Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj6
-rw-r--r--source/blender/makesdna/DNA_actuator_types.h5
-rw-r--r--source/blender/src/buttons_logic.c61
-rw-r--r--source/gameengine/Converter/BL_BlenderDataConversion.cpp3
-rw-r--r--source/gameengine/Converter/KX_ConvertActuators.cpp7
-rw-r--r--source/gameengine/GameLogic/SCA_ActuatorSensor.cpp2
-rw-r--r--source/gameengine/GameLogic/SCA_IActuator.h1
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.cpp8
-rw-r--r--source/gameengine/GameLogic/SCA_IObject.h15
-rw-r--r--source/gameengine/GameLogic/SCA_ISensor.h2
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp39
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h14
-rw-r--r--source/gameengine/Ketsji/KX_IPO_SGController.cpp87
-rw-r--r--source/gameengine/Ketsji/KX_IPO_SGController.h7
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.cpp171
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.h12
-rw-r--r--source/gameengine/Ketsji/KX_ParentActuator.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp2
-rw-r--r--source/gameengine/SceneGraph/SG_Controller.h4
19 files changed, 274 insertions, 178 deletions
diff --git a/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj b/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj
index 34c195cf23d..0dfbcaa5577 100644
--- a/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj
+++ b/projectfiles_vc7/blender/blenlib/BLI_blenlib.vcproj
@@ -359,6 +359,9 @@
RelativePath="..\..\..\source\blender\blenlib\intern\BLI_memarena.c">
</File>
<File
+ RelativePath="..\..\..\source\blender\blenlib\intern\BLI_mempool.c">
+ </File>
+ <File
RelativePath="..\..\..\source\blender\blenlib\intern\boxpack2d.c">
</File>
<File
@@ -474,6 +477,9 @@
RelativePath="..\..\..\source\blender\blenlib\BLI_memarena.h">
</File>
<File
+ RelativePath="..\..\..\source\blender\blenlib\BLI_mempool.h">
+ </File>
+ <File
RelativePath="..\..\..\source\blender\blenlib\intern\BLI_scanfill.h">
</File>
<File
diff --git a/source/blender/makesdna/DNA_actuator_types.h b/source/blender/makesdna/DNA_actuator_types.h
index 3cf80a4efa6..77ebef744eb 100644
--- a/source/blender/makesdna/DNA_actuator_types.h
+++ b/source/blender/makesdna/DNA_actuator_types.h
@@ -339,8 +339,9 @@ typedef struct FreeCamera {
/* ipoactuator->flag */
#define ACT_IPOFORCE (1 << 0)
#define ACT_IPOEND (1 << 1)
-#define ACT_IPOFORCE_LOCAL (1 << 2)
-#define ACT_IPOCHILD (1 << 4)
+#define ACT_IPOLOCAL (1 << 2)
+#define ACT_IPOCHILD (1 << 4)
+#define ACT_IPOADD (1 << 5)
/* ipoactuator->flag for k2k */
#define ACT_K2K_PREV 1
diff --git a/source/blender/src/buttons_logic.c b/source/blender/src/buttons_logic.c
index 616a5a227c4..7050e61a6ac 100644
--- a/source/blender/src/buttons_logic.c
+++ b/source/blender/src/buttons_logic.c
@@ -1581,6 +1581,18 @@ static void change_object_actuator(void *act, void *arg)
}
}
+static void change_ipo_actuator(void *arg1_but, void *arg2_ia)
+{
+ bIpoActuator *ia = arg2_ia;
+ uiBut *but = arg1_but;
+
+ if (but->retval & ACT_IPOFORCE)
+ ia->flag &= ~ACT_IPOADD;
+ else if (but->retval & ACT_IPOADD)
+ ia->flag &= ~ACT_IPOFORCE;
+ but->retval = B_REDR;
+}
+
void update_object_actuator_PID(void *act, void *arg)
{
bObjectActuator *oa = act;
@@ -1799,42 +1811,49 @@ static short draw_actuatorbuttons(Object *ob, bActuator *act, uiBlock *block, sh
str = "Ipo types %t|Play %x0|Ping Pong %x1|Flipper %x2|Loop Stop %x3|Loop End %x4|Property %x6";
- uiDefButS(block, MENU, B_REDR, str, xco+20, yco-24, width-40 - (width-40)/3, 19, &ia->type, 0, 0, 0, 0, "");
- uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR,
- "Child", xco+20+0.666*(width-40), yco-24, (width-40)/3, 19,
+ uiDefButS(block, MENU, B_REDR, str, xco+10, yco-24, (width-20)/2, 19, &ia->type, 0, 0, 0, 0, "");
+
+ but = uiDefButBitS(block, TOG, ACT_IPOFORCE, ACT_IPOFORCE,
+ "Force", xco+10+(width-20)/2, yco-24, (width-20)/4-10, 19,
&ia->flag, 0, 0, 0, 0,
- "Add all children Objects as well");
+ "Convert Ipo to force. Force is applied in global or local coordinate according to Local flag");
+ uiButSetFunc(but, change_ipo_actuator, but, ia);
+
+ but = uiDefButBitS(block, TOG, ACT_IPOADD, ACT_IPOADD,
+ "Add", xco+3*(width-20)/4, yco-24, (width-20)/4-10, 19,
+ &ia->flag, 0, 0, 0, 0,
+ "Ipo is added to the current loc/rot/scale in global or local coordinate according to Local flag");
+ uiButSetFunc(but, change_ipo_actuator, but, ia);
+
+ /* Only show the do-force-local toggle if force is requested */
+ if (ia->flag & (ACT_IPOFORCE|ACT_IPOADD)) {
+ uiDefButBitS(block, TOG, ACT_IPOLOCAL, 0,
+ "L", xco+width-30, yco-24, 20, 19,
+ &ia->flag, 0, 0, 0, 0,
+ "Let the ipo acts in local coordinates, used in Force and Add mode.");
+ }
if(ia->type==ACT_IPO_FROM_PROP) {
uiDefBut(block, TEX, 0,
- "Prop: ", xco+20, yco-44, width-40, 19,
+ "Prop: ", xco+10, yco-44, width-80, 19,
ia->name, 0.0, 31.0, 0, 0,
"Use this property to define the Ipo position");
}
else {
uiDefButI(block, NUM, 0,
- "Sta", xco+20, yco-44, (width-100)/2, 19,
+ "Sta", xco+10, yco-44, (width-80)/2, 19,
&ia->sta, 0.0, MAXFRAMEF, 0, 0,
"Start frame, (subtract 1 to match blenders frame numbers)");
uiDefButI(block, NUM, 0,
- "End", xco+18+(width-90)/2, yco-44, (width-100)/2, 19,
+ "End", xco+10+(width-80)/2, yco-44, (width-80)/2, 19,
&ia->end, 0.0, MAXFRAMEF, 0, 0,
"End frame, (subtract 1 to match blenders frame numbers)");
-
- uiDefButBitS(block, TOG, ACT_IPOFORCE, B_REDR,
- "Force", xco+width-78, yco-44, 43, 19,
- &ia->flag, 0, 0, 0, 0,
- "Convert Ipo to force");
-
- /* Only show the do-force-local toggle if force is requested */
- if (ia->flag & ACT_IPOFORCE) {
- uiDefButBitS(block, TOG, ACT_IPOFORCE_LOCAL, 0,
- "L", xco+width-35, yco-44, 15, 19,
- &ia->flag, 0, 0, 0, 0,
- "Let the force-ipo act in local coordinates.");
- }
-
}
+ uiDefButBitS(block, TOG, ACT_IPOCHILD, B_REDR,
+ "Child", xco+10+(width-80), yco-44, 60, 19,
+ &ia->flag, 0, 0, 0, 0,
+ "Update IPO on all children Objects as well");
+
yco-= ysize;
break;
}
diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
index 665783a1ba5..d8b157cb5b4 100644
--- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp
+++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp
@@ -2331,7 +2331,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie,
{
KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i));
struct Object* blenderobj = converter->FindBlenderObject(gameobj);
- gameobj->SetState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state);
+ gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state);
+ gameobj->ResetState();
}
#endif //CONVERT_LOGIC
diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp
index 6e05ea31fe8..9b1bc1e6b90 100644
--- a/source/gameengine/Converter/KX_ConvertActuators.cpp
+++ b/source/gameengine/Converter/KX_ConvertActuators.cpp
@@ -233,7 +233,8 @@ void BL_ConvertActuators(char* maggiename,
STR_String propname = ( ipoact->name ? ipoact->name : "");
// first bit?
bool ipo_as_force = (ipoact->flag & ACT_IPOFORCE);
- bool force_local = (ipoact->flag & ACT_IPOFORCE_LOCAL);
+ bool local = (ipoact->flag & ACT_IPOLOCAL);
+ bool ipo_add = (ipoact->flag & ACT_IPOADD);
KX_IpoActuator* tmpbaseact = new KX_IpoActuator(
gameobj,
@@ -244,8 +245,8 @@ void BL_ConvertActuators(char* maggiename,
ipoact->type + 1, // + 1, because Blender starts to count at zero,
// Ketsji at 1, because zero is reserved for "NoDef"
ipo_as_force,
- force_local
- );
+ ipo_add,
+ local);
baseact = tmpbaseact;
break;
}
diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
index 9645bfbed4a..e1c8ef87dd1 100644
--- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
+++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp
@@ -111,7 +111,7 @@ void SCA_ActuatorSensor::Update()
{
if (m_actuator)
{
- m_midresult = m_actuator->IsActive();
+ m_midresult = m_actuator->IsActive() && !m_actuator->IsNegativeEvent();
}
}
diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h
index 774b27c5ad4..7ffb21b5490 100644
--- a/source/gameengine/GameLogic/SCA_IActuator.h
+++ b/source/gameengine/GameLogic/SCA_IActuator.h
@@ -87,6 +87,7 @@ public:
bool IsNegativeEvent() const;
virtual ~SCA_IActuator();
+ void ClrLink() { m_links=0; }
void IncLink() { m_links++; }
void DecLink();
bool IsNoLink() const { return !m_links; }
diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp
index 27e7d5faada..c5bb4a41552 100644
--- a/source/gameengine/GameLogic/SCA_IObject.cpp
+++ b/source/gameengine/GameLogic/SCA_IObject.cpp
@@ -40,7 +40,7 @@
MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0);
-SCA_IObject::SCA_IObject(PyTypeObject* T): m_state(0), CValue(T)
+SCA_IObject::SCA_IObject(PyTypeObject* T): m_initState(0), m_state(0), CValue(T)
{
m_suspended = false;
}
@@ -164,7 +164,9 @@ void SCA_IObject::ReParentLogic()
{
SCA_IActuator* newactuator = (SCA_IActuator*) (*ita)->GetReplica();
newactuator->ReParent(this);
+ // actuators are initially not connected to any controller
newactuator->SetActive(false);
+ newactuator->ClrLink();
oldactuators[act++] = newactuator;
}
@@ -175,6 +177,7 @@ void SCA_IObject::ReParentLogic()
{
SCA_IController* newcontroller = (SCA_IController*)(*itc)->GetReplica();
newcontroller->ReParent(this);
+ newcontroller->SetActive(false);
oldcontrollers[con++]=newcontroller;
}
@@ -186,6 +189,9 @@ void SCA_IObject::ReParentLogic()
{
SCA_ISensor* newsensor = (SCA_ISensor*)(*its)->GetReplica();
newsensor->ReParent(this);
+ newsensor->SetActive(false);
+ // sensors are initially not connected to any controller
+ newsensor->ClrLink();
oldsensors[sen++] = newsensor;
}
diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h
index 07b4310a91e..38a7ed29dca 100644
--- a/source/gameengine/GameLogic/SCA_IObject.h
+++ b/source/gameengine/GameLogic/SCA_IObject.h
@@ -69,6 +69,11 @@ protected:
bool m_suspended;
/**
+ * init state of object (used when object is created)
+ */
+ unsigned int m_initState;
+
+ /**
* current state = bit mask of state that are active
*/
unsigned int m_state;
@@ -118,6 +123,16 @@ public:
void Resume(void);
/**
+ * Set init state
+ */
+ void SetInitState(unsigned int initState) { m_initState = initState; }
+
+ /**
+ * initialize the state when object is created
+ */
+ void ResetState(void) { SetState(m_initState); }
+
+ /**
* Set the object state
*/
void SetState(unsigned int state);
diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h
index f2ed6a803c2..4ce49e71507 100644
--- a/source/gameengine/GameLogic/SCA_ISensor.h
+++ b/source/gameengine/GameLogic/SCA_ISensor.h
@@ -126,6 +126,8 @@ public:
/** Resume sensing. */
void Resume();
+ void ClrLink()
+ { m_links = 0; }
void IncLink()
{ m_links++; }
void DecLink();
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index bde5e2cd0a2..88fbbb5fd1f 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -405,34 +405,25 @@ void KX_GameObject::ResetDebugColor()
SetDebugColor(0xff000000);
}
+void KX_GameObject::InitIPO(bool ipo_as_force,
+ bool ipo_add,
+ bool ipo_local)
+{
+ SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
+ while (it != GetSGNode()->GetSGControllerList().end()) {
+ (*it)->SetOption(SG_Controller::SG_CONTR_IPO_RESET, true);
+ (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
+ (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_ADD, ipo_add);
+ (*it)->SetOption(SG_Controller::SG_CONTR_IPO_LOCAL, ipo_local);
+ it++;
+ }
+}
void KX_GameObject::UpdateIPO(float curframetime,
- bool recurse,
- bool ipo_as_force,
- bool force_local)
+ bool recurse)
{
-
- // The ipo-actuator needs a sumo reference... this is retrieved (unfortunately)
- // by the iposgcontr itself...
-// ipocontr->SetSumoReference(gameobj->GetSumoScene(),
-// gameobj->GetSumoObject());
-
-
- // The ipo has to be treated as a force, and not a displacement!
- // For this case, we send some settings to the controller. This
- // may need some caching...
- if (ipo_as_force) {
- SGControllerList::iterator it = GetSGNode()->GetSGControllerList().begin();
-
- while (it != GetSGNode()->GetSGControllerList().end()) {
- (*it)->SetOption(SG_Controller::SG_CONTR_IPO_IPO_AS_FORCE, ipo_as_force);
- (*it)->SetOption(SG_Controller::SG_CONTR_IPO_FORCES_ACT_LOCAL, force_local);
- it++;
- }
- }
-
- // The rest is the 'normal' update procedure.
+ // just the 'normal' update procedure.
GetSGNode()->SetSimulatedTime(curframetime,recurse);
GetSGNode()->UpdateWorldData(curframetime);
UpdateTransform();
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index 5e44a36515d..b4f50087742 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -490,14 +490,22 @@ public:
);
/**
+ * Function to set IPO option at start of IPO
+ */
+ void
+ InitIPO(
+ bool ipo_as_force,
+ bool ipo_add,
+ bool ipo_local
+ );
+
+ /**
* Odd function to update an ipo. ???
*/
void
UpdateIPO(
float curframetime,
- bool recurse,
- bool ipo_as_force,
- bool force_ipo_local
+ bool recurse
);
/**
* Updates Material Ipo data
diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp
index 5303e9a9e85..d3aa924665e 100644
--- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp
+++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp
@@ -55,7 +55,8 @@ typedef unsigned long uint_ptr;
// start on another frame, the 1.0 should change.
KX_IpoSGController::KX_IpoSGController()
: m_ipo_as_force(false),
- m_force_ipo_acts_local(false),
+ m_ipo_add(false),
+ m_ipo_local(false),
m_modified(true),
m_ipo_start_initialized(false),
m_ipotime(1.0)
@@ -75,8 +76,23 @@ void KX_IpoSGController::SetOption(
m_ipo_as_force = (value != 0);
m_modified = true;
break;
- case SG_CONTR_IPO_FORCES_ACT_LOCAL:
- m_force_ipo_acts_local = (value != 0);
+ case SG_CONTR_IPO_IPO_ADD:
+ m_ipo_add = (value != 0);
+ m_modified = true;
+ break;
+ case SG_CONTR_IPO_RESET:
+ if (m_ipo_start_initialized && value) {
+ m_ipo_start_initialized = false;
+ m_modified = true;
+ }
+ break;
+ case SG_CONTR_IPO_LOCAL:
+ if (value/* && ((SG_Node*)m_pObject)->GetSGParent() == NULL*/) {
+ // only accept local Ipo if the object has no parent
+ m_ipo_local = true;
+ } else {
+ m_ipo_local = false;
+ }
m_modified = true;
break;
default:
@@ -129,15 +145,19 @@ bool KX_IpoSGController::Update(double currentTime)
{
if (m_game_object && ob)
{
- m_game_object->GetPhysicsController()->ApplyForce(m_force_ipo_acts_local ?
+ m_game_object->GetPhysicsController()->ApplyForce(m_ipo_local ?
ob->GetWorldOrientation() * m_ipo_xform.GetPosition() :
m_ipo_xform.GetPosition(), false);
}
}
else
{
- //by default, leave object as it stands
- MT_Point3 newPosition = ob->GetLocalPosition();
+ // Local ipo should be defined with the object position at (0,0,0)
+ // Local transform is applied to the object based on initial position
+ MT_Point3 newPosition(0.0,0.0,0.0);
+
+ if (!m_ipo_add)
+ 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
@@ -145,23 +165,28 @@ bool KX_IpoSGController::Update(double currentTime)
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]);
+ newPosition[0] = (((!m_ipo_add)?m_ipo_start_point[0]:0.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]);
+ newPosition[1] = (((!m_ipo_add)?m_ipo_start_point[1]:0.0) + 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]);
+ newPosition[2] = (((!m_ipo_add)?m_ipo_start_point[2]:0.0) + m_ipo_xform.GetDeltaPosition()[2]);
+ }
+ if (m_ipo_add) {
+ if (m_ipo_local)
+ newPosition = m_ipo_start_point + m_ipo_start_scale*(m_ipo_start_orient*newPosition);
+ else
+ newPosition = m_ipo_start_point + newPosition;
}
-
ob->SetLocalPosition(newPosition);
}
}
@@ -170,21 +195,23 @@ bool KX_IpoSGController::Update(double currentTime)
if (m_ipo_as_force) {
if (m_game_object && ob) {
- m_game_object->ApplyTorque(m_force_ipo_acts_local ?
+ m_game_object->ApplyTorque(m_ipo_local ?
ob->GetWorldOrientation() * m_ipo_xform.GetEulerAngles() :
m_ipo_xform.GetEulerAngles(), false);
}
} else {
- double yaw, pitch, roll; //final Euler angles
+ double yaw=0, pitch=0, roll=0; //final Euler angles
double tempYaw=0, tempPitch=0, tempRoll=0; //temp holders
- ob->GetLocalOrientation().getEuler(yaw, pitch, roll);
+ if (!m_ipo_add)
+ 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);
+ if (!m_ipo_add)
+ m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
yaw = tempYaw + m_ipo_xform.GetDeltaEulerAngles()[0];
}
@@ -193,7 +220,8 @@ bool KX_IpoSGController::Update(double currentTime)
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);
+ if (!m_ipo_add)
+ m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
pitch = tempPitch + m_ipo_xform.GetDeltaEulerAngles()[1];
}
@@ -202,23 +230,34 @@ bool KX_IpoSGController::Update(double currentTime)
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);
+ if (!m_ipo_add)
+ m_ipo_start_orient.getEuler(tempYaw, tempPitch, tempRoll);
roll = tempRoll + m_ipo_xform.GetDeltaEulerAngles()[2];
}
-
- ob->SetLocalOrientation(MT_Vector3(yaw, pitch, roll));
+ if (m_ipo_add) {
+ MT_Matrix3x3 rotation(MT_Vector3(yaw, pitch, roll));
+ if (m_ipo_local)
+ rotation = m_ipo_start_orient * rotation;
+ else
+ rotation = rotation * m_ipo_start_orient;
+ ob->SetLocalOrientation(rotation);
+ } else {
+ ob->SetLocalOrientation(MT_Vector3(yaw, pitch, roll));
+ }
}
}
//modifies scale?
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();
+ MT_Vector3 newScale(1.0,1.0,1.0);
+ if (!m_ipo_add)
+ 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]);
+ newScale[0] = (m_ipo_xform.GetDeltaScaling()[0] + ((!m_ipo_add)?m_ipo_start_scale[0]:0.0));
}
//RotY dRotY
@@ -226,7 +265,7 @@ bool KX_IpoSGController::Update(double currentTime)
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]);
+ newScale[1] = (m_ipo_xform.GetDeltaScaling()[1] + ((!m_ipo_add)?m_ipo_start_scale[1]:0.0));
}
//RotZ and dRotZ
@@ -234,7 +273,11 @@ bool KX_IpoSGController::Update(double currentTime)
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]);
+ newScale[2] = (m_ipo_xform.GetDeltaScaling()[2] + ((!m_ipo_add)?m_ipo_start_scale[2]:1.0));
+ }
+
+ if (m_ipo_add) {
+ newScale = m_ipo_start_scale * newScale;
}
ob->SetLocalScale(newScale);
diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.h b/source/gameengine/Ketsji/KX_IPO_SGController.h
index 7b5a151b41c..0bd8980f11c 100644
--- a/source/gameengine/Ketsji/KX_IPO_SGController.h
+++ b/source/gameengine/Ketsji/KX_IPO_SGController.h
@@ -48,8 +48,11 @@ class KX_IpoSGController : public SG_Controller
/** Interpret the ipo as a force rather than a displacement? */
bool m_ipo_as_force;
- /** Ipo-as-force acts in local rather than in global coordinates? */
- bool m_force_ipo_acts_local;
+ /** Add Ipo curve to current loc/rot/scale */
+ bool m_ipo_add;
+
+ /** Ipo must be applied in local coordinate rather than in global coordinates (used for force and Add mode)*/
+ bool m_ipo_local;
/** Were settings altered since the last update? */
bool m_modified;
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp
index cf246342cf9..b7103f49aee 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.cpp
+++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp
@@ -59,40 +59,6 @@ STR_String KX_IpoActuator::S_KX_ACT_IPO_FROM_PROP_STRING = "FromProp";
/* ------------------------------------------------------------------------- */
/* Native functions */
/* ------------------------------------------------------------------------- */
-/** Another poltergeist? This seems to be a very transient class... */
-class CIpoAction : public CAction
-{
- float m_curtime;
- bool m_recurse;
- KX_GameObject* m_gameobj;
- bool m_ipo_as_force;
- bool m_force_ipo_local;
-
-public:
- CIpoAction(KX_GameObject* gameobj,
- float curtime,
- bool recurse,
- bool ipo_as_force,
- bool force_ipo_local) :
- m_curtime(curtime) ,
- m_recurse(recurse),
- m_gameobj(gameobj),
- m_ipo_as_force(ipo_as_force),
- m_force_ipo_local(force_ipo_local)
- {
- /* intentionally empty */
- };
-
- virtual void Execute() const
- {
- m_gameobj->UpdateIPO(
- m_curtime,
- m_recurse,
- m_ipo_as_force,
- m_force_ipo_local);
- };
-
-};
KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj,
const STR_String& propname,
@@ -101,7 +67,8 @@ KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj,
bool recurse,
int acttype,
bool ipo_as_force,
- bool force_ipo_local,
+ bool ipo_add,
+ bool ipo_local,
PyTypeObject* T)
: SCA_IActuator(gameobj,T),
m_bNegativeEvent(false),
@@ -112,7 +79,8 @@ KX_IpoActuator::KX_IpoActuator(SCA_IObject* gameobj,
m_direction(1),
m_propname(propname),
m_ipo_as_force(ipo_as_force),
- m_force_ipo_local(force_ipo_local),
+ m_ipo_add(ipo_add),
+ m_ipo_local(ipo_local),
m_type((IpoActType)acttype)
{
m_starttime = -2.0*fabs(m_endframe - m_startframe) - 1.0;
@@ -160,7 +128,7 @@ bool KX_IpoActuator::ClampLocalTime()
void KX_IpoActuator::SetStartTime(float curtime)
{
- float direction = m_startframe < m_endframe ? 1.0 : -1.0;
+ float direction = m_startframe < m_endframe ? 1.0f : -1.0f;
curtime = curtime - KX_KetsjiEngine::GetSuspendedDelta();
if (m_direction > 0)
@@ -195,31 +163,26 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
// maybe there are events for us in the queue !
bool bNegativeEvent = false;
int numevents = 0;
+ bool bIpoStart = false;
if (frame)
{
numevents = m_events.size();
- for (vector<CValue*>::iterator i=m_events.end(); !(i==m_events.begin());)
- {
- --i;
- if ((*i)->GetNumber() == 0.0f)
- bNegativeEvent = true;
-
- (*i)->Release();
- }
- m_events.clear();
+ bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
}
- double start_smaller_then_end = ( m_startframe < m_endframe ? 1.0 : -1.0);
+ float start_smaller_then_end = ( m_startframe < m_endframe ? 1.0f : -1.0f);
bool result=true;
if (!bNegativeEvent)
{
- if (m_starttime < -2.0*start_smaller_then_end*(m_endframe - m_startframe))
+ if (m_starttime < -2.0f*start_smaller_then_end*(m_endframe - m_startframe))
{
// start for all Ipo, initial start for LOOP_STOP
m_starttime = curtime - KX_KetsjiEngine::GetSuspendedDelta();
m_bIpoPlaying = true;
+ bIpoStart = true;
}
}
@@ -230,7 +193,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
{
// Check if playing forwards. result = ! finished
- if (start_smaller_then_end > 0.0)
+ if (start_smaller_then_end > 0.f)
result = (m_localtime < m_endframe && m_bIpoPlaying);
else
result = (m_localtime > m_endframe && m_bIpoPlaying);
@@ -241,14 +204,10 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
/* Perform clamping */
ClampLocalTime();
-
- CIpoAction ipoaction(
- (KX_GameObject*)GetParent(),
- m_localtime,
- m_recurse,
- m_ipo_as_force,
- m_force_ipo_local);
- GetParent()->Execute(ipoaction);
+
+ if (bIpoStart)
+ ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
+ ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
} else
{
m_localtime=m_startframe;
@@ -270,13 +229,9 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
m_direction = -m_direction;
}
- CIpoAction ipoaction(
- (KX_GameObject*) GetParent(),
- m_localtime,
- m_recurse,
- m_ipo_as_force,
- m_force_ipo_local);
- GetParent()->Execute(ipoaction);
+ if (bIpoStart && m_direction > 0)
+ ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
+ ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
break;
}
case KX_ACT_IPO_FLIPPER:
@@ -299,14 +254,10 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
if (ClampLocalTime() && m_localtime == m_startframe)
result = false;
-
- CIpoAction ipoaction(
- (KX_GameObject*) GetParent(),
- m_localtime,
- m_recurse,
- m_ipo_as_force,
- m_force_ipo_local);
- GetParent()->Execute(ipoaction);
+
+ if (bIpoStart)
+ ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
+ ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
break;
}
@@ -352,8 +303,12 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
if (!m_bNegativeEvent){
/* Perform wraparound */
SetLocalTime(curtime);
- m_localtime = m_startframe + fmod(m_localtime, m_startframe - m_endframe);
+ if (start_smaller_then_end > 0.f)
+ m_localtime = m_startframe + fmod(m_localtime - m_startframe, m_endframe - m_startframe);
+ else
+ m_localtime = m_startframe - fmod(m_startframe - m_localtime, m_startframe - m_endframe);
SetStartTime(curtime);
+ bIpoStart = true;
}
else
{
@@ -365,13 +320,9 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
}
}
- CIpoAction ipoaction(
- (KX_GameObject*) GetParent(),
- m_localtime,
- m_recurse,
- m_ipo_as_force,
- m_force_ipo_local);
- GetParent()->Execute(ipoaction);
+ if (m_bIpoPlaying && bIpoStart)
+ ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
+ ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
break;
}
@@ -391,14 +342,9 @@ bool KX_IpoActuator::Update(double curtime, bool frame)
{
m_localtime = propval->GetNumber();
- CIpoAction ipoaction(
- (KX_GameObject*) GetParent(),
- m_localtime,
- m_recurse,
- m_ipo_as_force,
- m_force_ipo_local);
- GetParent()->Execute(ipoaction);
-
+ if (bIpoStart)
+ ((KX_GameObject*)GetParent())->InitIPO(m_ipo_as_force, m_ipo_add, m_ipo_local);
+ ((KX_GameObject*)GetParent())->UpdateIPO(m_localtime,m_recurse);
} else
{
result = false;
@@ -493,6 +439,10 @@ PyMethodDef KX_IpoActuator::Methods[] = {
METH_VARARGS, SetIpoAsForce_doc},
{"getIpoAsForce", (PyCFunction) KX_IpoActuator::sPyGetIpoAsForce,
METH_VARARGS, GetIpoAsForce_doc},
+ {"setIpoAdd", (PyCFunction) KX_IpoActuator::sPySetIpoAdd,
+ METH_VARARGS, SetIpoAdd_doc},
+ {"getIpoAdd", (PyCFunction) KX_IpoActuator::sPyGetIpoAdd,
+ METH_VARARGS, GetIpoAdd_doc},
{"setType", (PyCFunction) KX_IpoActuator::sPySetType,
METH_VARARGS, SetType_doc},
{"getType", (PyCFunction) KX_IpoActuator::sPyGetType,
@@ -512,11 +462,11 @@ PyObject* KX_IpoActuator::_getattr(const STR_String& attr) {
/* set --------------------------------------------------------------------- */
char KX_IpoActuator::Set_doc[] =
-"set(mode, startframe, endframe, force?)\n"
-"\t - mode: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
+"set(type, startframe, endframe, mode?)\n"
+"\t - type: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n"
"\t - startframe: first frame to use (int)\n"
"\t - endframe : last frame to use (int)\n"
-"\t - force? : interpret this ipo as a force? (KX_TRUE, KX_FALSE)"
+"\t - mode? : special mode (0=normal, 1=interpret location as force, 2=additive)"
"\tSet the properties of the actuator.\n";
PyObject* KX_IpoActuator::PySet(PyObject* self,
PyObject* args,
@@ -543,7 +493,8 @@ PyObject* KX_IpoActuator::PySet(PyObject* self,
m_type = modenum;
m_startframe = startFrame;
m_endframe = stopFrame;
- m_ipo_as_force = PyArgToBool(forceToggle);
+ m_ipo_as_force = forceToggle == 1;
+ m_ipo_add = forceToggle == 2;
break;
default:
; /* error */
@@ -641,6 +592,8 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self,
}
m_ipo_as_force = PyArgToBool(boolArg);
+ if (m_ipo_as_force)
+ m_ipo_add = false;
Py_Return;
}
@@ -654,6 +607,36 @@ PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self,
return BoolToPyArg(m_ipo_as_force);
}
+/* 6. setIpoAsForce: */
+char KX_IpoActuator::SetIpoAdd_doc[] =
+"setIpoAdd(add?)\n"
+"\t - add? : add flag (KX_TRUE, KX_FALSE)\n"
+"\tSet whether to interpret the ipo as additive rather than absolute.\n";
+PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ int boolArg;
+
+ if (!PyArg_ParseTuple(args, "i", &boolArg)) {
+ return NULL;
+ }
+
+ m_ipo_add = PyArgToBool(boolArg);
+ if (m_ipo_add)
+ m_ipo_as_force = false;
+
+ Py_Return;
+}
+/* 7. getIpoAsForce: */
+char KX_IpoActuator::GetIpoAdd_doc[] =
+"getIpoAsAdd()\n"
+"\tReturns whether to interpret the ipo as additive rather than absolute.\n";
+PyObject* KX_IpoActuator::PyGetIpoAdd(PyObject* self,
+ PyObject* args,
+ PyObject* kwds) {
+ return BoolToPyArg(m_ipo_add);
+}
+
/* 8. setType: */
char KX_IpoActuator::SetType_doc[] =
"setType(mode)\n"
@@ -701,7 +684,7 @@ PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self,
return NULL;
}
- m_force_ipo_local = PyArgToBool(boolArg);
+ m_ipo_local = PyArgToBool(boolArg);
Py_Return;
}
@@ -713,7 +696,7 @@ char KX_IpoActuator::GetForceIpoActsLocal_doc[] =
PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self,
PyObject* args,
PyObject* kwds) {
- return BoolToPyArg(m_force_ipo_local);
+ return BoolToPyArg(m_ipo_local);
}
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h
index 79e8daa3f87..ae554fb0fce 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.h
+++ b/source/gameengine/Ketsji/KX_IpoActuator.h
@@ -75,8 +75,11 @@ protected:
/** Interpret the ipo as a force? */
bool m_ipo_as_force;
- /** Apply a force-ipo locally? */
- bool m_force_ipo_local;
+ /** Add Ipo curve to current loc/rot/scale */
+ bool m_ipo_add;
+
+ /** The Ipo curve is applied in local coordinates */
+ bool m_ipo_local;
bool m_bIpoPlaying;
@@ -113,7 +116,8 @@ public:
bool recurse,
int acttype,
bool ipo_as_force,
- bool force_ipo_local,
+ bool ipo_add,
+ bool ipo_local,
PyTypeObject* T=&Type);
virtual ~KX_IpoActuator() {};
@@ -144,6 +148,8 @@ public:
KX_PYMETHOD_DOC(KX_IpoActuator,GetEnd);
KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAsForce);
KX_PYMETHOD_DOC(KX_IpoActuator,GetIpoAsForce);
+ KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAdd);
+ KX_PYMETHOD_DOC(KX_IpoActuator,GetIpoAdd);
KX_PYMETHOD_DOC(KX_IpoActuator,SetType);
KX_PYMETHOD_DOC(KX_IpoActuator,GetType);
KX_PYMETHOD_DOC(KX_IpoActuator,SetForceIpoActsLocal);
diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp
index 5c433cb68b1..8b379bcd44f 100644
--- a/source/gameengine/Ketsji/KX_ParentActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp
@@ -77,6 +77,12 @@ CValue* KX_ParentActuator::GetReplica()
bool KX_ParentActuator::Update()
{
+ bool bNegativeEvent = IsNegativeEvent();
+ RemoveAllEvents();
+
+ if (bNegativeEvent)
+ return false; // do nothing on negative events
+
KX_GameObject *obj = (KX_GameObject*) GetParent();
KX_Scene *scene = PHY_GetActiveScene();
switch (m_mode) {
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index 337b1af6df7..c5f6230b2f2 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -601,6 +601,8 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj)
}
}
}
+ // ready to set initial state
+ newobj->ResetState();
}
diff --git a/source/gameengine/SceneGraph/SG_Controller.h b/source/gameengine/SceneGraph/SG_Controller.h
index d65a2f0c256..c32885b915f 100644
--- a/source/gameengine/SceneGraph/SG_Controller.h
+++ b/source/gameengine/SceneGraph/SG_Controller.h
@@ -101,7 +101,9 @@ public:
enum SG_Controller_option {
SG_CONTR_NODEF = 0,
SG_CONTR_IPO_IPO_AS_FORCE,
- SG_CONTR_IPO_FORCES_ACT_LOCAL,
+ SG_CONTR_IPO_IPO_ADD,
+ SG_CONTR_IPO_LOCAL,
+ SG_CONTR_IPO_RESET,
SG_CONTR_CAMIPO_LENS,
SG_CONTR_CAMIPO_CLIPEND,
SG_CONTR_CAMIPO_CLIPSTART,