Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(157)

Side by Side Diff: sky/examples/game/lib/node.dart

Issue 1201983004: Adds API documentation for SkyGames (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sky/examples/game/lib/game_demo_world.dart ('k') | sky/examples/game/lib/node_with_size.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 part of sprites; 1 part of sprites;
2 2
3 double convertDegrees2Radians(double degrees) => degrees * Math.PI/180.8; 3 double convertDegrees2Radians(double degrees) => degrees * Math.PI/180.8;
4 4
5 double convertRadians2Degrees(double radians) => radians * 180.0/Math.PI; 5 double convertRadians2Degrees(double radians) => radians * 180.0/Math.PI;
6 6
7 /// A base class for all objects that can be added to the sprite node tree and r endered to screen using [SpriteBox] and
8 /// [SpriteWidget].
9 ///
10 /// The [Node] class itself doesn't render any content, but provides the basic f unctions of any type of node, such as
11 /// handling transformations and user input. To render the node tree, a root nod e must be added to a [SpriteBox] or a
12 /// [SpriteWidget]. Commonly used sub-classes of [Node] are [Sprite], [NodeWithS ize], and many more upcoming subclasses.
13 ///
14 /// Nodes form a hierarchical tree. Each node can have a number of children, and the transformation (positioning,
15 /// rotation, and scaling) of a node also affects its children.
7 class Node { 16 class Node {
8 17
9 // Member variables 18 // Member variables
10 19
11 SpriteBox _spriteBox; 20 SpriteBox _spriteBox;
12 Node _parent; 21 Node _parent;
13 22
14 Point _position; 23 Point _position = Point.origin;
15 double _rotation; 24 double _rotation = 0.0;
16 25
17 Matrix4 _transformMatrix; 26 Matrix4 _transformMatrix = new Matrix4.identity();
18 Matrix4 _transformMatrixNodeToBox; 27 Matrix4 _transformMatrixNodeToBox;
19 Matrix4 _transformMatrixBoxToNode; 28 Matrix4 _transformMatrixBoxToNode;
20 29
21 double _scaleX; 30 double _scaleX = 1.0;
22 double _scaleY; 31 double _scaleY = 1.0;
23 32
24 bool visible; 33 /// The visibility of this node and its children.
34 bool visible = true;
25 35
26 double _zPosition; 36 double _zPosition = 0.0;
27 int _addedOrder; 37 int _addedOrder;
28 int _childrenLastAddedOrder; 38 int _childrenLastAddedOrder = 0;
29 bool _childrenNeedSorting; 39 bool _childrenNeedSorting = false;
30 40
41 /// Decides if the node and its children is currently paused.
42 ///
43 /// A paused node will not receive any input events, update calls, or run any animations.
44 ///
45 /// myNodeTree.paused = true;
31 bool paused = false; 46 bool paused = false;
32 47
33 bool _userInteractionEnabled = false; 48 bool _userInteractionEnabled = false;
49
50 /// If set to true the node will receive multiple pointers, otherwise it will only receive events the first pointer.
51 ///
52 /// This property is only meaningful if [userInteractionEnabled] is set to tru e. Default value is false.
53 ///
54 /// class MyCustomNode extends Node {
55 /// handleMultiplePointers = true;
56 /// }
34 bool handleMultiplePointers = false; 57 bool handleMultiplePointers = false;
35 int _handlingPointer; 58 int _handlingPointer;
36 59
37 List<Node>_children; 60 List<Node>_children = [];
38 61
39 // Constructors 62 // Constructors
40 63
64 /// Creates a new [Node] without any transformation.
65 ///
66 /// var myNode = new Node();
41 Node() { 67 Node() {
42 _rotation = 0.0;
43 _position = Point.origin;
44 _scaleX = _scaleY = 1.0;
45 _transformMatrix = new Matrix4.identity();
46 _children = [];
47 _childrenNeedSorting = false;
48 _childrenLastAddedOrder = 0;
49 _zPosition = 0.0;
50 visible = true;
51 } 68 }
52 69
53 // Property setters and getters 70 // Property setters and getters
54 71
72 /// The [SpriteBox] this node is added to, or null if it's not currently added to a [SpriteBox].
73 ///
74 /// For most applications it's not necessary to access the [SpriteBox] directl y.
75 ///
76 /// // Get the transformMode of the sprite box
77 /// var transformMode = myNode.spriteBox.transformMode;
55 SpriteBox get spriteBox => _spriteBox; 78 SpriteBox get spriteBox => _spriteBox;
56 79
80 /// The parent of this node, or null if it doesn't have a parent.
81 ///
82 /// // Hide the parent
83 /// myNode.parent.visible = false;
57 Node get parent => _parent; 84 Node get parent => _parent;
58 85
86 /// The rotation of this node in degrees.
87 ///
88 /// myNode.rotation = 45.0;
59 double get rotation => _rotation; 89 double get rotation => _rotation;
60 90
61 void set rotation(double rotation) { 91 void set rotation(double rotation) {
62 assert(rotation != null); 92 assert(rotation != null);
63 _rotation = rotation; 93 _rotation = rotation;
64 _invalidateTransformMatrix(); 94 _invalidateTransformMatrix();
65 } 95 }
66 96
97 /// The position of this node relative to its parent.
98 ///
99 /// myNode.position = new Point(42.0, 42.0);
67 Point get position => _position; 100 Point get position => _position;
68 101
69 void set position(Point position) { 102 void set position(Point position) {
70 assert(position != null); 103 assert(position != null);
71 _position = position; 104 _position = position;
72 _invalidateTransformMatrix(); 105 _invalidateTransformMatrix();
73 } 106 }
74 107
108 /// The draw order of this node compared to its parent and its siblings.
109 ///
110 /// By default nodes are drawn in the order that they have been added to a par ent. To override this behavior the
111 /// [zPosition] property can be used. A higher value of this property will for ce the node to be drawn in front of
112 /// siblings that have a lower value. If a negative value is used the node wil l be drawn behind its parent.
113 ///
114 /// nodeInFront.zPosition = 1.0;
115 /// nodeBehind.zPosition = -1.0;
75 double get zPosition => _zPosition; 116 double get zPosition => _zPosition;
76 117
77 void set zPosition(double zPosition) { 118 void set zPosition(double zPosition) {
78 assert(zPosition != null); 119 assert(zPosition != null);
79 _zPosition = zPosition; 120 _zPosition = zPosition;
80 if (_parent != null) { 121 if (_parent != null) {
81 _parent._childrenNeedSorting = true; 122 _parent._childrenNeedSorting = true;
82 } 123 }
83 } 124 }
84 125
126 /// The scale of this node relative its parent.
127 ///
128 /// The [scale] property is only valid if [scaleX] and [scaleY] are equal valu es.
129 ///
130 /// myNode.scale = 5.0;
85 double get scale { 131 double get scale {
86 assert(_scaleX == _scaleY); 132 assert(_scaleX == _scaleY);
87 return _scaleX; 133 return _scaleX;
88 } 134 }
89 135
90 void set scale(double scale) { 136 void set scale(double scale) {
91 assert(scale != null); 137 assert(scale != null);
92 _scaleX = _scaleY = scale; 138 _scaleX = _scaleY = scale;
93 _invalidateTransformMatrix(); 139 _invalidateTransformMatrix();
94 } 140 }
95 141
142 /// The horizontal scale of this node relative its parent.
143 ///
144 /// myNode.scaleX = 5.0;
96 double get scaleX => _scaleX; 145 double get scaleX => _scaleX;
97 146
98 void set scaleX(double scaleX) { 147 void set scaleX(double scaleX) {
99 assert(scaleX != null); 148 assert(scaleX != null);
100 _scaleX = scaleX; 149 _scaleX = scaleX;
101 _invalidateTransformMatrix(); 150 _invalidateTransformMatrix();
102 } 151 }
103 152
153 /// The vertical scale of this node relative its parent.
154 ///
155 /// myNode.scaleY = 5.0;
104 double get scaleY => _scaleY; 156 double get scaleY => _scaleY;
105 157
106 void set scaleY(double scaleY) { 158 void set scaleY(double scaleY) {
107 assert(scaleY != null); 159 assert(scaleY != null);
108 _scaleY = scaleY; 160 _scaleY = scaleY;
109 _invalidateTransformMatrix(); 161 _invalidateTransformMatrix();
110 } 162 }
111 163
164 /// A list of the children of this node.
165 ///
166 /// This list should only be modified by using the [addChild] and [removeChild ] methods.
167 ///
168 /// // Iterate over a nodes children
169 /// for (Node child in myNode.children) {
170 /// // Do something with the child
171 /// }
112 List<Node> get children { 172 List<Node> get children {
113 _sortChildren(); 173 _sortChildren();
114 return _children; 174 return _children;
115 } 175 }
116 176
117 // Adding and removing children 177 // Adding and removing children
118 178
179 /// Adds a child to this node.
180 ///
181 /// The same node cannot be added to multiple nodes.
182 ///
183 /// addChild(new Sprite(myImage));
119 void addChild(Node child) { 184 void addChild(Node child) {
120 assert(child != null); 185 assert(child != null);
121 assert(child._parent == null); 186 assert(child._parent == null);
122 187
123 _childrenNeedSorting = true; 188 _childrenNeedSorting = true;
124 _children.add(child); 189 _children.add(child);
125 child._parent = this; 190 child._parent = this;
126 child._spriteBox = this._spriteBox; 191 child._spriteBox = this._spriteBox;
127 _childrenLastAddedOrder += 1; 192 _childrenLastAddedOrder += 1;
128 child._addedOrder = _childrenLastAddedOrder; 193 child._addedOrder = _childrenLastAddedOrder;
129 if (_spriteBox != null) _spriteBox._eventTargets = null; 194 if (_spriteBox != null) _spriteBox._eventTargets = null;
130 } 195 }
131 196
197 /// Removes a child from this node.
198 ///
199 /// removeChild(myChildNode);
132 void removeChild(Node child) { 200 void removeChild(Node child) {
133 assert(child != null); 201 assert(child != null);
134 if (_children.remove(child)) { 202 if (_children.remove(child)) {
135 child._parent = null; 203 child._parent = null;
136 child._spriteBox = null; 204 child._spriteBox = null;
137 if (_spriteBox != null) _spriteBox._eventTargets = null; 205 if (_spriteBox != null) _spriteBox._eventTargets = null;
138 } 206 }
139 } 207 }
140 208
209 /// Removes this node from its parent node.
210 ///
211 /// removeFromParent();
141 void removeFromParent() { 212 void removeFromParent() {
142 assert(_parent != null); 213 assert(_parent != null);
143 _parent.removeChild(this); 214 _parent.removeChild(this);
144 } 215 }
145 216
217 /// Removes all children of this node.
218 ///
219 /// removeAllChildren();
146 void removeAllChildren() { 220 void removeAllChildren() {
147 for (Node child in _children) { 221 for (Node child in _children) {
148 child._parent = null; 222 child._parent = null;
149 child._spriteBox = null; 223 child._spriteBox = null;
150 } 224 }
151 _children = []; 225 _children = [];
152 _childrenNeedSorting = false; 226 _childrenNeedSorting = false;
153 if (_spriteBox != null) _spriteBox._eventTargets = null; 227 if (_spriteBox != null) _spriteBox._eventTargets = null;
154 } 228 }
155 229
156 void _sortChildren() { 230 void _sortChildren() {
157 // Sort children primarily by zPosition, secondarily by added order 231 // Sort children primarily by zPosition, secondarily by added order
158 if (_childrenNeedSorting) { 232 if (_childrenNeedSorting) {
159 _children.sort((Node a, Node b) { 233 _children.sort((Node a, Node b) {
160 if (a._zPosition == b._zPosition) { 234 if (a._zPosition == b._zPosition) {
161 return a._addedOrder - b._addedOrder; 235 return a._addedOrder - b._addedOrder;
162 } 236 }
163 else if (a._zPosition > b._zPosition) { 237 else if (a._zPosition > b._zPosition) {
164 return 1; 238 return 1;
165 } 239 }
166 else { 240 else {
167 return -1; 241 return -1;
168 } 242 }
169 }); 243 });
170 _childrenNeedSorting = false; 244 _childrenNeedSorting = false;
171 } 245 }
172 } 246 }
173 247
174 // Calculating the transformation matrix 248 // Calculating the transformation matrix
175 249
250 /// The transformMatrix describes the transformation from the node's parent.
251 ///
252 /// You cannot set the transformMatrix directly, instead use the position, rot ation and scale properties.
253 ///
254 /// Matrix4 matrix = myNode.transformMatrix;
176 Matrix4 get transformMatrix { 255 Matrix4 get transformMatrix {
177 if (_transformMatrix != null) { 256 if (_transformMatrix != null) {
178 return _transformMatrix; 257 return _transformMatrix;
179 } 258 }
180 259
181 double cx, sx, cy, sy; 260 double cx, sx, cy, sy;
182 261
183 if (_rotation == 0.0) { 262 if (_rotation == 0.0) {
184 cx = 1.0; 263 cx = 1.0;
185 sx = 0.0; 264 sx = 0.0;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 if (_transformMatrixBoxToNode != null) { 323 if (_transformMatrixBoxToNode != null) {
245 return _transformMatrixBoxToNode; 324 return _transformMatrixBoxToNode;
246 } 325 }
247 326
248 _transformMatrixBoxToNode = new Matrix4.copy(_nodeToBoxMatrix()); 327 _transformMatrixBoxToNode = new Matrix4.copy(_nodeToBoxMatrix());
249 _transformMatrixBoxToNode.invert(); 328 _transformMatrixBoxToNode.invert();
250 329
251 return _transformMatrixBoxToNode; 330 return _transformMatrixBoxToNode;
252 } 331 }
253 332
333 /// Converts a point from the coordinate system of the [SpriteBox] to the loca l coordinate system of the node.
334 ///
335 /// This method is particularly useful when handling pointer events and need t he pointers position in a local
336 /// coordinate space.
337 ///
338 /// Point localPoint = myNode.convertPointToNodeSpace(pointInBoxCoordinate s);
254 Point convertPointToNodeSpace(Point boxPoint) { 339 Point convertPointToNodeSpace(Point boxPoint) {
255 assert(boxPoint != null); 340 assert(boxPoint != null);
256 assert(_spriteBox != null); 341 assert(_spriteBox != null);
257 342
258 Vector4 v =_boxToNodeMatrix().transform(new Vector4(boxPoint.x, boxPoint.y, 0.0, 1.0)); 343 Vector4 v =_boxToNodeMatrix().transform(new Vector4(boxPoint.x, boxPoint.y, 0.0, 1.0));
259 return new Point(v[0], v[1]); 344 return new Point(v[0], v[1]);
260 } 345 }
261 346
347 /// Converts a point from the local coordinate system of the node to the coord inate system of the [SpriteBox].
348 ///
349 /// Point pointInBoxCoordinates = myNode.convertPointToBoxSpace(localPoint );
262 Point convertPointToBoxSpace(Point nodePoint) { 350 Point convertPointToBoxSpace(Point nodePoint) {
263 assert(nodePoint != null); 351 assert(nodePoint != null);
264 assert(_spriteBox != null); 352 assert(_spriteBox != null);
265 353
266 Vector4 v =_nodeToBoxMatrix().transform(new Vector4(nodePoint.x, nodePoint.y , 0.0, 1.0)); 354 Vector4 v =_nodeToBoxMatrix().transform(new Vector4(nodePoint.x, nodePoint.y , 0.0, 1.0));
267 return new Point(v[0], v[1]); 355 return new Point(v[0], v[1]);
268 } 356 }
269 357
358 /// Converts a [point] from another [node]s coordinate system into the local c oordinate system of this node.
359 ///
360 /// Point pointInNodeASpace = nodeA.convertPointFromNode(pointInNodeBSpace , nodeB);
270 Point convertPointFromNode(Point point, Node node) { 361 Point convertPointFromNode(Point point, Node node) {
271 assert(node != null); 362 assert(node != null);
272 assert(point != null); 363 assert(point != null);
273 assert(_spriteBox != null); 364 assert(_spriteBox != null);
274 assert(_spriteBox == node._spriteBox); 365 assert(_spriteBox == node._spriteBox);
275 366
276 Point boxPoint = node.convertPointToBoxSpace(point); 367 Point boxPoint = node.convertPointToBoxSpace(point);
277 Point localPoint = convertPointToNodeSpace(boxPoint); 368 Point localPoint = convertPointToNodeSpace(boxPoint);
278 369
279 return localPoint; 370 return localPoint;
280 } 371 }
281 372
282 // Hit test 373 // Hit test
283 374
284 bool isPointInside(Point nodePoint) { 375 /// Returns true if the [point] is inside the node, the [point] is in the loca l coordinate system of the node.
285 assert(nodePoint != null); 376 ///
377 /// myNode.isPointInside(localPoint);
378 ///
379 /// [NodeWithSize] provides a basic bounding box check for this method, if you require a more detailed check this
380 /// method can be overridden.
381 ///
382 /// bool isPointInside (Point nodePoint) {
383 /// double minX = -size.width * pivot.x;
384 /// double minY = -size.height * pivot.y;
385 /// double maxX = minX + size.width;
386 /// double maxY = minY + size.height;
387 /// return (nodePoint.x >= minX && nodePoint.x < maxX &&
388 /// nodePoint.y >= minY && nodePoint.y < maxY);
389 /// }
390 bool isPointInside(Point point) {
391 assert(point != null);
286 392
287 return false; 393 return false;
288 } 394 }
289 395
290 // Rendering 396 // Rendering
291 397
292 void _visit(PictureRecorder canvas) { 398 void _visit(PictureRecorder canvas) {
293 assert(canvas != null); 399 assert(canvas != null);
294 if (!visible) return; 400 if (!visible) return;
295 401
296 _prePaint(canvas); 402 _prePaint(canvas);
297 _visitChildren(canvas); 403 _visitChildren(canvas);
298 _postPaint(canvas); 404 _postPaint(canvas);
299 } 405 }
300 406
301 void _prePaint(PictureRecorder canvas) { 407 void _prePaint(PictureRecorder canvas) {
302 canvas.save(); 408 canvas.save();
303 409
304 // Get the transformation matrix and apply transform 410 // Get the transformation matrix and apply transform
305 canvas.concat(transformMatrix.storage); 411 canvas.concat(transformMatrix.storage);
306 } 412 }
307 413
414 /// Paints this node to the canvas.
415 ///
416 /// Subclasses, such as [Sprite], override this method to do the actual painti ng of the node. To do custom
417 /// drawing override this method and make calls to the [canvas] object. All dr awing is done in the node's local
418 /// coordinate system, relative to the node's position. If you want to make th e drawing relative to the node's
419 /// bounding box's origin, override [NodeWithSize] and call the applyTransform ForPivot method before making calls for
420 /// drawing.
421 ///
422 /// void paint(PictureRecorder canvas) {
423 /// canvas.save();
424 /// applyTransformForPivot(canvas);
Hixie 2015/06/22 17:08:42 note that save/transform/restore is expensive (exp
425 ///
426 /// // Do painting here
427 ///
428 /// canvas.restore();
429 /// }
308 void paint(PictureRecorder canvas) { 430 void paint(PictureRecorder canvas) {
309 } 431 }
310 432
311 void _visitChildren(PictureRecorder canvas) { 433 void _visitChildren(PictureRecorder canvas) {
312 // Sort children if needed 434 // Sort children if needed
313 _sortChildren(); 435 _sortChildren();
314 436
315 int i = 0; 437 int i = 0;
316 438
317 // Visit children behind this node 439 // Visit children behind this node
(...skipping 14 matching lines...) Expand all
332 i++; 454 i++;
333 } 455 }
334 } 456 }
335 457
336 void _postPaint(PictureRecorder canvas) { 458 void _postPaint(PictureRecorder canvas) {
337 canvas.restore(); 459 canvas.restore();
338 } 460 }
339 461
340 // Receiving update calls 462 // Receiving update calls
341 463
464 /// Called before a frame is drawn.
465 ///
466 /// Override this method to do any updates to the node or node tree before it' s drawn to screen.
467 ///
468 /// // Make the node rotate at a fixed speed
469 /// void update(double dt) {
470 /// rotation = rotation * 10.0 * dt;
471 /// }
342 void update(double dt) { 472 void update(double dt) {
343 } 473 }
344 474
475 /// Called whenever the [SpriteBox] is modified or resized, or if the device i s rotated.
476 ///
477 /// Override this method to do any updates that may be necessary to correctly display the node or node tree with the
478 /// new layout of the [SpriteBox].
479 ///
480 /// void spriteBoxPerformedLayout() {
481 /// // Move some stuff around here
482 /// }
345 void spriteBoxPerformedLayout() { 483 void spriteBoxPerformedLayout() {
346 } 484 }
347 485
348 // Handling user interaction 486 // Handling user interaction
349 487
488 /// The node will receive user interactions, such as pointer (touch or mouse) events.
489 ///
490 /// class MyCustomNode extends NodeWithSize {
491 /// userInteractionEnabled = true;
492 /// }
350 bool get userInteractionEnabled => _userInteractionEnabled; 493 bool get userInteractionEnabled => _userInteractionEnabled;
351 494
352 void set userInteractionEnabled(bool userInteractionEnabled) { 495 void set userInteractionEnabled(bool userInteractionEnabled) {
353 _userInteractionEnabled = userInteractionEnabled; 496 _userInteractionEnabled = userInteractionEnabled;
354 if (_spriteBox != null) _spriteBox._eventTargets = null; 497 if (_spriteBox != null) _spriteBox._eventTargets = null;
355 } 498 }
356 499
500 /// Handles an event, such as a pointer (touch or mouse) event.
501 ///
502 /// Override this method to handle events. The node will only receive events i f the [userInteractionEnabled] property
503 /// is set to true and the [isPointInside] method returns true for the positio n of the pointer down event (default
504 /// behavior provided by [NodeWithSize]). Unless [handleMultiplePointers] is s et to true, the node will only receive
505 /// events for the first pointer that is down.
506 ///
507 /// Return true if the node has consumed the event, if an event is consumed it will not be passed on to nodes behind
508 /// the current node.
509 ///
510 /// // MyTouchySprite gets transparent when we touch it
511 /// class MyTouchySprite extends Sprite {
512 ///
513 /// MyTouchySprite(Image img) : super (img) {
514 /// userInteractionEnabled = true;
515 /// }
516 ///
517 /// bool handleEvent(SpriteBoxEvent event) {
518 /// if (event.type == 'pointerdown) {
519 /// opacity = 0.5;
520 /// }
521 /// else if (event.type == 'pointerup') {
522 /// opacity = 1.0;
523 /// }
524 /// return true;
525 /// }
526 /// }
357 bool handleEvent(SpriteBoxEvent event) { 527 bool handleEvent(SpriteBoxEvent event) {
358 return false; 528 return false;
359 } 529 }
360 } 530 }
OLDNEW
« no previous file with comments | « sky/examples/game/lib/game_demo_world.dart ('k') | sky/examples/game/lib/node_with_size.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698