From c02006bc2b8566ae96af1e9e9630f0ecd5a1d05e Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Thu, 16 Jun 2011 01:18:52 +0000 Subject: [PATCH] BGE Animations: Adding the ipo flag options to the action actuator. This still needs more testing. --- .../editors/space_logic/logic_window.c | 14 +++++- source/blender/makesrna/intern/rna_actuator.c | 46 +++++++++++++++++++ .../Converter/BL_ActionActuator.cpp | 2 +- .../gameengine/Converter/BL_ActionActuator.h | 3 ++ .../Converter/KX_ConvertActuators.cpp | 10 ++++ source/gameengine/Ketsji/BL_Action.cpp | 16 ++++--- source/gameengine/Ketsji/BL_Action.h | 11 +++++ source/gameengine/Ketsji/BL_ActionManager.cpp | 3 +- source/gameengine/Ketsji/BL_ActionManager.h | 1 + source/gameengine/Ketsji/KX_GameObject.cpp | 14 +++--- source/gameengine/Ketsji/KX_GameObject.h | 1 + 11 files changed, 105 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/space_logic/logic_window.c b/source/blender/editors/space_logic/logic_window.c index a45e7d39c76..9500b1afe3c 100644 --- a/source/blender/editors/space_logic/logic_window.c +++ b/source/blender/editors/space_logic/logic_window.c @@ -3677,12 +3677,22 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr) { Object *ob = (Object *)ptr->id.data; PointerRNA settings_ptr; - uiLayout *row; + uiLayout *row, *subrow, *col;; RNA_pointer_create((ID *)ob, &RNA_GameObjectSettings, ob, &settings_ptr); row= uiLayoutRow(layout, 0); uiItemR(row, ptr, "play_mode", 0, "", ICON_NONE); + + subrow= uiLayoutRow(row, 1); + uiItemR(subrow, ptr, "use_force", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); + uiItemR(subrow, ptr, "use_additive", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); + + col = uiLayoutColumn(subrow, 0); + uiLayoutSetActive(col, (RNA_boolean_get(ptr, "use_additive") || RNA_boolean_get(ptr, "use_force"))); + uiItemR(col, ptr, "use_local", UI_ITEM_R_TOGGLE, NULL, ICON_NONE); + + row= uiLayoutRow(layout, 0); uiItemR(row, ptr, "action", 0, "", ICON_NONE); uiItemR(row, ptr, "use_continue_last_frame", 0, NULL, ICON_NONE); @@ -3695,6 +3705,8 @@ static void draw_actuator_action(uiLayout *layout, PointerRNA *ptr) uiItemR(row, ptr, "frame_end", 0, NULL, ICON_NONE); } + uiItemR(row, ptr, "apply_to_children", 0, NULL, ICON_NONE); + row= uiLayoutRow(layout, 0); uiItemR(row, ptr, "frame_blend_in", 0, NULL, ICON_NONE); uiItemR(row, ptr, "priority", 0, NULL, ICON_NONE); diff --git a/source/blender/makesrna/intern/rna_actuator.c b/source/blender/makesrna/intern/rna_actuator.c index 75c884a5fbb..41b1ff11f04 100644 --- a/source/blender/makesrna/intern/rna_actuator.c +++ b/source/blender/makesrna/intern/rna_actuator.c @@ -353,6 +353,29 @@ static void rna_FcurveActuator_force_set(struct PointerRNA *ptr, int value) ia->flag &= ~ACT_IPOFORCE; } +static void rna_ActionActuator_add_set(struct PointerRNA *ptr, int value) +{ + bActuator *act = (bActuator *)ptr->data; + bActionActuator *aa = act->data; + + if(value == 1){ + aa->flag &= ~ACT_IPOFORCE; + aa->flag |= ACT_IPOADD; + }else + aa->flag &= ~ACT_IPOADD; +} + +static void rna_ActionActuator_force_set(struct PointerRNA *ptr, int value) +{ + bActuator *act = (bActuator *)ptr->data; + bActionActuator *aa = act->data; + + if(value == 1){ + aa->flag &= ~ACT_IPOADD; + aa->flag |= ACT_IPOFORCE; + }else + aa->flag &= ~ACT_IPOFORCE; +} static void rna_ObjectActuator_type_set(struct PointerRNA *ptr, int value) { @@ -626,6 +649,29 @@ static void rna_def_action_actuator(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Frame Property", "Assign the action's current frame number to this property"); RNA_def_property_update(prop, NC_LOGIC, NULL); + /* booleans */ + prop= RNA_def_property(srna, "use_additive", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_IPOADD); + RNA_def_property_boolean_funcs(prop, NULL, "rna_ActionActuator_add_set"); + RNA_def_property_ui_text(prop, "Add", "Action is added to the current loc/rot/scale in global or local coordinate according to Local flag"); + RNA_def_property_update(prop, NC_LOGIC, NULL); + + prop= RNA_def_property(srna, "use_force", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_IPOFORCE); + RNA_def_property_boolean_funcs(prop, NULL, "rna_ActionActuator_force_set"); + RNA_def_property_ui_text(prop, "Force", "Apply Action as a global or local force depending on the local option (dynamic objects only)"); + RNA_def_property_update(prop, NC_LOGIC, NULL); + + prop= RNA_def_property(srna, "use_local", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_IPOLOCAL); + RNA_def_property_ui_text(prop, "L", "Let the Action act in local coordinates, used in Force and Add mode"); + RNA_def_property_update(prop, NC_LOGIC, NULL); + + prop= RNA_def_property(srna, "apply_to_children", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_IPOCHILD); + RNA_def_property_ui_text(prop, "Child", "Update Action on all children Objects as well"); + RNA_def_property_update(prop, NC_LOGIC, NULL); + #ifdef __NLA_ACTION_BY_MOTION_ACTUATOR prop= RNA_def_property(srna, "stride_length", PROP_FLOAT, PROP_NONE); RNA_def_property_float_sdna(prop, NULL, "stridelength"); diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 6230f03c4ed..b57eaadaea6 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -180,7 +180,7 @@ bool BL_ActionActuator::Update(double curtime, bool frame) if (!m_is_going && bPositiveEvent) { m_is_going = true; - obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_blendin, play_mode); + obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_blendin, play_mode, 0, m_ipo_flags); if (m_end_reset) obj->SetActionFrame(m_layer, m_localtime); } diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index 6daf412d9a3..96b9b5e2551 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -53,6 +53,7 @@ public: short blendin, short priority, short layer, + short ipo_flags, short end_reset, float stride) : SCA_IActuator(gameobj, KX_ACT_ACTION), @@ -71,6 +72,7 @@ public: m_playtype(playtype), m_priority(priority), m_layer(layer), + m_ipo_flags(ipo_flags), m_end_reset(end_reset), m_is_going(false), m_pose(NULL), @@ -166,6 +168,7 @@ protected: short m_playtype; short m_priority; short m_layer; + short m_ipo_flags; bool m_end_reset; bool m_is_going; struct bPose* m_pose; diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 1a8368a12fa..c7b873de5e4 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -95,6 +95,7 @@ #include "BL_ActionActuator.h" #include "BL_ShapeActionActuator.h" #include "BL_ArmatureActuator.h" +#include "BL_Action.h" /* end of blender include block */ #include "BL_BlenderDataConversion.h" @@ -195,6 +196,14 @@ void BL_ConvertActuators(char* maggiename, bActionActuator* actact = (bActionActuator*) bact->data; STR_String propname = (actact->name ? actact->name : ""); STR_String propframe = (actact->frameProp ? actact->frameProp : ""); + + short ipo_flags = 0; + + // Convert flags + if (actact->flag & ACT_IPOFORCE) ipo_flags |= BL_Action::ACT_IPOFLAG_FORCE; + if (actact->flag & ACT_IPOLOCAL) ipo_flags |= BL_Action::ACT_IPOFLAG_LOCAL; + if (actact->flag & ACT_IPOADD) ipo_flags |= BL_Action::ACT_IPOFLAG_ADD; + if (actact->flag & ACT_IPOCHILD) ipo_flags |= BL_Action::ACT_IPOFLAG_CHILD; BL_ActionActuator* tmpbaseact = new BL_ActionActuator( gameobj, @@ -207,6 +216,7 @@ void BL_ConvertActuators(char* maggiename, actact->blendin, actact->priority, actact->layer, + ipo_flags, actact->end_reset, actact->stridelength // Ketsji at 1, because zero is reserved for "NoDef" diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp index bd65c7d45d8..836bc24ffcd 100644 --- a/source/gameengine/Ketsji/BL_Action.cpp +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -58,6 +58,7 @@ BL_Action::BL_Action(class KX_GameObject* gameobj) m_blendframe(0.f), m_blendstart(0.f), m_speed(0.f), + m_ipo_flags(0), m_pose(NULL), m_blendpose(NULL), m_sg_contr(NULL), @@ -85,6 +86,7 @@ void BL_Action::Play(const char* name, float blendin, short play_mode, short blend_mode, + short ipo_flags, float playback_speed) { bAction* prev_action = m_action; @@ -105,8 +107,10 @@ void BL_Action::Play(const char* name, 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(); } + + m_ipo_flags = ipo_flags; + InitIPO(); // Now that we have an action, we have something we can play m_starttime = KX_GetActiveEngine()->GetFrameTime(); @@ -131,9 +135,9 @@ 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); + m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE); + m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD); + m_sg_contr->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL); } float BL_Action::GetFrame() @@ -259,8 +263,6 @@ void BL_Action::Update(float curtime) else { InitIPO(); - m_sg_contr->SetSimulatedTime(m_localtime); - m_obj->GetSGNode()->UpdateWorldData(m_localtime); - m_obj->UpdateTransform(); + 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 index 1eb4483eb37..fc80d9bea34 100644 --- a/source/gameengine/Ketsji/BL_Action.h +++ b/source/gameengine/Ketsji/BL_Action.h @@ -59,6 +59,8 @@ private: short m_playmode; short m_blendmode; + short m_ipo_flags; + bool m_done; void InitIPO(); @@ -73,6 +75,7 @@ public: float blendin, short play_mode, short blend_mode, + short ipo_flags, float playback_speed); void Stop(); bool IsDone() {return m_done;} @@ -99,6 +102,14 @@ public: ACT_BLEND_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"); } diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp index 0a99a5a43a9..935e9129d21 100644 --- a/source/gameengine/Ketsji/BL_ActionManager.cpp +++ b/source/gameengine/Ketsji/BL_ActionManager.cpp @@ -63,6 +63,7 @@ void BL_ActionManager::PlayAction(const char* name, float blendin, short play_mode, short blend_mode, + short ipo_flags, float playback_speed) { // Remove a currently running action on this layer if there is one @@ -70,7 +71,7 @@ void BL_ActionManager::PlayAction(const char* name, StopAction(layer); // Create a new action - m_layers[layer]->Play(name, start, end, blendin, play_mode, blend_mode, playback_speed); + m_layers[layer]->Play(name, start, end, blendin, play_mode, blend_mode, ipo_flags, 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 b769db02bf9..f4ef43d3801 100644 --- a/source/gameengine/Ketsji/BL_ActionManager.h +++ b/source/gameengine/Ketsji/BL_ActionManager.h @@ -49,6 +49,7 @@ public: float blendin=0.f, short play_mode=0, short blend_mode=0, + short ipo_flags=0, float playback_speed=1.f); float GetActionFrame(short layer); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 27f4a72ccdf..aa0ce14a3cc 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -367,9 +367,10 @@ void KX_GameObject::PlayAction(const char* name, float blendin, short play_mode, short blend_mode, + short ipo_flags, float playback_speed) { - GetActionManager()->PlayAction(name, start, end, layer, blendin, play_mode, blend_mode, playback_speed); + GetActionManager()->PlayAction(name, start, end, layer, blendin, play_mode, blend_mode, ipo_flags, playback_speed); } void KX_GameObject::StopAction(short layer) @@ -3033,18 +3034,19 @@ 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, speed=1.0)\n" + "playAction(name, start_frame, end_frame, layer=0, blendin=0, play_mode=ACT_MODE_PLAY, blend_mode=ACT_BLEND_NONE, ipo_flags=0, speed=1.0)\n" "plays an action\n") { const char* name; float start, end, blendin=0.f, speed=1.f; short layer=0; + short ipo_flags=0; short play_mode=0, blend_mode=0; - static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "blendin", "play_mode", "blend_mode", "speed", NULL}; + static const char *kwlist[] = {"name", "start_frame", "end_frame", "layer", "blendin", "play_mode", "blend_mode", "ipo_flags", "speed", NULL}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hfhhf", const_cast(kwlist), - &name, &start, &end, &layer, &blendin, &play_mode, &blend_mode, &speed)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "sff|hfhhhf", const_cast(kwlist), + &name, &start, &end, &layer, &blendin, &play_mode, &blend_mode, &ipo_flags, &speed)) return NULL; if (layer < 0 || layer > MAX_ACTION_LAYERS) @@ -3065,7 +3067,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, playAction, blend_mode = BL_Action::ACT_BLEND_NONE; } - PlayAction(name, start, end, layer, blendin, play_mode, blend_mode, speed); + PlayAction(name, start, end, layer, blendin, play_mode, blend_mode, ipo_flags, speed); Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 0ff0ec84529..b97dad1a35e 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -218,6 +218,7 @@ public: float blendin=0.f, short play_mode=0, short blend_mode=0, + short ipo_flags=0, float playback_speed=1.f); /**