gamnit: cache UICamera anchor points
authorAlexis Laferrière <alexis.laf@xymus.net>
Tue, 6 Jun 2017 23:32:00 +0000 (19:32 -0400)
committerAlexis Laferrière <alexis.laf@xymus.net>
Thu, 8 Jun 2017 15:57:24 +0000 (11:57 -0400)
Signed-off-by: Alexis Laferrière <alexis.laf@xymus.net>

contrib/action_nitro/src/action_nitro.nit
lib/gamnit/bmfont.nit
lib/gamnit/cameras.nit
lib/gamnit/flat.nit

index e5a68f9..56a055b 100644 (file)
@@ -561,7 +561,7 @@ redef class Player
                end
 
                # Display respawn instructions
-               app.ui_sprites.add new Sprite(app.texts_sheet.respawn, app.ui_camera.center)
+               app.ui_sprites.add new Sprite(app.texts_sheet.respawn, app.ui_camera.center.offset(0.0, 0.0, 0.0))
        end
 end
 
index 4abdaa5..2cd69d7 100644 (file)
@@ -270,7 +270,8 @@ end
 # ~~~
 # redef class App
 #     var font = new BMFontAsset("arial.fnt")
-#     var ui_text = new TextSprites(font, ui_camera.top_left)
+#     var pos: Point3d[Float] = ui_camera.top_left.offset(128.0, -128.0, 0.0)
+#     var ui_text = new TextSprites(font, pos)
 #
 #     redef fun on_create
 #     do
index 042896a..7183e6b 100644 (file)
@@ -29,7 +29,7 @@ abstract class Camera
        var display: GamnitDisplay
 
        # Position of this camera in world space
-       var position = new Point3d[Float](0.0, 0.0, 0.0) is writable
+       var position = new Point3d[Float](0.0, 0.0, 0.0)
 
        # The Model-View-Projection matrix created by this camera
        #
@@ -238,33 +238,31 @@ class UICamera
        end
 
        # Center of the screen, from the point of view of the camera, at z = 0
-       fun center: Point3d[Float] do return new Point3d[Float](position.x + width / 2.0, position.y - height / 2.0, 0.0)
+       var center: IPoint3d[Float] = new CameraAnchor(self, 0.5, -0.5)
 
        # Center of the top of the screen, at z = 0
-       fun top: Point3d[Float] do return new Point3d[Float](position.x + width / 2.0, position.y, 0.0)
+       var top: IPoint3d[Float] = new CameraAnchor(self, 0.5, 0.0)
 
        # Center of the bottom of the screen, at z = 0
-       fun bottom: Point3d[Float] do return new Point3d[Float](position.x + width / 2.0, position.y - height, 0.0)
+       var bottom: IPoint3d[Float] = new CameraAnchor(self, 0.5, -1.0)
 
        # Center of the left border of the screen, at z = 0
-       fun left: Point3d[Float] do return new Point3d[Float](position.x, position.y - height / 2.0, 0.0)
+       var left: IPoint3d[Float] = new CameraAnchor(self, 0.0, -1.0)
 
        # Center of the right border of the screen, at z = 0
-       fun right: Point3d[Float] do return new Point3d[Float](position.x + width, position.y - height / 2.0, 0.0)
+       var right: IPoint3d[Float] = new CameraAnchor(self, 1.0, -1.0)
 
        # Top left corner of the screen, at z = 0
-       fun top_left: Point3d[Float] do return new Point3d[Float](position.x, position.y, 0.0)
+       var top_left: IPoint3d[Float] = new CameraAnchor(self, 0.0, 0.0)
 
        # Top right corner of the screen, at z = 0
-       fun top_right: Point3d[Float] do return new Point3d[Float](position.x + width, position.y, 0.0)
+       var top_right: IPoint3d[Float] = new CameraAnchor(self, 1.0, 0.0)
 
        # Bottom left corner of the screen, at z = 0
-       fun bottom_left: Point3d[Float] do return new Point3d[Float](position.x, position.y - height, 0.0)
+       var bottom_left: IPoint3d[Float] = new CameraAnchor(self, 0.0, -1.0)
 
        # Bottom right corner of the screen, at z = 0
-       fun bottom_right: Point3d[Float] do return new Point3d[Float](position.x + width, position.y - height, 0.0)
-
-       # TODO cache the anchors
+       var bottom_right: IPoint3d[Float] = new CameraAnchor(self, 1.0, -1.0)
 
        redef fun mvp_matrix
        do
@@ -279,3 +277,55 @@ class UICamera
                return view * projection
        end
 end
+
+# Immutable relative anchors for reference points on `camera`
+private class CameraAnchor
+       super IPoint3d[Float]
+
+       # Reference camera
+       var camera: UICamera
+
+       # Reference position, the top left of the screen
+       var ref: Point3d[Float] = camera.position is lazy
+
+       # X position as proportion of the screen width
+       var relative_x: Float
+
+       # Y position as proportion of the screen height
+       var relative_y: Float
+
+       redef fun x do return ref.x + relative_x*camera.width
+       redef fun y do return ref.y + relative_y*camera.height
+       redef fun z do return ref.z
+
+       redef fun offset(x, y, z) do return new OffsetPoint3d(self, x.to_f, y.to_f, z.to_f)
+end
+
+# Position relative to another point or usually a `CameraAnchor`
+private class OffsetPoint3d
+       super Point3d[Float]
+
+       autoinit ref, offset_x, offset_y, offset_z
+
+       # Reference point to which the offsets are applied
+       var ref: IPoint3d[Float]
+
+       # Difference on the X axis
+       var offset_x: Float
+
+       # Difference on the X axis
+       var offset_y: Float
+
+       # Difference on the X axis
+       var offset_z: Float
+
+       redef fun x do return ref.x + offset_x
+       redef fun y do return ref.y + offset_y
+       redef fun z do return ref.z + offset_z
+
+       redef fun x=(value) do if value != null then offset_x += value - x
+       redef fun y=(value) do if value != null then offset_y += value - y
+       redef fun z=(value) do if value != null then offset_z += value - z
+
+       redef fun offset(x, y, z) do return new OffsetPoint3d(self, x.to_f, y.to_f, z.to_f)
+end
index f7f7c4a..cafac8a 100644 (file)
@@ -42,6 +42,7 @@ import performance_analysis
 
 import gamnit
 import gamnit::cameras_cache
+intrude import gamnit::cameras
 import gamnit::dynamic_resolution
 import gamnit::limit_fps
 import gamnit::camera_control
@@ -633,6 +634,26 @@ redef class Point3d[N]
        end
 end
 
+redef class OffsetPoint3d
+       redef fun x=(v)
+       do
+               if isset _x and v != x then needs_update
+               super
+       end
+
+       redef fun y=(v)
+       do
+               if isset _y and v != y then needs_update
+               super
+       end
+
+       redef fun z=(v)
+       do
+               if isset _z and v != z then needs_update
+               super
+       end
+end
+
 # Set of sprites sorting them into different `SpriteContext`
 private class SpriteSet
        super HashSet[Sprite]