BGE bug #18168: Get local orientation of object using game engine python script syste...
authorBenoit Bolsee <benoit.bolsee@online.be>
Wed, 15 Apr 2009 21:17:08 +0000 (21:17 +0000)
committerBenoit Bolsee <benoit.bolsee@online.be>
Wed, 15 Apr 2009 21:17:08 +0000 (21:17 +0000)
source/gameengine/Ketsji/KX_GameObject.cpp
source/gameengine/Ketsji/KX_GameObject.h
source/gameengine/PyDoc/KX_GameObject.py

index 36fb9142adc875100233fd8596e253ce7fa71be7..283b78c294784d68d565ba497454e9b566368439 100644 (file)
@@ -76,6 +76,10 @@ typedef unsigned long uint_ptr;
 #include "KX_SG_NodeRelationships.h"
 
 static MT_Point3 dummy_point= MT_Point3(0.0, 0.0, 0.0);
+static MT_Vector3 dummy_scaling = MT_Vector3(1.0, 1.0, 1.0);
+static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(  1.0, 0.0, 0.0,
+                                                                                                               0.0, 1.0, 0.0,
+                                                                                                               0.0, 0.0, 1.0);
 
 KX_GameObject::KX_GameObject(
        void* sgReplicationInfo,
@@ -373,11 +377,14 @@ void KX_GameObject::ApplyTorque(const MT_Vector3& torque,bool local)
 
 void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
 {
-       if (m_pPhysicsController1) // (IsDynamic())
+       if (GetSGNode()) 
        {
-               m_pPhysicsController1->RelativeTranslate(dloc,local);
+               if (m_pPhysicsController1) // (IsDynamic())
+               {
+                       m_pPhysicsController1->RelativeTranslate(dloc,local);
+               }
+               GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
        }
-       GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local);
 }
 
 
@@ -385,11 +392,13 @@ void KX_GameObject::ApplyMovement(const MT_Vector3& dloc,bool local)
 void KX_GameObject::ApplyRotation(const MT_Vector3& drot,bool local)
 {
        MT_Matrix3x3 rotmat(drot);
+       
+       if (GetSGNode()) {
+               GetSGNode()->RelativeRotate(rotmat,local);
 
-       GetSGNode()->RelativeRotate(rotmat,local);
-
-       if (m_pPhysicsController1) { // (IsDynamic())
-               m_pPhysicsController1->RelativeRotate(rotmat,local); 
+               if (m_pPhysicsController1) { // (IsDynamic())
+                       m_pPhysicsController1->RelativeRotate(rotmat,local); 
+               }
        }
 }
 
@@ -402,16 +411,17 @@ double*   KX_GameObject::GetOpenGLMatrix()
 {
        // todo: optimize and only update if necessary
        double* fl = m_OpenGL_4x4Matrix.getPointer();
-       MT_Transform trans;
+       if (GetSGNode()) {
+               MT_Transform trans;
        
-       trans.setOrigin(GetSGNode()->GetWorldPosition());
-       trans.setBasis(GetSGNode()->GetWorldOrientation());
+               trans.setOrigin(GetSGNode()->GetWorldPosition());
+               trans.setBasis(GetSGNode()->GetWorldOrientation());
        
-       MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
-       m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
-       trans.scale(scaling[0], scaling[1], scaling[2]);
-       trans.getValue(fl);
-
+               MT_Vector3 scaling = GetSGNode()->GetWorldScaling();
+               m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false;
+               trans.scale(scaling[0], scaling[1], scaling[2]);
+               trans.getValue(fl);
+       }
        return fl;
 }
 
@@ -442,13 +452,15 @@ static void UpdateBuckets_recursive(SG_Node* node)
 
 void KX_GameObject::UpdateBuckets( bool recursive )
 {
-       double* fl = GetOpenGLMatrixPtr()->getPointer();
+       if (GetSGNode()) {
+               double* fl = GetOpenGLMatrixPtr()->getPointer();
 
-       for (size_t i=0;i<m_meshes.size();i++)
-               m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled);
+               for (size_t i=0;i<m_meshes.size();i++)
+                       m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled);
        
-       if (recursive) {
-               UpdateBuckets_recursive(m_pSGNode);
+               if (recursive) {
+                       UpdateBuckets_recursive(GetSGNode());
+               }
        }
 }
 
@@ -599,9 +611,11 @@ KX_GameObject::SetVisible(
        bool recursive
        )
 {
-       m_bVisible = v;
-       if (recursive)
-               setVisible_recursive(m_pSGNode, v);
+       if (GetSGNode()) {
+               m_bVisible = v;
+               if (recursive)
+                       setVisible_recursive(GetSGNode(), v);
+       }
 }
 
 static void setOccluder_recursive(SG_Node* node, bool v)
@@ -627,9 +641,11 @@ KX_GameObject::SetOccluder(
        bool recursive
        )
 {
-       m_bOccluder = v;
-       if (recursive)
-               setOccluder_recursive(m_pSGNode, v);
+       if (GetSGNode()) {
+               m_bOccluder = v;
+               if (recursive)
+                       setOccluder_recursive(GetSGNode(), v);
+       }
 }
 
 void
@@ -929,7 +945,9 @@ void KX_GameObject::NodeSetRelativeScale(const MT_Vector3& scale)
 
 void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans)
 {
-       SG_Node* parent = m_pSGNode->GetSGParent();
+       if (!GetSGNode())
+               return;
+       SG_Node* parent = GetSGNode()->GetSGParent();
        if (parent != NULL)
        {
                // Make sure the objects have some scale
@@ -964,13 +982,9 @@ void KX_GameObject::NodeUpdateGS(double time)
 
 const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
 {
-       static MT_Matrix3x3 defaultOrientation = MT_Matrix3x3(  1.0, 0.0, 0.0,
-                                                                                                                       0.0, 1.0, 0.0,
-                                                                                                                       0.0, 0.0, 1.0);
-
        // check on valid node in case a python controller holds a reference to a deleted object
        if (!GetSGNode())
-               return defaultOrientation;
+               return dummy_orientation;
        return GetSGNode()->GetWorldOrientation();
 }
 
@@ -978,11 +992,9 @@ const MT_Matrix3x3& KX_GameObject::NodeGetWorldOrientation() const
 
 const MT_Vector3& KX_GameObject::NodeGetWorldScaling() const
 {
-       static MT_Vector3 defaultScaling = MT_Vector3(1.0, 1.0, 1.0);
-
        // check on valid node in case a python controller holds a reference to a deleted object
        if (!GetSGNode())
-               return defaultScaling;
+               return dummy_scaling;
 
        return GetSGNode()->GetWorldScaling();
 }
@@ -1091,13 +1103,19 @@ PyAttributeDef KX_GameObject::Attributes[] = {
        KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax",            KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max),
        KX_PYATTRIBUTE_RW_FUNCTION("visible",   KX_GameObject, pyattr_get_visible,      pyattr_set_visible),
        KX_PYATTRIBUTE_BOOL_RW    ("occlusion", KX_GameObject, m_bOccluder),
-       KX_PYATTRIBUTE_RW_FUNCTION("position",  KX_GameObject, pyattr_get_position,     pyattr_set_position),
+       KX_PYATTRIBUTE_RW_FUNCTION("position",  KX_GameObject, pyattr_get_worldPosition,        pyattr_set_localPosition),
        KX_PYATTRIBUTE_RO_FUNCTION("localInertia",      KX_GameObject, pyattr_get_localInertia),
-       KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_orientation,pyattr_set_orientation),
-       KX_PYATTRIBUTE_RW_FUNCTION("scaling",   KX_GameObject, pyattr_get_scaling,      pyattr_set_scaling),
+       KX_PYATTRIBUTE_RW_FUNCTION("orientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_localOrientation),
+       KX_PYATTRIBUTE_RW_FUNCTION("scaling",   KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling),
        KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset),
        KX_PYATTRIBUTE_RW_FUNCTION("state",             KX_GameObject, pyattr_get_state,        pyattr_set_state),
        KX_PYATTRIBUTE_RO_FUNCTION("meshes",    KX_GameObject, pyattr_get_meshes),
+       KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation),
+       KX_PYATTRIBUTE_RO_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation),
+       KX_PYATTRIBUTE_RW_FUNCTION("localPosition",     KX_GameObject, pyattr_get_localPosition,        pyattr_set_localPosition),
+       KX_PYATTRIBUTE_RW_FUNCTION("worldPosition",     KX_GameObject, pyattr_get_worldPosition,    pyattr_set_worldPosition),
+       KX_PYATTRIBUTE_RW_FUNCTION("localScaling",      KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling),
+       KX_PYATTRIBUTE_RO_FUNCTION("worldScaling",      KX_GameObject, pyattr_get_worldScaling),
        
        KX_PYATTRIBUTE_RO_FUNCTION("__dict__",  KX_GameObject, pyattr_get_dir_dict),
        
@@ -1448,13 +1466,34 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at
        return 0;
 }
 
-PyObject* KX_GameObject::pyattr_get_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        return PyObjectFrom(self->NodeGetWorldPosition());
 }
 
-int KX_GameObject::pyattr_set_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       MT_Point3 pos;
+       if (!PyVecTo(value, pos))
+               return 1;
+       
+       self->NodeSetWorldPosition(pos);
+       self->NodeUpdateGS(0.f);
+       return 0;
+}
+
+PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       if (self->GetSGNode())
+               return PyObjectFrom(self->GetSGNode()->GetLocalPosition());
+       else
+               return PyObjectFrom(dummy_point);
+}
+
+int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        MT_Point3 pos;
@@ -1476,13 +1515,22 @@ PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIB
        return Py_BuildValue("fff", 0.0f, 0.0f, 0.0f);
 }
 
-PyObject* KX_GameObject::pyattr_get_orientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        return PyObjectFrom(self->NodeGetWorldOrientation());
 }
 
-int KX_GameObject::pyattr_set_orientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       if (self->GetSGNode())
+               return PyObjectFrom(self->GetSGNode()->GetLocalOrientation());
+       else
+               return PyObjectFrom(dummy_orientation);
+}
+
+int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        if (!PySequence_Check(value)) {
@@ -1530,13 +1578,22 @@ int KX_GameObject::pyattr_set_orientation(void *self_v, const KX_PYATTRIBUTE_DEF
        return 1;
 }
 
-PyObject* KX_GameObject::pyattr_get_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        return PyObjectFrom(self->NodeGetWorldScaling());
 }
 
-int KX_GameObject::pyattr_set_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+PyObject* KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+       KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+       if (self->GetSGNode())
+               return PyObjectFrom(self->GetSGNode()->GetLocalScale());
+       else
+               return PyObjectFrom(dummy_scaling);
+}
+
+int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
        MT_Vector3 scale;
@@ -1551,8 +1608,8 @@ int KX_GameObject::pyattr_set_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *at
 PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-       SG_Node* sg_parent= self->GetSGNode()->GetSGParent(); /* GetSGNode() is valid or exception would be raised */
-       if (sg_parent && sg_parent->IsSlowParent()) {
+       SG_Node* sg_parent;
+       if (self->GetSGNode() && (sg_parent = self->GetSGNode()->GetSGParent()) != NULL && sg_parent->IsSlowParent()) {
                return PyFloat_FromDouble(static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->GetTimeOffset());
        } else {
                return PyFloat_FromDouble(0.0);
@@ -1562,16 +1619,16 @@ PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUT
 int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
 {
        KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
-       MT_Scalar val = PyFloat_AsDouble(value);
-       SG_Node* sg_parent= self->GetSGNode()->GetSGParent(); /* GetSGNode() is valid or exception would be raised */
-       if (val < 0.0f) { /* also accounts for non float */
-               PyErr_SetString(PyExc_AttributeError, "expected a float zero or above");
-               return 1;
+       if (self->GetSGNode()) {
+               MT_Scalar val = PyFloat_AsDouble(value);
+               SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
+               if (val < 0.0f) { /* also accounts for non float */
+                       PyErr_SetString(PyExc_AttributeError, "expected a float zero or above");
+                       return 1;
+               }
+               if (sg_parent && sg_parent->IsSlowParent())
+                       static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
        }
-
-       if (sg_parent && sg_parent->IsSlowParent())
-               static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
-
        return 0;
 }
 
@@ -2092,6 +2149,8 @@ PyObject* KX_GameObject::PyRemoveParent(PyObject* self)
 
 static void walk_children(SG_Node* node, CListValue* list, bool recursive)
 {
+       if (!node)
+               return;
        NodeList& children = node->GetSGChildren();
 
        for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
@@ -2122,7 +2181,7 @@ PyObject* KX_GameObject::PyGetChildren(PyObject* self)
 PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self)
 {
        CListValue* list = new CListValue();
-       walk_children(m_pSGNode, list, 1);
+       walk_children(GetSGNode(), list, 1);
        return list;
 }
 
index 0bf3e60f34b1af9f877d396d4af170c2839c4b09..cf0c0e6b0f58051f051bad69e8d5977316843b67 100644 (file)
@@ -880,14 +880,18 @@ public:
        static int                      pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
        static PyObject*        pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
        static int                      pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-       static PyObject*        pyattr_get_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
-       static int                      pyattr_set_position(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+       static PyObject*        pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static int                      pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+       static PyObject*        pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static int                      pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
        static PyObject*        pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
        static int                      pyattr_set_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-       static PyObject*        pyattr_get_orientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
-       static int                      pyattr_set_orientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-       static PyObject*        pyattr_get_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
-       static int                      pyattr_set_scaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+       static PyObject*        pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static PyObject*        pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static int                      pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+       static PyObject*        pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static PyObject*        pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+       static int                      pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
        static PyObject*        pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
        static int                      pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
        static PyObject*        pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
index 4aa9de2fe86e5e9f9720568c26595f0e244ce0e4..21ddf439924364dd28a2e0340ee6b14ce16d81cf 100644 (file)
@@ -39,11 +39,26 @@ class KX_GameObject: # (SCA_IObject)
        @ivar occlusion: occlusion capability flag.
        @type occlusion: boolean
        @ivar position: The object's position. 
-       @type position: list [x, y, z]
+                       DEPRECATED: use localPosition and worldPosition
+       @type position: list [x, y, z] On write: local position, on read: world position
        @ivar orientation: The object's orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector.
-       @type orientation: 3x3 Matrix [[float]]
+                          DEPRECATED: use localOrientation and worldOrientation
+       @type orientation: 3x3 Matrix [[float]] On write: local orientation, on read: world orientation
        @ivar scaling: The object's scaling factor. list [sx, sy, sz]
-       @type scaling: list [sx, sy, sz]
+                      DEPRECATED: use localScaling and worldScaling
+       @type scaling: list [sx, sy, sz] On write: local scaling, on read: world scaling
+       @ivar localOrientation: The object's local orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector.
+       @type localOrientation: 3x3 Matrix [[float]]
+       @ivar worldOrientation: The object's world orientation. Read-only.
+       @type worldOrientation: 3x3 Matrix [[float]]
+       @ivar localScaling: The object's local scaling factor.
+       @type localScaling: list [sx, sy, sz]
+       @ivar worldScaling: The object's world scaling factor. Read-only
+       @type worldScaling: list [sx, sy, sz]
+       @ivar localPosition: The object's local position. 
+       @type localPosition: list [x, y, z]
+       @ivar worldPosition: The object's world position. 
+       @type worldPosition: list [x, y, z]
        @ivar timeOffset: adjust the slowparent delay at runtime.
        @type timeOffset: float
        @ivar state: the game object's state bitmask, using the first 30 bits, one bit must always be set.