1     package
2     {
3        import away3d.cameras.Camera3D;
4        import away3d.containers.View3D;
5        import away3d.core.render.Renderer;
6
7        import mx.collections.ArrayCollection;
8        import mx.core.UIComponent;
9
10       import flash.events.*;
11
12       public class EngineManager extends UIComponent
13       {
14          public static const version:String = "1.0.0";
15          protected static const MEASURED_MIN_WIDTH:int = 25;
16          protected static const MEASURED_MIN_HEIGHT:int = 25;
17          protected static const MEASURED_WIDTH:int = 100;
18          protected static const MEASURED_HEIGHT:int = 100;
19
20          // Away3D view
21          internal var view:View3D = null;
22          // Away3D camera
23          internal var cam:Camera3D = null;
24          // a collection of the BaseObjects 
25          protected var baseObjects:ArrayCollection = new ArrayCollection();
26          // a collection where new BaseObjects are placed, to avoid adding items 
27          // to baseObjects while in the baseObjects collection while it is in a loop
28          protected var newBaseObjects:ArrayCollection = new ArrayCollection();
29          // a collection where removed BaseObjects are placed, to avoid removing items 
30          // to baseObjects while in the baseObjects collection while it is in a loop
31          protected var removedBaseObjects:ArrayCollection = new ArrayCollection();
32          // the last frame time 
33          protected var lastFrame:Date;
34          // the application manager
35          protected var applicationManager:ApplicationManager = null;
36          // the resource manager
37          protected var myResourceManager:ResourceManager = null;
38          // true when we have added the Away3D controls
39          protected var addedToStage:Boolean = false;
40          // true if some properties have been modifed
41          protected var propertiesDirty:Boolean = false;
42
43          internal function get MyResourceManager():ResourceManager
44          {
45             return myResourceManager;
46          }
47
48          protected function propertyChanged():void
49          {
50             propertiesDirty = true;
51             invalidateProperties();
52             invalidateDisplayList();
53          }
54
55          public function EngineManager()
56          {
57             super();
58          }
59
60          override protected function measure():void
61          {
62             super.measure();
63
64             // set a bunch of predefined sizes
65             this.measuredMinWidth = MEASURED_MIN_WIDTH;
66             this.measuredMinHeight = MEASURED_MIN_HEIGHT;
67             this.measuredHeight = MEASURED_HEIGHT;
68             this.measuredWidth = MEASURED_WIDTH;
69          }
70
71          override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
72          {
73             super.updateDisplayList(unscaledWidth, unscaledHeight);
74
75             if (view != null)
76             {
77                // resize the viewport to match the new settings
78                view.height = this.height;
79                view.width = this.width;
80             }
81          }
82
83          override protected function commitProperties():void
84          {
85             super.commitProperties();
86
87             if (propertiesDirty)
88             {
89                propertiesDirty = false;
90
91                if (addedToStage)
92                {
93                   applicationManager.shutdown();
94                   applicationManager.startupApplicationManager();
95                }
96             }
97          }
98
99          override protected function createChildren():void
100         {
101            super.createChildren();
102
103            addEventListener(Event.ADDED_TO_STAGE, createChildrenEx);
104            addEventListener(Event.REMOVED_FROM_STAGE, shutdown);
105         }
106
107         protected function shutdown(event:Event):void
108         {
109            if (applicationManager != null)
110               applicationManager.shutdown();
111
112            shutdownAll();
113
114            this.removeChild(view);
115
116            applicationManager = null;
117            addedToStage = false;
118            view = null;
119            cam = null;
120         }
121
122         protected function createChildrenEx(event:Event):void
123         {
124            if (!addedToStage)
125            {
126               cam = new Camera3D();
127
128               view = new View3D({x:250,y:150,camera:cam});
129               view.renderer = Renderer.BASIC;
130               addChild(view);
131               addEventListener(Event.ENTER_FRAME, onEnterFrame);
132
133               // set the initial frame time
134               lastFrame = new Date();
135
136               // load any resources
137               myResourceManager = new ResourceManager();
138               myResourceManager.loadResources();
139
140               // start the application manager
141               applicationManager = new ApplicationManager(this).startupApplicationManager();
142
143               addedToStage = true;
144            }
145         }
146
147         protected function onEnterFrame(event:Event):void
148         {
149            // Calculate the time since the last frame
150            var thisFrame:Date = new Date();
151            var seconds:Number = (thisFrame.getTime() - lastFrame.getTime())/1000.0;
152            lastFrame = thisFrame;
153
154            // sync the baseObjects collection with any BaseObjects created or removed during the 
155            // render loop
156            removeDeletedBaseObjects();
157            insertNewBaseObjects();
158
159            // allow each BaseObject to update itself
160            for each (var baseObject:BaseObject in baseObjects)
161               baseObject.enterFrame(seconds);
162
163            // render the scene
164            view.render();
165         }
166
167         public function addBaseObject(baseObject:BaseObject):void
168         {
169            newBaseObjects.addItem(baseObject);
170         }
171
172         public function removeBaseObject(baseObject:BaseObject):void
173         {
174            removedBaseObjects.addItem(baseObject);
175         }
176
177         public function shutdownAll():void
178         {
179            // don't dispose objects twice
180            for each (var baseObject:BaseObject in baseObjects)
181            {
182               var found:Boolean = false;
183               for each (var removedObject:BaseObject in removedBaseObjects)
184               {
185                  if (removedObject == baseObject)
186                  {
187                     found = true;
188                     break;
189                  }
190               }
191
192               if (!found)
193                  baseObject.shutdown();
194            }
195         }
196
197         protected function insertNewBaseObjects():void
198         {
199            for each (var baseObject:BaseObject in newBaseObjects)
200               baseObjects.addItem(baseObject);
201
202            newBaseObjects.removeAll();
203         }
204
205         protected function removeDeletedBaseObjects():void
206         {
207            for each (var removedObject:BaseObject in removedBaseObjects)
208            {
209               var i:int = 0;
210               for (i = 0; i < baseObjects.length; ++i)
211               {
212                  if (baseObjects.getItemAt(i) == removedObject)
213                  {
214                     baseObjects.removeItemAt(i);
215                     break;
216                  }
217               }
218
219            }
220
221            removedBaseObjects.removeAll();
222         }
223      }
224   }