From e90de2b65208d40c1e608e75284c77ad547a9726 Mon Sep 17 00:00:00 2001 From: Viktor Lidholt Date: Mon, 22 Jun 2015 10:13:23 -0700 Subject: [PATCH] Adds API documentation, improves the API names, and cleans up code. R=ianh@google.com Review URL: https://codereview.chromium.org/1201983004. --- examples/game/lib/game_demo_world.dart | 12 +- examples/game/lib/node.dart | 222 ++++++++++++++++++++++--- examples/game/lib/node_with_size.dart | 39 ++++- examples/game/lib/sprite.dart | 57 +++++-- examples/game/lib/sprite_box.dart | 94 +++++++++-- examples/game/lib/sprite_widget.dart | 19 ++- 6 files changed, 369 insertions(+), 74 deletions(-) diff --git a/examples/game/lib/game_demo_world.dart b/examples/game/lib/game_demo_world.dart index ce57d7084..605a08faa 100644 --- a/examples/game/lib/game_demo_world.dart +++ b/examples/game/lib/game_demo_world.dart @@ -42,7 +42,7 @@ class GameDemoWorld extends NodeWithSize { StarField _starField; Nebula _nebula; - GameDemoWorld(ImageMap images) : super.withSize(new Size(_gameSizeWidth, _gameSizeHeight)) { + GameDemoWorld(ImageMap images) : super(new Size(_gameSizeWidth, _gameSizeHeight)) { // Fetch images _imgBg = images["https://raw.githubusercontent.com/slembcke/GalacticGuardian.spritebuilder/GDC/Packages/SpriteBuilder%20Resources.sbpack/resources-auto/BurnTexture.png"]; @@ -81,7 +81,7 @@ class GameDemoWorld extends NodeWithSize { // Methods for adding game objects void addBackground() { - Sprite sprtBg = new Sprite.withImage(_imgBg); + Sprite sprtBg = new Sprite(_imgBg); sprtBg.size = new Size(_gameSizeWidth, _gameSizeHeight); sprtBg.pivot = Point.origin; _gameLayer.addChild(sprtBg); @@ -296,7 +296,7 @@ class Asteroid extends Sprite { return _radius; } - Asteroid.withImage(Image img, AsteroidSize this._asteroidSize) : super.withImage(img) { + Asteroid.withImage(Image img, AsteroidSize this._asteroidSize) : super(img) { size = new Size(radius * 2.0, radius * 2.0); position = new Point(_gameSizeWidth * _rand.nextDouble(), _gameSizeHeight * _rand.nextDouble()); rotation = 360.0 * _rand.nextDouble(); @@ -322,7 +322,7 @@ class Ship extends Sprite { Vector2 _movementVector; double _rotationTarget; - Ship.withImage(Image img) : super.withImage(img) { + Ship.withImage(Image img) : super(img) { _movementVector = new Vector2.zero(); rotation = _rotationTarget = 270.0; @@ -350,7 +350,7 @@ class Laser extends Sprite { Point _movementVector; double radius = 10.0; - Laser.withImage(Image img, Ship ship) : super.withImage(img) { + Laser.withImage(Image img, Ship ship) : super(img) { size = new Size(20.0, 20.0); position = ship.position; rotation = ship.rotation + 90.0; @@ -436,7 +436,7 @@ class Nebula extends Node { Nebula.withImage(Image img) { for (int i = 0; i < 2; i++) { for (int j = 0; j < 2; j++) { - Sprite sprt = new Sprite.withImage(img); + Sprite sprt = new Sprite(img); sprt.pivot = Point.origin; sprt.position = new Point(i * _gameSizeWidth - _gameSizeWidth, j * _gameSizeHeight - _gameSizeHeight); addChild(sprt); diff --git a/examples/game/lib/node.dart b/examples/game/lib/node.dart index 5ab4dec1c..ef6162be5 100644 --- a/examples/game/lib/node.dart +++ b/examples/game/lib/node.dart @@ -4,6 +4,15 @@ double convertDegrees2Radians(double degrees) => degrees * Math.PI/180.8; double convertRadians2Degrees(double radians) => radians * 180.0/Math.PI; +/// A base class for all objects that can be added to the sprite node tree and rendered to screen using [SpriteBox] and +/// [SpriteWidget]. +/// +/// The [Node] class itself doesn't render any content, but provides the basic functions of any type of node, such as +/// handling transformations and user input. To render the node tree, a root node must be added to a [SpriteBox] or a +/// [SpriteWidget]. Commonly used sub-classes of [Node] are [Sprite], [NodeWithSize], and many more upcoming subclasses. +/// +/// Nodes form a hierarchical tree. Each node can have a number of children, and the transformation (positioning, +/// rotation, and scaling) of a node also affects its children. class Node { // Member variables @@ -11,51 +20,72 @@ class Node { SpriteBox _spriteBox; Node _parent; - Point _position; - double _rotation; + Point _position = Point.origin; + double _rotation = 0.0; - Matrix4 _transformMatrix; + Matrix4 _transformMatrix = new Matrix4.identity(); Matrix4 _transformMatrixNodeToBox; Matrix4 _transformMatrixBoxToNode; - double _scaleX; - double _scaleY; + double _scaleX = 1.0; + double _scaleY = 1.0; - bool visible; + /// The visibility of this node and its children. + bool visible = true; - double _zPosition; + double _zPosition = 0.0; int _addedOrder; - int _childrenLastAddedOrder; - bool _childrenNeedSorting; - + int _childrenLastAddedOrder = 0; + bool _childrenNeedSorting = false; + + /// Decides if the node and its children is currently paused. + /// + /// A paused node will not receive any input events, update calls, or run any animations. + /// + /// myNodeTree.paused = true; bool paused = false; bool _userInteractionEnabled = false; + + /// If set to true the node will receive multiple pointers, otherwise it will only receive events the first pointer. + /// + /// This property is only meaningful if [userInteractionEnabled] is set to true. Default value is false. + /// + /// class MyCustomNode extends Node { + /// handleMultiplePointers = true; + /// } bool handleMultiplePointers = false; int _handlingPointer; - List_children; + List_children = []; // Constructors - + + /// Creates a new [Node] without any transformation. + /// + /// var myNode = new Node(); Node() { - _rotation = 0.0; - _position = Point.origin; - _scaleX = _scaleY = 1.0; - _transformMatrix = new Matrix4.identity(); - _children = []; - _childrenNeedSorting = false; - _childrenLastAddedOrder = 0; - _zPosition = 0.0; - visible = true; } // Property setters and getters + /// The [SpriteBox] this node is added to, or null if it's not currently added to a [SpriteBox]. + /// + /// For most applications it's not necessary to access the [SpriteBox] directly. + /// + /// // Get the transformMode of the sprite box + /// var transformMode = myNode.spriteBox.transformMode; SpriteBox get spriteBox => _spriteBox; + /// The parent of this node, or null if it doesn't have a parent. + /// + /// // Hide the parent + /// myNode.parent.visible = false; Node get parent => _parent; - + + /// The rotation of this node in degrees. + /// + /// myNode.rotation = 45.0; double get rotation => _rotation; void set rotation(double rotation) { @@ -64,6 +94,9 @@ class Node { _invalidateTransformMatrix(); } + /// The position of this node relative to its parent. + /// + /// myNode.position = new Point(42.0, 42.0); Point get position => _position; void set position(Point position) { @@ -72,6 +105,14 @@ class Node { _invalidateTransformMatrix(); } + /// The draw order of this node compared to its parent and its siblings. + /// + /// By default nodes are drawn in the order that they have been added to a parent. To override this behavior the + /// [zPosition] property can be used. A higher value of this property will force the node to be drawn in front of + /// siblings that have a lower value. If a negative value is used the node will be drawn behind its parent. + /// + /// nodeInFront.zPosition = 1.0; + /// nodeBehind.zPosition = -1.0; double get zPosition => _zPosition; void set zPosition(double zPosition) { @@ -82,6 +123,11 @@ class Node { } } + /// The scale of this node relative its parent. + /// + /// The [scale] property is only valid if [scaleX] and [scaleY] are equal values. + /// + /// myNode.scale = 5.0; double get scale { assert(_scaleX == _scaleY); return _scaleX; @@ -93,6 +139,9 @@ class Node { _invalidateTransformMatrix(); } + /// The horizontal scale of this node relative its parent. + /// + /// myNode.scaleX = 5.0; double get scaleX => _scaleX; void set scaleX(double scaleX) { @@ -101,6 +150,9 @@ class Node { _invalidateTransformMatrix(); } + /// The vertical scale of this node relative its parent. + /// + /// myNode.scaleY = 5.0; double get scaleY => _scaleY; void set scaleY(double scaleY) { @@ -109,6 +161,14 @@ class Node { _invalidateTransformMatrix(); } + /// A list of the children of this node. + /// + /// This list should only be modified by using the [addChild] and [removeChild] methods. + /// + /// // Iterate over a nodes children + /// for (Node child in myNode.children) { + /// // Do something with the child + /// } List get children { _sortChildren(); return _children; @@ -116,6 +176,11 @@ class Node { // Adding and removing children + /// Adds a child to this node. + /// + /// The same node cannot be added to multiple nodes. + /// + /// addChild(new Sprite(myImage)); void addChild(Node child) { assert(child != null); assert(child._parent == null); @@ -129,6 +194,9 @@ class Node { if (_spriteBox != null) _spriteBox._eventTargets = null; } + /// Removes a child from this node. + /// + /// removeChild(myChildNode); void removeChild(Node child) { assert(child != null); if (_children.remove(child)) { @@ -138,11 +206,17 @@ class Node { } } + /// Removes this node from its parent node. + /// + /// removeFromParent(); void removeFromParent() { assert(_parent != null); _parent.removeChild(this); } + /// Removes all children of this node. + /// + /// removeAllChildren(); void removeAllChildren() { for (Node child in _children) { child._parent = null; @@ -172,7 +246,12 @@ class Node { } // Calculating the transformation matrix - + + /// The transformMatrix describes the transformation from the node's parent. + /// + /// You cannot set the transformMatrix directly, instead use the position, rotation and scale properties. + /// + /// Matrix4 matrix = myNode.transformMatrix; Matrix4 get transformMatrix { if (_transformMatrix != null) { return _transformMatrix; @@ -251,6 +330,12 @@ class Node { return _transformMatrixBoxToNode; } + /// Converts a point from the coordinate system of the [SpriteBox] to the local coordinate system of the node. + /// + /// This method is particularly useful when handling pointer events and need the pointers position in a local + /// coordinate space. + /// + /// Point localPoint = myNode.convertPointToNodeSpace(pointInBoxCoordinates); Point convertPointToNodeSpace(Point boxPoint) { assert(boxPoint != null); assert(_spriteBox != null); @@ -259,6 +344,9 @@ class Node { return new Point(v[0], v[1]); } + /// Converts a point from the local coordinate system of the node to the coordinate system of the [SpriteBox]. + /// + /// Point pointInBoxCoordinates = myNode.convertPointToBoxSpace(localPoint); Point convertPointToBoxSpace(Point nodePoint) { assert(nodePoint != null); assert(_spriteBox != null); @@ -267,6 +355,9 @@ class Node { return new Point(v[0], v[1]); } + /// Converts a [point] from another [node]s coordinate system into the local coordinate system of this node. + /// + /// Point pointInNodeASpace = nodeA.convertPointFromNode(pointInNodeBSpace, nodeB); Point convertPointFromNode(Point point, Node node) { assert(node != null); assert(point != null); @@ -281,8 +372,23 @@ class Node { // Hit test - bool isPointInside(Point nodePoint) { - assert(nodePoint != null); + /// Returns true if the [point] is inside the node, the [point] is in the local coordinate system of the node. + /// + /// myNode.isPointInside(localPoint); + /// + /// [NodeWithSize] provides a basic bounding box check for this method, if you require a more detailed check this + /// method can be overridden. + /// + /// bool isPointInside (Point nodePoint) { + /// double minX = -size.width * pivot.x; + /// double minY = -size.height * pivot.y; + /// double maxX = minX + size.width; + /// double maxY = minY + size.height; + /// return (nodePoint.x >= minX && nodePoint.x < maxX && + /// nodePoint.y >= minY && nodePoint.y < maxY); + /// } + bool isPointInside(Point point) { + assert(point != null); return false; } @@ -304,7 +410,23 @@ class Node { // Get the transformation matrix and apply transform canvas.concat(transformMatrix.storage); } - + + /// Paints this node to the canvas. + /// + /// Subclasses, such as [Sprite], override this method to do the actual painting of the node. To do custom + /// drawing override this method and make calls to the [canvas] object. All drawing is done in the node's local + /// coordinate system, relative to the node's position. If you want to make the drawing relative to the node's + /// bounding box's origin, override [NodeWithSize] and call the applyTransformForPivot method before making calls for + /// drawing. + /// + /// void paint(PictureRecorder canvas) { + /// canvas.save(); + /// applyTransformForPivot(canvas); + /// + /// // Do painting here + /// + /// canvas.restore(); + /// } void paint(PictureRecorder canvas) { } @@ -339,14 +461,35 @@ class Node { // Receiving update calls + /// Called before a frame is drawn. + /// + /// Override this method to do any updates to the node or node tree before it's drawn to screen. + /// + /// // Make the node rotate at a fixed speed + /// void update(double dt) { + /// rotation = rotation * 10.0 * dt; + /// } void update(double dt) { } + /// Called whenever the [SpriteBox] is modified or resized, or if the device is rotated. + /// + /// Override this method to do any updates that may be necessary to correctly display the node or node tree with the + /// new layout of the [SpriteBox]. + /// + /// void spriteBoxPerformedLayout() { + /// // Move some stuff around here + /// } void spriteBoxPerformedLayout() { } // Handling user interaction + /// The node will receive user interactions, such as pointer (touch or mouse) events. + /// + /// class MyCustomNode extends NodeWithSize { + /// userInteractionEnabled = true; + /// } bool get userInteractionEnabled => _userInteractionEnabled; void set userInteractionEnabled(bool userInteractionEnabled) { @@ -354,6 +497,33 @@ class Node { if (_spriteBox != null) _spriteBox._eventTargets = null; } + /// Handles an event, such as a pointer (touch or mouse) event. + /// + /// Override this method to handle events. The node will only receive events if the [userInteractionEnabled] property + /// is set to true and the [isPointInside] method returns true for the position of the pointer down event (default + /// behavior provided by [NodeWithSize]). Unless [handleMultiplePointers] is set to true, the node will only receive + /// events for the first pointer that is down. + /// + /// Return true if the node has consumed the event, if an event is consumed it will not be passed on to nodes behind + /// the current node. + /// + /// // MyTouchySprite gets transparent when we touch it + /// class MyTouchySprite extends Sprite { + /// + /// MyTouchySprite(Image img) : super (img) { + /// userInteractionEnabled = true; + /// } + /// + /// bool handleEvent(SpriteBoxEvent event) { + /// if (event.type == 'pointerdown) { + /// opacity = 0.5; + /// } + /// else if (event.type == 'pointerup') { + /// opacity = 1.0; + /// } + /// return true; + /// } + /// } bool handleEvent(SpriteBoxEvent event) { return false; } diff --git a/examples/game/lib/node_with_size.dart b/examples/game/lib/node_with_size.dart index 33d4ee6be..b527619b8 100644 --- a/examples/game/lib/node_with_size.dart +++ b/examples/game/lib/node_with_size.dart @@ -1,18 +1,45 @@ part of sprites; +/// The super class of any [Node] that has a size. +/// +/// NodeWithSize adds the ability for a node to have a size and a pivot point. abstract class NodeWithSize extends Node { + + /// Changing the size will affect the size of the rendering of the node. + /// + /// myNode.size = new Size(1024.0, 1024.0); Size size; - Point pivot; - NodeWithSize() { - size = Size.zero; - pivot = Point.origin; - } + /// The normalized point which the node is transformed around. + /// + /// // Position myNode from is middle top + /// myNode.pivot = new Point(0.5, 0.0); + Point pivot; - NodeWithSize.withSize(Size this.size, [Point this.pivot]) { + /// Creates a new NodeWithSize. + /// + /// The default [size] is zero and the default [pivot] point is the origin. Subclasses may change the default values. + /// + /// var myNodeWithSize = new NodeWithSize(new Size(1024.0, 1024.0)); + NodeWithSize([Size this.size, Point this.pivot]) { + if (size == null) size = Size.zero; if (pivot == null) pivot = Point.origin; } + /// Call this method in your [paint] method if you want the origin of your drawing to be the top left corner of the + /// node's bounding box. + /// + /// If you use this method you will need to save and restore your canvas at the beginning and + /// end of your [paint] method. + /// + /// void paint(PictureRecorder canvas) { + /// canvas.save(); + /// applyTransformForPivot(canvas); + /// + /// // Do painting here + /// + /// canvas.restore(); + /// } void applyTransformForPivot(PictureRecorder canvas) { if (pivot.x != 0 || pivot.y != 0) { double pivotInPointsX = size.width * pivot.x; diff --git a/examples/game/lib/sprite.dart b/examples/game/lib/sprite.dart index c730056eb..a58168f18 100644 --- a/examples/game/lib/sprite.dart +++ b/examples/game/lib/sprite.dart @@ -1,24 +1,47 @@ part of sprites; -// TODO: Actually draw images - +/// A Sprite is a [Node] that renders a bitmap image to the screen. class Sprite extends NodeWithSize { - - Image _image; + + /// The image that the sprite will render to screen. + /// + /// If the image is null, the sprite will be rendered as a red square + /// marking the bounds of the sprite. + /// + /// mySprite.image = myImage; + Image image; + + /// If true, constrains the proportions of the image by scaling it down, if its proportions doesn't match the [size]. + /// + /// mySprite.constrainProportions = true; bool constrainProportions = false; double _opacity = 1.0; + + /// The color to draw on top of the sprite, null if no color overlay is used. + /// + /// // Color the sprite red + /// mySprite.colorOverlay = new Color(0x77ff0000); Color colorOverlay; + + /// The transfer mode used when drawing the sprite to screen. + /// + /// // Add the colors of the sprite with the colors of the background + /// mySprite.transferMode = TransferMode.plusMode; TransferMode transferMode; - - Sprite() { - } - - Sprite.withImage(Image image) { + + /// Creates a new sprite from the provided [image]. + /// + /// var mySprite = new Sprite(myImage); + Sprite([Image this.image]) { pivot = new Point(0.5, 0.5); - size = new Size(image.width.toDouble(), image.height.toDouble()); - _image = image; + if (image != null) { + size = new Size(image.width.toDouble(), image.height.toDouble()); + } } + /// The opacity of the sprite in the range 0.0 to 1.0. + /// + /// mySprite.opacity = 0.5; double get opacity => _opacity; void set opacity(double opacity) { @@ -33,19 +56,19 @@ class Sprite extends NodeWithSize { // Account for pivot point applyTransformForPivot(canvas); - if (_image != null && _image.width > 0 && _image.height > 0) { + if (image != null && image.width > 0 && image.height > 0) { - double scaleX = size.width/_image.width; - double scaleY = size.height/_image.height; + double scaleX = size.width/image.width; + double scaleY = size.height/image.height; if (constrainProportions) { // Constrain proportions, using the smallest scale and by centering the image if (scaleX < scaleY) { - canvas.translate(0.0, (size.height - scaleX * _image.height)/2.0); + canvas.translate(0.0, (size.height - scaleX * image.height)/2.0); scaleY = scaleX; } else { - canvas.translate((size.width - scaleY * _image.width)/2.0, 0.0); + canvas.translate((size.width - scaleY * image.width)/2.0, 0.0); scaleX = scaleY; } } @@ -62,7 +85,7 @@ class Sprite extends NodeWithSize { paint.setTransferMode(transferMode); } - canvas.drawImage(_image, 0.0, 0.0, paint); + canvas.drawImage(image, 0.0, 0.0, paint); } else { // Paint a red square for missing texture diff --git a/examples/game/lib/sprite_box.dart b/examples/game/lib/sprite_box.dart index 131c4d01f..173b1d894 100644 --- a/examples/game/lib/sprite_box.dart +++ b/examples/game/lib/sprite_box.dart @@ -1,5 +1,17 @@ part of sprites; +/// Options for setting up a [SpriteBox]. +/// +/// * [nativePoints], use the same points as the parent [Widget]. +/// * [letterbox], use the size of the root node for the coordinate system, constrain the aspect ratio and trim off +/// areas that end up outside the screen. +/// * [stretch], use the size of the root node for the coordinate system, scale it to fit the size of the box. +/// * [scaleToFit], similar to the letterbox option, but instead of trimming areas the sprite system will be scaled +/// down to fit the box. +/// * [fixedWidth], uses the width of the root node to set the size of the coordinate system, this option will change +/// the height of the root node to fit the box. +/// * [fixedHeight], uses the height of the root node to set the size of the coordinate system, this option will change +/// the width of the root node to fit the box. enum SpriteBoxTransformMode { nativePoints, letterbox, @@ -22,9 +34,10 @@ class SpriteBox extends RenderBox { double _frameRate = 0.0; // Transformation mode - SpriteBoxTransformMode transformMode; -// double _systemWidth; -// double _systemHeight; + SpriteBoxTransformMode _transformMode; + + /// The transform mode used by the [SpriteBox]. + SpriteBoxTransformMode get transformMode => _transformMode; // Cached transformation matrix Matrix4 _transformMatrix; @@ -33,7 +46,14 @@ class SpriteBox extends RenderBox { // Setup - SpriteBox(NodeWithSize rootNode, [SpriteBoxTransformMode mode = SpriteBoxTransformMode.nativePoints]) { + /// Creates a new SpriteBox with a node as its content, by default uses letterboxing. + /// + /// The [rootNode] provides the content of the node tree, typically it's a custom subclass of [NodeWithSize]. The + /// [mode] provides different ways to scale the content to best fit it to the screen. In most cases it's preferred to + /// use a [SpriteWidget] that automatically wraps the SpriteBox. + /// + /// var spriteBox = new SpriteBox(myNode, SpriteBoxTransformMode.fixedHeight); + SpriteBox(NodeWithSize rootNode, [SpriteBoxTransformMode mode = SpriteBoxTransformMode.letterbox]) { assert(rootNode != null); assert(rootNode._spriteBox == null); @@ -44,9 +64,7 @@ class SpriteBox extends RenderBox { _addSpriteBoxReference(_rootNode); // Setup transform mode - transformMode = mode; -// _systemWidth = rootNode.size.width; -// _systemHeight = rootNode.size.height; + _transformMode = mode; _scheduleTick(); } @@ -60,9 +78,9 @@ class SpriteBox extends RenderBox { // Properties - double get systemWidth => rootNode.size.width; - double get systemHeight => rootNode.size.height; - + /// The root node of the node tree that is rendered by this box. + /// + /// var rootNode = mySpriteBox.rootNode; NodeWithSize get rootNode => _rootNode; void performLayout() { @@ -98,7 +116,7 @@ class SpriteBox extends RenderBox { } } - void handleEvent(Event event, SpriteBoxHitTestEntry entry) { + void handleEvent(Event event, _SpriteBoxHitTestEntry entry) { if (event is PointerEvent) { if (event.type == 'pointerdown') { @@ -148,12 +166,17 @@ class SpriteBox extends RenderBox { } bool hitTest(HitTestResult result, { Point position }) { - result.add(new SpriteBoxHitTestEntry(this, position)); + result.add(new _SpriteBoxHitTestEntry(this, position)); return true; } // Rendering + /// The transformation matrix used to transform the root node to the space of the box. + /// + /// It's uncommon to need access to this property. + /// + /// var matrix = mySpriteBox.transformMatrix; Matrix4 get transformMatrix { // Get cached matrix if available if (_transformMatrix != null) { @@ -171,7 +194,7 @@ class SpriteBox extends RenderBox { double systemWidth = rootNode.size.width; double systemHeight = rootNode.size.height; - switch(transformMode) { + switch(_transformMode) { case SpriteBoxTransformMode.stretch: scaleX = size.width/systemWidth; scaleY = size.height/systemHeight; @@ -287,6 +310,12 @@ class SpriteBox extends RenderBox { // Hit tests + /// Finds all nodes at a position defined in the box's coordinates. + /// + /// Use this method with caution. It searches the complete node tree to locate the nodes, which can be slow if the + /// node tree is large. + /// + /// List nodes = mySpriteBox.findNodesAtPosition(new Point(50.0, 50.0)); List findNodesAtPosition(Point position) { assert(position != null); @@ -311,15 +340,44 @@ class SpriteBox extends RenderBox { } } -class SpriteBoxHitTestEntry extends BoxHitTestEntry { +class _SpriteBoxHitTestEntry extends BoxHitTestEntry { List nodeTargets; - SpriteBoxHitTestEntry(RenderBox target, Point localPosition) : super(target, localPosition); + _SpriteBoxHitTestEntry(RenderBox target, Point localPosition) : super(target, localPosition); } +/// An event that is passed down the node tree when pointer events occur. The SpriteBoxEvent is typically handled in +/// the handleEvent method of [Node]. class SpriteBoxEvent { - Point boxPosition; - String type; - int pointer; + /// The position of the event in box coordinates. + /// + /// You can use the convertPointToNodeSpace of [Node] to convert the position to local coordinates. + /// + /// bool handleEvent(SpriteBoxEvent event) { + /// Point localPosition = convertPointToNodeSpace(event.boxPosition); + /// if (event.type == 'pointerdown') { + /// // Do something! + /// } + /// } + final Point boxPosition; + + /// The type of event, there are currently four valid types, 'pointerdown', 'pointermoved', 'pointerup', and + /// 'pointercancel'. + /// + /// if (event.type == 'pointerdown') { + /// // Do something! + /// } + final String type; + + /// The id of the pointer. Each pointer on the screen will have a unique pointer id. + /// + /// if (event.pointer == firstPointerId) { + /// // Do something + /// } + final int pointer; + + /// Creates a new SpriteBoxEvent, typically this is done internally inside the SpriteBox. + /// + /// var event = new SpriteBoxEvent(new Point(50.0, 50.0), 'pointerdown', 0); SpriteBoxEvent(this.boxPosition, this.type, this.pointer); } \ No newline at end of file diff --git a/examples/game/lib/sprite_widget.dart b/examples/game/lib/sprite_widget.dart index 11a06a367..95934ae75 100644 --- a/examples/game/lib/sprite_widget.dart +++ b/examples/game/lib/sprite_widget.dart @@ -1,10 +1,27 @@ part of sprites; +/// A widget that uses a [SpriteBox] to render a sprite node tree to the screen. class SpriteWidget extends OneChildRenderObjectWrapper { + /// The rootNode of the sprite node tree. + /// + /// var node = mySpriteWidget.rootNode; final NodeWithSize rootNode; + + /// The transform mode used to fit the sprite node tree to the size of the widget. final SpriteBoxTransformMode transformMode; + /// Creates a new sprite widget with [rootNode] as its content. + /// + /// The widget will setup the coordinate space for the sprite node tree using the size of the [rootNode] in + /// combination with the supplied [transformMode]. By default the letterbox transform mode is used. See + /// [SpriteBoxTransformMode] for more details on the different modes. + /// + /// The most common way to setup the sprite node graph is to subclass [NodeWithSize] and pass it to the sprite widget. + /// In the custom subclass it's possible to build the node graph, do animations and handle user events. + /// + /// var mySpriteTree = new MyCustomNodeWithSize(); + /// var mySpriteWidget = new SpriteWidget(mySpriteTree, SpriteBoxTransformMode.fixedHeight); SpriteWidget(this.rootNode, [this.transformMode = SpriteBoxTransformMode.letterbox]); SpriteBox get root => super.root; @@ -16,6 +33,6 @@ class SpriteWidget extends OneChildRenderObjectWrapper { // SpriteBox doesn't allow mutation of these properties assert(rootNode == root.rootNode); - assert(transformMode == root.transformMode); + assert(transformMode == root._transformMode); } } \ No newline at end of file -- GitLab