PageRenderTime 106ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/as3isolib/core/IsoDisplayObject.as

https://bitbucket.org/spautet/as3isolib-starling
ActionScript | 753 lines | 340 code | 133 blank | 280 comment | 38 complexity | 11297047092c0e3099029c03a85527df MD5 | raw file
  1. /*
  2. as3isolib - An open-source ActionScript 3.0 Isometric Library developed to assist
  3. in creating isometrically projected content (such as games and graphics)
  4. targeted for the Flash player platform
  5. http://code.google.com/p/as3isolib/
  6. Copyright (c) 2006 - 3000 J.W.Opitz, All Rights Reserved.
  7. Permission is hereby granted, free of charge, to any person obtaining a copy of
  8. this software and associated documentation files (the "Software"), to deal in
  9. the Software without restriction, including without limitation the rights to
  10. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  11. of the Software, and to permit persons to whom the Software is furnished to do
  12. so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in all
  14. copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  21. SOFTWARE.
  22. */
  23. package as3isolib.core
  24. {
  25. import as3isolib.bounds.IBounds;
  26. import as3isolib.bounds.PrimitiveBounds;
  27. import as3isolib.data.RenderData;
  28. import as3isolib.events.IsoEvent;
  29. import as3isolib.geom.IsoMath;
  30. import as3isolib.geom.Pt;
  31. import flash.display.Sprite;
  32. import starling.Utils;
  33. import flash.display.BitmapData;
  34. import flash.display.DisplayObject;
  35. import flash.geom.Matrix;
  36. import flash.geom.Point;
  37. import flash.geom.Rectangle;
  38. import flash.utils.getDefinitionByName;
  39. import flash.utils.getQualifiedClassName;
  40. use namespace as3isolib_internal;
  41. /**
  42. * IsoDisplayObject is the base class that all primitive and complex isometric display objects should extend.
  43. * Developers should not instantiate this class but rather extend it.
  44. */
  45. public class IsoDisplayObject extends IsoContainer implements IIsoDisplayObject
  46. {
  47. //////////////////////////////////////////////////////////////////
  48. // GET RENDER DATA
  49. //////////////////////////////////////////////////////////////////
  50. private var cachedRenderData:RenderData;
  51. /**
  52. * @inheritDoc
  53. */
  54. public function getRenderData():RenderData
  55. {
  56. var r:Rectangle = mainContainer.getBounds( mainContainer );
  57. if ( isInvalidated || !cachedRenderData )
  58. {
  59. var flag:Boolean = bRenderAsOrphan; //set to allow for rendering regardless of hierarchy
  60. bRenderAsOrphan = true;
  61. render( true );
  62. var bd:BitmapData = new BitmapData( r.width + 1, r.height + 1, true, 0x000000 );
  63. //starling adapt
  64. //bd.draw( mainContainer, new Matrix( 1, 0, 0, 1, -r.left, -r.top ) );
  65. bd.draw( Utils.copyAsBitmapData(mainContainer) , new Matrix( 1, 0, 0, 1, -r.left, -r.top ) );
  66. var renderData:RenderData = new RenderData();
  67. renderData.x = mainContainer.x + r.left;
  68. renderData.y = mainContainer.y + r.top;
  69. renderData.bitmapData = bd;
  70. cachedRenderData = renderData;
  71. bRenderAsOrphan = flag; //set back to original
  72. }
  73. else
  74. {
  75. cachedRenderData.x = mainContainer.x + r.left;
  76. cachedRenderData.y = mainContainer.y + r.top;
  77. }
  78. return cachedRenderData;
  79. }
  80. ////////////////////////////////////////////////////////////////////////
  81. // IS ANIMATED
  82. ////////////////////////////////////////////////////////////////////////
  83. private var _isAnimated:Boolean = false;
  84. /**
  85. * @private
  86. */
  87. public function get isAnimated():Boolean
  88. {
  89. return _isAnimated;
  90. }
  91. /**
  92. * @inheritDoc
  93. */
  94. public function set isAnimated( value:Boolean ):void
  95. {
  96. _isAnimated = value;
  97. //mainContainer.cacheAsBitmap = value;
  98. }
  99. ////////////////////////////////////////////////////////////////////////
  100. // BOUNDS
  101. ////////////////////////////////////////////////////////////////////////
  102. protected var isoBoundsObject:IBounds;
  103. /**
  104. * @inheritDoc
  105. */
  106. public function get isoBounds():IBounds
  107. {
  108. if ( !isoBoundsObject || isInvalidated )
  109. isoBoundsObject = new PrimitiveBounds( this );
  110. return isoBoundsObject;
  111. }
  112. /**
  113. * @inheritDoc
  114. */
  115. public function get screenBounds():Rectangle
  116. {
  117. var screenBounds:Rectangle = mainContainer.getBounds( mainContainer );
  118. screenBounds.x += mainContainer.x;
  119. screenBounds.y += mainContainer.y;
  120. return screenBounds;
  121. }
  122. /**
  123. * @inheritDoc
  124. */
  125. public function getBounds( targetCoordinateSpace:DisplayObject ):Rectangle
  126. {
  127. var rect:Rectangle = screenBounds;
  128. var pt:Point = new Point( rect.x, rect.y );
  129. pt = IIsoContainer( parent ).container.localToGlobal( pt );
  130. pt = targetCoordinateSpace.globalToLocal( pt );
  131. rect.x = pt.x;
  132. rect.y = pt.y;
  133. return rect;
  134. }
  135. public function get inverseOriginX():Number
  136. {
  137. return IsoMath.isoToScreen( new Pt( x + width, y + length, z ) ).x;
  138. }
  139. public function get inverseOriginY():Number
  140. {
  141. return IsoMath.isoToScreen( new Pt( x + width, y + length, z ) ).y;
  142. }
  143. /////////////////////////////////////////////////////////
  144. // POSITION
  145. /////////////////////////////////////////////////////////
  146. ////////////////////////////////////////////////////////////////////////
  147. // X, Y, Z
  148. ////////////////////////////////////////////////////////////////////////
  149. /**
  150. * @inheritDoc
  151. */
  152. public function moveTo( x:Number, y:Number, z:Number ):void
  153. {
  154. this.x = x;
  155. this.y = y;
  156. this.z = z;
  157. }
  158. /**
  159. * @inheritDoc
  160. */
  161. public function moveBy( x:Number, y:Number, z:Number ):void
  162. {
  163. this.x += x;
  164. this.y += y;
  165. this.z += z;
  166. }
  167. ////////////////////////////////////////////////////////////////////////
  168. // USE PRECISE VALUES
  169. ////////////////////////////////////////////////////////////////////////
  170. /**
  171. * Flag indicating if positional and dimensional values are rounded to the nearest whole number or not.
  172. */
  173. public var usePreciseValues:Boolean = false;
  174. ////////////////////////////////////////////////////////////////////////
  175. // X
  176. ////////////////////////////////////////////////////////////////////////
  177. /**
  178. * @private
  179. *
  180. * The positional value based on the isometric x-axis.
  181. */
  182. as3isolib_internal var isoX:Number = 0;
  183. /**
  184. * @private
  185. */
  186. protected var oldX:Number;
  187. /**
  188. * @private
  189. */
  190. //[Bindable( "move" )]
  191. public function get x():Number
  192. {
  193. return isoX;
  194. }
  195. /**
  196. * @inheritDoc
  197. */
  198. public function set x( value:Number ):void
  199. {
  200. if ( !usePreciseValues )
  201. value = Math.round( value );
  202. if ( isoX != value )
  203. {
  204. oldX = isoX;
  205. isoX = value;
  206. invalidatePosition();
  207. if ( autoUpdate )
  208. render();
  209. }
  210. }
  211. /**
  212. * @inheritDoc
  213. */
  214. public function get screenX():Number
  215. {
  216. return IsoMath.isoToScreen( new Pt( x, y, z ) ).x;
  217. }
  218. ////////////////////////////////////////////////////////////////////////
  219. // Y
  220. ////////////////////////////////////////////////////////////////////////
  221. /**
  222. * @private
  223. */
  224. as3isolib_internal var isoY:Number = 0;
  225. /**
  226. * @private
  227. */
  228. protected var oldY:Number;
  229. /**
  230. * @private
  231. */
  232. //[Bindable( "move" )]
  233. public function get y():Number
  234. {
  235. return isoY;
  236. }
  237. /**
  238. * @inheritDoc
  239. */
  240. public function set y( value:Number ):void
  241. {
  242. if ( !usePreciseValues )
  243. value = Math.round( value );
  244. if ( isoY != value )
  245. {
  246. oldY = isoY;
  247. isoY = value;
  248. invalidatePosition();
  249. if ( autoUpdate )
  250. render();
  251. }
  252. }
  253. /**
  254. * @inheritDoc
  255. */
  256. public function get screenY():Number
  257. {
  258. return IsoMath.isoToScreen( new Pt( x, y, z ) ).y
  259. }
  260. ////////////////////////////////////////////////////////////////////////
  261. // Z
  262. ////////////////////////////////////////////////////////////////////////
  263. /**
  264. * @private
  265. */
  266. as3isolib_internal var isoZ:Number = 0;
  267. /**
  268. * @private
  269. */
  270. protected var oldZ:Number;
  271. /**
  272. * @private
  273. */
  274. //[Bindable( "move" )]
  275. public function get z():Number
  276. {
  277. return isoZ;
  278. }
  279. /**
  280. * @inheritDoc
  281. */
  282. public function set z( value:Number ):void
  283. {
  284. if ( !usePreciseValues )
  285. value = Math.round( value );
  286. if ( isoZ != value )
  287. {
  288. oldZ = isoZ;
  289. isoZ = value;
  290. invalidatePosition();
  291. if ( autoUpdate )
  292. render();
  293. }
  294. }
  295. ////////////////////////////////////////////////////////////////////////
  296. // WIDTH
  297. ////////////////////////////////////////////////////////////////////////
  298. private var dist:Number;
  299. public function get distance():Number
  300. {
  301. return dist;
  302. }
  303. public function set distance( value:Number ):void
  304. {
  305. dist = value;
  306. }
  307. /////////////////////////////////////////////////////////
  308. // GEOMETRY
  309. /////////////////////////////////////////////////////////
  310. /**
  311. * @inheritDoc
  312. */
  313. public function setSize( width:Number, length:Number, height:Number ):void
  314. {
  315. this.width = width;
  316. this.length = length;
  317. this.height = height;
  318. }
  319. ////////////////////////////////////////////////////////////////////////
  320. // WIDTH
  321. ////////////////////////////////////////////////////////////////////////
  322. /**
  323. * @private
  324. */
  325. as3isolib_internal var isoWidth:Number = 0;
  326. /**
  327. * @private
  328. */
  329. protected var oldWidth:Number;
  330. /**
  331. * @private
  332. */
  333. //[Bindable( "resize" )]
  334. public function get width():Number
  335. {
  336. return isoWidth;
  337. }
  338. /**
  339. * @inheritDoc
  340. */
  341. public function set width( value:Number ):void
  342. {
  343. if ( !usePreciseValues )
  344. value = Math.round( value );
  345. value = Math.abs( value );
  346. if ( isoWidth != value )
  347. {
  348. oldWidth = isoWidth;
  349. isoWidth = value;
  350. invalidateSize();
  351. if ( autoUpdate )
  352. render();
  353. }
  354. }
  355. ////////////////////////////////////////////////////////////////////////
  356. // LENGTH
  357. ////////////////////////////////////////////////////////////////////////
  358. /**
  359. * @private
  360. */
  361. as3isolib_internal var isoLength:Number = 0;
  362. /**
  363. * @private
  364. */
  365. protected var oldLength:Number;
  366. /**
  367. * @private
  368. */
  369. //[Bindable( "resize" )]
  370. public function get length():Number
  371. {
  372. return isoLength;
  373. }
  374. /**
  375. * @inheritDoc
  376. */
  377. public function set length( value:Number ):void
  378. {
  379. if ( !usePreciseValues )
  380. value = Math.round( value );
  381. value = Math.abs( value );
  382. if ( isoLength != value )
  383. {
  384. oldLength = isoLength;
  385. isoLength = value;
  386. invalidateSize();
  387. if ( autoUpdate )
  388. render();
  389. }
  390. }
  391. ////////////////////////////////////////////////////////////////////////
  392. // HEIGHT
  393. ////////////////////////////////////////////////////////////////////////
  394. /**
  395. * @private
  396. */
  397. as3isolib_internal var isoHeight:Number = 0;
  398. /**
  399. * @private
  400. */
  401. protected var oldHeight:Number;
  402. /**
  403. * @private
  404. */
  405. //[Bindable( "resize" )]
  406. public function get height():Number
  407. {
  408. return isoHeight;
  409. }
  410. /**
  411. * @inheritDoc
  412. */
  413. public function set height( value:Number ):void
  414. {
  415. if ( !usePreciseValues )
  416. value = Math.round( value );
  417. value = Math.abs( value );
  418. if ( isoHeight != value )
  419. {
  420. oldHeight = isoHeight;
  421. isoHeight = value;
  422. invalidateSize();
  423. if ( autoUpdate )
  424. render();
  425. }
  426. }
  427. /////////////////////////////////////////////////////////
  428. // RENDER AS ORPHAN
  429. /////////////////////////////////////////////////////////
  430. private var bRenderAsOrphan:Boolean = false;
  431. /**
  432. * @private
  433. */
  434. public function get renderAsOrphan():Boolean
  435. {
  436. return bRenderAsOrphan;
  437. }
  438. /**
  439. * @inheritDoc
  440. */
  441. public function set renderAsOrphan( value:Boolean ):void
  442. {
  443. bRenderAsOrphan = value;
  444. }
  445. /////////////////////////////////////////////////////////
  446. // RENDERING
  447. /////////////////////////////////////////////////////////
  448. /**
  449. * Flag indicating whether a property change will automatically trigger a render phase.
  450. */
  451. public var autoUpdate:Boolean = false;
  452. /**
  453. * @inheritDoc
  454. */
  455. override protected function renderLogic( recursive:Boolean = true ):void
  456. {
  457. if ( !hasParent && !renderAsOrphan )
  458. return;
  459. if ( bPositionInvalidated )
  460. {
  461. validatePosition();
  462. bPositionInvalidated = false;
  463. }
  464. if ( bSizeInvalidated )
  465. {
  466. validateSize();
  467. bSizeInvalidated = false;
  468. }
  469. //set the flag back for the next time we invalidate the object
  470. bInvalidateEventDispatched = false;
  471. super.renderLogic( recursive );
  472. }
  473. ////////////////////////////////////////////////////////////////////////
  474. // INCLUDE LAYOUT
  475. ////////////////////////////////////////////////////////////////////////
  476. /**
  477. * @inheritDoc
  478. */
  479. /* override public function set includeInLayout (value:Boolean):void
  480. {
  481. super.includeInLayout = value;
  482. if (includeInLayoutChanged)
  483. {
  484. if (!bInvalidateEventDispatched)
  485. {
  486. dispatchEvent(new IsoEvent(IsoEvent.INVALIDATE));
  487. bInvalidateEventDispatched = true;
  488. }
  489. }
  490. } */
  491. /////////////////////////////////////////////////////////
  492. // VALIDATION
  493. /////////////////////////////////////////////////////////
  494. /**
  495. * Takes the given 3D isometric coordinates and positions them in cartesian coordinates relative to the parent container.
  496. */
  497. protected function validatePosition():void
  498. {
  499. var pt:Pt = new Pt( x, y, z );
  500. IsoMath.isoToScreen( pt );
  501. mainContainer.x = pt.x;
  502. mainContainer.y = pt.y;
  503. var evt:IsoEvent = new IsoEvent( IsoEvent.MOVE, true );
  504. evt.propName = "position";
  505. evt.oldValue = { x:oldX, y:oldY, z:oldZ };
  506. evt.newValue = { x:isoX, y:isoY, z:isoZ };
  507. dispatchEvent( evt );
  508. }
  509. /**
  510. * Takes the given 3D isometric sizes and performs the necessary rendering logic.
  511. */
  512. protected function validateSize():void
  513. {
  514. var evt:IsoEvent = new IsoEvent( IsoEvent.RESIZE, true );
  515. evt.propName = "size";
  516. evt.oldValue = { width:oldWidth, length:oldLength, height:oldHeight };
  517. evt.newValue = { width:isoWidth, length:isoLength, height:isoHeight };
  518. dispatchEvent( evt );
  519. }
  520. /////////////////////////////////////////////////////////
  521. // INVALIDATION
  522. /////////////////////////////////////////////////////////
  523. /**
  524. * @private
  525. *
  526. * Flag indicated that an IsoEvent.INVALIDATE has already been dispatched, negating the need to dispatch another.
  527. */
  528. as3isolib_internal var bInvalidateEventDispatched:Boolean = false;
  529. /**
  530. * @private
  531. */
  532. as3isolib_internal var bPositionInvalidated:Boolean = false;
  533. /**
  534. * @private
  535. */
  536. as3isolib_internal var bSizeInvalidated:Boolean = false;
  537. /**
  538. * @inheritDoc
  539. */
  540. public function invalidatePosition():void
  541. {
  542. bPositionInvalidated = true;
  543. if ( !bInvalidateEventDispatched )
  544. {
  545. dispatchEvent( new IsoEvent( IsoEvent.INVALIDATE ) );
  546. bInvalidateEventDispatched = true;
  547. }
  548. }
  549. /**
  550. * @inheritDoc
  551. */
  552. public function invalidateSize():void
  553. {
  554. bSizeInvalidated = true;
  555. if ( !bInvalidateEventDispatched )
  556. {
  557. dispatchEvent( new IsoEvent( IsoEvent.INVALIDATE ) );
  558. bInvalidateEventDispatched = true;
  559. }
  560. }
  561. /**
  562. * @inheritDoc
  563. */
  564. override public function get isInvalidated():Boolean
  565. {
  566. return ( bPositionInvalidated || bSizeInvalidated );
  567. }
  568. /////////////////////////////////////////////////////////
  569. // CREATE CHILDREN
  570. /////////////////////////////////////////////////////////
  571. override protected function createChildren():void
  572. {
  573. super.createChildren();
  574. //starling adapt
  575. //mainContainer.cacheAsBitmap = _isAnimated;
  576. _isAnimated ? mainContainer.flatten() : mainContainer.unflatten();
  577. }
  578. /////////////////////////////////////////////////////////
  579. // CLONE
  580. /////////////////////////////////////////////////////////
  581. /**
  582. * @inheritDoc
  583. */
  584. public function clone():*
  585. {
  586. var CloneClass:Class = getDefinitionByName( getQualifiedClassName( this ) ) as Class;
  587. var cloneInstance:IIsoDisplayObject = new CloneClass();
  588. cloneInstance.setSize( isoWidth, isoLength, isoHeight );
  589. return cloneInstance;
  590. }
  591. /////////////////////////////////////////////////////////
  592. // CONSTRUCTOR
  593. /////////////////////////////////////////////////////////
  594. private function createObjectFromDescriptor( descriptor:Object ):void
  595. {
  596. var prop:String;
  597. for ( prop in descriptor )
  598. {
  599. if ( this.hasOwnProperty( prop ) )
  600. this[ prop ] = descriptor[ prop ];
  601. }
  602. }
  603. /**
  604. * Constructor
  605. */
  606. public function IsoDisplayObject( descriptor:Object = null )
  607. {
  608. super();
  609. if ( descriptor )
  610. createObjectFromDescriptor( descriptor );
  611. }
  612. }
  613. }