package away3d.containers { import away3d.arcane; import away3d.core.base.*; import away3d.core.math.*; import away3d.core.render.*; import away3d.core.traverse.*; import away3d.core.utils.*; import away3d.events.*; import flash.display.*; import flash.events.*; import flash.utils.*; use namespace arcane; /** * The root container of all 3d objects in a single scene */ public class Scene3D extends ObjectContainer3D { /** @private */ arcane function internalRemoveView(view:View3D):void { view.removeEventListener(ViewEvent.UPDATE_SCENE, onUpdate); } /** @private */ arcane function internalAddView(view:View3D):void { view.addEventListener(ViewEvent.UPDATE_SCENE, onUpdate); } private var _view:View3D; private var _currentView:View3D; private var _mesh:Mesh; private var _time:int; private var _autoUpdate:Boolean; private var _projtraverser:ProjectionTraverser = new ProjectionTraverser(); private var _sessiontraverser:SessionTraverser = new SessionTraverser(); private var _lighttraverser:LightTraverser = new LightTraverser(); private function onUpdate(event:ViewEvent):void { if (autoUpdate) { if (_currentView && _currentView != event.view) Debug.warning("Multiple views detected! Should consider switching to manual update"); _currentView = event.view; update(); } } public var viewDictionary:Dictionary = new Dictionary(true); /** * Traverser object for all custom tick() methods * * @see away3d.core.base.Object3D#tick() */ public var tickTraverser:TickTraverser = new TickTraverser(); /** * Library of updated 3d objects in the scene. */ public var updatedObjects:Dictionary; /** * Library of updated sessions in the scene. */ public var updatedSessions:Dictionary; /** * Library of all meshes in the scene. */ public var meshes:Dictionary; /** * Defines whether scene events are automatically triggered by the view, or manually by updateScene() */ public var autoUpdate:Boolean; /** * Interface for physics (not implemented) */ public var physics:IPhysicsScene; /** * @inheritDoc */ public override function get sceneTransform():MatrixAway3D { if (_transformDirty) _sceneTransformDirty = true; if (_sceneTransformDirty) notifySceneTransformChange(); return transform; } /** * Creates a new Scene3D object * * @param ...initarray An array of 3d objects to be added as children of the scene on instatiation. Can contain an initialisation object */ public function Scene3D(...initarray) { var init:Object; var childarray:Array = []; for each (var object:Object in initarray) if (object is Object3D) childarray.push(object); else init = object; //force ownCanvas and ownLights if (init) { init.ownCanvas = true; init.ownLights = true; } else { init = {ownCanvas:true, ownLights:true}; } super(init); autoUpdate = ini.getBoolean("autoUpdate", true); var ph:Object = ini.getObject("physics"); if (ph is IPhysicsScene) physics = ph as IPhysicsScene; if (ph is Boolean) if (ph == true) physics = null; // new RobPhysicsEngine(); if (ph is Object) physics = null; // new RobPhysicsEngine(ph); // ph - init object for each (var child:Object3D in childarray) addChild(child); } /** * Calling manually will update scene specific variables */ public function update():void { //clear updated objects updatedObjects = new Dictionary(true); //clear updated sessions updatedSessions = new Dictionary(true); //traverse lights traverse(_lighttraverser); //execute projection traverser on each view for each(_view in viewDictionary) { //clear meshes meshes = new Dictionary(true); //clear camera view transforms _view.camera.clearViewTransforms(); //clear blockers _view.blockerarray.clip = _view.clip; //traverse scene _projtraverser.view = _view; traverse(_projtraverser); _time = getTimer(); //update materials in meshes for each (_mesh in meshes) { //update node materials _mesh.updateMaterials(_mesh, _view); //update geometry materials _mesh.geometry.updateMaterials(_mesh, _view); //update elements _mesh.geometry.updateElements(_time); } } //traverse sessions traverse(_sessiontraverser); } /** * Calling manually will update 3d objects that execute updates on their tick() methods. * Uses the TickTraverser to traverse all tick methods in the scene. * * @see away3d.core.base.Object3D#tick() * @see away3d.core.traverse.TickTraverser */ public function updateTime(time:int = -1):void { //set current time if (time == -1) time = getTimer(); //traverser scene ticks tickTraverser.now = time; traverse(tickTraverser); if (physics != null) physics.updateTime(time); } } }