1     package
2     {
3        import away3d.cameras.Camera3D;
4        import away3d.containers.View3D;
5        import away3d.core.render.Renderer;
6
7        import flash.events.*;
8
9        import mx.collections.ArrayCollection;
10       import mx.core.UIComponent;
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          protected var blurFilterEnabled:Boolean = true;
44          protected var glowFilterEnabled:Boolean = true;
45          protected var filterAnimationsEnabled:Boolean = true;
46
47          internal function get MyResourceManager():ResourceManager
48          {
49             return myResourceManager;
50          }
51
52          public function get FilterAnimationsEnabled():Boolean
53          {
54             return filterAnimationsEnabled;
55          }
56
57          [Inspectable(defaultValue=filterAnimationsEnabled)]
58          [Bindable]
59          public function set FilterAnimationsEnabled(value:Boolean):void
60          {
61             filterAnimationsEnabled = value;
62             propertyChanged();
63          }
64
65          public function get BlurFilterEnabled():Boolean
66          {
67             return blurFilterEnabled;
68          }
69
70          [Inspectable(defaultValue=blurFilterEnabled)]
71          [Bindable]
72          public function set BlurFilterEnabled(value:Boolean):void
73          {
74             blurFilterEnabled = value;
75             propertyChanged();
76          }
77
78          public function get GlowFilterEnabled():Boolean
79          {
80             return glowFilterEnabled;
81          }
82
83          [Inspectable(defaultValue=glowFilterEnabled)]
84          [Bindable]
85          public function set GlowFilterEnabled(value:Boolean):void
86          {
87             glowFilterEnabled = value;
88             propertyChanged();
89          }
90
91          protected function propertyChanged():void
92          {
93             propertiesDirty = true;
94             invalidateProperties();
95             invalidateDisplayList();
96          }
97
98          public function EngineManager()
99          {
100            super();
101         }
102
103         override protected function measure():void
104         {
105            super.measure();
106
107            // set a bunch of predefined sizes
108            this.measuredMinWidth = MEASURED_MIN_WIDTH;
109            this.measuredMinHeight = MEASURED_MIN_HEIGHT;
110            this.measuredHeight = MEASURED_HEIGHT;
111            this.measuredWidth = MEASURED_WIDTH;
112         }
113
114         override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
115         {
116            super.updateDisplayList(unscaledWidth, unscaledHeight);
117
118            if (view != null)
119            {
120               // resize the viewport to match the new settings
121               view.height = this.height;
122               view.width = this.width;
123            }
124         }
125
126         override protected function commitProperties():void
127         {
128            super.commitProperties();
129
130            if (propertiesDirty)
131            {
132               propertiesDirty = false;
133
134               if (addedToStage)
135               {
136                  applicationManager.shutdown();
137                  applicationManager.startupApplicationManager();
138               }
139            }
140         }
141
142         override protected function createChildren():void
143         {
144            super.createChildren();
145
146            addEventListener(Event.ADDED_TO_STAGE, createChildrenEx);
147            addEventListener(Event.REMOVED_FROM_STAGE, shutdown);
148         }
149
150         protected function shutdown(event:Event):void
151         {
152            if (applicationManager != null)
153               applicationManager.shutdown();
154
155            shutdownAll();
156
157            this.removeChild(view);
158
159            applicationManager = null;
160            addedToStage = false;
161            view = null;
162            cam = null;
163         }
164
165         protected function createChildrenEx(event:Event):void
166         {
167            if (!addedToStage)
168            {
169               cam = new Camera3D();
170
171               view = new View3D({x:250,y:150,camera:cam});
172               view.renderer = Renderer.BASIC;
173               addChild(view);
174               addEventListener(Event.ENTER_FRAME, onEnterFrame);
175
176               // set the initial frame time
177               lastFrame = new Date();
178
179               // load any resources
180               myResourceManager = new ResourceManager();
181               myResourceManager.loadResources();
182
183               // start the application manager
184               applicationManager = new ApplicationManager(this).startupApplicationManager();
185
186               addedToStage = true;
187            }
188         }
189
190         protected function onEnterFrame(event:Event):void
191         {
192            // Calculate the time since the last frame
193            var thisFrame:Date = new Date();
194            var seconds:Number = (thisFrame.getTime() - lastFrame.getTime())/1000.0;
195            lastFrame = thisFrame;
196
197            // sync the baseObjects collection with any BaseObjects created or removed during the 
198            // render loop
199            removeDeletedBaseObjects();
200            insertNewBaseObjects();
201
202            // allow each BaseObject to update itself
203            for each (var baseObject:BaseObject in baseObjects)
204               baseObject.enterFrame(seconds);
205
206            // render the scene
207            view.render();
208         }
209
210         public function addBaseObject(baseObject:BaseObject):void
211         {
212            newBaseObjects.addItem(baseObject);
213         }
214
215         public function removeBaseObject(baseObject:BaseObject):void
216         {
217            removedBaseObjects.addItem(baseObject);
218         }
219
220         public function shutdownAll():void
221         {
222            // don't dispose objects twice
223            for each (var baseObject:BaseObject in baseObjects)
224            {
225               var found:Boolean = false;
226               for each (var removedObject:BaseObject in removedBaseObjects)
227               {
228                  if (removedObject == baseObject)
229                  {
230                     found = true;
231                     break;
232                  }
233               }
234
235               if (!found)
236                  baseObject.shutdown();
237            }
238         }
239
240         protected function insertNewBaseObjects():void
241         {
242            for each (var baseObject:BaseObject in newBaseObjects)
243               baseObjects.addItem(baseObject);
244
245            newBaseObjects.removeAll();
246         }
247
248         protected function removeDeletedBaseObjects():void
249         {
250            for each (var removedObject:BaseObject in removedBaseObjects)
251            {
252               var i:int = 0;
253               for (i = 0; i < baseObjects.length; ++i)
254               {
255                  if (baseObjects.getItemAt(i) == removedObject)
256                  {
257                     baseObjects.removeItemAt(i);
258                     break;
259                  }
260               }
261
262            }
263
264            removedBaseObjects.removeAll();
265         }
266      }
267   }