PageRenderTime 70ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/as3/tags/1_7/src/org/papervision3d/utils/InteractiveSceneManager.as

http://papervision3d.googlecode.com/
ActionScript | 675 lines | 270 code | 58 blank | 347 comment | 43 complexity | 9499c676fb1830c24ca169b8c08abbd6 MD5 | raw file
  1. /*
  2. * PAPER ON ERVIS NPAPER ISION PE IS ON PERVI IO APER SI PA
  3. * AP VI ONPA RV IO PA SI PA ER SI NP PE ON AP VI ION AP
  4. * PERVI ON PE VISIO APER IONPA RV IO PA RVIS NP PE IS ONPAPE
  5. * ER NPAPER IS PE ON PE ISIO AP IO PA ER SI NP PER
  6. * RV PA RV SI ERVISI NP ER IO PE VISIO AP VISI PA RV3D
  7. * ______________________________________________________________________
  8. * papervision3d.org ďż˝ blog.papervision3d.org ďż˝ osflash.org/papervision3d
  9. */
  10. /*
  11. * Copyright 2006 (c) Carlos Ulloa Matesanz, noventaynueve.com.
  12. *
  13. * Permission is hereby granted, free of charge, to any person
  14. * obtaining a copy of this software and associated documentation
  15. * files (the "Software"), to deal in the Software without
  16. * restriction, including without limitation the rights to use,
  17. * copy, modify, merge, publish, distribute, sublicense, and/or sell
  18. * copies of the Software, and to permit persons to whom the
  19. * Software is furnished to do so, subject to the following
  20. * conditions:
  21. *
  22. * The above copyright notice and this permission notice shall be
  23. * included in all copies or substantial portions of the Software.
  24. *
  25. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  26. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  27. * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  28. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  29. * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  30. * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  31. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  32. * OTHER DEALINGS IN THE SOFTWARE.
  33. */
  34. /**
  35. * ...
  36. * @author John Grden
  37. * @version 0.1
  38. */
  39. package org.papervision3d.utils
  40. {
  41. import com.blitzagency.xray.logger.XrayLog;
  42. import com.blitzagency.xray.logger.util.ObjectTools;
  43. import flash.display.BitmapData;
  44. import flash.display.Graphics;
  45. import flash.display.Sprite;
  46. import flash.display.BlendMode;
  47. import flash.events.EventDispatcher;
  48. import flash.events.MouseEvent;
  49. import flash.events.Event;
  50. import flash.geom.Point;
  51. import flash.geom.Rectangle;
  52. import flash.utils.Dictionary;
  53. import org.papervision3d.core.geom.Mesh3D;
  54. import org.papervision3d.core.geom.Face3DInstance;
  55. import org.papervision3d.core.geom.Face3D;
  56. import org.papervision3d.core.proto.CameraObject3D;
  57. import org.papervision3d.core.proto.SceneObject3D;
  58. import org.papervision3d.events.InteractiveScene3DEvent;
  59. import org.papervision3d.objects.DisplayObject3D;
  60. import org.papervision3d.utils.InteractiveSprite;
  61. import org.papervision3d.materials.InteractiveMovieMaterial;
  62. import org.papervision3d.materials.MovieMaterial;
  63. import org.papervision3d.materials.BitmapMaterial;
  64. import org.papervision3d.components.as3.utils.CoordinateTools;
  65. import org.papervision3d.core.geom.Vertex2D;
  66. import org.papervision3d.core.geom.Vertex3D;
  67. import org.papervision3d.utils.virtualmouse.VirtualMouse;
  68. /**
  69. * Dispatched when an InteractiveSprite container in the ISM recieves a MouseEvent.CLICK
  70. *
  71. * @eventType org.papervision3d.events.InteractiveScene3DEvent.OBJECT_CLICK
  72. */
  73. [Event(name="mouseClick", type="org.papervision3d.events.InteractiveScene3DEvent")]
  74. /**
  75. * Dispatched when an InteractiveSprite in the ISM receives an MouseEvent.MOUSE_OVER event
  76. *
  77. * @eventType org.papervision3d.events.InteractiveScene3DEvent.OBJECT_OVER
  78. */
  79. [Event(name="mouseOver", type="org.papervision3d.events.InteractiveScene3DEvent")]
  80. /**
  81. * Dispatched when an InteractiveSprite in the ISM receives an MouseEvent.MOUSE_OUT event
  82. *
  83. * @eventType org.papervision3d.events.InteractiveScene3DEvent.OBJECT_OUT
  84. */
  85. [Event(name="mouseOut", type="org.papervision3d.events.InteractiveScene3DEvent")]
  86. /**
  87. * Dispatched when an InteractiveSprite in the ISM receives a MouseEvent.MOUSE_MOVE event
  88. *
  89. * @eventType org.papervision3d.events.InteractiveScene3DEvent.OBJECT_MOVE
  90. */
  91. [Event(name="mouseMove", type="org.papervision3d.events.InteractiveScene3DEvent")]
  92. /**
  93. * Dispatched when an InteractiveSprite in the ISM receives a MouseEvent.MOUSE_PRESS event
  94. *
  95. * @eventType org.papervision3d.events.InteractiveScene3DEvent.OBJECT_PRESS
  96. */
  97. [Event(name="mousePress", type="org.papervision3d.events.InteractiveScene3DEvent")]
  98. /**
  99. * Dispatched when an InteractiveSprite in the ISM receives a MouseEvent.MOUSE_RELEASE event
  100. *
  101. * @eventType org.papervision3d.events.InteractiveScene3DEvent.OBJECT_RELEASE
  102. */
  103. [Event(name="mouseRelease", type="org.papervision3d.events.InteractiveScene3DEvent")]
  104. /**
  105. * Dispatched when the main container of the ISM is clicked
  106. *
  107. * @eventType org.papervision3d.events.InteractiveScene3DEvent.OBJECT_RELEASE_OUTSIDE
  108. */
  109. [Event(name="mouseReleaseOutside", type="org.papervision3d.events.InteractiveScene3DEvent")]
  110. /**
  111. * Dispatched when an InteractiveSprite is created in the ISM for drawing and mouse interaction purposes
  112. *
  113. * @eventType org.papervision3d.events.InteractiveScene3DEvent.OBJECT_ADDED
  114. */
  115. [Event(name="objectAdded", type="org.papervision3d.events.InteractiveScene3DEvent")]
  116. /**
  117. * InteractiveSceneManager handles all the traffic and sub rendering of faces for mouse interactivity within an interactive scene.
  118. * </p>
  119. * <p>
  120. * When you create an InteractiveScene3D object, it automatically creates the InteractiveSceneManager (ISM for short) for you. From there on, any 3D object using an interactive material
  121. * will automatically be given mouse events that are dispatched through the ISM OR the DisplayObject3D itself. The event type is InteractiveScene3DEvent.
  122. * </p>
  123. * <p>
  124. * ISM has 2 modes:
  125. * <ul>
  126. * <li>Object level mode</li>
  127. * <li>Face level mode</li>
  128. * </ul>
  129. * </p>
  130. * <p>
  131. * Object level mode is a bit faster in that sprite containers for the objects are created and then all faces are drawn in that container. You're able to receive mouse
  132. * events based on the objects, but not the contents of the materials used on the objects.
  133. * </P>
  134. * <p>
  135. * For example, if you created a movieclip, put UI components in it and applied it to a DisplayObject3D (DO3D for short), you would not be able to interact with those elements in
  136. * your movieclip. But you WOULD be able to have mouse events on the entire DO3D.
  137. * </p>
  138. * <p>
  139. * Face level mode creates sprite containers for each face of a DO3D that uses an interactive material and gives you the ability to interact with a movieclips objects like UI components.
  140. * </p>
  141. * <p>
  142. * For example, if you created a movieclip, put UI components in it and applied it to a DO3D, you would be able to interact with those elements in
  143. * your movieclip and receive their mouse events like you normally would.
  144. * </p>
  145. * <p>There is one other option for faceLevelMode and that's directly on the DO3D's themselves. This is even heavier in terms of speed, but its there if you need face level access to all DO3D's.
  146. * DisplayObject3D.faceLevelMode is a public static property that when set to true, causes all DO3D's do create their own sprite containers for their faces. The difference between
  147. * this and what the ISM does is that, the ISM only draws faces for DO3D's that have interactive materials - giving you the control you need to dictate what needs interactivity and what doesn't.
  148. * </p>
  149. * @author John Grden
  150. *
  151. */
  152. public class InteractiveSceneManager extends EventDispatcher
  153. {
  154. /**
  155. * The ISM, by default, uses a BlendMode.ERASE to hide the hit area of the drawn face.
  156. * Setting this to true will show the drawn faces and give you the ability to add whatever type effects/filters you want
  157. * over your scene and 3D objects.
  158. * </p>
  159. * <p>
  160. * When set to true, you should set DEFAULT_SPRITE_ALPHA, DEFAULT_FILL_ALPHA and DEFAULT_FILL_COLOR as these will dictate how the faces are drawn over the scene.
  161. * </p>
  162. * <p>
  163. * Setting DEFAULT_SPRITE_ALPHA = 0 will give you the same effect as the blendmode, but only slower. A combination of DEFAULT_SPRITE_ALPHA and DEFAULT_FILL_ALPHA along with filters
  164. * can really give you some nice visual affects over your scene for your 3D objects.
  165. */
  166. public static var SHOW_DRAWN_FACES :Boolean = false;
  167. /**
  168. * Alpha value 0-1 of the sprite container created for DO3D's or Face3D containers in the ISM
  169. */
  170. public static var DEFAULT_SPRITE_ALPHA :Number = 1;
  171. /**
  172. * Alpha value 0-1 of the drawn face
  173. */
  174. public static var DEFAULT_FILL_ALPHA :Number = 1;
  175. /**
  176. * Color used to draw the face in the sprite container
  177. */
  178. public static var DEFAULT_FILL_COLOR :Number = 0xFFFFFF;
  179. /**
  180. * Color used for the line drawn around the face
  181. */
  182. public static var DEFAULT_LINE_COLOR :Number = -1;
  183. /**
  184. * Line size of the line drawn around the face
  185. */
  186. public static var DEFAULT_LINE_SIZE :Number = 1;
  187. /**
  188. * Alpha value 0-1 of the line drawn around the face
  189. */
  190. public static var DEFAULT_LINE_ALPHA :Number = 1;
  191. /**
  192. * MOUSE_IS_DOWN is a quick static property to check and is maintained by the ISM
  193. */
  194. public static var MOUSE_IS_DOWN :Boolean = false;
  195. /**
  196. * When set to true, the hand cursor is shown over objects that have mouse events assigned to it.
  197. */
  198. public var buttonMode :Boolean = false;
  199. /**
  200. * This allows objects faces to have their own containers. When set to true
  201. * and the DisplayObject3D.faceLevelMode = false, the faces will be drawn in ISM's layer of containers
  202. */
  203. public var faceLevelMode :Boolean = false;
  204. private var _mouseInteractionMode :Boolean = false;
  205. /**
  206. * @private
  207. * @param value
  208. *
  209. */
  210. public function set mouseInteractionMode(value:Boolean):void
  211. {
  212. _mouseInteractionMode = value;
  213. allowDraw = !value;
  214. if( value ) container.stage.addEventListener(MouseEvent.MOUSE_MOVE, handleStageMouseMove);
  215. if( !value ) container.stage.removeEventListener(MouseEvent.MOUSE_MOVE, handleStageMouseMove);
  216. }
  217. /**
  218. * If the user sets this to true, then we monitor the allowDraw flag via mouse interaction and we only draw the faces if there's mouse interaction with the scene.
  219. * This is meant to maximize CPU for interactivity
  220. * If set to true, then leave SHOW_DRAWN_FACES set to false to avoid odd drawings over the 3D scene
  221. */
  222. public function get mouseInteractionMode():Boolean { return _mouseInteractionMode; }
  223. /**
  224. * A dictionary where the InteractiveContainerData objects are stored for DO3D's or Face3D objects. You can get to a DO3D or Face3D's InteractiveContainerDate object
  225. * with:
  226. * </P>
  227. * <p>
  228. * <code>
  229. * var icd:InteractiveContainerData = faceDictionary[do3dInstance];
  230. * </code>
  231. * </p>
  232. */
  233. public var faceDictionary :Dictionary = new Dictionary();
  234. /**
  235. * A dictionary where the DO3D's and Face3D objects are stored. You can get to a DO3D or Face3D by supplying the sprite container reference:
  236. * </P>
  237. * <p>
  238. * <code>
  239. * var do3d:DisplayObject3D = containerDictionary[spriteInstance];
  240. * or
  241. * var face3d:Face3D = containerDictionary[spriteInstance];
  242. * </code>
  243. * </p>
  244. */
  245. public var containerDictionary :Dictionary = new Dictionary();
  246. /**
  247. * Main container for ISM to create the sub InteractiveSprite containers for the faces and DO3D objects passed in during the render loop
  248. */
  249. public var container :Sprite = new InteractiveSprite();
  250. /**
  251. * InteractiveScene3D instance, usually passed in by the constructor
  252. */
  253. public var scene :SceneObject3D;
  254. /**
  255. * Mouse3D gives you a pointer in 3D space that orients itself to a face your mouse is currently over. It copy's the transform information of the face giving you the ability to do something in 3D at that same location
  256. */
  257. public var mouse3D :Mouse3D = new Mouse3D();
  258. /**
  259. * VirtualMouse is used with faceLevelMode of ISM or DO3D's. Its a virtual mouse that causes the objects in your materials movieclip containers to fire off their mouse events such as click, over, out, release, press etc
  260. * </p>
  261. * <p>
  262. * Using these events requires you only to do what you normally do - establish listeners with your objects like you normally would, and you'll receive them!
  263. */
  264. public var virtualMouse :VirtualMouse = new VirtualMouse();
  265. /**
  266. * @private
  267. */
  268. public function set enableMouse(value:Boolean):void
  269. {
  270. Mouse3D.enabled = value;
  271. }
  272. /**
  273. * Boolean value that sets Mouse3D.enabled = true
  274. */
  275. public function get enableMouse():Boolean { return Mouse3D.enabled; }
  276. /**
  277. * Setting to true will show output via trace window in IDE or Xray's output
  278. */
  279. public var debug :Boolean = false;
  280. /**
  281. * @private
  282. * Boolean flag used internally to turn off ISM drawing when it's not needed in the render loop. This only applies if mouseInteractionMode is set to true.
  283. */
  284. protected var allowDraw :Boolean = true;
  285. /**
  286. * @private
  287. * When mouseInteractionMode is turned on, this tells ISM's MouseOver event to dispatch a click event
  288. */
  289. protected var evaluateClick :Boolean = false;
  290. /**
  291. * @private
  292. */
  293. protected var log :XrayLog = new XrayLog();
  294. /**
  295. *
  296. * @param p_scene The InteractiveScene3D object instance. This is passed in via the constructor of InteractiveScene3D when you create a new one.
  297. * @return
  298. */
  299. public function InteractiveSceneManager(p_scene:SceneObject3D):void
  300. {
  301. container.addEventListener(Event.ADDED_TO_STAGE, handleAddedToStage);
  302. scene = p_scene;
  303. scene.container.parent.addChild(container);
  304. container.x = scene.container.x;
  305. container.y = scene.container.y;
  306. enableMouse = false;
  307. }
  308. /**
  309. * Convenience method to help set the default parameters of the ISM.
  310. * This gives you faceLevelMode and buttonMode interaction on your scene. Setting faceLevelMode = false reverts ISM to Object level mode
  311. * @return
  312. */
  313. public function setInteractivityDefaults():void
  314. {
  315. SHOW_DRAWN_FACES = false;
  316. DEFAULT_SPRITE_ALPHA = 1;
  317. DEFAULT_FILL_ALPHA = 1;
  318. BitmapMaterial.AUTO_MIP_MAPPING = false;
  319. DisplayObject3D.faceLevelMode = false;
  320. buttonMode = true;
  321. faceLevelMode = true;
  322. mouseInteractionMode = false;
  323. }
  324. /**
  325. * Adds a DisplayObject3D or Face3D object to the ISM
  326. * @param container3d
  327. * @return
  328. */
  329. public function addInteractiveObject(container3d:Object):void
  330. {
  331. if(faceDictionary[container3d] == null)
  332. {
  333. var icd:InteractiveContainerData = faceDictionary[container3d] = new InteractiveContainerData(container3d);
  334. // for reverse lookup when you have the sprite container
  335. containerDictionary[icd.container] = container3d;
  336. // add mouse events to be captured and passed along
  337. var icdContainer:InteractiveSprite = icd.container;
  338. icdContainer.addEventListener(MouseEvent.MOUSE_DOWN, handleMousePress);
  339. icdContainer.addEventListener(MouseEvent.MOUSE_UP, handleMouseRelease);
  340. icdContainer.addEventListener(MouseEvent.CLICK, handleMouseClick);
  341. icdContainer.addEventListener(MouseEvent.MOUSE_OVER, handleMouseOver);
  342. icdContainer.addEventListener(MouseEvent.MOUSE_OUT, handleMouseOut);
  343. icdContainer.addEventListener(MouseEvent.MOUSE_MOVE, handleMouseMove);
  344. icdContainer.buttonMode = buttonMode;
  345. if( !SHOW_DRAWN_FACES && !DisplayObject3D.faceLevelMode ) icdContainer.blendMode = BlendMode.ERASE;
  346. // need to let virtualMouse know what to ignore
  347. virtualMouse.ignore(icdContainer);
  348. // let others know we've added a container
  349. dispatchEvent(new InteractiveScene3DEvent(InteractiveScene3DEvent.OBJECT_ADDED, null, icdContainer));
  350. if(debug) log.debug("addDisplayObject id", container3d.id, container3d.name, DEFAULT_SPRITE_ALPHA);
  351. }
  352. }
  353. /**
  354. * drawFace is called from each of the interactive materials in the render loop. It either receives DisplayObject3D or a Face3D object reference. It then creates a container
  355. * if one doesn't exist. Then, it draws the face into the designated container which is an InteractiveSprite.
  356. *
  357. * @param container3d
  358. * @param face3d
  359. * @param x0
  360. * @param x1
  361. * @param x2
  362. * @param y0
  363. * @param y1
  364. * @param y2
  365. * @return
  366. */
  367. public function drawFace(container3d:DisplayObject3D, face3d:Face3D, x0:Number, x1:Number, x2:Number, y0:Number, y1:Number, y2:Number ):void
  368. {
  369. // if we're face level on this DO3D, then we switch to the face3D object
  370. var container:Object = container3d;
  371. if(faceLevelMode || DisplayObject3D.faceLevelMode) container = face3d;
  372. // add to the dictionary if not added already
  373. if(faceDictionary[container] == null) addInteractiveObject(container);
  374. if( allowDraw && !DisplayObject3D.faceLevelMode )
  375. {
  376. var drawingContainer:InteractiveContainerData = faceDictionary[container];
  377. var iContainer:InteractiveSprite = drawingContainer.container;
  378. var graphics:Graphics = iContainer.graphics;
  379. iContainer.x0 = x0;
  380. iContainer.x1 = x1;
  381. iContainer.x2 = x2;
  382. iContainer.y0 = y0;
  383. iContainer.y1 = y1;
  384. iContainer.y2 = y2;
  385. graphics.beginFill(drawingContainer.color, drawingContainer.fillAlpha);
  386. if( drawingContainer.lineColor != -1 && SHOW_DRAWN_FACES ) graphics.lineStyle(drawingContainer.lineSize, drawingContainer.lineColor, drawingContainer.lineAlpha);
  387. graphics.moveTo( x0, y0 );
  388. graphics.lineTo( x1, y1 );
  389. graphics.lineTo( x2, y2 );
  390. graphics.endFill();
  391. drawingContainer.isDrawn = true;
  392. }
  393. }
  394. /*
  395. public function getSprite(container3d:DisplayObject3D):InteractiveSprite
  396. {
  397. return InteractiveContainerData(faceDictionary[container3d]).container;
  398. }
  399. public function getDisplayObject3D(sprite:InteractiveSprite):DisplayObject3D
  400. {
  401. return DisplayObject3D(containerDictionary[sprite]);
  402. }
  403. */
  404. /**
  405. * When called, aligns the ISM's container with the scene's container to make sure faces drawn in the ISM are aligned with the scene perfectly
  406. *
  407. */
  408. public function resizeStage():void
  409. {
  410. container.x = scene.container.x;
  411. container.y = scene.container.y;
  412. }
  413. /**
  414. * When called, all faces are cleared and the isDrawn flag is reset on the InteractiveContainerData objects to ready them for the next loop.
  415. *
  416. * This is called via InteractiveScene3D before the render.
  417. *
  418. */
  419. public function resetFaces():void
  420. {
  421. // clear all triangles/faces that have been drawn
  422. for each( var item:InteractiveContainerData in faceDictionary)
  423. {
  424. item.container.graphics.clear();
  425. item.sort = item.isDrawn;
  426. item.isDrawn = false;
  427. }
  428. // make sure the sprite is aligned with the scene's canvas
  429. resizeStage();
  430. }
  431. /**
  432. * After the render loop is completed, InteractiveScene3D calls this method to sort the interactive scene objects. If nothing was drawn into a container, it's completely
  433. * ignored at this level as well.
  434. *
  435. */
  436. public function sortObjects():void
  437. {
  438. // called from the scene after the render loop is completed
  439. var sort:Array = [];
  440. for each( var item:InteractiveContainerData in faceDictionary)
  441. {
  442. if(!item.sort) continue;
  443. var distance:Number = item.face3d == null ? item.screenZ : item.face3d.face3DInstance.screenZ;
  444. sort.push({container:item.container, distance:distance});
  445. }
  446. sort.sortOn("distance", Array.DESCENDING | Array.NUMERIC);
  447. for(var i:uint=0;i<sort.length;i++) container.addChild(sort[i].container);
  448. // after the render loop is complete, and we've sorted, we reset the allowDraw flag
  449. if( mouseInteractionMode ) allowDraw = false;
  450. }
  451. /**
  452. * @private
  453. * @param e
  454. *
  455. */
  456. protected function handleAddedToStage(e:Event):void
  457. {
  458. container.stage.addEventListener (Event.RESIZE, handleResize);
  459. container.stage.addEventListener(MouseEvent.MOUSE_UP, handleReleaseOutside);
  460. virtualMouse.stage = container.stage;
  461. }
  462. /**
  463. * Handles the MOUSE_DOWN event on an InteractiveSprite container
  464. * @param e
  465. *
  466. */
  467. protected function handleMousePress(e:MouseEvent):void
  468. {
  469. MOUSE_IS_DOWN = true;
  470. if( virtualMouse ) virtualMouse.press();
  471. dispatchObjectEvent(InteractiveScene3DEvent.OBJECT_PRESS, Sprite(e.currentTarget));
  472. }
  473. /**
  474. * Handles the MOUSE_UP event on an InteractiveSprite container
  475. * @param e
  476. *
  477. */
  478. protected function handleMouseRelease(e:MouseEvent):void
  479. {
  480. MOUSE_IS_DOWN = false;
  481. if( virtualMouse ) virtualMouse.release();
  482. dispatchObjectEvent(InteractiveScene3DEvent.OBJECT_RELEASE, Sprite(e.currentTarget));
  483. }
  484. /**
  485. * Handles the MOUSE_CLICK event on an InteractiveSprite container
  486. * @param e
  487. *
  488. */
  489. protected function handleMouseClick(e:MouseEvent):void
  490. {
  491. dispatchObjectEvent(InteractiveScene3DEvent.OBJECT_CLICK, Sprite(e.currentTarget));
  492. }
  493. /**
  494. * Handles the MOUSE_OVER event on an InteractiveSprite container
  495. * @param e
  496. *
  497. */
  498. protected function handleMouseOver(e:MouseEvent):void
  499. {
  500. var eventType:String
  501. eventType = !evaluateClick || !mouseInteractionMode ? InteractiveScene3DEvent.OBJECT_OVER : InteractiveScene3DEvent.OBJECT_CLICK;
  502. evaluateClick = false;
  503. if( virtualMouse && eventType == InteractiveScene3DEvent.OBJECT_CLICK ) virtualMouse.click()
  504. dispatchObjectEvent(eventType, Sprite(e.currentTarget));
  505. }
  506. /**
  507. * Handles the MOUSE_OUT event on an InteractiveSprite container
  508. * @param e
  509. *
  510. */
  511. protected function handleMouseOut(e:MouseEvent):void
  512. {
  513. if( VirtualMouse && ( faceLevelMode || DisplayObject3D.faceLevelMode ))
  514. {
  515. try
  516. {
  517. var face3d:Face3D = containerDictionary[e.currentTarget];
  518. var p:Object = InteractiveUtils.getMapCoordAtPoint(face3d, container.mouseX, container.mouseY);
  519. var mat:InteractiveMovieMaterial = InteractiveMovieMaterial(face3d.face3DInstance.instance.material);
  520. var rect:Rectangle = new Rectangle(0, 0, mat.movie.width, mat.movie.height);
  521. var contains:Boolean = rect.contains(p.x, p.y);
  522. if (!contains) virtualMouse.exitContainer();
  523. }catch(err:Error)
  524. {
  525. log.error("material type is not Interactive. If you're using a Collada object, you may have to reassign the material to the object after the collada scene is loaded", err.message);
  526. }
  527. }
  528. dispatchObjectEvent(InteractiveScene3DEvent.OBJECT_OUT, Sprite(e.currentTarget));
  529. }
  530. /**
  531. * Handles the MOUSE_MOVE event on an InteractiveSprite container
  532. * @param e
  533. *
  534. */
  535. protected function handleMouseMove(e:MouseEvent):void
  536. {
  537. var point:Object;
  538. if( VirtualMouse && ( faceLevelMode || DisplayObject3D.faceLevelMode ))
  539. {
  540. // need the face3d for the coordinate conversion
  541. var face3d:Face3D = containerDictionary[e.currentTarget];
  542. // get 2D coordinates
  543. point = InteractiveUtils.getMapCoordAtPoint(face3d, container.mouseX, container.mouseY);
  544. //log.debug("material type", ObjectTools.getImmediateClassPath(face3d.face3DInstance.instance.material), face3d.face3DInstance.instance.material is InteractiveMovieMaterial);
  545. try
  546. {
  547. // locate the material's movie
  548. var mat:MovieMaterial = face3d.face3DInstance.instance.material as MovieMaterial;
  549. // set the location where the calcs should be performed
  550. virtualMouse.container = mat.movie as Sprite;
  551. // update virtual mouse so it can test
  552. if( virtualMouse.container ) virtualMouse.setLocation(point.x, point.y);
  553. }catch(err:Error)
  554. {
  555. log.error("material type is not Inter active. If you're using a Collada object, you may have to reassign the material to the object after the collada scene is loaded", err.message);
  556. }
  557. }
  558. dispatchObjectEvent(InteractiveScene3DEvent.OBJECT_MOVE, Sprite(e.currentTarget));
  559. if( Mouse3D.enabled && ( faceLevelMode || DisplayObject3D.faceLevelMode ) )
  560. {
  561. mouse3D.updatePosition(Face3D(containerDictionary[e.currentTarget]), e.currentTarget as Sprite);
  562. }
  563. }
  564. /**
  565. * Handles mouse clicks on the stage. If so, we release a releaseOutside event
  566. * @param e
  567. *
  568. */
  569. protected function handleReleaseOutside(e:MouseEvent):void
  570. {
  571. if(debug) log.debug("releaseOutside");
  572. dispatchEvent(new InteractiveScene3DEvent(InteractiveScene3DEvent.OBJECT_RELEASE_OUTSIDE));
  573. MOUSE_IS_DOWN = false;
  574. evaluateClick = true
  575. allowDraw = true;
  576. }
  577. /**
  578. * When ISM is in mouseInteractionMode, we capture mouse move events from the stage to trigger a draw
  579. * @param e
  580. *
  581. */
  582. protected function handleStageMouseMove(e:MouseEvent):void
  583. {
  584. allowDraw = true;
  585. }
  586. /**
  587. * @private
  588. * @param event
  589. * @param currentTarget
  590. *
  591. */
  592. protected function dispatchObjectEvent(event:String, currentTarget:Sprite):void
  593. {
  594. if(debug) log.debug(event, DisplayObject3D(containerDictionary[currentTarget]).name);
  595. if(containerDictionary[currentTarget] is DisplayObject3D)
  596. {
  597. containerDictionary[currentTarget].dispatchEvent(new InteractiveScene3DEvent(event, containerDictionary[currentTarget], InteractiveSprite(currentTarget)));
  598. dispatchEvent(new InteractiveScene3DEvent(event, containerDictionary[currentTarget], InteractiveSprite(currentTarget), null, null));
  599. }else if(containerDictionary[currentTarget] is Face3D)
  600. {
  601. var face3d:Face3D = containerDictionary[currentTarget];
  602. var face3dContainer:InteractiveContainerData = faceDictionary[face3d];
  603. dispatchEvent(new InteractiveScene3DEvent(event, null, InteractiveSprite(currentTarget), face3d, face3dContainer));
  604. }
  605. }
  606. /**
  607. * @private
  608. * @param e
  609. *
  610. */
  611. protected function handleResize(e:Event):void
  612. {
  613. resizeStage();
  614. }
  615. }
  616. }