Changeset View
Changeset View
Standalone View
Standalone View
source/gameengine/Ketsji/KX_GameObject.cpp
| Context not available. | |||||
| # pragma warning( disable:4786 ) | # pragma warning( disable:4786 ) | ||||
| #endif | #endif | ||||
| #include "RAS_IPolygonMaterial.h" | |||||
| #include "KX_BlenderMaterial.h" | |||||
| #include "KX_GameObject.h" | #include "KX_GameObject.h" | ||||
| #include "KX_PythonComponent.h" | |||||
| #include "KX_Camera.h" // only for their ::Type | #include "KX_Camera.h" // only for their ::Type | ||||
| #include "KX_Light.h" // only for their ::Type | #include "KX_Light.h" // only for their ::Type | ||||
| #include "KX_FontObject.h" // only for their ::Type | #include "KX_FontObject.h" // only for their ::Type | ||||
| #include "RAS_MeshObject.h" | #include "RAS_MeshObject.h" | ||||
| #include "RAS_MeshUser.h" | |||||
| #include "RAS_BoundingBoxManager.h" | |||||
| #include "RAS_Deformer.h" | |||||
| #include "RAS_IDisplayArray.h" | |||||
| #include "RAS_Polygon.h" | |||||
| #include "KX_NavMeshObject.h" | #include "KX_NavMeshObject.h" | ||||
| #include "KX_MeshProxy.h" | #include "KX_MeshProxy.h" | ||||
| #include "KX_PolyProxy.h" | #include "KX_PolyProxy.h" | ||||
| #include <stdio.h> // printf | |||||
| #include "SG_Controller.h" | #include "SG_Controller.h" | ||||
| #include "PHY_IGraphicController.h" | #include "PHY_IGraphicController.h" | ||||
| #include "SG_Node.h" | #include "SG_Node.h" | ||||
| #include "KX_ClientObjectInfo.h" | #include "KX_ClientObjectInfo.h" | ||||
| #include "RAS_BucketManager.h" | #include "RAS_BucketManager.h" | ||||
| #include "KX_RayCast.h" | #include "KX_RayCast.h" | ||||
| #include "KX_PythonInit.h" | #include "KX_Globals.h" | ||||
| #include "KX_PyMath.h" | #include "KX_PyMath.h" | ||||
| #include "SCA_IActuator.h" | #include "SCA_IActuator.h" | ||||
| #include "SCA_ISensor.h" | #include "SCA_ISensor.h" | ||||
| #include "SCA_IController.h" | #include "SCA_IController.h" | ||||
| #include "NG_NetworkScene.h" //Needed for sendMessage() | #include "KX_NetworkMessageScene.h" //Needed for sendMessage() | ||||
| #include "KX_ObstacleSimulation.h" | #include "KX_ObstacleSimulation.h" | ||||
| #include "KX_Scene.h" | #include "KX_Scene.h" | ||||
| #include "KX_LodLevel.h" | |||||
| #include "KX_LodManager.h" | |||||
| #include "KX_BoundingBox.h" | |||||
| #include "KX_CollisionContactPoints.h" | |||||
| #include "BKE_object.h" | #include "BKE_object.h" | ||||
| Context not available. | |||||
| # include "python_utildefines.h" | # include "python_utildefines.h" | ||||
| #endif | #endif | ||||
| // Component stuff | |||||
| #include "DNA_python_component_types.h" | |||||
| // This file defines relationships between parents and children | // This file defines relationships between parents and children | ||||
| // in the game engine. | // in the game engine. | ||||
| Context not available. | |||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| static MT_Point3 dummy_point= MT_Point3(0.0f, 0.0f, 0.0f); | #include "CM_Message.h" | ||||
| static MT_Vector3 dummy_point= MT_Vector3(0.0f, 0.0f, 0.0f); | |||||
| static MT_Vector3 dummy_scaling = MT_Vector3(1.0f, 1.0f, 1.0f); | static MT_Vector3 dummy_scaling = MT_Vector3(1.0f, 1.0f, 1.0f); | ||||
| static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(1.0f, 0.0f, 0.0f, | static MT_Matrix3x3 dummy_orientation = MT_Matrix3x3(1.0f, 0.0f, 0.0f, | ||||
| 0.0f, 1.0f, 0.0f, | 0.0f, 1.0f, 0.0f, | ||||
| Context not available. | |||||
| void* sgReplicationInfo, | void* sgReplicationInfo, | ||||
| SG_Callbacks callbacks) | SG_Callbacks callbacks) | ||||
| : SCA_IObject(), | : SCA_IObject(), | ||||
| m_bDyna(false), | |||||
| m_layer(0), | m_layer(0), | ||||
| m_lodManager(NULL), | |||||
| m_currentLodLevel(0), | m_currentLodLevel(0), | ||||
| m_previousLodLevel(0), | m_meshUser(NULL), | ||||
| m_pBlenderObject(NULL), | m_pBlenderObject(NULL), | ||||
| m_pBlenderGroupObject(NULL), | m_pBlenderGroupObject(NULL), | ||||
| m_bUseObjectColor(false), | |||||
| m_bIsNegativeScaling(false), | m_bIsNegativeScaling(false), | ||||
| m_objectColor(1.0f, 1.0f, 1.0f, 1.0f), | m_objectColor(1.0f, 1.0f, 1.0f, 1.0f), | ||||
| m_bVisible(true), | m_bVisible(true), | ||||
| m_bCulled(true), | m_bCulled(true), | ||||
| m_bOccluder(false), | m_bOccluder(false), | ||||
| m_autoUpdateBounds(false), | |||||
| m_pPhysicsController(NULL), | m_pPhysicsController(NULL), | ||||
| m_pGraphicController(NULL), | m_pGraphicController(NULL), | ||||
| m_pObstacleSimulation(NULL), | m_components(NULL), | ||||
| m_pInstanceObjects(NULL), | m_pInstanceObjects(NULL), | ||||
| m_pDupliGroupObject(NULL), | m_pDupliGroupObject(NULL), | ||||
| m_actionManager(NULL), | m_actionManager(NULL) | ||||
| m_bRecordAnimation(false), | |||||
| m_isDeformable(false) | |||||
| #ifdef WITH_PYTHON | #ifdef WITH_PYTHON | ||||
| , m_attr_dict(NULL), | , m_attr_dict(NULL), | ||||
| m_collisionCallbacks(NULL) | m_collisionCallbacks(NULL) | ||||
| Context not available. | |||||
| UnregisterCollisionCallbacks(); | UnregisterCollisionCallbacks(); | ||||
| Py_CLEAR(m_collisionCallbacks); | Py_CLEAR(m_collisionCallbacks); | ||||
| } | } | ||||
| if (m_components) { | |||||
| m_components->Release(); | |||||
| } | |||||
| #endif // WITH_PYTHON | #endif // WITH_PYTHON | ||||
| RemoveMeshes(); | RemoveMeshes(); | ||||
| Context not available. | |||||
| delete m_pPhysicsController; | delete m_pPhysicsController; | ||||
| } | } | ||||
| if (m_pObstacleSimulation) | |||||
| { | |||||
| m_pObstacleSimulation->DestroyObstacleForObj(this); | |||||
| } | |||||
| if (m_actionManager) | if (m_actionManager) | ||||
| { | { | ||||
| delete m_actionManager; | delete m_actionManager; | ||||
| Context not available. | |||||
| { | { | ||||
| m_pInstanceObjects->Release(); | m_pInstanceObjects->Release(); | ||||
| } | } | ||||
| if (m_lodManager) { | |||||
| m_lodManager->Release(); | |||||
| } | |||||
| } | } | ||||
| KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo *info) | KX_GameObject* KX_GameObject::GetClientObject(KX_ClientObjectInfo *info) | ||||
| Context not available. | |||||
| return info->m_gameobject; | return info->m_gameobject; | ||||
| } | } | ||||
| CValue* KX_GameObject:: Calc(VALUE_OPERATOR op, CValue *val) | const std::string KX_GameObject::GetText() | ||||
| { | |||||
| return NULL; | |||||
| } | |||||
| CValue* KX_GameObject::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val) | |||||
| { | |||||
| return NULL; | |||||
| } | |||||
| const STR_String & KX_GameObject::GetText() | |||||
| { | { | ||||
| return m_text; | return m_text; | ||||
| } | } | ||||
| std::string KX_GameObject::GetName() | |||||
| double KX_GameObject::GetNumber() | |||||
| { | |||||
| return 0; | |||||
| } | |||||
| STR_String& KX_GameObject::GetName() | |||||
| { | { | ||||
| return m_name; | return m_name; | ||||
| } | } | ||||
| /* Set the name of the value */ | /* Set the name of the value */ | ||||
| void KX_GameObject::SetName(const char *name) | void KX_GameObject::SetName(const std::string& name) | ||||
| { | { | ||||
| m_name = name; | m_name = name; | ||||
| } | } | ||||
| Context not available. | |||||
| } | } | ||||
| void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost) | void KX_GameObject::SetParent(KX_GameObject* obj, bool addToCompound, bool ghost) | ||||
| { | { | ||||
| // check on valid node in case a python controller holds a reference to a deleted object | // check on valid node in case a python controller holds a reference to a deleted object | ||||
| if (obj && | if (obj && | ||||
| Context not available. | |||||
| obj->GetSGNode() && // object is not zombi | obj->GetSGNode() && // object is not zombi | ||||
| GetSGNode()->GetSGParent() != obj->GetSGNode() && // not already parented to same object | GetSGNode()->GetSGParent() != obj->GetSGNode() && // not already parented to same object | ||||
| !GetSGNode()->IsAncessor(obj->GetSGNode()) && // no parenting loop | !GetSGNode()->IsAncessor(obj->GetSGNode()) && // no parenting loop | ||||
| this != obj) // not the object itself | this != obj) // not the object itself | ||||
| { | { | ||||
| if (!(GetScene()->GetInactiveList()->SearchValue(obj) != GetScene()->GetObjectList()->SearchValue(this))) { | |||||
| CM_FunctionWarning("child and parent are not in the same game objects list (active or inactive). This operation is forbidden."); | |||||
| return; | |||||
| } | |||||
| // Make sure the objects have some scale | // Make sure the objects have some scale | ||||
| MT_Vector3 scale1 = NodeGetWorldScaling(); | MT_Vector3 scale1 = NodeGetWorldScaling(); | ||||
| MT_Vector3 scale2 = obj->NodeGetWorldScaling(); | MT_Vector3 scale2 = obj->NodeGetWorldScaling(); | ||||
| Context not available. | |||||
| fabs(scale1[1]) < (MT_Scalar)FLT_EPSILON || | fabs(scale1[1]) < (MT_Scalar)FLT_EPSILON || | ||||
| fabs(scale1[2]) < (MT_Scalar)FLT_EPSILON) { return; } | fabs(scale1[2]) < (MT_Scalar)FLT_EPSILON) { return; } | ||||
| KX_Scene *scene = GetScene(); | |||||
| // Remove us from our old parent and set our new parent | // Remove us from our old parent and set our new parent | ||||
| RemoveParent(scene); | RemoveParent(); | ||||
| obj->GetSGNode()->AddChild(GetSGNode()); | obj->GetSGNode()->AddChild(GetSGNode()); | ||||
| if (m_pPhysicsController) | if (m_pPhysicsController) | ||||
| Context not available. | |||||
| MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2; | MT_Vector3 newpos = invori*(NodeGetWorldPosition()-obj->NodeGetWorldPosition())*scale2; | ||||
| NodeSetLocalScale(scale1); | NodeSetLocalScale(scale1); | ||||
| NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2])); | NodeSetLocalPosition(MT_Vector3(newpos[0],newpos[1],newpos[2])); | ||||
| NodeSetLocalOrientation(invori*NodeGetWorldOrientation()); | NodeSetLocalOrientation(invori*NodeGetWorldOrientation()); | ||||
| NodeUpdateGS(0.f); | NodeUpdateGS(0.f); | ||||
| // object will now be a child, it must be removed from the parent list | // object will now be a child, it must be removed from the parent list | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| void KX_GameObject::RemoveParent(KX_Scene *scene) | void KX_GameObject::RemoveParent() | ||||
| { | { | ||||
| // check on valid node in case a python controller holds a reference to a deleted object | // check on valid node in case a python controller holds a reference to a deleted object | ||||
| if (GetSGNode() && GetSGNode()->GetSGParent()) | if (GetSGNode() && GetSGNode()->GetSGParent()) | ||||
| Context not available. | |||||
| // Remove us from our parent | // Remove us from our parent | ||||
| GetSGNode()->DisconnectFromParent(); | GetSGNode()->DisconnectFromParent(); | ||||
| NodeUpdateGS(0.f); | NodeUpdateGS(0.f); | ||||
| KX_Scene *scene = GetScene(); | |||||
| // the object is now a root object, add it to the parentlist | // the object is now a root object, add it to the parentlist | ||||
| CListValue* rootlist = scene->GetRootParentList(); | CListValue* rootlist = scene->GetRootParentList(); | ||||
| if (!rootlist->SearchValue(this)) | if (!rootlist->SearchValue(this)) | ||||
| Context not available. | |||||
| if (m_pPhysicsController->IsDynamic() && (rootobj != NULL && rootobj->m_pPhysicsController)) | if (m_pPhysicsController->IsDynamic() && (rootobj != NULL && rootobj->m_pPhysicsController)) | ||||
| { | { | ||||
| // dynamic object should remember the velocity they had while being parented | // dynamic object should remember the velocity they had while being parented | ||||
| MT_Point3 childPoint = GetSGNode()->GetWorldPosition(); | MT_Vector3 childPoint = GetSGNode()->GetWorldPosition(); | ||||
| MT_Point3 rootPoint = rootobj->GetSGNode()->GetWorldPosition(); | MT_Vector3 rootPoint = rootobj->GetSGNode()->GetWorldPosition(); | ||||
| MT_Point3 relPoint; | MT_Vector3 relPoint; | ||||
| relPoint = (childPoint-rootPoint); | relPoint = (childPoint-rootPoint); | ||||
| MT_Vector3 linVel = rootobj->m_pPhysicsController->GetVelocity(relPoint); | MT_Vector3 linVel = rootobj->m_pPhysicsController->GetVelocity(relPoint); | ||||
| MT_Vector3 angVel = rootobj->m_pPhysicsController->GetAngularVelocity(); | MT_Vector3 angVel = rootobj->m_pPhysicsController->GetAngularVelocity(); | ||||
| Context not available. | |||||
| return m_actionManager; | return m_actionManager; | ||||
| } | } | ||||
| bool KX_GameObject::PlayAction(const char* name, | bool KX_GameObject::PlayAction(const std::string& name, | ||||
| float start, | float start, | ||||
| float end, | float end, | ||||
| short layer, | short layer, | ||||
| Context not available. | |||||
| return GetActionManager()->IsActionDone(layer); | return GetActionManager()->IsActionDone(layer); | ||||
| } | } | ||||
| void KX_GameObject::UpdateActionManager(float curtime) | void KX_GameObject::UpdateActionManager(float curtime, bool applyToObject) | ||||
| { | |||||
| GetActionManager()->Update(curtime, applyToObject); | |||||
| } | |||||
| void KX_GameObject::UpdateActionIPOs() | |||||
| { | { | ||||
| GetActionManager()->Update(curtime); | GetActionManager()->UpdateIPOs(); | ||||
| } | } | ||||
| float KX_GameObject::GetActionFrame(short layer) | float KX_GameObject::GetActionFrame(short layer) | ||||
| Context not available. | |||||
| return GetActionManager()->GetActionFrame(layer); | return GetActionManager()->GetActionFrame(layer); | ||||
| } | } | ||||
| const char *KX_GameObject::GetActionName(short layer) | const std::string KX_GameObject::GetActionName(short layer) | ||||
| { | { | ||||
| return GetActionManager()->GetActionName(layer); | return GetActionManager()->GetActionName(layer); | ||||
| } | } | ||||
| Context not available. | |||||
| m_actionManager = NULL; | m_actionManager = NULL; | ||||
| m_state = 0; | m_state = 0; | ||||
| KX_Scene* scene = KX_GetActiveScene(); | m_meshUser = NULL; | ||||
| KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation(); | if (m_lodManager) { | ||||
| struct Object* blenderobject = GetBlenderObject(); | m_lodManager->AddRef(); | ||||
| if (obssimulation && (blenderobject->gameflag & OB_HASOBSTACLE)) | |||||
| { | |||||
| obssimulation->AddObstacleForObj(this); | |||||
| } | } | ||||
| #ifdef WITH_PYTHON | #ifdef WITH_PYTHON | ||||
| if (m_attr_dict) | if (m_attr_dict) | ||||
| m_attr_dict= PyDict_Copy(m_attr_dict); | m_attr_dict= PyDict_Copy(m_attr_dict); | ||||
| if (m_components) { | |||||
| m_components = (CListValue *)m_components->GetReplica(); | |||||
| for (CListValue::iterator<KX_PythonComponent> it = m_components->GetBegin(), end = m_components->GetEnd(); it != end; ++it) { | |||||
| KX_PythonComponent *component = *it; | |||||
| component->SetGameObject(this); | |||||
| } | |||||
| } | |||||
| #endif | #endif | ||||
| } | } | ||||
| static void setGraphicController_recursive(SG_Node* node) | static void setGraphicController_recursive(SG_Node* node) | ||||
| Context not available. | |||||
| return replica; | return replica; | ||||
| } | } | ||||
| bool KX_GameObject::IsDynamic() const | |||||
| { | |||||
| if (m_pPhysicsController) { | |||||
| return m_pPhysicsController->IsDynamic(); | |||||
| } | |||||
| return false; | |||||
| } | |||||
| bool KX_GameObject::IsDynamicsSuspended() const | bool KX_GameObject::IsDynamicsSuspended() const | ||||
| { | { | ||||
| if (m_pPhysicsController) | if (m_pPhysicsController) | ||||
| return m_pPhysicsController->IsSuspended(); | return m_pPhysicsController->IsDynamicsSuspended(); | ||||
| return false; | return false; | ||||
| } | } | ||||
| Context not available. | |||||
| m_pPhysicsController->RelativeTranslate(dloc,local); | m_pPhysicsController->RelativeTranslate(dloc,local); | ||||
| } | } | ||||
| GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local); | GetSGNode()->RelativeTranslate(dloc,GetSGNode()->GetSGParent(),local); | ||||
| NodeUpdateGS(0.0f); | |||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| if (m_pPhysicsController) { // (IsDynamic()) | if (m_pPhysicsController) { // (IsDynamic()) | ||||
| m_pPhysicsController->RelativeRotate(rotmat,local); | m_pPhysicsController->RelativeRotate(rotmat,local); | ||||
| } | } | ||||
| NodeUpdateGS(0.0f); | |||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| void KX_GameObject::AddMeshUser() | void KX_GameObject::AddMeshUser() | ||||
| { | { | ||||
| for (size_t i=0;i<m_meshes.size();i++) | for (size_t i = 0; i < m_meshes.size(); ++i) { | ||||
| { | m_meshUser = m_meshes[i]->AddMeshUser(m_pClient_info, GetDeformer()); | ||||
| m_meshes[i]->AddMeshUser(this, &m_meshSlots, GetDeformer()); | |||||
| } | } | ||||
| // set the part of the mesh slot that never change | // set the part of the mesh slot that never change | ||||
| float *fl = GetOpenGLMatrixPtr()->getPointer(); | float *fl = GetOpenGLMatrixPtr()->getPointer(); | ||||
| SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots); | if (m_meshUser) { | ||||
| // RAS_MeshSlot* ms; | m_meshUser->SetMatrix(fl); | ||||
| for (mit.begin(); !mit.end(); ++mit) | |||||
| { | |||||
| (*mit)->m_OpenGLMatrix = fl; | |||||
| } | } | ||||
| UpdateBuckets(false); | |||||
| } | } | ||||
| static void UpdateBuckets_recursive(SG_Node* node) | void KX_GameObject::UpdateBuckets() | ||||
| { | { | ||||
| NodeList& children = node->GetSGChildren(); | // Update datas and add mesh slot to be rendered only if the object is not culled. | ||||
| if (!m_bCulled && m_bVisible && m_meshUser) { | |||||
| for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) | if (m_pSGNode->IsDirty()) { | ||||
| { | |||||
| SG_Node* childnode = (*childit); | |||||
| KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject()); | |||||
| if (clientgameobj != NULL) // This is a GameObject | |||||
| clientgameobj->UpdateBuckets(0); | |||||
| // if the childobj is NULL then this may be an inverse parent link | |||||
| // so a non recursive search should still look down this node. | |||||
| UpdateBuckets_recursive(childnode); | |||||
| } | |||||
| } | |||||
| void KX_GameObject::UpdateBuckets( bool recursive ) | |||||
| { | |||||
| if (GetSGNode()) { | |||||
| RAS_MeshSlot *ms; | |||||
| if (GetSGNode()->IsDirty()) | |||||
| GetOpenGLMatrix(); | GetOpenGLMatrix(); | ||||
| 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()); | |||||
| } | } | ||||
| m_meshUser->SetColor(m_objectColor); | |||||
| m_meshUser->SetFrontFace(!m_bIsNegativeScaling); | |||||
| m_meshUser->ActivateMeshSlots(); | |||||
| } | } | ||||
| } | } | ||||
| void KX_GameObject::RemoveMeshes() | void KX_GameObject::RemoveMeshes() | ||||
| { | { | ||||
| for (size_t i=0;i<m_meshes.size();i++) | for (size_t i=0;i<m_meshes.size();i++) | ||||
| m_meshes[i]->RemoveFromBuckets(this); | m_meshes[i]->RemoveFromBuckets(m_pClient_info); | ||||
| // Remove all mesh slots. | |||||
| if (m_meshUser) { | |||||
| delete m_meshUser; | |||||
| m_meshUser = NULL; | |||||
| } | |||||
| //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter | //note: meshes can be shared, and are deleted by KX_BlenderSceneConverter | ||||
| m_meshes.clear(); | m_meshes.clear(); | ||||
| } | } | ||||
| void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh) | void KX_GameObject::SetLodManager(KX_LodManager *lodManager) | ||||
| { | { | ||||
| m_lodmeshes.push_back(mesh); | // Reset lod level to avoid overflow index in KX_LodManager::GetLevel. | ||||
| } | m_currentLodLevel = 0; | ||||
| // Restore object original mesh. | |||||
| if (!lodManager && m_lodManager && m_lodManager->GetLevelCount() > 0) { | |||||
| KX_Scene *scene = GetScene(); | |||||
| RAS_MeshObject *origmesh = m_lodManager->GetLevel(0)->GetMesh(); | |||||
| scene->ReplaceMesh(this, origmesh, true, false); | |||||
| } | |||||
| static float calcHysteresis(KX_Scene *kxscene, LodLevel *lod) | m_lodManager = lodManager; | ||||
| { | |||||
| float hystvariance = 0.0f; | |||||
| if (!kxscene->IsActivedLodHysteresis()) | |||||
| return hystvariance; | |||||
| short hysteresis = 0; | |||||
| // if exists, LoD level hysteresis will override scene hysteresis | |||||
| if (lod->next->flags & OB_LOD_USE_HYST) | |||||
| hysteresis = lod->next->obhysteresis; | |||||
| else | |||||
| hysteresis = kxscene->GetLodHysteresisValue(); | |||||
| return hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100; | |||||
| } | } | ||||
| void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos) | KX_LodManager *KX_GameObject::GetLodManager() const | ||||
| { | { | ||||
| // Handle dupligroups | return m_lodManager; | ||||
| if (m_pInstanceObjects) { | } | ||||
| KX_GameObject *instob; | |||||
| int count = m_pInstanceObjects->GetCount(); | |||||
| for (int i = 0; i < count; i++) { | |||||
| instob = (KX_GameObject*)m_pInstanceObjects->GetValue(i); | |||||
| instob->UpdateLod(cam_pos); | |||||
| } | |||||
| } | |||||
| if (m_lodmeshes.empty()) | void KX_GameObject::UpdateLod(const MT_Vector3& cam_pos, float lodfactor) | ||||
| { | |||||
| if (!m_lodManager) { | |||||
| return; | return; | ||||
| } | |||||
| MT_Vector3 delta = NodeGetWorldPosition() - cam_pos; | KX_Scene *scene = GetScene(); | ||||
| float distance2 = delta.length2(); | const float distance2 = NodeGetWorldPosition().distance2(cam_pos) * (lodfactor * lodfactor); | ||||
| KX_LodLevel *lodLevel = m_lodManager->GetLevel(scene, m_currentLodLevel, distance2); | |||||
| int level = 0; | |||||
| float hystvariance = 0.0f; | |||||
| Object *bob = GetBlenderObject(); | |||||
| LodLevel *lod = (LodLevel *)bob->lodlevels.first; | |||||
| KX_Scene *kxscene = GetScene(); | |||||
| for (; lod; lod = lod->next, level++) { | |||||
| if (!lod->source || lod->source->type != OB_MESH) | |||||
| level--; | |||||
| if (!lod->next) | |||||
| break; | |||||
| if (level == m_previousLodLevel || level == (m_previousLodLevel + 1)) { | if (lodLevel) { | ||||
| hystvariance = calcHysteresis(kxscene, lod); | RAS_MeshObject *mesh = lodLevel->GetMesh(); | ||||
| float newdistance = lod->next->distance + hystvariance; | if (mesh != m_meshes[0]) { | ||||
| if (newdistance * newdistance > distance2) | scene->ReplaceMesh(this, mesh, true, false); | ||||
| break; | |||||
| } | |||||
| else if (level == (m_previousLodLevel - 1)) { | |||||
| hystvariance = calcHysteresis(kxscene, lod); | |||||
| float newdistance = lod->next->distance - hystvariance; | |||||
| if (newdistance * newdistance > distance2) | |||||
| break; | |||||
| } | } | ||||
| } | |||||
| RAS_MeshObject *mesh = m_lodmeshes[level]; | m_currentLodLevel = lodLevel->GetLevel(); | ||||
| m_currentLodLevel = level; | |||||
| if (mesh != m_meshes[0]) { | |||||
| m_previousLodLevel = level; | |||||
| GetScene()->ReplaceMesh(this, mesh, true, false); | |||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| ((KX_GameObject*)gameobj)->SynchronizeTransform(); | ((KX_GameObject*)gameobj)->SynchronizeTransform(); | ||||
| } | } | ||||
| void KX_GameObject::SetDebugColor(unsigned int bgra) | |||||
| { | |||||
| for (size_t i=0;i<m_meshes.size();i++) | |||||
| m_meshes[i]->DebugColor(bgra); | |||||
| } | |||||
| void KX_GameObject::ResetDebugColor() | |||||
| { | |||||
| SetDebugColor(0xff000000); | |||||
| } | |||||
| void KX_GameObject::InitIPO(bool ipo_as_force, | void KX_GameObject::InitIPO(bool ipo_as_force, | ||||
| bool ipo_add, | bool ipo_add, | ||||
| bool ipo_local) | bool ipo_local) | ||||
| Context not available. | |||||
| void KX_GameObject::UpdateIPO(float curframetime, | void KX_GameObject::UpdateIPO(float curframetime, | ||||
| bool recurse) | bool recurse) | ||||
| { | { | ||||
| /* This function shouldn't call BL_Action::Update, not even indirectly, | |||||
| * as it will cause deadlock due to the lock in BL_Action::Update. */ | |||||
| // just the 'normal' update procedure. | // just the 'normal' update procedure. | ||||
| GetSGNode()->SetSimulatedTime(curframetime,recurse); | GetSGNode()->SetSimulatedTime(curframetime,recurse); | ||||
| GetSGNode()->UpdateWorldData(curframetime); | GetSGNode()->UpdateWorldData(curframetime); | ||||
| UpdateTransform(); | UpdateTransform(); | ||||
| } | } | ||||
| // IPO update | |||||
| void | |||||
| KX_GameObject::UpdateMaterialData( | |||||
| dword matname_hash, | |||||
| MT_Vector4 rgba, | |||||
| MT_Vector3 specrgb, | |||||
| MT_Scalar hard, | |||||
| MT_Scalar spec, | |||||
| MT_Scalar ref, | |||||
| MT_Scalar emit, | |||||
| MT_Scalar alpha | |||||
| ) | |||||
| { | |||||
| int mesh = 0; | |||||
| if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { | |||||
| list<RAS_MeshMaterial>::iterator mit = m_meshes[mesh]->GetFirstMaterial(); | |||||
| for (; mit != m_meshes[mesh]->GetLastMaterial(); ++mit) | |||||
| { | |||||
| RAS_IPolyMaterial* poly = mit->m_bucket->GetPolyMaterial(); | |||||
| if (poly->GetFlag() & RAS_BLENDERMAT ) | |||||
| { | |||||
| KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly); | |||||
| if (matname_hash == 0) | |||||
| { | |||||
| m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); | |||||
| // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance) | |||||
| SetObjectColor(rgba); | |||||
| } | |||||
| else | |||||
| { | |||||
| if (matname_hash == poly->GetMaterialNameHash()) | |||||
| { | |||||
| m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); | |||||
| m_meshes[mesh]->SetVertexColor(poly,rgba); | |||||
| // no break here, because one blender material can be split into several game engine materials | |||||
| // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body | |||||
| // if here was a break then would miss some vertices if material was split | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| bool | bool | ||||
| KX_GameObject::GetVisible( | KX_GameObject::GetVisible( | ||||
| void | void | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| static void setDebug_recursive(SG_Node *node, bool debug) | static void setDebug_recursive(KX_Scene *scene, SG_Node *node, bool debug) | ||||
| { | { | ||||
| NodeList& children = node->GetSGChildren(); | NodeList& children = node->GetSGChildren(); | ||||
| KX_Scene *scene = KX_GetActiveScene(); | |||||
| for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) { | for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) { | ||||
| SG_Node *childnode = (*childit); | SG_Node *childnode = (*childit); | ||||
| Context not available. | |||||
| /* if the childobj is NULL then this may be an inverse parent link | /* if the childobj is NULL then this may be an inverse parent link | ||||
| * so a non recursive search should still look down this node. */ | * so a non recursive search should still look down this node. */ | ||||
| setDebug_recursive(childnode, debug); | setDebug_recursive(scene, childnode, debug); | ||||
| } | } | ||||
| } | } | ||||
| void KX_GameObject::SetUseDebugProperties( bool debug, bool recursive ) | void KX_GameObject::SetUseDebugProperties( bool debug, bool recursive ) | ||||
| { | { | ||||
| KX_Scene *scene = KX_GetActiveScene(); | KX_Scene *scene = GetScene(); | ||||
| if (debug) { | if (debug) { | ||||
| if (!scene->ObjectInDebugList(this)) | if (!scene->ObjectInDebugList(this)) | ||||
| Context not available. | |||||
| scene->RemoveObjectDebugProperties(this); | scene->RemoveObjectDebugProperties(this); | ||||
| if (recursive) | if (recursive) | ||||
| setDebug_recursive(GetSGNode(), debug); | setDebug_recursive(scene, GetSGNode(), debug); | ||||
| } | } | ||||
| void | void | ||||
| Context not available. | |||||
| void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec) | void KX_GameObject::SetObjectColor(const MT_Vector4& rgbavec) | ||||
| { | { | ||||
| m_bUseObjectColor = true; | |||||
| m_objectColor = rgbavec; | m_objectColor = rgbavec; | ||||
| } | } | ||||
| Context not available. | |||||
| len = vect.length(); | len = vect.length(); | ||||
| if (MT_fuzzyZero(len)) | if (MT_fuzzyZero(len)) | ||||
| { | { | ||||
| cout << "alignAxisToVect() Error: Null vector!\n"; | CM_FunctionError("null vector!"); | ||||
| return; | return; | ||||
| } | } | ||||
| Context not available. | |||||
| y = z.cross(x); | y = z.cross(x); | ||||
| break; | break; | ||||
| default: // invalid axis specified | default: // invalid axis specified | ||||
| cout << "alignAxisToVect(): Invalid axis '" << axis <<"'\n"; | CM_FunctionWarning("invalid axis '" << axis <<"'"); | ||||
| return; | return; | ||||
| } | } | ||||
| x.normalize(); // normalize the new base vectors | x.normalize(); // normalize the new base vectors | ||||
| Context not available. | |||||
| return velocity; | return velocity; | ||||
| } | } | ||||
| MT_Vector3 KX_GameObject::GetVelocity(const MT_Point3& point) | MT_Vector3 KX_GameObject::GetVelocity(const MT_Vector3& point) | ||||
| { | { | ||||
| if (m_pPhysicsController) | if (m_pPhysicsController) | ||||
| { | { | ||||
| Context not available. | |||||
| // scenegraph node stuff | // scenegraph node stuff | ||||
| void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans) | void KX_GameObject::NodeSetLocalPosition(const MT_Vector3& trans) | ||||
| { | { | ||||
| // check on valid node in case a python controller holds a reference to a deleted object | // check on valid node in case a python controller holds a reference to a deleted object | ||||
| if (!GetSGNode()) | if (!GetSGNode()) | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| void KX_GameObject::NodeSetWorldPosition(const MT_Point3& trans) | void KX_GameObject::NodeSetWorldPosition(const MT_Vector3& trans) | ||||
| { | { | ||||
| if (!GetSGNode()) | if (!GetSGNode()) | ||||
| return; | return; | ||||
| Context not available. | |||||
| scale[2] = 1.0f/scale[2]; | scale[2] = 1.0f/scale[2]; | ||||
| MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse(); | MT_Matrix3x3 invori = parent->GetWorldOrientation().inverse(); | ||||
| MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale; | MT_Vector3 newpos = invori*(trans-parent->GetWorldPosition())*scale; | ||||
| NodeSetLocalPosition(MT_Point3(newpos[0],newpos[1],newpos[2])); | NodeSetLocalPosition(MT_Vector3(newpos[0],newpos[1],newpos[2])); | ||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| Context not available. | |||||
| return GetSGNode()->GetLocalScale(); | return GetSGNode()->GetLocalScale(); | ||||
| } | } | ||||
| const MT_Point3& KX_GameObject::NodeGetWorldPosition() const | const MT_Vector3& KX_GameObject::NodeGetWorldPosition() const | ||||
| { | { | ||||
| // check on valid node in case a python controller holds a reference to a deleted object | // check on valid node in case a python controller holds a reference to a deleted object | ||||
| if (GetSGNode()) | if (GetSGNode()) | ||||
| Context not available. | |||||
| return dummy_point; | return dummy_point; | ||||
| } | } | ||||
| const MT_Point3& KX_GameObject::NodeGetLocalPosition() const | const MT_Vector3& KX_GameObject::NodeGetLocalPosition() const | ||||
| { | { | ||||
| // check on valid node in case a python controller holds a reference to a deleted object | // check on valid node in case a python controller holds a reference to a deleted object | ||||
| if (GetSGNode()) | if (GetSGNode()) | ||||
| Context not available. | |||||
| return dummy_point; | return dummy_point; | ||||
| } | } | ||||
| void KX_GameObject::UpdateBounds(bool force) | |||||
| { | |||||
| if ((!m_autoUpdateBounds && !force) || !m_meshUser) { | |||||
| return; | |||||
| } | |||||
| RAS_BoundingBox *boundingBox = m_meshUser->GetBoundingBox(); | |||||
| if (!boundingBox || !boundingBox->GetModified()) { | |||||
| return; | |||||
| } | |||||
| // AABB Box : min/max. | |||||
| MT_Vector3 aabbMin; | |||||
| MT_Vector3 aabbMax; | |||||
| boundingBox->GetAabb(aabbMin, aabbMax); | |||||
| SetBoundsAabb(aabbMin, aabbMax); | |||||
| } | |||||
| void KX_GameObject::SetBoundsAabb(MT_Vector3 aabbMin, MT_Vector3 aabbMax) | |||||
| { | |||||
| // Set the AABB in SG node box. | |||||
| SG_BBox &box = m_pSGNode->BBox(); | |||||
| box.SetMin(aabbMin); | |||||
| box.SetMax(aabbMax); | |||||
| // And in the object's graphic controller if it exists. | |||||
| if (m_pGraphicController) { | |||||
| m_pGraphicController->SetLocalAabb(aabbMin, aabbMax); | |||||
| } | |||||
| } | |||||
| void KX_GameObject::GetBoundsAabb(MT_Vector3 &aabbMin, MT_Vector3 &aabbMax) const | |||||
| { | |||||
| // Get the node box AABB | |||||
| SG_BBox &box = m_pSGNode->BBox(); | |||||
| aabbMin = box.GetMin(); | |||||
| aabbMax = box.GetMax(); | |||||
| } | |||||
| void KX_GameObject::UnregisterCollisionCallbacks() | void KX_GameObject::UnregisterCollisionCallbacks() | ||||
| { | { | ||||
| if (!GetPhysicsController()) { | if (!GetPhysicsController()) { | ||||
| printf("Warning, trying to unregister collision callbacks for object without collisions: %s!\n", GetName().ReadPtr()); | CM_Warning("trying to unregister collision callbacks for object without collisions: " << GetName()); | ||||
| return; | return; | ||||
| } | } | ||||
| Context not available. | |||||
| void KX_GameObject::RegisterCollisionCallbacks() | void KX_GameObject::RegisterCollisionCallbacks() | ||||
| { | { | ||||
| if (!GetPhysicsController()) { | if (!GetPhysicsController()) { | ||||
| printf("Warning, trying to register collision callbacks for object without collisions: %s!\n", GetName().ReadPtr()); | CM_Warning("trying to register collision callbacks for object without collisions: " << GetName()); | ||||
| return; | return; | ||||
| } | } | ||||
| Context not available. | |||||
| pe->AddSensor(spc); | pe->AddSensor(spc); | ||||
| } | } | ||||
| } | } | ||||
| void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal) | void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider, KX_CollisionContactPointList& contactPointList) | ||||
| { | { | ||||
| #ifdef WITH_PYTHON | #ifdef WITH_PYTHON | ||||
| if (!m_collisionCallbacks || PyList_GET_SIZE(m_collisionCallbacks) == 0) | if (!m_collisionCallbacks || PyList_GET_SIZE(m_collisionCallbacks) == 0) { | ||||
| return; | return; | ||||
| } | |||||
| PyObject *args[] = {collider->GetProxy(), PyObjectFrom(point), PyObjectFrom(normal)}; | CListWrapper *listWrapper = contactPointList.GetListWrapper(); | ||||
| PyObject *args[] = {collider->GetProxy(), | |||||
| PyObjectFrom(contactPointList.GetCollData()->GetWorldPoint(0, contactPointList.GetFirstObject())), | |||||
| PyObjectFrom(contactPointList.GetCollData()->GetNormal(0, contactPointList.GetFirstObject())), | |||||
| listWrapper->GetProxy()}; | |||||
| RunPythonCallBackList(m_collisionCallbacks, args, 1, ARRAY_SIZE(args)); | RunPythonCallBackList(m_collisionCallbacks, args, 1, ARRAY_SIZE(args)); | ||||
| for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) { | for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) { | ||||
| Py_DECREF(args[i]); | Py_DECREF(args[i]); | ||||
| } | } | ||||
| // Invalidate the collison contact point to avoid acces to it in next frame | |||||
| listWrapper->InvalidateProxy(); | |||||
| delete listWrapper; | |||||
| #endif | #endif | ||||
| } | } | ||||
| Context not available. | |||||
| CValue* childobj = (CValue*)childnode->GetSGClientObject(); | CValue* childobj = (CValue*)childnode->GetSGClientObject(); | ||||
| if (childobj != NULL) // This is a GameObject | if (childobj != NULL) // This is a GameObject | ||||
| { | { | ||||
| // add to the list | // add to the list, no AddRef because the list doesn't own its items. | ||||
| list->Add(childobj->AddRef()); | list->Add(childobj); | ||||
| } | } | ||||
| // if the childobj is NULL then this may be an inverse parent link | // if the childobj is NULL then this may be an inverse parent link | ||||
| Context not available. | |||||
| CListValue* KX_GameObject::GetChildren() | CListValue* KX_GameObject::GetChildren() | ||||
| { | { | ||||
| CListValue* list = new CListValue(); | CListValue* list = new CListValue(); | ||||
| /* The list must not own any data because is temporary and we can't | |||||
| * ensure that it will freed before item's in it (e.g python owner). */ | |||||
| list->SetReleaseOnDestruct(false); | |||||
| walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */ | walk_children(GetSGNode(), list, 0); /* GetSGNode() is always valid or it would have raised an exception before this */ | ||||
| return list; | return list; | ||||
| } | } | ||||
| Context not available. | |||||
| CListValue* KX_GameObject::GetChildrenRecursive() | CListValue* KX_GameObject::GetChildrenRecursive() | ||||
| { | { | ||||
| CListValue* list = new CListValue(); | CListValue* list = new CListValue(); | ||||
| /* The list must not own any data because is temporary and we can't | |||||
| * ensure that it will freed before item's in it (e.g python owner). */ | |||||
| list->SetReleaseOnDestruct(false); | |||||
| walk_children(GetSGNode(), list, 1); | walk_children(GetSGNode(), list, 1); | ||||
| return list; | return list; | ||||
| } | } | ||||
| CListValue *KX_GameObject::GetComponents() const | |||||
| { | |||||
| return m_components; | |||||
| } | |||||
| void KX_GameObject::SetComponents(CListValue *components) | |||||
| { | |||||
| m_components = components; | |||||
| } | |||||
| void KX_GameObject::UpdateComponents() | |||||
| { | |||||
| #ifdef WITH_PYTHON | |||||
| if (!m_components) { | |||||
| return; | |||||
| } | |||||
| for (CListValue::iterator<KX_PythonComponent> it = m_components->GetBegin(), end = m_components->GetEnd(); it != end; ++it) { | |||||
| KX_PythonComponent *comp = *it; | |||||
| comp->Update(); | |||||
| } | |||||
| #endif // WITH_PYTHON | |||||
| } | |||||
| KX_Scene* KX_GameObject::GetScene() | KX_Scene* KX_GameObject::GetScene() | ||||
| { | { | ||||
| SG_Node* node = this->GetSGNode(); | SG_Node* node = this->GetSGNode(); | ||||
| Context not available. | |||||
| /* --------------------------------------------------------------------- | /* --------------------------------------------------------------------- | ||||
| * Some stuff taken from the header | * Some stuff taken from the header | ||||
| * --------------------------------------------------------------------- */ | * --------------------------------------------------------------------- */ | ||||
| void KX_GameObject::Relink(CTR_Map<CTR_HashedPtr, void*> *map_parameter) | void KX_GameObject::Relink(std::map<void *, void *>& map_parameter) | ||||
| { | { | ||||
| // we will relink the sensors and actuators that use object references | // we will relink the sensors and actuators that use object references | ||||
| // if the object is part of the replicated hierarchy, use the new | // if the object is part of the replicated hierarchy, use the new | ||||
| Context not available. | |||||
| } | } | ||||
| } | } | ||||
| #ifdef WITH_PYTHON | |||||
| #define PYTHON_CHECK_PHYSICS_CONTROLLER(obj, attr, ret) \ | |||||
| if (!(obj)->GetPhysicsController()) { \ | |||||
| PyErr_Format(PyExc_AttributeError, "KX_GameObject.%s, is missing a physics controller", (attr)); \ | |||||
| return (ret); \ | |||||
| } | |||||
| #endif | |||||
| #ifdef USE_MATHUTILS | #ifdef USE_MATHUTILS | ||||
| /* These require an SGNode */ | /* These require an SGNode */ | ||||
| Context not available. | |||||
| if (self == NULL) | if (self == NULL) | ||||
| return -1; | return -1; | ||||
| #define PHYS_ERR(attr) PyErr_SetString(PyExc_AttributeError, "KX_GameObject." attr ", is missing a physics controller") | |||||
| switch (subtype) { | switch (subtype) { | ||||
| case MATHUTILS_VEC_CB_POS_LOCAL: | case MATHUTILS_VEC_CB_POS_LOCAL: | ||||
| self->NodeGetLocalPosition().getValue(bmo->data); | self->NodeGetLocalPosition().getValue(bmo->data); | ||||
| Context not available. | |||||
| self->NodeGetWorldScaling().getValue(bmo->data); | self->NodeGetWorldScaling().getValue(bmo->data); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_INERTIA_LOCAL: | case MATHUTILS_VEC_CB_INERTIA_LOCAL: | ||||
| if (!self->GetPhysicsController()) return PHYS_ERR("localInertia"), -1; | PYTHON_CHECK_PHYSICS_CONTROLLER(self, "localInertia", -1); | ||||
| self->GetPhysicsController()->GetLocalInertia().getValue(bmo->data); | self->GetPhysicsController()->GetLocalInertia().getValue(bmo->data); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_OBJECT_COLOR: | case MATHUTILS_VEC_CB_OBJECT_COLOR: | ||||
| self->GetObjectColor().getValue(bmo->data); | self->GetObjectColor().getValue(bmo->data); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_LINVEL_LOCAL: | case MATHUTILS_VEC_CB_LINVEL_LOCAL: | ||||
| if (!self->GetPhysicsController()) return PHYS_ERR("localLinearVelocity"), -1; | PYTHON_CHECK_PHYSICS_CONTROLLER(self, "localLinearVelocity", -1); | ||||
| self->GetLinearVelocity(true).getValue(bmo->data); | self->GetLinearVelocity(true).getValue(bmo->data); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_LINVEL_GLOBAL: | case MATHUTILS_VEC_CB_LINVEL_GLOBAL: | ||||
| if (!self->GetPhysicsController()) return PHYS_ERR("worldLinearVelocity"), -1; | PYTHON_CHECK_PHYSICS_CONTROLLER(self, "worldLinearVelocity", -1); | ||||
| self->GetLinearVelocity(false).getValue(bmo->data); | self->GetLinearVelocity(false).getValue(bmo->data); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_ANGVEL_LOCAL: | case MATHUTILS_VEC_CB_ANGVEL_LOCAL: | ||||
| if (!self->GetPhysicsController()) return PHYS_ERR("localLinearVelocity"), -1; | PYTHON_CHECK_PHYSICS_CONTROLLER(self, "localLinearVelocity", -1); | ||||
| self->GetAngularVelocity(true).getValue(bmo->data); | self->GetAngularVelocity(true).getValue(bmo->data); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_ANGVEL_GLOBAL: | case MATHUTILS_VEC_CB_ANGVEL_GLOBAL: | ||||
| if (!self->GetPhysicsController()) return PHYS_ERR("worldLinearVelocity"), -1; | PYTHON_CHECK_PHYSICS_CONTROLLER(self, "worldLinearVelocity", -1); | ||||
| self->GetAngularVelocity(false).getValue(bmo->data); | self->GetAngularVelocity(false).getValue(bmo->data); | ||||
| break; | break; | ||||
| Context not available. | |||||
| switch (subtype) { | switch (subtype) { | ||||
| case MATHUTILS_VEC_CB_POS_LOCAL: | case MATHUTILS_VEC_CB_POS_LOCAL: | ||||
| self->NodeSetLocalPosition(MT_Point3(bmo->data)); | self->NodeSetLocalPosition(MT_Vector3(bmo->data)); | ||||
| self->NodeUpdateGS(0.f); | self->NodeUpdateGS(0.f); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_POS_GLOBAL: | case MATHUTILS_VEC_CB_POS_GLOBAL: | ||||
| self->NodeSetWorldPosition(MT_Point3(bmo->data)); | self->NodeSetWorldPosition(MT_Vector3(bmo->data)); | ||||
| self->NodeUpdateGS(0.f); | self->NodeUpdateGS(0.f); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_SCALE_LOCAL: | case MATHUTILS_VEC_CB_SCALE_LOCAL: | ||||
| self->NodeSetLocalScale(MT_Point3(bmo->data)); | self->NodeSetLocalScale(MT_Vector3(bmo->data)); | ||||
| self->NodeUpdateGS(0.f); | self->NodeUpdateGS(0.f); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_SCALE_GLOBAL: | case MATHUTILS_VEC_CB_SCALE_GLOBAL: | ||||
| PyErr_SetString(PyExc_AttributeError, "KX_GameObject.worldScale is read-only"); | self->NodeSetWorldScale(MT_Vector3(bmo->data)); | ||||
| return -1; | self->NodeUpdateGS(0.0f); | ||||
| break; | |||||
| case MATHUTILS_VEC_CB_INERTIA_LOCAL: | case MATHUTILS_VEC_CB_INERTIA_LOCAL: | ||||
| /* read only */ | /* read only */ | ||||
| break; | break; | ||||
| Context not available. | |||||
| self->SetObjectColor(MT_Vector4(bmo->data)); | self->SetObjectColor(MT_Vector4(bmo->data)); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_LINVEL_LOCAL: | case MATHUTILS_VEC_CB_LINVEL_LOCAL: | ||||
| self->setLinearVelocity(MT_Point3(bmo->data),true); | self->setLinearVelocity(MT_Vector3(bmo->data),true); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_LINVEL_GLOBAL: | case MATHUTILS_VEC_CB_LINVEL_GLOBAL: | ||||
| self->setLinearVelocity(MT_Point3(bmo->data),false); | self->setLinearVelocity(MT_Vector3(bmo->data),false); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_ANGVEL_LOCAL: | case MATHUTILS_VEC_CB_ANGVEL_LOCAL: | ||||
| self->setAngularVelocity(MT_Point3(bmo->data),true); | self->setAngularVelocity(MT_Vector3(bmo->data),true); | ||||
| break; | break; | ||||
| case MATHUTILS_VEC_CB_ANGVEL_GLOBAL: | case MATHUTILS_VEC_CB_ANGVEL_GLOBAL: | ||||
| self->setAngularVelocity(MT_Point3(bmo->data),false); | self->setAngularVelocity(MT_Vector3(bmo->data),false); | ||||
| break; | break; | ||||
| } | } | ||||
| Context not available. | |||||
| {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, | {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, | ||||
| {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, | {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, | ||||
| {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O}, | {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O}, | ||||
| {"suspendPhysics", (PyCFunction)KX_GameObject::sPySuspendPhysics, METH_NOARGS}, | |||||
| {"restorePhysics", (PyCFunction)KX_GameObject::sPyRestorePhysics,METH_NOARGS}, | |||||
| {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS}, | {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS}, | ||||
| {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS}, | {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS}, | ||||
| {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS}, | {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS}, | ||||
| Context not available. | |||||
| {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_VARARGS}, | {"replaceMesh",(PyCFunction) KX_GameObject::sPyReplaceMesh, METH_VARARGS}, | ||||
| {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS}, | {"endObject",(PyCFunction) KX_GameObject::sPyEndObject, METH_NOARGS}, | ||||
| {"reinstancePhysicsMesh", (PyCFunction)KX_GameObject::sPyReinstancePhysicsMesh,METH_VARARGS}, | {"reinstancePhysicsMesh", (PyCFunction)KX_GameObject::sPyReinstancePhysicsMesh,METH_VARARGS}, | ||||
| {"replacePhysicsShape", (PyCFunction)KX_GameObject::sPyReplacePhysicsShape, METH_O}, | |||||
| KX_PYMETHODTABLE(KX_GameObject, rayCastTo), | KX_PYMETHODTABLE(KX_GameObject, rayCastTo), | ||||
| KX_PYMETHODTABLE(KX_GameObject, rayCast), | KX_PYMETHODTABLE(KX_GameObject, rayCast), | ||||
| KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo), | KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo), | ||||
| Context not available. | |||||
| }; | }; | ||||
| PyAttributeDef KX_GameObject::Attributes[] = { | PyAttributeDef KX_GameObject::Attributes[] = { | ||||
| KX_PYATTRIBUTE_INT_RO("currentLodLevel", KX_GameObject, m_currentLodLevel), | KX_PYATTRIBUTE_SHORT_RO("currentLodLevel", KX_GameObject, m_currentLodLevel), | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name), | KX_PYATTRIBUTE_RW_FUNCTION("lodManager", KX_GameObject, pyattr_get_lodManager, pyattr_set_lodManager), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("name", KX_GameObject, pyattr_get_name, pyattr_set_name), | |||||
| KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), | KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("groupMembers", KX_GameObject, pyattr_get_group_members), | KX_PYATTRIBUTE_RO_FUNCTION("groupMembers", KX_GameObject, pyattr_get_group_members), | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("groupObject", KX_GameObject, pyattr_get_group_object), | KX_PYATTRIBUTE_RO_FUNCTION("groupObject", KX_GameObject, pyattr_get_group_object), | ||||
| Context not available. | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max), | KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("angularVelocityMin", KX_GameObject, pyattr_get_ang_vel_min, pyattr_set_ang_vel_min), | KX_PYATTRIBUTE_RW_FUNCTION("angularVelocityMin", KX_GameObject, pyattr_get_ang_vel_min, pyattr_set_ang_vel_min), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("angularVelocityMax", KX_GameObject, pyattr_get_ang_vel_max, pyattr_set_ang_vel_max), | KX_PYATTRIBUTE_RW_FUNCTION("angularVelocityMax", KX_GameObject, pyattr_get_ang_vel_max, pyattr_set_ang_vel_max), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("layer", KX_GameObject, pyattr_get_layer, pyattr_set_layer), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), | KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("record_animation", KX_GameObject, pyattr_get_record_animation, pyattr_set_record_animation), | KX_PYATTRIBUTE_RO_FUNCTION("culled", KX_GameObject, pyattr_get_culled), | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("cullingBox", KX_GameObject, pyattr_get_cullingBox), | |||||
| KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder), | KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("position", KX_GameObject, pyattr_get_worldPosition, pyattr_set_localPosition), | 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_RO_FUNCTION("localInertia", KX_GameObject, pyattr_get_localInertia), | ||||
| Context not available. | |||||
| KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict), | KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("color", KX_GameObject, pyattr_get_obcolor, pyattr_set_obcolor), | KX_PYATTRIBUTE_RW_FUNCTION("color", KX_GameObject, pyattr_get_obcolor, pyattr_set_obcolor), | ||||
| KX_PYATTRIBUTE_RW_FUNCTION("debug", KX_GameObject, pyattr_get_debug, pyattr_set_debug), | KX_PYATTRIBUTE_RW_FUNCTION("debug", KX_GameObject, pyattr_get_debug, pyattr_set_debug), | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("components", KX_GameObject, pyattr_get_components), | |||||
| KX_PYATTRIBUTE_RW_FUNCTION("debugRecursive", KX_GameObject, pyattr_get_debugRecursive, pyattr_set_debugRecursive), | KX_PYATTRIBUTE_RW_FUNCTION("debugRecursive", KX_GameObject, pyattr_get_debugRecursive, pyattr_set_debugRecursive), | ||||
| /* experimental, don't rely on these yet */ | /* experimental, don't rely on these yet */ | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("sensors", KX_GameObject, pyattr_get_sensors), | KX_PYATTRIBUTE_RO_FUNCTION("sensors", KX_GameObject, pyattr_get_sensors), | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("controllers", KX_GameObject, pyattr_get_controllers), | KX_PYATTRIBUTE_RO_FUNCTION("controllers", KX_GameObject, pyattr_get_controllers), | ||||
| KX_PYATTRIBUTE_RO_FUNCTION("actuators", KX_GameObject, pyattr_get_actuators), | KX_PYATTRIBUTE_RO_FUNCTION("actuators", KX_GameObject, pyattr_get_actuators), | ||||
| {NULL} //Sentinel | KX_PYATTRIBUTE_NULL //Sentinel | ||||
| }; | }; | ||||
| PyObject *KX_GameObject::PyReplaceMesh(PyObject *args) | PyObject *KX_GameObject::PyReplaceMesh(PyObject *args) | ||||
| { | { | ||||
| KX_Scene *scene = KX_GetActiveScene(); | |||||
| SCA_LogicManager *logicmgr = GetScene()->GetLogicManager(); | SCA_LogicManager *logicmgr = GetScene()->GetLogicManager(); | ||||
| PyObject *value; | PyObject *value; | ||||
| Context not available. | |||||
| if (!ConvertPythonToMesh(logicmgr, value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject")) | if (!ConvertPythonToMesh(logicmgr, value, &new_mesh, false, "gameOb.replaceMesh(value): KX_GameObject")) | ||||
| return NULL; | return NULL; | ||||
| scene->ReplaceMesh(this, new_mesh, (bool)use_gfx, (bool)use_phys); | GetScene()->ReplaceMesh(this, new_mesh, (bool)use_gfx, (bool)use_phys); | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| PyObject *KX_GameObject::PyEndObject() | PyObject *KX_GameObject::PyEndObject() | ||||
| { | { | ||||
| KX_Scene* scene = GetScene(); | GetScene()->DelayedRemoveObject(this); | ||||
| scene->DelayedRemoveObject(this); | |||||
| Py_RETURN_NONE; | |||||
| Py_RETURN_NONE; | |||||
| } | } | ||||
| PyObject *KX_GameObject::PyReinstancePhysicsMesh(PyObject *args) | PyObject *KX_GameObject::PyReinstancePhysicsMesh(PyObject *args) | ||||
| Context not available. | |||||
| KX_GameObject *gameobj= NULL; | KX_GameObject *gameobj= NULL; | ||||
| RAS_MeshObject *mesh= NULL; | RAS_MeshObject *mesh= NULL; | ||||
| SCA_LogicManager *logicmgr = GetScene()->GetLogicManager(); | SCA_LogicManager *logicmgr = GetScene()->GetLogicManager(); | ||||
| int dupli = 0; | |||||
| PyObject *gameobj_py= NULL; | PyObject *gameobj_py= NULL; | ||||
| PyObject *mesh_py= NULL; | PyObject *mesh_py= NULL; | ||||
| if ( !PyArg_ParseTuple(args,"|OO:reinstancePhysicsMesh",&gameobj_py, &mesh_py) || | if (!PyArg_ParseTuple(args,"|OOi:reinstancePhysicsMesh",&gameobj_py, &mesh_py, &dupli) || | ||||
| (gameobj_py && !ConvertPythonToGameObject(logicmgr, gameobj_py, &gameobj, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject")) || | (gameobj_py && !ConvertPythonToGameObject(logicmgr, gameobj_py, &gameobj, true, "gameOb.reinstancePhysicsMesh(obj, mesh, dupli): KX_GameObject")) || | ||||
| (mesh_py && !ConvertPythonToMesh(logicmgr, mesh_py, &mesh, true, "gameOb.reinstancePhysicsMesh(obj, mesh): KX_GameObject")) | (mesh_py && !ConvertPythonToMesh(logicmgr, mesh_py, &mesh, true, "gameOb.reinstancePhysicsMesh(obj, mesh, dupli): KX_GameObject"))) | ||||
| ) { | { | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| /* gameobj and mesh can be NULL */ | /* gameobj and mesh can be NULL */ | ||||
| if (GetPhysicsController() && GetPhysicsController()->ReinstancePhysicsShape(gameobj, mesh)) | if (GetPhysicsController() && GetPhysicsController()->ReinstancePhysicsShape(gameobj, mesh, dupli)) | ||||
| Py_RETURN_TRUE; | Py_RETURN_TRUE; | ||||
| Py_RETURN_FALSE; | Py_RETURN_FALSE; | ||||
| } | } | ||||
| PyObject *KX_GameObject::PyReplacePhysicsShape(PyObject *value) | |||||
| { | |||||
| KX_GameObject *gameobj; | |||||
| SCA_LogicManager *logicmgr = GetScene()->GetLogicManager(); | |||||
| if (!ConvertPythonToGameObject(logicmgr, value, &gameobj, false, "gameOb.replacePhysicsShape(obj): KX_GameObject")) { | |||||
| return NULL; | |||||
| } | |||||
| if (!GetPhysicsController() || !gameobj->GetPhysicsController()) { | |||||
| PyErr_SetString(PyExc_AttributeError, "gameOb.replacePhysicsShape(obj): function only available for objects with collisions enabled"); | |||||
| return NULL; | |||||
| } | |||||
| GetPhysicsController()->ReplacePhysicsShape(gameobj->GetPhysicsController()); | |||||
| Py_RETURN_NONE; | |||||
| } | |||||
| static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) | static PyObject *Map_GetItem(PyObject *self_v, PyObject *item) | ||||
| { | { | ||||
| KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); | KX_GameObject* self = static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); | ||||
| Context not available. | |||||
| PyObject *KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_GameObject::pyattr_get_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | ||||
| return PyUnicode_From_STR_String(self->GetName()); | return PyUnicode_FromStdString(self->GetName()); | ||||
| } | |||||
| int KX_GameObject::pyattr_set_name(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| { | |||||
| KX_GameObject *self = static_cast<KX_GameObject *>(self_v); | |||||
| if (!PyUnicode_Check(value)) { | |||||
| PyErr_SetString(PyExc_TypeError, "gameOb.name = str: KX_GameObject, expected a string"); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| std::string newname = std::string(_PyUnicode_AsString(value)); | |||||
| std::string oldname = self->GetName(); | |||||
| SCA_LogicManager *manager = self->GetScene()->GetLogicManager(); | |||||
| // If true, it mean that's this game object is not a replica and was added at conversion time. | |||||
| if (manager->GetGameObjectByName(oldname) == self) { | |||||
| /* Two non-replica objects can have the same name bacause these objects are register in the | |||||
| * logic manager and that the result of GetGameObjectByName will be undefined. */ | |||||
| if (manager->GetGameObjectByName(newname)) { | |||||
| PyErr_Format(PyExc_TypeError, "gameOb.name = str: name %s is already used by an other non-replica game object", oldname.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| // Unregister the old name. | |||||
| manager->UnregisterGameObjectName(oldname); | |||||
| // Register the object under the new name. | |||||
| manager->RegisterGameObjectName(newname, self); | |||||
| } | |||||
| // Change the name | |||||
| self->SetName(newname); | |||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | } | ||||
| PyObject *KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| Context not available. | |||||
| KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | ||||
| // Only objects with a physics controller should have collision callbacks | // Only objects with a physics controller should have collision callbacks | ||||
| if (!self->GetPhysicsController()) { | PYTHON_CHECK_PHYSICS_CONTROLLER(self, "collisionCallbacks", NULL); | ||||
| PyErr_SetString(PyExc_AttributeError, "KX_GameObject.collisionCallbacks: attribute only available for objects with collisions enabled"); | |||||
| return NULL; | |||||
| } | |||||
| // Return the existing callbacks | // Return the existing callbacks | ||||
| if (self->m_collisionCallbacks == NULL) | if (self->m_collisionCallbacks == NULL) | ||||
| { | { | ||||
| self->m_collisionCallbacks = PyList_New(0); | self->m_collisionCallbacks = PyList_New(0); | ||||
| // Subscribe to collision update from KX_TouchManager | // Subscribe to collision update from KX_CollisionEventManager | ||||
| self->RegisterCollisionCallbacks(); | self->RegisterCollisionCallbacks(); | ||||
| } | } | ||||
| Py_INCREF(self->m_collisionCallbacks); | Py_INCREF(self->m_collisionCallbacks); | ||||
| Context not available. | |||||
| KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | ||||
| // Only objects with a physics controller should have collision callbacks | // Only objects with a physics controller should have collision callbacks | ||||
| if (!self->GetPhysicsController()) { | PYTHON_CHECK_PHYSICS_CONTROLLER(self, "collisionCallbacks", PY_SET_ATTR_FAIL); | ||||
| PyErr_SetString(PyExc_AttributeError, "KX_GameObject.collisionCallbacks: attribute only available for objects with collisions enabled"); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| if (!PyList_CheckExact(value)) | if (!PyList_CheckExact(value)) | ||||
| { | { | ||||
| Context not available. | |||||
| KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | ||||
| // Only objects with a physics controller can be suspended | // Only objects with a physics controller can be suspended | ||||
| if (!self->GetPhysicsController()) { | PYTHON_CHECK_PHYSICS_CONTROLLER(self, attrdef->m_name, NULL); | ||||
| PyErr_SetString(PyExc_AttributeError, "This object has not Physics Controller"); | |||||
| return NULL; | |||||
| } | |||||
| return PyBool_FromLong(self->IsDynamicsSuspended()); | return PyBool_FromLong(self->IsDynamicsSuspended()); | ||||
| } | } | ||||
| Context not available. | |||||
| } | } | ||||
| PyObject *KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_GameObject::pyattr_get_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | KX_GameObject *self = static_cast<KX_GameObject *>(self_v); | ||||
| return PyBool_FromLong(self->GetVisible()); | return PyLong_FromLong(self->GetLayer()); | ||||
| } | } | ||||
| int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | #define MAX_LAYERS ((1 << 20) - 1) | ||||
| int KX_GameObject::pyattr_set_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| { | { | ||||
| KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | KX_GameObject *self = static_cast<KX_GameObject *>(self_v); | ||||
| int param = PyObject_IsTrue( value ); | int layer = PyLong_AsLong(value); | ||||
| if (param == -1) { | |||||
| PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False"); | if (layer == -1 && PyErr_Occurred()) { | ||||
| PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| } | } | ||||
| self->SetVisible(param, false); | if (layer < 1) { | ||||
| self->UpdateBuckets(false); | PyErr_Format(PyExc_TypeError, "expected an integer greater than 1 for attribute \"%s\"", attrdef->m_name.c_str()); | ||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| else if (layer > MAX_LAYERS) { | |||||
| PyErr_Format(PyExc_TypeError, "expected an integer less than %i for attribute \"%s\"", MAX_LAYERS, attrdef->m_name.c_str()); | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| self->SetLayer(layer); | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| #undef MAX_LAYERS | |||||
| PyObject *KX_GameObject::pyattr_get_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | ||||
| return PyBool_FromLong(self->IsRecordAnimation()); | return PyBool_FromLong(self->GetVisible()); | ||||
| } | } | ||||
| int KX_GameObject::pyattr_set_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| { | { | ||||
| KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | ||||
| int param = PyObject_IsTrue(value); | int param = PyObject_IsTrue( value ); | ||||
| if (param == -1) { | if (param == -1) { | ||||
| PyErr_SetString(PyExc_AttributeError, "gameOb.record_animation = bool: KX_GameObject, expected boolean"); | PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False"); | ||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| } | } | ||||
| self->SetRecordAnimation(param); | self->SetVisible(param, false); | ||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| PyObject *KX_GameObject::pyattr_get_culled(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| KX_GameObject *self = static_cast<KX_GameObject *>(self_v); | |||||
| return PyBool_FromLong(self->GetCulled()); | |||||
| } | |||||
| PyObject *KX_GameObject::pyattr_get_cullingBox(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| KX_GameObject *self = static_cast<KX_GameObject *>(self_v); | |||||
| return (new KX_BoundingBox(self))->NewProxy(true); | |||||
| } | |||||
| PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| Context not available. | |||||
| int KX_GameObject::pyattr_set_worldPosition(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); | KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | ||||
| MT_Point3 pos; | MT_Vector3 pos; | ||||
| if (!PyVecTo(value, pos)) | if (!PyVecTo(value, pos)) | ||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| Context not available. | |||||
| int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | 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); | KX_GameObject* self = static_cast<KX_GameObject*>(self_v); | ||||
| MT_Point3 pos; | MT_Vector3 pos; | ||||
| if (!PyVecTo(value, pos)) | if (!PyVecTo(value, pos)) | ||||
| return PY_SET_ATTR_FAIL; | return PY_SET_ATTR_FAIL; | ||||
| Context not available. | |||||
| temp.getValue(*transform); | temp.getValue(*transform); | ||||
| mat4_to_loc_rot_size(loc, rot, size, transform); | mat4_to_loc_rot_size(loc, rot, size, transform); | ||||
| self->NodeSetLocalPosition(MT_Point3(loc)); | self->NodeSetLocalPosition(MT_Vector3(loc)); | ||||
| //MT_Matrix3x3's constructor expects a 4x4 matrix | //MT_Matrix3x3's constructor expects a 4x4 matrix | ||||
| orientation = MT_Matrix3x3(); | orientation = MT_Matrix3x3(); | ||||
| Context not available. | |||||
| temp.getValue(*transform); | temp.getValue(*transform); | ||||
| mat4_to_loc_rot_size(loc, rot, size, transform); | mat4_to_loc_rot_size(loc, rot, size, transform); | ||||
| self->NodeSetWorldPosition(MT_Point3(loc)); | self->NodeSetWorldPosition(MT_Vector3(loc)); | ||||
| //MT_Matrix3x3's constructor expects a 4x4 matrix | //MT_Matrix3x3's constructor expects a 4x4 matrix | ||||
| orientation = MT_Matrix3x3(); | orientation = MT_Matrix3x3(); | ||||
| Context not available. | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| PyObject* KX_GameObject::pyattr_get_components(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| KX_GameObject *self = static_cast<KX_GameObject *>(self_v); | |||||
| CListValue *components = self->GetComponents(); | |||||
| return components ? components->GetProxy() : (new CListValue())->NewProxy(true); | |||||
| } | |||||
| static int kx_game_object_get_sensors_size_cb(void *self_v) | static int kx_game_object_get_sensors_size_cb(void *self_v) | ||||
| { | { | ||||
| return ((KX_GameObject *)self_v)->GetSensors().size(); | return ((KX_GameObject *)self_v)->GetSensors().size(); | ||||
| Context not available. | |||||
| return ((KX_GameObject *)self_v)->GetSensors()[index]->GetProxy(); | return ((KX_GameObject *)self_v)->GetSensors()[index]->GetProxy(); | ||||
| } | } | ||||
| static const char *kx_game_object_get_sensors_item_name_cb(void *self_v, int index) | static const std::string kx_game_object_get_sensors_item_name_cb(void *self_v, int index) | ||||
| { | { | ||||
| return ((KX_GameObject *)self_v)->GetSensors()[index]->GetName().ReadPtr(); | return ((KX_GameObject *)self_v)->GetSensors()[index]->GetName(); | ||||
| } | } | ||||
| /* These are experimental! */ | /* These are experimental! */ | ||||
| Context not available. | |||||
| return ((KX_GameObject *)self_v)->GetControllers()[index]->GetProxy(); | return ((KX_GameObject *)self_v)->GetControllers()[index]->GetProxy(); | ||||
| } | } | ||||
| static const char *kx_game_object_get_controllers_item_name_cb(void *self_v, int index) | static const std::string kx_game_object_get_controllers_item_name_cb(void *self_v, int index) | ||||
| { | { | ||||
| return ((KX_GameObject *)self_v)->GetControllers()[index]->GetName().ReadPtr(); | return ((KX_GameObject *)self_v)->GetControllers()[index]->GetName(); | ||||
| } | } | ||||
| PyObject *KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| Context not available. | |||||
| return ((KX_GameObject *)self_v)->GetActuators()[index]->GetProxy(); | return ((KX_GameObject *)self_v)->GetActuators()[index]->GetProxy(); | ||||
| } | } | ||||
| static const char *kx_game_object_get_actuators_item_name_cb(void *self_v, int index) | static const std::string kx_game_object_get_actuators_item_name_cb(void *self_v, int index) | ||||
| { | { | ||||
| return ((KX_GameObject *)self_v)->GetActuators()[index]->GetName().ReadPtr(); | return ((KX_GameObject *)self_v)->GetActuators()[index]->GetName(); | ||||
| } | } | ||||
| PyObject *KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| Context not available. | |||||
| PyObject *KX_GameObject::pyattr_get_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_GameObject::pyattr_get_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_Scene *scene = KX_GetActiveScene(); | |||||
| KX_GameObject *self = static_cast<KX_GameObject*>(self_v); | KX_GameObject *self = static_cast<KX_GameObject*>(self_v); | ||||
| return PyBool_FromLong(scene->ObjectInDebugList(self)); | return PyBool_FromLong(self->GetScene()->ObjectInDebugList(self)); | ||||
| } | } | ||||
| int KX_GameObject::pyattr_set_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | int KX_GameObject::pyattr_set_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| Context not available. | |||||
| PyObject *KX_GameObject::pyattr_get_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | PyObject *KX_GameObject::pyattr_get_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | ||||
| { | { | ||||
| KX_Scene *scene = KX_GetActiveScene(); | |||||
| KX_GameObject *self = static_cast<KX_GameObject*>(self_v); | KX_GameObject *self = static_cast<KX_GameObject*>(self_v); | ||||
| return PyBool_FromLong(scene->ObjectInDebugList(self)); | return PyBool_FromLong(self->GetScene()->ObjectInDebugList(self)); | ||||
| } | } | ||||
| int KX_GameObject::pyattr_set_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | int KX_GameObject::pyattr_set_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | ||||
| Context not available. | |||||
| return PY_SET_ATTR_SUCCESS; | return PY_SET_ATTR_SUCCESS; | ||||
| } | } | ||||
| PyObject *KX_GameObject::pyattr_get_lodManager(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) | |||||
| { | |||||
| KX_GameObject *self = static_cast<KX_GameObject *>(self_v); | |||||
| return (self->m_lodManager) ? self->m_lodManager->GetProxy() : Py_None; | |||||
| } | |||||
| int KX_GameObject::pyattr_set_lodManager(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) | |||||
| { | |||||
| KX_GameObject *self = static_cast<KX_GameObject*>(self_v); | |||||
| KX_LodManager *lodManager = NULL; | |||||
| if (!ConvertPythonToLodManager(value, &lodManager, true, "gameobj.lodManager: KX_GameObject")) { | |||||
| return PY_SET_ATTR_FAIL; | |||||
| } | |||||
| self->SetLodManager(lodManager); | |||||
| return PY_SET_ATTR_SUCCESS; | |||||
| } | |||||
| PyObject *KX_GameObject::PyApplyForce(PyObject *args) | PyObject *KX_GameObject::PyApplyForce(PyObject *args) | ||||
| { | { | ||||
| int local = 0; | int local = 0; | ||||
| Context not available. | |||||
| return NULL; | return NULL; | ||||
| SetVisible(visible ? true:false, recursive ? true:false); | SetVisible(visible ? true:false, recursive ? true:false); | ||||
| UpdateBuckets(recursive ? true:false); | |||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| PyObject *KX_GameObject::PyGetVelocity(PyObject *args) | PyObject *KX_GameObject::PyGetVelocity(PyObject *args) | ||||
| { | { | ||||
| // only can get the velocity if we have a physics object connected to us... | // only can get the velocity if we have a physics object connected to us... | ||||
| MT_Point3 point(0.0f,0.0f,0.0f); | MT_Vector3 point(0.0f,0.0f,0.0f); | ||||
| PyObject *pypos = NULL; | PyObject *pypos = NULL; | ||||
| if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point))) | if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point))) | ||||
| Context not available. | |||||
| PyObject *KX_GameObject::PySetParent(PyObject *args) | PyObject *KX_GameObject::PySetParent(PyObject *args) | ||||
| { | { | ||||
| KX_Scene *scene = KX_GetActiveScene(); | |||||
| SCA_LogicManager *logicmgr = GetScene()->GetLogicManager(); | SCA_LogicManager *logicmgr = GetScene()->GetLogicManager(); | ||||
| PyObject *pyobj; | PyObject *pyobj; | ||||
| KX_GameObject *obj; | KX_GameObject *obj; | ||||
| Context not available. | |||||
| } | } | ||||
| if (!ConvertPythonToGameObject(logicmgr, pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject")) | if (!ConvertPythonToGameObject(logicmgr, pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject")) | ||||
| return NULL; | return NULL; | ||||
| if (obj) | if (obj) | ||||
| this->SetParent(scene, obj, addToCompound, ghost); | SetParent(obj, addToCompound, ghost); | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| PyObject *KX_GameObject::PyRemoveParent() | PyObject *KX_GameObject::PyRemoveParent() | ||||
| { | { | ||||
| KX_Scene *scene = KX_GetActiveScene(); | RemoveParent(); | ||||
| this->RemoveParent(scene); | |||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| PyErr_SetString(PyExc_TypeError, "expected a float"); | PyErr_SetString(PyExc_TypeError, "expected a float"); | ||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| if (m_pPhysicsController) | PYTHON_CHECK_PHYSICS_CONTROLLER(this, "setCollisionMargin", NULL); | ||||
| { | |||||
| m_pPhysicsController->SetMargin(collisionMargin); | m_pPhysicsController->SetMargin(collisionMargin); | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | |||||
| PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller"); | |||||
| return NULL; | |||||
| } | } | ||||
| Context not available. | |||||
| PyObject *pyattach; | PyObject *pyattach; | ||||
| PyObject *pyimpulse; | PyObject *pyimpulse; | ||||
| int local = 0; | int local = 0; | ||||
| if (!m_pPhysicsController) { | PYTHON_CHECK_PHYSICS_CONTROLLER(this, "applyImpulse", NULL); | ||||
| PyErr_SetString(PyExc_RuntimeError, "This object has no physics controller"); | |||||
| return NULL; | |||||
| } | |||||
| if (PyArg_ParseTuple(args, "OO|i:applyImpulse", &pyattach, &pyimpulse, &local)) | if (PyArg_ParseTuple(args, "OO|i:applyImpulse", &pyattach, &pyimpulse, &local)) | ||||
| { | { | ||||
| MT_Point3 attach; | MT_Vector3 attach; | ||||
| MT_Vector3 impulse; | MT_Vector3 impulse; | ||||
| if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse)) | if (PyVecTo(pyattach, attach) && PyVecTo(pyimpulse, impulse)) | ||||
| { | { | ||||
| Context not available. | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| PyObject *KX_GameObject::PySuspendPhysics() | |||||
| { | |||||
| if (GetPhysicsController()) { | |||||
| GetPhysicsController()->SuspendPhysics(); | |||||
| } | |||||
| Py_RETURN_NONE; | |||||
| } | |||||
| PyObject *KX_GameObject::PyRestorePhysics() | |||||
| { | |||||
| if (GetPhysicsController()) { | |||||
| GetPhysicsController()->RestorePhysics(); | |||||
| } | |||||
| Py_RETURN_NONE; | |||||
| } | |||||
| PyObject *KX_GameObject::PySuspendDynamics(PyObject *args) | PyObject *KX_GameObject::PySuspendDynamics(PyObject *args) | ||||
| { | { | ||||
| Context not available. | |||||
| KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo, | KX_PYMETHODDEF_DOC_O(KX_GameObject, getDistanceTo, | ||||
| "getDistanceTo(other): get distance to another point/KX_GameObject") | "getDistanceTo(other): get distance to another point/KX_GameObject") | ||||
| { | { | ||||
| MT_Point3 b; | MT_Vector3 b; | ||||
| if (PyVecTo(value, b)) | if (PyVecTo(value, b)) | ||||
| { | { | ||||
| return PyFloat_FromDouble(NodeGetWorldPosition().distance(b)); | return PyFloat_FromDouble(NodeGetWorldPosition().distance(b)); | ||||
| Context not available. | |||||
| "getVectTo(other): get vector and the distance to another point/KX_GameObject\n" | "getVectTo(other): get vector and the distance to another point/KX_GameObject\n" | ||||
| "Returns a 3-tuple with (distance,worldVector,localVector)\n") | "Returns a 3-tuple with (distance,worldVector,localVector)\n") | ||||
| { | { | ||||
| MT_Point3 toPoint, fromPoint; | MT_Vector3 toPoint, fromPoint; | ||||
| MT_Vector3 toDir, locToDir; | MT_Vector3 toDir, locToDir; | ||||
| MT_Scalar distance; | MT_Scalar distance; | ||||
| Context not available. | |||||
| if (MT_fuzzyZero(distance)) | if (MT_fuzzyZero(distance)) | ||||
| { | { | ||||
| //cout << "getVectTo() Error: Null vector!\n"; | |||||
| locToDir = toDir = MT_Vector3(0.0f,0.0f,0.0f); | locToDir = toDir = MT_Vector3(0.0f,0.0f,0.0f); | ||||
| distance = 0.0f; | distance = 0.0f; | ||||
| } else { | } else { | ||||
| Context not available. | |||||
| struct KX_GameObject::RayCastData | struct KX_GameObject::RayCastData | ||||
| { | { | ||||
| RayCastData(STR_String prop, bool xray, short mask) | RayCastData(std::string prop, bool xray, unsigned int mask) | ||||
| :m_prop(prop), | :m_prop(prop), | ||||
| m_xray(xray), | m_xray(xray), | ||||
| m_mask(mask), | m_mask(mask), | ||||
| Context not available. | |||||
| { | { | ||||
| } | } | ||||
| STR_String m_prop; | std::string m_prop; | ||||
| bool m_xray; | bool m_xray; | ||||
| unsigned short m_mask; | unsigned int m_mask; | ||||
| KX_GameObject *m_hitObject; | KX_GameObject *m_hitObject; | ||||
| }; | }; | ||||
| Context not available. | |||||
| // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit | // if X-ray option is selected, the unwnted objects were not tested, so get here only with true hit | ||||
| // if not, all objects were tested and the front one may not be the correct one. | // if not, all objects were tested and the front one may not be the correct one. | ||||
| if ((rayData->m_xray || rayData->m_prop.Length() == 0 || hitKXObj->GetProperty(rayData->m_prop) != NULL) && | if ((rayData->m_xray || rayData->m_prop.size() == 0 || hitKXObj->GetProperty(rayData->m_prop) != NULL) && | ||||
| hitKXObj->GetUserCollisionGroup() & rayData->m_mask) | hitKXObj->GetUserCollisionGroup() & rayData->m_mask) | ||||
| { | { | ||||
| rayData->m_hitObject = hitKXObj; | rayData->m_hitObject = hitKXObj; | ||||
| Context not available. | |||||
| { | { | ||||
| // Unknown type of object, skip it. | // Unknown type of object, skip it. | ||||
| // Should not occur as the sensor objects are filtered in RayTest() | // Should not occur as the sensor objects are filtered in RayTest() | ||||
| printf("Invalid client type %d found in ray casting\n", client->m_type); | CM_Error("invalid client type " << client->m_type << " found in ray casting"); | ||||
| return false; | return false; | ||||
| } | } | ||||
| // if X-Ray option is selected, skip object that don't match the criteria as we see through them | // if X-Ray option is selected, skip object that don't match the criteria as we see through them | ||||
| // if not, test all objects because we don't know yet which one will be on front | // if not, test all objects because we don't know yet which one will be on front | ||||
| if ((!rayData->m_xray || rayData->m_prop.Length() == 0 || hitKXObj->GetProperty(rayData->m_prop) != NULL) && | if ((!rayData->m_xray || rayData->m_prop.size() == 0 || hitKXObj->GetProperty(rayData->m_prop) != NULL) && | ||||
| hitKXObj->GetUserCollisionGroup() & rayData->m_mask) | hitKXObj->GetUserCollisionGroup() & rayData->m_mask) | ||||
| { | { | ||||
| return true; | return true; | ||||
| Context not available. | |||||
| " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n" | " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to other\n" | ||||
| " other = 3-tuple or object reference") | " other = 3-tuple or object reference") | ||||
| { | { | ||||
| MT_Point3 toPoint; | MT_Vector3 toPoint; | ||||
| PyObject *pyarg; | PyObject *pyarg; | ||||
| float dist = 0.0f; | float dist = 0.0f; | ||||
| char *propName = NULL; | const char *propName = ""; | ||||
| SCA_LogicManager *logicmgr = GetScene()->GetLogicManager(); | SCA_LogicManager *logicmgr = GetScene()->GetLogicManager(); | ||||
| if (!PyArg_ParseTuple(args,"O|fs:rayCastTo", &pyarg, &dist, &propName)) { | if (!PyArg_ParseTuple(args,"O|fs:rayCastTo", &pyarg, &dist, &propName)) { | ||||
| Context not available. | |||||
| return NULL; | return NULL; | ||||
| } | } | ||||
| } | } | ||||
| MT_Point3 fromPoint = NodeGetWorldPosition(); | MT_Vector3 fromPoint = NodeGetWorldPosition(); | ||||
| if (dist != 0.0f) | if (dist != 0.0f) | ||||
| toPoint = fromPoint + dist * (toPoint-fromPoint).safe_normalized(); | toPoint = fromPoint + dist * (toPoint-fromPoint).safe_normalized(); | ||||
| Context not available. | |||||
| " prop on, xray off: return closest hit if it matches prop, no hit otherwise\n" | " prop on, xray off: return closest hit if it matches prop, no hit otherwise\n" | ||||
| " prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray\n") | " prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray\n") | ||||
| { | { | ||||
| MT_Point3 toPoint; | MT_Vector3 toPoint; | ||||
| MT_Point3 fromPoint; | MT_Vector3 fromPoint; | ||||
| PyObject *pyto; | PyObject *pyto; | ||||
| PyObject *pyfrom = NULL; | PyObject *pyfrom = NULL; | ||||
| float dist = 0.0f; | float dist = 0.0f; | ||||
| char *propName = NULL; | const char *propName = ""; | ||||
| KX_GameObject *other; | KX_GameObject *other; | ||||
| int face=0, xray=0, poly=0; | int face=0, xray=0, poly=0; | ||||
| int mask = (1 << OB_MAX_COL_MASKS) - 1; | int mask = (1 << OB_MAX_COL_MASKS) - 1; | ||||
| Context not available. | |||||
| { | { | ||||
| if (callback.m_hitMesh) | if (callback.m_hitMesh) | ||||
| { | { | ||||
| KX_MeshProxy *meshProxy = new KX_MeshProxy(callback.m_hitMesh); | |||||
| // if this field is set, then we can trust that m_hitPolygon is a valid polygon | // if this field is set, then we can trust that m_hitPolygon is a valid polygon | ||||
| RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon); | RAS_Polygon* polygon = callback.m_hitMesh->GetPolygon(callback.m_hitPolygon); | ||||
| KX_PolyProxy* polyproxy = new KX_PolyProxy(callback.m_hitMesh, polygon); | KX_PolyProxy* polyproxy = new KX_PolyProxy(meshProxy, callback.m_hitMesh, polygon); | ||||
| PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true)); | PyTuple_SET_ITEM(returnValue, 3, polyproxy->NewProxy(true)); | ||||
| if (poly == 2) | if (poly == 2) | ||||
| { | { | ||||
| Context not available. | |||||
| "body = Message body (string)" | "body = Message body (string)" | ||||
| "to = Name of object to send the message to") | "to = Name of object to send the message to") | ||||
| { | { | ||||
| KX_Scene *scene = KX_GetActiveScene(); | |||||
| char* subject; | char* subject; | ||||
| char* body = (char *)""; | char* body = (char *)""; | ||||
| char* to = (char *)""; | char* to = (char *)""; | ||||
| const STR_String& from = GetName(); | |||||
| if (!PyArg_ParseTuple(args, "s|ss:sendMessage", &subject, &body, &to)) | if (!PyArg_ParseTuple(args, "s|ss:sendMessage", &subject, &body, &to)) | ||||
| return NULL; | return NULL; | ||||
| scene->GetNetworkScene()->SendMessage(to, from, subject, body); | GetScene()->GetNetworkMessageScene()->SendMessage(to, this, subject, body); | ||||
| Py_RETURN_NONE; | Py_RETURN_NONE; | ||||
| } | } | ||||
| Context not available. | |||||
| { | { | ||||
| if (layer < 0 || layer >= MAX_ACTION_LAYERS) | if (layer < 0 || layer >= MAX_ACTION_LAYERS) | ||||
| { | { | ||||
| printf("KX_GameObject.%s(): given layer (%d) is out of range (0 - %d), setting to 0.\n", method_name, layer, MAX_ACTION_LAYERS-1); | CM_PythonFunctionWarning("KX_GameObject", method_name, "given layer (" << layer | ||||
| << ") is out of range (0 - " << (MAX_ACTION_LAYERS - 1) << "), setting to 0."); | |||||
| layer = 0; | layer = 0; | ||||
| } | } | ||||
| } | } | ||||
| Context not available. | |||||
| if (play_mode < 0 || play_mode > BL_Action::ACT_MODE_MAX) | if (play_mode < 0 || play_mode > BL_Action::ACT_MODE_MAX) | ||||
| { | { | ||||
| printf("KX_GameObject.playAction(): given play_mode (%d) is out of range (0 - %d), setting to ACT_MODE_PLAY", play_mode, BL_Action::ACT_MODE_MAX-1); | CM_PythonFunctionWarning("KX_GameObject", "playAction", "given play_mode (" << play_mode << ") is out of range (0 - " | ||||
| << (BL_Action::ACT_MODE_MAX - 1) << "), setting to ACT_MODE_PLAY"); | |||||
| play_mode = BL_Action::ACT_MODE_PLAY; | play_mode = BL_Action::ACT_MODE_PLAY; | ||||
| } | } | ||||
| if (blend_mode < 0 || blend_mode > BL_Action::ACT_BLEND_MAX) | if (blend_mode < 0 || blend_mode > BL_Action::ACT_BLEND_MAX) | ||||
| { | { | ||||
| printf("KX_GameObject.playAction(): given blend_mode (%d) is out of range (0 - %d), setting to ACT_BLEND_BLEND", blend_mode, BL_Action::ACT_BLEND_MAX-1); | CM_PythonFunctionWarning("KX_GameObject", "playAction", "given blend_mode (" << blend_mode << ") is out of range (0 - " | ||||
| << (BL_Action::ACT_BLEND_MAX - 1) << "), setting to ACT_BLEND_BLEND"); | |||||
| blend_mode = BL_Action::ACT_BLEND_BLEND; | blend_mode = BL_Action::ACT_BLEND_BLEND; | ||||
| } | } | ||||
| if (layer_weight < 0.f || layer_weight > 1.f) | if (layer_weight < 0.f || layer_weight > 1.f) | ||||
| { | { | ||||
| printf("KX_GameObject.playAction(): given layer_weight (%f) is out of range (0.0 - 1.0), setting to 0.0", layer_weight); | CM_PythonFunctionWarning("KX_GameObject", "playAction", "given layer_weight (" << layer_weight | ||||
| << ") is out of range (0.0 - 1.0), setting to 0.0"); | |||||
| layer_weight = 0.f; | layer_weight = 0.f; | ||||
| } | } | ||||
| Context not available. | |||||
| layer_check(layer, "getActionName"); | layer_check(layer, "getActionName"); | ||||
| return PyUnicode_FromString(GetActionName(layer)); | return PyUnicode_FromStdString(GetActionName(layer)); | ||||
| } | } | ||||
| KX_PYMETHODDEF_DOC(KX_GameObject, setActionFrame, | KX_PYMETHODDEF_DOC(KX_GameObject, setActionFrame, | ||||
| Context not available. | |||||
| "addDebugProperty(name, visible=1)\n" | "addDebugProperty(name, visible=1)\n" | ||||
| "Added or remove a debug property to the debug list.\n") | "Added or remove a debug property to the debug list.\n") | ||||
| { | { | ||||
| KX_Scene *scene = KX_GetActiveScene(); | KX_Scene *scene = GetScene(); | ||||
| char *name; | char *name; | ||||
| int visible = 1; | int visible = 1; | ||||
| Context not available. | |||||
| } | } | ||||
| if (PyUnicode_Check(value)) { | if (PyUnicode_Check(value)) { | ||||
| *object = (KX_GameObject*)manager->GetGameObjectByName(STR_String( _PyUnicode_AsString(value) )); | *object = (KX_GameObject*)manager->GetGameObjectByName(std::string( _PyUnicode_AsString(value) )); | ||||
| if (*object) { | if (*object) { | ||||
| return true; | return true; | ||||
| } else { | } else { | ||||
| Context not available. | |||||