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:
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.cpp145
-rw-r--r--source/gameengine/Converter/BL_ActionActuator.h53
-rw-r--r--source/gameengine/Ketsji/BL_Action.cpp34
-rw-r--r--source/gameengine/Ketsji/BL_Action.h2
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.cpp6
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.h2
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp5
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h6
8 files changed, 168 insertions, 85 deletions
diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp
index 1cfd46c7e11..f52f8387a6d 100644
--- a/source/gameengine/Converter/BL_ActionActuator.cpp
+++ b/source/gameengine/Converter/BL_ActionActuator.cpp
@@ -61,6 +61,49 @@ extern "C" {
#include "RNA_define.h"
}
+BL_ActionActuator::BL_ActionActuator(SCA_IObject* gameobj,
+ const STR_String& propname,
+ const STR_String& framepropname,
+ float starttime,
+ float endtime,
+ struct bAction *action,
+ short playtype,
+ short blendin,
+ short priority,
+ short layer,
+ float layer_weight,
+ short ipo_flags,
+ short end_reset,
+ float stride)
+ : SCA_IActuator(gameobj, KX_ACT_ACTION),
+
+ m_lastpos(0, 0, 0),
+ m_blendframe(0),
+ m_flag(0),
+ m_startframe (starttime),
+ m_endframe(endtime) ,
+ m_starttime(0),
+ m_localtime(starttime),
+ m_lastUpdate(-1),
+ m_blendin(blendin),
+ m_blendstart(0),
+ m_stridelength(stride),
+ m_playtype(playtype),
+ m_priority(priority),
+ m_layer(layer),
+ m_layer_weight(layer_weight),
+ m_ipo_flags(ipo_flags),
+ m_pose(NULL),
+ m_blendpose(NULL),
+ m_userpose(NULL),
+ m_action(action),
+ m_propname(propname),
+ m_framepropname(framepropname)
+{
+ if (!end_reset)
+ m_flag |= ACT_FLAG_CONTINUE;
+};
+
BL_ActionActuator::~BL_ActionActuator()
{
if (m_pose)
@@ -92,6 +135,7 @@ CValue* BL_ActionActuator::GetReplica() {
return replica;
}
+#if 0
bool BL_ActionActuator::ClampLocalTime()
{
if (m_startframe < m_endframe)
@@ -143,7 +187,7 @@ void BL_ActionActuator::SetLocalTime(float curtime)
else
m_localtime = m_endframe - delta_time;
}
-
+#endif
bool BL_ActionActuator::Update(double curtime, bool frame)
{
bool bNegativeEvent = false;
@@ -156,10 +200,6 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
if (!m_action)
return false;
- // Don't do anything if we're not "active"
- if (!frame)
- return true;
-
// Convert playmode
if (m_playtype == ACT_ACTION_LOOP_END)
play_mode = BL_Action::ACT_MODE_LOOP;
@@ -173,32 +213,56 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
play_mode = BL_Action::ACT_MODE_PLAY;
start = end = prop->GetNumber();
- m_is_going = false;
}
-
+
+
// Handle events
- bNegativeEvent = m_negevent;
- bPositiveEvent = m_posevent;
- RemoveAllEvents();
-
- if (!m_is_going && bPositiveEvent)
- {
- m_is_going = true;
- if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, play_mode, m_layer_weight, m_ipo_flags) && m_end_reset)
- obj->SetActionFrame(m_layer, m_localtime);
+ if (frame)
+ {
+ bNegativeEvent = m_negevent;
+ bPositiveEvent = m_posevent;
+ RemoveAllEvents();
}
- else if (m_is_going && bNegativeEvent)
- {
- if (m_playtype == ACT_ACTION_LOOP_STOP)
+
+ if (bPositiveEvent)
+ {
+ if (m_flag & ACT_FLAG_ACTIVE && m_flag & ACT_FLAG_CONTINUE)
+ start = m_localtime = obj->GetActionFrame(m_layer);
+
+ if (obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, m_blendin, play_mode, m_layer_weight, m_ipo_flags))
{
- if (!m_end_reset)
- {
- obj->StopAction(m_layer);
- return false;
- }
+ m_flag |= ACT_FLAG_ACTIVE;
+ if (m_flag & ACT_FLAG_CONTINUE)
+ obj->SetActionFrame(m_layer, m_localtime);
+
+ if (m_playtype == ACT_ACTION_PLAY)
+ m_flag |= ACT_FLAG_PLAY_END;
+ else
+ m_flag &= ~ACT_FLAG_PLAY_END;
+ }
+ else
+ return false;
+ }
+ else if ((m_flag & ACT_FLAG_ACTIVE) && bNegativeEvent)
+ {
+ bAction *curr_action = obj->GetCurrentAction(m_layer);
+ if (curr_action && curr_action != m_action)
+ {
+ // Someone changed the action on us, so we wont mess with it
+ // Hopefully there wont be too many problems with two actuators using
+ // the same action...
+ m_flag &= ~ACT_FLAG_ACTIVE;
+ return false;
+ }
+ if (m_playtype == ACT_ACTION_LOOP_STOP)
+ {
m_localtime = obj->GetActionFrame(m_layer);
obj->StopAction(m_layer); // Stop the action after getting the frame
+
+ // We're done
+ m_flag &= ~ACT_FLAG_ACTIVE;
+ return false;
}
else if (m_playtype == ACT_ACTION_LOOP_END)
{
@@ -207,7 +271,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
obj->StopAction(m_layer);
obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags);
- return true;
+ m_flag |= ACT_FLAG_PLAY_END;
}
else if (m_playtype == ACT_ACTION_FLIPPER)
{
@@ -217,14 +281,12 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
obj->StopAction(m_layer);
obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags);
- return true;
+ m_flag |= ACT_FLAG_PLAY_END;
}
-
- m_is_going = false;
}
// Handle a frame property if it's defined
- if (m_is_going && m_framepropname[0] != 0)
+ if ((m_flag & ACT_FLAG_ACTIVE) && m_framepropname[0] != 0)
{
CValue* oldprop = obj->GetProperty(m_framepropname);
CValue* newval = new CFloatValue(obj->GetActionFrame(m_layer));
@@ -235,10 +297,11 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
newval->Release();
}
+
// Handle a finished animation
- if (m_is_going && obj->IsActionDone(m_layer))
+ if ((m_flag & ACT_FLAG_PLAY_END) && obj->IsActionDone(m_layer))
{
- m_is_going = false;
+ m_flag &= ~ACT_FLAG_ACTIVE;
obj->StopAction(m_layer);
return false;
}
@@ -740,7 +803,7 @@ PyAttributeDef BL_ActionActuator::Attributes[] = {
KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame),
KX_PYATTRIBUTE_STRING_RW("propName", 0, 31, false, BL_ActionActuator, m_propname),
KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 31, false, BL_ActionActuator, m_framepropname),
- KX_PYATTRIBUTE_BOOL_RW("useContinue", BL_ActionActuator, m_end_reset),
+ KX_PYATTRIBUTE_RW_FUNCTION("useContinue", BL_ActionActuator, pyattr_get_use_continue, pyattr_set_use_continue),
KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime),
KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",0,100,false,BL_ActionActuator,m_playtype,CheckType),
{ NULL } //Sentinel
@@ -800,4 +863,22 @@ PyObject* BL_ActionActuator::pyattr_get_channel_names(void *self_v, const KX_PYA
return ret;
}
+PyObject* BL_ActionActuator::pyattr_get_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
+ return PyBool_FromLong(self->m_flag & ACT_FLAG_CONTINUE);
+}
+
+int BL_ActionActuator::pyattr_set_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ BL_ActionActuator* self= static_cast<BL_ActionActuator*>(self_v);
+
+ if (PyObject_IsTrue(value))
+ self->m_flag |= ACT_FLAG_CONTINUE;
+ else
+ self->m_flag &= ~ACT_FLAG_CONTINUE;
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
#endif // WITH_PYTHON
diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h
index 3004aa2e6ca..7b4200fa19b 100644
--- a/source/gameengine/Converter/BL_ActionActuator.h
+++ b/source/gameengine/Converter/BL_ActionActuator.h
@@ -56,35 +56,8 @@ public:
float layer_weight,
short ipo_flags,
short end_reset,
- float stride)
- : SCA_IActuator(gameobj, KX_ACT_ACTION),
-
- m_lastpos(0, 0, 0),
- m_blendframe(0),
- m_flag(0),
- m_startframe (starttime),
- m_endframe(endtime) ,
- m_starttime(0),
- m_localtime(starttime),
- m_lastUpdate(-1),
- m_blendin(blendin),
- m_blendstart(0),
- m_stridelength(stride),
- m_playtype(playtype),
- m_priority(priority),
- m_layer(layer),
- m_layer_weight(layer_weight),
- m_ipo_flags(ipo_flags),
- m_end_reset(end_reset),
- m_is_going(false),
- m_pose(NULL),
- m_blendpose(NULL),
- m_userpose(NULL),
- m_action(action),
- m_propname(propname),
- m_framepropname(framepropname)
- {
- };
+ float stride);
+
virtual ~BL_ActionActuator();
virtual bool Update(double curtime, bool frame);
virtual CValue* GetReplica();
@@ -103,6 +76,9 @@ public:
static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_channel_names(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static PyObject* pyattr_get_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_use_continue(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
/* attribute check */
static int CheckFrame(void *self, const PyAttributeDef*)
{
@@ -147,9 +123,9 @@ public:
protected:
- void SetStartTime(float curtime);
- void SetLocalTime(float curtime);
- bool ClampLocalTime();
+ //void SetStartTime(float curtime);
+ //void SetLocalTime(float curtime);
+ //bool ClampLocalTime();
MT_Point3 m_lastpos;
float m_blendframe;
@@ -172,8 +148,6 @@ protected:
short m_priority;
short m_layer;
short m_ipo_flags;
- bool m_end_reset;
- bool m_is_going;
struct bPose* m_pose;
struct bPose* m_blendpose;
struct bPose* m_userpose;
@@ -183,10 +157,13 @@ protected:
};
enum {
- ACT_FLAG_REVERSE = 0x00000001,
- ACT_FLAG_LOCKINPUT = 0x00000002,
- ACT_FLAG_KEYUP = 0x00000004,
- ACT_FLAG_ACTIVE = 0x00000008
+ ACT_FLAG_REVERSE = 1<<0,
+ ACT_FLAG_LOCKINPUT = 1<<1,
+ ACT_FLAG_KEYUP = 1<<2,
+ ACT_FLAG_ACTIVE = 1<<3,
+ ACT_FLAG_CONTINUE = 1<<4,
+ ACT_FLAG_PLAY_END = 1<<5
+
};
#endif
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp
index 04d05d87c06..f1b53fc4151 100644
--- a/source/gameengine/Ketsji/BL_Action.cpp
+++ b/source/gameengine/Ketsji/BL_Action.cpp
@@ -62,8 +62,7 @@ BL_Action::BL_Action(class KX_GameObject* gameobj)
m_blendinpose(NULL),
m_sg_contr(NULL),
m_ptrrna(NULL),
- m_done(true),
- m_bcalc_local_time(true)
+ m_done(true)
{
if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
{
@@ -197,6 +196,11 @@ void BL_Action::InitIPO()
m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL);
}
+bAction *BL_Action::GetAction()
+{
+ return (IsDone()) ? NULL : m_action;
+}
+
float BL_Action::GetFrame()
{
return m_localtime;
@@ -204,14 +208,24 @@ float BL_Action::GetFrame()
void BL_Action::SetFrame(float frame)
{
+ float dt;
+
// Clamp the frame to the start and end frame
if (frame < min(m_startframe, m_endframe))
frame = min(m_startframe, m_endframe);
else if (frame > max(m_startframe, m_endframe))
frame = max(m_startframe, m_endframe);
+
+ // We don't set m_localtime directly since it's recalculated
+ // in the next update. So, we modify the value (m_starttime)
+ // used to calculate m_localtime the next time SetLocalTime() is called.
+
+ dt = frame-m_startframe;
+
+ if (m_endframe < m_startframe)
+ dt = -dt;
- m_localtime = frame;
- m_bcalc_local_time = false;
+ m_starttime -= dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed);
}
void BL_Action::SetLocalTime(float curtime)
@@ -263,16 +277,8 @@ void BL_Action::Update(float curtime)
if (m_done)
return;
- // We only want to calculate the current time if we weren't given a frame (e.g., from SetFrame())
- if (m_bcalc_local_time)
- {
- curtime -= KX_KetsjiEngine::GetSuspendedDelta();
- SetLocalTime(curtime);
- }
- else
- {
- m_bcalc_local_time = true;
- }
+ curtime -= KX_KetsjiEngine::GetSuspendedDelta();
+ SetLocalTime(curtime);
// Handle wrap around
if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe))
diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h
index eea00b15036..f7c5a811721 100644
--- a/source/gameengine/Ketsji/BL_Action.h
+++ b/source/gameengine/Ketsji/BL_Action.h
@@ -66,7 +66,6 @@ private:
short m_ipo_flags;
bool m_done;
- bool m_bcalc_local_time;
void InitIPO();
void SetLocalTime(float curtime);
@@ -91,6 +90,7 @@ public:
// Accessors
float GetFrame();
+ struct bAction *GetAction();
// Mutators
void SetFrame(float frame);
diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp
index 8d862c38961..c3b4dc5d4db 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.cpp
+++ b/source/gameengine/Ketsji/BL_ActionManager.cpp
@@ -56,6 +56,12 @@ void BL_ActionManager::SetActionFrame(short layer, float frame)
m_layers[layer]->SetFrame(frame);
}
+struct bAction *BL_ActionManager::GetCurrentAction(short layer)
+{
+ if (m_layers[layer])
+ return m_layers[layer]->GetAction();
+}
+
bool BL_ActionManager::PlayAction(const char* name,
float start,
float end,
diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h
index 3836c6b59d2..c527c7bbd3a 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.h
+++ b/source/gameengine/Ketsji/BL_ActionManager.h
@@ -56,6 +56,8 @@ public:
float GetActionFrame(short layer);
void SetActionFrame(short layer, float frame);
+ struct bAction *GetCurrentAction(short layer);
+
void StopAction(short layer);
bool IsActionDone(short layer);
void Update(float);
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 334868d283a..3404cd227f0 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -399,6 +399,11 @@ void KX_GameObject::SetActionFrame(short layer, float frame)
GetActionManager()->SetActionFrame(layer, frame);
}
+bAction *KX_GameObject::GetCurrentAction(short layer)
+{
+ return GetActionManager()->GetCurrentAction(layer);
+}
+
void KX_GameObject::ProcessReplica()
{
SCA_IObject::ProcessReplica();
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 96bd42ba702..6e22dc5fbc3 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -65,6 +65,7 @@ class PHY_IGraphicController;
class PHY_IPhysicsEnvironment;
class BL_ActionManager;
struct Object;
+struct bAction;
#ifdef WITH_PYTHON
/* utility conversion function */
@@ -233,6 +234,11 @@ public:
void SetActionFrame(short layer, float frame);
/**
+ * Gets the currently running action on the given layer
+ */
+ bAction *GetCurrentAction(short layer);
+
+ /**
* Remove an action from the object's action manager
*/
void StopAction(short layer);