Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitchell Stokes <mogurijin@gmail.com>2011-05-28 11:15:27 +0400
committerMitchell Stokes <mogurijin@gmail.com>2011-05-28 11:15:27 +0400
commit07dca944766e702453730fe1a55605dab9380c6e (patch)
treec0ac8ab439ef1cd06154353f0d7fa3aa71862ecb
parentbd5f78d1a0bf4e04800395952e9a26ba868cc31a (diff)
BGE Animation:
* Adding IPOs to BL_Action * Adding a "speed" option to adjust the playback speed by some factor
-rw-r--r--source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp6
-rw-r--r--source/gameengine/Converter/KX_BlenderScalarInterpolator.h2
-rw-r--r--source/gameengine/Converter/KX_IpoConvert.cpp210
-rw-r--r--source/gameengine/Converter/KX_IpoConvert.h4
-rw-r--r--source/gameengine/Ketsji/BL_Action.cpp48
-rw-r--r--source/gameengine/Ketsji/BL_Action.h7
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.cpp5
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.h3
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp12
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.cpp12
-rw-r--r--source/gameengine/SceneGraph/SG_IObject.h10
11 files changed, 197 insertions, 122 deletions
diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp
index a9a3e66f996..75c0e012226 100644
--- a/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp
+++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.cpp
@@ -47,11 +47,11 @@ float BL_ScalarInterpolator::GetValue(float currentTime) const {
return evaluate_fcurve(m_fcu, currentTime);
}
-BL_InterpolatorList::BL_InterpolatorList(struct AnimData *adt) {
- if(adt->action==NULL)
+BL_InterpolatorList::BL_InterpolatorList(bAction *action) {
+ if(action==NULL)
return;
- for(FCurve *fcu= (FCurve *)adt->action->curves.first; fcu; fcu= (FCurve *)fcu->next) {
+ for(FCurve *fcu= (FCurve *)action->curves.first; fcu; fcu= (FCurve *)fcu->next) {
if(fcu->rna_path) {
BL_ScalarInterpolator *new_ipo = new BL_ScalarInterpolator(fcu);
//assert(new_ipo);
diff --git a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h
index bd786bae969..cca66b3771c 100644
--- a/source/gameengine/Converter/KX_BlenderScalarInterpolator.h
+++ b/source/gameengine/Converter/KX_BlenderScalarInterpolator.h
@@ -66,7 +66,7 @@ public:
class BL_InterpolatorList : public std::vector<KX_IScalarInterpolator *> {
public:
- BL_InterpolatorList(struct AnimData *adt);
+ BL_InterpolatorList(struct bAction *action);
~BL_InterpolatorList();
KX_IScalarInterpolator *GetScalarInterpolator(const char *rna_path, int array_index);
diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp
index 2ad56717e26..27ae857f45c 100644
--- a/source/gameengine/Converter/KX_IpoConvert.cpp
+++ b/source/gameengine/Converter/KX_IpoConvert.cpp
@@ -54,6 +54,7 @@
#include "DNA_object_types.h"
#include "DNA_action_types.h"
+#include "DNA_anim_types.h"
#include "DNA_ipo_types.h"
#include "DNA_lamp_types.h"
#include "DNA_world_types.h"
@@ -76,133 +77,134 @@ static BL_InterpolatorList *GetAdtList(struct AnimData *for_adt, KX_BlenderScene
BL_InterpolatorList *adtList= converter->FindInterpolatorList(for_adt);
if (!adtList) {
- adtList = new BL_InterpolatorList(for_adt);
+ adtList = new BL_InterpolatorList(for_adt->action);
converter->RegisterInterpolatorList(adtList, for_adt);
}
return adtList;
}
-void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_BlenderSceneConverter *converter)
+SG_Controller *BL_CreateIPO(struct bAction *action, KX_GameObject* gameobj, KX_BlenderSceneConverter *converter)
{
- if (blenderobject->adt) {
-
- KX_IpoSGController* ipocontr = new KX_IpoSGController();
- gameobj->GetSGNode()->AddSGController(ipocontr);
- ipocontr->SetObject(gameobj->GetSGNode());
-
- // For ipo_as_force, we need to know which SM object and Scene the
- // object associated with this ipo is in. Is this already known here?
- // I think not.... then it must be done later :(
-// ipocontr->SetSumoReference(gameobj->GetSumoScene(),
-// gameobj->GetSumoObject());
-
- ipocontr->SetGameObject(gameobj);
-
- ipocontr->GetIPOTransform().SetPosition(
- MT_Point3(
- blenderobject->loc[0]/*+blenderobject->dloc[0]*/,
- blenderobject->loc[1]/*+blenderobject->dloc[1]*/,
- blenderobject->loc[2]/*+blenderobject->dloc[2]*/
- )
- );
- ipocontr->GetIPOTransform().SetEulerAngles(
- MT_Vector3(
- blenderobject->rot[0],
- blenderobject->rot[1],
- blenderobject->rot[2]
- )
- );
- ipocontr->GetIPOTransform().SetScaling(
- MT_Vector3(
- blenderobject->size[0],
- blenderobject->size[1],
- blenderobject->size[2]
- )
- );
-
- const char *rotmode, *drotmode;
-
- switch(blenderobject->rotmode)
- {
- case ROT_MODE_AXISANGLE:
- rotmode = "rotation_axis_angle";
- drotmode = "delta_rotation_axis_angle";
- case ROT_MODE_QUAT:
- rotmode = "rotation_quaternion";
- drotmode = "delta_rotation_quaternion";
- default:
- rotmode = "rotation_euler";
- drotmode = "delta_rotation_euler";
- }
+ KX_IpoSGController* ipocontr = new KX_IpoSGController();
+ ipocontr->SetGameObject(gameobj);
+
+ Object* blenderobject = gameobj->GetBlenderObject();
+
+ ipocontr->GetIPOTransform().SetPosition(
+ MT_Point3(
+ blenderobject->loc[0]/*+blenderobject->dloc[0]*/,
+ blenderobject->loc[1]/*+blenderobject->dloc[1]*/,
+ blenderobject->loc[2]/*+blenderobject->dloc[2]*/
+ )
+ );
+ ipocontr->GetIPOTransform().SetEulerAngles(
+ MT_Vector3(
+ blenderobject->rot[0],
+ blenderobject->rot[1],
+ blenderobject->rot[2]
+ )
+ );
+ ipocontr->GetIPOTransform().SetScaling(
+ MT_Vector3(
+ blenderobject->size[0],
+ blenderobject->size[1],
+ blenderobject->size[2]
+ )
+ );
+
+ const char *rotmode, *drotmode;
+
+ switch(blenderobject->rotmode)
+ {
+ case ROT_MODE_AXISANGLE:
+ rotmode = "rotation_axis_angle";
+ drotmode = "delta_rotation_axis_angle";
+ case ROT_MODE_QUAT:
+ rotmode = "rotation_quaternion";
+ drotmode = "delta_rotation_quaternion";
+ default:
+ rotmode = "rotation_euler";
+ drotmode = "delta_rotation_euler";
+ }
- BL_InterpolatorList *adtList= GetAdtList(blenderobject->adt, converter);
+ BL_InterpolatorList *adtList= GetAdtList(blenderobject->adt, converter);
- // For each active channel in the adtList add an
- // interpolator to the game object.
+ // For each active channel in the adtList add an
+ // interpolator to the game object.
- KX_IInterpolator *interpolator;
- KX_IScalarInterpolator *interp;
+ KX_IInterpolator *interpolator;
+ KX_IScalarInterpolator *interp;
- for(int i=0; i<3; i++) {
- if ((interp = adtList->GetScalarInterpolator("location", i))) {
- interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetPosition()[i]), interp);
- ipocontr->AddInterpolator(interpolator);
- ipocontr->SetIPOChannelActive(OB_LOC_X+i, true);
- }
+ for(int i=0; i<3; i++) {
+ if ((interp = adtList->GetScalarInterpolator("location", i))) {
+ interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetPosition()[i]), interp);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetIPOChannelActive(OB_LOC_X+i, true);
}
- for(int i=0; i<3; i++) {
- if ((interp = adtList->GetScalarInterpolator("delta_location", i))) {
- interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaPosition()[i]), interp);
- ipocontr->AddInterpolator(interpolator);
- ipocontr->SetIPOChannelActive(OB_DLOC_X+i, true);
- }
+ }
+ for(int i=0; i<3; i++) {
+ if ((interp = adtList->GetScalarInterpolator("delta_location", i))) {
+ interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaPosition()[i]), interp);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetIPOChannelActive(OB_DLOC_X+i, true);
}
- for(int i=0; i<3; i++) {
- if ((interp = adtList->GetScalarInterpolator(rotmode, i))) {
- interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetEulerAngles()[i]), interp);
- ipocontr->AddInterpolator(interpolator);
- ipocontr->SetIPOChannelActive(OB_ROT_X+i, true);
- }
+ }
+ for(int i=0; i<3; i++) {
+ if ((interp = adtList->GetScalarInterpolator(rotmode, i))) {
+ interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetEulerAngles()[i]), interp);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetIPOChannelActive(OB_ROT_X+i, true);
}
- for(int i=0; i<3; i++) {
- if ((interp = adtList->GetScalarInterpolator(drotmode, i))) {
- interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[i]), interp);
- ipocontr->AddInterpolator(interpolator);
- ipocontr->SetIPOChannelActive(OB_DROT_X+i, true);
- }
+ }
+ for(int i=0; i<3; i++) {
+ if ((interp = adtList->GetScalarInterpolator(drotmode, i))) {
+ interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[i]), interp);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetIPOChannelActive(OB_DROT_X+i, true);
}
- for(int i=0; i<3; i++) {
- if ((interp = adtList->GetScalarInterpolator("scale", i))) {
- interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetScaling()[i]), interp);
- ipocontr->AddInterpolator(interpolator);
- ipocontr->SetIPOChannelActive(OB_SIZE_X+i, true);
- }
+ }
+ for(int i=0; i<3; i++) {
+ if ((interp = adtList->GetScalarInterpolator("scale", i))) {
+ interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetScaling()[i]), interp);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetIPOChannelActive(OB_SIZE_X+i, true);
}
- for(int i=0; i<3; i++) {
- if ((interp = adtList->GetScalarInterpolator("delta_scale", i))) {
- interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaScaling()[i]), interp);
- ipocontr->AddInterpolator(interpolator);
- ipocontr->SetIPOChannelActive(OB_DSIZE_X+i, true);
- }
+ }
+ for(int i=0; i<3; i++) {
+ if ((interp = adtList->GetScalarInterpolator("delta_scale", i))) {
+ interpolator= new KX_ScalarInterpolator(&(ipocontr->GetIPOTransform().GetDeltaScaling()[i]), interp);
+ ipocontr->AddInterpolator(interpolator);
+ ipocontr->SetIPOChannelActive(OB_DSIZE_X+i, true);
}
+ }
- {
- KX_ObColorIpoSGController* ipocontr_obcol=NULL;
+ {
+ KX_ObColorIpoSGController* ipocontr_obcol=NULL;
- for(int i=0; i<4; i++) {
- if ((interp = adtList->GetScalarInterpolator("color", i))) {
- if (!ipocontr_obcol) {
- ipocontr_obcol = new KX_ObColorIpoSGController();
- gameobj->GetSGNode()->AddSGController(ipocontr_obcol);
- ipocontr_obcol->SetObject(gameobj->GetSGNode());
- }
- interpolator= new KX_ScalarInterpolator(&ipocontr_obcol->m_rgba[i], interp);
- ipocontr_obcol->AddInterpolator(interpolator);
+ for(int i=0; i<4; i++) {
+ if ((interp = adtList->GetScalarInterpolator("color", i))) {
+ if (!ipocontr_obcol) {
+ ipocontr_obcol = new KX_ObColorIpoSGController();
+ gameobj->GetSGNode()->AddSGController(ipocontr_obcol);
+ ipocontr_obcol->SetObject(gameobj->GetSGNode());
}
+ interpolator= new KX_ScalarInterpolator(&ipocontr_obcol->m_rgba[i], interp);
+ ipocontr_obcol->AddInterpolator(interpolator);
}
}
}
+
+ return ipocontr;
+}
+
+void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_BlenderSceneConverter *converter)
+{
+ if (blenderobject->adt) {
+ SG_Controller *ipocontr = BL_CreateIPO(blenderobject->adt->action, gameobj, converter);
+ gameobj->GetSGNode()->AddSGController(ipocontr);
+ ipocontr->SetObject(gameobj->GetSGNode());
+ }
}
void BL_ConvertLampIpos(struct Lamp* blenderlamp, KX_GameObject *lightobj,KX_BlenderSceneConverter *converter)
diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Converter/KX_IpoConvert.h
index d77a72a82e2..914422ba83f 100644
--- a/source/gameengine/Converter/KX_IpoConvert.h
+++ b/source/gameengine/Converter/KX_IpoConvert.h
@@ -36,6 +36,10 @@
struct Object;
+class SG_Controller *BL_CreateIPO(struct bAction *action,
+ class KX_GameObject* gameobj,
+ class KX_BlenderSceneConverter *converter);
+
void BL_ConvertIpos(struct Object* blenderobject,
class KX_GameObject* gameobj,
class KX_BlenderSceneConverter *converter);
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp
index dcd0c1402e1..6cce2a3486d 100644
--- a/source/gameengine/Ketsji/BL_Action.cpp
+++ b/source/gameengine/Ketsji/BL_Action.cpp
@@ -29,6 +29,7 @@
#include "BL_Action.h"
#include "BL_ArmatureObject.h"
+#include "KX_IpoConvert.h"
#include "KX_GameObject.h"
// These three are for getting the action from the logic manager
@@ -49,7 +50,8 @@ BL_Action::BL_Action(class KX_GameObject* gameobj,
float end,
float blendin,
short play_mode,
- short blend_mode)
+ short blend_mode,
+ float playback_speed)
:
m_obj(gameobj),
m_startframe(start),
@@ -60,14 +62,26 @@ BL_Action::BL_Action(class KX_GameObject* gameobj,
m_localtime(start),
m_blendframe(0.f),
m_blendstart(0.f),
+ m_speed(playback_speed),
m_pose(NULL),
m_blendpose(NULL),
+ m_sg_contr(NULL),
m_done(false)
{
m_starttime = KX_GetActiveEngine()->GetFrameTime();
m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name);
if (!m_action) printf("Failed to load action: %s\n", name);
+
+ if (m_obj->GetGameObjectType() != SCA_IObject::OBJ_ARMATURE)
+ {
+ // Create an SG_Controller
+ m_sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter());
+ m_obj->GetSGNode()->AddSGController(m_sg_contr);
+ m_sg_contr->SetObject(m_obj->GetSGNode());
+ InitIPO();
+ }
+
}
BL_Action::~BL_Action()
@@ -76,11 +90,25 @@ BL_Action::~BL_Action()
game_free_pose(m_pose);
if (m_blendpose)
game_free_pose(m_blendpose);
+ if (m_sg_contr)
+ {
+ m_obj->GetSGNode()->RemoveSGController(m_sg_contr);
+ delete m_sg_contr;
+ }
+}
+
+void BL_Action::InitIPO()
+{
+ // Initialize the IPO
+ m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
+ m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, false);
+ m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, false);
+ m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, false);
}
void BL_Action::SetLocalTime(float curtime)
{
- float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate();
+ float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed;
if (m_endframe < m_startframe)
dt = -dt;
@@ -90,12 +118,18 @@ void BL_Action::SetLocalTime(float curtime)
void BL_Action::Update(float curtime)
{
+ // Don't bother if we're done with the animation
+ if (m_done)
+ return;
+
curtime -= KX_KetsjiEngine::GetSuspendedDelta();
SetLocalTime(curtime);
// Handle wrap around
- if (m_localtime < m_startframe || m_localtime > m_endframe)
+ bool bforward = m_startframe < m_endframe;
+ if (bforward && (m_localtime < m_startframe || m_localtime > m_endframe) ||
+ !bforward && (m_localtime > m_startframe || m_localtime < m_endframe))
{
switch(m_playmode)
{
@@ -119,6 +153,9 @@ void BL_Action::Update(float curtime)
break;
}
+
+ if (!m_done)
+ InitIPO();
}
if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
@@ -193,6 +230,9 @@ void BL_Action::Update(float curtime)
}
else
{
- printf("Only armature actions are currently supported\n");
+ InitIPO();
+ m_sg_contr->SetSimulatedTime(m_localtime);
+ m_obj->GetSGNode()->UpdateWorldData(m_localtime);
+ m_obj->UpdateTransform();
}
}
diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h
index 3d977f3984a..203714a3b2f 100644
--- a/source/gameengine/Ketsji/BL_Action.h
+++ b/source/gameengine/Ketsji/BL_Action.h
@@ -41,6 +41,7 @@ private:
struct bPose* m_pose;
struct bPose* m_blendpose;
struct PointerRNA *m_ptrrna;
+ class SG_Controller *m_sg_contr;
class KX_GameObject* m_obj;
float m_startframe;
@@ -53,11 +54,14 @@ private:
float m_blendframe;
float m_blendstart;
+ float m_speed;
+
short m_playmode;
short m_blendmode;
bool m_done;
+ void InitIPO();
void SetLocalTime(float curtime);
public:
BL_Action(class KX_GameObject* gameobj,
@@ -66,7 +70,8 @@ public:
float end,
float blendin,
short play_mode,
- short blend_mode);
+ short blend_mode,
+ float playback_speed);
~BL_Action();
bool IsDone() {return m_done;}
diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp
index 359a7389b51..a4c8a7fe93f 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.cpp
+++ b/source/gameengine/Ketsji/BL_ActionManager.cpp
@@ -49,14 +49,15 @@ void BL_ActionManager::PlayAction(class KX_GameObject* gameobj,
short layer,
float blendin,
short play_mode,
- short blend_mode)
+ short blend_mode,
+ float playback_speed)
{
// Remove a currently running action on this layer if there is one
if (m_layers[layer])
StopAction(layer);
// Create a new action
- m_layers[layer] = new BL_Action(gameobj, name, start, end, blendin, play_mode, blend_mode);
+ m_layers[layer] = new BL_Action(gameobj, name, start, end, blendin, play_mode, blend_mode, playback_speed);
}
void BL_ActionManager::StopAction(short layer)
diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h
index 409d6c24e30..a57e0e1ce87 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.h
+++ b/source/gameengine/Ketsji/BL_ActionManager.h
@@ -49,7 +49,8 @@ public:
short layer=0,
float blendin=0.f,
short play_mode=0,
- short blend_mode=0);
+ short blend_mode=0,
+ float playback_speed=1.f);
void StopAction(short layer);
void Update(float);
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 868dc4591e4..804a3d394ec 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -2992,18 +2992,18 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage,
}
KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
- "playAction(name, start_frame, end_frame, layer=0, blendin=0, play_mode=ACT_MODE_PLAY, blend_mode=ACT_BLEND_NONE)\n"
+ "playAction(name, start_frame, end_frame, layer=0, blendin=0, play_mode=ACT_MODE_PLAY, blend_mode=ACT_BLEND_NONE, speed=1.0)\n"
"plays an action\n")
{
const char* name;
- float start, end, blendin=0.f;
+ float start, end, blendin=0.f, speed=1.f;
short layer=0;
short play_mode=0, blend_mode=0;
- static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "blendin", "play_mode", "blend_mode", NULL};
+ static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "blendin", "play_mode", "blend_mode", "speed", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hfhh", const_cast<char**>(kwlist),
- &name, &start, &end, &layer, &blendin, &play_mode, &blend_mode))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hfhhf", const_cast<char**>(kwlist),
+ &name, &start, &end, &layer, &blendin, &play_mode, &blend_mode, &speed))
return NULL;
if (layer < 0 || layer > MAX_ACTION_LAYERS)
@@ -3024,7 +3024,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
blend_mode = BL_Action::ACT_BLEND_NONE;
}
- m_actionManager->PlayAction(this, name, start, end, layer, blendin, play_mode, blend_mode);
+ m_actionManager->PlayAction(this, name, start, end, layer, blendin, play_mode, blend_mode, speed);
Py_RETURN_NONE;
}
diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp
index 3064e6662b9..b22d210984d 100644
--- a/source/gameengine/SceneGraph/SG_IObject.cpp
+++ b/source/gameengine/SceneGraph/SG_IObject.cpp
@@ -34,6 +34,8 @@
#include "SG_IObject.h"
#include "SG_Controller.h"
+#include <algorithm>
+
SG_Stage gSG_Stage = SG_STAGE_UNKNOWN;
SG_IObject::
@@ -71,6 +73,16 @@ AddSGController(
void
SG_IObject::
+RemoveSGController(
+ SG_Controller* cont
+) {
+ SGControllerList::iterator contit;
+
+ m_SGcontrollers.erase(std::remove(m_SGcontrollers.begin(), m_SGcontrollers.end(), cont));
+}
+
+ void
+SG_IObject::
RemoveAllControllers(
) {
m_SGcontrollers.clear();
diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h
index 26e317bdcd9..e709699c08a 100644
--- a/source/gameengine/SceneGraph/SG_IObject.h
+++ b/source/gameengine/SceneGraph/SG_IObject.h
@@ -180,6 +180,16 @@ public:
SG_Controller* cont
);
+ /**
+ * Remove a pointer to a controller from this node.
+ * This does not delete the controller itself! Be careful to
+ * avoid memory leaks.
+ */
+ void
+ RemoveSGController(
+ SG_Controller* cont
+ );
+
/**
* Clear the array of pointers to controllers associated with
* this node. This does not delete the controllers themselves!