Delta Loc/Rot/Scale Ipo curve are now supporting in the BGE with the following limitations:

1. All Ipo channels are now independent. 
In Blender 2.45, all 3 Loc Ipo channels were automatically set
together. For example, having just a LocX Ipo channel was sufficient
to fix the X, Y and Z coordinates, with the Y and Z value taken
from the object original Y and Z location in Blender. The same
was true for the 3 Rot and the 3 Scale Ipo channels: the missing
channels were assumed to have constant value taken from the object
original orientation/scale in Blender.
With this patch, all Ipo channels are now independent. 
THIS WILL CREATE BACKWARD COMPATIBILITY PROBLEM if you omit to
define the 3 channels of a same type together in your Blend file:
the undefined Loc, Rot, Scale coordinates of the object will
be influenced by the parent/spawner Loc/Rot/Scale in case the
object is a child or dynamically created.

2. Delta Loc, Rot, Scale are now supported with the following
limitations:
- The delta Loc/Rot Ipo modify the object global (NOT local)
location/orientation
- The delta Scale change the object local scale
- The delta Ipo curves are relative to the object starting
Loc/Rot/Scale when the Ipo was first activated; after that, the
delta Ipo becomes global. This means that the object will return
to this initial Loc/Rot/Scale when you later restart the Ipo
curve, even if you had changed the object Loc/Rot/Scale in the
meantime. Of course this applies only to the specific Loc/Rot/Scale
coordinate that are defined in the Ipo channels as the channels
are now independent.

3. When the objects are converted from Blender to the BGE, the
delta Loc/Rot/Scale that might result from initial non-zero values
in delta Ipo Curves will be ignored. However, as soon as the
delta Ipo curve is activated, the non-zero values will be taken
into account and the object will jump to the same Loc/Rot/Scale
situation as in Blender. Note that delta Ipo curves with initial
non-zero values is bad practice; logically, a delta Ipo curver
should always start from 0.

4. If you define both a global and delta channel of the same
type (LocX and DLocX), the result will be a global channel equivalent
to the sum of the two channels (LocX+DLocX).
This commit is contained in:
Benoit Bolsee 2008-03-12 21:33:24 +00:00
parent 8cc341a5a4
commit 3444d6612a
4 changed files with 180 additions and 52 deletions

@ -147,6 +147,26 @@ public:
-sj, cj * si, cj * ci); -sj, cj * si, cj * ci);
} }
void getEuler(MT_Scalar& yaw, MT_Scalar& pitch, MT_Scalar& roll) const
{
if (m_el[2][0] != -1.0 && m_el[2][0] != 1.0) {
pitch = MT_Scalar(-asin(m_el[2][0]));
yaw = MT_Scalar(atan2(m_el[2][1] / cos(pitch), m_el[2][2] / cos(pitch)));
roll = MT_Scalar(atan2(m_el[1][0] / cos(pitch), m_el[0][0] / cos(pitch)));
}
else {
roll = MT_Scalar(0);
if (m_el[2][0] == -1.0) {
pitch = MT_PI / 2.0;
yaw = MT_Scalar(atan2(m_el[0][1], m_el[0][2]));
}
else {
pitch = - MT_PI / 2.0;
yaw = MT_Scalar(atan2(m_el[0][1], m_el[0][2]));
}
}
}
void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z) { void scale(MT_Scalar x, MT_Scalar y, MT_Scalar z) {
m_el[0][0] *= x; m_el[0][1] *= y; m_el[0][2] *= z; m_el[0][0] *= x; m_el[0][1] *= y; m_el[0][2] *= z;
m_el[1][0] *= x; m_el[1][1] *= y; m_el[1][2] *= z; m_el[1][0] *= x; m_el[1][1] *= y; m_el[1][2] *= z;

@ -100,9 +100,9 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
ipocontr->GetIPOTransform().SetPosition( ipocontr->GetIPOTransform().SetPosition(
MT_Point3( MT_Point3(
blenderobject->loc[0]+blenderobject->dloc[0], blenderobject->loc[0]/*+blenderobject->dloc[0]*/,
blenderobject->loc[1]+blenderobject->dloc[1], blenderobject->loc[1]/*+blenderobject->dloc[1]*/,
blenderobject->loc[2]+blenderobject->dloc[2] blenderobject->loc[2]/*+blenderobject->dloc[2]*/
) )
); );
ipocontr->GetIPOTransform().SetEulerAngles( ipocontr->GetIPOTransform().SetEulerAngles(
@ -134,7 +134,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetPosition()[0]), &(ipocontr->GetIPOTransform().GetPosition()[0]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyPosition(true); ipocontr->SetIPOChannelActive(OB_LOC_X, true);
} }
@ -145,7 +145,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetPosition()[1]), &(ipocontr->GetIPOTransform().GetPosition()[1]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyPosition(true); ipocontr->SetIPOChannelActive(OB_LOC_Y, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_LOC_Z); ipo = ipoList->GetScalarInterpolator(OB_LOC_Z);
@ -155,7 +155,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetPosition()[2]), &(ipocontr->GetIPOTransform().GetPosition()[2]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyPosition(true); ipocontr->SetIPOChannelActive(OB_LOC_Z, true);
} }
// Master the art of cut & paste programming... // Master the art of cut & paste programming...
@ -167,7 +167,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetDeltaPosition()[0]), &(ipocontr->GetIPOTransform().GetDeltaPosition()[0]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyPosition(true); ipocontr->SetIPOChannelActive(OB_DLOC_X, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_DLOC_Y); ipo = ipoList->GetScalarInterpolator(OB_DLOC_Y);
@ -177,7 +177,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetDeltaPosition()[1]), &(ipocontr->GetIPOTransform().GetDeltaPosition()[1]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyPosition(true); ipocontr->SetIPOChannelActive(OB_DLOC_Y, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_DLOC_Z); ipo = ipoList->GetScalarInterpolator(OB_DLOC_Z);
@ -187,7 +187,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetDeltaPosition()[2]), &(ipocontr->GetIPOTransform().GetDeltaPosition()[2]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyPosition(true); ipocontr->SetIPOChannelActive(OB_DLOC_Z, true);
} }
// Explore the finesse of reuse and slight modification // Explore the finesse of reuse and slight modification
@ -199,7 +199,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetEulerAngles()[0]), &(ipocontr->GetIPOTransform().GetEulerAngles()[0]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyOrientation(true); ipocontr->SetIPOChannelActive(OB_ROT_X, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_ROT_Y); ipo = ipoList->GetScalarInterpolator(OB_ROT_Y);
if (ipo) { if (ipo) {
@ -208,7 +208,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetEulerAngles()[1]), &(ipocontr->GetIPOTransform().GetEulerAngles()[1]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyOrientation(true); ipocontr->SetIPOChannelActive(OB_ROT_Y, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_ROT_Z); ipo = ipoList->GetScalarInterpolator(OB_ROT_Z);
if (ipo) { if (ipo) {
@ -217,7 +217,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetEulerAngles()[2]), &(ipocontr->GetIPOTransform().GetEulerAngles()[2]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyOrientation(true); ipocontr->SetIPOChannelActive(OB_ROT_Z, true);
} }
// Hmmm, the need for a macro comes to mind... // Hmmm, the need for a macro comes to mind...
@ -229,7 +229,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[0]), &(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[0]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyOrientation(true); ipocontr->SetIPOChannelActive(OB_DROT_X, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_DROT_Y); ipo = ipoList->GetScalarInterpolator(OB_DROT_Y);
if (ipo) { if (ipo) {
@ -238,7 +238,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[1]), &(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[1]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyOrientation(true); ipocontr->SetIPOChannelActive(OB_DROT_Y, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_DROT_Z); ipo = ipoList->GetScalarInterpolator(OB_DROT_Z);
if (ipo) { if (ipo) {
@ -247,7 +247,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[2]), &(ipocontr->GetIPOTransform().GetDeltaEulerAngles()[2]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyOrientation(true); ipocontr->SetIPOChannelActive(OB_DROT_Z, true);
} }
// Hang on, almost there... // Hang on, almost there...
@ -259,7 +259,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetScaling()[0]), &(ipocontr->GetIPOTransform().GetScaling()[0]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyScaling(true); ipocontr->SetIPOChannelActive(OB_SIZE_X, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_SIZE_Y); ipo = ipoList->GetScalarInterpolator(OB_SIZE_Y);
if (ipo) { if (ipo) {
@ -268,7 +268,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetScaling()[1]), &(ipocontr->GetIPOTransform().GetScaling()[1]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyScaling(true); ipocontr->SetIPOChannelActive(OB_SIZE_Y, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_SIZE_Z); ipo = ipoList->GetScalarInterpolator(OB_SIZE_Z);
if (ipo) { if (ipo) {
@ -277,7 +277,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetScaling()[2]), &(ipocontr->GetIPOTransform().GetScaling()[2]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyScaling(true); ipocontr->SetIPOChannelActive(OB_SIZE_Z, true);
} }
// The last few... // The last few...
@ -289,7 +289,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetDeltaScaling()[0]), &(ipocontr->GetIPOTransform().GetDeltaScaling()[0]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyScaling(true); ipocontr->SetIPOChannelActive(OB_DSIZE_X, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_DSIZE_Y); ipo = ipoList->GetScalarInterpolator(OB_DSIZE_Y);
if (ipo) { if (ipo) {
@ -298,7 +298,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetDeltaScaling()[1]), &(ipocontr->GetIPOTransform().GetDeltaScaling()[1]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyScaling(true); ipocontr->SetIPOChannelActive(OB_DSIZE_Y, true);
} }
ipo = ipoList->GetScalarInterpolator(OB_DSIZE_Z); ipo = ipoList->GetScalarInterpolator(OB_DSIZE_Z);
if (ipo) { if (ipo) {
@ -307,7 +307,7 @@ void BL_ConvertIpos(struct Object* blenderobject,KX_GameObject* gameobj,KX_Blend
&(ipocontr->GetIPOTransform().GetDeltaScaling()[2]), &(ipocontr->GetIPOTransform().GetDeltaScaling()[2]),
ipo); ipo);
ipocontr->AddInterpolator(interpolator); ipocontr->AddInterpolator(interpolator);
ipocontr->SetModifyScaling(true); ipocontr->SetIPOChannelActive(OB_DSIZE_Z, true);
} }
{ {

@ -51,20 +51,21 @@ typedef unsigned long uint_ptr;
#include "KX_ScalarInterpolator.h" #include "KX_ScalarInterpolator.h"
#include "KX_GameObject.h" #include "KX_GameObject.h"
#include "KX_IPhysicsController.h" #include "KX_IPhysicsController.h"
#include "DNA_ipo_types.h"
#include "BLI_arithb.h"
// All objects should start on frame 1! Will we ever need an object to // All objects should start on frame 1! Will we ever need an object to
// start on another frame, the 1.0 should change. // start on another frame, the 1.0 should change.
KX_IpoSGController::KX_IpoSGController() KX_IpoSGController::KX_IpoSGController()
: m_modify_position(false), : m_ipo_as_force(false),
m_modify_orientation(false),
m_modify_scaling(false),
m_ipo_as_force(false),
m_force_ipo_acts_local(false), m_force_ipo_acts_local(false),
m_modified(true), m_modified(true),
m_ipo_start_initialized(false),
m_ipotime(1.0) m_ipotime(1.0)
{ {
m_game_object = NULL; m_game_object = NULL;
for (int i=0; i < KX_MAX_IPO_CHANNELS; i++)
m_ipo_channels_active[i] = false;
} }
@ -115,21 +116,60 @@ bool KX_IpoSGController::Update(double currentTime)
} }
SG_Spatial* ob = (SG_Spatial*)m_pObject; SG_Spatial* ob = (SG_Spatial*)m_pObject;
if (m_modify_position) { //initialization on the first frame of the IPO
if (m_ipo_as_force) { if (! m_ipo_start_initialized && currentTime > 0.0) {
m_ipo_start_point = ob->GetLocalPosition();
if (m_game_object && ob) { m_ipo_start_orient = ob->GetLocalOrientation();
m_ipo_start_scale = ob->GetLocalScale();
m_ipo_start_initialized = true;
}
//modifies position?
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 == true)
{
if (m_game_object && ob)
{
m_game_object->GetPhysicsController()->ApplyForce(m_force_ipo_acts_local ? m_game_object->GetPhysicsController()->ApplyForce(m_force_ipo_acts_local ?
ob->GetWorldOrientation() * m_ipo_xform.GetPosition() : ob->GetWorldOrientation() * m_ipo_xform.GetPosition() :
m_ipo_xform.GetPosition(), false); m_ipo_xform.GetPosition(), false);
} }
}
} else { else
ob->SetLocalPosition(m_ipo_xform.GetPosition()); {
//by default, leave object as it stands
MT_Point3 newPosition = ob->GetLocalPosition();
//apply separate IPO channels if there is any data in them
//Loc and dLoc act by themselves or are additive
//LocX and dLocX
if (m_ipo_channels_active[OB_LOC_X]) {
newPosition[0] = (m_ipo_channels_active[OB_DLOC_X] ? m_ipo_xform.GetPosition()[0] + m_ipo_xform.GetDeltaPosition()[0] : m_ipo_xform.GetPosition()[0]);
}
else if (m_ipo_channels_active[OB_DLOC_X] && m_ipo_start_initialized) {
newPosition[0] = (m_ipo_start_point[0] + m_ipo_xform.GetDeltaPosition()[0]);
}
//LocY and dLocY
if (m_ipo_channels_active[OB_LOC_Y]) {
newPosition[1] = (m_ipo_channels_active[OB_DLOC_Y] ? m_ipo_xform.GetPosition()[1] + m_ipo_xform.GetDeltaPosition()[1] : m_ipo_xform.GetPosition()[1]);
}
else if (m_ipo_channels_active[OB_DLOC_Y] && m_ipo_start_initialized) {
newPosition[1] = (m_ipo_start_point[1] + m_ipo_xform.GetDeltaPosition()[1]);
}
//LocZ and dLocZ
if (m_ipo_channels_active[OB_LOC_Z]) {
newPosition[2] = (m_ipo_channels_active[OB_DLOC_Z] ? m_ipo_xform.GetPosition()[2] + m_ipo_xform.GetDeltaPosition()[2] : m_ipo_xform.GetPosition()[2]);
}
else if (m_ipo_channels_active[OB_DLOC_Z] && m_ipo_start_initialized) {
newPosition[2] = (m_ipo_start_point[2] + m_ipo_xform.GetDeltaPosition()[2]);
}
ob->SetLocalPosition(newPosition);
} }
} }
if (m_modify_orientation) { //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_ipo_as_force) {
if (m_game_object && ob) { if (m_game_object && ob) {
@ -137,13 +177,71 @@ bool KX_IpoSGController::Update(double currentTime)
ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() : ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() :
m_ipo_xform.GetEulerAngles(), false); m_ipo_xform.GetEulerAngles(), false);
} }
} else { } else {
ob->SetLocalOrientation(MT_Matrix3x3(m_ipo_xform.GetEulerAngles())); double yaw, pitch, roll; //final Euler angles
double tempYaw=0, tempPitch=0, tempRoll=0; //temp holders
ob->GetLocalOrientation().getEuler(yaw, pitch, roll);
//RotX and dRotX
if (m_ipo_channels_active[OB_ROT_X]) {
yaw = (m_ipo_channels_active[OB_DROT_X] ? (m_ipo_xform.GetEulerAngles()[0] + m_ipo_xform.GetDeltaEulerAngles()[0]) : m_ipo_xform.GetEulerAngles()[0] );
}
else if (m_ipo_channels_active[OB_DROT_X] && m_ipo_start_initialized) {
m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
yaw = tempYaw + m_ipo_xform.GetDeltaEulerAngles()[0];
}
//RotY dRotY
if (m_ipo_channels_active[OB_ROT_Y]) {
pitch = (m_ipo_channels_active[OB_DROT_Y] ? (m_ipo_xform.GetEulerAngles()[1] + m_ipo_xform.GetDeltaEulerAngles()[1]) : m_ipo_xform.GetEulerAngles()[1] );
}
else if (m_ipo_channels_active[OB_DROT_Y] && m_ipo_start_initialized) {
m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
pitch = tempPitch + m_ipo_xform.GetDeltaEulerAngles()[1];
}
//RotZ and dRotZ
if (m_ipo_channels_active[OB_ROT_Z]) {
roll = (m_ipo_channels_active[OB_DROT_Z] ? (m_ipo_xform.GetEulerAngles()[2] + m_ipo_xform.GetDeltaEulerAngles()[2]) : m_ipo_xform.GetEulerAngles()[2] );
}
else if (m_ipo_channels_active[OB_DROT_Z] && m_ipo_start_initialized) {
m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
roll = tempRoll + m_ipo_xform.GetDeltaEulerAngles()[2];
}
ob->SetLocalOrientation(MT_Vector3(yaw, pitch, roll));
} }
} }
if (m_modify_scaling) //modifies scale?
ob->SetLocalScale(m_ipo_xform.GetScaling()); if (m_ipo_channels_active[OB_SIZE_X] || m_ipo_channels_active[OB_SIZE_Y] || m_ipo_channels_active[OB_SIZE_Z] || m_ipo_channels_active[OB_DSIZE_X] || m_ipo_channels_active[OB_DSIZE_Y] || m_ipo_channels_active[OB_DSIZE_Z]) {
//default is no scale change
MT_Vector3 newScale = ob->GetLocalScale();
if (m_ipo_channels_active[OB_SIZE_X]) {
newScale[0] = (m_ipo_channels_active[OB_DSIZE_X] ? (m_ipo_xform.GetScaling()[0] + m_ipo_xform.GetDeltaScaling()[0]) : m_ipo_xform.GetScaling()[0]);
}
else if (m_ipo_channels_active[OB_DSIZE_X] && m_ipo_start_initialized) {
newScale[0] = (m_ipo_xform.GetDeltaScaling()[0] + m_ipo_start_scale[0]);
}
//RotY dRotY
if (m_ipo_channels_active[OB_SIZE_Y]) {
newScale[1] = (m_ipo_channels_active[OB_DSIZE_Y] ? (m_ipo_xform.GetScaling()[1] + m_ipo_xform.GetDeltaScaling()[1]): m_ipo_xform.GetScaling()[1]);
}
else if (m_ipo_channels_active[OB_DSIZE_Y] && m_ipo_start_initialized) {
newScale[1] = (m_ipo_xform.GetDeltaScaling()[1] + m_ipo_start_scale[1]);
}
//RotZ and dRotZ
if (m_ipo_channels_active[OB_SIZE_Z]) {
newScale[2] = (m_ipo_channels_active[OB_DSIZE_Z] ? (m_ipo_xform.GetScaling()[2] + m_ipo_xform.GetDeltaScaling()[2]) : m_ipo_xform.GetScaling()[2]);
}
else if (m_ipo_channels_active[OB_DSIZE_Z] && m_ipo_start_initialized) {
newScale[2] = (m_ipo_xform.GetDeltaScaling()[2] + m_ipo_start_scale[2]);
}
ob->SetLocalScale(newScale);
}
m_modified=false; m_modified=false;
} }

@ -38,27 +38,40 @@
#include "KX_IPOTransform.h" #include "KX_IPOTransform.h"
#include "KX_IInterpolator.h" #include "KX_IInterpolator.h"
#define KX_MAX_IPO_CHANNELS 19 //note- [0] is not used
class KX_IpoSGController : public SG_Controller class KX_IpoSGController : public SG_Controller
{ {
KX_IPOTransform m_ipo_xform; KX_IPOTransform m_ipo_xform;
T_InterpolatorList m_interpolators; T_InterpolatorList m_interpolators;
/* Why not bools? */
short m_modify_position : 1; /** Flag for each IPO channel that can be applied to a game object */
short m_modify_orientation : 1; bool m_ipo_channels_active[KX_MAX_IPO_CHANNELS];
short m_modify_scaling : 1;
/** Interpret the ipo as a force rather than a displacement? */ /** Interpret the ipo as a force rather than a displacement? */
bool m_ipo_as_force; bool m_ipo_as_force;
/** Ipo-as-force acts in local rather than in global coordinates? */ /** Ipo-as-force acts in local rather than in global coordinates? */
bool m_force_ipo_acts_local; bool m_force_ipo_acts_local;
/** Were settings altered since the last update? */ /** Were settings altered since the last update? */
bool m_modified; bool m_modified;
/** Local time of this ipo.*/ /** Local time of this ipo.*/
double m_ipotime; double m_ipotime;
/** Location of the object when the IPO is first fired (for local transformations) */
class MT_Point3 m_ipo_start_point;
/** Orientation of the object when the IPO is first fired (for local transformations) */
class MT_Matrix3x3 m_ipo_start_orient;
/** Scale of the object when the IPO is first fired (for local transformations) */
class MT_Vector3 m_ipo_start_scale;
/** if IPO initial position has been set for local normal IPO */
bool m_ipo_start_initialized;
/** A reference to the original game object. */ /** A reference to the original game object. */
class KX_GameObject* m_game_object; class KX_GameObject* m_game_object;
@ -80,16 +93,12 @@ public:
/** Set reference to the corresponding game object. */ /** Set reference to the corresponding game object. */
void SetGameObject(class KX_GameObject*); void SetGameObject(class KX_GameObject*);
void SetModifyPosition(bool modifypos) { void SetIPOChannelActive(int index, bool value) {
m_modify_position=modifypos; //indexes found in makesdna\DNA_ipo_types.h
} m_ipo_channels_active[index] = value;
void SetModifyOrientation(bool modifyorient) {
m_modify_orientation=modifyorient;
}
void SetModifyScaling(bool modifyscale) {
m_modify_scaling=modifyscale;
} }
KX_IPOTransform& GetIPOTransform() KX_IPOTransform& GetIPOTransform()
{ {
return m_ipo_xform; return m_ipo_xform;
@ -105,3 +114,4 @@ public:
#endif //__IPO_SGCONTROLLER_H #endif //__IPO_SGCONTROLLER_H