Browse Source

Removal of self from script is now properly delayed until the end of the scene update.

Lasse Öörni 15 years ago
parent
commit
8f67b457c6
4 changed files with 62 additions and 4 deletions
  1. 4 0
      Bin/Data/Scripts/Ninja.as
  2. 38 4
      Engine/Engine/RegisterScene.cpp
  3. 13 0
      Engine/Scene/Scene.cpp
  4. 7 0
      Engine/Scene/Scene.h

+ 4 - 0
Bin/Data/Scripts/Ninja.as

@@ -251,6 +251,10 @@ class Ninja : ScriptObject, GameObject
         prevControls = controls;
         prevControls = controls;
         
         
         resetWorldCollision();
         resetWorldCollision();
+        
+        // Test removing self
+        if (input.getKeyPress('K'))
+        	scene.removeEntity(entity);
     }
     }
     
     
     void handleEntityCollision(StringHash eventType, VariantMap& eventData)
     void handleEntityCollision(StringHash eventType, VariantMap& eventData)

+ 38 - 4
Engine/Engine/RegisterScene.cpp

@@ -391,6 +391,41 @@ static CScriptArray* SceneGetEntitiesWithClass(const std::string& className, Sce
     return vectorToHandleArray<Entity*>(result, "array<Entity@>");
     return vectorToHandleArray<Entity*>(result, "array<Entity@>");
 }
 }
 
 
+static void SceneRemoveEntityByID(EntityID id, Scene* ptr)
+{
+    Entity* entity = ptr->getEntity(id);
+    if (entity)
+    {
+        if (entity == getScriptContextEntity())
+            ptr->addDelayedRemoveEntity(id);
+        else
+            ptr->removeEntity(id);
+    }
+}
+
+static void SceneRemoveEntityByPtr(Entity* entity, Scene* ptr)
+{
+    if ((entity) && (entity->getScene() == ptr))
+    {
+        if (entity == getScriptContextEntity())
+            ptr->addDelayedRemoveEntity(entity->getID());
+        else
+            ptr->removeEntity(entity->getID());
+    }
+}
+
+static void SceneRemoveEntityByName(const std::string& name, Scene* ptr)
+{
+    Entity* entity = ptr->getEntity(name);
+    if (entity)
+    {
+        if (entity == getScriptContextEntity())
+            ptr->addDelayedRemoveEntity(entity->getID());
+        else
+            ptr->removeEntity(entity->getID());
+    }
+}
+
 static void SendDelayedEvent(const std::string& eventType, const VariantMap& eventData, float delay)
 static void SendDelayedEvent(const std::string& eventType, const VariantMap& eventData, float delay)
 {
 {
     Scene* scene = getScriptContextScene();
     Scene* scene = getScriptContextScene();
@@ -437,10 +472,9 @@ static void registerScene(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Scene", "Entity@+ createEntity(const string& in)", asFUNCTION(SceneCreateEntityWithName), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Scene", "Entity@+ createEntity(const string& in)", asFUNCTION(SceneCreateEntityWithName), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Scene", "Entity@+ createEntity(const string& in, bool)", asFUNCTION(SceneCreateEntityWithNameAndLocalFlag), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Scene", "Entity@+ createEntity(const string& in, bool)", asFUNCTION(SceneCreateEntityWithNameAndLocalFlag), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Scene", "void addEntity(Entity@+)", asMETHOD(Scene, addEntity), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void addEntity(Entity@+)", asMETHOD(Scene, addEntity), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Scene", "void removeEntity(uint)", asMETHODPR(Scene, removeEntity, (EntityID), void), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Scene", "void removeEntity(Entity@+)", asMETHODPR(Scene, removeEntity, (Entity*), void), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Scene", "void removeEntity(const string& in)", asMETHODPR(Scene, removeEntity, (const std::string&), void), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Scene", "void removeEntity(uint)", asMETHODPR(Scene, removeEntity, (EntityID), void), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Scene", "void removeEntity(uint)", asFUNCTION(SceneRemoveEntityByID), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Scene", "void removeEntity(Entity@+)", asFUNCTION(SceneRemoveEntityByPtr), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Scene", "void removeEntity(const string& in)", asFUNCTION(SceneRemoveEntityByName), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Scene", "void removeAllEntities(uint8)", asMETHOD(Scene, removeAllEntities), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void removeAllEntities(uint8)", asMETHOD(Scene, removeAllEntities), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void setTransientPredictionTime(float)", asMETHOD(Scene, setTransientPredictionTime), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void setTransientPredictionTime(float)", asMETHOD(Scene, setTransientPredictionTime), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void setInterpolationConstant(float)", asMETHOD(Scene, setInterpolationConstant), asCALL_THISCALL);
     engine->RegisterObjectMethod("Scene", "void setInterpolationConstant(float)", asMETHOD(Scene, setInterpolationConstant), asCALL_THISCALL);

+ 13 - 0
Engine/Scene/Scene.cpp

@@ -96,6 +96,14 @@ void Scene::update(float timeStep)
     // In networked client scenes, interpolate entities and update transient prediction timers
     // In networked client scenes, interpolate entities and update transient prediction timers
     if ((!isPlayback()) && (isProxy()))
     if ((!isPlayback()) && (isProxy()))
         interpolate(timeStep);
         interpolate(timeStep);
+    
+    // Process delayed removes
+    if (mDelayedRemoveEntities.size())
+    {
+        for (std::set<EntityID>::iterator i = mDelayedRemoveEntities.begin(); i != mDelayedRemoveEntities.end(); ++i)
+            removeEntity(*i);
+        mDelayedRemoveEntities.clear();
+    }
 }
 }
 
 
 void Scene::interpolate(float timeStep)
 void Scene::interpolate(float timeStep)
@@ -943,6 +951,11 @@ void Scene::setPlayback(bool enable)
         i->second->setPlayback(enable);
         i->second->setPlayback(enable);
 }
 }
 
 
+void Scene::addDelayedRemoveEntity(EntityID id)
+{
+    mDelayedRemoveEntities.insert(id);
+}
+
 void Scene::removeEntity(std::map<EntityID, SharedPtr<Entity> >::iterator i)
 void Scene::removeEntity(std::map<EntityID, SharedPtr<Entity> >::iterator i)
 {
 {
     i->second->mScene = 0;
     i->second->mScene = 0;

+ 7 - 0
Engine/Scene/Scene.h

@@ -31,6 +31,8 @@
 #include "VectorBuffer.h"
 #include "VectorBuffer.h"
 #include "XMLElement.h"
 #include "XMLElement.h"
 
 
+#include <set>
+
 class ComponentFactory;
 class ComponentFactory;
 class Deserializer;
 class Deserializer;
 class Engine;
 class Engine;
@@ -197,6 +199,8 @@ public:
     
     
     //! Set client-side prediction controls playback mode. Called by Client
     //! Set client-side prediction controls playback mode. Called by Client
     void setPlayback(bool enable);
     void setPlayback(bool enable);
+    //! Add a delayed self remove of a (scripted) entity, to be processed at the end of scene update
+    void addDelayedRemoveEntity(EntityID id);
     
     
 private:
 private:
     //! Remove an entity by iterator
     //! Remove an entity by iterator
@@ -265,6 +269,9 @@ private:
     unsigned mAsyncLoadedEntities;
     unsigned mAsyncLoadedEntities;
     //! Asynchronous loading flag
     //! Asynchronous loading flag
     bool mAsyncLoading;
     bool mAsyncLoading;
+    
+    //! Delayed entity removes
+    std::set<EntityID> mDelayedRemoveEntities;
 };
 };
 
 
 template <class T> SharedPtr<T> Scene::createComponent(const std::string& name)
 template <class T> SharedPtr<T> Scene::createComponent(const std::string& name)