OLD | NEW |
1 part of sprites; | 1 part of sprites; |
2 | 2 |
3 enum SpriteBoxTransformMode { | 3 enum SpriteBoxTransformMode { |
4 nativePoints, | 4 nativePoints, |
5 letterbox, | 5 letterbox, |
6 stretch, | 6 stretch, |
7 scaleToFit, | 7 scaleToFit, |
8 fixedWidth, | 8 fixedWidth, |
9 fixedHeight, | 9 fixedHeight, |
10 } | 10 } |
11 | 11 |
12 class SpriteBox extends RenderBox { | 12 class SpriteBox extends RenderBox { |
13 | 13 |
14 // Member variables | 14 // Member variables |
15 | 15 |
16 // Root node for drawing | 16 // Root node for drawing |
17 Node _rootNode; | 17 Node _rootNode; |
18 | 18 |
19 // Tracking of frame rate and updates | 19 // Tracking of frame rate and updates |
20 double _lastTimeStamp; | 20 double _lastTimeStamp; |
21 int _numFrames = 0; | 21 int _numFrames = 0; |
| 22 double _frameRate = 0.0; |
22 | 23 |
| 24 // Transformation mode |
23 SpriteBoxTransformMode transformMode; | 25 SpriteBoxTransformMode transformMode; |
24 double _systemWidth; | 26 double _systemWidth; |
25 double _systemHeight; | 27 double _systemHeight; |
26 | 28 |
| 29 // Cached transformation matrix |
| 30 Matrix4 _transformMatrix; |
| 31 bool _transformMatrixIsDirty; |
| 32 |
27 // Setup | 33 // Setup |
28 | 34 |
29 SpriteBox(Node rootNode, [SpriteBoxTransformMode mode = SpriteBoxTransformMode
.nativePoints, double width=1024.0, double height=1024.0]) { | 35 SpriteBox(Node rootNode, [SpriteBoxTransformMode mode = SpriteBoxTransformMode
.nativePoints, double width=1024.0, double height=1024.0]) { |
30 assert(rootNode != null); | 36 assert(rootNode != null); |
31 assert(rootNode._spriteBox == null); | 37 assert(rootNode._spriteBox == null); |
32 | 38 |
33 // Setup root node | 39 // Setup root node |
34 _rootNode = rootNode; | 40 _rootNode = rootNode; |
35 | 41 |
36 // Assign SpriteBox reference to all the nodes | 42 // Assign SpriteBox reference to all the nodes |
37 _addSpriteBoxReference(_rootNode); | 43 _addSpriteBoxReference(_rootNode); |
38 | 44 |
39 // Setup transform mode | 45 // Setup transform mode |
40 transformMode = mode; | 46 transformMode = mode; |
41 _systemWidth = width; | 47 _systemWidth = width; |
42 _systemHeight = height; | 48 _systemHeight = height; |
43 | 49 |
| 50 _transformMatrixIsDirty = true; |
| 51 |
44 _scheduleTick(); | 52 _scheduleTick(); |
45 } | 53 } |
46 | 54 |
47 void _addSpriteBoxReference(Node node) { | 55 void _addSpriteBoxReference(Node node) { |
48 node._spriteBox = this; | 56 node._spriteBox = this; |
49 for (Node child in node._children) { | 57 for (Node child in node._children) { |
50 _addSpriteBoxReference(child); | 58 _addSpriteBoxReference(child); |
51 } | 59 } |
52 } | 60 } |
53 | 61 |
54 // Properties | 62 // Properties |
55 | 63 |
56 double get systemWidth => _systemWidth; | 64 double get systemWidth => _systemWidth; |
57 double get systemHeight => _systemHeight; | 65 double get systemHeight => _systemHeight; |
58 | 66 |
59 Node get rootNode => _rootNode; | 67 Node get rootNode => _rootNode; |
60 | 68 |
61 void performLayout() { | 69 void performLayout() { |
62 size = constraints.constrain(Size.infinite); | 70 size = constraints.constrain(Size.infinite); |
| 71 _transformMatrixIsDirty = true; |
| 72 _callSpriteBoxPerformedLayout(_rootNode); |
63 } | 73 } |
64 | 74 |
65 // Event handling | 75 // Event handling |
66 | 76 |
67 void handleEvent(Event event, BoxHitTestEntry entry) { | 77 void handleEvent(Event event, BoxHitTestEntry entry) { |
68 } | 78 } |
69 | 79 |
70 // Rendering | 80 // Rendering |
71 | 81 |
72 void paint(RenderObjectDisplayList canvas) { | 82 Matrix4 get transformMatrix { |
73 // Move to correct coordinate space before drawing | 83 // Get cached matrix if available |
| 84 if (!_transformMatrixIsDirty && _transformMatrix != null) { |
| 85 return _transformMatrix; |
| 86 } |
| 87 |
| 88 _transformMatrix = new Matrix4.identity(); |
| 89 |
| 90 // Calculate matrix |
74 double scaleX = 1.0; | 91 double scaleX = 1.0; |
75 double scaleY = 1.0; | 92 double scaleY = 1.0; |
76 double offsetX = 0.0; | 93 double offsetX = 0.0; |
77 double offsetY = 0.0; | 94 double offsetY = 0.0; |
78 | 95 |
79 switch(transformMode) { | 96 switch(transformMode) { |
80 case SpriteBoxTransformMode.stretch: | 97 case SpriteBoxTransformMode.stretch: |
81 scaleX = size.width/_systemWidth; | 98 scaleX = size.width/_systemWidth; |
82 scaleY = size.height/_systemHeight; | 99 scaleY = size.height/_systemHeight; |
83 break; | 100 break; |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 scaleX = scaleY; | 132 scaleX = scaleY; |
116 _systemWidth = size.width/scaleY; | 133 _systemWidth = size.width/scaleY; |
117 break; | 134 break; |
118 case SpriteBoxTransformMode.nativePoints: | 135 case SpriteBoxTransformMode.nativePoints: |
119 break; | 136 break; |
120 default: | 137 default: |
121 assert(false); | 138 assert(false); |
122 break; | 139 break; |
123 } | 140 } |
124 | 141 |
| 142 _transformMatrix.translate(offsetX, offsetY); |
| 143 _transformMatrix.scale(scaleX, scaleY); |
| 144 |
| 145 return _transformMatrix; |
| 146 } |
| 147 |
| 148 void paint(RenderObjectDisplayList canvas) { |
125 canvas.save(); | 149 canvas.save(); |
126 | 150 |
127 canvas.translate(offsetX, offsetY); | 151 // Move to correct coordinate space before drawing |
128 canvas.scale(scaleX, scaleY); | 152 canvas.concat(transformMatrix.storage); |
129 | 153 |
130 // Draw the sprite tree | 154 // Draw the sprite tree |
131 _rootNode.visit(canvas); | 155 _rootNode.visit(canvas); |
132 | 156 |
133 canvas.restore(); | 157 canvas.restore(); |
134 } | 158 } |
135 | 159 |
136 // Updates | 160 // Updates |
137 | 161 |
138 int _animationId = 0; | 162 int _animationId = 0; |
139 | 163 |
140 void _scheduleTick() { | 164 void _scheduleTick() { |
141 _animationId = scheduler.requestAnimationFrame(_tick); | 165 _animationId = scheduler.requestAnimationFrame(_tick); |
142 } | 166 } |
143 | 167 |
144 void _tick(double timeStamp) { | 168 void _tick(double timeStamp) { |
145 | 169 |
146 // Calculate the time between frames in seconds | 170 // Calculate the time between frames in seconds |
147 if (_lastTimeStamp == null) _lastTimeStamp = timeStamp; | 171 if (_lastTimeStamp == null) _lastTimeStamp = timeStamp; |
148 double delta = (timeStamp - _lastTimeStamp) / 1000; | 172 double delta = (timeStamp - _lastTimeStamp) / 1000; |
149 _lastTimeStamp = timeStamp; | 173 _lastTimeStamp = timeStamp; |
150 | 174 |
151 // Count the number of frames we've been running | 175 // Count the number of frames we've been running |
152 _numFrames += 1; | 176 _numFrames += 1; |
153 | 177 |
| 178 _frameRate = 1.0/delta; |
| 179 |
154 // Print frame rate | 180 // Print frame rate |
155 if (_numFrames % 60 == 0) print("delta: ${delta} fps: ${1.0/delta}"); | 181 if (_numFrames % 60 == 0) print("delta: $delta fps: $_frameRate"); |
156 | 182 |
157 _rootNode.update(delta); | 183 _callUpdate(_rootNode, delta); |
158 _scheduleTick(); | 184 _scheduleTick(); |
159 } | 185 } |
160 | 186 |
| 187 void _callUpdate(Node node, double dt) { |
| 188 node.update(dt); |
| 189 for (Node child in node.children) { |
| 190 if (!child.paused) { |
| 191 _callUpdate(child, dt); |
| 192 } |
| 193 } |
| 194 } |
| 195 |
| 196 void _callSpriteBoxPerformedLayout(Node node) { |
| 197 node.spriteBoxPerformedLayout(); |
| 198 for (Node child in node.children) { |
| 199 _callSpriteBoxPerformedLayout(child); |
| 200 } |
| 201 } |
| 202 |
161 // Hit tests | 203 // Hit tests |
162 | 204 |
163 List<Node> findNodesAtPosition(Point position) { | 205 List<Node> findNodesAtPosition(Point position) { |
164 assert(position != null); | 206 assert(position != null); |
165 | 207 |
166 List<Node> nodes = []; | 208 List<Node> nodes = []; |
167 | 209 |
168 // Traverse the render tree and find objects at the position | 210 // Traverse the render tree and find objects at the position |
169 _addNodesAtPosition(_rootNode, position, nodes); | 211 _addNodesAtPosition(_rootNode, position, nodes); |
170 | 212 |
171 return nodes; | 213 return nodes; |
172 } | 214 } |
173 | 215 |
174 _addNodesAtPosition(Node node, Point position, List<Node> list) { | 216 _addNodesAtPosition(Node node, Point position, List<Node> list) { |
175 // Visit children first | 217 // Visit children first |
176 for (Node child in node.children) { | 218 for (Node child in node.children) { |
177 _addNodesAtPosition(child, position, list); | 219 _addNodesAtPosition(child, position, list); |
178 } | 220 } |
179 // Do the hit test | 221 // Do the hit test |
180 Point posInNodeSpace = node.convertPointToNodeSpace(position); | 222 Point posInNodeSpace = node.convertPointToNodeSpace(position); |
181 if (node.hitTest(posInNodeSpace)) { | 223 if (node.hitTest(posInNodeSpace)) { |
182 list.add(node); | 224 list.add(node); |
183 } | 225 } |
184 } | 226 } |
185 } | 227 } |
OLD | NEW |