Scene.cpp 11 KB

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