PageRenderTime 3677ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/src/aerys/minko/render/Viewport.as

http://github.com/aerys/minko
ActionScript | 489 lines | 345 code | 84 blank | 60 comment | 55 complexity | 0e63ef395688870544ae1b28f35029d8 MD5 | raw file
Possible License(s): Apache-2.0, BSD-3-Clause, LGPL-3.0, LGPL-2.1
  1. package aerys.minko.render
  2. {
  3. import aerys.minko.ns.minko_render;
  4. import aerys.minko.render.resource.Context3DResource;
  5. import aerys.minko.type.KeyboardManager;
  6. import aerys.minko.type.MouseManager;
  7. import aerys.minko.type.Signal;
  8. import flash.display.DisplayObject;
  9. import flash.display.DisplayObjectContainer;
  10. import flash.display.Graphics;
  11. import flash.display.Shape;
  12. import flash.display.Sprite;
  13. import flash.display.Stage;
  14. import flash.display.Stage3D;
  15. import flash.display.StageAlign;
  16. import flash.display.StageScaleMode;
  17. import flash.events.Event;
  18. import flash.events.MouseEvent;
  19. import flash.events.TouchEvent;
  20. import flash.geom.Point;
  21. /**
  22. * The Viewport is the display area where a 3D scene can be rendered.
  23. *
  24. * @author Jean-Marc Le Roux
  25. *
  26. */
  27. public class Viewport extends Sprite
  28. {
  29. private static const ZERO2 : Point = new Point();
  30. private var _stage3d : Stage3D = null;
  31. private var _context3d : Context3DResource = null;
  32. private var _width : uint = 0;
  33. private var _height : uint = 0;
  34. private var _autoResize : Boolean = false;
  35. private var _antiAliasing : uint = 0;
  36. private var _backgroundColor : uint = 0;
  37. private var _backBuffer : RenderTarget = null;
  38. private var _invalidBackBuffer : Boolean = false;
  39. private var _alwaysOnTop : Boolean = false;
  40. private var _mask : Shape = new Shape();
  41. private var _mouseManager : MouseManager = new MouseManager();
  42. private var _keyboardManager : KeyboardManager = new KeyboardManager();
  43. private var _resized : Signal = new Signal('Viewport.resized');
  44. minko_render function get context3D() : Context3DResource
  45. {
  46. return _context3d;
  47. }
  48. minko_render function get backBuffer() : RenderTarget
  49. {
  50. var positionOnStage : Point = localToGlobal(ZERO2);
  51. if (_stage3d.x != positionOnStage.x || _stage3d.y != positionOnStage.y)
  52. updateStage3D()
  53. return _backBuffer;
  54. }
  55. public function get ready() : Boolean
  56. {
  57. return _stage3d != null && _stage3d.context3D != null && _backBuffer != null;
  58. }
  59. /**
  60. * Whether the viewport is visible or not.
  61. * @return
  62. *
  63. */
  64. override public function set visible(value : Boolean) : void
  65. {
  66. if (_stage3d)
  67. _stage3d.visible = value;
  68. super.visible = value;
  69. }
  70. override public function set x(value : Number) : void
  71. {
  72. super.x = value;
  73. updateStage3D();
  74. }
  75. override public function set y(value : Number) : void
  76. {
  77. super.y = value;
  78. updateStage3D();
  79. }
  80. /**
  81. * The width of the display area.
  82. * @return
  83. *
  84. */
  85. override public function get width() : Number
  86. {
  87. return _width;
  88. }
  89. override public function set width(value : Number) : void
  90. {
  91. resize(value, _height);
  92. }
  93. /**
  94. * The height of the display area.
  95. * @return
  96. *
  97. */
  98. override public function get height() : Number
  99. {
  100. return _height;
  101. }
  102. override public function set height(value : Number) : void
  103. {
  104. resize(_width, value);
  105. }
  106. public function get alwaysOnTop() : Boolean
  107. {
  108. return _alwaysOnTop;
  109. }
  110. public function set alwaysOnTop(value : Boolean) : void
  111. {
  112. _alwaysOnTop = value;
  113. }
  114. public function get keyboardManager() : KeyboardManager
  115. {
  116. return _keyboardManager;
  117. }
  118. public function get mouseManager() : MouseManager
  119. {
  120. return _mouseManager;
  121. }
  122. /**
  123. * The signal executed when the viewport is resized.
  124. * Callback functions for this signal should accept the following
  125. * arguments:
  126. * <ul>
  127. * <li>viewport : Viewport, the viewport executing the signal</li>
  128. * <li>width : Number, the new width of the viewport</li>
  129. * <li>height : Number, the new height of the viewport</li>
  130. * </ul>
  131. * @return
  132. *
  133. */
  134. public function get resized() : Signal
  135. {
  136. return _resized;
  137. }
  138. /**
  139. * The background color of the display area. This value must use the
  140. * RGB format.
  141. * @return
  142. *
  143. */
  144. public function get backgroundColor() : uint
  145. {
  146. return _backgroundColor;
  147. }
  148. public function set backgroundColor(value : uint) : void
  149. {
  150. _backgroundColor = value;
  151. updateBackBuffer();
  152. }
  153. /**
  154. * The anti-aliasing to use (0, 2, 4, 8 or 16). The actual anti-aliasing
  155. * used for rendering depends on the hardware capabilities. If the specified
  156. * anti-aliasing value is not supported, the value 0 will be used.
  157. * @return
  158. *
  159. */
  160. public function get antiAliasing() : uint
  161. {
  162. return _antiAliasing;
  163. }
  164. public function set antiAliasing(value : uint) : void
  165. {
  166. _antiAliasing = value;
  167. updateStage3D();
  168. }
  169. /**
  170. * The driver informations provided by the Stage3D API.
  171. */
  172. public function get driverInfo() : String
  173. {
  174. return _stage3d && _stage3d.context3D
  175. ? _stage3d.context3D.driverInfo
  176. : null;
  177. }
  178. public function Viewport(antiAliasing : uint = 0,
  179. width : uint = 0,
  180. height : uint = 0)
  181. {
  182. _antiAliasing = antiAliasing;
  183. if (width == 0 && height == 0)
  184. _autoResize = true;
  185. _width = width;
  186. _height = height;
  187. initialize();
  188. }
  189. private function initialize() : void
  190. {
  191. _mouseManager.bind(this);
  192. addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
  193. addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
  194. }
  195. private function addedToStageHandler(event : Event) : void
  196. {
  197. _keyboardManager.bind(stage);
  198. parent.addEventListener(Event.RESIZE, parentResizedHandler);
  199. stage.addEventListener(Event.ADDED_TO_STAGE, displayObjectAddedToStageHandler);
  200. stage.addEventListener(Event.REMOVED_FROM_STAGE, displayObjectRemovedFromStageHandler);
  201. stage.addEventListener(Event.RESIZE, stageResizedHandler);
  202. setupOnStage(stage);
  203. }
  204. private function removedFromStageHandler(event : Event) : void
  205. {
  206. _keyboardManager.unbind(stage);
  207. parent.removeEventListener(Event.RESIZE, parentResizedHandler);
  208. stage.removeEventListener(Event.ADDED_TO_STAGE, displayObjectAddedToStageHandler);
  209. stage.removeEventListener(Event.REMOVED_FROM_STAGE, displayObjectRemovedFromStageHandler);
  210. stage.removeEventListener(Event.RESIZE, stageResizedHandler);
  211. if (_stage3d != null)
  212. _stage3d.visible = false;
  213. }
  214. private function setupOnStage(stage : Stage, stage3dId : uint = 0) : void
  215. {
  216. if (_autoResize)
  217. {
  218. _width = stage.stageWidth;
  219. _height = stage.stageHeight;
  220. }
  221. if (!_stage3d)
  222. {
  223. _stage3d = stage.stage3Ds[stage3dId];
  224. _stage3d.addEventListener(Event.CONTEXT3D_CREATE, context3dCreatedHandler);
  225. _stage3d.requestContext3D();
  226. }
  227. else
  228. {
  229. _stage3d.visible = visible;
  230. }
  231. stage.scaleMode = StageScaleMode.NO_SCALE;
  232. stage.align = StageAlign.TOP_LEFT;
  233. }
  234. /**
  235. * Dispose the Viewport and all the Stage3D related objects. After this operation,
  236. * the Viewport cannot be used anymore and is ready for garbage collection.
  237. */
  238. public function dispose():void
  239. {
  240. if (_stage3d != null)
  241. {
  242. _stage3d.removeEventListener(Event.CONTEXT3D_CREATE, context3dCreatedHandler);
  243. _stage3d = null;
  244. }
  245. if (_context3d != null)
  246. {
  247. _context3d.dispose();
  248. _context3d = null;
  249. }
  250. return ;
  251. }
  252. /**
  253. * Resize the display area. The "resized" signal is executed when the new width and
  254. * height have be set.
  255. * @param width
  256. * @param height
  257. *
  258. */
  259. public function resize(width : Number, height : Number) : void
  260. {
  261. _autoResize = false;
  262. setSize(width, height);
  263. }
  264. private function setSize(width : Number, height : Number) : void
  265. {
  266. if (width == _width && _height == height)
  267. return ;
  268. _width = width;
  269. _height = height;
  270. updateStage3D();
  271. updateBackBuffer();
  272. _resized.execute(this, width, height);
  273. }
  274. private function stageResizedHandler(event : Event) : void
  275. {
  276. updateMask();
  277. updateStage3D();
  278. updateBackBuffer();
  279. }
  280. private function parentResizedHandler(event : Event) : void
  281. {
  282. if (_autoResize)
  283. {
  284. if (parent == stage)
  285. setSize(stage.stageWidth, stage.stageHeight);
  286. else
  287. setSize(parent.width, parent.height);
  288. }
  289. }
  290. private function context3dCreatedHandler(event : Event) : void
  291. {
  292. _context3d = new Context3DResource(_stage3d.context3D);
  293. updateStage3D();
  294. updateBackBuffer();
  295. dispatchEvent(new Event(Event.INIT));
  296. }
  297. private function updateBackBuffer() : void
  298. {
  299. if (_width == 0 || _height == 0 || _stage3d == null || _stage3d.context3D == null)
  300. return ;
  301. _invalidBackBuffer = false;
  302. var backBufferWidth : Number = _width * getGlobalScaleX();
  303. var backBufferHeight : Number = _height * getGlobalScaleY();
  304. _stage3d.context3D.configureBackBuffer(backBufferWidth, backBufferHeight, _antiAliasing, true);
  305. _backBuffer = new RenderTarget(backBufferWidth, backBufferHeight, null, 0, _backgroundColor);
  306. graphics.clear();
  307. graphics.beginFill(0, 0);
  308. graphics.drawRect(0, 0, _width, _height);
  309. }
  310. private function updateStage3D() : void
  311. {
  312. if (_stage3d == null)
  313. return ;
  314. var upperLeft : Point = localToGlobal(ZERO2);
  315. _stage3d.x = upperLeft.x;
  316. _stage3d.y = upperLeft.y;
  317. if (_width > 2048)
  318. {
  319. _stage3d.x = (_width - 2048) * 0.5;
  320. _width = 2048;
  321. }
  322. else
  323. _stage3d.x = upperLeft.x;
  324. if (_height > 2048)
  325. {
  326. _stage3d.y = (_height - 2048) * 0.5;
  327. _height = 2048;
  328. }
  329. else
  330. _stage3d.y = upperLeft.y;
  331. updateMask();
  332. }
  333. private function updateMask() : void
  334. {
  335. if (!stage)
  336. return ;
  337. var numChildren : uint = stage.numChildren;
  338. var i : uint = 0;
  339. if (_alwaysOnTop)
  340. {
  341. var gfx : Graphics = _mask.graphics;
  342. var stageWidth : int = stage.stageWidth;
  343. var stageHeight : int = stage.stageHeight;
  344. gfx.clear();
  345. gfx.beginFill(0);
  346. gfx.moveTo(0, 0);
  347. gfx.lineTo(stageWidth, 0);
  348. gfx.lineTo(stageWidth, stageHeight);
  349. gfx.lineTo(0., stageHeight);
  350. gfx.lineTo(0, 0);
  351. gfx.moveTo(_stage3d.x, _stage3d.y);
  352. gfx.lineTo(_stage3d.x, _stage3d.y + height);
  353. gfx.lineTo(_stage3d.x + width, _stage3d.y + height);
  354. gfx.lineTo(_stage3d.x + width, _stage3d.y);
  355. gfx.lineTo(_stage3d.x, _stage3d.y);
  356. gfx.endFill();
  357. for (i = 0; i < numChildren; ++i)
  358. stage.getChildAt(i).mask = _mask;
  359. }
  360. else
  361. {
  362. for (i = 0; i < numChildren; ++i)
  363. {
  364. var child : DisplayObject = stage.getChildAt(i);
  365. if (child.mask == _mask)
  366. child.mask = null;
  367. }
  368. }
  369. }
  370. private function displayObjectAddedToStageHandler(event : Event) : void
  371. {
  372. var displayObject : DisplayObject = event.target as DisplayObject;
  373. if (displayObject.parent == stage)
  374. updateMask();
  375. }
  376. private function displayObjectRemovedFromStageHandler(event : Event) : void
  377. {
  378. var displayObject : DisplayObject = event.target as DisplayObject;
  379. if (_autoResize && displayObject.parent == stage)
  380. displayObject.mask = null;
  381. }
  382. private function getGlobalScaleX() : Number
  383. {
  384. var currentParent : DisplayObjectContainer = parent;
  385. var scale : Number = scaleX;
  386. while(currentParent != stage)
  387. {
  388. scale *= currentParent.scaleX;
  389. currentParent = currentParent.parent;
  390. }
  391. return scale;
  392. }
  393. private function getGlobalScaleY() : Number
  394. {
  395. var currentParent : DisplayObjectContainer = parent;
  396. var scale : Number = scaleY;
  397. while(currentParent != stage)
  398. {
  399. scale *= currentParent.scaleY;
  400. currentParent = currentParent.parent;
  401. }
  402. return scale;
  403. }
  404. }
  405. }