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