SHARE
TWEET

Starling.as

a guest Mar 23rd, 2020 76 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // =================================================================================================
  2. //
  3. //  Starling Framework
  4. //  Copyright 2012 Gamua OG. All Rights Reserved.
  5. //
  6. //  This program is free software. You can redistribute and/or modify it
  7. //  in accordance with the terms of the accompanying license agreement.
  8. //
  9. // =================================================================================================
  10.  
  11. package starling.core {
  12. import flash.display.Sprite;
  13. import flash.display.Stage3D;
  14. import flash.display.StageAlign;
  15. import flash.display.StageScaleMode;
  16. import flash.display3D.Context3D;
  17. import flash.display3D.Context3DCompareMode;
  18. import flash.display3D.Context3DTriangleFace;
  19. import flash.display3D.Program3D;
  20. import flash.errors.IllegalOperationError;
  21. import flash.events.ErrorEvent;
  22. import flash.events.Event;
  23. import flash.events.KeyboardEvent;
  24. import flash.events.MouseEvent;
  25. import flash.events.TouchEvent;
  26. import flash.geom.Rectangle;
  27. import flash.system.Capabilities;
  28. import flash.text.TextField;
  29. import flash.text.TextFieldAutoSize;
  30. import flash.text.TextFormat;
  31. import flash.text.TextFormatAlign;
  32. import flash.ui.Mouse;
  33. import flash.ui.Multitouch;
  34. import flash.ui.MultitouchInputMode;
  35. import flash.utils.ByteArray;
  36. import flash.utils.Dictionary;
  37. import flash.utils.getTimer;
  38. import flash.utils.setTimeout;
  39.  
  40. import starling.animation.Juggler;
  41. import starling.display.DisplayObject;
  42. import starling.display.Stage;
  43. import starling.events.EventDispatcher;
  44. import starling.events.ResizeEvent;
  45. import starling.events.TouchPhase;
  46. import starling.events.TouchProcessor;
  47. import starling.utils.HAlign;
  48. import starling.utils.VAlign;
  49.  
  50. /** Dispatched when a new render context is created. */
  51. [Event(name="context3DCreate", type="starling.events.Event")]
  52.  
  53. /** Dispatched when the root class has been created. */
  54. [Event(name="rootCreated", type="starling.events.Event")]
  55.  
  56. /** The Starling class represents the core of the Starling framework.
  57.  *
  58.  *  <p>The Starling framework makes it possible to create 2D applications and games that make
  59.  *  use of the Stage3D architecture introduced in Flash Player 11. It implements a display tree
  60.  *  system that is very similar to that of conventional Flash, while leveraging modern GPUs
  61.  *  to speed up rendering.</p>
  62.  *
  63.  *  <p>The Starling class represents the link between the conventional Flash display tree and
  64.  *  the Starling display tree. To create a Starling-powered application, you have to create
  65.  *  an instance of the Starling class:</p>
  66.  *
  67.  *  <pre>var starling:Starling = new Starling(Game, stage);</pre>
  68.  *
  69.  *  <p>The first parameter has to be a Starling display object class, e.g. a subclass of
  70.  *  <code>starling.display.Sprite</code>. In the sample above, the class "Game" is the
  71.  *  application root. An instance of "Game" will be created as soon as Starling is initialized.
  72.  *  The second parameter is the conventional (Flash) stage object. Per default, Starling will
  73.  *  display its contents directly below the stage.</p>
  74.  *
  75.  *  <p>It is recommended to store the Starling instance as a member variable, to make sure
  76.  *  that the Garbage Collector does not destroy it. After creating the Starling object, you
  77.  *  have to start it up like this:</p>
  78.  *
  79.  *  <pre>starling.start();</pre>
  80.  *
  81.  *  <p>It will now render the contents of the "Game" class in the frame rate that is set up for
  82.  *  the application (as defined in the Flash stage).</p>
  83.  *
  84.  *  <strong>Accessing the Starling object</strong>
  85.  *
  86.  *  <p>From within your application, you can access the current Starling object anytime
  87.  *  through the static method <code>Starling.current</code>. It will return the active Starling
  88.  *  instance (most applications will only have one Starling object, anyway).</p>
  89.  *
  90.  *  <strong>Viewport</strong>
  91.  *
  92.  *  <p>The area the Starling content is rendered into is, per default, the complete size of the
  93.  *  stage. You can, however, use the "viewPort" property to change it. This can be  useful
  94.  *  when you want to render only into a part of the screen, or if the player size changes. For
  95.  *  the latter, you can listen to the RESIZE-event dispatched by the Starling
  96.  *  stage.</p>
  97.  *
  98.  *  <strong>Native overlay</strong>
  99.  *
  100.  *  <p>Sometimes you will want to display native Flash content on top of Starling. That's what the
  101.  *  <code>nativeOverlay</code> property is for. It returns a Flash Sprite lying directly
  102.  *  on top of the Starling content. You can add conventional Flash objects to that overlay.</p>
  103.  *
  104.  *  <p>Beware, though, that conventional Flash content on top of 3D content can lead to
  105.  *  performance penalties on some (mobile) platforms. For that reason, always remove all child
  106.  *  objects from the overlay when you don't need them any longer. Starling will remove the
  107.  *  overlay from the display list when it's empty.</p>
  108.  *
  109.  *  <strong>Multitouch</strong>
  110.  *
  111.  *  <p>Starling supports multitouch input on devices that provide it. During development,
  112.  *  where most of us are working with a conventional mouse and keyboard, Starling can simulate
  113.  *  multitouch events with the help of the "Shift" and "Ctrl" (Mac: "Cmd") keys. Activate
  114.  *  this feature by enabling the <code>simulateMultitouch</code> property.</p>
  115.  *
  116.  *  <strong>Handling a lost render context</strong>
  117.  *
  118.  *  <p>On some operating systems and under certain conditions (e.g. returning from system
  119.  *  sleep), Starling's stage3D render context may be lost. Starling can recover from a lost
  120.  *  context if the class property "handleLostContext" is set to "true". Keep in mind, however,
  121.  *  that this comes at the price of increased memory consumption; Starling will cache textures
  122.  *  in RAM to be able to restore them when the context is lost.</p>
  123.  *
  124.  *  <p>In case you want to react to a context loss, Starling dispatches an event with
  125.  *  the type "Event.CONTEXT3D_CREATE" when the context is restored. You can recreate any
  126.  *  invalid resources in a corresponding event listener.</p>
  127.  *
  128.  *  <strong>Sharing a 3D Context</strong>
  129.  *
  130.  *  <p>Per default, Starling handles the Stage3D context independently. If you want to combine
  131.  *  Starling with another Stage3D engine, however, this may not be what you want. In this case,
  132.  *  you can make use of the <code>shareContext</code> property:</p>
  133.  *
  134.  *  <ol>
  135.  *    <li>Manually create and configure a context3D object that both frameworks can work with
  136.  *        (through <code>stage3D.requestContext3D</code> and
  137.  *        <code>context.configureBackBuffer</code>).</li>
  138.  *    <li>Initialize Starling with the stage3D instance that contains that configured context.
  139.  *        This will automatically enable <code>shareContext</code>.</li>
  140.  *    <li>Call <code>start()</code> on your Starling instance (as usual). This will make
  141.  *        Starling queue input events (keyboard/mouse/touch).</li>
  142.  *    <li>Create a game loop (e.g. using the native <code>ENTER_FRAME</code> event) and let it
  143.  *        call Starling's <code>nextFrame</code> as well as the equivalent method of the other
  144.  *        Stage3D engine. Surround those calls with <code>context.clear()</code> and
  145.  *        <code>context.present()</code>.</li>
  146.  *  </ol>
  147.  *
  148.  *  <p>The Starling wiki contains a <a href="http://goo.gl/BsXzw">tutorial</a> with more
  149.  *  information about this topic.</p>
  150.  *
  151.  */
  152. public class Starling extends EventDispatcher {
  153.     /** The version of the Starling framework. */
  154.     public static const VERSION:String = "1.4.1";
  155.  
  156.     /** The key for the shader programs stored in 'contextData' */
  157.     private static const PROGRAM_DATA_NAME:String = "Starling.programs";
  158.  
  159.     // members
  160.  
  161.     private var mStage3D:Stage3D;
  162.     private var mStage:Stage; // starling.display.stage!
  163.     private var mRootClass:Class;
  164.     private var mRoot:DisplayObject;
  165.     private var mJuggler:Juggler;
  166.     private var mSupport:RenderSupport;
  167.     private var mTouchProcessor:TouchProcessor;
  168.     private var mAntiAliasing:int;
  169.     private var mSimulateMultitouch:Boolean;
  170.     private var mEnableErrorChecking:Boolean;
  171.     private var mLastFrameTimestamp:Number;
  172.     private var mLeftMouseDown:Boolean;
  173.     private var mStatsDisplay:StatsDisplay;
  174.     private var mShareContext:Boolean;
  175.     private var mProfile:String;
  176.     private var mSupportHighResolutions:Boolean;
  177.     private var mContext:Context3D;
  178.     private var mStarted:Boolean;
  179.     private var mRendering:Boolean;
  180.  
  181.     private var mViewPort:Rectangle;
  182.     private var mPreviousViewPort:Rectangle;
  183.     private var mClippedViewPort:Rectangle;
  184.  
  185.     private var mNativeStage:flash.display.Stage;
  186.     private var mNativeOverlay:Sprite;
  187.     private var mNativeStageContentScaleFactor:Number;
  188.  
  189.     private static var sCurrent:Starling;
  190.     private static var sHandleLostContext:Boolean;
  191.     private static var sContextData:Dictionary = new Dictionary(true);
  192.  
  193.     // construction
  194.  
  195.     /** Creates a new Starling instance.
  196.      *  @param rootClass  A subclass of a Starling display object. It will be created as soon as
  197.      *                    initialization is finished and will become the first child of the
  198.      *                    Starling stage.
  199.      *  @param stage      The Flash (2D) stage.
  200.      *  @param viewPort   A rectangle describing the area into which the content will be
  201.      *                    rendered. @default stage size
  202.      *  @param stage3D    The Stage3D object into which the content will be rendered. If it
  203.      *                    already contains a context, <code>sharedContext</code> will be set
  204.      *                    to <code>true</code>. @default the first available Stage3D.
  205.      *  @param renderMode Use this parameter to force "software" rendering.
  206.      *  @param profile    The Context3DProfile that should be requested.
  207.      */
  208.     public function Starling(rootClass:Class, stage:flash.display.Stage, viewPort:Rectangle = null, stage3D:Stage3D = null, renderMode:String = "auto", profile:String = "baselineConstrained") {
  209.         if (stage == null) throw new ArgumentError("Stage must not be null");
  210.         if (rootClass == null) throw new ArgumentError("Root class must not be null");
  211.         if (viewPort == null) viewPort = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
  212.         if (stage3D == null) stage3D = stage.stage3Ds[0];
  213.  
  214.         makeCurrent();
  215.  
  216.         mRootClass = rootClass;
  217.         mViewPort = viewPort;
  218.         mPreviousViewPort = new Rectangle();
  219.         mStage3D = stage3D;
  220.         mStage = new Stage(viewPort.width, viewPort.height, stage.color);
  221.         mNativeOverlay = new Sprite();
  222.         mNativeStage = stage;
  223.         mNativeStage.addChild(mNativeOverlay);
  224.         mNativeStageContentScaleFactor = 1.0;
  225.         mTouchProcessor = new TouchProcessor(mStage);
  226.         mJuggler = new Juggler();
  227.         mAntiAliasing = 0;
  228.         mSimulateMultitouch = false;
  229.         mEnableErrorChecking = false;
  230.         mProfile = profile;
  231.         mSupportHighResolutions = false;
  232.         mLastFrameTimestamp = getTimer() / 1000.0;
  233.         mSupport = new RenderSupport();
  234.  
  235.         // for context data, we actually reference by stage3D, since it survives a context loss
  236.         sContextData[stage3D] = new Dictionary();
  237.         sContextData[stage3D][PROGRAM_DATA_NAME] = new Dictionary();
  238.  
  239.         // all other modes are problematic in Starling, so we force those here
  240.         stage.scaleMode = StageScaleMode.NO_SCALE;
  241.         stage.align = StageAlign.TOP_LEFT;
  242.  
  243.         // register touch/mouse event handlers
  244.         for each (var touchEventType:String in touchEventTypes)
  245.             stage.addEventListener(touchEventType, onTouch, false, 0, true);
  246.  
  247.         // register other event handlers
  248.         stage.addEventListener(Event.ENTER_FRAME, onEnterFrame, false, 0, true);
  249.         stage.addEventListener(KeyboardEvent.KEY_DOWN, onKey, false, 0, true);
  250.         stage.addEventListener(KeyboardEvent.KEY_UP, onKey, false, 0, true);
  251.         stage.addEventListener(Event.RESIZE, onResize, false, 0, true);
  252.         stage.addEventListener(Event.MOUSE_LEAVE, onMouseLeave, false, 0, true);
  253.  
  254.         mStage3D.addEventListener(Event.CONTEXT3D_CREATE, onContextCreated, false, 10, true);
  255.         mStage3D.addEventListener(ErrorEvent.ERROR, onStage3DError, false, 10, true);
  256.  
  257.         if (mStage3D.context3D && mStage3D.context3D.driverInfo != "Disposed") {
  258.             mShareContext = true;
  259.             setTimeout(initialize, 1); // we don't call it right away, because Starling should
  260.             // behave the same way with or without a shared context
  261.         }
  262.         else {
  263.             mShareContext = false;
  264.  
  265.             try {
  266.                 // "Context3DProfile" is only available starting with Flash Player 11.4/AIR 3.4.
  267.                 // to stay compatible with older versions, we check if the parameter is available.
  268.  
  269.                 var requestContext3D:Function = mStage3D.requestContext3D;
  270.                 if (requestContext3D.length == 1) requestContext3D(renderMode);
  271.                 else requestContext3D(renderMode, profile);
  272.             }
  273.             catch (e:Error) {
  274.                 showFatalError("Context3D error: " + e.message);
  275.             }
  276.         }
  277.     }
  278.  
  279.     /** Disposes all children of the stage and the render context; removes all registered
  280.      *  event listeners. */
  281.     public function dispose():void {
  282.         stop(true);
  283.  
  284.         mNativeStage.removeEventListener(Event.ENTER_FRAME, onEnterFrame, false);
  285.         mNativeStage.removeEventListener(KeyboardEvent.KEY_DOWN, onKey, false);
  286.         mNativeStage.removeEventListener(KeyboardEvent.KEY_UP, onKey, false);
  287.         mNativeStage.removeEventListener(Event.RESIZE, onResize, false);
  288.         mNativeStage.removeEventListener(Event.MOUSE_LEAVE, onMouseLeave, false);
  289.         mNativeStage.removeChild(mNativeOverlay);
  290.  
  291.         mStage3D.removeEventListener(Event.CONTEXT3D_CREATE, onContextCreated, false);
  292.         mStage3D.removeEventListener(ErrorEvent.ERROR, onStage3DError, false);
  293.  
  294.         for each (var touchEventType:String in touchEventTypes)
  295.             mNativeStage.removeEventListener(touchEventType, onTouch, false);
  296.  
  297.         if (mStage) mStage.dispose();
  298.         if (mSupport) mSupport.dispose();
  299.         if (mTouchProcessor) mTouchProcessor.dispose();
  300.         if (sCurrent == this) sCurrent = null;
  301.         if (mContext && !mShareContext) {
  302.             // Per default, the context is recreated as long as there are listeners on it.
  303.             // Beginning with AIR 3.6, we can avoid that with an additional parameter.
  304.  
  305.             var disposeContext3D:Function = mContext.dispose;
  306.             if (disposeContext3D.length == 1) disposeContext3D(false);
  307.             else disposeContext3D();
  308.         }
  309.     }
  310.  
  311.     // functions
  312.  
  313.     private function initialize():void {
  314.         makeCurrent();
  315.  
  316.         initializeGraphicsAPI();
  317.         initializeRoot();
  318.  
  319.         mTouchProcessor.simulateMultitouch = mSimulateMultitouch;
  320.         mLastFrameTimestamp = getTimer() / 1000.0;
  321.     }
  322.  
  323.     private function initializeGraphicsAPI():void {
  324.         mContext = mStage3D.context3D;
  325.         mContext.enableErrorChecking = mEnableErrorChecking;
  326.         contextData[PROGRAM_DATA_NAME] = new Dictionary();
  327.  
  328.         updateViewPort(true);
  329.  
  330.         trace("[Starling] Initialization complete.");
  331.         trace("[Starling] Display Driver:", mContext.driverInfo);
  332.  
  333.         dispatchEventWith(starling.events.Event.CONTEXT3D_CREATE, false, mContext);
  334.     }
  335.  
  336.     private function initializeRoot():void {
  337.         if (mRoot == null) {
  338.             mRoot = new mRootClass() as DisplayObject;
  339.             if (mRoot == null) throw new Error("Invalid root class: " + mRootClass);
  340.             mStage.addChildAt(mRoot, 0);
  341.  
  342.             dispatchEventWith(starling.events.Event.ROOT_CREATED, false, mRoot);
  343.         }
  344.     }
  345.  
  346.     /** Calls <code>advanceTime()</code> (with the time that has passed since the last frame)
  347.      *  and <code>render()</code>. */
  348.     public function nextFrame():void {
  349.         var now:Number = getTimer() / 1000.0;
  350.         var passedTime:Number = now - mLastFrameTimestamp;
  351.         mLastFrameTimestamp = now;
  352.  
  353.         advanceTime(passedTime);
  354.         render();
  355.     }
  356.  
  357.     /** Dispatches ENTER_FRAME events on the display list, advances the Juggler
  358.      *  and processes touches. */
  359.     public function advanceTime(passedTime:Number):void {
  360.         makeCurrent();
  361.  
  362.         mTouchProcessor.advanceTime(passedTime);
  363.         mStage.advanceTime(passedTime);
  364.         mJuggler.advanceTime(passedTime);
  365.     }
  366.  
  367.     /** Renders the complete display list. Before rendering, the context is cleared; afterwards,
  368.      *  it is presented. This can be avoided by enabling <code>shareContext</code>.*/
  369.     public function render():void {
  370.         if (!contextValid)
  371.             return;
  372.  
  373.         makeCurrent();
  374.         updateViewPort();
  375.         updateNativeOverlay();
  376.  
  377.         mSupport.nextFrame();
  378.  
  379.         if (!mShareContext)
  380.             RenderSupport.clear(mStage.color, 1.0);
  381.  
  382.         var scaleX:Number = mViewPort.width / mStage.stageWidth;
  383.         var scaleY:Number = mViewPort.height / mStage.stageHeight;
  384.  
  385.         mContext.setDepthTest(false, Context3DCompareMode.ALWAYS);
  386.         mContext.setCulling(Context3DTriangleFace.NONE);
  387.  
  388.         mSupport.renderTarget = null; // back buffer
  389.         mSupport.setOrthographicProjection(
  390.                         mViewPort.x < 0 ? -mViewPort.x / scaleX : 0.0,
  391.                         mViewPort.y < 0 ? -mViewPort.y / scaleY : 0.0,
  392.                         mClippedViewPort.width / scaleX,
  393.                         mClippedViewPort.height / scaleY);
  394.  
  395.         mStage.render(mSupport, 1.0);
  396.         mSupport.finishQuadBatch();
  397.  
  398.         if (mStatsDisplay)
  399.             mStatsDisplay.drawCount = mSupport.drawCount;
  400.  
  401.         if (!mShareContext)
  402.             mContext.present();
  403.     }
  404.  
  405.     private function updateViewPort(forceUpdate:Boolean = false):void {
  406.         // the last set viewport is stored in a variable; that way, people can modify the
  407.         // viewPort directly (without a copy) and we still know if it has changed.
  408.  
  409.         if (forceUpdate || mPreviousViewPort.width != mViewPort.width ||
  410.                 mPreviousViewPort.height != mViewPort.height ||
  411.                 mPreviousViewPort.x != mViewPort.x || mPreviousViewPort.y != mViewPort.y) {
  412.             mPreviousViewPort.setTo(mViewPort.x, mViewPort.y, mViewPort.width, mViewPort.height);
  413.  
  414.             // Constrained mode requires that the viewport is within the native stage bounds;
  415.             // thus, we use a clipped viewport when configuring the back buffer. (In baseline
  416.             // mode, that's not necessary, but it does not hurt either.)
  417.  
  418.             mClippedViewPort = mViewPort.intersection(
  419.                     new Rectangle(0, 0, mNativeStage.stageWidth, mNativeStage.stageHeight));
  420.  
  421.             if (!mShareContext) {
  422.                 // setting x and y might move the context to invalid bounds (since changing
  423.                 // the size happens in a separate operation) -- so we have no choice but to
  424.                 // set the backbuffer to a very small size first, to be on the safe side.
  425.  
  426.                 if (mProfile == "baselineConstrained")
  427.                     configureBackBuffer(32, 32, mAntiAliasing, false);
  428.  
  429.                 mStage3D.x = mClippedViewPort.x;
  430.                 mStage3D.y = mClippedViewPort.y;
  431.  
  432.                 configureBackBuffer(mClippedViewPort.width, mClippedViewPort.height,
  433.                         mAntiAliasing, false, mSupportHighResolutions);
  434.  
  435.                 if (mSupportHighResolutions && "contentsScaleFactor" in mNativeStage)
  436.                     mNativeStageContentScaleFactor = mNativeStage["contentsScaleFactor"];
  437.                 else
  438.                     mNativeStageContentScaleFactor = 1.0;
  439.             }
  440.         }
  441.     }
  442.  
  443.     /** Configures the back buffer while automatically keeping backwards compatibility with
  444.      *  AIR versions that do not support the "wantsBestResolution" argument. */
  445.     private function configureBackBuffer(width:int, height:int, antiAlias:int, enableDepthAndStencil:Boolean, wantsBestResolution:Boolean = false):void {
  446.         var configureBackBuffer:Function = mContext.configureBackBuffer;
  447.         var methodArgs:Array = [width, height, antiAlias, enableDepthAndStencil];
  448.         if (configureBackBuffer.length > 4) methodArgs.push(wantsBestResolution);
  449.         configureBackBuffer.apply(mContext, methodArgs);
  450.     }
  451.  
  452.     private function updateNativeOverlay():void {
  453.         mNativeOverlay.x = mViewPort.x;
  454.         mNativeOverlay.y = mViewPort.y;
  455.         mNativeOverlay.scaleX = mViewPort.width / mStage.stageWidth;
  456.         mNativeOverlay.scaleY = mViewPort.height / mStage.stageHeight;
  457.     }
  458.  
  459.     private function showFatalError(message:String):void {
  460.         var textField:TextField = new TextField();
  461.         var textFormat:TextFormat = new TextFormat("Verdana", 12, 0xFFFFFF);
  462.         textFormat.align = TextFormatAlign.CENTER;
  463.         textField.defaultTextFormat = textFormat;
  464.         textField.wordWrap = true;
  465.         textField.width = mStage.stageWidth * 0.75;
  466.         textField.autoSize = TextFieldAutoSize.CENTER;
  467.         textField.text = message;
  468.         textField.x = (mStage.stageWidth - textField.width) / 2;
  469.         textField.y = (mStage.stageHeight - textField.height) / 2;
  470.         textField.background = true;
  471.         textField.backgroundColor = 0x440000;
  472.         nativeOverlay.addChild(textField);
  473.     }
  474.  
  475.     /** Make this Starling instance the <code>current</code> one. */
  476.     public function makeCurrent():void {
  477.         sCurrent = this;
  478.     }
  479.  
  480.     /** As soon as Starling is started, it will queue input events (keyboard/mouse/touch);
  481.      *  furthermore, the method <code>nextFrame</code> will be called once per Flash Player
  482.      *  frame. (Except when <code>shareContext</code> is enabled: in that case, you have to
  483.      *  call that method manually.) */
  484.     public function start():void {
  485.         mStarted = mRendering = true;
  486.         mLastFrameTimestamp = getTimer() / 1000.0;
  487.     }
  488.  
  489.     /** Stops all logic and input processing, effectively freezing the app in its current state.
  490.      *  Per default, rendering will continue: that's because the classic display list
  491.      *  is only updated when stage3D is. (If Starling stopped rendering, conventional Flash
  492.      *  contents would freeze, as well.)
  493.      *
  494.      *  <p>However, if you don't need classic Flash contents, you can stop rendering, too.
  495.      *  On some mobile systems (e.g. iOS), you are even required to do so if you have
  496.      *  activated background code execution.</p>
  497.      */
  498.     public function stop(suspendRendering:Boolean = false):void {
  499.         mStarted = false;
  500.         mRendering = !suspendRendering;
  501.     }
  502.  
  503.     // event handlers
  504.  
  505.     private function onStage3DError(event:ErrorEvent):void {
  506.         if (event.errorID == 3702) {
  507.             var mode:String = Capabilities.playerType == "Desktop" ? "renderMode" : "wmode";
  508.             showFatalError("Context3D not available! Possible reasons: wrong " + mode +
  509.                     " or missing device support.");
  510.         }
  511.         else
  512.             showFatalError("Stage3D error: " + event.text);
  513.     }
  514.  
  515.     private function onContextCreated(event:Event):void {
  516.         if (!Starling.handleLostContext && mContext) {
  517.             stop();
  518.             event.stopImmediatePropagation();
  519.             showFatalError("Fatal error: The application lost the device context!");
  520.             trace("[Starling] The device context was lost. " +
  521.                     "Enable 'Starling.handleLostContext' to avoid this error.");
  522.         }
  523.         else {
  524.             initialize();
  525.         }
  526.     }
  527.  
  528.     private function onEnterFrame(event:Event):void {
  529.         // On mobile, the native display list is only updated on stage3D draw calls.
  530.         // Thus, we render even when Starling is paused.
  531.  
  532.         if (!mShareContext) {
  533.             if (mStarted) nextFrame();
  534.             else if (mRendering) render();
  535.         }
  536.     }
  537.  
  538.     private function onKey(event:KeyboardEvent):void {
  539.         if (!mStarted) return;
  540.  
  541.         var keyEvent:starling.events.KeyboardEvent = new starling.events.KeyboardEvent(
  542.                 event.type, event.charCode, event.keyCode, event.keyLocation,
  543.                 event.ctrlKey, event.altKey, event.shiftKey);
  544.  
  545.         makeCurrent();
  546.         mStage.broadcastEvent(keyEvent);
  547.  
  548.         if (keyEvent.isDefaultPrevented())
  549.             event.preventDefault();
  550.     }
  551.  
  552.     private function onResize(event:Event):void {
  553.         var stage:flash.display.Stage = event.target as flash.display.Stage;
  554.         mStage.dispatchEvent(new ResizeEvent(Event.RESIZE, stage.stageWidth, stage.stageHeight));
  555.     }
  556.  
  557.     private function onMouseLeave(event:Event):void {
  558.         mTouchProcessor.enqueueMouseLeftStage();
  559.     }
  560.  
  561.     private function onTouch(event:Event):void {
  562.         if (!mStarted) return;
  563.  
  564.         var globalX:Number;
  565.         var globalY:Number;
  566.         var touchID:int;
  567.         var phase:String;
  568.         var pressure:Number = 1.0;
  569.         var width:Number = 1.0;
  570.         var height:Number = 1.0;
  571.  
  572.         // figure out general touch properties
  573.         if (event is MouseEvent) {
  574.             var mouseEvent:MouseEvent = event as MouseEvent;
  575.             globalX = mouseEvent.stageX;
  576.             globalY = mouseEvent.stageY;
  577.             touchID = 0;
  578.  
  579.             // MouseEvent.buttonDown returns true for both left and right button (AIR supports
  580.             // the right mouse button). We only want to react on the left button for now,
  581.             // so we have to save the state for the left button manually.
  582.             if (event.type == MouseEvent.MOUSE_DOWN)    mLeftMouseDown = true;
  583.             else if (event.type == MouseEvent.MOUSE_UP) mLeftMouseDown = false;
  584.         }
  585.         else {
  586.             var touchEvent:TouchEvent = event as TouchEvent;
  587.  
  588.             // On a system that supports both mouse and touch input, the primary touch point
  589.             // is dispatched as mouse event as well. Since we don't want to listen to that
  590.             // event twice, we ignore the primary touch in that case.
  591.  
  592.             if (Mouse.supportsCursor && touchEvent.isPrimaryTouchPoint) return;
  593.             else {
  594.                 globalX = touchEvent.stageX;
  595.                 globalY = touchEvent.stageY;
  596.                 touchID = touchEvent.touchPointID;
  597.                 pressure = touchEvent.pressure;
  598.                 width = touchEvent.sizeX;
  599.                 height = touchEvent.sizeY;
  600.             }
  601.         }
  602.  
  603.         // figure out touch phase
  604.         switch (event.type) {
  605.             case TouchEvent.TOUCH_BEGIN:
  606.                 phase = TouchPhase.BEGAN;
  607.                 break;
  608.             case TouchEvent.TOUCH_MOVE:
  609.                 phase = TouchPhase.MOVED;
  610.                 break;
  611.             case TouchEvent.TOUCH_END:
  612.                 phase = TouchPhase.ENDED;
  613.                 break;
  614.             case MouseEvent.MOUSE_DOWN:
  615.                 phase = TouchPhase.BEGAN;
  616.                 break;
  617.             case MouseEvent.MOUSE_UP:
  618.                 phase = TouchPhase.ENDED;
  619.                 break;
  620.             case MouseEvent.MOUSE_MOVE:
  621.                 phase = (mLeftMouseDown ? TouchPhase.MOVED : TouchPhase.HOVER);
  622.                 break;
  623.         }
  624.  
  625.         // move position into viewport bounds
  626.         globalX = mStage.stageWidth * (globalX - mViewPort.x) / mViewPort.width;
  627.         globalY = mStage.stageHeight * (globalY - mViewPort.y) / mViewPort.height;
  628.  
  629.         // enqueue touch in touch processor
  630.         mTouchProcessor.enqueue(touchID, phase, globalX, globalY, pressure, width, height);
  631.  
  632.         // allow objects that depend on mouse-over state to be updated immediately
  633.         if (event.type == MouseEvent.MOUSE_UP)
  634.             mTouchProcessor.enqueue(touchID, TouchPhase.HOVER, globalX, globalY);
  635.     }
  636.  
  637.     private function get touchEventTypes():Array {
  638.         var types:Array = [];
  639.  
  640.         if (multitouchEnabled)
  641.             types.push(TouchEvent.TOUCH_BEGIN, TouchEvent.TOUCH_MOVE, TouchEvent.TOUCH_END);
  642.  
  643.         if (!multitouchEnabled || Mouse.supportsCursor)
  644.             types.push(MouseEvent.MOUSE_DOWN, MouseEvent.MOUSE_MOVE, MouseEvent.MOUSE_UP);
  645.  
  646.         return types;
  647.     }
  648.  
  649.     // program management
  650.  
  651.     /** Registers a compiled shader-program under a certain name.
  652.      *  If the name was already used, the previous program is overwritten. */
  653.     public function registerProgram(name:String, vertexShader:ByteArray, fragmentShader:ByteArray):Program3D {
  654.         deleteProgram(name);
  655.  
  656.         var program:Program3D = mContext.createProgram();
  657.         program.upload(vertexShader, fragmentShader);
  658.         programs[name] = program;
  659.  
  660.         return program;
  661.     }
  662.  
  663.     /** Compiles a shader-program and registers it under a certain name.
  664.      *  If the name was already used, the previous program is overwritten. */
  665.     public function registerProgramFromSource(name:String, vertexShader:String, fragmentShader:String):Program3D {
  666.         deleteProgram(name);
  667.  
  668.         var program:Program3D = RenderSupport.assembleAgal(vertexShader, fragmentShader);
  669.         programs[name] = program;
  670.  
  671.         return program;
  672.     }
  673.  
  674.     /** Deletes the vertex- and fragment-programs of a certain name. */
  675.     public function deleteProgram(name:String):void {
  676.         var program:Program3D = getProgram(name);
  677.         if (program) {
  678.             program.dispose();
  679.             delete programs[name];
  680.         }
  681.     }
  682.  
  683.     /** Returns the vertex- and fragment-programs registered under a certain name. */
  684.     public function getProgram(name:String):Program3D {
  685.         return programs[name] as Program3D;
  686.     }
  687.  
  688.     /** Indicates if a set of vertex- and fragment-programs is registered under a certain name. */
  689.     public function hasProgram(name:String):Boolean {
  690.         return name in programs;
  691.     }
  692.  
  693.     private function get programs():Dictionary {
  694.         return contextData[PROGRAM_DATA_NAME];
  695.     }
  696.  
  697.     // properties
  698.  
  699.     /** Indicates if a context is available and non-disposed. */
  700.     private function get contextValid():Boolean {
  701.         return (mContext && mContext.driverInfo != "Disposed");
  702.     }
  703.  
  704.     /** Indicates if this Starling instance is started. */
  705.     public function get isStarted():Boolean {
  706.         return mStarted;
  707.     }
  708.  
  709.     /** The default juggler of this instance. Will be advanced once per frame. */
  710.     public function get juggler():Juggler {
  711.         return mJuggler;
  712.     }
  713.  
  714.     /** The render context of this instance. */
  715.     public function get context():Context3D {
  716.         return mContext;
  717.     }
  718.  
  719.     /** A dictionary that can be used to save custom data related to the current context.
  720.      *  If you need to share data that is bound to a specific stage3D instance
  721.      *  (e.g. textures), use this dictionary instead of creating a static class variable.
  722.      *  The Dictionary is actually bound to the stage3D instance, thus it survives a
  723.      *  context loss. */
  724.     public function get contextData():Dictionary {
  725.         return sContextData[mStage3D] as Dictionary;
  726.     }
  727.  
  728.     /** Returns the actual width (in pixels) of the back buffer. This can differ from the
  729.      *  width of the viewPort rectangle if it is partly outside the native stage. */
  730.     public function get backBufferWidth():int {
  731.         return mClippedViewPort.width;
  732.     }
  733.  
  734.     /** Returns the actual height (in pixels) of the back buffer. This can differ from the
  735.      *  height of the viewPort rectangle if it is partly outside the native stage. */
  736.     public function get backBufferHeight():int {
  737.         return mClippedViewPort.height;
  738.     }
  739.  
  740.     /** Indicates if multitouch simulation with "Shift" and "Ctrl"/"Cmd"-keys is enabled.
  741.      *  @default false */
  742.     public function get simulateMultitouch():Boolean {
  743.         return mSimulateMultitouch;
  744.     }
  745.  
  746.     public function set simulateMultitouch(value:Boolean):void {
  747.         mSimulateMultitouch = value;
  748.         if (mContext) mTouchProcessor.simulateMultitouch = value;
  749.     }
  750.  
  751.     /** Indicates if Stage3D render methods will report errors. Activate only when needed,
  752.      *  as this has a negative impact on performance. @default false */
  753.     public function get enableErrorChecking():Boolean {
  754.         return mEnableErrorChecking;
  755.     }
  756.  
  757.     public function set enableErrorChecking(value:Boolean):void {
  758.         mEnableErrorChecking = value;
  759.         if (mContext) mContext.enableErrorChecking = value;
  760.     }
  761.  
  762.     /** The antialiasing level. 0 - no antialasing, 16 - maximum antialiasing. @default 0 */
  763.     public function get antiAliasing():int {
  764.         return mAntiAliasing;
  765.     }
  766.  
  767.     public function set antiAliasing(value:int):void {
  768.         if (mAntiAliasing != value) {
  769.             mAntiAliasing = value;
  770.             if (contextValid) updateViewPort(true);
  771.         }
  772.     }
  773.  
  774.     /** The viewport into which Starling contents will be rendered. */
  775.     public function get viewPort():Rectangle {
  776.         return mViewPort;
  777.     }
  778.  
  779.     public function set viewPort(value:Rectangle):void {
  780.         mViewPort = value.clone();
  781.     }
  782.  
  783.     /** The ratio between viewPort width and stage width. Useful for choosing a different
  784.      *  set of textures depending on the display resolution. */
  785.     public function get contentScaleFactor():Number {
  786.         return (mViewPort.width * mNativeStageContentScaleFactor) / mStage.stageWidth;
  787.     }
  788.  
  789.     /** A Flash Sprite placed directly on top of the Starling content. Use it to display native
  790.      *  Flash components. */
  791.     public function get nativeOverlay():Sprite {
  792.         return mNativeOverlay;
  793.     }
  794.  
  795.     /** Indicates if a small statistics box (with FPS, memory usage and draw count) is displayed. */
  796.     public function get showStats():Boolean {
  797.         return mStatsDisplay && mStatsDisplay.parent;
  798.     }
  799.  
  800.     public function set showStats(value:Boolean):void {
  801.         if (value == showStats) return;
  802.  
  803.         if (value) {
  804.             if (mStatsDisplay) mStage.addChild(mStatsDisplay);
  805.             else               showStatsAt();
  806.         }
  807.         else mStatsDisplay.removeFromParent();
  808.     }
  809.  
  810.     /** Displays the statistics box at a certain position. */
  811.     public function showStatsAt(hAlign:String = "left", vAlign:String = "top", scale:Number = 1):void {
  812.         if (mContext == null) {
  813.             // Starling is not yet ready - we postpone this until it's initialized.
  814.             addEventListener(starling.events.Event.ROOT_CREATED, onRootCreated);
  815.         }
  816.         else {
  817.             if (mStatsDisplay == null) {
  818.                 mStatsDisplay = new StatsDisplay();
  819.                 mStatsDisplay.touchable = false;
  820.                 mStage.addChild(mStatsDisplay);
  821.             }
  822.  
  823.             var stageWidth:int = mStage.stageWidth;
  824.             var stageHeight:int = mStage.stageHeight;
  825.  
  826.             mStatsDisplay.scaleX = mStatsDisplay.scaleY = scale;
  827.  
  828.             if (hAlign == HAlign.LEFT) mStatsDisplay.x = 0;
  829.             else if (hAlign == HAlign.RIGHT) mStatsDisplay.x = stageWidth - mStatsDisplay.width;
  830.             else mStatsDisplay.x = int((stageWidth - mStatsDisplay.width) / 2);
  831.  
  832.             if (vAlign == VAlign.TOP) mStatsDisplay.y = 0;
  833.             else if (vAlign == VAlign.BOTTOM) mStatsDisplay.y = stageHeight - mStatsDisplay.height;
  834.             else mStatsDisplay.y = int((stageHeight - mStatsDisplay.height) / 2);
  835.         }
  836.  
  837.         function onRootCreated():void {
  838.             showStatsAt(hAlign, vAlign, scale);
  839.             removeEventListener(starling.events.Event.ROOT_CREATED, onRootCreated);
  840.         }
  841.     }
  842.  
  843.     /** The Starling stage object, which is the root of the display tree that is rendered. */
  844.     public function get stage():Stage {
  845.         return mStage;
  846.     }
  847.  
  848.     /** The Flash Stage3D object Starling renders into. */
  849.     public function get stage3D():Stage3D {
  850.         return mStage3D;
  851.     }
  852.  
  853.     /** The Flash (2D) stage object Starling renders beneath. */
  854.     public function get nativeStage():flash.display.Stage {
  855.         return mNativeStage;
  856.     }
  857.  
  858.     /** The instance of the root class provided in the constructor. Available as soon as
  859.      *  the event 'ROOT_CREATED' has been dispatched. */
  860.     public function get root():DisplayObject {
  861.         return mRoot;
  862.     }
  863.  
  864.     /** Indicates if the Context3D render calls are managed externally to Starling,
  865.      *  to allow other frameworks to share the Stage3D instance. @default false */
  866.     public function get shareContext():Boolean {
  867.         return mShareContext;
  868.     }
  869.  
  870.     public function set shareContext(value:Boolean):void {
  871.         mShareContext = value;
  872.     }
  873.  
  874.     /** The Context3D profile as requested in the constructor. Beware that if you are
  875.      *  using a shared context, this might not be accurate. */
  876.     public function get profile():String {
  877.         return mProfile;
  878.     }
  879.  
  880.     /** Indicates that if the device supports HiDPI screens Starling will attempt to allocate
  881.      *  a larger back buffer than indicated via the viewPort size. Note that this is used
  882.      *  on Desktop only; mobile AIR apps still use the "requestedDisplayResolution" parameter
  883.      *  the application descriptor XML. */
  884.     public function get supportHighResolutions():Boolean {
  885.         return mSupportHighResolutions;
  886.     }
  887.  
  888.     public function set supportHighResolutions(value:Boolean):void {
  889.         if (mSupportHighResolutions != value) {
  890.             mSupportHighResolutions = value;
  891.             if (contextValid) updateViewPort(true);
  892.         }
  893.     }
  894.  
  895.     /** The TouchProcessor is passed all mouse and touch input and is responsible for
  896.      *  dispatching TouchEvents to the Starling display tree. If you want to handle these
  897.      *  types of input manually, pass your own custom subclass to this property. */
  898.     public function get touchProcessor():TouchProcessor {
  899.         return mTouchProcessor;
  900.     }
  901.  
  902.     public function set touchProcessor(value:TouchProcessor):void {
  903.         if (value != mTouchProcessor) {
  904.             mTouchProcessor.dispose();
  905.             mTouchProcessor = value;
  906.         }
  907.     }
  908.  
  909.     // static properties
  910.  
  911.     /** The currently active Starling instance. */
  912.     public static function get current():Starling {
  913.         return sCurrent;
  914.     }
  915.  
  916.     /** The render context of the currently active Starling instance. */
  917.     public static function get context():Context3D {
  918.         return sCurrent ? sCurrent.context : null;
  919.     }
  920.  
  921.     /** The default juggler of the currently active Starling instance. */
  922.     public static function get juggler():Juggler {
  923.         return sCurrent ? sCurrent.juggler : null;
  924.     }
  925.  
  926.     /** The contentScaleFactor of the currently active Starling instance. */
  927.     public static function get contentScaleFactor():Number {
  928.         return sCurrent ? sCurrent.contentScaleFactor : 1.0;
  929.     }
  930.  
  931.     /** Indicates if multitouch input should be supported. */
  932.     public static function get multitouchEnabled():Boolean {
  933.         return Multitouch.inputMode == MultitouchInputMode.TOUCH_POINT;
  934.     }
  935.  
  936.     public static function set multitouchEnabled(value:Boolean):void {
  937.         if (sCurrent) throw new IllegalOperationError(
  938.                 "'multitouchEnabled' must be set before Starling instance is created");
  939.         else
  940.             Multitouch.inputMode = value ? MultitouchInputMode.TOUCH_POINT :
  941.                     MultitouchInputMode.NONE;
  942.     }
  943.  
  944.     /** Indicates if Starling should automatically recover from a lost device context.
  945.      *  On some systems, an upcoming screensaver or entering sleep mode may
  946.      *  invalidate the render context. This setting indicates if Starling should recover from
  947.      *  such incidents. Beware that this has a huge impact on memory consumption!
  948.      *  It is recommended to enable this setting on Android and Windows, but to deactivate it
  949.      *  on iOS and Mac OS X. @default false */
  950.     public static function get handleLostContext():Boolean {
  951.         return sHandleLostContext;
  952.     }
  953.  
  954.     public static function set handleLostContext(value:Boolean):void {
  955.         if (sCurrent) throw new IllegalOperationError(
  956.                 "'handleLostContext' must be set before Starling instance is created");
  957.         else
  958.             sHandleLostContext = value;
  959.     }
  960. }
  961. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top