BGE Animations: Adding in layer weights to allow for layer blending.
authorMitchell Stokes <mogurijin@gmail.com>
Sun, 3 Jul 2011 01:59:17 +0000 (01:59 +0000)
committerMitchell Stokes <mogurijin@gmail.com>
Sun, 3 Jul 2011 01:59:17 +0000 (01:59 +0000)
14 files changed:
source/blender/editors/space_logic/logic_window.c
source/blender/makesdna/DNA_actuator_types.h
source/blender/makesrna/intern/rna_actuator.c
source/gameengine/Converter/BL_ActionActuator.cpp
source/gameengine/Converter/BL_ActionActuator.h
source/gameengine/Converter/BL_ArmatureObject.cpp
source/gameengine/Converter/BL_ArmatureObject.h
source/gameengine/Converter/KX_ConvertActuators.cpp
source/gameengine/Ketsji/BL_Action.cpp
source/gameengine/Ketsji/BL_Action.h
source/gameengine/Ketsji/BL_ActionManager.cpp
source/gameengine/Ketsji/BL_ActionManager.h
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h

index c1fc27e..882d89f 100644 (file)
@@ -3713,6 +3713,7 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr)
 
        row= uiLayoutRow(layout, 0);
        uiItemR(row, ptr, "layer", 0, NULL, ICON_NONE);
+       uiItemR(row, ptr, "layer_weight", 0, NULL, ICON_NONE);
 
        row= uiLayoutRow(layout, 0);
        uiItemPointerR(layout, ptr, "frame_property", &settings_ptr, "properties", NULL, ICON_NONE);
index 071f66c..93db834 100644 (file)
@@ -59,8 +59,9 @@ typedef struct bActionActuator {
        short   layer;                  /* Animation layer */
        short   end_reset;      /* Ending the actuator (negative pulse) wont reset the the action to its starting frame */
        short   strideaxis;             /* Displacement axis */
-       short   pad[3];
+       short   pad;
        float   stridelength;   /* Displacement incurred by cycle */ // not in use
+       float   layer_weight;   /* How much of the previous layer to use for blending. (<0 = disable, 0 = add mode) */
 } bActionActuator;                                                                                             
 
 typedef struct Sound3D
index ebda1b8..3c44720 100644 (file)
@@ -631,6 +631,11 @@ static void rna_def_action_actuator(BlenderRNA *brna)
        RNA_def_property_ui_text(prop, "Layer", "The animation layer to play the action on");
        RNA_def_property_update(prop, NC_LOGIC, NULL);
 
+       prop= RNA_def_property(srna, "layer_weight", PROP_FLOAT, PROP_NONE);
+       RNA_def_property_range(prop, 0.0, 1.0);
+       RNA_def_property_ui_text(prop, "Layer Weight", "How much of the previous layer to blend into this one (0 = add mode)");
+       RNA_def_property_update(prop, NC_LOGIC, NULL);
+
        prop= RNA_def_property(srna, "frame_property", PROP_STRING, PROP_NONE);
        RNA_def_property_string_sdna(prop, NULL, "frameProp");
        RNA_def_property_ui_text(prop, "Frame Property", "Assign the action's current frame number to this property");
index 7c86f19..05e6120 100644 (file)
@@ -184,7 +184,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
        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, 0, m_ipo_flags) && m_end_reset)
+               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);
        }
        else if (m_is_going && bNegativeEvent)
@@ -203,7 +203,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame)
                else if (m_playtype == ACT_ACTION_LOOP_END)
                {
                        // Convert into a play and let it finish
-                       obj->PlayAction(m_action->id.name+2, start, end, m_layer, 0, 0, BL_Action::ACT_MODE_PLAY, 0, m_ipo_flags);
+                       obj->PlayAction(m_action->id.name+2, start, end, m_layer, 0, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags);
                        obj->SetActionFrame(m_layer, m_localtime);
 
                        return true;
index 96b9b5e..3004aa2 100644 (file)
@@ -53,6 +53,7 @@ public:
                                                short   blendin,
                                                short   priority,
                                                short   layer,
+                                               float   layer_weight,
                                                short   ipo_flags,
                                                short   end_reset,
                                                float   stride) 
@@ -72,6 +73,7 @@ public:
                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),
@@ -165,6 +167,7 @@ protected:
        float   m_blendin;
        float   m_blendstart;
        float   m_stridelength;
+       float   m_layer_weight;
        short   m_playtype;
        short   m_priority;
        short   m_layer;
index f33eafc..7fd4087 100644 (file)
@@ -137,13 +137,14 @@ void game_copy_pose(bPose **dst, bPose *src, int copy_constraint)
 
 
 /* Only allowed for Poses with identical channels */
-void game_blend_poses(bPose *dst, bPose *src, float srcweight, short mode)
+void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
 {      
        bPoseChannel *dchan;
        const bPoseChannel *schan;
        bConstraint *dcon, *scon;
        float dstweight;
        int i;
+       short mode = ACTSTRIPMODE_BLEND;
 
        switch (mode){
        case ACTSTRIPMODE_BLEND:
index 92a9a36..2c3ca74 100644 (file)
@@ -145,7 +145,7 @@ protected:
 };
 
 /* Pose function specific to the game engine */
-void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight, short mode); /* was blend_poses */
+void game_blend_poses(struct bPose *dst, struct bPose *src, float srcweight/*, short mode*/); /* was blend_poses */
 //void extract_pose_from_pose(struct bPose *pose, const struct bPose *src);
 void game_copy_pose(struct bPose **dst, struct bPose *src, int copy_con);
 void game_free_pose(struct bPose *pose);
index e952fb2..a06e16b 100644 (file)
@@ -220,6 +220,7 @@ void BL_ConvertActuators(char* maggiename,
                                        actact->blendin,
                                        actact->priority,
                                        actact->layer,
+                                       actact->layer_weight,
                                        ipo_flags,
                                        actact->end_reset,
                                        actact->stridelength
index dec3428..f764a4b 100644 (file)
@@ -46,7 +46,6 @@ extern "C" {
 #include "BKE_action.h"
 #include "RNA_access.h"
 #include "RNA_define.h"
-#include "DNA_nla_types.h"
 }
 
 BL_Action::BL_Action(class KX_GameObject* gameobj)
@@ -111,7 +110,7 @@ bool BL_Action::Play(const char* name,
                                        short priority,
                                        float blendin,
                                        short play_mode,
-                                       short blend_mode,
+                                       float layer_weight,
                                        short ipo_flags,
                                        float playback_speed)
 {
@@ -173,11 +172,11 @@ bool BL_Action::Play(const char* name,
        m_endframe = end;
        m_blendin = blendin;
        m_playmode = play_mode;
-       m_blendmode = blend_mode;
        m_endtime = 0.f;
        m_blendframe = 0.f;
        m_blendstart = 0.f;
        m_speed = playback_speed;
+       m_layer_weight = layer_weight;
        
        m_done = false;
 
@@ -335,15 +334,15 @@ void BL_Action::Update(float curtime)
                        float weight = 1.f - (m_blendframe/m_blendin);
 
                        // Blend the poses
-                       game_blend_poses(m_pose, m_blendpose, weight, ACTSTRIPMODE_BLEND);
+                       game_blend_poses(m_pose, m_blendpose, weight);
                }
 
 
                // Handle layer blending
-               if (m_blendmode != ACT_BLEND_NONE)
+               if (m_layer_weight >= 0)
                {
                        obj->GetMRDPose(&m_blendpose);
-                       game_blend_poses(m_pose, m_blendpose, 1.f, ACTSTRIPMODE_ADD);
+                       game_blend_poses(m_pose, m_blendpose, m_layer_weight);
                }
 
                obj->SetPose(m_pose);
index d9a2187..f03a22a 100644 (file)
@@ -58,12 +58,13 @@ private:
        float m_blendframe;
        float m_blendstart;
 
+       float m_layer_weight;
+
        float m_speed;
 
        short m_priority;
 
        short m_playmode;
-       short m_blendmode;
 
        short m_ipo_flags;
 
@@ -84,7 +85,7 @@ public:
                        short priority,
                        float blendin,
                        short play_mode,
-                       short blend_mode,
+                       float layer_weight,
                        short ipo_flags,
                        float playback_speed);
        void Stop();
@@ -105,13 +106,6 @@ public:
                ACT_MODE_MAX,
        };
 
-       enum
-       {
-               ACT_BLEND_NONE = 0,
-               ACT_BLEND_MIX,
-               ACT_BLEND_MAX,
-       };
-
        enum
        {
                ACT_IPOFLAG_FORCE = 1,
index 096235e..8d862c3 100644 (file)
@@ -63,14 +63,14 @@ bool BL_ActionManager::PlayAction(const char* name,
                                                                short priority,
                                                                float blendin,
                                                                short play_mode,
-                                                               short blend_mode,
+                                                               float layer_weight,
                                                                short ipo_flags,
                                                                float playback_speed)
 {
        // Disable layer blending on the first layer
-       if (layer == 0) blend_mode = BL_Action::ACT_BLEND_NONE;
+       if (layer == 0) layer_weight = -1.f;
 
-       return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, blend_mode, ipo_flags, playback_speed);
+       return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
 }
 
 void BL_ActionManager::StopAction(short layer)
index 99053ba..3836c6b 100644 (file)
@@ -49,7 +49,7 @@ public:
                                        short priority=0,
                                        float blendin=0.f,
                                        short play_mode=0,
-                                       short blend_mode=0,
+                                       float layer_weight=0.f,
                                        short ipo_flags=0,
                                        float playback_speed=1.f);
        
index 35fe956..334868d 100644 (file)
@@ -367,11 +367,11 @@ bool KX_GameObject::PlayAction(const char* name,
                                                                short priority,
                                                                float blendin,
                                                                short play_mode,
-                                                               short blend_mode,
+                                                               float layer_weight,
                                                                short ipo_flags,
                                                                float playback_speed)
 {
-       return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, blend_mode, ipo_flags, playback_speed);
+       return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
 }
 
 void KX_GameObject::StopAction(short layer)
@@ -3037,19 +3037,19 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage,
 }
 
 KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
-       "playAction(name, start_frame, end_frame, layer=0, priority=0 blendin=0, play_mode=ACT_MODE_PLAY, blend_mode=ACT_BLEND_NONE, ipo_flags=0, speed=1.0)\n"
+       "playAction(name, start_frame, end_frame, layer=0, priority=0 blendin=0, play_mode=ACT_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0)\n"
        "plays an action\n")
 {
        const char* name;
-       float start, end, blendin=0.f, speed=1.f;
+       float start, end, blendin=0.f, speed=1.f, layer_weight=0.f;
        short layer=0, priority=0;
        short ipo_flags=0;
-       short play_mode=0, blend_mode=0;
+       short play_mode=0;
 
-       static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "blend_mode", "ipo_flags", "speed", NULL};
+       static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", NULL};
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhhhf:playAction", const_cast<char**>(kwlist),
-                                                                       &name, &start, &end, &layer, &priority, &blendin, &play_mode, &blend_mode, &ipo_flags, &speed))
+       if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhf:playAction", const_cast<char**>(kwlist),
+                                                                       &name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed))
                return NULL;
 
        if (layer < 0 || layer > MAX_ACTION_LAYERS)
@@ -3064,13 +3064,13 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
                play_mode = BL_Action::ACT_MODE_MAX;
        }
 
-       if (blend_mode < 0 || blend_mode > BL_Action::ACT_BLEND_MAX)
+       if (layer_weight < 0.f || layer_weight > 1.f)
        {
-               printf("KX_GameObject.playAction(): given blend_mode (%d) is out of range (0 - %d), setting to ACT_BLEND_NONE", blend_mode, BL_Action::ACT_BLEND_MAX-1);
-               blend_mode = BL_Action::ACT_BLEND_NONE;
+               printf("KX_GameObject.playAction(): given layer_weight (%f) is out of range (0.0 - 1.0), setting to 0.0", layer_weight);
+               layer_weight = 0.f;
        }
 
-       PlayAction(name, start, end, layer, priority, blendin, play_mode, blend_mode, ipo_flags, speed);
+       PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed);
 
        Py_RETURN_NONE;
 }
index b43b5e0..96bd42b 100644 (file)
@@ -218,7 +218,7 @@ public:
                                        short priority=0,
                                        float blendin=0.f,
                                        short play_mode=0,
-                                       short blend_mode=0,
+                                       float layer_weight=0.f,
                                        short ipo_flags=0,
                                        float playback_speed=1.f);