BGE: Finally adding support for additive layer blending.
Currently this is only for the Python API. The logic brick will be updated in a future commit.
This commit is contained in:
@@ -1114,6 +1114,19 @@ See :class:`bge.types.KX_GameObject.playAction`
|
||||
|
||||
:value: 2
|
||||
|
||||
.. _gameobject-playaction-blend:
|
||||
|
||||
.. data:: KX_ACTION_BLEND_BLEND
|
||||
|
||||
Blend layers using linear interpolation
|
||||
|
||||
:value: 0
|
||||
|
||||
.. data:: KX_ACTION_BLEND_ADD
|
||||
|
||||
Adds the layers together
|
||||
|
||||
:value: 1
|
||||
|
||||
-------------
|
||||
Mouse Buttons
|
||||
|
@@ -776,7 +776,7 @@ base class --- :class:`SCA_IObject`
|
||||
Return the value matching key, or the default value if its not found.
|
||||
:return: The key value or a default.
|
||||
|
||||
.. method:: 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)
|
||||
.. method:: playAction(name, start_frame, end_frame, layer=0, priority=0, blendin=0, play_mode=KX_ACTION_MODE_PLAY, layer_weight=0.0, ipo_flags=0, speed=1.0, blend_mode=KX_ACTION_BLEND_BLEND)
|
||||
|
||||
Plays an action.
|
||||
|
||||
@@ -794,12 +794,14 @@ base class --- :class:`SCA_IObject`
|
||||
:type blendin: float
|
||||
:arg play_mode: the play mode
|
||||
:type play_mode: one of :ref:`these constants <gameobject-playaction-mode>`
|
||||
:arg layer_weight: how much of the previous layer to use for blending (0 = add)
|
||||
:arg layer_weight: how much of the previous layer to use for blending
|
||||
:type layer_weight: float
|
||||
:arg ipo_flags: flags for the old IPO behaviors (force, etc)
|
||||
:type ipo_flags: int bitfield
|
||||
:arg speed: the playback speed of the action as a factor (1.0 = normal speed, 2.0 = 2x speed, etc)
|
||||
:type speed: float
|
||||
:arg blend_mode: how to blend this layer with previous layers
|
||||
:type blend_mode: one of :ref:`these constants <gameobject-playaction-blend>`
|
||||
|
||||
.. method:: stopAction(layer=0)
|
||||
|
||||
|
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "BL_ArmatureObject.h"
|
||||
#include "BL_ActionActuator.h"
|
||||
#include "BL_Action.h"
|
||||
#include "KX_BlenderSceneConverter.h"
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "BLI_blenlib.h"
|
||||
@@ -50,7 +51,6 @@
|
||||
#include "DNA_armature_types.h"
|
||||
#include "DNA_object_types.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "DNA_nla_types.h"
|
||||
#include "DNA_constraint_types.h"
|
||||
#include "KX_PythonSeq.h"
|
||||
#include "KX_PythonInit.h"
|
||||
@@ -137,25 +137,22 @@ 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)
|
||||
{
|
||||
short mode= ACTSTRIPMODE_BLEND;
|
||||
|
||||
bPoseChannel *dchan;
|
||||
const bPoseChannel *schan;
|
||||
bConstraint *dcon, *scon;
|
||||
float dstweight;
|
||||
int i;
|
||||
|
||||
switch (mode) {
|
||||
case ACTSTRIPMODE_BLEND:
|
||||
dstweight = 1.0F - srcweight;
|
||||
break;
|
||||
case ACTSTRIPMODE_ADD:
|
||||
dstweight = 1.0F;
|
||||
break;
|
||||
default :
|
||||
dstweight = 1.0F;
|
||||
if (mode == BL_Action::ACT_BLEND_BLEND)
|
||||
{
|
||||
dstweight = 1.0f - srcweight;
|
||||
} else if (mode == BL_Action::ACT_BLEND_ADD)
|
||||
{
|
||||
dstweight = 1.0f;
|
||||
} else {
|
||||
dstweight = 1.0f;
|
||||
}
|
||||
|
||||
schan= (bPoseChannel *)src->chanbase.first;
|
||||
@@ -167,7 +164,7 @@ void game_blend_poses(bPose *dst, bPose *src, float srcweight/*, short mode*/)
|
||||
|
||||
copy_qt_qt(dquat, dchan->quat);
|
||||
copy_qt_qt(squat, schan->quat);
|
||||
if (mode==ACTSTRIPMODE_BLEND)
|
||||
if (mode==BL_Action::ACT_BLEND_BLEND)
|
||||
interp_qt_qtqt(dchan->quat, dquat, squat, srcweight);
|
||||
else {
|
||||
mul_fac_qt_fl(squat, srcweight);
|
||||
|
@@ -147,7 +147,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);
|
||||
|
@@ -65,7 +65,8 @@ BL_Action::BL_Action(class KX_GameObject* gameobj)
|
||||
m_blendstart(0.f),
|
||||
m_speed(0.f),
|
||||
m_priority(0),
|
||||
m_playmode(0),
|
||||
m_playmode(ACT_MODE_PLAY),
|
||||
m_blendmode(ACT_BLEND_BLEND),
|
||||
m_ipo_flags(0),
|
||||
m_done(true),
|
||||
m_calc_localtime(true)
|
||||
@@ -104,7 +105,8 @@ bool BL_Action::Play(const char* name,
|
||||
short play_mode,
|
||||
float layer_weight,
|
||||
short ipo_flags,
|
||||
float playback_speed)
|
||||
float playback_speed,
|
||||
short blend_mode)
|
||||
{
|
||||
|
||||
// Only start playing a new action if we're done, or if
|
||||
@@ -229,6 +231,7 @@ 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;
|
||||
@@ -423,7 +426,7 @@ void BL_Action::Update(float curtime)
|
||||
float weight = 1.f - (m_blendframe/m_blendin);
|
||||
|
||||
// Blend the poses
|
||||
game_blend_poses(m_pose, m_blendinpose, weight);
|
||||
game_blend_poses(m_pose, m_blendinpose, weight, ACT_BLEND_BLEND);
|
||||
}
|
||||
|
||||
|
||||
@@ -431,7 +434,7 @@ void BL_Action::Update(float curtime)
|
||||
if (m_layer_weight >= 0)
|
||||
{
|
||||
obj->GetMRDPose(&m_blendpose);
|
||||
game_blend_poses(m_pose, m_blendpose, m_layer_weight);
|
||||
game_blend_poses(m_pose, m_blendpose, m_layer_weight, m_blendmode);
|
||||
}
|
||||
|
||||
obj->SetPose(m_pose);
|
||||
|
@@ -34,7 +34,6 @@
|
||||
#include "MEM_guardedalloc.h"
|
||||
#endif
|
||||
|
||||
|
||||
class BL_Action
|
||||
{
|
||||
private:
|
||||
@@ -64,6 +63,7 @@ private:
|
||||
short m_priority;
|
||||
|
||||
short m_playmode;
|
||||
short m_blendmode;
|
||||
|
||||
short m_ipo_flags;
|
||||
|
||||
@@ -91,7 +91,8 @@ public:
|
||||
short play_mode,
|
||||
float layer_weight,
|
||||
short ipo_flags,
|
||||
float playback_speed);
|
||||
float playback_speed,
|
||||
short blend_mode);
|
||||
/**
|
||||
* Stop playing the action
|
||||
*/
|
||||
@@ -122,6 +123,13 @@ public:
|
||||
ACT_MODE_MAX,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ACT_BLEND_BLEND=0,
|
||||
ACT_BLEND_ADD=1,
|
||||
ACT_BLEND_MAX,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
ACT_IPOFLAG_FORCE = 1,
|
||||
|
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "BL_ActionManager.h"
|
||||
#include "BL_Action.h"
|
||||
|
||||
BL_ActionManager::BL_ActionManager(class KX_GameObject *obj)
|
||||
{
|
||||
@@ -72,12 +73,13 @@ bool BL_ActionManager::PlayAction(const char* name,
|
||||
short play_mode,
|
||||
float layer_weight,
|
||||
short ipo_flags,
|
||||
float playback_speed)
|
||||
float playback_speed,
|
||||
short blend_mode)
|
||||
{
|
||||
// Disable layer blending on the first layer
|
||||
if (layer == 0) layer_weight = -1.f;
|
||||
|
||||
return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
|
||||
return m_layers[layer]->Play(name, start, end, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
|
||||
}
|
||||
|
||||
void BL_ActionManager::StopAction(short layer)
|
||||
|
@@ -27,10 +27,10 @@
|
||||
#ifndef __BL_ACTIONMANAGER_H__
|
||||
#define __BL_ACTIONMANAGER_H__
|
||||
|
||||
#include "BL_Action.h"
|
||||
|
||||
#define MAX_ACTION_LAYERS 8
|
||||
|
||||
class BL_Action;
|
||||
|
||||
/**
|
||||
* BL_ActionManager is responsible for handling a KX_GameObject's actions.
|
||||
*/
|
||||
@@ -52,7 +52,8 @@ public:
|
||||
short play_mode=0,
|
||||
float layer_weight=0.f,
|
||||
short ipo_flags=0,
|
||||
float playback_speed=1.f);
|
||||
float playback_speed=1.f,
|
||||
short blend_mode=0);
|
||||
/**
|
||||
* Gets the current frame of an action
|
||||
*/
|
||||
|
@@ -73,6 +73,7 @@ typedef unsigned long uint_ptr;
|
||||
#include "KX_ObstacleSimulation.h"
|
||||
|
||||
#include "BL_ActionManager.h"
|
||||
#include "BL_Action.h"
|
||||
|
||||
#include "PyObjectPlus.h" /* python stuff */
|
||||
|
||||
@@ -429,9 +430,10 @@ bool KX_GameObject::PlayAction(const char* name,
|
||||
short play_mode,
|
||||
float layer_weight,
|
||||
short ipo_flags,
|
||||
float playback_speed)
|
||||
float playback_speed,
|
||||
short blend_mode)
|
||||
{
|
||||
return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed);
|
||||
return GetActionManager()->PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, playback_speed, blend_mode);
|
||||
}
|
||||
|
||||
void KX_GameObject::StopAction(short layer)
|
||||
@@ -3311,11 +3313,12 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
|
||||
short layer=0, priority=0;
|
||||
short ipo_flags=0;
|
||||
short play_mode=0;
|
||||
short blend_mode=0;
|
||||
|
||||
static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", NULL};
|
||||
static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "priority", "blendin", "play_mode", "layer_weight", "ipo_flags", "speed", "blend_mode", NULL};
|
||||
|
||||
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))
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hhfhfhfh:playAction", const_cast<char**>(kwlist),
|
||||
&name, &start, &end, &layer, &priority, &blendin, &play_mode, &layer_weight, &ipo_flags, &speed, &blend_mode))
|
||||
return NULL;
|
||||
|
||||
layer_check(layer, "playAction");
|
||||
@@ -3323,7 +3326,13 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
|
||||
if (play_mode < 0 || play_mode > BL_Action::ACT_MODE_MAX)
|
||||
{
|
||||
printf("KX_GameObject.playAction(): given play_mode (%d) is out of range (0 - %d), setting to ACT_MODE_PLAY", play_mode, BL_Action::ACT_MODE_MAX-1);
|
||||
play_mode = BL_Action::ACT_MODE_MAX;
|
||||
play_mode = BL_Action::ACT_MODE_PLAY;
|
||||
}
|
||||
|
||||
if (blend_mode < 0 || blend_mode > BL_Action::ACT_BLEND_MAX)
|
||||
{
|
||||
printf("KX_GameObject.playAction(): given blend_mode (%d) is out of range (0 - %d), setting to ACT_BLEND_BLEND", blend_mode, BL_Action::ACT_BLEND_MAX-1);
|
||||
blend_mode = BL_Action::ACT_BLEND_BLEND;
|
||||
}
|
||||
|
||||
if (layer_weight < 0.f || layer_weight > 1.f)
|
||||
@@ -3332,7 +3341,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction,
|
||||
layer_weight = 0.f;
|
||||
}
|
||||
|
||||
PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed);
|
||||
PlayAction(name, start, end, layer, priority, blendin, play_mode, layer_weight, ipo_flags, speed, blend_mode);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@@ -255,7 +255,8 @@ public:
|
||||
short play_mode=0,
|
||||
float layer_weight=0.f,
|
||||
short ipo_flags=0,
|
||||
float playback_speed=1.f);
|
||||
float playback_speed=1.f,
|
||||
short blend_mode=0);
|
||||
|
||||
/**
|
||||
* Gets the current frame of an action
|
||||
|
@@ -1820,6 +1820,10 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
|
||||
KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_LOOP, BL_Action::ACT_MODE_LOOP);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACTION_MODE_PING_PONG, BL_Action::ACT_MODE_PING_PONG);
|
||||
|
||||
/* BL_Action blend modes */
|
||||
KX_MACRO_addTypesToDict(d, KX_ACTION_BLEND_BLEND, BL_Action::ACT_BLEND_BLEND);
|
||||
KX_MACRO_addTypesToDict(d, KX_ACTION_BLEND_ADD, BL_Action::ACT_BLEND_ADD);
|
||||
|
||||
// Check for errors
|
||||
if (PyErr_Occurred())
|
||||
{
|
||||
|
Reference in New Issue
Block a user