Browse Source

Added DelayedStart() script object method to work around missing child scene nodes during Start().

Lasse Öörni 13 years ago
parent
commit
ea2f6e967a
3 changed files with 39 additions and 5 deletions
  1. 4 1
      Docs/Reference.dox
  2. 31 3
      Engine/Script/ScriptInstance.cpp
  3. 4 1
      Engine/Script/ScriptInstance.h

+ 4 - 1
Docs/Reference.dox

@@ -285,6 +285,7 @@ The following methods that implement the component behaviour will be checked for
 
 - void Start()
 - void Stop()
+- void DelayedStart()
 - void Update(float)
 - void PostUpdate(float)
 - void FixedUpdate(float)
@@ -295,7 +296,9 @@ The following methods that implement the component behaviour will be checked for
 
 The update methods above correspond to the variable timestep scene update and post-update, and the fixed timestep physics world update and post-update. The application-wide update events are not handled by default.
 
-The Start() and Stop() methods do not have direct counterparts in C++ components. Start() is called just after the script object has been created. Stop() is called just before the script object is destroyed. This happens when the ScriptInstance is destroyed, or if the script class is changed.
+The Start() and Stop() methods do not have direct counterparts in C++ components. Start() is called just after the script object has been created. Stop() is called just before the script object is destroyed. This happens when the ScriptInstance is destroyed, or if the script class is changed. 
+
+When a scene node hierarchy with script objects is instantiated (such as when loading a scene) any child nodes may not have been created yet when Start() is executed, and can thus not be relied upon for initialization. The DelayedStart() method can be used in this case instead: if defined, it is called immediately before any of the Update() calls.
 
 Subscribing to \ref Events "events" in script behaves differently depending on whether \ref Object::SubscribeToEvent "SubscribeToEvent()" is called from a script object's method, or from a procedural script function. If called from an object method, the ScriptInstance becomes the event receiver on the C++ side, and forwards the events to the script object. If called from a function, the ScriptFile will be the event receiver. Note that object-based event handling only works when the script object in question is attached to a ScriptInstance component, as a C++ side proxy is always needed. If you simply create a new free-standing object in script, it will not be able to subscribe to events.
 

+ 31 - 3
Engine/Script/ScriptInstance.cpp

@@ -42,6 +42,7 @@
 static const String methodDeclarations[] = {
     "void Start()",
     "void Stop()",
+    "void DelayedStart()",
     "void Update(float)",
     "void PostUpdate(float)",
     "void FixedUpdate(float)",
@@ -58,6 +59,7 @@ ScriptInstance::ScriptInstance(Context* context) :
     script_(GetSubsystem<Script>()),
     scriptObject_(0),
     active_(true),
+    delayedStart_(false),
     fixedUpdateFps_(0),
     fixedUpdateInterval_(0.0f),
     fixedUpdateAcc_(0.0f),
@@ -86,8 +88,8 @@ void ScriptInstance::RegisterObject(Context* context)
 
 void ScriptInstance::ApplyAttributes()
 {
-    if (scriptObject_ && methods_[METHOD_FINISHUPDATE])
-        scriptFile_->Execute(scriptObject_, methods_[METHOD_FINISHUPDATE]);
+    if (scriptObject_ && methods_[METHOD_APPLYATTRIBUTES])
+        scriptFile_->Execute(scriptObject_, methods_[METHOD_APPLYATTRIBUTES]);
 }
 
 bool ScriptInstance::CreateObject(ScriptFile* scriptFile, const String& className)
@@ -336,7 +338,6 @@ void ScriptInstance::ReleaseObject()
         
         UnsubscribeFromAllEvents();
         ClearMethods();
-        ClearDelayedExecute();
         
         scriptObject_->SetUserData(0);
         scriptObject_->Release();
@@ -375,6 +376,8 @@ void ScriptInstance::GetSupportedMethods()
                 SubscribeToEvent(world, E_PHYSICSPOSTSTEP, HANDLER(ScriptInstance, HandlePhysicsPostStep));
         }
     }
+    
+    delayedStart_ = false;
 }
 
 void ScriptInstance::HandleSceneUpdate(StringHash eventType, VariantMap& eventData)
@@ -399,6 +402,13 @@ void ScriptInstance::HandleSceneUpdate(StringHash eventType, VariantMap& eventDa
             ++i;
     }
     
+    // Execute delayed start before first update
+    if (methods_[METHOD_DELAYEDSTART] && !delayedStart_)
+    {
+        scriptFile_->Execute(scriptObject_, methods_[METHOD_DELAYEDSTART]);
+        delayedStart_ = true;
+    }
+    
     if (methods_[METHOD_UPDATE])
     {
         VariantVector parameters;
@@ -414,6 +424,12 @@ void ScriptInstance::HandleScenePostUpdate(StringHash eventType, VariantMap& eve
     
     using namespace ScenePostUpdate;
     
+    if (methods_[METHOD_DELAYEDSTART] && !delayedStart_)
+    {
+        scriptFile_->Execute(scriptObject_, methods_[METHOD_DELAYEDSTART]);
+        delayedStart_ = true;
+    }
+    
     VariantVector parameters;
     parameters.Push(eventData[P_TIMESTEP]);
     scriptFile_->Execute(scriptObject_, methods_[METHOD_POSTUPDATE], parameters);
@@ -426,6 +442,12 @@ void ScriptInstance::HandlePhysicsPreStep(StringHash eventType, VariantMap& even
     
     using namespace PhysicsPreStep;
     
+    if (methods_[METHOD_DELAYEDSTART] && !delayedStart_)
+    {
+        scriptFile_->Execute(scriptObject_, methods_[METHOD_DELAYEDSTART]);
+        delayedStart_ = true;
+    }
+    
     if (!fixedUpdateFps_)
     {
         VariantVector parameters;
@@ -453,6 +475,12 @@ void ScriptInstance::HandlePhysicsPostStep(StringHash eventType, VariantMap& eve
     
     using namespace PhysicsPostStep;
     
+    if (methods_[METHOD_DELAYEDSTART] && !delayedStart_)
+    {
+        scriptFile_->Execute(scriptObject_, methods_[METHOD_DELAYEDSTART]);
+        delayedStart_ = true;
+    }
+    
     if (!fixedUpdateFps_)
     {
         VariantVector parameters;

+ 4 - 1
Engine/Script/ScriptInstance.h

@@ -36,13 +36,14 @@ enum ScriptInstanceMethod
 {
     METHOD_START = 0,
     METHOD_STOP,
+    METHOD_DELAYEDSTART,
     METHOD_UPDATE,
     METHOD_POSTUPDATE,
     METHOD_FIXEDUPDATE,
     METHOD_FIXEDPOSTUPDATE,
     METHOD_LOAD,
     METHOD_SAVE,
-    METHOD_FINISHUPDATE,
+    METHOD_APPLYATTRIBUTES,
     MAX_SCRIPT_METHODS
 };
 
@@ -160,6 +161,8 @@ private:
     asIScriptFunction* methods_[MAX_SCRIPT_METHODS];
     /// Active flag.
     bool active_;
+    /// DelayedStart called flag.
+    bool delayedStart_;
     /// Fixed update FPS.
     int fixedUpdateFps_;
     /// Fixed update time interval.