/src/com/pblabs/screens/ScreenManager.as

https://github.com/joelhooks/PushButtonEngine · ActionScript · 195 lines · 98 code · 23 blank · 74 comment · 11 complexity · d9e2b56d8364411e93686b528d88321a MD5 · raw file

  1. /*******************************************************************************
  2. * PushButton Engine
  3. * Copyright (C) 2009 PushButton Labs, LLC
  4. * For more information see http://www.pushbuttonengine.com
  5. *
  6. * This file is licensed under the terms of the MIT license, which is included
  7. * in the License.html file at the root directory of this SDK.
  8. ******************************************************************************/
  9. package com.pblabs.screens
  10. {
  11. import com.pblabs.engine.PBE;
  12. import com.pblabs.engine.core.*;
  13. import com.pblabs.engine.debug.Logger;
  14. import flash.display.DisplayObject;
  15. import flash.display.DisplayObjectContainer;
  16. import flash.display.Sprite;
  17. import flash.events.*;
  18. import flash.utils.*;
  19. /**
  20. * A simple system for managing a game's UI.
  21. *
  22. * <p>The ScreenManager lets you have a set of named screens. The
  23. * goto(), push(), and pop() methods let you move from screen
  24. * to screen in an easy to follow way. A screen is just a DisplayObject
  25. * which implements IScreen; the included classes are all AS, but if you
  26. * entirely use Flex, you can use .mxml, too.</p>
  27. *
  28. * <p>To use, first register screen instances by calling registerScreen.
  29. * Each screen has a unique name. That is what you pass to goto() and
  30. * push().</p>
  31. *
  32. * <p>The ScreenManager maintains a stack of screens. Only the topmost
  33. * screen is added to the display list, for efficiency. If you want a
  34. * dialog or another element which only partially covers the screen,
  35. * you will probably want to use a different system.</p>
  36. */
  37. public class ScreenManager implements IAnimatedObject, ITickedObject
  38. {
  39. static private var _instance:ScreenManager;
  40. static public function get instance():ScreenManager
  41. {
  42. if(!_instance)
  43. _instance = new ScreenManager();
  44. return _instance;
  45. }
  46. public function ScreenManager()
  47. {
  48. PBE.processManager.addTickedObject(this);
  49. PBE.processManager.addAnimatedObject(this);
  50. screenParent = PBE.mainClass;
  51. }
  52. /**
  53. * Associate a named screen with the ScreenManager.
  54. */
  55. public function registerScreen(name:String, instance:IScreen):void
  56. {
  57. screenDictionary[name] = instance;
  58. }
  59. /**
  60. * Get a screen by name.
  61. * @param name Name of the string to get.
  62. * @return Requested screen.
  63. */
  64. public function get(name:String):IScreen
  65. {
  66. return screenDictionary[name];
  67. }
  68. /**
  69. * Go to a named screen.
  70. */
  71. private function set currentScreen(value:String):void
  72. {
  73. if(_currentScreen)
  74. {
  75. _currentScreen.onHide();
  76. _currentScreen = null;
  77. }
  78. if(value)
  79. {
  80. _currentScreen = screenDictionary[value];
  81. if(!_currentScreen)
  82. throw new Error("No such screen '" + value + "'");
  83. _currentScreen.onShow();
  84. }
  85. }
  86. /**
  87. * @returns The screen currently being displayed, if any.
  88. */
  89. public function getCurrentScreen():IScreen
  90. {
  91. return _currentScreen;
  92. }
  93. /**
  94. * Return true if a screen of given name exists.
  95. * @param screenName Name of screen.
  96. * @return True if screen exists.
  97. *
  98. */
  99. public function hasScreen(screenName:String):Boolean
  100. {
  101. return get(screenName) != null;
  102. }
  103. /**
  104. * Switch to the specified screen, altering the top of the stack.
  105. * @param screenName Name of the screen to switch to.
  106. */
  107. public function goto(screenName:String):void
  108. {
  109. pop();
  110. push(screenName);
  111. }
  112. /**
  113. * Switch to the specified screen, saving the current screen in the
  114. * stack so you can pop() and return to it later.
  115. * @param screenName Name of the screen to switch to.
  116. */
  117. public function push(screenName:String):void
  118. {
  119. screenStack.push(screenName);
  120. currentScreen = screenName;
  121. screenParent.addChild(get(screenName) as DisplayObject);
  122. }
  123. /**
  124. * Pop the top of the stack and change to the new top element. Useful
  125. * for returning to the previous screen when it push()ed to the
  126. * current one.
  127. */
  128. public function pop():void
  129. {
  130. if(screenStack.length == 0)
  131. {
  132. Logger.warn(this, "pop", "Trying to pop empty ScreenManager.");
  133. return;
  134. }
  135. var oldScreen:DisplayObject = get(screenStack.pop()) as DisplayObject;
  136. currentScreen = screenStack[screenStack.length - 1];
  137. if(oldScreen && oldScreen.parent)
  138. oldScreen.parent.removeChild(oldScreen);
  139. }
  140. /**
  141. * @private
  142. */
  143. public function onFrame(elapsed:Number):void
  144. {
  145. if(_currentScreen)
  146. _currentScreen.onFrame(elapsed);
  147. }
  148. /**
  149. * @private
  150. */
  151. public function onTick(tickRate:Number):void
  152. {
  153. if(_currentScreen)
  154. _currentScreen.onTick(tickRate);
  155. }
  156. /**
  157. * @private
  158. */
  159. public function onInterpolateTick(i:Number):void
  160. {
  161. }
  162. /**
  163. * This is where the screens are added and removed. Normally it is
  164. * set to Global.mainClass, but you may want to override it for
  165. * special cases.
  166. */
  167. public var screenParent:DisplayObjectContainer = null;
  168. private var _currentScreen:IScreen = null;
  169. private var screenStack:Array = [null];
  170. private var screenDictionary:Dictionary = new Dictionary();
  171. }
  172. }