OLD | NEW |
---|---|
1 part of sprites; | 1 part of sprites; |
2 | 2 |
3 double degrees2radians(double degrees) => degrees * Math.PI/180.8; | 3 double degrees2radians(double degrees) => degrees * Math.PI/180.8; |
4 | 4 |
5 double radians2degrees(double radians) => radians * 180.0/Math.PI; | 5 double radians2degrees(double radians) => radians * 180.0/Math.PI; |
6 | 6 |
7 class TransformNode { | 7 class Node { |
8 | 8 |
9 // Member variables | 9 // Member variables |
10 | 10 |
11 SpriteBox _spriteBox; | 11 SpriteBox _spriteBox; |
12 TransformNode _parent; | 12 Node _parent; |
13 | 13 |
14 Vector2 _position; | 14 Point _position; |
15 double _rotation; | 15 double _rotation; |
16 | 16 |
17 bool _isMatrixDirty; | 17 bool _isMatrixDirty; |
18 Matrix3 _transform; | 18 Matrix4 _transformMatrix; |
19 Matrix3 _pivotTransform; | 19 Matrix4 _transformMatrixFromWorld; |
20 | |
21 double _width; | |
22 double _height; | |
23 | 20 |
24 double _scaleX; | 21 double _scaleX; |
25 double _scaleY; | 22 double _scaleY; |
26 | |
27 Vector2 _pivot; | |
28 | 23 |
29 bool visible; | 24 bool visible; |
30 | 25 |
31 double _zPosition; | 26 double _zPosition; |
32 int _addedOrder; | 27 int _addedOrder; |
33 int _childrenLastAddedOrder; | 28 int _childrenLastAddedOrder; |
34 bool _childrenNeedSorting; | 29 bool _childrenNeedSorting; |
35 | 30 |
36 List<TransformNode>_children; | 31 List<Node>_children; |
37 | 32 |
38 // Constructors | 33 // Constructors |
39 | 34 |
40 TransformNode() { | 35 Node() { |
41 _width = 0.0; | |
42 _height = 0.0; | |
43 _rotation = 0.0; | 36 _rotation = 0.0; |
44 _pivot = new Vector2(0.0, 0.0); | 37 _position = new Point(0.0, 0.0); |
abarth-chromium
2015/06/11 00:20:19
Point.origin
| |
45 _position = new Vector2(0.0, 0.0); | |
46 _scaleX = _scaleY = 1.0; | 38 _scaleX = _scaleY = 1.0; |
47 _isMatrixDirty = false; | 39 _isMatrixDirty = false; |
48 _transform = new Matrix3.identity(); | 40 _transformMatrix = new Matrix4.identity(); |
49 _pivotTransform = new Matrix3.identity(); | |
50 _children = []; | 41 _children = []; |
51 _childrenNeedSorting = false; | 42 _childrenNeedSorting = false; |
52 _childrenLastAddedOrder = 0; | 43 _childrenLastAddedOrder = 0; |
53 visible = true; | 44 visible = true; |
54 } | 45 } |
55 | 46 |
56 // Property setters and getters | 47 // Property setters and getters |
57 | 48 |
58 SpriteBox get spriteBox => _spriteBox; | 49 SpriteBox get spriteBox => _spriteBox; |
59 | 50 |
60 TransformNode get parent => _parent; | 51 Node get parent => _parent; |
61 | 52 |
62 double get rotation => _rotation; | 53 double get rotation => _rotation; |
63 | 54 |
64 void set rotation(double rotation) { | 55 void set rotation(double rotation) { |
65 _rotation = rotation; | 56 _rotation = rotation; |
66 _isMatrixDirty = true; | 57 _isMatrixDirty = true; |
67 } | 58 } |
68 | 59 |
69 Vector2 get position => _position; | 60 Point get position => _position; |
70 | 61 |
71 void set position(Vector2 position) { | 62 void set position(Point position) { |
72 _position = position; | 63 _position = position; |
73 _isMatrixDirty = true; | 64 _isMatrixDirty = true; |
74 } | 65 } |
75 | |
76 double get width => _width; | |
77 | |
78 void set width(double width) { | |
79 _width = width; | |
80 _isMatrixDirty = true; | |
81 } | |
82 | |
83 double get height => _height; | |
84 | |
85 void set height(double height) { | |
86 _height = height; | |
87 _isMatrixDirty = true; | |
88 } | |
89 | |
90 Vector2 get pivot => _pivot; | |
91 | |
92 void set pivot(Vector2 pivot) { | |
93 _pivot = pivot; | |
94 _isMatrixDirty = true; | |
95 } | |
96 | 66 |
97 double get zPosition => _zPosition; | 67 double get zPosition => _zPosition; |
98 | 68 |
99 void set zPosition(double zPosition) { | 69 void set zPosition(double zPosition) { |
100 _zPosition = zPosition; | 70 _zPosition = zPosition; |
101 if (_parent != null) { | 71 if (_parent != null) { |
102 _parent._childrenNeedSorting = true; | 72 _parent._childrenNeedSorting = true; |
103 } | 73 } |
104 } | 74 } |
105 | 75 |
106 double get scale { | 76 double get scale { |
107 assert(_scaleX == _scaleY); | 77 assert(_scaleX == _scaleY); |
108 return _scaleX; | 78 return _scaleX; |
109 } | 79 } |
110 | 80 |
111 void set scale(double scale) { | 81 void set scale(double scale) { |
112 _scaleX = _scaleY = scale; | 82 _scaleX = _scaleY = scale; |
113 _isMatrixDirty = true; | 83 _isMatrixDirty = true; |
114 } | 84 } |
115 | 85 |
116 List<TransformNode> get children => _children; | 86 List<Node> get children => _children; |
117 | 87 |
118 // Adding and removing children | 88 // Adding and removing children |
119 | 89 |
120 void addChild(TransformNode child) { | 90 void addChild(Node child) { |
121 assert(child._parent == null); | 91 assert(child._parent == null); |
122 | 92 |
123 _childrenNeedSorting = true; | 93 _childrenNeedSorting = true; |
124 _children.add(child); | 94 _children.add(child); |
125 child._parent = this; | 95 child._parent = this; |
126 child._spriteBox = this._spriteBox; | 96 child._spriteBox = this._spriteBox; |
127 _childrenLastAddedOrder += 1; | 97 _childrenLastAddedOrder += 1; |
128 child._addedOrder = _childrenLastAddedOrder; | 98 child._addedOrder = _childrenLastAddedOrder; |
129 } | 99 } |
130 | 100 |
131 void removeChild(TransformNode child) { | 101 void removeChild(Node child) { |
132 if (_children.remove(child)) { | 102 if (_children.remove(child)) { |
133 child._parent = null; | 103 child._parent = null; |
134 child._spriteBox = null; | 104 child._spriteBox = null; |
135 } | 105 } |
136 } | 106 } |
137 | 107 |
138 void removeFromParent() { | 108 void removeFromParent() { |
139 assert(_parent != null); | 109 assert(_parent != null); |
140 _parent.removeFromParent(); | 110 _parent.removeFromParent(); |
141 } | 111 } |
142 | 112 |
143 void removeAllChildren() { | 113 void removeAllChildren() { |
144 for (TransformNode child in _children) { | 114 for (Node child in _children) { |
145 child._parent = null; | 115 child._parent = null; |
146 child._spriteBox = null; | 116 child._spriteBox = null; |
147 } | 117 } |
148 _children = []; | 118 _children = []; |
149 _childrenNeedSorting = false; | 119 _childrenNeedSorting = false; |
150 } | 120 } |
151 | 121 |
152 // Calculating the transformation matrix | 122 // Calculating the transformation matrix |
153 | 123 |
154 Matrix3 get transformMatrix { | 124 Matrix4 get transformMatrix { |
155 if (!_isMatrixDirty) { | 125 if (!_isMatrixDirty) { |
156 return _transform; | 126 return _transformMatrix; |
157 } | 127 } |
158 | |
159 Vector2 pivotInPoints = new Vector2(_width * _pivot[0], _height * _pivot[1]) ; | |
160 | 128 |
161 double cx, sx, cy, sy; | 129 double cx, sx, cy, sy; |
162 | 130 |
163 if (_rotation == 0) { | 131 if (_rotation == 0.0) { |
164 cx = 1.0; | 132 cx = 1.0; |
165 sx = 0.0; | 133 sx = 0.0; |
166 cy = 1.0; | 134 cy = 1.0; |
167 sy = 0.0; | 135 sy = 0.0; |
168 } | 136 } |
169 else { | 137 else { |
170 double radiansX = degrees2radians(_rotation); | 138 double radiansX = degrees2radians(_rotation); |
171 double radiansY = degrees2radians(_rotation); | 139 double radiansY = degrees2radians(_rotation); |
172 | 140 |
173 cx = Math.cos(radiansX); | 141 cx = Math.cos(radiansX); |
174 sx = Math.sin(radiansX); | 142 sx = Math.sin(radiansX); |
175 cy = Math.cos(radiansY); | 143 cy = Math.cos(radiansY); |
176 sy = Math.sin(radiansY); | 144 sy = Math.sin(radiansY); |
177 } | 145 } |
146 | |
147 // Create transformation matrix for scale, position and rotation | |
148 _transformMatrix.setValues(cy * _scaleX, sy * _scaleX, 0.0, 0.0, | |
149 -sx * _scaleY, cx * _scaleY, 0.0, 0.0, | |
150 0.0, 0.0, 1.0, 0.0, | |
151 _position.x, _position.y, 0.0, 1.0 | |
152 ); | |
178 | 153 |
179 // TODO: Add support for scale | 154 return _transformMatrix; |
180 double scaleX = 1.0; | 155 } |
181 double scaleY = 1.0; | 156 |
182 | 157 // Transforms to other nodes |
183 // Create transformation matrix for scale, position and rotation | 158 |
184 _transform.setValues(cy * scaleX, sy * scaleX, 0.0, | 159 Matrix4 _nodeToBoxMatrix() { |
185 -sx * scaleY, cx * scaleY, 0.0, | 160 Matrix4 t = transformMatrix; |
186 _position[0], _position[1], 1.0); | 161 |
187 | 162 Node p = this.parent; |
188 if (_pivot.x != 0 || _pivot.y != 0) { | 163 while (p != null) { |
189 _pivotTransform.setValues(1.0, 0.0, 0.0, 0.0, 1.0, 0.0, pivotInPoints[0], pivotInPoints[1], 1.0); | 164 t = new Matrix4.copy(p.transformMatrix).multiply(t); |
190 _transform.multiply(_pivotTransform); | 165 p = p.parent; |
191 } | 166 } |
192 | 167 return t; |
193 return _transform; | 168 } |
169 | |
170 Matrix4 _boxToNodeMatrix() { | |
171 Matrix4 t = _nodeToBoxMatrix(); | |
172 t.invert(); | |
173 return t; | |
174 } | |
175 | |
176 Point convertPointToNodeSpace(Point boxPoint) { | |
177 assert(boxPoint != null); | |
178 assert(_spriteBox != null); | |
179 | |
180 Vector4 v =_boxToNodeMatrix().transform(new Vector4(boxPoint.x, boxPoint.y, 0.0, 1.0)); | |
181 return new Point(v[0], v[1]); | |
182 } | |
183 | |
184 Point convertPointToBoxSpace(Point nodePoint) { | |
185 assert(nodePoint != null); | |
186 assert(_spriteBox != null); | |
187 | |
188 Vector4 v =_nodeToBoxMatrix().transform(new Vector4(nodePoint.x, nodePoint.y , 0.0, 1.0)); | |
189 return new Point(v[0], v[1]); | |
190 } | |
191 | |
192 Point convertPointFromNode(Point point, Node node) { | |
193 assert(node != null); | |
194 assert(point != null); | |
195 assert(_spriteBox != null); | |
196 assert(_spriteBox == node._spriteBox); | |
197 | |
198 Point boxPoint = node.convertPointToBoxSpace(point); | |
199 Point localPoint = convertPointToNodeSpace(boxPoint); | |
200 | |
201 return localPoint; | |
202 } | |
203 | |
204 // Hit test | |
205 | |
206 bool hitTest(Point nodePoint) { | |
207 assert(nodePoint != null); | |
208 | |
209 return false; | |
194 } | 210 } |
195 | 211 |
196 // Rendering | 212 // Rendering |
197 | 213 |
198 void visit(PictureRecorder canvas) { | 214 void visit(PictureRecorder canvas) { |
199 if (!visible) return; | 215 if (!visible) return; |
200 | 216 |
201 prePaint(canvas); | 217 prePaint(canvas); |
202 paint(canvas); | 218 paint(canvas); |
203 visitChildren(canvas); | 219 visitChildren(canvas); |
204 postPaint(canvas); | 220 postPaint(canvas); |
205 } | 221 } |
206 | 222 |
207 void prePaint(PictureRecorder canvas) { | 223 void prePaint(PictureRecorder canvas) { |
208 canvas.save(); | 224 canvas.save(); |
209 | 225 |
210 canvas.translate(_position[0], _position[1]); | 226 // TODO: Can this be done more efficiently? |
211 canvas.rotate(degrees2radians(_rotation)); | 227 // Get the transformation matrix and apply transform |
212 canvas.scale(_scaleX, _scaleY); | 228 List<double> matrix = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 , 0.0, 0.0, 0.0, 0.0, 0.0]; |
abarth-chromium
2015/06/11 00:20:19
? This looks very strange. Is this really want y
| |
213 canvas.translate(-_width*_pivot[0], -_height*_pivot[1]); | 229 this.transformMatrix.copyIntoArray(matrix); |
214 | 230 Float32List list32 = new Float32List.fromList(matrix); |
215 // TODO: Use transformation matrix instead of individual calls | 231 canvas.concat(list32); |
abarth-chromium
2015/06/11 00:33:14
canvas.concat(transformMatrix.storage)
| |
216 // List<double> matrix = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]; | |
217 // this.transformMatrix.copyIntoArray(matrix); | |
218 // canvas.concat(matrix); | |
219 } | 232 } |
220 | 233 |
221 void paint(PictureRecorder canvas) { | 234 void paint(PictureRecorder canvas) { |
222 | 235 |
223 } | 236 } |
224 | 237 |
225 void visitChildren(PictureRecorder canvas) { | 238 void visitChildren(PictureRecorder canvas) { |
226 // Sort children primarily by zPosition, secondarily by added order | 239 // Sort children primarily by zPosition, secondarily by added order |
227 if (_childrenNeedSorting) { | 240 if (_childrenNeedSorting) { |
228 _children.sort((TransformNode a, TransformNode b) { | 241 _children.sort((Node a, Node b) { |
229 if (a._zPosition == b._zPosition) { | 242 if (a._zPosition == b._zPosition) { |
230 return b._addedOrder - a._addedOrder; | 243 return b._addedOrder - a._addedOrder; |
231 } | 244 } |
232 else if (a._zPosition > b._zPosition) { | 245 else if (a._zPosition > b._zPosition) { |
233 return 1; | 246 return 1; |
234 } | 247 } |
235 else { | 248 else { |
236 return -1; | 249 return -1; |
237 } | 250 } |
238 }); | 251 }); |
239 _childrenNeedSorting = false; | 252 _childrenNeedSorting = false; |
240 } | 253 } |
241 | 254 |
242 // Visit each child | 255 // Visit each child |
243 _children.forEach((child) => child.visit(canvas)); | 256 _children.forEach((child) => child.visit(canvas)); |
244 } | 257 } |
245 | 258 |
246 void postPaint(PictureRecorder canvas) { | 259 void postPaint(PictureRecorder canvas) { |
247 canvas.restore(); | 260 canvas.restore(); |
248 } | 261 } |
249 | 262 |
250 // Receiving update calls | 263 // Receiving update calls |
251 | 264 |
252 void update(double dt) { | 265 void update(double dt) { |
253 | 266 |
254 } | 267 } |
255 } | 268 } |
OLD | NEW |