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:
Diffstat (limited to 'source/gameengine/Ketsji/KX_GameObject.cpp')
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp556
1 files changed, 365 insertions, 191 deletions
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index bea0fcff2af..7f417b325c8 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -49,6 +49,8 @@ typedef unsigned long uint_ptr;
#include "RAS_IPolygonMaterial.h"
#include "KX_BlenderMaterial.h"
#include "KX_GameObject.h"
+#include "KX_Camera.h" // only for their ::Type
+#include "KX_Light.h" // only for their ::Type
#include "RAS_MeshObject.h"
#include "KX_MeshProxy.h"
#include "KX_PolyProxy.h"
@@ -63,6 +65,7 @@ typedef unsigned long uint_ptr;
#include "KX_RayCast.h"
#include "KX_PythonInit.h"
#include "KX_PyMath.h"
+#include "KX_PythonSeq.h"
#include "SCA_IActuator.h"
#include "SCA_ISensor.h"
#include "SCA_IController.h"
@@ -187,38 +190,23 @@ double KX_GameObject::GetNumber()
-STR_String KX_GameObject::GetName()
+STR_String& KX_GameObject::GetName()
{
return m_name;
}
-void KX_GameObject::SetName(STR_String name)
+void KX_GameObject::SetName(const char *name)
{
m_name = name;
}; // Set the name of the value
-
-
-void KX_GameObject::ReplicaSetName(STR_String name)
-{
-}
-
-
-
-
-
-
KX_IPhysicsController* KX_GameObject::GetPhysicsController()
{
return m_pPhysicsController1;
}
-
-
-
-
KX_GameObject* KX_GameObject::GetParent()
{
KX_GameObject* result = NULL;
@@ -238,7 +226,7 @@ KX_GameObject* KX_GameObject::GetParent()
}
-void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
+void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost)
{
// check on valid node in case a python controller holds a reference to a deleted object
if (obj && GetSGNode() && obj->GetSGNode() && GetSGNode()->GetSGParent() != obj->GetSGNode())
@@ -259,7 +247,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
if (m_pPhysicsController1)
{
- m_pPhysicsController1->SuspendDynamics(true);
+ m_pPhysicsController1->SuspendDynamics(ghost);
}
// Set us to our new scale, position, and orientation
scale2[0] = 1.0/scale2[0];
@@ -280,7 +268,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj)
Release();
// if the new parent is a compound object, add this object shape to the compound shape.
// step 0: verify this object has physical controller
- if (m_pPhysicsController1)
+ if (m_pPhysicsController1 && addToCompound)
{
// step 1: find the top parent (not necessarily obj)
KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject();
@@ -326,33 +314,75 @@ void KX_GameObject::RemoveParent(KX_Scene *scene)
rootobj->m_pPhysicsController1->RemoveCompoundChild(m_pPhysicsController1);
}
m_pPhysicsController1->RestoreDynamics();
+ if (m_pPhysicsController1->IsDyna() && rootobj->m_pPhysicsController1)
+ {
+ // dynamic object should remember the velocity they had while being parented
+ MT_Point3 childPoint = GetSGNode()->GetWorldPosition();
+ MT_Point3 rootPoint = rootobj->GetSGNode()->GetWorldPosition();
+ MT_Point3 relPoint;
+ relPoint = (childPoint-rootPoint);
+ MT_Vector3 linVel = rootobj->m_pPhysicsController1->GetVelocity(relPoint);
+ MT_Vector3 angVel = rootobj->m_pPhysicsController1->GetAngularVelocity();
+ m_pPhysicsController1->SetLinearVelocity(linVel, false);
+ m_pPhysicsController1->SetAngularVelocity(angVel, false);
+ }
}
// graphically, the object hasn't change place, no need to update m_pGraphicController
}
}
-void KX_GameObject::ProcessReplica(KX_GameObject* replica)
+void KX_GameObject::ProcessReplica()
{
- replica->m_pPhysicsController1 = NULL;
- replica->m_pGraphicController = NULL;
- replica->m_pSGNode = NULL;
- replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
- replica->m_pClient_info->m_gameobject = replica;
- replica->m_state = 0;
+ SCA_IObject::ProcessReplica();
+
+ m_pPhysicsController1 = NULL;
+ m_pGraphicController = NULL;
+ m_pSGNode = NULL;
+ m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info);
+ m_pClient_info->m_gameobject = this;
+ m_state = 0;
if(m_attr_dict)
- replica->m_attr_dict= PyDict_Copy(m_attr_dict);
+ m_attr_dict= PyDict_Copy(m_attr_dict);
+
+}
+
+static void setGraphicController_recursive(SG_Node* node)
+{
+ NodeList& children = node->GetSGChildren();
+
+ for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit)
+ {
+ SG_Node* childnode = (*childit);
+ KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject());
+ if (clientgameobj != NULL) // This is a GameObject
+ clientgameobj->ActivateGraphicController(false);
+ // if the childobj is NULL then this may be an inverse parent link
+ // so a non recursive search should still look down this node.
+ setGraphicController_recursive(childnode);
+ }
}
+void KX_GameObject::ActivateGraphicController(bool recurse)
+{
+ if (m_pGraphicController)
+ {
+ m_pGraphicController->Activate(m_bVisible);
+ }
+ if (recurse)
+ {
+ setGraphicController_recursive(GetSGNode());
+ }
+}
+
CValue* KX_GameObject::GetReplica()
{
KX_GameObject* replica = new KX_GameObject(*this);
// this will copy properties and so on...
- CValue::AddDataToReplica(replica);
- ProcessReplica(replica);
+ replica->ProcessReplica();
return replica;
}
@@ -421,6 +451,7 @@ double* KX_GameObject::GetOpenGLMatrix()
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);
+ GetSGNode()->ClearDirty();
}
return fl;
}
@@ -428,8 +459,18 @@ double* KX_GameObject::GetOpenGLMatrix()
void KX_GameObject::AddMeshUser()
{
for (size_t i=0;i<m_meshes.size();i++)
- m_meshes[i]->AddMeshUser(this);
-
+ {
+ m_meshes[i]->AddMeshUser(this, &m_meshSlots, GetDeformer());
+ }
+ // set the part of the mesh slot that never change
+ double* fl = GetOpenGLMatrixPtr()->getPointer();
+
+ SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
+ RAS_MeshSlot* ms;
+ for(mit.begin(); !mit.end(); ++mit)
+ {
+ (*mit)->m_OpenGLMatrix = fl;
+ }
UpdateBuckets(false);
}
@@ -453,10 +494,27 @@ static void UpdateBuckets_recursive(SG_Node* node)
void KX_GameObject::UpdateBuckets( bool recursive )
{
if (GetSGNode()) {
- double* fl = GetOpenGLMatrixPtr()->getPointer();
+ RAS_MeshSlot *ms;
+
+ if (GetSGNode()->IsDirty())
+ GetOpenGLMatrix();
- for (size_t i=0;i<m_meshes.size();i++)
- m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled);
+ SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
+ for(mit.begin(); !mit.end(); ++mit)
+ {
+ ms = *mit;
+ ms->m_bObjectColor = m_bUseObjectColor;
+ ms->m_RGBAcolor = m_objectColor;
+ ms->m_bVisible = m_bVisible;
+ ms->m_bCulled = m_bCulled || !m_bVisible;
+ if (!ms->m_bCulled)
+ ms->m_bucket->ActivateMesh(ms);
+
+ /* split if necessary */
+#ifdef USE_SPLIT
+ ms->Split();
+#endif
+ }
if (recursive) {
UpdateBuckets_recursive(GetSGNode());
@@ -476,11 +534,11 @@ void KX_GameObject::RemoveMeshes()
void KX_GameObject::UpdateTransform()
{
- if (m_pPhysicsController1)
- // only update the transform of static object, dynamic object are handled differently
- // note that for bullet, this does not even update the transform of static object
+ // HACK: saves function call for dynamic object, they are handled differently
+ if (m_pPhysicsController1 && !m_pPhysicsController1->IsDyna())
+ // Note that for Bullet, this does not even update the transform of static object
// but merely sets there collision flag to "kinematic" because the synchronization is
- // done differently during physics simulation
+ // done during physics simulation
m_pPhysicsController1->SetSumoTransform(true);
if (m_pGraphicController)
// update the culling tree
@@ -493,6 +551,20 @@ void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* s
((KX_GameObject*)gameobj)->UpdateTransform();
}
+void KX_GameObject::SynchronizeTransform()
+{
+ // only used for sensor object, do full synchronization as bullet doesn't do it
+ if (m_pPhysicsController1)
+ m_pPhysicsController1->SetTransform();
+ if (m_pGraphicController)
+ m_pGraphicController->SetGraphicTransform();
+}
+
+void KX_GameObject::SynchronizeTransformFunc(SG_IObject* node, void* gameobj, void* scene)
+{
+ ((KX_GameObject*)gameobj)->SynchronizeTransform();
+}
+
void KX_GameObject::SetDebugColor(unsigned int bgra)
{
@@ -613,6 +685,8 @@ KX_GameObject::SetVisible(
{
if (GetSGNode()) {
m_bVisible = v;
+ if (m_pGraphicController)
+ m_pGraphicController->Activate(m_bVisible);
if (recursive)
setVisible_recursive(GetSGNode(), v);
}
@@ -1081,7 +1155,6 @@ CListValue* KX_GameObject::GetChildrenRecursive()
/* ------- python stuff ---------------------------------------------------*/
PyMethodDef KX_GameObject::Methods[] = {
- {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
{"applyForce", (PyCFunction) KX_GameObject::sPyApplyForce, METH_VARARGS},
{"applyTorque", (PyCFunction) KX_GameObject::sPyApplyTorque, METH_VARARGS},
{"applyRotation", (PyCFunction) KX_GameObject::sPyApplyRotation, METH_VARARGS},
@@ -1100,7 +1173,7 @@ PyMethodDef KX_GameObject::Methods[] = {
{"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS},
{"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS},
{"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O},
- {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O},
+ {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS},
{"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS},
{"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS},
{"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS},
@@ -1116,10 +1189,15 @@ PyMethodDef KX_GameObject::Methods[] = {
KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo),
KX_PYMETHODTABLE_O(KX_GameObject, getVectTo),
KX_PYMETHODTABLE(KX_GameObject, sendMessage),
-
+
+ // dict style access for props
+ {"has_key",(PyCFunction) KX_GameObject::sPyhas_key, METH_O},
+ {"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS},
+
// deprecated
{"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS},
{"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O},
+ {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O},
{"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS},
{"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O},
{"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS},
@@ -1147,13 +1225,14 @@ PyAttributeDef KX_GameObject::Attributes[] = {
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("worldOrientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_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),
+ KX_PYATTRIBUTE_RW_FUNCTION("localScale", KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling),
+ KX_PYATTRIBUTE_RO_FUNCTION("worldScale", KX_GameObject, pyattr_get_worldScaling),
+ KX_PYATTRIBUTE_RO_FUNCTION("children", KX_GameObject, pyattr_get_children),
+ KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
+ KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict),
/* Experemental, dont rely on these yet */
KX_PYATTRIBUTE_RO_FUNCTION("sensors", KX_GameObject, pyattr_get_sensors),
@@ -1193,8 +1272,8 @@ PyObject* KX_GameObject::PyReplaceMesh(PyObject* value)
PyObject* KX_GameObject::PyEndObject()
{
-
KX_Scene *scene = KX_GetActiveScene();
+
scene->DelayedRemoveObject(this);
Py_RETURN_NONE;
@@ -1208,21 +1287,6 @@ PyObject* KX_GameObject::PyGetPosition()
return PyObjectFrom(NodeGetWorldPosition());
}
-
-Py_ssize_t KX_GameObject::Map_Len(PyObject* self_v)
-{
- KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
-
- if (self==NULL) /* not sure what to do here */
- return 0;
-
- Py_ssize_t len= self->GetPropertyCount();
- if(self->m_attr_dict)
- len += PyDict_Size(self->m_attr_dict);
- return len;
-}
-
-
PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item)
{
KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v);
@@ -1231,7 +1295,7 @@ PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item)
PyObject* pyconvert;
if (self==NULL) {
- PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG);
+ PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
return NULL;
}
@@ -1265,7 +1329,7 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
PyErr_Clear();
if (self==NULL) {
- PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG);
+ PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG);
return -1;
}
@@ -1281,7 +1345,7 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
if (del==0) {
if(attr_str) PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str);
- else PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key could not be set");
+ else PyErr_SetString(PyExc_KeyError, "del gameOb[key]: KX_GameObject, key could not be deleted");
return -1;
}
else if (self->m_attr_dict) {
@@ -1292,9 +1356,9 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
int set= 0;
/* as CValue */
- if(attr_str)
+ if(attr_str && BGE_PROXY_CHECK_TYPE(val)==0) /* dont allow GameObjects for eg to be assigned to CValue props */
{
- CValue* vallie = self->ConvertPythonToValue(val);
+ CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */
if(vallie)
{
@@ -1345,17 +1409,21 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val)
return 0; /* success */
}
-
+/* Cant set the len otherwise it can evaluate as false */
PyMappingMethods KX_GameObject::Mapping = {
- (lenfunc)KX_GameObject::Map_Len, /*inquiry mp_length */
+ (lenfunc)NULL , /*inquiry mp_length */
(binaryfunc)KX_GameObject::Map_GetItem, /*binaryfunc mp_subscript */
(objobjargproc)KX_GameObject::Map_SetItem, /*objobjargproc mp_ass_subscript */
};
-
PyTypeObject KX_GameObject::Type = {
- PyObject_HEAD_INIT(NULL)
- 0,
+#if (PY_VERSION_HEX >= 0x02060000)
+ PyVarObject_HEAD_INIT(NULL, 0)
+#else
+ /* python 2.5 and below */
+ PyObject_HEAD_INIT( NULL ) /* required py macro */
+ 0, /* ob_size */
+#endif
"KX_GameObject",
sizeof(PyObjectPlus_Proxy),
0,
@@ -1396,8 +1464,10 @@ PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DE
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
KX_GameObject* parent = self->GetParent();
- if (parent)
+ if (parent) {
+ parent->Release(); /* self->GetParent() AddRef's */
return parent->GetProxy();
+ }
Py_RETURN_NONE;
}
@@ -1415,13 +1485,13 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd
MT_Scalar val = PyFloat_AsDouble(value);
if (val < 0.0f) { /* also accounts for non float */
PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above");
- return 1;
+ return PY_SET_ATTR_FAIL;
}
if (spc)
spc->SetMass(val);
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1438,13 +1508,13 @@ int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF
MT_Scalar val = PyFloat_AsDouble(value);
if (val < 0.0f) { /* also accounts for non float */
PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above");
- return 1;
+ return PY_SET_ATTR_FAIL;
}
if (spc)
spc->SetLinVelocityMin(val);
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1461,13 +1531,13 @@ int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF
MT_Scalar val = PyFloat_AsDouble(value);
if (val < 0.0f) { /* also accounts for non float */
PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above");
- return 1;
+ return PY_SET_ATTR_FAIL;
}
if (spc)
spc->SetLinVelocityMax(val);
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
@@ -1483,12 +1553,12 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at
int param = PyObject_IsTrue( value );
if (param == -1) {
PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False");
- return 1;
+ return PY_SET_ATTR_FAIL;
}
self->SetVisible(param, false);
self->UpdateBuckets(false);
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1502,11 +1572,11 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
MT_Point3 pos;
if (!PyVecTo(value, pos))
- return 1;
+ return PY_SET_ATTR_FAIL;
self->NodeSetWorldPosition(pos);
self->NodeUpdateGS(0.f);
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1523,11 +1593,11 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
MT_Point3 pos;
if (!PyVecTo(value, pos))
- return 1;
+ return PY_SET_ATTR_FAIL;
self->NodeSetLocalPosition(pos);
self->NodeUpdateGS(0.f);
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1546,6 +1616,26 @@ PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYAT
return PyObjectFrom(self->NodeGetWorldOrientation());
}
+int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+
+ /* if value is not a sequence PyOrientationTo makes an error */
+ MT_Matrix3x3 rot;
+ if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, "))
+ return PY_SET_ATTR_FAIL;
+
+ if (self->GetSGNode() && self->GetSGNode()->GetSGParent()) {
+ self->NodeSetLocalOrientation(self->GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot);
+ }
+ else {
+ self->NodeSetLocalOrientation(rot);
+ }
+
+ self->NodeUpdateGS(0.f);
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
@@ -1561,12 +1651,12 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT
/* if value is not a sequence PyOrientationTo makes an error */
MT_Matrix3x3 rot;
- if (!PyOrientationTo(value, rot, "gameOb.orientation = sequence: KX_GameObject, "))
- return NULL;
+ if (!PyOrientationTo(value, rot, "gameOb.localOrientation = sequence: KX_GameObject, "))
+ return PY_SET_ATTR_FAIL;
self->NodeSetLocalOrientation(rot);
self->NodeUpdateGS(0.f);
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1589,11 +1679,11 @@ int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DE
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
MT_Vector3 scale;
if (!PyVecTo(value, scale))
- return 1;
+ return PY_SET_ATTR_FAIL;
self->NodeSetLocalScale(scale);
self->NodeUpdateGS(0.f);
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1615,12 +1705,12 @@ int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF
SG_Node* sg_parent= self->GetSGNode()->GetSGParent();
if (val < 0.0f) { /* also accounts for non float */
PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above");
- return 1;
+ return PY_SET_ATTR_FAIL;
}
if (sg_parent && sg_parent->IsSlowParent())
static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val);
}
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1639,16 +1729,16 @@ int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attr
if (state_i == -1 && PyErr_Occurred()) {
PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field");
- return 1;
+ return PY_SET_ATTR_FAIL;
}
state |= state_i;
if ((state & ((1<<30)-1)) == 0) {
PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)");
- return 1;
+ return PY_SET_ATTR_FAIL;
}
self->SetState(state);
- return 0;
+ return PY_SET_ATTR_SUCCESS;
}
PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -1657,10 +1747,10 @@ PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE
PyObject *meshes= PyList_New(self->m_meshes.size());
int i;
- for(i=0; i < self->m_meshes.size(); i++)
+ for(i=0; i < (int)self->m_meshes.size(); i++)
{
KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]);
- PyList_SET_ITEM(meshes, i, meshproxy->GetProxy());
+ PyList_SET_ITEM(meshes, i, meshproxy->NewProxy(true));
}
return meshes;
@@ -1669,69 +1759,40 @@ PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE
/* experemental! */
PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
- SCA_SensorList& sensors= self->GetSensors();
- PyObject* resultlist = PyList_New(sensors.size());
-
- for (unsigned int index=0;index<sensors.size();index++)
- PyList_SET_ITEM(resultlist, index, sensors[index]->GetProxy());
-
- return resultlist;
+ return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS);
}
PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
- KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
- SCA_ControllerList& controllers= self->GetControllers();
- PyObject* resultlist = PyList_New(controllers.size());
-
- for (unsigned int index=0;index<controllers.size();index++)
- PyList_SET_ITEM(resultlist, index, controllers[index]->GetProxy());
-
- return resultlist;
+ return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS);
}
PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
+ return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS);
+}
+
+PyObject* KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
- SCA_ActuatorList& actuators= self->GetActuators();
- PyObject* resultlist = PyList_New(actuators.size());
-
- for (unsigned int index=0;index<actuators.size();index++)
- PyList_SET_ITEM(resultlist, index, actuators[index]->GetProxy());
-
- return resultlist;
+ return self->GetChildren()->NewProxy(true);
}
-/* __dict__ only for the purpose of giving useful dir() results */
-PyObject* KX_GameObject::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+PyObject* KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
+ return self->GetChildrenRecursive()->NewProxy(true);
+}
+
+PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_GameObject* self= static_cast<KX_GameObject*>(self_v);
- PyObject *dict_str = PyString_FromString("__dict__");
- PyObject *dict= py_getattr_dict(self->SCA_IObject::py_getattro(dict_str), Type.tp_dict);
- Py_DECREF(dict_str);
-
- if(dict==NULL)
- return NULL;
-
- /* Not super fast getting as a list then making into dict keys but its only for dir() */
- PyObject *list= self->ConvertKeysToPython();
- if(list)
- {
- int i;
- for(i=0; i<PyList_Size(list); i++)
- PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None);
- }
- else
- PyErr_Clear();
-
- Py_DECREF(list);
- /* Add m_attr_dict if we have it */
- if(self->m_attr_dict)
- PyDict_Update(dict, self->m_attr_dict);
+ if(self->m_attr_dict==NULL)
+ self->m_attr_dict= PyDict_New();
- return dict;
+ Py_INCREF(self->m_attr_dict);
+ return self->m_attr_dict;
}
/* We need these because the macros have a return in them */
@@ -1772,11 +1833,38 @@ PyObject* KX_GameObject::py_getattro(PyObject *attr)
return object;
}
+PyObject* KX_GameObject::py_getattro_dict() {
+ //py_getattro_dict_up(SCA_IObject);
+ PyObject *dict= py_getattr_dict(SCA_IObject::py_getattro_dict(), Type.tp_dict);
+ if(dict==NULL)
+ return NULL;
+
+ /* normally just return this but KX_GameObject has some more items */
+
+
+ /* Not super fast getting as a list then making into dict keys but its only for dir() */
+ PyObject *list= ConvertKeysToPython();
+ if(list)
+ {
+ int i;
+ for(i=0; i<PyList_Size(list); i++)
+ PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None);
+ }
+ else
+ PyErr_Clear();
+
+ Py_DECREF(list);
+
+ /* Add m_attr_dict if we have it */
+ if(m_attr_dict)
+ PyDict_Update(dict, m_attr_dict);
+
+ return dict;
+}
+
int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro method
{
- int ret;
-
- ret= py_setattro__internal(attr, value);
+ int ret= py_setattro__internal(attr, value);
if (ret==PY_SET_ATTR_SUCCESS) {
/* remove attribute in our own dict to avoid double ups */
@@ -1789,7 +1877,7 @@ int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro m
if (ret==PY_SET_ATTR_COERCE_FAIL) {
/* CValue attribute exists, remove CValue and add PyDict value */
- RemoveProperty(STR_String(PyString_AsString(attr)));
+ RemoveProperty(PyString_AsString(attr));
ret= PY_SET_ATTR_MISSING;
}
@@ -1814,16 +1902,18 @@ int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro m
int KX_GameObject::py_delattro(PyObject *attr)
{
+ ShowDeprecationWarning("del ob.attr", "del ob['attr'] for user defined properties");
+
char *attr_str= PyString_AsString(attr);
- if (RemoveProperty(STR_String(attr_str))) // XXX - should call CValues instead but its only 2 lines here
- return 0;
+ if (RemoveProperty(attr_str)) // XXX - should call CValues instead but its only 2 lines here
+ return PY_SET_ATTR_SUCCESS;
if (m_attr_dict && (PyDict_DelItem(m_attr_dict, attr) == 0))
- return 0;
+ return PY_SET_ATTR_SUCCESS;
PyErr_Format(PyExc_AttributeError, "del gameOb.myAttr: KX_GameObject, attribute \"%s\" dosnt exist", attr_str);
- return 1;
+ return PY_SET_ATTR_MISSING;
}
@@ -2008,14 +2098,8 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* args)
MT_Point3 point(0.0,0.0,0.0);
PyObject* pypos = NULL;
- if (PyArg_ParseTuple(args, "|O:getVelocity", &pypos))
- {
- if (pypos)
- PyVecTo(pypos, point);
- }
- else {
+ if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point)))
return NULL;
- }
if (m_pPhysicsController1)
{
@@ -2075,35 +2159,49 @@ PyObject* KX_GameObject::PyGetParent()
{
ShowDeprecationWarning("getParent()", "the parent property");
KX_GameObject* parent = this->GetParent();
- if (parent)
+ if (parent) {
+ parent->Release(); /* self->GetParent() AddRef's */
return parent->GetProxy();
+ }
Py_RETURN_NONE;
}
-PyObject* KX_GameObject::PySetParent(PyObject* value)
+PyObject* KX_GameObject::PySetParent(PyObject* args)
{
+ KX_Scene *scene = KX_GetActiveScene();
+ PyObject* pyobj;
KX_GameObject *obj;
- if (!ConvertPythonToGameObject(value, &obj, false, "gameOb.setParent(value): KX_GameObject"))
- return NULL;
+ int addToCompound=1, ghost=1;
- this->SetParent(KX_GetActiveScene(), obj);
+ if (!PyArg_ParseTuple(args,"O|ii:setParent", &pyobj, &addToCompound, &ghost)) {
+ return NULL; // Python sets a simple error
+ }
+ if (!ConvertPythonToGameObject(pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject"))
+ return NULL;
+ if (obj)
+ this->SetParent(scene, obj, addToCompound, ghost);
Py_RETURN_NONE;
}
PyObject* KX_GameObject::PyRemoveParent()
{
KX_Scene *scene = KX_GetActiveScene();
+
this->RemoveParent(scene);
Py_RETURN_NONE;
}
PyObject* KX_GameObject::PyGetChildren()
{
+ ShowDeprecationWarning("getChildren()", "the children property");
+
return GetChildren()->NewProxy(true);
}
PyObject* KX_GameObject::PyGetChildrenRecursive()
{
+ ShowDeprecationWarning("getChildrenRecursive()", "the childrenRecursive property");
+
return GetChildrenRecursive()->NewProxy(true);
}
@@ -2203,23 +2301,15 @@ PyObject* KX_GameObject::PyGetOrientation() //keywords
PyObject* KX_GameObject::PySetOrientation(PyObject* value)
{
ShowDeprecationWarning("setOrientation()", "the orientation property");
- MT_Matrix3x3 matrix;
- if (PyObject_IsMT_Matrix(value, 3) && PyMatTo(value, matrix))
- {
- NodeSetLocalOrientation(matrix);
- NodeUpdateGS(0.f);
- Py_RETURN_NONE;
- }
+ MT_Matrix3x3 rot;
+
+ /* if value is not a sequence PyOrientationTo makes an error */
+ if (!PyOrientationTo(value, rot, "gameOb.setOrientation(sequence): KX_GameObject, "))
+ return NULL;
- MT_Quaternion quat;
- if (PyVecTo(value, quat))
- {
- matrix.setRotation(quat);
- NodeSetLocalOrientation(matrix);
- NodeUpdateGS(0.f);
- Py_RETURN_NONE;
- }
- return NULL;
+ NodeSetLocalOrientation(rot);
+ NodeUpdateGS(0.f);
+ Py_RETURN_NONE;
}
PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args)
@@ -2256,7 +2346,7 @@ PyObject* KX_GameObject::PyGetAxisVect(PyObject* value)
PyObject* KX_GameObject::PySetPosition(PyObject* value)
{
- ShowDeprecationWarning("setPosition()", "the position property");
+ ShowDeprecationWarning("setPosition()", "the localPosition property");
MT_Point3 pos;
if (PyVecTo(value, pos))
{
@@ -2270,6 +2360,7 @@ PyObject* KX_GameObject::PySetPosition(PyObject* value)
PyObject* KX_GameObject::PySetWorldPosition(PyObject* value)
{
+ ShowDeprecationWarning("setWorldPosition()", "the worldPosition property");
MT_Point3 pos;
if (PyVecTo(value, pos))
{
@@ -2474,6 +2565,34 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo,
Py_RETURN_NONE;
}
+/* faster then Py_BuildValue since some scripts call raycast a lot */
+static PyObject *none_tuple_3()
+{
+ PyObject *ret= PyTuple_New(3);
+ PyTuple_SET_ITEM(ret, 0, Py_None);
+ PyTuple_SET_ITEM(ret, 1, Py_None);
+ PyTuple_SET_ITEM(ret, 2, Py_None);
+
+ Py_INCREF(Py_None);
+ Py_INCREF(Py_None);
+ Py_INCREF(Py_None);
+ return ret;
+}
+static PyObject *none_tuple_4()
+{
+ PyObject *ret= PyTuple_New(4);
+ PyTuple_SET_ITEM(ret, 0, Py_None);
+ PyTuple_SET_ITEM(ret, 1, Py_None);
+ PyTuple_SET_ITEM(ret, 2, Py_None);
+ PyTuple_SET_ITEM(ret, 3, Py_None);
+
+ Py_INCREF(Py_None);
+ Py_INCREF(Py_None);
+ Py_INCREF(Py_None);
+ Py_INCREF(Py_None);
+ return ret;
+}
+
KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
"rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) of contact point with object within dist that matches prop.\n"
" If no hit, return (None,None,None) or (None,None,None,None).\n"
@@ -2541,12 +2660,14 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
if (dist != 0.0f) {
MT_Vector3 toDir = toPoint-fromPoint;
if (MT_fuzzyZero(toDir.length2())) {
- return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
+ //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
+ return none_tuple_3();
}
toDir.normalize();
toPoint = fromPoint + (dist) * toDir;
} else if (MT_fuzzyZero((toPoint-fromPoint).length2())) {
- return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
+ //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
+ return none_tuple_3();
}
PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment();
@@ -2594,9 +2715,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast,
}
// no hit
if (poly)
- return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None);
+ //return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None);
+ return none_tuple_4();
else
- return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
+ //return Py_BuildValue("OOO", Py_None, Py_None, Py_None);
+ return none_tuple_3();
}
KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage,
@@ -2606,6 +2729,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage,
"body = Message body (string)"
"to = Name of object to send the message to")
{
+ KX_Scene *scene = KX_GetActiveScene();
char* subject;
char* body = (char *)"";
char* to = (char *)"";
@@ -2613,12 +2737,58 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage,
if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to))
return NULL;
+
+ scene->GetNetworkScene()->SendMessage(to, from, subject, body);
+ Py_RETURN_NONE;
+}
- KX_GetActiveScene()->GetNetworkScene()->SendMessage(to, from, subject, body);
+/* dict style access */
- Py_RETURN_NONE;
+
+/* Matches python dict.get(key, [default]) */
+PyObject* KX_GameObject::Pyget(PyObject *args)
+{
+ PyObject *key;
+ PyObject* def = Py_None;
+ PyObject* ret;
+
+ if (!PyArg_ParseTuple(args, "O|O:get", &key, &def))
+ return NULL;
+
+
+ if(PyString_Check(key)) {
+ CValue *item = GetProperty(PyString_AsString(key));
+ if (item) {
+ ret = item->ConvertValueToPython();
+ if(ret)
+ return ret;
+ else
+ return item->GetProxy();
+ }
+ }
+
+ if (m_attr_dict && (ret=PyDict_GetItem(m_attr_dict, key))) {
+ Py_INCREF(ret);
+ return ret;
+ }
+
+ Py_INCREF(def);
+ return def;
+}
+
+/* Matches python dict.has_key() */
+PyObject* KX_GameObject::Pyhas_key(PyObject* value)
+{
+ if(PyString_Check(value) && GetProperty(PyString_AsString(value)))
+ Py_RETURN_TRUE;
+
+ if (m_attr_dict && PyDict_GetItem(m_attr_dict, value))
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
}
+
/* ---------------------------------------------------------------------
* Some stuff taken from the header
* --------------------------------------------------------------------- */
@@ -2641,6 +2811,7 @@ void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter)
}
}
+
bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix)
{
if (value==NULL) {
@@ -2671,12 +2842,15 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py
}
}
- if (PyObject_TypeCheck(value, &KX_GameObject::Type)) {
+ if ( PyObject_TypeCheck(value, &KX_GameObject::Type) ||
+ PyObject_TypeCheck(value, &KX_LightObject::Type) ||
+ PyObject_TypeCheck(value, &KX_Camera::Type) )
+ {
*object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
/* sets the error */
if (*object==NULL) {
- PyErr_Format(PyExc_RuntimeError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
+ PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix);
return false;
}