Skip to content

Commit

Permalink
UPBGE: Simplify SG_Controller interaction with SG_Node.
Browse files Browse the repository at this point in the history
Previously the SG_Controller were helding a pointer to the node owning them,
but this pointer was used only in Update function called by the node.
So the member is removed and the function Update receive the node pointer
instead.

Also BL_Action use an helper function AddController to add a valid controller,
controllers without any interpolators (Empty()) are ignored.
  • Loading branch information
panzergame committed May 26, 2018
1 parent 06e8f2a commit 96567f2
Show file tree
Hide file tree
Showing 19 changed files with 140 additions and 198 deletions.
1 change: 0 additions & 1 deletion source/gameengine/Converter/BL_IpoConvert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ static BL_InterpolatorList *GetAdtList(struct bAction *for_act, KX_Scene *scene)
SG_Controller *BL_CreateIPO(struct bAction *action, KX_GameObject *gameobj, KX_Scene *scene)
{
KX_IpoController *ipocontr = new KX_IpoController();
ipocontr->SetGameObject(gameobj);

Object *blenderobject = gameobj->GetBlenderObject();

Expand Down
76 changes: 29 additions & 47 deletions source/gameengine/Ketsji/BL_Action.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ extern "C" {
#include "BKE_global.h"

BL_Action::BL_Action(class KX_GameObject *gameobj)
:
m_action(nullptr),
:m_action(nullptr),
m_tmpaction(nullptr),
m_blendpose(nullptr),
m_blendinpose(nullptr),
Expand Down Expand Up @@ -102,14 +101,24 @@ BL_Action::~BL_Action()
}
}

void BL_Action::AddController(SG_Controller *cont)
{
if (!cont || cont->Empty()) {
return;
}

m_sg_contr_list.push_back(cont);
m_obj->GetNode()->AddController(cont);
}

void BL_Action::ClearControllerList()
{
SG_Node *node = m_obj->GetNode();

// 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->GetNode()->RemoveController((*it));
delete *it;
for (SG_Controller *cont : m_sg_contr_list) {
node->RemoveController(cont);
delete cont;
}

m_sg_contr_list.clear();
Expand Down Expand Up @@ -166,54 +175,29 @@ bool BL_Action::Play(const std::string& name,
// First get rid of any old controllers
ClearControllerList();

// Create an SG_Controller
SG_Controller *sg_contr = BL_CreateIPO(m_action, m_obj, kxscene);
m_sg_contr_list.push_back(sg_contr);
m_obj->GetNode()->AddController(sg_contr);
sg_contr->SetNode(m_obj->GetNode());
SG_Node *node = m_obj->GetNode();

// Create an SG_Controller
AddController(BL_CreateIPO(m_action, m_obj, kxscene));
// World
sg_contr = BL_CreateWorldIPO(m_action, kxscene->GetBlenderScene()->world, kxscene);
if (sg_contr) {
m_sg_contr_list.push_back(sg_contr);
m_obj->GetNode()->AddController(sg_contr);
sg_contr->SetNode(m_obj->GetNode());
}

AddController(BL_CreateWorldIPO(m_action, kxscene->GetBlenderScene()->world, kxscene));
// Try obcolor
sg_contr = BL_CreateObColorIPO(m_action, m_obj, kxscene);
if (sg_contr) {
m_sg_contr_list.push_back(sg_contr);
m_obj->GetNode()->AddController(sg_contr);
sg_contr->SetNode(m_obj->GetNode());
}
AddController(BL_CreateObColorIPO(m_action, m_obj, kxscene));

// Now try materials
for (KX_Mesh *mesh : m_obj->GetMeshList()) {
for (RAS_MeshMaterial *meshmat : mesh->GetMeshMaterialList()) {
RAS_IPolyMaterial *polymat = meshmat->GetBucket()->GetPolyMaterial();

sg_contr = BL_CreateMaterialIpo(m_action, polymat, m_obj, kxscene);
if (sg_contr) {
m_sg_contr_list.push_back(sg_contr);
m_obj->GetNode()->AddController(sg_contr);
sg_contr->SetNode(m_obj->GetNode());
}
AddController(BL_CreateMaterialIpo(m_action, polymat, m_obj, kxscene));
}
}

// Extra controllers
if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_LIGHT) {
sg_contr = BL_CreateLampIPO(m_action, m_obj, kxscene);
m_sg_contr_list.push_back(sg_contr);
m_obj->GetNode()->AddController(sg_contr);
sg_contr->SetNode(m_obj->GetNode());
AddController(BL_CreateLampIPO(m_action, m_obj, kxscene));
}
else if (m_obj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA) {
sg_contr = BL_CreateCameraIPO(m_action, m_obj, kxscene);
m_sg_contr_list.push_back(sg_contr);
m_obj->GetNode()->AddController(sg_contr);
sg_contr->SetNode(m_obj->GetNode());
AddController(BL_CreateCameraIPO(m_action, m_obj, kxscene));
}

m_ipo_flags = ipo_flags;
Expand Down Expand Up @@ -269,13 +253,11 @@ bool BL_Action::IsDone()
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);
for (SG_Controller *cont : m_sg_contr_list) {
cont->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
cont->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, m_ipo_flags & ACT_IPOFLAG_FORCE);
cont->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, m_ipo_flags & ACT_IPOFLAG_ADD);
cont->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, m_ipo_flags & ACT_IPOFLAG_LOCAL);
}
}

Expand Down
1 change: 1 addition & 0 deletions source/gameengine/Ketsji/BL_Action.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class BL_Action
float m_prevUpdate;

void ClearControllerList();
void AddController(SG_Controller *cont);
void InitIPO();
void SetLocalTime(float curtime);
void ResetStartTime(float curtime);
Expand Down
6 changes: 3 additions & 3 deletions source/gameengine/Ketsji/KX_CameraIpoSGController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@
#include "KX_Camera.h"
#include "RAS_CameraData.h"

bool KX_CameraIpoSGController::Update()
bool KX_CameraIpoSGController::Update(SG_Node *node)
{
if (!SG_Controller::Update()) {
if (!SG_Controller::Update(node)) {
return false;
}

KX_Camera *kxcamera = (KX_Camera *)m_node->GetClientObject();
KX_Camera *kxcamera = static_cast<KX_Camera *>(node->GetClientObject());
RAS_CameraData *camdata = kxcamera->GetCameraData();

if (m_modify_lens) {
Expand Down
2 changes: 1 addition & 1 deletion source/gameengine/Ketsji/KX_CameraIpoSGController.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class KX_CameraIpoSGController : public SG_Controller
{}

virtual ~KX_CameraIpoSGController() = default;
virtual bool Update();
virtual bool Update(SG_Node *node);

void SetModifyLens(bool modify) {
m_modify_lens = modify;
Expand Down
91 changes: 38 additions & 53 deletions source/gameengine/Ketsji/KX_IpoController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,23 +36,19 @@
#include "DNA_ipo_types.h"
#include "BLI_math.h"

// All objects should start on frame 1! Will we ever need an m_nodeject to
// start on another frame, the 1.0 should change.
KX_IpoController::KX_IpoController()
:m_ipo_as_force(false),
m_ipo_add(false),
m_ipo_local(false),
m_ipo_start_initialized(false),
m_ipo_start_euler(mt::zero3),
m_ipo_euler_initialized(false),
m_game_object(nullptr)
m_ipo_euler_initialized(false)
{
for (int i = 0; i < KX_MAX_IPO_CHANNELS; i++) {
m_ipo_channels_active[i] = false;
}
}


void KX_IpoController::SetOption(SG_ControllerOption option, bool value)
{
m_modified = true;
Expand Down Expand Up @@ -85,23 +81,21 @@ void KX_IpoController::SetOption(SG_ControllerOption option, bool value)
}
}

void KX_IpoController::SetGameObject(KX_GameObject *go)
bool KX_IpoController::Update(SG_Node *node)
{
m_game_object = go;
}

bool KX_IpoController::Update()
{
if (!SG_Controller::Update()) {
if (!SG_Controller::Update(node)) {
return false;
}

KX_GameObject *obj = static_cast<KX_GameObject *>(node->GetClientObject());

//initialization on the first frame of the IPO
if (!m_ipo_start_initialized) {
m_ipo_start_point = m_node->GetLocalPosition();
m_ipo_start_orient = m_node->GetLocalOrientation();
m_ipo_start_scale = m_node->GetLocalScale();
m_ipo_start_point = node->GetLocalPosition();
m_ipo_start_orient = node->GetLocalOrientation();
m_ipo_start_scale = node->GetLocalScale();
m_ipo_start_initialized = true;

if (!m_ipo_euler_initialized) {
// do it only once to avoid angle discontinuities
m_ipo_start_euler = m_ipo_start_orient.GetEuler();
Expand All @@ -113,33 +107,33 @@ bool KX_IpoController::Update()
if (m_ipo_channels_active[OB_LOC_X] || m_ipo_channels_active[OB_LOC_Y] || m_ipo_channels_active[OB_LOC_Z] ||
m_ipo_channels_active[OB_DLOC_X] || m_ipo_channels_active[OB_DLOC_Y] || m_ipo_channels_active[OB_DLOC_Z]) {
if (m_ipo_as_force) {
if (m_game_object && m_node && m_game_object->GetPhysicsController()) {
if (obj->GetPhysicsController()) {
const mt::vec3 vec = m_ipo_local ?
m_node->GetWorldOrientation() * m_ipo_xform.GetPosition() :
node->GetWorldOrientation() * m_ipo_xform.GetPosition() :
m_ipo_xform.GetPosition();
m_game_object->GetPhysicsController()->ApplyForce(vec, false);
obj->GetPhysicsController()->ApplyForce(vec, false);
}
}
else {
// Local ipo should be defined with the m_nodeject position at (0,0,0)
// Local transform is applied to the m_nodeject based on initial position
// Local ipo should be defined with the nodeject position at (0,0,0)
// Local transform is applied to the nodeject based on initial position
mt::vec3 newPosition = mt::zero3;

if (!m_ipo_add) {
newPosition = m_node->GetLocalPosition();
newPosition = node->GetLocalPosition();
}
//apply separate IPO channels if there is any data in them
//Loc and dLoc act by themselves or are additive
for (unsigned short i = 0; i < 3; ++i) {
const mt::vec3& loc = m_ipo_xform.GetPosition();
const mt::vec3& dloc = m_ipo_xform.GetDeltaPosition();

const bool dactive = m_ipo_channels_active[OB_DLOC_X + i];
const bool delta = m_ipo_channels_active[OB_DLOC_X + i];

if (m_ipo_channels_active[OB_LOC_X + i]) {
newPosition[i] = (dactive ? loc[i] + dloc[i] : loc[i]);
newPosition[i] = (delta ? loc[i] + dloc[i] : loc[i]);
}
else if (dactive) {
else if (delta) {
newPosition[i] = (((!m_ipo_add) ? m_ipo_start_point[i] : 0.0f) + dloc[i]);
}
}
Expand All @@ -152,20 +146,17 @@ bool KX_IpoController::Update()
newPosition = m_ipo_start_point + newPosition;
}
}
if (m_game_object) {
m_game_object->NodeSetLocalPosition(newPosition);
}

obj->NodeSetLocalPosition(newPosition);
}
}
//modifies orientation?
if (m_ipo_channels_active[OB_ROT_X] || m_ipo_channels_active[OB_ROT_Y] || m_ipo_channels_active[OB_ROT_Z] ||
m_ipo_channels_active[OB_DROT_X] || m_ipo_channels_active[OB_DROT_Y] || m_ipo_channels_active[OB_DROT_Z]) {
if (m_ipo_as_force) {
if (m_game_object && m_node) {
m_game_object->ApplyTorque(m_ipo_local ?
m_node->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() :
m_ipo_xform.GetEulerAngles(), false);
}
obj->ApplyTorque(m_ipo_local ?
node->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() :
m_ipo_xform.GetEulerAngles(), false);
}
else if (m_ipo_add) {
// Delta euler angles.
Expand All @@ -187,9 +178,8 @@ bool KX_IpoController::Update()
else {
rotation = rotation * m_ipo_start_orient;
}
if (m_game_object) {
m_game_object->NodeSetLocalOrientation(rotation);
}

obj->NodeSetLocalOrientation(rotation);
}
else if (m_ipo_channels_active[OB_ROT_X] || m_ipo_channels_active[OB_ROT_Y] || m_ipo_channels_active[OB_ROT_Z]) {
// assume all channel absolute
Expand All @@ -201,19 +191,17 @@ bool KX_IpoController::Update()
const mt::vec3& eul = m_ipo_xform.GetEulerAngles();
const mt::vec3& deul = m_ipo_xform.GetDeltaEulerAngles();

const bool dactive = m_ipo_channels_active[OB_DROT_X + i];
const bool delta = m_ipo_channels_active[OB_DROT_X + i];

if (m_ipo_channels_active[OB_ROT_X + i]) {
angles[i] = (dactive ? (eul[i] + deul[i]) : eul[i]);
angles[i] = (delta ? (eul[i] + deul[i]) : eul[i]);
}
else if (dactive) {
else if (delta) {
angles[i] += deul[i];
}
}

if (m_game_object) {
m_game_object->NodeSetLocalOrientation(mt::mat3(angles));
}
obj->NodeSetLocalOrientation(mt::mat3(angles));
}
else {
mt::vec3 angles = mt::zero3;
Expand All @@ -225,11 +213,9 @@ bool KX_IpoController::Update()
}

// dRot are always local
mt::mat3 rotation(angles);
rotation = m_ipo_start_orient * rotation;
if (m_game_object) {
m_game_object->NodeSetLocalOrientation(rotation);
}
const mt::mat3 rotation = m_ipo_start_orient * mt::mat3(angles);

obj->NodeSetLocalOrientation(rotation);
}
}
//modifies scale?
Expand All @@ -238,29 +224,28 @@ bool KX_IpoController::Update()
//default is no scale change
mt::vec3 newScale = mt::one3;
if (!m_ipo_add) {
newScale = m_node->GetLocalScale();
newScale = node->GetLocalScale();
}

for (unsigned short i = 0; i < 3; ++i) {
const mt::vec3& scale = m_ipo_xform.GetScaling();
const mt::vec3& dscale = m_ipo_xform.GetDeltaScaling();

const bool dactive = m_ipo_channels_active[OB_DSIZE_X + i];
const bool delta = m_ipo_channels_active[OB_DSIZE_X + i];

if (m_ipo_channels_active[OB_SIZE_X + i]) {
newScale[i] = (dactive ? (scale[i] + dscale[i]) : scale[i]);
newScale[i] = (delta ? (scale[i] + dscale[i]) : scale[i]);
}
else if (dactive) {
else if (delta) {
newScale[i] = (dscale[i] + ((!m_ipo_add) ? m_ipo_start_scale[i] : 0.0f));
}
}

if (m_ipo_add) {
newScale = m_ipo_start_scale * newScale;
}
if (m_game_object) {
m_game_object->NodeSetLocalScale(newScale);
}

obj->NodeSetLocalScale(newScale);
}

return true;
Expand Down
Loading

0 comments on commit 96567f2

Please sign in to comment.