Public Functions
DefineEngineFunction(getRootScene , S32 , () , "Get the root <a href="/coding/class/classscene/">Scene</a> object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the Root Scene. Will be 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no root scene is loaded" )
DefineEngineFunction(getScene , Scene * , (U32 sceneId) , (0) , "Get the root <a href="/coding/class/classscene/">Scene</a> object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the Root Scene. Will be 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no root scene is loaded" )
DefineEngineFunction(getSceneCount , S32 , () , "Get the number of active <a href="/coding/class/classscene/">Scene</a> objects that are <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n</a>" "@return The number of active scenes" )
DefineEngineMethod(Scene , addDynamicObject , void , (SceneObject *sceneObj) , (nullAsType< SceneObject * >()) , "Get the root <a href="/coding/class/classscene/">Scene</a> object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the Root Scene. Will be 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no root scene is loaded" )
DefineEngineMethod(Scene , dumpUtilizedAssets , void , () , "Get the root <a href="/coding/class/classscene/">Scene</a> object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the Root Scene. Will be 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no root scene is loaded" )
DefineEngineMethod(Scene , getLevelAsset , const char * , () , "Get the root <a href="/coding/class/classscene/">Scene</a> object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the Root Scene. Will be 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no root scene is loaded" )
DefineEngineMethod(Scene , getObjectsByClass , String , (String className) , ("") , "Get the root <a href="/coding/class/classscene/">Scene</a> object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the Root Scene. Will be 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no root scene is loaded" )
DefineEngineMethod(Scene , getOriginatingFile , const char * , () , "Get the root <a href="/coding/class/classscene/">Scene</a> object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the Root Scene. Will be 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no root scene is loaded" )
DefineEngineMethod(Scene , getRootScene , S32 , () , "Get the root <a href="/coding/class/classscene/">Scene</a> object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the Root Scene. Will be 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no root scene is loaded" )
DefineEngineMethod(Scene , removeDynamicObject , void , (SceneObject *sceneObj) , (nullAsType< SceneObject * >()) , "Get the root <a href="/coding/class/classscene/">Scene</a> object that is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">loaded.\n</a>" "@return The <a href="/coding/file/win32cursorcontroller_8cpp/#win32cursorcontroller_8cpp_1ab38592509822a5f4674447022cc62efe">id</a> of the Root Scene. Will be 0 <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> no root scene is loaded" )
DefineEngineMethod(Scene , save , bool , (const char *fileName) , ("") , "Save out the object <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n</a>" "@param fileName The name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> save to." "@param selectedOnly If true, only objects marked as selected will be saved <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">out.\n</a>" " @param preAppendString Text which will be preprended directly <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the object <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">serialization.\n</a>" " @param True on success, false on failure." )
IMPLEMENT_CO_NETOBJECT_V1(Scene )
1
2#include "Scene.h"
3#include "T3D/assets/LevelAsset.h"
4
5Scene * Scene::smRootScene = nullptr;
6Vector<Scene*> Scene::smSceneList;
7
8IMPLEMENT_CO_NETOBJECT_V1(Scene);
9
10Scene::Scene() :
11 mIsSubScene(false),
12 mParentScene(nullptr),
13 mSceneId(-1),
14 mIsEditing(false),
15 mIsDirty(false),
16 mEditPostFX(0)
17{
18 mGameModeName = StringTable->EmptyString();
19}
20
21Scene::~Scene()
22{
23
24}
25
26void Scene::initPersistFields()
27{
28 Parent::initPersistFields();
29
30 addGroup("Internal");
31 addField("isSubscene", TypeBool, Offset(mIsSubScene, Scene), "", AbstractClassRep::FIELD_HideInInspectors);
32 addField("isEditing", TypeBool, Offset(mIsEditing, Scene), "", AbstractClassRep::FIELD_HideInInspectors);
33 addField("isDirty", TypeBool, Offset(mIsDirty, Scene), "", AbstractClassRep::FIELD_HideInInspectors);
34 endGroup("Internal");
35
36 addGroup("Gameplay");
37 addField("gameModeName", TypeString, Offset(mGameModeName, Scene), "The name of the gamemode that this scene utilizes");
38 endGroup("Gameplay");
39
40 addGroup("PostFX");
41 addProtectedField("EditPostEffects", TypeBool, Offset(mEditPostFX, Scene),
42 &Scene::_editPostEffects, &defaultProtectedGetFn, "Edit Scene's default Post Effects", AbstractClassRep::FieldFlags::FIELD_ComponentInspectors);
43 endGroup("PostFX");
44}
45
46bool Scene::onAdd()
47{
48 if (!Parent::onAdd())
49 return false;
50
51 smSceneList.push_back(this);
52 mSceneId = smSceneList.size() - 1;
53
54 /*if (smRootScene == nullptr)
55 {
56 //we're the first scene, so we're the root. woo!
57 smRootScene = this;
58 }
59 else
60 {
61 mIsSubScene = true;
62 smRootScene->mSubScenes.push_back(this);
63 }*/
64
65 return true;
66}
67
68void Scene::onRemove()
69{
70 Parent::onRemove();
71
72 smSceneList.remove(this);
73 mSceneId = -1;
74
75 /*if (smRootScene == this)
76 {
77 for (U32 i = 0; i < mSubScenes.size(); i++)
78 {
79 mSubScenes[i]->deleteObject();
80 }
81 }
82 else if (smRootScene != nullptr)
83 {
84 for (U32 i = 0; i < mSubScenes.size(); i++)
85 {
86 if(mSubScenes[i]->getId() == getId())
87 smRootScene->mSubScenes.erase(i);
88 }
89 }*/
90}
91
92void Scene::onPostAdd()
93{
94 if (isMethod("onPostAdd"))
95 Con::executef(this, "onPostAdd");
96}
97
98bool Scene::_editPostEffects(void* object, const char* index, const char* data)
99{
100 Scene* scene = static_cast<Scene*>(object);
101
102#ifdef TORQUE_TOOLS
103 if(Con::isFunction("editScenePostEffects"))
104 Con::executef("editScenePostEffects", scene);
105#endif
106
107 return false;
108}
109
110void Scene::addObject(SimObject* object)
111{
112 //Child scene
113 Scene* scene = dynamic_cast<Scene*>(object);
114 if (scene)
115 {
116 //We'll keep these principly separate so they don't get saved into each other
117 mSubScenes.push_back(scene);
118 return;
119 }
120
121 SceneObject* sceneObj = dynamic_cast<SceneObject*>(object);
122 if (sceneObj)
123 {
124 //We'll operate on the presumption that if it's being added via regular parantage means, it's considered permanent
125 mPermanentObjects.push_back(sceneObj);
126 Parent::addObject(object);
127
128 return;
129 }
130
131 //Do it like regular, though we should probably bail if we're trying to add non-scene objects to the scene?
132 Parent::addObject(object);
133}
134
135void Scene::removeObject(SimObject* object)
136{
137 //Child scene
138 Scene* scene = dynamic_cast<Scene*>(object);
139 if (scene)
140 {
141 //We'll keep these principly separate so they don't get saved into each other
142 mSubScenes.remove(scene);
143 return;
144 }
145
146 SceneObject* sceneObj = dynamic_cast<SceneObject*>(object);
147 if (sceneObj)
148 {
149 //We'll operate on the presumption that if it's being added via regular parantage means, it's considered permanent
150
151 mPermanentObjects.remove(sceneObj);
152 Parent::removeObject(object);
153
154 return;
155 }
156
157 Parent::removeObject(object);
158}
159
160void Scene::addDynamicObject(SceneObject* object)
161{
162 mDynamicObjects.push_back(object);
163
164 //Do it like regular, though we should probably bail if we're trying to add non-scene objects to the scene?
165 Parent::addObject(object);
166}
167
168void Scene::removeDynamicObject(SceneObject* object)
169{
170 mDynamicObjects.remove(object);
171
172 //Do it like regular, though we should probably bail if we're trying to add non-scene objects to the scene?
173 Parent::removeObject(object);
174}
175
176void Scene::interpolateTick(F32 delta)
177{
178
179}
180
181void Scene::processTick()
182{
183
184}
185
186void Scene::advanceTime(F32 timeDelta)
187{
188
189}
190
191U32 Scene::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
192{
193 bool ret = Parent::packUpdate(conn, mask, stream);
194
195 return ret;
196}
197
198void Scene::unpackUpdate(NetConnection *conn, BitStream *stream)
199{
200
201}
202
203void Scene::dumpUtilizedAssets()
204{
205 Con::printf("Dumping utilized assets in scene!");
206
207 Vector<StringTableEntry> utilizedAssetsList;
208 for (U32 i = 0; i < mPermanentObjects.size(); i++)
209 {
210 mPermanentObjects[i]->getUtilizedAssets(&utilizedAssetsList);
211 }
212
213 for (U32 i = 0; i < mDynamicObjects.size(); i++)
214 {
215 mDynamicObjects[i]->getUtilizedAssets(&utilizedAssetsList);
216 }
217
218 for (U32 i = 0; i < utilizedAssetsList.size(); i++)
219 {
220 Con::printf("Utilized Asset: %s", utilizedAssetsList[i]);
221 }
222
223 Con::printf("Utilized Asset dump complete!");
224}
225
226StringTableEntry Scene::getOriginatingFile()
227{
228 return getFilename();
229}
230
231StringTableEntry Scene::getLevelAsset()
232{
233 StringTableEntry levelFile = getFilename();
234
235 if (levelFile == StringTable->EmptyString())
236 return StringTable->EmptyString();
237
238 AssetQuery* query = new AssetQuery();
239 query->registerObject();
240
241 S32 foundAssetcount = AssetDatabase.findAssetLooseFile(query, levelFile);
242 if (foundAssetcount == 0)
243 return StringTable->EmptyString();
244 else
245 return query->mAssetList[0];
246}
247
248bool Scene::saveScene(StringTableEntry fileName)
249{
250 //So, we ultimately want to not only save out the level, but also collate all the assets utilized
251 //by the static objects in the scene so we can have those before we parse the level file itself
252 //Useful for preloading or stat tracking
253
254 //First, save the level file
255 if (fileName == StringTable->EmptyString())
256 {
257 fileName = getOriginatingFile();
258 }
259
260 bool saveSuccess = save(fileName);
261
262 if (!saveSuccess)
263 return false;
264
265 //Get the level asset
266 StringTableEntry levelAsset = getLevelAsset();
267 if (levelAsset == StringTable->EmptyString())
268 return saveSuccess;
269
270 LevelAsset* levelAssetDef = AssetDatabase.acquireAsset<LevelAsset>(levelAsset);
271 levelAssetDef->clearAssetDependencyFields("staticObjectAssetDependency");
272
273 //Next, lets build out our
274 Vector<StringTableEntry> utilizedAssetsList;
275 for (U32 i = 0; i < size(); i++)
276 {
277 getUtilizedAssetsFromSceneObject(getObject(i), &utilizedAssetsList);
278 }
279
280 for (U32 i = 0; i < utilizedAssetsList.size(); i++)
281 {
282 char depSlotName[50];
283 dSprintf(depSlotName, sizeof(depSlotName), "%s%d", "staticObjectAssetDependency", i);
284
285 char depValue[255];
286 dSprintf(depValue, sizeof(depValue), "@Asset=%s", utilizedAssetsList[i]);
287
288 levelAssetDef->setDataField(StringTable->insert(depSlotName), NULL, StringTable->insert(depValue));
289
290 }
291
292 saveSuccess = levelAssetDef->saveAsset();
293
294 return saveSuccess;
295}
296
297void Scene::getUtilizedAssetsFromSceneObject(SimObject* object, Vector<StringTableEntry>* usedAssetsList)
298{
299 SceneObject* obj = dynamic_cast<SceneObject*>(object);
300 if(obj)
301 obj->getUtilizedAssets(usedAssetsList);
302
303 SimGroup* group = dynamic_cast<SimGroup*>(object);
304 if (group)
305 {
306 for (U32 c = 0; c < group->size(); c++)
307 {
308 SceneObject* childObj = dynamic_cast<SceneObject*>(group->getObject(c));
309
310 //Recurse down
311 getUtilizedAssetsFromSceneObject(childObj, usedAssetsList);
312 }
313 }
314}
315
316//
317Vector<SceneObject*> Scene::getObjectsByClass(String className, bool checkSubscenes)
318{
319 return Vector<SceneObject*>();
320}
321
322DefineEngineFunction(getScene, Scene*, (U32 sceneId), (0),
323 "Get the root Scene object that is loaded.\n"
324 "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
325{
326 if (Scene::smSceneList.empty() || sceneId >= Scene::smSceneList.size())
327 return nullptr;
328
329 return Scene::smSceneList[sceneId];
330}
331
332DefineEngineFunction(getSceneCount, S32, (),,
333 "Get the number of active Scene objects that are loaded.\n"
334 "@return The number of active scenes")
335{
336 return Scene::smSceneList.size();
337}
338
339DefineEngineFunction(getRootScene, S32, (), ,
340 "Get the root Scene object that is loaded.\n"
341 "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
342{
343 Scene* root = Scene::getRootScene();
344
345 if (root)
346 return root->getId();
347
348 return 0;
349}
350
351DefineEngineMethod(Scene, getRootScene, S32, (),,
352 "Get the root Scene object that is loaded.\n"
353 "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
354{
355 Scene* root = Scene::getRootScene();
356
357 if (root)
358 return root->getId();
359
360 return 0;
361}
362
363DefineEngineMethod(Scene, addDynamicObject, void, (SceneObject* sceneObj), (nullAsType<SceneObject*>()),
364 "Get the root Scene object that is loaded.\n"
365 "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
366{
367 object->addDynamicObject(sceneObj);
368}
369
370DefineEngineMethod(Scene, removeDynamicObject, void, (SceneObject* sceneObj), (nullAsType<SceneObject*>()),
371 "Get the root Scene object that is loaded.\n"
372 "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
373{
374 object->removeDynamicObject(sceneObj);
375}
376
377DefineEngineMethod(Scene, getObjectsByClass, String, (String className), (""),
378 "Get the root Scene object that is loaded.\n"
379 "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
380{
381 if (className == String::EmptyString)
382 return "";
383
384 //return object->getObjectsByClass(className);
385 return "";
386}
387
388DefineEngineMethod(Scene, dumpUtilizedAssets, void, (), ,
389 "Get the root Scene object that is loaded.\n"
390 "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
391{
392 object->dumpUtilizedAssets();
393}
394
395DefineEngineMethod(Scene, getOriginatingFile, const char*, (), ,
396 "Get the root Scene object that is loaded.\n"
397 "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
398{
399 return object->getOriginatingFile();
400}
401
402DefineEngineMethod(Scene, getLevelAsset, const char*, (), ,
403 "Get the root Scene object that is loaded.\n"
404 "@return The id of the Root Scene. Will be 0 if no root scene is loaded")
405{
406 return object->getLevelAsset();
407}
408
409DefineEngineMethod(Scene, save, bool, (const char* fileName), (""),
410 "Save out the object to the given file.\n"
411 "@param fileName The name of the file to save to."
412 "@param selectedOnly If true, only objects marked as selected will be saved out.\n"
413 "@param preAppendString Text which will be preprended directly to the object serialization.\n"
414 "@param True on success, false on failure.")
415{
416 return object->saveScene(StringTable->insert(fileName));
417}
418