Dart DocumentationstagexlStage

Stage class

The Stage is the drawing area wher all display objects are rendered to. Place a Canvas element to your HTML and use the Stage to wrap all the rendering functions to this Canvas element.

Example:

HTML: <canvas id="stage" width="800" height="600"></canvas> Dart: var stage = new Stage(querySelector("#stage"));

class Stage extends DisplayObjectContainer {

 static bool autoHiDpi = _autoHiDpi;
 static bool get isMobile => _isMobile;
 static num get devicePixelRatio => _devicePixelRatio;

 CanvasElement _canvas;
 RenderContext _renderContext;

 int _sourceWidth = 0;
 int _sourceHeight = 0;
 int _frameRate = 30;
 int _canvasWidth = -1;
 int _canvasHeight = -1;
 Rectangle _contentRectangle = new Rectangle.zero();

 Matrix _clientTransformation = new Matrix.fromIdentity();
 Matrix _stageTransformation = new Matrix.fromIdentity();
 RenderLoop _renderLoop = null;
 Juggler _juggler = new Juggler();

 InteractiveObject _focus = null;
 RenderState _renderState = null;
 String _stageRenderMode = StageRenderMode.AUTO;
 String _stageScaleMode = StageScaleMode.SHOW_ALL;
 String _stageAlign = StageAlign.NONE;

 String _mouseCursor = MouseCursor.ARROW;
 Point _mousePosition = new Point.zero();
 InteractiveObject _mouseTarget = null;

 Map<int, _Touch> _touches = new Map<int, _Touch>();
 List<_MouseButton> _mouseButtons = [
   new _MouseButton(MouseEvent.MOUSE_DOWN, MouseEvent.MOUSE_UP, MouseEvent.CLICK, MouseEvent.DOUBLE_CLICK),
   new _MouseButton(MouseEvent.MIDDLE_MOUSE_DOWN, MouseEvent.MIDDLE_MOUSE_UP, MouseEvent.MIDDLE_CLICK, MouseEvent.MIDDLE_CLICK),
   new _MouseButton(MouseEvent.RIGHT_MOUSE_DOWN, MouseEvent.RIGHT_MOUSE_UP, MouseEvent.RIGHT_CLICK, MouseEvent.RIGHT_CLICK)];

 //-------------------------------------------------------------------------------------------------

 static const EventStreamProvider<Event> resizeEvent = const EventStreamProvider<Event>(Event.RESIZE);
 EventStream<Event> get onResize => Stage.resizeEvent.forTarget(this);

 //-------------------------------------------------------------------------------------------------

 Stage(CanvasElement canvas, {int width, int height,
   bool webGL: false, int frameRate: 30, int color: Color.White}) {

   if (canvas is! CanvasElement) {
     throw new ArgumentError("The canvas argument is not a CanvasElement");
   }

   _canvas = canvas;

   if (canvas.tabIndex == -1) canvas.tabIndex = 0;
   if (canvas.style.outline == "") canvas.style.outline = "none";

   _sourceWidth = _ensureInt((width != null) ? width : canvas.width);
   _sourceHeight = _ensureInt((width != null) ? height : canvas.height);
   _frameRate = _ensureInt((frameRate != null) ? frameRate : 30);

   _renderContext = webGL && gl.RenderingContext.supported
       ? new RenderContextWebGL(canvas, color)
       : new RenderContextCanvas(canvas, color);

   _renderState = new RenderState(_renderContext);
   _updateCanvasSize();

   print("StageXL render engine : ${_renderContext.renderEngine}");

   canvas.onKeyDown.listen(_onKeyEvent);
   canvas.onKeyUp.listen(_onKeyEvent);
   canvas.onKeyPress.listen(_onKeyEvent);
   canvas.onMouseDown.listen(_onMouseEvent);
   canvas.onMouseUp.listen(_onMouseEvent);
   canvas.onMouseMove.listen(_onMouseEvent);
   canvas.onMouseOut.listen(_onMouseEvent);
   canvas.onContextMenu.listen(_onMouseEvent);
   canvas.onMouseWheel.listen(_onMouseWheelEvent);

   Mouse._onMouseCursorChanged.listen(_onMouseCursorChanged);
   Multitouch._onInputModeChanged.listen(_onMultitouchInputModeChanged);

   _onMultitouchInputModeChanged(null);
 }

 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------

 /**
  * Gets the original source width of the Stage as defined in the constructor.
  */
 int get sourceWidth => _sourceWidth;

 /**
  * Gets the original source height of the Stage as defined in the constructor.
  */
 int get sourceHeight => _sourceHeight;

 /**
  * Gets the current width of the Stage in pixels on the screen.
  */
 int get stageWidth => _canvasWidth;

 /**
  * Gets the current height of the Stage in pixels on the screen.
  */
 int get stageHeight => _canvasHeight;

 /**
  * Gets the available content area on the stage. The value of this rectangle
  * changes with the scaleMode and the alignment of the stage, as well as the size
  * of the underlying Canvas element.
  */
 Rectangle get contentRectangle => _contentRectangle.clone();

 /**
  * Gets the underlying render engine used to draw the pixels to the screen.
  * The returned string is defined in [RenderEngine] and is either "WebGL"
  * or "Canvas2D".
  */
 String get renderEngine => _renderContext.renderEngine;

 /**
  * Gets the [RenderLoop] where this Stage was added to, or
  * NULL in case this Stage is not added to a [RenderLoop].
  */
 RenderLoop get renderLoop => _renderLoop;

 /**
  * Gets the [Juggler] of this Stage. The Juggler is driven by the
  * [RenderLoop] where this Stage is added to. If this Stage is not
  * added to a RenderLoop, the [Juggler] will not advance in time.
  */
 Juggler get juggler => _juggler;

 /**
  * Gets the last known mouse position in Stage coordinates.
  */
 Point get mousePosition => _mousePosition;

 /**
  * Gets and sets the default frame rate for MovieClips. This value has no
  * impact on the frame rate of the Stage itself.
  */
 int get frameRate => _frameRate;

 set frameRate(int value) {
   _frameRate = value;
 }

 /**
  * Gets and sets the [InteractiveObject] (a DisplayObject which can
  * receive user input like mouse, touch or keyboard).
  */
 InteractiveObject get focus => _focus;

 set focus(InteractiveObject value) {
   _focus = value;
 }

 /**
  * Gets and sets the render mode of this Stage. You can choose between
  * three different modes defined in [StageRenderMode].
  */
 String get renderMode => _stageRenderMode;

 set renderMode(String value) {
   _stageRenderMode = value;
 }

 /**
  * Gets and sets the scale mode of this Stage. You can choose between
  * four dfferent modes defined in [StageScaleMode].
  */
 String get scaleMode => _stageScaleMode;

 set scaleMode(String value) {
   _stageScaleMode = value;
   _updateCanvasSize();
 }

 /**
  * Gets and sets the alignment of this Stage inside of the Canvas element.
  * You can choose between nine different align modes defined in [StageAlign].
  */
 String get align => _stageAlign;
 set align(String value) {
   _stageAlign = value;
   _updateCanvasSize();
 }

 /**
  * Calling this method will cause an [RenderEvent] to be fired right before
  * the next frame will be rendered by the render loop. To receive the render
  * event attach a listener to [DisplayObject.onRender].
  */
 invalidate() {
   if (_renderLoop != null) {
     _renderLoop.invalidate();
   }
 }

 //-------------------------------------------------------------------------------------------------

 _throwStageException() {
   throw new UnsupportedError("Error #2071: The Stage class does not implement this property or method.");
 }

 set x(num value) { _throwStageException(); }
 set y(num value) { _throwStageException(); }
 set pivotX(num value) { _throwStageException(); }
 set pivotY(num value) { _throwStageException(); }
 set scaleX(num value) { _throwStageException(); }
 set scaleY(num value) { _throwStageException(); }
 set skewX(num value) { _throwStageException(); }
 set skewY(num value) { _throwStageException(); }
 set rotation(num value) { _throwStageException(); }
 set alpha(num value) { _throwStageException(); }
 set width(num value) { _throwStageException(); }
 set height(num value) { _throwStageException(); }

 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------

 /**
  * This method is called by the [RenderLoop] where this Stage is added to.
  * If this Stage is not added to a [RenderLoop] you could call this method
  * on your own and therefore get full control of the rendering of this Stage.
  */
 materialize(num currentTime, num deltaTime) {

   if (_stageRenderMode == StageRenderMode.AUTO || _stageRenderMode == StageRenderMode.ONCE) {

     _updateCanvasSize();

     _renderState.reset(_stageTransformation, currentTime, deltaTime);
     render(_renderState);
     _renderState.flush();

     if (_stageRenderMode == StageRenderMode.ONCE)
       _stageRenderMode = StageRenderMode.STOP;
   }
 }

 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------

 _updateCanvasSize() {

   var client = _canvas.getBoundingClientRect();
   var clientLeft = _canvas.clientLeft + client.left;
   var clientTop = _canvas.clientTop + client.top;
   var clientWidth = _canvas.clientWidth;
   var clientHeight = _canvas.clientHeight;
   var sourceWidth = _sourceWidth;
   var sourceHeight = _sourceHeight;

   if (clientWidth is! num) throw "dart2js_hint";
   if (clientHeight is! num) throw "dart2js_hint";
   if (sourceWidth is! num) throw "dart2js_hint";
   if (sourceHeight is! num) throw "dart2js_hint";

   if (clientWidth == 0 || clientHeight == 0) return;

   //----------------------------

   var scaleX = 1.0;
   var scaleY = 1.0;
   var pivotX = 0.0;
   var pivotY = 0.0;
   var ratioWidth = clientWidth / sourceWidth;
   var ratioHeight = clientHeight / sourceHeight;

   switch(_stageScaleMode) {
     case StageScaleMode.EXACT_FIT:
       scaleX = ratioWidth;
       scaleY = ratioHeight;
       break;
     case StageScaleMode.NO_BORDER:
       scaleX = scaleY = (ratioWidth > ratioHeight) ? ratioWidth : ratioHeight;
       break;
     case StageScaleMode.NO_SCALE:
       scaleX = scaleY = 1.0;
       break;
     case StageScaleMode.SHOW_ALL:
       scaleX = scaleY = (ratioWidth < ratioHeight) ? ratioWidth : ratioHeight;
       break;
   }

   switch(_stageAlign) {
     case StageAlign.TOP_RIGHT:
     case StageAlign.RIGHT:
     case StageAlign.BOTTOM_RIGHT:
       pivotX = (clientWidth - sourceWidth * scaleX);
       break;
     case StageAlign.TOP:
     case StageAlign.NONE:
     case StageAlign.BOTTOM:
       pivotX = (clientWidth - sourceWidth * scaleX) / 2;
       break;
   }

   switch(_stageAlign) {
     case StageAlign.BOTTOM_LEFT:
     case StageAlign.BOTTOM:
     case StageAlign.BOTTOM_RIGHT:
       pivotY = (clientHeight - sourceHeight * scaleY);
       break;
     case StageAlign.LEFT:
     case StageAlign.NONE:
     case StageAlign.RIGHT:
       pivotY = (clientHeight - sourceHeight * scaleY) / 2;
       break;
   }

   //----------------------------

   var contentRectangle = _contentRectangle;
   contentRectangle.x = - pivotX / scaleX;
   contentRectangle.y = - pivotY / scaleY;
   contentRectangle.width = clientWidth / scaleX;
   contentRectangle.height = clientHeight / scaleY;

   var pixelRatio = (Stage.autoHiDpi ? _devicePixelRatio : 1.0) / _backingStorePixelRatio;

   // stage to canvas coordinate transformation
   _stageTransformation.setTo(scaleX, 0.0, 0.0, scaleY, pivotX, pivotY);
   _stageTransformation.scale(pixelRatio, pixelRatio);

   // client to stage coordinate transformation
   _clientTransformation.setTo(1.0, 0.0, 0.0, 1.0, - clientLeft - pivotX, - clientTop - pivotY);
   _clientTransformation.scale(1.0 / scaleX, 1.0 / scaleY);

   if (_canvasWidth != clientWidth || _canvasHeight != clientHeight) {
     _canvasWidth = clientWidth;
     _canvasHeight = clientHeight;
     _canvas.width = (_canvasWidth * pixelRatio).round();
     _canvas.height = (_canvasHeight * pixelRatio).round();

     // update hi-dpi canvas style size if client size has changed
     if (_canvas.clientWidth != clientWidth || _canvas.clientHeight != clientHeight) {
       _canvas.style.width = "${clientWidth}px";
       _canvas.style.height = "${clientHeight}px";
     }

     dispatchEvent(new Event(Event.RESIZE));
   }
 }

 //-------------------------------------------------------------------------------------------------

 _onMouseCursorChanged(String action) {

   _canvas.style.cursor = Mouse._getCssStyle(_mouseCursor);
 }

 //-------------------------------------------------------------------------------------------------

 _onMouseEvent(html.MouseEvent event) {

   event.preventDefault();

   var time = new DateTime.now().millisecondsSinceEpoch;
   var button = event.button;

   InteractiveObject target = null;
   Point stagePoint = _clientTransformation._transformHtmlPoint(event.client);
   Point localPoint = null;

   if (button < 0 || button > 2) return;
   if (event.type == "mousemove" && _mousePosition.equals(stagePoint)) return;

   _MouseButton mouseButton = _mouseButtons[button];
   _mousePosition = stagePoint;

   if (Mouse._dragSprite != null) {
     Mouse._dragSprite._updateDrag();
   }

   if (event.type != "mouseout") {
     target = hitTestInput(stagePoint.x, stagePoint.y) as InteractiveObject;
   }

   //-----------------------------------------------------------------

   var mouseCursor = MouseCursor.ARROW;

   if (target is Sprite && (target as Sprite).useHandCursor) {
     mouseCursor = MouseCursor.BUTTON;
   }

   if (target is SimpleButton && (target as SimpleButton).useHandCursor) {
     mouseCursor = MouseCursor.BUTTON;
   }

   if (target is TextField && (target as TextField).type == TextFieldType.INPUT) {
     mouseCursor = MouseCursor.IBEAM;
   }

   if (_mouseCursor != mouseCursor) {
     _mouseCursor = mouseCursor;
     _canvas.style.cursor = Mouse._getCssStyle(mouseCursor);
   }

   //-----------------------------------------------------------------

   if (_mouseTarget != target) {

     DisplayObject oldTarget = _mouseTarget;
     DisplayObject newTarget = target;
     List oldTargetList = [];
     List newTargetList = [];
     int commonCount = 0;

     for(DisplayObject p = oldTarget; p != null; p = p.parent) {
       oldTargetList.add(p);
     }

     for(DisplayObject p = newTarget; p != null; p = p.parent) {
       newTargetList.add(p);
     }

     for(;;commonCount++) {
       if (commonCount == oldTargetList.length) break;
       if (commonCount == newTargetList.length) break;
       var ot = oldTargetList[oldTargetList.length - commonCount - 1];
       var nt = newTargetList[newTargetList.length - commonCount - 1];
       if (ot != nt) break;
     }

     if (oldTarget != null) {
       oldTarget.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OUT, true)
           .._localPoint = oldTarget.globalToLocal(stagePoint)
           .._stagePoint = stagePoint
           .._buttonDown = mouseButton.buttonDown);
     }

     for(int i = 0; i < oldTargetList.length - commonCount; i++) {
       DisplayObject target = oldTargetList[i];
       target.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT, false)
           .._localPoint = target.globalToLocal(stagePoint)
           .._stagePoint = stagePoint
           .._buttonDown = mouseButton.buttonDown);
     }

     for(int i = newTargetList.length - commonCount - 1; i >= 0; i--) {
       DisplayObject target = newTargetList[i];
       target.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OVER, false)
           .._localPoint = target.globalToLocal(stagePoint)
           .._stagePoint = stagePoint
           .._buttonDown = mouseButton.buttonDown);
     }

     if (newTarget != null) {
       newTarget.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OVER, true)
           .._localPoint = newTarget.globalToLocal(stagePoint)
           .._stagePoint = stagePoint
           .._buttonDown = mouseButton.buttonDown);
     }

     _mouseTarget = newTarget;
   }

   //-----------------------------------------------------------------

   String mouseEventType = null;
   bool isClick = false;
   bool isDoubleClick = false;

   if (event.type == "mousedown") {
     _canvas.focus();
     mouseEventType = mouseButton.mouseDownEventType;

     if (target != mouseButton.target || time > mouseButton.clickTime + 500) {
       mouseButton.clickCount = 0;
     }

     mouseButton.buttonDown = true;
     mouseButton.target = target;
     mouseButton.clickTime = time;
     mouseButton.clickCount++;
   }

   if (event.type == "mouseup") {
     mouseEventType = mouseButton.mouseUpEventType;
     mouseButton.buttonDown = false;
     isClick = (mouseButton.target == target);
     isDoubleClick = isClick
         && mouseButton.clickCount.isEven
         && (time < mouseButton.clickTime + 500);
   }

   if (event.type == "mousemove") {
     mouseEventType = MouseEvent.MOUSE_MOVE;
   }

   if (event.type == "contextmenu") {
     mouseEventType = MouseEvent.CONTEXT_MENU;
   }

   //-----------------------------------------------------------------

   if (mouseEventType != null && target != null) {

     localPoint = target.globalToLocal(stagePoint);

     target.dispatchEvent(new MouseEvent(mouseEventType, true)
         .._localPoint = localPoint
         .._stagePoint = stagePoint
         .._buttonDown = mouseButton.buttonDown
         .._clickCount = mouseButton.clickCount);

     if (isClick) {

       if (isDoubleClick && target.doubleClickEnabled) {

         target.dispatchEvent(new MouseEvent(mouseButton.mouseDoubleClickEventType, true)
             .._localPoint = localPoint
             .._stagePoint = stagePoint
             .._buttonDown = mouseButton.buttonDown);

       } else {

         target.dispatchEvent(new MouseEvent(mouseButton.mouseClickEventType, true)
             .._localPoint = localPoint
             .._stagePoint = stagePoint
             .._buttonDown = mouseButton.buttonDown);
       }
     }
   }
 }

 //-------------------------------------------------------------------------------------------------

 _onMouseWheelEvent(html.WheelEvent event) {

   var stagePoint = _clientTransformation._transformHtmlPoint(event.client);
   var target = hitTestInput(stagePoint.x, stagePoint.y) as InteractiveObject;

   if (target != null) {
     var mouseEvent = new MouseEvent(MouseEvent.MOUSE_WHEEL, true)
         .._localPoint = target.globalToLocal(stagePoint)
         .._stagePoint = stagePoint
         .._deltaX = event.deltaX
         .._deltaY = event.deltaY;

     target.dispatchEvent(mouseEvent);
     if (mouseEvent.stopsPropagation) event.preventDefault();
   }
 }

 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------

 List<StreamSubscription<html.TouchEvent>> _touchEventSubscriptions = [];

 _onMultitouchInputModeChanged(String inputMode) {

   _touchEventSubscriptions.forEach((s) => s.cancel());

   if (Multitouch.inputMode == MultitouchInputMode.TOUCH_POINT) {
     _touchEventSubscriptions = [
       _canvas.onTouchStart.listen(_onTouchEvent),
       _canvas.onTouchEnd.listen(_onTouchEvent),
       _canvas.onTouchMove.listen(_onTouchEvent),
       _canvas.onTouchEnter.listen(_onTouchEvent),
       _canvas.onTouchLeave.listen(_onTouchEvent),
       _canvas.onTouchCancel.listen(_onTouchEvent)
     ];
   }
 }

 //-------------------------------------------------------------------------------------------------

 _onTouchEvent(html.TouchEvent event) {

   event.preventDefault();

   for(var changedTouch in event.changedTouches) {

     var identifier = changedTouch.identifier;
     var stagePoint = _clientTransformation._transformHtmlPoint(changedTouch.client);
     var target = hitTestInput(stagePoint.x, stagePoint.y) as InteractiveObject;
     var touch = _touches.containsKey(identifier) ? _touches[identifier] : new _Touch(target, _touches.length == 0);

     //-----------------------------------------------------------------

     if (touch.target != null && touch.target != target) {

       touch.target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OUT, true)
         .._localPoint = (touch.target.stage != null)
             ? touch.target.globalToLocal(stagePoint) : new Point.zero()
         .._stagePoint = stagePoint
         .._touchPointID = touch.touchPointID
         .._isPrimaryTouchPoint = touch.primaryTouchPoint);

       touch.target = null;
     }

     if (target != null && target != touch.target) {

       target.dispatchEvent(new TouchEvent(TouchEvent.TOUCH_OVER, true)
         .._localPoint = target.globalToLocal(stagePoint)
         .._stagePoint = stagePoint
         .._touchPointID = touch.touchPointID
         .._isPrimaryTouchPoint = touch.primaryTouchPoint);

       touch.target = target;
     }

     //-----------------------------------------------------------------

     String touchEventType = null;

     if (event.type == "touchstart") {
       _canvas.focus();
       _touches[identifier] = touch;
       touchEventType = TouchEvent.TOUCH_BEGIN;
     }

     if (event.type == "touchend") {
       _touches.remove(identifier);
       touchEventType = TouchEvent.TOUCH_END;
     }

     if (event.type == "touchcancel") {
       _touches.remove(identifier);
       touchEventType = TouchEvent.TOUCH_CANCEL;
     }

     if (event.type == "touchmove") {
       touchEventType = TouchEvent.TOUCH_MOVE;
     }

     if (touchEventType != null && target != null) {

       target.dispatchEvent(new TouchEvent(touchEventType, true)
         .._localPoint = target.globalToLocal(stagePoint)
         .._stagePoint = stagePoint
         .._touchPointID = touch.touchPointID
         .._isPrimaryTouchPoint = touch.primaryTouchPoint);
     }
   }
 }

 //-------------------------------------------------------------------------------------------------
 //-------------------------------------------------------------------------------------------------

 _onKeyEvent(html.KeyboardEvent event) {

   if (event.keyCode == 8) event.preventDefault();
   if (_focus == null) return;

   if (event.type == "keypress") {

     var charCode = event.charCode;
     var keyCode = event.keyCode;
     if (keyCode == 13) charCode = 13;
     if (charCode == 0) return;

     _focus.dispatchEvent(new TextEvent(TextEvent.TEXT_INPUT, true)
         .._text = new String.fromCharCodes([charCode]));

   } else {

     var keyLocation = KeyLocation.STANDARD;
     var keyboardEventType = "";

     if (event.type == "keyup") keyboardEventType = KeyboardEvent.KEY_UP;
     if (event.type == "keydown") keyboardEventType = KeyboardEvent.KEY_DOWN;
     if (event.keyLocation == html.KeyLocation.LEFT) keyLocation = KeyLocation.LEFT;
     if (event.keyLocation == html.KeyLocation.RIGHT) keyLocation = KeyLocation.RIGHT;
     if (event.keyLocation == html.KeyLocation.NUMPAD) keyLocation = KeyLocation.NUM_PAD;
     if (event.keyLocation == html.KeyLocation.JOYSTICK) keyLocation = KeyLocation.D_PAD;
     if (event.keyLocation == html.KeyLocation.MOBILE) keyLocation = KeyLocation.D_PAD;

     var keyboardEvent = new KeyboardEvent(keyboardEventType, true)
         .._altKey = event.altKey
         .._ctrlKey = event.ctrlKey
         .._shiftKey = event.shiftKey
         .._charCode = event.charCode
         .._keyCode = event.keyCode
         .._keyLocation = keyLocation;

     _focus.dispatchEvent(keyboardEvent);

     if (keyboardEvent.stopsPropagation) event.preventDefault();
   }
 }

}

Extends

EventDispatcher > DisplayObject > InteractiveObject > DisplayObjectContainer > Stage

Static Properties

bool autoHiDpi #

static bool autoHiDpi = _autoHiDpi

final num devicePixelRatio #

static num get devicePixelRatio => _devicePixelRatio;

final bool isMobile #

static bool get isMobile => _isMobile;

const EventStreamProvider<Event> resizeEvent #

static const EventStreamProvider<Event> resizeEvent = const EventStreamProvider<Event>(Event.RESIZE)

Constructors

new Stage(CanvasElement canvas, {int width, int height, bool webGL: false, int frameRate: 30, int color: Color.White}) #

Creates a new Object instance.

Object instances have no meaningful state, and are only useful through their identity. An Object instance is equal to itself only.

docs inherited from Object
Stage(CanvasElement canvas, {int width, int height,
 bool webGL: false, int frameRate: 30, int color: Color.White}) {

 if (canvas is! CanvasElement) {
   throw new ArgumentError("The canvas argument is not a CanvasElement");
 }

 _canvas = canvas;

 if (canvas.tabIndex == -1) canvas.tabIndex = 0;
 if (canvas.style.outline == "") canvas.style.outline = "none";

 _sourceWidth = _ensureInt((width != null) ? width : canvas.width);
 _sourceHeight = _ensureInt((width != null) ? height : canvas.height);
 _frameRate = _ensureInt((frameRate != null) ? frameRate : 30);

 _renderContext = webGL && gl.RenderingContext.supported
     ? new RenderContextWebGL(canvas, color)
     : new RenderContextCanvas(canvas, color);

 _renderState = new RenderState(_renderContext);
 _updateCanvasSize();

 print("StageXL render engine : ${_renderContext.renderEngine}");

 canvas.onKeyDown.listen(_onKeyEvent);
 canvas.onKeyUp.listen(_onKeyEvent);
 canvas.onKeyPress.listen(_onKeyEvent);
 canvas.onMouseDown.listen(_onMouseEvent);
 canvas.onMouseUp.listen(_onMouseEvent);
 canvas.onMouseMove.listen(_onMouseEvent);
 canvas.onMouseOut.listen(_onMouseEvent);
 canvas.onContextMenu.listen(_onMouseEvent);
 canvas.onMouseWheel.listen(_onMouseWheelEvent);

 Mouse._onMouseCursorChanged.listen(_onMouseCursorChanged);
 Multitouch._onInputModeChanged.listen(_onMultitouchInputModeChanged);

 _onMultitouchInputModeChanged(null);
}

Properties

String align #

Gets and sets the alignment of this Stage inside of the Canvas element. You can choose between nine different align modes defined in StageAlign.

String get align => _stageAlign;
set align(String value) {
 _stageAlign = value;
 _updateCanvasSize();
}

num get alpha #

inherited from DisplayObject
num get alpha => _alpha;

dynamic set alpha(num value) #

set alpha(num value) { _throwStageException(); }

final bool cached #

inherited from DisplayObject
bool get cached => _cacheTexture != null;

String compositeOperation #

inherited from DisplayObject
String get compositeOperation => _compositeOperation;
set compositeOperation(String value) {
 _compositeOperation = value;
}

final Rectangle contentRectangle #

Gets the available content area on the stage. The value of this rectangle changes with the scaleMode and the alignment of the stage, as well as the size of the underlying Canvas element.

Rectangle get contentRectangle => _contentRectangle.clone();

bool doubleClickEnabled #

inherited from InteractiveObject
bool doubleClickEnabled = false

List<BitmapFilter> filters #

inherited from DisplayObject
List<BitmapFilter> get filters {
 if (_filters == null) _filters = new List<BitmapFilter>();
 return _filters;
}
set filters(List<BitmapFilter> value) {
 _filters = value;
}

InteractiveObject focus #

Gets and sets the InteractiveObject (a DisplayObject which can receive user input like mouse, touch or keyboard).

InteractiveObject get focus => _focus;
set focus(InteractiveObject value) {
 _focus = value;
}

int frameRate #

Gets and sets the default frame rate for MovieClips. This value has no impact on the frame rate of the Stage itself.

int get frameRate => _frameRate;
set frameRate(int value) {
 _frameRate = value;
}

num get height #

inherited from DisplayObject
num get height => getBoundsTransformed(this.transformationMatrix).height;

dynamic set height(num value) #

set height(num value) { _throwStageException(); }

final Juggler juggler #

Gets the Juggler of this Stage. The Juggler is driven by the RenderLoop where this Stage is added to. If this Stage is not added to a RenderLoop, the Juggler will not advance in time.

Juggler get juggler => _juggler;

Mask mask #

inherited from DisplayObject
Mask get mask => _mask;
set mask(Mask value) {
 _mask = value;
}

bool mouseChildren #

inherited from DisplayObjectContainer
bool get mouseChildren => _mouseChildren;
void set mouseChildren(bool value) { _mouseChildren = value; }

bool mouseEnabled #

inherited from InteractiveObject
bool mouseEnabled = true

final Point mousePosition #

Gets the last known mouse position in Stage coordinates.

Point get mousePosition => _mousePosition;

final num mouseX #

inherited from DisplayObject
num get mouseX {
 var mp = this.mousePosition;
 return (mp != null) ? mp.x : 0.0;
}

final num mouseY #

inherited from DisplayObject
num get mouseY {
 var mp = this.mousePosition;
 return (mp != null) ? mp.y : 0.0;
}

String name #

inherited from DisplayObject
String get name => _name;
set name(String value) {
 _name = value;
}

final int numChildren #

inherited from DisplayObjectContainer
int get numChildren => _children.length;

bool off #

inherited from DisplayObject
bool get off => _off;
set off(bool value) {
 if (value is bool) _off = value;
}

final EventStream<Event> onAdded #

inherited from DisplayObject
EventStream<Event> get onAdded => DisplayObject.addedEvent.forTarget(this);

final EventStream<Event> onAddedToStage #

inherited from DisplayObject
EventStream<Event> get onAddedToStage => DisplayObject.addedToStageEvent.forTarget(this);

final EventStream<EnterFrameEvent> onEnterFrame #

inherited from DisplayObject
EventStream<EnterFrameEvent> get onEnterFrame => DisplayObject.enterFrameEvent.forTarget(this);

final EventStream<ExitFrameEvent> onExitFrame #

inherited from DisplayObject
EventStream<ExitFrameEvent> get onExitFrame => DisplayObject.exitFrameEvent.forTarget(this);

final EventStream<KeyboardEvent> onKeyDown #

inherited from InteractiveObject
EventStream<KeyboardEvent> get onKeyDown => InteractiveObject.keyDownEvent.forTarget(this);

final EventStream<KeyboardEvent> onKeyUp #

inherited from InteractiveObject
EventStream<KeyboardEvent> get onKeyUp => InteractiveObject.keyUpEvent.forTarget(this);

final EventStream<MouseEvent> onMouseClick #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseClick => InteractiveObject.mouseClickEvent.forTarget(this);

final EventStream<MouseEvent> onMouseContextMenu #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseContextMenu => InteractiveObject.mouseContextMenu.forTarget(this);

final EventStream<MouseEvent> onMouseDoubleClick #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseDoubleClick => InteractiveObject.mouseDoubleClickEvent.forTarget(this);

final EventStream<MouseEvent> onMouseDown #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseDown => InteractiveObject.mouseDownEvent.forTarget(this);

final EventStream<MouseEvent> onMouseMiddleClick #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseMiddleClick => InteractiveObject.mouseMiddleClickEvent.forTarget(this);

final EventStream<MouseEvent> onMouseMiddleDown #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseMiddleDown => InteractiveObject.mouseMiddleDownEvent.forTarget(this);

final EventStream<MouseEvent> onMouseMiddleUp #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseMiddleUp => InteractiveObject.mouseMiddleUpEvent.forTarget(this);

final EventStream<MouseEvent> onMouseMove #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseMove => InteractiveObject.mouseMoveEvent.forTarget(this);

final EventStream<MouseEvent> onMouseOut #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseOut => InteractiveObject.mouseOutEvent.forTarget(this);

final EventStream<MouseEvent> onMouseOver #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseOver => InteractiveObject.mouseOverEvent.forTarget(this);

final EventStream<MouseEvent> onMouseRightClick #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseRightClick => InteractiveObject.mouseRightClickEvent.forTarget(this);

final EventStream<MouseEvent> onMouseRightDown #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseRightDown => InteractiveObject.mouseRightDownEvent.forTarget(this);

final EventStream<MouseEvent> onMouseRightUp #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseRightUp => InteractiveObject.mouseRightUpEvent.forTarget(this);

final EventStream<MouseEvent> onMouseRollOut #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseRollOut => InteractiveObject.mouseRollOutEvent.forTarget(this);

final EventStream<MouseEvent> onMouseRollOver #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseRollOver => InteractiveObject.mouseRollOverEvent.forTarget(this);

final EventStream<MouseEvent> onMouseUp #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseUp => InteractiveObject.mouseUpEvent.forTarget(this);

final EventStream<MouseEvent> onMouseWheel #

inherited from InteractiveObject
EventStream<MouseEvent> get onMouseWheel => InteractiveObject.mouseWheelEvent.forTarget(this);

final EventStream<Event> onRemoved #

inherited from DisplayObject
EventStream<Event> get onRemoved => DisplayObject.removedEvent.forTarget(this);

final EventStream<Event> onRemovedFromStage #

inherited from DisplayObject
EventStream<Event> get onRemovedFromStage => DisplayObject.removedFromStageEvent.forTarget(this);

final EventStream<RenderEvent> onRender #

inherited from DisplayObject
EventStream<RenderEvent> get onRender => DisplayObject.renderEvent.forTarget(this);

final EventStream<Event> onResize #

EventStream<Event> get onResize => Stage.resizeEvent.forTarget(this);

final EventStream<TextEvent> onTextInput #

inherited from InteractiveObject
EventStream<TextEvent> get onTextInput => InteractiveObject.textInputEvent.forTarget(this);

final EventStream<TouchEvent> onTouchBegin #

inherited from InteractiveObject
EventStream<TouchEvent> get onTouchBegin => InteractiveObject.touchBeginEvent.forTarget(this);

final EventStream<TouchEvent> onTouchCancel #

inherited from InteractiveObject
EventStream<TouchEvent> get onTouchCancel => InteractiveObject.touchCancelEvent.forTarget(this);

final EventStream<TouchEvent> onTouchEnd #

inherited from InteractiveObject
EventStream<TouchEvent> get onTouchEnd => InteractiveObject.touchEndEvent.forTarget(this);

final EventStream<TouchEvent> onTouchMove #

inherited from InteractiveObject
EventStream<TouchEvent> get onTouchMove => InteractiveObject.touchMoveEvent.forTarget(this);

final EventStream<TouchEvent> onTouchOut #

inherited from InteractiveObject
EventStream<TouchEvent> get onTouchOut => InteractiveObject.touchOutEvent.forTarget(this);

final EventStream<TouchEvent> onTouchOver #

inherited from InteractiveObject
EventStream<TouchEvent> get onTouchOver => InteractiveObject.touchOverEvent.forTarget(this);

final DisplayObjectContainer parent #

inherited from DisplayObject
DisplayObjectContainer get parent => _parent;

num get pivotX #

inherited from DisplayObject
num get pivotX => _pivotX;

dynamic set pivotX(num value) #

set pivotX(num value) { _throwStageException(); }

num get pivotY #

inherited from DisplayObject
num get pivotY => _pivotY;

dynamic set pivotY(num value) #

set pivotY(num value) { _throwStageException(); }

final String renderEngine #

Gets the underlying render engine used to draw the pixels to the screen. The returned string is defined in RenderEngine and is either "WebGL" or "Canvas2D".

String get renderEngine => _renderContext.renderEngine;

final RenderLoop renderLoop #

Gets the RenderLoop where this Stage was added to, or NULL in case this Stage is not added to a RenderLoop.

RenderLoop get renderLoop => _renderLoop;

String renderMode #

Gets and sets the render mode of this Stage. You can choose between three different modes defined in StageRenderMode.

String get renderMode => _stageRenderMode;
set renderMode(String value) {
 _stageRenderMode = value;
}

final DisplayObject root #

inherited from DisplayObject
DisplayObject get root {

 DisplayObject currentObject = this;

 while (currentObject._parent != null)
   currentObject = currentObject._parent;

 return currentObject;
}

num get rotation #

inherited from DisplayObject
num get rotation => _rotation;

dynamic set rotation(num value) #

set rotation(num value) { _throwStageException(); }

String scaleMode #

Gets and sets the scale mode of this Stage. You can choose between four dfferent modes defined in StageScaleMode.

String get scaleMode => _stageScaleMode;
set scaleMode(String value) {
 _stageScaleMode = value;
 _updateCanvasSize();
}

num get scaleX #

inherited from DisplayObject
num get scaleX => _scaleX;

dynamic set scaleX(num value) #

set scaleX(num value) { _throwStageException(); }

num get scaleY #

inherited from DisplayObject
num get scaleY => _scaleY;

dynamic set scaleY(num value) #

set scaleY(num value) { _throwStageException(); }

Shadow shadow #

inherited from DisplayObject
Shadow get shadow => _shadow;
set shadow(Shadow value) {
 _shadow = value;
}

num get skewX #

inherited from DisplayObject
num get skewX => _skewX;

dynamic set skewX(num value) #

set skewX(num value) { _throwStageException(); }

num get skewY #

inherited from DisplayObject
num get skewY => _skewY;

dynamic set skewY(num value) #

set skewY(num value) { _throwStageException(); }

final int sourceHeight #

Gets the original source height of the Stage as defined in the constructor.

int get sourceHeight => _sourceHeight;

final int sourceWidth #

Gets the original source width of the Stage as defined in the constructor.

int get sourceWidth => _sourceWidth;

final Stage stage #

inherited from DisplayObject
Stage get stage {

 DisplayObject root = this.root;
 return (root is Stage) ? root : null;
}

final int stageHeight #

Gets the current height of the Stage in pixels on the screen.

int get stageHeight => _canvasHeight;

final int stageWidth #

Gets the current width of the Stage in pixels on the screen.

int get stageWidth => _canvasWidth;

bool tabChildren #

inherited from DisplayObjectContainer
bool get tabChildren => _tabChildren;
void set tabChildren(bool value) { _tabChildren = value; }

bool tabEnabled #

inherited from InteractiveObject
bool tabEnabled = true

int tabIndex #

inherited from InteractiveObject
int tabIndex = 0

final Matrix transformationMatrix #

inherited from DisplayObject
Matrix get transformationMatrix {
 /*
 _transformationMatrix.identity();
 _transformationMatrix.translate(-_pivotX, -_pivotY);
 _transformationMatrix.scale(_scaleX, _scaleY);
 _transformationMatrix.rotate(_rotation);
 _transformationMatrix.translate(_x, _y);
 */

 if (_transformationMatrixRefresh) {

   _transformationMatrixRefresh = false;

   num skewXrotation =  _skewX + _rotation;
   num skewYrotation =  _skewY + _rotation;
   num scaleX = _scaleX;
   num scaleY = _scaleY;
   num pivotX = _pivotX;
   num pivotY = _pivotY;

   // ToDo: https://bugzilla.mozilla.org/show_bug.cgi?id=661452
   if (scaleX > -0.0001 && scaleX < 0.0001) scaleX = (scaleX >= 0) ? 0.0001 : -0.0001;
   if (scaleY > -0.0001 && scaleY < 0.0001) scaleY = (scaleY >= 0) ? 0.0001 : -0.0001;

   if (skewXrotation == 0.0 && skewYrotation == 0.0) {

     _transformationMatrix.setTo(scaleX, 0.0, 0.0, scaleY, _x - pivotX * scaleX, _y - pivotY * scaleY);

   } else {

     num a, b, c, d;
     num cosX = cos(skewXrotation);
     num sinX = sin(skewXrotation);

     if (skewXrotation == skewYrotation) {
       a =   scaleX * cosX;
       b =   scaleX * sinX;
       c = - scaleY * sinX;
       d =   scaleY * cosX;
     } else {
       a =   scaleX * cos(skewYrotation);
       b =   scaleX * sin(skewYrotation);
       c = - scaleY * sinX;
       d =   scaleY * cosX;
     }

     num tx =  _x - (pivotX * a + pivotY * c);
     num ty =  _y - (pivotX * b + pivotY * d);

     _transformationMatrix.setTo(a, b, c, d, tx, ty);
   }
 }

 return _transformationMatrix;
}

var userData #

inherited from DisplayObject

Gets or sets user-defined data associated with the display object.

dynamic userData = null

bool visible #

inherited from DisplayObject
bool get visible => _visible;
set visible(bool value) {
 if (value is bool) _visible = value;
}

num get width #

inherited from DisplayObject
num get width => getBoundsTransformed(this.transformationMatrix).width;

dynamic set width(num value) #

set width(num value) { _throwStageException(); }

num get x #

inherited from DisplayObject
num get x => _x;

dynamic set x(num value) #

set x(num value) { _throwStageException(); }

num get y #

inherited from DisplayObject
num get y => _y;

dynamic set y(num value) #

set y(num value) { _throwStageException(); }

Methods

void addChild(DisplayObject child) #

inherited from DisplayObjectContainer
void addChild(DisplayObject child) {
 addChildAt(child, _children.length);
}

void addChildAt(DisplayObject child, int index) #

inherited from DisplayObjectContainer
void addChildAt(DisplayObject child, int index) {

 if (index < 0 || index > _children.length) {
   throw new ArgumentError("Error #2006: The supplied index is out of bounds.");
 }

 if (child == this) {
   throw new ArgumentError("Error #2024: An object cannot be added as a child of itself.");
 }

 if (child.parent == this) {

   _children.remove(child);
   if (index > _children.length) index -= 1;
   _children.insert(index, child);

 } else {

   child.removeFromParent();

   for(var ancestor = this; ancestor != null; ancestor = ancestor.parent) {
     if (ancestor == child) {
       throw new ArgumentError("Error #2150: An object cannot be added as "
           "a child to one of it's children (or children's children, etc.).");
     }
   }

   _children.insert(index, child);

   child._parent = this;
   child.dispatchEvent(new Event(Event.ADDED, true));

   if (this.stage != null) {
     _dispatchEventDescendants(child, new Event(Event.ADDED_TO_STAGE));
   }
 }
}

StreamSubscription<Event> addEventListener(String eventType, EventListener eventListener, {bool useCapture: false, int priority: 0}) #

inherited from EventDispatcher
StreamSubscription<Event> addEventListener(String eventType, EventListener eventListener, {
 bool useCapture: false, int priority: 0 }) {

 return this.on(eventType)._subscribe(eventListener, useCapture, priority);
}

void addTo(DisplayObjectContainer parent) #

inherited from DisplayObject
void addTo(DisplayObjectContainer parent) {
 parent.addChild(this);
}

void applyCache(int x, int y, int width, int height, {bool debugBorder: false}) #

inherited from DisplayObject
void applyCache(int x, int y, int width, int height, {bool debugBorder: false}) {

 var pixelRatio = Stage.autoHiDpi ? _devicePixelRatio : 1.0;

 if (_cacheTexture == null) {
   _cacheTexture = new RenderTexture(width, height, true, Color.Transparent, pixelRatio);
 } else {
   _cacheTexture.resize(width, height);
 }

 _cacheRectangle = new Rectangle(x, y, width, height);
 _cacheDebugBorder = debugBorder;

 refreshCache();
}

bool contains(DisplayObject child) #

inherited from DisplayObjectContainer
bool contains(DisplayObject child) {

 while(child != null) {
   if (child == this) return true;
   child = child.parent;
 }
 return false;
}

void dispatchEvent(Event event) #

inherited from DisplayObject
void dispatchEvent(Event event) {

 List<DisplayObject> ancestors = null;

 if (event.captures || event.bubbles) {
   for(DisplayObject ancestor = parent; ancestor != null; ancestor = ancestor.parent) {
     if(ancestor._hasPropagationEventListeners(event)) {
       if (ancestors == null) ancestors = [];
       ancestors.add(ancestor);
     }
   }
 }

 if (ancestors != null && event.captures) {
   for(int i = ancestors.length - 1 ; i >= 0; i--) {
     ancestors[i]._dispatchEventInternal(event, this, EventPhase.CAPTURING_PHASE);
     if (event.stopsPropagation) return;
   }
 }

 _dispatchEventInternal(event, this, EventPhase.AT_TARGET);
 if (event.stopsPropagation) return;

 if (ancestors != null && event.bubbles) {
   for(int i = 0; i < ancestors.length; i++) {
     ancestors[i]._dispatchEventInternal(event, this, EventPhase.BUBBLING_PHASE);
     if (event.stopsPropagation) return;
   }
 }
}

Rectangle getBounds(DisplayObject targetSpace) #

inherited from DisplayObject
Rectangle getBounds(DisplayObject targetSpace) {

 Rectangle returnRectangle = new Rectangle.zero();
 Matrix matrix = (targetSpace == null) ? transformationMatrix : transformationMatrixTo(targetSpace);

 return (matrix != null) ? getBoundsTransformed(matrix, returnRectangle) : returnRectangle;
}

Rectangle getBoundsTransformed(Matrix matrix, [Rectangle returnRectangle]) #

inherited from DisplayObjectContainer
Rectangle getBoundsTransformed(Matrix matrix, [Rectangle returnRectangle]) {

 if (returnRectangle == null) {
   returnRectangle = new Rectangle.zero();
 }

 if (_children.length == 0) {
   return super.getBoundsTransformed(matrix, returnRectangle);
 }

 num left = double.INFINITY;
 num top = double.INFINITY;
 num right = double.NEGATIVE_INFINITY;
 num bottom = double.NEGATIVE_INFINITY;

 int childrenLength = _children.length;

 for (int i = 0; i < _children.length; i++) {

   DisplayObject child = _children[i];

   _tmpMatrix.copyFromAndConcat(child.transformationMatrix, matrix);
   Rectangle rectangle = child.getBoundsTransformed(_tmpMatrix, returnRectangle);

   if (rectangle.left < left) left = rectangle.left;
   if (rectangle.top < top ) top = rectangle.top;
   if (rectangle.right > right) right = rectangle.right;
   if (rectangle.bottom > bottom) bottom = rectangle.bottom;
 }

 returnRectangle.x = left;
 returnRectangle.y = top;
 returnRectangle.width = right - left;
 returnRectangle.height = bottom - top;

 return returnRectangle;
}

dynamic getChildAt(int index) #

inherited from DisplayObjectContainer
dynamic getChildAt(int index) {

 if (index < 0 || index >= _children.length) {
   throw new ArgumentError("Error #2006: The supplied index is out of bounds.");
 }
 return _children[index];
}

dynamic getChildByName(String name) #

inherited from DisplayObjectContainer
dynamic getChildByName(String name) {

 for(int i = 0; i < _children.length; i++) {
   DisplayObject child = _children[i];
   if (child.name == name) return child;
 }
 return null;
}

int getChildIndex(DisplayObject child) #

inherited from DisplayObjectContainer
int getChildIndex(DisplayObject child) {

 return _children.indexOf(child);
}

Point globalToLocal(Point globalPoint) #

inherited from DisplayObject
Point globalToLocal(Point globalPoint) {

 _tmpMatrix.identity();

 for(var current = this; current != null; current = current._parent) {
   _tmpMatrix.concat(current.transformationMatrix);
 }

 _tmpMatrix.invert();

 return _tmpMatrix.transformPoint(globalPoint);
}

bool hasEventListener(String eventType) #

inherited from EventDispatcher
bool hasEventListener(String eventType) {

 var eventStreams = _eventStreams;
 if (eventStreams == null) return false;
 var eventStream = eventStreams[eventType];
 if (eventStream == null) return false;

 return eventStream.hasSubscriptions;
}

DisplayObject hitTestInput(num localX, num localY) #

inherited from DisplayObjectContainer
DisplayObject hitTestInput(num localX, num localY) {

 localX = localX.toDouble();
 localY = localY.toDouble();

 DisplayObject hit = null;

 for (int i = _children.length - 1; i >= 0; i--) {

   var child = _children[i];
   var mask = child.mask;
   var matrix = child.transformationMatrix;

   if (child.visible && child.off == false) {

     num deltaX = localX - matrix.tx;
     num deltaY = localY - matrix.ty;
     num childX = (matrix.d * deltaX - matrix.c * deltaY) / matrix.det;
     num childY = (matrix.a * deltaY - matrix.b * deltaX) / matrix.det;
     num maskX = 0.0;
     num maskY = 0.0;

     if (mask != null) {
       if (mask.targetSpace == null) {
         maskX = childX;
         maskY = childY;
       } else if (identical(mask.targetSpace, child)) {
         maskX = childX;
         maskY = childY;
       } else if (identical(mask.targetSpace, this)) {
         maskX = localX;
         maskY = localY;
       } else {
         matrix = this.transformationMatrixTo(mask.targetSpace);
         matrix = (matrix != null) ? matrix : _identityMatrix;
         maskX = localX * matrix.a + localY * matrix.c + matrix.tx;
         maskY = localX * matrix.b + localY * matrix.d + matrix.ty;
       }
       if (mask.hitTest(maskX, maskY) == false) continue;
     }

     var displayObject = child.hitTestInput(childX, childY);
     if (displayObject == null) continue;

     if (displayObject is InteractiveObject && displayObject.mouseEnabled) {
       return _mouseChildren ? displayObject : this;
     }

     hit = this;
   }
 }

 return hit;
}

bool hitTestObject(DisplayObject other) #

inherited from DisplayObject
bool hitTestObject(DisplayObject other) {

 var stage1 = this.stage;
 var stage2 = other.stage;

 if (stage1 == null || stage2 == null || stage1 != stage2) return false;

 var rect1 = this.getBounds(stage1);
 var rect2 = other.getBounds(stage2);

 return rect1.intersects(rect2);
}

bool hitTestPoint(num x, num y, [bool shapeFlag = false]) #

inherited from DisplayObject
bool hitTestPoint(num x, num y, [bool shapeFlag = false]) {

 var stage = this.stage;
 if (stage == null) return false;

 if (shapeFlag) {
   var matrix = stage.transformationMatrixTo(this);
   if (matrix == null) return false;

   var stagePoint = new Point(x, y);
   var localPoint = matrix.transformPoint(stagePoint);

   return this.hitTestInput(localPoint.x, localPoint.y) != null;

 } else {

   var rect = this.getBounds(stage);
   return rect.contains(x, y);
 }
}

dynamic invalidate() #

Calling this method will cause an RenderEvent to be fired right before the next frame will be rendered by the render loop. To receive the render event attach a listener to DisplayObject.onRender.

invalidate() {
 if (_renderLoop != null) {
   _renderLoop.invalidate();
 }
}

Point localToGlobal(Point localPoint) #

inherited from DisplayObject
Point localToGlobal(Point localPoint) {

 _tmpMatrix.identity();

 for(var current = this; current != null; current = current._parent) {
   _tmpMatrix.concat(current.transformationMatrix);
 }

 return _tmpMatrix.transformPoint(localPoint);
}

dynamic materialize(num currentTime, num deltaTime) #

This method is called by the RenderLoop where this Stage is added to. If this Stage is not added to a RenderLoop you could call this method on your own and therefore get full control of the rendering of this Stage.

materialize(num currentTime, num deltaTime) {

 if (_stageRenderMode == StageRenderMode.AUTO || _stageRenderMode == StageRenderMode.ONCE) {

   _updateCanvasSize();

   _renderState.reset(_stageTransformation, currentTime, deltaTime);
   render(_renderState);
   _renderState.flush();

   if (_stageRenderMode == StageRenderMode.ONCE)
     _stageRenderMode = StageRenderMode.STOP;
 }
}

EventStream<Event> on(String eventType) #

inherited from EventDispatcher
EventStream<Event> on(String eventType) {

 var eventStreams = _eventStreams;
 if (eventStreams == null) {
   eventStreams = new Map<String, EventStream>();
   _eventStreams = eventStreams;
 }

 var eventStream = eventStreams[eventType];
 if (eventStream == null) {
   eventStream = new EventStream._internal(this, eventType);
   eventStreams[eventType] = eventStream;
 }

 return eventStream;
}

void refreshCache() #

inherited from DisplayObject
void refreshCache() {

 if (_cacheTexture == null) return;

 var x = _cacheRectangle.x;
 var y = _cacheRectangle.y;
 var width = _cacheRectangle.width;
 var height = _cacheRectangle.height;
 var canvas = _cacheTexture.canvas;

 var matrix = _cacheTexture.quad.drawMatrix..translate(-x, -y);
 var renderContext = new RenderContextCanvas(canvas, Color.Transparent);
 var renderState = new RenderState(renderContext, matrix);

 renderContext.clear();
 render(renderState);

 if (_filters != null) {
   var cacheBitmapData = new BitmapData.fromRenderTextureQuad(_cacheTexture.quad);
   var bounds = this.getBoundsTransformed(_identityMatrix)..offset(-x, -y);
   for(var filter in _filters) {
     var filterOverlap = filter.overlap;
     var filterBounds = bounds.clone();
     filterBounds.offset(filterOverlap.x, filterOverlap.y);
     filterBounds.inflate(filterOverlap.width, filterOverlap.height);
     filter.apply(cacheBitmapData, filterBounds.align());
   }
 }

 if (_cacheDebugBorder) {
   canvas.context2D
       ..setTransform(1.0, 0.0, 0.0, 1.0, 0.0, 0.0)
       ..lineWidth = 1
       ..lineJoin = "miter"
       ..lineCap = "butt"
       ..strokeStyle = "#FF00FF"
       ..strokeRect(0.5, 0.5, canvas.width - 1, canvas.height - 1);
 }

 _cacheTexture.update();
}

void removeCache() #

inherited from DisplayObject
void removeCache() {
 if (_cacheTexture != null) {
   _cacheTexture.dispose();
   _cacheTexture = null;
 }
}

void removeChild(DisplayObject child) #

inherited from DisplayObjectContainer
void removeChild(DisplayObject child) {

 int childIndex = _children.indexOf(child);
 if (childIndex == -1) {
   throw new ArgumentError(
       "Error #2025: The supplied DisplayObject must be a child of the caller.");
 }

 removeChildAt(childIndex);
}

void removeChildAt(int index) #

inherited from DisplayObjectContainer
void removeChildAt(int index) {

 if (index < 0 || index >= _children.length) {
   throw new ArgumentError("Error #2006: The supplied index is out of bounds.");
 }

 DisplayObject child = _children[index];

 child.dispatchEvent(new Event(Event.REMOVED, true));

 if (this.stage != null) {
   _dispatchEventDescendants(child, new Event(Event.REMOVED_FROM_STAGE));
 }

 child._parent = null;
 _children.removeAt(index);
}

void removeChildren([int beginIndex = 0, int endIndex = 0x7fffffff]) #

inherited from DisplayObjectContainer
void removeChildren([int beginIndex = 0, int endIndex = 0x7fffffff]) {

 var length = _children.length;
 if (length == 0) return;

 if (endIndex == 0x7fffffff) {
   endIndex = length - 1;
 }

 if (beginIndex < 0 || endIndex < 0 || beginIndex >= length || endIndex >= length) {
   throw new ArgumentError("Error #2006: The supplied index is out of bounds.");
 }

 for(int i = beginIndex; i <= endIndex; i++) {
   if (beginIndex >= _children.length) break;
   removeChildAt(beginIndex);
 }
}

void removeEventListener(String eventType, EventListener eventListener, {bool useCapture: false}) #

inherited from EventDispatcher
void removeEventListener(String eventType, EventListener eventListener, {
 bool useCapture: false }) {

 this.on(eventType)._unsubscribe(eventListener, useCapture);
}

void removeEventListeners(String eventType) #

inherited from EventDispatcher
void removeEventListeners(String eventType) {
 this.on(eventType).cancelSubscriptions();
}

void removeFromParent() #

inherited from DisplayObject
void removeFromParent() {
 if (_parent != null)
   _parent.removeChild(this);
}

void render(RenderState renderState) #

inherited from DisplayObjectContainer
void render(RenderState renderState) {

 for(int i = 0; i < _children.length; i++) {
   DisplayObject child = _children[i];
   if (child.visible && child.off == false) {
     renderState.renderDisplayObject(child);
   }
 }
}

void setChildIndex(DisplayObject child, int index) #

inherited from DisplayObjectContainer
void setChildIndex(DisplayObject child, int index) {

 if (index < 0 || index >= _children.length) {
   throw new ArgumentError("Error #2006: The supplied index is out of bounds.");
 }

 int oldIndex = getChildIndex(child);
 if (oldIndex == -1) {
   throw new ArgumentError("Error #2025: The supplied DisplayObject must be a child of the caller.");
 }

 _children.removeAt(oldIndex);
 _children.insert(index, child);
}

void setTransform(num x, num y, [num scaleX, num scaleY, num rotation, num skewX, num skewY, num pivotX, num pivotY]) #

inherited from DisplayObject
void setTransform(num x, num y, [num scaleX, num scaleY, num rotation, num skewX, num skewY, num pivotX, num pivotY]) {
 if (x is num) _x = x;
 if (y is num) _y = y;
 if (scaleX is num) _scaleX = scaleX;
 if (scaleY is num) _scaleY = scaleY;
 if (rotation is num) _rotation = rotation;
 if (skewX is num) _skewX = skewX;
 if (skewY is num) _skewY = skewY;
 if (pivotX is num) _pivotX = pivotX;
 if (pivotY is num) _pivotY = pivotY;
 _transformationMatrixRefresh = true;
}

void sortChildren(Function compareFunction) #

inherited from DisplayObjectContainer
void sortChildren(Function compareFunction) {
 _children.sort(compareFunction);
}

void swapChildren(DisplayObject child1, DisplayObject child2) #

inherited from DisplayObjectContainer
void swapChildren(DisplayObject child1, DisplayObject child2) {

 int index1 = getChildIndex(child1);
 int index2 = getChildIndex(child2);

 if (index1 == -1 || index2 == -1) {
   throw new ArgumentError("Error #2025: The supplied DisplayObject must be a child of the caller.");
 }

 swapChildrenAt(index1, index2);
}

void swapChildrenAt(int index1, int index2) #

inherited from DisplayObjectContainer
void swapChildrenAt(int index1, int index2) {

 DisplayObject child1 = getChildAt(index1);
 DisplayObject child2 = getChildAt(index2);
 _children[index1] = child2;
 _children[index2] = child1;
}

Matrix transformationMatrixTo(DisplayObject targetSpace) #

inherited from DisplayObject
Matrix transformationMatrixTo(DisplayObject targetSpace) {

 if (targetSpace == _parent) {
   return this.transformationMatrix.clone();
 }

 if (targetSpace != null && targetSpace._parent == this) {
   return targetSpace.transformationMatrix.cloneInvert();
 }

 //------------------------------------------------

 Matrix resultMatrix = new Matrix.fromIdentity();
 DisplayObject resultObject = this;

 while(resultObject != targetSpace && resultObject._parent != null) {
   resultMatrix.concat(resultObject.transformationMatrix);
   resultObject = resultObject._parent;
 }

 if (targetSpace == null && resultObject != null) {
   resultMatrix.concat(resultObject.transformationMatrix);
   resultObject = null;
 }

 if (resultObject == targetSpace)
   return resultMatrix;

 //------------------------------------------------

 Matrix targetMatrix = new Matrix.fromIdentity();
 DisplayObject targetObject = targetSpace;

 while(targetObject != this && targetObject._parent != null) {
   targetMatrix.concat(targetObject.transformationMatrix);
   targetObject = targetObject._parent;
 }

 targetMatrix.invert();

 if (targetObject == this) {
   return targetMatrix;
 }

 if (targetObject != resultObject) {
   return null;
 }

 resultMatrix.concat(targetMatrix);

 return resultMatrix;
}