Scene.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  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. static const float DEFAULT_SMOOTHING_CONSTANT = 50.0f;
  37. static const float DEFAULT_SNAP_THRESHOLD = 1.0f;
  38. OBJECTTYPESTATIC(Scene);
  39. Scene::Scene(Context* context) :
  40. Node(context),
  41. replicatedNodeID_(FIRST_REPLICATED_ID),
  42. replicatedComponentID_(FIRST_REPLICATED_ID),
  43. localNodeID_(FIRST_LOCAL_ID),
  44. localComponentID_(FIRST_LOCAL_ID),
  45. smoothingConstant_(DEFAULT_SMOOTHING_CONSTANT),
  46. snapThreshold_(DEFAULT_SNAP_THRESHOLD),
  47. checksum_(0),
  48. active_(true),
  49. asyncLoading_(false)
  50. {
  51. // Assign an ID to self so that nodes can refer to this node as a parent
  52. SetID(GetFreeNodeID(REPLICATED));
  53. NodeAdded(this);
  54. SubscribeToEvent(E_UPDATE, HANDLER(Scene, HandleUpdate));
  55. }
  56. Scene::~Scene()
  57. {
  58. // Remove scene reference and owner from all nodes that still exist
  59. for (Map<unsigned, Node*>::Iterator i = allNodes_.Begin(); i != allNodes_.End(); ++i)
  60. {
  61. i->second_->SetScene(0);
  62. i->second_->SetOwner(0);
  63. }
  64. }
  65. void Scene::RegisterObject(Context* context)
  66. {
  67. context->RegisterFactory<Scene>();
  68. context->CopyBaseAttributes<Node, Scene>();
  69. ATTRIBUTE(Scene, VAR_INT, "Next Replicated Node ID", replicatedNodeID_, FIRST_REPLICATED_ID, AM_DEFAULT);
  70. ATTRIBUTE(Scene, VAR_INT, "Next Replicated Component ID", replicatedComponentID_, FIRST_REPLICATED_ID, AM_DEFAULT);
  71. ATTRIBUTE(Scene, VAR_INT, "Next Local Node ID", localNodeID_, FIRST_LOCAL_ID, AM_DEFAULT);
  72. ATTRIBUTE(Scene, VAR_INT, "Next Local Component ID", localComponentID_, FIRST_LOCAL_ID, AM_DEFAULT);
  73. ATTRIBUTE(Scene, VAR_FLOAT, "Motion Smoothing Constant", smoothingConstant_, DEFAULT_SMOOTHING_CONSTANT, AM_DEFAULT);
  74. ATTRIBUTE(Scene, VAR_FLOAT, "Motion Snap Threshold", snapThreshold_, DEFAULT_SNAP_THRESHOLD, AM_DEFAULT);
  75. }
  76. bool Scene::Load(Deserializer& source)
  77. {
  78. StopAsyncLoading();
  79. // Check ID
  80. if (source.ReadID() != "USCN")
  81. {
  82. LOGERROR(source.GetName() + " is not a valid scene file");
  83. return false;
  84. }
  85. LOGINFO("Loading scene from " + source.GetName());
  86. // Load the whole scene, then perform post-load if successfully loaded
  87. if (Node::Load(source))
  88. {
  89. FinishLoading(&source);
  90. return true;
  91. }
  92. else
  93. return false;
  94. }
  95. bool Scene::Save(Serializer& dest)
  96. {
  97. // Write ID first
  98. if (!dest.WriteID("USCN"))
  99. {
  100. LOGERROR("Could not save scene, writing to stream failed");
  101. return false;
  102. }
  103. Deserializer* ptr = dynamic_cast<Deserializer*>(&dest);
  104. if (ptr)
  105. LOGINFO("Saving scene to " + ptr->GetName());
  106. return Node::Save(dest);
  107. }
  108. bool Scene::LoadXML(const XMLElement& source)
  109. {
  110. StopAsyncLoading();
  111. // Load the whole scene, then perform post-load if successfully loaded
  112. // Note: the scene filename and checksum can not be set, as we only used an XML element
  113. if (Node::LoadXML(source))
  114. {
  115. FinishLoading(0);
  116. return true;
  117. }
  118. else
  119. return false;
  120. }
  121. bool Scene::LoadXML(Deserializer& source)
  122. {
  123. StopAsyncLoading();
  124. SharedPtr<XMLFile> xml(new XMLFile(context_));
  125. if (!xml->Load(source))
  126. return false;
  127. LOGINFO("Loading scene from " + source.GetName());
  128. // Load the whole scene, then perform post-load if successfully loaded
  129. if (Node::LoadXML(xml->GetRoot()))
  130. {
  131. FinishLoading(&source);
  132. return true;
  133. }
  134. else
  135. return false;
  136. }
  137. bool Scene::SaveXML(Serializer& dest)
  138. {
  139. SharedPtr<XMLFile> xml(new XMLFile(context_));
  140. XMLElement rootElem = xml->CreateRoot("scene");
  141. if (!SaveXML(rootElem))
  142. return false;
  143. Deserializer* ptr = dynamic_cast<Deserializer*>(&dest);
  144. if (ptr)
  145. LOGINFO("Saving scene to " + ptr->GetName());
  146. return xml->Save(dest);
  147. }
  148. bool Scene::LoadAsync(File* file)
  149. {
  150. if (!file)
  151. {
  152. LOGERROR("Null file for async loading");
  153. return false;
  154. }
  155. StopAsyncLoading();
  156. // Check ID
  157. if (file->ReadID() != "USCN")
  158. {
  159. LOGERROR(file->GetName() + " is not a valid scene file");
  160. return false;
  161. }
  162. LOGINFO("Loading scene from " + file->GetName());
  163. // Clear the previous scene and load the root level components first
  164. Clear();
  165. if (!Node::Load(*file, false))
  166. return false;
  167. // Then prepare for loading all root level child nodes in the async update
  168. asyncLoading_ = true;
  169. asyncProgress_.file_ = file;
  170. asyncProgress_.xmlFile_.Reset();
  171. asyncProgress_.xmlElement_ = XMLElement();
  172. asyncProgress_.loadedNodes_ = 0;
  173. asyncProgress_.totalNodes_ = file->ReadVLE();
  174. return true;
  175. }
  176. bool Scene::LoadAsyncXML(File* file)
  177. {
  178. if (!file)
  179. {
  180. LOGERROR("Null file for async loading");
  181. return false;
  182. }
  183. StopAsyncLoading();
  184. SharedPtr<XMLFile> xmlFile(new XMLFile(context_));
  185. if (!xmlFile->Load(*file))
  186. return false;
  187. LOGINFO("Loading scene from " + file->GetName());
  188. // Clear the previous scene and load the root level components first
  189. Clear();
  190. XMLElement rootElement = xmlFile->GetRoot();
  191. if (!Node::LoadXML(rootElement, false))
  192. return false;
  193. // Then prepare for loading all root level child nodes in the async update
  194. XMLElement childNodeElement = rootElement.GetChild("node");
  195. asyncLoading_ = true;
  196. asyncProgress_.file_ = file;
  197. asyncProgress_.xmlFile_ = xmlFile;
  198. asyncProgress_.xmlElement_ = childNodeElement;
  199. asyncProgress_.loadedNodes_ = 0;
  200. asyncProgress_.totalNodes_ = 0;
  201. // Count the amount of child nodes
  202. while (childNodeElement)
  203. {
  204. ++asyncProgress_.totalNodes_;
  205. childNodeElement = childNodeElement.GetNext("node");
  206. }
  207. return true;
  208. }
  209. void Scene::StopAsyncLoading()
  210. {
  211. asyncLoading_ = false;
  212. asyncProgress_.file_.Reset();
  213. asyncProgress_.xmlFile_.Reset();
  214. asyncProgress_.xmlElement_ = XMLElement();
  215. }
  216. void Scene::Clear()
  217. {
  218. RemoveAllChildren();
  219. RemoveAllComponents();
  220. fileName_ = String();
  221. checksum_ = 0;
  222. }
  223. void Scene::Update(float timeStep)
  224. {
  225. if (asyncLoading_)
  226. {
  227. UpdateAsyncLoading();
  228. return;
  229. }
  230. PROFILE(UpdateScene);
  231. using namespace SceneUpdate;
  232. VariantMap eventData;
  233. eventData[P_SCENE] = (void*)this;
  234. eventData[P_TIMESTEP] = timeStep;
  235. // Update variable timestep logic
  236. SendEvent(E_SCENEUPDATE, eventData);
  237. // Update scene subsystems. If a physics world is present, it will be updated, triggering fixed timestep logic updates
  238. SendEvent(E_SCENESUBSYSTEMUPDATE, eventData);
  239. // Post-update variable timestep logic
  240. SendEvent(E_SCENEPOSTUPDATE, eventData);
  241. // Update smoothing if enabled (network client scenes)
  242. if (IsSmoothed())
  243. {
  244. PROFILE(UpdateSmoothing);
  245. float constant = 1.0f - Clamp(powf(2.0f, -timeStep * smoothingConstant_), 0.0f, 1.0f);
  246. float squaredSnapThreshold = snapThreshold_ * snapThreshold_;
  247. for (Map<unsigned, Node*>::ConstIterator i = allNodes_.Begin(); i != allNodes_.End() && i->first_ < FIRST_LOCAL_ID; ++i)
  248. i->second_->UpdateSmoothing(constant, squaredSnapThreshold);
  249. }
  250. }
  251. void Scene::SetActive(bool enable)
  252. {
  253. active_ = enable;
  254. }
  255. void Scene::SetSmoothingConstant(float constant)
  256. {
  257. smoothingConstant_ = Max(constant, M_EPSILON);
  258. }
  259. void Scene::SetSnapThreshold(float threshold)
  260. {
  261. snapThreshold_ = Max(threshold, 0.0f);
  262. }
  263. void Scene::AddRequiredPackageFile(PackageFile* file)
  264. {
  265. if (file)
  266. requiredPackageFiles_.Push(SharedPtr<PackageFile>(file));
  267. }
  268. void Scene::ClearRequiredPackageFiles()
  269. {
  270. requiredPackageFiles_.Clear();
  271. }
  272. void Scene::ResetOwner(Connection* owner)
  273. {
  274. for (Map<unsigned, Node*>::Iterator i = allNodes_.Begin(); i != allNodes_.End(); ++i)
  275. {
  276. if (i->second_->GetOwner() == owner)
  277. i->second_->SetOwner(0);
  278. }
  279. }
  280. Node* Scene::GetNodeByID(unsigned id) const
  281. {
  282. Map<unsigned, Node*>::ConstIterator i = allNodes_.Find(id);
  283. if (i != allNodes_.End())
  284. return i->second_;
  285. else
  286. return 0;
  287. }
  288. Component* Scene::GetComponentByID(unsigned id) const
  289. {
  290. Map<unsigned, Component*>::ConstIterator i = allComponents_.Find(id);
  291. if (i != allComponents_.End())
  292. return i->second_;
  293. else
  294. return 0;
  295. }
  296. float Scene::GetAsyncProgress() const
  297. {
  298. if (!asyncLoading_ || !asyncProgress_.totalNodes_)
  299. return 1.0f;
  300. else
  301. return (float)asyncProgress_.loadedNodes_ / (float)asyncProgress_.totalNodes_;
  302. }
  303. unsigned Scene::GetFreeNodeID(CreateMode mode)
  304. {
  305. if (mode == REPLICATED)
  306. {
  307. for (;;)
  308. {
  309. if (allNodes_.Find(replicatedNodeID_) == allNodes_.End())
  310. return replicatedNodeID_;
  311. if (replicatedNodeID_ != LAST_REPLICATED_ID)
  312. ++replicatedNodeID_;
  313. else
  314. replicatedNodeID_ = FIRST_REPLICATED_ID;
  315. }
  316. }
  317. else
  318. {
  319. for (;;)
  320. {
  321. if (allNodes_.Find(localNodeID_) == allNodes_.End())
  322. return localNodeID_;
  323. if (localNodeID_ != LAST_LOCAL_ID)
  324. ++localNodeID_;
  325. else
  326. localNodeID_ = FIRST_LOCAL_ID;
  327. }
  328. }
  329. }
  330. unsigned Scene::GetFreeComponentID(CreateMode mode)
  331. {
  332. if (mode == REPLICATED)
  333. {
  334. for (;;)
  335. {
  336. if (allComponents_.Find(replicatedComponentID_) == allComponents_.End())
  337. return replicatedComponentID_;
  338. if (replicatedComponentID_ != LAST_REPLICATED_ID)
  339. ++replicatedComponentID_;
  340. else
  341. replicatedComponentID_ = FIRST_REPLICATED_ID;
  342. }
  343. }
  344. else
  345. {
  346. for (;;)
  347. {
  348. if (allComponents_.Find(localComponentID_) == allComponents_.End())
  349. return localComponentID_;
  350. if (localComponentID_ != LAST_LOCAL_ID)
  351. ++localComponentID_;
  352. else
  353. localComponentID_ = FIRST_LOCAL_ID;
  354. }
  355. }
  356. }
  357. void Scene::NodeAdded(Node* node)
  358. {
  359. if (!node || node->GetScene())
  360. return;
  361. node->SetScene(this);
  362. // If we already have an existing node with the same ID, must remove the scene reference from it
  363. unsigned id = node->GetID();
  364. Map<unsigned, Node*>::Iterator i = allNodes_.Find(id);
  365. if (i != allNodes_.End() && i->second_ != node)
  366. {
  367. LOGWARNING("Overwriting node with ID " + String(id));
  368. i->second_->SetScene(0);
  369. i->second_->SetOwner(0);
  370. }
  371. allNodes_[id] = node;
  372. }
  373. void Scene::NodeRemoved(Node* node)
  374. {
  375. if (!node || node->GetScene() != this)
  376. return;
  377. allNodes_.Erase(node->GetID());
  378. node->SetID(0);
  379. node->SetScene(0);
  380. }
  381. void Scene::ComponentAdded(Component* component)
  382. {
  383. if (!component)
  384. return;
  385. allComponents_[component->GetID()] = component;
  386. }
  387. void Scene::ComponentRemoved(Component* component)
  388. {
  389. if (!component)
  390. return;
  391. allComponents_.Erase(component->GetID());
  392. component->SetID(0);
  393. }
  394. void Scene::HandleUpdate(StringHash eventType, VariantMap& eventData)
  395. {
  396. using namespace Update;
  397. if (active_)
  398. Update(eventData[P_TIMESTEP].GetFloat());
  399. }
  400. void Scene::UpdateAsyncLoading()
  401. {
  402. PROFILE(UpdateAsyncLoading);
  403. Timer asyncLoadTimer;
  404. for (;;)
  405. {
  406. if (asyncProgress_.loadedNodes_ >= asyncProgress_.totalNodes_)
  407. {
  408. FinishAsyncLoading();
  409. return;
  410. }
  411. // Read one child node either from binary or XML
  412. if (!asyncProgress_.xmlFile_)
  413. {
  414. Node* newNode = CreateChild(asyncProgress_.file_->ReadUInt(), REPLICATED);
  415. newNode->Load(*asyncProgress_.file_);
  416. }
  417. else
  418. {
  419. Node* newNode = CreateChild(asyncProgress_.xmlElement_.GetInt("id"), REPLICATED);
  420. newNode->LoadXML(asyncProgress_.xmlElement_);
  421. asyncProgress_.xmlElement_ = asyncProgress_.xmlElement_.GetNext("node");
  422. }
  423. ++asyncProgress_.loadedNodes_;
  424. // Break if time limit exceeded, so that we keep sufficient FPS
  425. if (asyncLoadTimer.GetMSec(false) >= ASYNC_LOAD_MAX_MSEC)
  426. break;
  427. }
  428. using namespace AsyncLoadProgress;
  429. VariantMap eventData;
  430. eventData[P_SCENE] = (void*)this;
  431. eventData[P_PROGRESS] = (float)asyncProgress_.loadedNodes_ / (float)asyncProgress_.totalNodes_;
  432. eventData[P_LOADEDNODES] = asyncProgress_.loadedNodes_;
  433. eventData[P_TOTALNODES] = asyncProgress_.totalNodes_;
  434. SendEvent(E_ASYNCLOADPROGRESS, eventData);
  435. }
  436. void Scene::FinishAsyncLoading()
  437. {
  438. FinishLoading(asyncProgress_.file_);
  439. StopAsyncLoading();
  440. using namespace AsyncLoadFinished;
  441. VariantMap eventData;
  442. eventData[P_SCENE] = (void*)this;
  443. SendEvent(E_ASYNCLOADFINISHED, eventData);
  444. }
  445. void Scene::FinishLoading(Deserializer* source)
  446. {
  447. FinishUpdate();
  448. if (source)
  449. {
  450. fileName_ = source->GetName();
  451. checksum_ = source->GetChecksum();
  452. }
  453. }
  454. void RegisterSceneLibrary(Context* context)
  455. {
  456. Node::RegisterObject(context);
  457. Scene::RegisterObject(context);
  458. }