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 }