Scene.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. //
  2. // Urho3D Engine
  3. // Copyright (c) 2008-2011 Lasse Öörni
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to deal
  7. // in the Software without restriction, including without limitation the rights
  8. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. // copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. // THE SOFTWARE.
  22. //
  23. #include "Precompiled.h"
  24. #include "Component.h"
  25. #include "Context.h"
  26. #include "CoreEvents.h"
  27. #include "File.h"
  28. #include "Log.h"
  29. #include "PackageFile.h"
  30. #include "Profiler.h"
  31. #include "Scene.h"
  32. #include "SceneEvents.h"
  33. #include "XMLFile.h"
  34. static const int ASYNC_LOAD_MIN_FPS = 50;
  35. static const int ASYNC_LOAD_MAX_MSEC = (int)(1000.0f / ASYNC_LOAD_MIN_FPS);
  36. OBJECTTYPESTATIC(Scene);
  37. Scene::Scene(Context* context) :
  38. Node(context),
  39. networkMode_(NM_NONETWORK),
  40. nonLocalNodeID_(FIRST_NONLOCAL_ID),
  41. nonLocalComponentID_(FIRST_NONLOCAL_ID),
  42. localNodeID_(FIRST_LOCAL_ID),
  43. localComponentID_(FIRST_LOCAL_ID),
  44. checksum_(0),
  45. active_(true),
  46. asyncLoading_(false)
  47. {
  48. // Assign an ID to self so that nodes can refer to this node as a parent
  49. SetID(GetFreeunsigned(false));
  50. NodeAdded(this);
  51. SubscribeToEvent(E_UPDATE, HANDLER(Scene, HandleUpdate));
  52. }
  53. Scene::~Scene()
  54. {
  55. // Remove scene reference and owner from all nodes that still exist
  56. for (Map<unsigned, Node*>::Iterator i = allNodes_.Begin(); i != allNodes_.End(); ++i)
  57. {
  58. i->second_->SetScene(0);
  59. i->second_->SetOwner(0);
  60. }
  61. }
  62. void Scene::RegisterObject(Context* context)
  63. {
  64. context->RegisterFactory<Scene>();
  65. context->CopyBaseAttributes<Node, Scene>();
  66. ATTRIBUTE(Scene, VAR_INT, "Next Non-Local Node ID", nonLocalNodeID_, FIRST_NONLOCAL_ID);
  67. ATTRIBUTE(Scene, VAR_INT, "Next Non-Local Component ID", nonLocalComponentID_, FIRST_NONLOCAL_ID);
  68. ATTRIBUTE(Scene, VAR_INT, "Next Local Node ID", localNodeID_, FIRST_LOCAL_ID);
  69. ATTRIBUTE(Scene, VAR_INT, "Next Local Component ID", localComponentID_, FIRST_LOCAL_ID);
  70. }
  71. bool Scene::Load(Deserializer& source)
  72. {
  73. StopAsyncLoading();
  74. // Check ID
  75. if (source.ReadID() != "USCN")
  76. {
  77. LOGERROR(source.GetName() + " is not a valid scene file");
  78. return false;
  79. }
  80. // Load the whole scene, then perform post-load if successfully loaded
  81. if (Node::Load(source))
  82. {
  83. FinishLoading(&source);
  84. return true;
  85. }
  86. else
  87. return false;
  88. }
  89. bool Scene::Save(Serializer& dest)
  90. {
  91. // Write ID first
  92. if (!dest.WriteID("USCN"))
  93. {
  94. LOGERROR("Could not save scene, writing to stream failed");
  95. return false;
  96. }
  97. return Node::Save(dest);
  98. }
  99. bool Scene::LoadXML(const XMLElement& source)
  100. {
  101. StopAsyncLoading();
  102. // Load the whole scene, then perform post-load if successfully loaded
  103. // Note: the scene filename and checksum can not be set, as we only used an XML element
  104. if (Node::LoadXML(source))
  105. {
  106. FinishLoading(0);
  107. return true;
  108. }
  109. else
  110. return false;
  111. }
  112. void Scene::Update(float timeStep)
  113. {
  114. if (asyncLoading_)
  115. {
  116. UpdateAsyncLoading();
  117. return;
  118. }
  119. PROFILE(UpdateScene);
  120. using namespace SceneUpdate;
  121. VariantMap eventData;
  122. eventData[P_SCENE] = (void*)this;
  123. eventData[P_TIMESTEP] = timeStep;
  124. // Update variable timestep logic
  125. SendEvent(E_SCENEUPDATE, eventData);
  126. // Update scene subsystems. If a physics world is present, it will be updated, triggering fixed timestep logic updates
  127. SendEvent(E_SCENESUBSYSTEMUPDATE, eventData);
  128. // Post-update variable timestep logic
  129. SendEvent(E_SCENEPOSTUPDATE, eventData);
  130. }
  131. bool Scene::LoadXML(Deserializer& source)
  132. {
  133. StopAsyncLoading();
  134. SharedPtr<XMLFile> xml(new XMLFile(context_));
  135. if (!xml->Load(source))
  136. return false;
  137. // Load the whole scene, then perform post-load if successfully loaded
  138. if (Node::LoadXML(xml->GetRootElement()))
  139. {
  140. FinishLoading(&source);
  141. return true;
  142. }
  143. else
  144. return false;
  145. }
  146. bool Scene::SaveXML(Serializer& dest)
  147. {
  148. SharedPtr<XMLFile> xml(new XMLFile(context_));
  149. XMLElement rootElem = xml->CreateRootElement("scene");
  150. if (!SaveXML(rootElem))
  151. return false;
  152. return xml->Save(dest);
  153. }
  154. bool Scene::LoadAsync(File* file)
  155. {
  156. if (!file)
  157. {
  158. LOGERROR("Null file for async loading");
  159. return false;
  160. }
  161. StopAsyncLoading();
  162. // Check ID
  163. if (file->ReadID() != "USCN")
  164. {
  165. LOGERROR(file->GetName() + " is not a valid scene file");
  166. return false;
  167. }
  168. // Clear the previous scene and load the root level components first
  169. Clear();
  170. if (!Node::Load(*file, false))
  171. return false;
  172. // Then prepare for loading all root level child nodes in the async update
  173. asyncLoading_ = true;
  174. asyncProgress_.file_ = file;
  175. asyncProgress_.xmlFile_.Reset();
  176. asyncProgress_.xmlElement_ = XMLElement();
  177. asyncProgress_.loadedNodes_ = 0;
  178. asyncProgress_.totalNodes_ = file->ReadVLE();
  179. return true;
  180. }
  181. bool Scene::LoadAsyncXML(File* file)
  182. {
  183. if (!file)
  184. {
  185. LOGERROR("Null file for async loading");
  186. return false;
  187. }
  188. StopAsyncLoading();
  189. SharedPtr<XMLFile> xmlFile(new XMLFile(context_));
  190. if (!xmlFile->Load(*file))
  191. return false;
  192. // Clear the previous scene and load the root level components first
  193. Clear();
  194. XMLElement rootElement = xmlFile->GetRootElement();
  195. if (!Node::LoadXML(rootElement, false))
  196. return false;
  197. // Then prepare for loading all root level child nodes in the async update
  198. XMLElement childNodeElement = rootElement.GetChildElement("node");
  199. asyncLoading_ = true;
  200. asyncProgress_.file_ = file;
  201. asyncProgress_.xmlFile_ = xmlFile;
  202. asyncProgress_.xmlElement_ = childNodeElement;
  203. asyncProgress_.loadedNodes_ = 0;
  204. asyncProgress_.totalNodes_ = 0;
  205. // Count the amount of child nodes
  206. while (childNodeElement)
  207. {
  208. ++asyncProgress_.totalNodes_;
  209. childNodeElement = childNodeElement.GetNextElement("node");
  210. }
  211. return true;
  212. }
  213. void Scene::StopAsyncLoading()
  214. {
  215. asyncLoading_ = false;
  216. asyncProgress_.file_.Reset();
  217. asyncProgress_.xmlFile_.Reset();
  218. asyncProgress_.xmlElement_ = XMLElement();
  219. }
  220. void Scene::SetActive(bool enable)
  221. {
  222. active_ = enable;
  223. }
  224. void Scene::SetNetworkMode(NetworkMode mode)
  225. {
  226. networkMode_ = mode;
  227. }
  228. void Scene::Clear()
  229. {
  230. RemoveAllChildren();
  231. RemoveAllComponents();
  232. fileName_ = String();
  233. checksum_ = 0;
  234. }
  235. void Scene::ClearNonLocal()
  236. {
  237. // Because node removal can remove arbitrary other nodes, can not iterate. Instead loop until the first node is local,
  238. // or the map is empty
  239. while ((allNodes_.Size()) && (allNodes_.Begin()->first_ < FIRST_LOCAL_ID))
  240. allNodes_.Begin()->second_->Remove();
  241. }
  242. void Scene::AddRequiredPackageFile(PackageFile* file)
  243. {
  244. if (file)
  245. requiredPackageFiles_.Push(SharedPtr<PackageFile>(file));
  246. }
  247. void Scene::ClearRequiredPackageFiles()
  248. {
  249. requiredPackageFiles_.Clear();
  250. }
  251. void Scene::ResetOwner(Connection* owner)
  252. {
  253. for (Map<unsigned, Node*>::Iterator i = allNodes_.Begin(); i != allNodes_.End(); ++i)
  254. {
  255. if (i->second_->GetOwner() == owner)
  256. i->second_->SetOwner(0);
  257. }
  258. }
  259. Node* Scene::GetNodeByID(unsigned id) const
  260. {
  261. Map<unsigned, Node*>::ConstIterator i = allNodes_.Find(id);
  262. if (i != allNodes_.End())
  263. return i->second_;
  264. else
  265. return 0;
  266. }
  267. Component* Scene::GetComponentByID(unsigned id) const
  268. {
  269. Map<unsigned, Component*>::ConstIterator i = allComponents_.Find(id);
  270. if (i != allComponents_.End())
  271. return i->second_;
  272. else
  273. return 0;
  274. }
  275. float Scene::GetAsyncProgress() const
  276. {
  277. if ((!asyncLoading_) || (!asyncProgress_.totalNodes_))
  278. return 1.0f;
  279. else
  280. return (float)asyncProgress_.loadedNodes_ / (float)asyncProgress_.totalNodes_;
  281. }
  282. unsigned Scene::GetFreeunsigned(bool local)
  283. {
  284. if (!local)
  285. {
  286. for (;;)
  287. {
  288. if (allNodes_.Find(nonLocalNodeID_) == allNodes_.End())
  289. return nonLocalNodeID_;
  290. if (nonLocalNodeID_ != LAST_NONLOCAL_ID)
  291. ++nonLocalNodeID_;
  292. else
  293. nonLocalNodeID_ = FIRST_NONLOCAL_ID;
  294. }
  295. }
  296. else
  297. {
  298. for (;;)
  299. {
  300. if (allNodes_.Find(localNodeID_) == allNodes_.End())
  301. return localNodeID_;
  302. if (localNodeID_ != LAST_LOCAL_ID)
  303. ++localNodeID_;
  304. else
  305. localNodeID_ = FIRST_LOCAL_ID;
  306. }
  307. }
  308. }
  309. unsigned Scene::GetFreeComponentID(bool local)
  310. {
  311. if (!local)
  312. {
  313. for (;;)
  314. {
  315. if (allComponents_.Find(nonLocalComponentID_) == allComponents_.End())
  316. return nonLocalComponentID_;
  317. if (nonLocalComponentID_ != LAST_NONLOCAL_ID)
  318. ++nonLocalComponentID_;
  319. else
  320. nonLocalComponentID_ = FIRST_NONLOCAL_ID;
  321. }
  322. }
  323. else
  324. {
  325. for (;;)
  326. {
  327. if (allComponents_.Find(localComponentID_) == allComponents_.End())
  328. return localComponentID_;
  329. if (localComponentID_ != LAST_LOCAL_ID)
  330. ++localComponentID_;
  331. else
  332. localComponentID_ = FIRST_LOCAL_ID;
  333. }
  334. }
  335. }
  336. void Scene::NodeAdded(Node* node)
  337. {
  338. if ((!node) || (node->GetScene()))
  339. return;
  340. node->SetScene(this);
  341. // If we already have an existing node with the same ID, must remove the scene reference from it
  342. unsigned id = node->GetID();
  343. Map<unsigned, Node*>::Iterator i = allNodes_.Find(id);
  344. if ((i != allNodes_.End()) && (i->second_ != node))
  345. {
  346. LOGWARNING("Overwriting node with ID " + id);
  347. i->second_->SetScene(0);
  348. i->second_->SetOwner(0);
  349. }
  350. allNodes_[id] = node;
  351. }
  352. void Scene::NodeRemoved(Node* node)
  353. {
  354. if ((!node) || (node->GetScene() != this))
  355. return;
  356. allNodes_.Erase(node->GetID());
  357. node->SetID(0);
  358. node->SetScene(0);
  359. }
  360. void Scene::ComponentAdded(Component* component)
  361. {
  362. if (!component)
  363. return;
  364. allComponents_[component->GetID()] = component;
  365. }
  366. void Scene::ComponentRemoved(Component* component)
  367. {
  368. if (!component)
  369. return;
  370. allComponents_.Erase(component->GetID());
  371. component->SetID(0);
  372. }
  373. void Scene::HandleUpdate(StringHash eventType, VariantMap& eventData)
  374. {
  375. using namespace Update;
  376. if (active_)
  377. Update(eventData[P_TIMESTEP].GetFloat());
  378. }
  379. void Scene::UpdateAsyncLoading()
  380. {
  381. PROFILE(UpdateAsyncLoading);
  382. Timer asyncLoadTimer;
  383. for (;;)
  384. {
  385. if (asyncProgress_.loadedNodes_ >= asyncProgress_.totalNodes_)
  386. {
  387. FinishAsyncLoading();
  388. return;
  389. }
  390. // Read one child node either from binary or XML
  391. if (!asyncProgress_.xmlFile_)
  392. {
  393. Node* newNode = CreateChild(asyncProgress_.file_->ReadUInt(), false);
  394. newNode->Load(*asyncProgress_.file_);
  395. }
  396. else
  397. {
  398. Node* newNode = CreateChild(asyncProgress_.xmlElement_.GetInt("id"), false);
  399. newNode->LoadXML(asyncProgress_.xmlElement_);
  400. asyncProgress_.xmlElement_ = asyncProgress_.xmlElement_.GetNextElement("node");
  401. }
  402. ++asyncProgress_.loadedNodes_;
  403. // Break if time limit exceeded, so that we keep sufficient FPS
  404. if (asyncLoadTimer.GetMSec(false) >= ASYNC_LOAD_MAX_MSEC)
  405. break;
  406. }
  407. using namespace AsyncLoadProgress;
  408. VariantMap eventData;
  409. eventData[P_SCENE] = (void*)this;
  410. eventData[P_PROGRESS] = (float)asyncProgress_.loadedNodes_ / (float)asyncProgress_.totalNodes_;
  411. eventData[P_LOADEDNODES] = asyncProgress_.loadedNodes_;
  412. eventData[P_TOTALNODES] = asyncProgress_.totalNodes_;
  413. SendEvent(E_ASYNCLOADPROGRESS, eventData);
  414. }
  415. void Scene::FinishAsyncLoading()
  416. {
  417. FinishLoading(asyncProgress_.file_);
  418. StopAsyncLoading();
  419. using namespace AsyncLoadFinished;
  420. VariantMap eventData;
  421. eventData[P_SCENE] = (void*)this;
  422. SendEvent(E_ASYNCLOADFINISHED, eventData);
  423. }
  424. void Scene::FinishLoading(Deserializer* source)
  425. {
  426. PostLoad();
  427. if (source)
  428. {
  429. fileName_ = source->GetName();
  430. checksum_ = source->GetChecksum();
  431. }
  432. }
  433. void RegisterSceneLibrary(Context* context)
  434. {
  435. Node::RegisterObject(context);
  436. Scene::RegisterObject(context);
  437. }