diff options
author | Xiao Xiangquan <xiaoxiangquan@gmail.com> | 2011-09-05 18:44:11 +0400 |
---|---|---|
committer | Xiao Xiangquan <xiaoxiangquan@gmail.com> | 2011-09-05 18:44:11 +0400 |
commit | 034cda72d36711c725862f89eddefa3e277e2ce2 (patch) | |
tree | b2ce911bc59714b4c47f9dd4bdd59a372f4d7afe /source/gameengine | |
parent | d31d7fd4875ac81c8e41572390b51cd14f5682be (diff) |
add missing files after merging
Diffstat (limited to 'source/gameengine')
-rwxr-xr-x | source/gameengine/Ketsji/BL_Action.cpp | 453 | ||||
-rwxr-xr-x | source/gameengine/Ketsji/BL_Action.h | 144 | ||||
-rwxr-xr-x | source/gameengine/Ketsji/BL_ActionManager.cpp | 110 | ||||
-rwxr-xr-x | source/gameengine/Ketsji/BL_ActionManager.h | 106 |
4 files changed, 813 insertions, 0 deletions
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp new file mode 100755 index 00000000000..5bc86264f9c --- /dev/null +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -0,0 +1,453 @@ +/** + * $Id: BL_Action.cpp 39792 2011-08-30 09:15:55Z nexyon $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Mitchell Stokes. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BL_Action.cpp + * \ingroup ketsji + */ + +#include <cstdlib> + +#include "BL_Action.h" +#include "BL_ArmatureObject.h" +#include "BL_DeformableGameObject.h" +#include "BL_ShapeDeformer.h" +#include "KX_IpoConvert.h" +#include "KX_GameObject.h" + +// These three are for getting the action from the logic manager +#include "KX_Scene.h" +#include "KX_PythonInit.h" +#include "SCA_LogicManager.h" + +extern "C" { +#include "BKE_animsys.h" +#include "BKE_action.h" +#include "RNA_access.h" +#include "RNA_define.h" +} + +BL_Action::BL_Action(class KX_GameObject* gameobj) +: + m_action(NULL), + m_pose(NULL), + m_blendpose(NULL), + m_blendinpose(NULL), + m_ptrrna(NULL), + m_obj(gameobj), + m_startframe(0.f), + m_endframe(0.f), + m_endtime(0.f), + m_localtime(0.f), + m_blendin(0.f), + m_blendframe(0.f), + m_blendstart(0.f), + m_speed(0.f), + m_priority(0), + m_playmode(0), + m_ipo_flags(0), + m_done(true), + m_calc_localtime(true) +{ + if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) + { + BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; + + m_ptrrna = new PointerRNA(); + RNA_id_pointer_create(&obj->GetArmatureObject()->id, m_ptrrna); + } + else + { + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; + BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); + + if (shape_deformer) + { + m_ptrrna = new PointerRNA(); + RNA_id_pointer_create(&shape_deformer->GetKey()->id, m_ptrrna); + } + } +} + +BL_Action::~BL_Action() +{ + if (m_pose) + game_free_pose(m_pose); + if (m_blendpose) + game_free_pose(m_blendpose); + if (m_blendinpose) + game_free_pose(m_blendinpose); + if (m_ptrrna) + delete m_ptrrna; + ClearControllerList(); +} + +void BL_Action::ClearControllerList() +{ + // Clear out the controller list + std::vector<SG_Controller*>::iterator it; + for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++) + { + m_obj->GetSGNode()->RemoveSGController((*it)); + delete *it; + } + + m_sg_contr_list.clear(); +} + +bool BL_Action::Play(const char* name, + float start, + float end, + short priority, + float blendin, + short play_mode, + float layer_weight, + short ipo_flags, + float playback_speed) +{ + + // Only start playing a new action if we're done, or if + // the new action has a higher priority + if (priority != 0 && !IsDone() && priority >= m_priority) + return false; + m_priority = priority; + bAction* prev_action = m_action; + + // First try to load the action + m_action = (bAction*)KX_GetActiveScene()->GetLogicManager()->GetActionByName(name); + if (!m_action) + { + printf("Failed to load action: %s\n", name); + m_done = true; + return false; + } + + if (prev_action != m_action) + { + // First get rid of any old controllers + ClearControllerList(); + + // Create an SG_Controller + SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); + m_sg_contr_list.push_back(sg_contr); + m_obj->GetSGNode()->AddSGController(sg_contr); + sg_contr->SetObject(m_obj->GetSGNode()); + + // Extra controllers + if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT) + { + sg_contr = BL_CreateLampIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); + m_sg_contr_list.push_back(sg_contr); + m_obj->GetSGNode()->AddSGController(sg_contr); + sg_contr->SetObject(m_obj->GetSGNode()); + } + else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA) + { + sg_contr = BL_CreateCameraIPO(m_action, m_obj, KX_GetActiveScene()->GetSceneConverter()); + m_sg_contr_list.push_back(sg_contr); + m_obj->GetSGNode()->AddSGController(sg_contr); + sg_contr->SetObject(m_obj->GetSGNode()); + } + } + + m_ipo_flags = ipo_flags; + InitIPO(); + + // Setup blendin shapes/poses + if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) + { + BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; + obj->GetMRDPose(&m_blendinpose); + } + else + { + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; + BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); + + if (shape_deformer && shape_deformer->GetKey()) + { + obj->GetShape(m_blendinshape); + + // Now that we have the previous blend shape saved, we can clear out the key to avoid any + // further interference. + KeyBlock *kb; + for (kb=(KeyBlock*)shape_deformer->GetKey()->block.first; kb; kb=(KeyBlock*)kb->next) + kb->curval = 0.f; + } + } + + // Now that we have an action, we have something we can play + m_starttime = KX_GetActiveEngine()->GetFrameTime(); + m_startframe = m_localtime = start; + m_endframe = end; + m_blendin = blendin; + m_playmode = play_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; + + return true; +} + +void BL_Action::Stop() +{ + m_done = true; +} + +bool BL_Action::IsDone() +{ + return m_done; +} + +void BL_Action::InitIPO() +{ + // Initialize the IPOs + std::vector<SG_Controller*>::iterator it; + for (it = m_sg_contr_list.begin(); it != m_sg_contr_list.end(); it++) + { + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true); + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE); + (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD); + (*it)->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; +} + +void BL_Action::SetFrame(float frame) +{ + // 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); + + m_localtime = frame; + m_calc_localtime = false; +} + +void BL_Action::SetPlayMode(short play_mode) +{ + m_playmode = play_mode; +} + +void BL_Action::SetTimes(float start, float end) +{ + m_startframe = start; + m_endframe = end; +} + +void BL_Action::SetLocalTime(float curtime) +{ + float dt = (curtime-m_starttime)*KX_KetsjiEngine::GetAnimFrameRate()*m_speed; + + if (m_endframe < m_startframe) + dt = -dt; + + m_localtime = m_startframe + dt; +} + +void BL_Action::ResetStartTime(float curtime) +{ + float dt = m_localtime - m_startframe; + + m_starttime = curtime - dt / (KX_KetsjiEngine::GetAnimFrameRate()*m_speed); + SetLocalTime(curtime); +} + +void BL_Action::IncrementBlending(float curtime) +{ + // Setup m_blendstart if we need to + if (m_blendstart == 0.f) + m_blendstart = curtime; + + // Bump the blend frame + m_blendframe = (curtime - m_blendstart)*KX_KetsjiEngine::GetAnimFrameRate(); + + // Clamp + if (m_blendframe>m_blendin) + m_blendframe = m_blendin; +} + + +void BL_Action::BlendShape(Key* key, float srcweight, std::vector<float>& blendshape) +{ + vector<float>::const_iterator it; + float dstweight; + KeyBlock *kb; + + dstweight = 1.0F - srcweight; + //printf("Dst: %f\tSrc: %f\n", srcweight, dstweight); + for (it=blendshape.begin(), kb = (KeyBlock*)key->block.first; + kb && it != blendshape.end(); + kb = (KeyBlock*)kb->next, it++) { + //printf("OirgKeys: %f\t%f\n", kb->curval, (*it)); + kb->curval = kb->curval * dstweight + (*it) * srcweight; + //printf("NewKey: %f\n", kb->curval); + } + //printf("\n"); +} + +void BL_Action::Update(float curtime) +{ + // Don't bother if we're done with the animation + if (m_done) + return; + + curtime -= KX_KetsjiEngine::GetSuspendedDelta(); + + if (m_calc_localtime) + SetLocalTime(curtime); + else + { + ResetStartTime(curtime); + m_calc_localtime = true; + } + + // Handle wrap around + if (m_localtime < min(m_startframe, m_endframe) || m_localtime > max(m_startframe, m_endframe)) + { + switch(m_playmode) + { + case ACT_MODE_PLAY: + // Clamp + m_localtime = m_endframe; + m_done = true; + break; + case ACT_MODE_LOOP: + // Put the time back to the beginning + m_localtime = m_startframe; + m_starttime = curtime; + break; + case ACT_MODE_PING_PONG: + // Swap the start and end frames + float temp = m_startframe; + m_startframe = m_endframe; + m_endframe = temp; + + m_starttime = curtime; + + break; + } + + if (!m_done) + InitIPO(); + } + + if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) + { + BL_ArmatureObject *obj = (BL_ArmatureObject*)m_obj; + obj->GetPose(&m_pose); + + // Extract the pose from the action + { + Object *arm = obj->GetArmatureObject(); + bPose *temp = arm->pose; + + arm->pose = m_pose; + animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime); + + arm->pose = temp; + } + + // Handle blending between armature actions + if (m_blendin && m_blendframe<m_blendin) + { + IncrementBlending(curtime); + + // Calculate weight + float weight = 1.f - (m_blendframe/m_blendin); + + // Blend the poses + game_blend_poses(m_pose, m_blendinpose, weight); + } + + + // Handle layer blending + if (m_layer_weight >= 0) + { + obj->GetMRDPose(&m_blendpose); + game_blend_poses(m_pose, m_blendpose, m_layer_weight); + } + + obj->SetPose(m_pose); + + obj->SetActiveAction(NULL, 0, curtime); + } + else + { + BL_DeformableGameObject *obj = (BL_DeformableGameObject*)m_obj; + BL_ShapeDeformer *shape_deformer = dynamic_cast<BL_ShapeDeformer*>(obj->GetDeformer()); + + // Handle shape actions if we have any + if (shape_deformer && shape_deformer->GetKey()) + { + Key *key = shape_deformer->GetKey(); + + + animsys_evaluate_action(m_ptrrna, m_action, NULL, m_localtime); + + // Handle blending between shape actions + if (m_blendin && m_blendframe < m_blendin) + { + IncrementBlending(curtime); + + float weight = 1.f - (m_blendframe/m_blendin); + + // We go through and clear out the keyblocks so there isn't any interference + // from other shape actions + KeyBlock *kb; + for (kb=(KeyBlock*)key->block.first; kb; kb=(KeyBlock*)kb->next) + kb->curval = 0.f; + + // Now blend the shape + BlendShape(key, weight, m_blendinshape); + } + + // Handle layer blending + if (m_layer_weight >= 0) + { + obj->GetShape(m_blendshape); + BlendShape(key, m_layer_weight, m_blendshape); + } + + obj->SetActiveAction(NULL, 0, curtime); + } + + + InitIPO(); + m_obj->UpdateIPO(m_localtime, m_ipo_flags & ACT_IPOFLAG_CHILD); + } +} diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h new file mode 100755 index 00000000000..de2bedb7062 --- /dev/null +++ b/source/gameengine/Ketsji/BL_Action.h @@ -0,0 +1,144 @@ +/** + * $Id: BL_Action.h 39792 2011-08-30 09:15:55Z nexyon $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Mitchell Stokes. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BL_Action.h + * \ingroup ketsji + */ + +#ifndef __BL_ACTION +#define __BL_ACTION + + +#include <vector> + +#ifdef WITH_CXX_GUARDEDALLOC +#include "MEM_guardedalloc.h" +#endif + + +class BL_Action +{ +private: + struct bAction* m_action; + struct bPose* m_pose; + struct bPose* m_blendpose; + struct bPose* m_blendinpose; + struct PointerRNA *m_ptrrna; + std::vector<class SG_Controller*> m_sg_contr_list; + class KX_GameObject* m_obj; + std::vector<float> m_blendshape; + std::vector<float> m_blendinshape; + + float m_startframe; + float m_endframe; + float m_starttime; + float m_endtime; + float m_localtime; + + float m_blendin; + float m_blendframe; + float m_blendstart; + + float m_layer_weight; + + float m_speed; + + short m_priority; + + short m_playmode; + + short m_ipo_flags; + + bool m_done; + bool m_calc_localtime; + + void ClearControllerList(); + void InitIPO(); + void SetLocalTime(float curtime); + void ResetStartTime(float curtime); + void IncrementBlending(float curtime); + void BlendShape(struct Key* key, float srcweight, std::vector<float>& blendshape); +public: + BL_Action(class KX_GameObject* gameobj); + ~BL_Action(); + + /** + * Play an action + */ + bool Play(const char* name, + float start, + float end, + short priority, + float blendin, + short play_mode, + float layer_weight, + short ipo_flags, + float playback_speed); + /** + * Stop playing the action + */ + void Stop(); + /** + * Whether or not the action is still playing + */ + bool IsDone(); + /** + * Update the action's frame, etc. + */ + void Update(float curtime); + + // Accessors + float GetFrame(); + struct bAction *GetAction(); + + // Mutators + void SetFrame(float frame); + void SetPlayMode(short play_mode); + void SetTimes(float start, float end); + + enum + { + ACT_MODE_PLAY = 0, + ACT_MODE_LOOP, + ACT_MODE_PING_PONG, + ACT_MODE_MAX, + }; + + enum + { + ACT_IPOFLAG_FORCE = 1, + ACT_IPOFLAG_LOCAL = 2, + ACT_IPOFLAG_ADD = 4, + ACT_IPOFLAG_CHILD = 8, + }; + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:BL_Action"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //BL_ACTION + diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp new file mode 100755 index 00000000000..2b7719a46ff --- /dev/null +++ b/source/gameengine/Ketsji/BL_ActionManager.cpp @@ -0,0 +1,110 @@ +/** + * $Id: BL_ActionManager.cpp 39792 2011-08-30 09:15:55Z nexyon $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Mitchell Stokes. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BL_ActionManager.cpp + * \ingroup ketsji + */ + +#include "BL_ActionManager.h" + +BL_ActionManager::BL_ActionManager(class KX_GameObject *obj) +{ + for (int i=0; i<MAX_ACTION_LAYERS; ++i) + m_layers[i] = new BL_Action(obj); +} + +BL_ActionManager::~BL_ActionManager() +{ + for (int i=0; i<MAX_ACTION_LAYERS; ++i) + delete m_layers[i]; +} + +float BL_ActionManager::GetActionFrame(short layer) +{ + return m_layers[layer]->GetFrame(); + + return 0.f; +} + +void BL_ActionManager::SetActionFrame(short layer, float frame) +{ + m_layers[layer]->SetFrame(frame); +} + +struct bAction *BL_ActionManager::GetCurrentAction(short layer) +{ + return m_layers[layer]->GetAction(); + + return 0; +} + +void BL_ActionManager::SetPlayMode(short layer, short mode) +{ + m_layers[layer]->SetPlayMode(mode); +} + +void BL_ActionManager::SetTimes(short layer, float start, float end) +{ + m_layers[layer]->SetTimes(start, end); +} + +bool BL_ActionManager::PlayAction(const char* name, + float start, + float end, + short layer, + short priority, + float blendin, + short play_mode, + float layer_weight, + short ipo_flags, + float playback_speed) +{ + // 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); +} + +void BL_ActionManager::StopAction(short layer) +{ + m_layers[layer]->Stop(); +} + +bool BL_ActionManager::IsActionDone(short layer) +{ + return m_layers[layer]->IsDone(); + + return true; +} + +void BL_ActionManager::Update(float curtime) +{ + for (int i=0; i<MAX_ACTION_LAYERS; ++i) + { + if (!m_layers[i]->IsDone()) + { + m_layers[i]->Update(curtime); + } + } +} diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h new file mode 100755 index 00000000000..96a37756124 --- /dev/null +++ b/source/gameengine/Ketsji/BL_ActionManager.h @@ -0,0 +1,106 @@ +/** + * $Id: BL_ActionManager.h 39792 2011-08-30 09:15:55Z nexyon $ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Mitchell Stokes. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file BL_ActionManager.cpp + * \ingroup ketsji + */ + +#ifndef __BL_ACTIONMANAGER +#define __BL_ACTIONMANAGER + +#include "BL_Action.h" + +#define MAX_ACTION_LAYERS 8 + +/** + * BL_ActionManager is responsible for handling a KX_GameObject's actions. + */ +class BL_ActionManager +{ +private: + BL_Action* m_layers[MAX_ACTION_LAYERS]; + +public: + BL_ActionManager(class KX_GameObject* obj); + ~BL_ActionManager(); + + bool PlayAction(const char* name, + float start, + float end, + short layer=0, + short priority=0, + float blendin=0.f, + short play_mode=0, + float layer_weight=0.f, + short ipo_flags=0, + float playback_speed=1.f); + /** + * Gets the current frame of an action + */ + float GetActionFrame(short layer); + + /** + * Sets the current frame of an action + */ + void SetActionFrame(short layer, float frame); + + /** + * Gets the currently running action on the given layer + */ + struct bAction *GetCurrentAction(short layer); + + /** + * Sets play mode of the action on the given layer + */ + void SetPlayMode(short layer, short mode); + + /** + * Sets the start and end times of the action on the given layer + */ + void SetTimes(short layer, float start, float end); + + /** + * Stop playing the action on the given layer + */ + void StopAction(short layer); + + /** + * Check if an action has finished playing + */ + bool IsActionDone(short layer); + + /** + * Update any running actions + */ + void Update(float); + +#ifdef WITH_CXX_GUARDEDALLOC +public: + void *operator new(size_t num_bytes) { return MEM_mallocN(num_bytes, "GE:BL_ActionManager"); } + void operator delete( void *mem ) { MEM_freeN(mem); } +#endif +}; + +#endif //BL_ACTIONMANAGER + |