浏览代码

Moved Controls to Network library.
Fixed async scene loading.
Fixed crashes if two scene nodes were created with the same ID.

Lasse Öörni 14 年之前
父节点
当前提交
6531fa08d5

+ 2 - 38
Engine/Engine/InputAPI.cpp

@@ -23,12 +23,9 @@
 
 #include "Precompiled.h"
 #include "APITemplates.h"
-#include "Controls.h"
 #include "Input.h"
 
-#include <angelscript.h>
-
-static void RegisterKeyCodes(asIScriptEngine* engine)
+static void RegisterInputConstants(asIScriptEngine* engine)
 {
     engine->RegisterGlobalProperty("const int MOUSEB_LEFT", (void*)&MOUSEB_LEFT);
     engine->RegisterGlobalProperty("const int MOUSEB_RIGHT", (void*)&MOUSEB_RIGHT);
@@ -121,38 +118,6 @@ static void RegisterKeyCodes(asIScriptEngine* engine)
     engine->RegisterGlobalProperty("const int KEY_OEM_8", (void*)&KEY_OEM_8);
 }
 
-static void ConstructControls(Controls* ptr)
-{
-    new(ptr) Controls();
-}
-
-static void ConstructControlsCopy(const Controls& controls, Controls* ptr)
-{
-    new(ptr) Controls(controls);
-}
-
-static void DestructControls(Controls* ptr)
-{
-    ptr->~Controls();
-}
-
-static void RegisterControls(asIScriptEngine* engine)
-{
-    engine->RegisterObjectType("Controls", sizeof(Controls), asOBJ_VALUE | asOBJ_APP_CLASS_CDA);
-    engine->RegisterObjectBehaviour("Controls", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructControls), asCALL_CDECL_OBJLAST);
-    engine->RegisterObjectBehaviour("Controls", asBEHAVE_CONSTRUCT, "void f(const Controls&in)", asFUNCTION(ConstructControlsCopy), asCALL_CDECL_OBJLAST);
-    engine->RegisterObjectBehaviour("Controls", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructControls), asCALL_CDECL_OBJLAST);
-    engine->RegisterObjectMethod("Controls", "Controls &opAssign(const Controls&in)", asMETHOD(Controls, operator =), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Controls", "void Reset()", asMETHOD(Controls, Reset), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Controls", "void Set(uint, bool)", asMETHOD(Controls, Set), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Controls", "bool IsDown(uint)", asMETHOD(Controls, IsDown), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Controls", "bool IsPressed(uint, const Controls&in)", asMETHOD(Controls, IsPressed), asCALL_THISCALL);
-    engine->RegisterObjectProperty("Controls", "uint buttons", offsetof(Controls, buttons_));
-    engine->RegisterObjectProperty("Controls", "float yaw", offsetof(Controls, yaw_));
-    engine->RegisterObjectProperty("Controls", "float pitch", offsetof(Controls, pitch_));
-    engine->RegisterObjectProperty("Controls", "VariantMap extraData", offsetof(Controls, extraData_));
-}
-
 static Input* GetInput()
 {
     return GetScriptContext()->GetSubsystem<Input>();
@@ -187,7 +152,6 @@ static void RegisterInput(asIScriptEngine* engine)
 
 void RegisterInputAPI(asIScriptEngine* engine)
 {
-    RegisterKeyCodes(engine);
-    RegisterControls(engine);
+    RegisterInputConstants(engine);
     RegisterInput(engine);
 }

+ 34 - 0
Engine/Engine/NetworkAPI.cpp

@@ -23,9 +23,42 @@
 
 #include "Precompiled.h"
 #include "APITemplates.h"
+#include "Controls.h"
 #include "Network.h"
 #include "Peer.h"
 
+static void ConstructControls(Controls* ptr)
+{
+    new(ptr) Controls();
+}
+
+static void ConstructControlsCopy(const Controls& controls, Controls* ptr)
+{
+    new(ptr) Controls(controls);
+}
+
+static void DestructControls(Controls* ptr)
+{
+    ptr->~Controls();
+}
+
+static void RegisterControls(asIScriptEngine* engine)
+{
+    engine->RegisterObjectType("Controls", sizeof(Controls), asOBJ_VALUE | asOBJ_APP_CLASS_CDA);
+    engine->RegisterObjectBehaviour("Controls", asBEHAVE_CONSTRUCT, "void f()", asFUNCTION(ConstructControls), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("Controls", asBEHAVE_CONSTRUCT, "void f(const Controls&in)", asFUNCTION(ConstructControlsCopy), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectBehaviour("Controls", asBEHAVE_DESTRUCT, "void f()", asFUNCTION(DestructControls), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Controls", "Controls &opAssign(const Controls&in)", asMETHOD(Controls, operator =), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Controls", "void Reset()", asMETHOD(Controls, Reset), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Controls", "void Set(uint, bool)", asMETHOD(Controls, Set), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Controls", "bool IsDown(uint)", asMETHOD(Controls, IsDown), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Controls", "bool IsPressed(uint, const Controls&in)", asMETHOD(Controls, IsPressed), asCALL_THISCALL);
+    engine->RegisterObjectProperty("Controls", "uint buttons", offsetof(Controls, buttons_));
+    engine->RegisterObjectProperty("Controls", "float yaw", offsetof(Controls, yaw_));
+    engine->RegisterObjectProperty("Controls", "float pitch", offsetof(Controls, pitch_));
+    engine->RegisterObjectProperty("Controls", "VariantMap extraData", offsetof(Controls, extraData_));
+}
+
 void RegisterPeer(asIScriptEngine* engine)
 {
     engine->RegisterGlobalProperty("const uint8 CHANNEL_ANY", (void*)&CHANNEL_ANY);
@@ -90,6 +123,7 @@ void RegisterNetwork(asIScriptEngine* engine)
 
 void RegisterNetworkAPI(asIScriptEngine* engine)
 {
+    RegisterControls(engine);
     RegisterPeer(engine);
     RegisterNetwork(engine);
 }

+ 4 - 2
Engine/Engine/SceneAPI.cpp

@@ -89,10 +89,12 @@ static void RegisterScene(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Scene", "Component@+ GetComponentByID(uint)", asMETHOD(Scene, GetComponentByID), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "Node@+ GetNodeByID(uint)", asMETHOD(Scene, GetNodeByID), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void Update(float)", asMETHOD(Scene, Update), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Scene", "void set_active(bool)", asMETHOD(Scene, SetActive), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Scene", "bool get_active() const", asMETHOD(Scene, IsActive), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void set_networkMode(NetworkMode)", asMETHOD(Scene, SetNetworkMode), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "NetworkMode get_networkMode() const", asMETHOD(Scene, GetNetworkMode), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Scene", "void set_active(bool)", asMETHOD(Scene, SetActive), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Scene", "bool get_active() const", asMETHOD(Scene, IsActive), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Scene", "bool get_asyncLoading() const", asMETHOD(Scene, IsAsyncLoading), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Scene", "float get_asyncProgress() const", asMETHOD(Scene, GetAsyncProgress), asCALL_THISCALL);
     engine->RegisterObjectMethod("Node", "Scene@+ get_scene() const", asMETHOD(Node, GetScene), asCALL_THISCALL);
     engine->RegisterGlobalFunction("Scene@+ get_scene()", asFUNCTION(GetScriptContextScene), asCALL_CDECL);
     

+ 2 - 2
Engine/Graphics/View.cpp

@@ -93,8 +93,8 @@ bool View::Define(RenderSurface* renderTarget, const Viewport& viewport)
         return false;
     
     // If scene is loading asynchronously, it is incomplete and should not be rendered
-    //if (viewport.scene_->isAsyncLoading())
-    //    return false;
+    if (viewport.scene_->IsAsyncLoading())
+        return false;
     
     Octree* octree = viewport.scene_->GetComponent<Octree>();
     if (!octree)

+ 1 - 0
Engine/Input/Controls.cpp → Engine/Network/Controls.cpp

@@ -21,6 +21,7 @@
 // THE SOFTWARE.
 //
 
+#include "Precompiled.h"
 #include "Controls.h"
 
 Controls::Controls()

+ 0 - 0
Engine/Input/Controls.h → Engine/Network/Controls.h


+ 0 - 1
Engine/Network/Precompiled.h

@@ -26,6 +26,5 @@
 #include <cstdio>
 #include <cstdlib>
 #include <map>
-#include <stdexcept>
 #include <string>
 #include <vector>

+ 8 - 8
Engine/Scene/Node.cpp

@@ -392,12 +392,6 @@ void Node::RemoveAllChildren()
         RemoveChild(children_.end() - 1);
 }
 
-void Node::SetParent(Node* parent)
-{
-    if (parent)
-        parent->AddChild(this);
-}
-
 Component* Node::CreateComponent(ShortStringHash type, bool local)
 {
     return CreateComponent(type, 0, local);
@@ -487,6 +481,12 @@ void Node::Remove()
         parent_->RemoveChild(this);
 }
 
+void Node::SetParent(Node* parent)
+{
+    if (parent)
+        parent->AddChild(this);
+}
+
 unsigned Node::GetNumChildren(bool recursive) const
 {
     if (!recursive)
@@ -665,7 +665,7 @@ bool Node::LoadXML(const XMLElement& source, bool readChildren)
     XMLElement childElem = source.GetChildElement("node");
     while (childElem)
     {
-        Node* newNode = CreateChild(compElem.GetInt("id"), false);
+        Node* newNode = CreateChild(childElem.GetInt("id"), false);
         if (!newNode->LoadXML(childElem))
             return false;
         
@@ -766,7 +766,7 @@ void Node::SetID(unsigned id)
     id_ = id;
 }
 
-void Node::setScene(Scene* scene)
+void Node::SetScene(Scene* scene)
 {
     scene_ = scene;
 }

+ 5 - 5
Engine/Scene/Node.h

@@ -105,10 +105,6 @@ public:
     void RemoveChild(Node* node);
     /// Remove all child scene nodes
     void RemoveAllChildren();
-    /// Remove from the parent node. If no other shared pointer references exist, causes immediate deletion
-    void Remove();
-    /// Set parent scene node. Same as parent->AddChild(this)
-    void SetParent(Node* parent);
     /// Create a component to this node
     Component* CreateComponent(ShortStringHash type, bool local = false);
     /// Create a component to this node if it does not exist already
@@ -121,6 +117,10 @@ public:
     void AddListener(Component* component);
     /// Remove listener component
     void RemoveListener(Component* component);
+    /// Remove from the parent node. If no other shared pointer references exist, causes immediate deletion
+    void Remove();
+    /// Set parent scene node. Same as parent->AddChild(this)
+    void SetParent(Node* parent);
     /// Template version of creating a component
     template <class T> T* CreateComponent(bool local = false);
     /// Template version of getting or creating a component
@@ -258,7 +258,7 @@ private:
     /// Set ID. Called by Scene
     void SetID(unsigned id);
     /// Set scene. Called by Scene
-    void setScene(Scene* scene);
+    void SetScene(Scene* scene);
     
     /// Unique ID within the scene
     unsigned id_;

+ 30 - 13
Engine/Scene/Scene.cpp

@@ -30,11 +30,12 @@
 #include "Profiler.h"
 #include "Scene.h"
 #include "SceneEvents.h"
+#include "StringUtils.h"
 #include "XMLFile.h"
 
 OBJECTTYPESTATIC(Scene);
 
-static const int ASYNC_LOAD_MIN_FPS = 60;
+static const int ASYNC_LOAD_MIN_FPS = 50;
 static const int ASYNC_LOAD_MAX_MSEC = (int)(1000.0f / ASYNC_LOAD_MIN_FPS);
 
 Scene::Scene(Context* context) :
@@ -58,7 +59,7 @@ Scene::~Scene()
 {
     // Remove scene reference from all nodes that still exist
     for (std::map<unsigned, Node*>::iterator i = allNodes_.begin(); i != allNodes_.end(); ++i)
-        i->second->setScene(0);
+        i->second->SetScene(0);
 }
 
 void Scene::RegisterObject(Context* context)
@@ -149,7 +150,7 @@ bool Scene::LoadAsync(File* file)
         return false;
     }
     
-    // Load the root level components first
+    // Clear the previous scene and load the root level components first
     if (!Node::Load(*file, false))
         return false;
     
@@ -176,14 +177,13 @@ bool Scene::LoadAsyncXML(File* file)
     if (!xmlFile->Load(*file))
         return false;
     
-    // Load the root level components first
+    // Clear the previous scene and load the root level components first
     XMLElement rootElement = xmlFile->GetRootElement();
-    if (!Node::LoadXML(rootElement))
+    if (!Node::LoadXML(rootElement, false))
         return false;
     
-    XMLElement childNodeElement = rootElement.GetChildElement("node");
-    
     // Then prepare for loading all root level child nodes in the async update
+    XMLElement childNodeElement = rootElement.GetChildElement("node");
     asyncLoading_ = true;
     asyncProgress_.file_.Reset();
     asyncProgress_.xmlFile_ = xmlFile;
@@ -255,6 +255,14 @@ Component* Scene::GetComponentByID(unsigned id) const
         return 0;
 }
 
+float Scene::GetAsyncProgress() const
+{
+    if ((!asyncLoading_) || (!asyncProgress_.totalNodes_))
+        return 1.0f;
+    else
+        return (float)asyncProgress_.loadedNodes_ / (float)asyncProgress_.totalNodes_;
+}
+
 unsigned Scene::GetFreeNodeID(bool local)
 {
     if (!local)
@@ -321,8 +329,18 @@ void Scene::NodeAdded(Node* node)
     if ((!node) || (node->GetScene()))
         return;
     
-    node->setScene(this);
-    allNodes_[node->GetID()] = node;
+    node->SetScene(this);
+    
+    // If we already have an existing node with the same ID, must remove the scene reference from it
+    unsigned id = node->GetID();
+    std::map<unsigned, Node*>::iterator i = allNodes_.find(id);
+    if ((i != allNodes_.end()) && (i->second != node))
+    {
+        LOGWARNING("Overwriting node with ID " + ToString(id));
+        i->second->SetScene(0);
+    }
+    
+    allNodes_[id] = node;
 }
 
 void Scene::NodeRemoved(Node* node)
@@ -332,7 +350,7 @@ void Scene::NodeRemoved(Node* node)
     
     allNodes_.erase(node->GetID());
     node->SetID(0);
-    node->setScene(0);
+    node->SetScene(0);
 }
 
 void Scene::ComponentAdded(Component* component)
@@ -368,7 +386,6 @@ void Scene::UpdateAsyncLoad()
     
     for (;;)
     {
-        // Check if everything loaded
         if (asyncProgress_.loadedNodes_ >= asyncProgress_.totalNodes_)
         {
             FinishAsyncLoad();
@@ -376,12 +393,12 @@ void Scene::UpdateAsyncLoad()
         }
         
         // Read one child node either from binary or XML
-        if (asyncProgress_.file_)
+        if ((asyncProgress_.file_) && (!asyncProgress_.file_->IsEof()))
         {
             Node* newNode = CreateChild(asyncProgress_.file_->ReadUInt(), false);
             newNode->Load(*asyncProgress_.file_);
         }
-        else
+        if (asyncProgress_.xmlElement_)
         {
             Node* newNode = CreateChild(asyncProgress_.xmlElement_.GetInt("id"), false);
             newNode->LoadXML(asyncProgress_.xmlElement_);

+ 4 - 0
Engine/Scene/Scene.h

@@ -105,6 +105,10 @@ public:
     NetworkMode GetNetworkMode() const { return networkMode_; }
     /// Return active flag
     bool IsActive() const { return active_; }
+    /// Return async loading flag
+    bool IsAsyncLoading() const { return asyncLoading_; }
+    /// Return async loading progress between 0.0 and 1.0, or 1.0 if not async loading
+    float GetAsyncProgress() const;
     
     /// Get free node ID, either non-local or local
     unsigned GetFreeNodeID(bool local);