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:
authorBenoit Bolsee <benoit.bolsee@online.be>2008-04-06 22:30:52 +0400
committerBenoit Bolsee <benoit.bolsee@online.be>2008-04-06 22:30:52 +0400
commite7384c9dd2d93e3814e8df51eea64f1dc687c338 (patch)
tree44fb5c808bb3af0783c675886e029e9e4bdb1a21 /source/gameengine/Ketsji/KX_GameObject.cpp
parent711306c2ba1c4ea0d0027087ce53746cde4be0ed (diff)
Commit patch #8799: Realtime SetParent function in the BGE
This patch consists in new KX_GameObject::SetParent() and KX_GameObject::RemoveParent() functions to create and destroy parent relation during game. These functions are accessible through python and through a new actuator KX_ParentActuator. Function documentation in PyDoc. The object keeps its orientation, position and scale when it is parented but will further rotate, move and scale with its parent from that point on. When the parent relation is broken, the object keeps the orientation, position and scale it had at that time. The function has no effect if any of the X/Y/Z scale of the object or its new parent are below Epsilon.
Diffstat (limited to 'source/gameengine/Ketsji/KX_GameObject.cpp')
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp94
1 files changed, 92 insertions, 2 deletions
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index 6f172a11005..7ffac9a82f1 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -62,7 +62,7 @@ typedef unsigned long uint_ptr;
#include "KX_ClientObjectInfo.h"
#include "RAS_BucketManager.h"
#include "KX_RayCast.h"
-
+#include "KX_PythonInit.h"
#include "KX_PyMath.h"
// This file defines relationships between parents and children
@@ -88,7 +88,7 @@ KX_GameObject::KX_GameObject(
m_ignore_activity_culling = false;
m_pClient_info = new KX_ClientObjectInfo(this, KX_ClientObjectInfo::ACTOR);
m_pSGNode = new SG_Node(this,sgReplicationInfo,callbacks);
-
+
// define the relationship between this node and it's parent.
KX_NormalParentRelation * parent_relation =
@@ -204,7 +204,62 @@ KX_GameObject* KX_GameObject::GetParent()
}
+void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
+{
+ if (obj && GetSGNode()->GetSGParent() != obj->GetSGNode())
+ {
+ // Make sure the objects have some scale
+ MT_Vector3 scale1 = NodeGetWorldScaling();
+ MT_Vector3 scale2 = obj->NodeGetWorldScaling();
+ if (fabs(scale2[0]) < FLT_EPSILON ||
+ fabs(scale2[1]) < FLT_EPSILON ||
+ fabs(scale2[2]) < FLT_EPSILON ||
+ fabs(scale1[0]) < FLT_EPSILON ||
+ fabs(scale1[1]) < FLT_EPSILON ||
+ fabs(scale1[2]) < FLT_EPSILON) { return; }
+
+ // Remove us from our old parent and set our new parent
+ RemoveParent(scene);
+ obj->GetSGNode()->AddChild(GetSGNode());
+
+ // Set us to our new scale, position, and orientation
+ scale1[0] = scale1[0]/scale2[0];
+ scale1[1] = scale1[1]/scale2[1];
+ scale1[2] = scale1[2]/scale2[2];
+ MT_Matrix3x3 invori = obj->NodeGetWorldOrientation().inverse();
+ MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale1;
+
+ NodeSetLocalScale(scale1);
+ NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2]));
+ NodeSetLocalOrientation(NodeGetWorldOrientation()*invori);
+ NodeUpdateGS(0.f,true);
+ // object will now be a child, it must be removed from the parent list
+ CListValue* rootlist = scene->GetRootParentList();
+ if (rootlist->RemoveValue(this))
+ // the object was in parent list, decrement ref count as it's now removed
+ Release();
+ }
+}
+
+void KX_GameObject::RemoveParent(KX_Scene *scene)
+{
+ if (GetSGNode()->GetSGParent())
+ {
+ // Set us to the right spot
+ GetSGNode()->SetLocalScale(GetSGNode()->GetWorldScaling());
+ GetSGNode()->SetLocalOrientation(GetSGNode()->GetWorldOrientation());
+ GetSGNode()->SetLocalPosition(GetSGNode()->GetWorldPosition());
+ // Remove us from our parent
+ GetSGNode()->DisconnectFromParent();
+ NodeUpdateGS(0.f,true);
+ // the object is now a root object, add it to the parentlist
+ CListValue* rootlist = scene->GetRootParentList();
+ if (!rootlist->SearchValue(this))
+ // object was not in root list, add it now and increment ref count
+ rootlist->Add(AddRef());
+ }
+}
void KX_GameObject::ProcessReplica(KX_GameObject* replica)
{
@@ -657,6 +712,8 @@ PyMethodDef KX_GameObject::Methods[] = {
{"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_VARARGS},
{"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_VARARGS},
{"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_VARARGS},
+ {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS},
+ {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_VARARGS},
{"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS},
{"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_VARARGS},
KX_PYMETHODTABLE(KX_GameObject, getDistanceTo),
@@ -797,6 +854,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr
if (PyMatTo(value, rot))
{
NodeSetLocalOrientation(rot);
+ NodeUpdateGS(0.f,true);
return 0;
}
return 1;
@@ -809,6 +867,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr
{
rot.setRotation(qrot);
NodeSetLocalOrientation(rot);
+ NodeUpdateGS(0.f,true);
return 0;
}
return 1;
@@ -821,6 +880,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr
{
rot.setEuler(erot);
NodeSetLocalOrientation(rot);
+ NodeUpdateGS(0.f,true);
return 0;
}
return 1;
@@ -835,6 +895,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr
if (PyVecTo(value, pos))
{
NodeSetLocalPosition(pos);
+ NodeUpdateGS(0.f,true);
return 0;
}
return 1;
@@ -846,6 +907,7 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr
if (PyVecTo(value, scale))
{
NodeSetLocalScale(scale);
+ NodeUpdateGS(0.f,true);
return 0;
}
return 1;
@@ -861,6 +923,8 @@ int KX_GameObject::_setattr(const STR_String& attr, PyObject *value) // _setattr
}
}
+ /* Need to have parent settable here too */
+
return SCA_IObject::_setattr(attr, value);
}
@@ -985,7 +1049,31 @@ PyObject* KX_GameObject::PyGetParent(PyObject* self,
Py_Return;
}
+PyObject* KX_GameObject::PySetParent(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ PyObject* gameobj;
+ if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj))
+ {
+ // The object we want to set as parent
+ CValue *m_ob = (CValue*)gameobj;
+ KX_GameObject *obj = ((KX_GameObject*)m_ob);
+ KX_Scene *scene = PHY_GetActiveScene();
+
+ this->SetParent(scene, obj);
+ }
+ Py_Return;
+}
+PyObject* KX_GameObject::PyRemoveParent(PyObject* self,
+ PyObject* args,
+ PyObject* kwds)
+{
+ KX_Scene *scene = PHY_GetActiveScene();
+ this->RemoveParent(scene);
+ Py_Return;
+}
PyObject* KX_GameObject::PyGetMesh(PyObject* self,
PyObject* args,
@@ -1116,6 +1204,7 @@ PyObject* KX_GameObject::PySetOrientation(PyObject* self,
if (PyObject_IsMT_Matrix(pylist, 3) && PyMatTo(pylist, matrix))
{
NodeSetLocalOrientation(matrix);
+ NodeUpdateGS(0.f,true);
Py_Return;
}
@@ -1124,6 +1213,7 @@ PyObject* KX_GameObject::PySetOrientation(PyObject* self,
{
matrix.setRotation(quat);
NodeSetLocalOrientation(matrix);
+ NodeUpdateGS(0.f,true);
Py_Return;
}
}