diff options
author | Antony Riakiotakis <kalast@gmail.com> | 2015-06-10 19:38:23 +0300 |
---|---|---|
committer | Antony Riakiotakis <kalast@gmail.com> | 2015-06-10 19:38:23 +0300 |
commit | 080cf9332bc9d71e0e14326bc8efdf06b738dea1 (patch) | |
tree | e8531a509dca4d8253aa19d89edc68152421f9e5 /source/gameengine/Ketsji | |
parent | 6d495cc4ef071171ff0686b2be898a41e05b8051 (diff) | |
parent | 9676642cc94599b3419c9aaa5cf1aae2fbbd235f (diff) |
Merge branch 'gooseberry' into temp_motionpathstemp_motionpaths
Conflicts:
source/blender/blenkernel/intern/object.c
Diffstat (limited to 'source/gameengine/Ketsji')
32 files changed, 1244 insertions, 568 deletions
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp index a50c07a486a..9bae119107e 100644 --- a/source/gameengine/Ketsji/BL_Action.cpp +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -49,6 +49,7 @@ extern "C" { // Needed for material IPOs #include "BKE_material.h" #include "DNA_material_types.h" +#include "DNA_scene_types.h" } #include "MEM_guardedalloc.h" @@ -162,6 +163,14 @@ bool BL_Action::Play(const char* name, m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); + // World + sg_contr = BL_CreateWorldIPO(m_action, kxscene->GetBlenderScene()->world, kxscene->GetSceneConverter()); + if (sg_contr) { + m_sg_contr_list.push_back(sg_contr); + m_obj->GetSGNode()->AddSGController(sg_contr); + sg_contr->SetObject(m_obj->GetSGNode()); + } + // Try obcolor sg_contr = BL_CreateObColorIPO(m_action, m_obj, kxscene->GetSceneConverter()); if (sg_contr) { diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index 58739e7ef81..e1a28961a68 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -203,9 +203,21 @@ void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap) glBindTexture(GL_TEXTURE_2D, mTexture ); if ( mipmap ) { + int i; + ImBuf *ibuf; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix ); + + ibuf = IMB_allocFromBuffer(pix, NULL, x, y); + + IMB_makemipmap(ibuf, true); + + for (i = 0; i < ibuf->miptot; i++) { + ImBuf *mip = IMB_getmipmap(ibuf, i); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } + IMB_freeImBuf(ibuf); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -245,9 +257,17 @@ void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap) glBindTexture(GL_TEXTURE_2D, mTexture ); if ( mipmap ) { + int i; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect ); + + IMB_makemipmap(ibuf, true); + + for (i = 0; i < ibuf->miptot; i++) { + ImBuf *mip = IMB_getmipmap(ibuf, i); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 9f0b582045f..7ec2673bf1f 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -94,6 +94,21 @@ void KX_BlenderMaterial::Initialize( ((data->ras_mode &TEX)), game ); + Material *ma = data->material; + + // Save material data to restore on exit + mSavedData.r = ma->r; + mSavedData.g = ma->g; + mSavedData.b = ma->b; + mSavedData.a = ma->alpha; + mSavedData.specr = ma->specr; + mSavedData.specg = ma->specg; + mSavedData.specb = ma->specb; + mSavedData.spec = ma->spec; + mSavedData.ref = ma->ref; + mSavedData.hardness = ma->har; + mSavedData.emit = ma->emit; + mMaterial = data; mShader = 0; mBlenderShader = 0; @@ -124,6 +139,20 @@ void KX_BlenderMaterial::Initialize( KX_BlenderMaterial::~KX_BlenderMaterial() { + Material *ma = mMaterial->material; + // Restore Blender material data + ma->r = mSavedData.r; + ma->g = mSavedData.g; + ma->b = mSavedData.b; + ma->alpha = mSavedData.a; + ma->specr = mSavedData.specr; + ma->specg = mSavedData.specg; + ma->specb = mSavedData.specb; + ma->spec = mSavedData.spec; + ma->ref = mSavedData.ref; + ma->har = mSavedData.hardness; + ma->emit = mSavedData.emit; + // cleanup work if (mConstructed) // clean only if material was actually used @@ -793,17 +822,19 @@ void KX_BlenderMaterial::UpdateIPO( ) { // only works one deep now - mMaterial->speccolor[0] = (float)(specrgb)[0]; - mMaterial->speccolor[1] = (float)(specrgb)[1]; - mMaterial->speccolor[2] = (float)(specrgb)[2]; - mMaterial->matcolor[0] = (float)(rgba[0]); - mMaterial->matcolor[1] = (float)(rgba[1]); - mMaterial->matcolor[2] = (float)(rgba[2]); - mMaterial->alpha = (float)(alpha); - mMaterial->hard = (float)(hard); - mMaterial->emit = (float)(emit); - mMaterial->spec_f = (float)(spec); - mMaterial->ref = (float)(ref); + + // GLSL Multitexture Input + mMaterial->material->specr = mMaterial->speccolor[0] = (float)(specrgb)[0]; + mMaterial->material->specg = mMaterial->speccolor[1] = (float)(specrgb)[1]; + mMaterial->material->specb = mMaterial->speccolor[2] = (float)(specrgb)[2]; + mMaterial->material->r = mMaterial->matcolor[0] = (float)(rgba[0]); + mMaterial->material->g = mMaterial->matcolor[1] = (float)(rgba[1]); + mMaterial->material->b = mMaterial->matcolor[2] = (float)(rgba[2]); + mMaterial->material->alpha = mMaterial->alpha = (float)(rgba[3]); + mMaterial->material->har = mMaterial->hard = (float)(hard); + mMaterial->material->emit = mMaterial->emit = (float)(emit); + mMaterial->material->spec = mMaterial->spec_f = (float)(spec); + mMaterial->material->ref = mMaterial->ref = (float)(ref); } void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index b7c64215eaf..23921588d6a 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -134,6 +134,15 @@ private: bool mConstructed; // if false, don't clean on exit int mLightLayer; + struct { + float r, g, b, a; + float specr, specg, specb; + float spec; + float ref; + float hardness; + float emit; + } mSavedData; + void InitTextures(); void SetBlenderGLSLShader(); diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index ce2fe5f5ad8..4456345e1d9 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -463,6 +463,7 @@ bool KX_Camera::GetFrustumCulling() const void KX_Camera::EnableViewport(bool viewport) { + InvalidateProjectionMatrix(false); // We need to reset projection matrix m_camdata.m_viewport = viewport; } @@ -885,7 +886,7 @@ int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_D PyObject *KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyObjectFrom(self->GetModelviewMatrix()); + return PyObjectFrom(self->GetWorldToCamera()); } PyObject *KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -994,7 +995,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, GLdouble modelmatrix[16]; GLdouble projmatrix[16]; - MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); m_modelmatrix.getValue(modelmatrix); @@ -1037,7 +1038,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect, GLdouble modelmatrix[16]; GLdouble projmatrix[16]; - MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); m_modelmatrix.getValue(modelmatrix); diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 454c4a54ec1..eeb836c44b8 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -192,7 +192,7 @@ public: void InvalidateProjectionMatrix(bool valid = false); /** Gets the modelview matrix that is used by the rasterizer. - * \warning If the Camera is a dynamic object then this method may return garbage. Use GetCameraToWorld() instead. + * \warning If the Camera is a dynamic object then this method may return garbage. Use GetWorldToCamera() instead. */ const MT_Matrix4x4& GetModelviewMatrix() const; diff --git a/source/gameengine/Ketsji/KX_FontObject.cpp b/source/gameengine/Ketsji/KX_FontObject.cpp index 9789a8294ee..f3b098f407a 100644 --- a/source/gameengine/Ketsji/KX_FontObject.cpp +++ b/source/gameengine/Ketsji/KX_FontObject.cpp @@ -118,7 +118,6 @@ CValue* KX_FontObject::GetReplica() void KX_FontObject::ProcessReplica() { KX_GameObject::ProcessReplica(); - KX_GetActiveScene()->AddFont(this); } int GetFontId(VFont *vfont) diff --git a/source/gameengine/Ketsji/KX_FontObject.h b/source/gameengine/Ketsji/KX_FontObject.h index 209ab6ca69f..bf70eedfde6 100644 --- a/source/gameengine/Ketsji/KX_FontObject.h +++ b/source/gameengine/Ketsji/KX_FontObject.h @@ -54,6 +54,7 @@ public: */ virtual CValue* GetReplica(); virtual void ProcessReplica(); + virtual int GetGameObjectType() { return OBJ_TEXT; } protected: std::vector<STR_String> m_text; diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index c6087ac676d..a23af680104 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -178,6 +178,11 @@ bool KX_GameActuator::Update() // obtain file size: fseek (fp , 0 , SEEK_END); marshal_length = ftell(fp); + if (marshal_length == -1) { + printf("warning: could not read position of '%s'\n", mashal_path); + fclose(fp); + break; + } rewind(fp); marshal_buffer = (char*) malloc (sizeof(char)*marshal_length); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 8d22c9132fd..e77960b99b1 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -47,6 +47,7 @@ #include "KX_MeshProxy.h" #include "KX_PolyProxy.h" #include <stdio.h> // printf +#include <climits> // USHRT_MAX #include "SG_Controller.h" #include "PHY_IGraphicController.h" #include "SG_Node.h" @@ -68,6 +69,7 @@ #include "BL_ActionManager.h" #include "BL_Action.h" +#include "KX_PythonCallBack.h" #include "PyObjectPlus.h" /* python stuff */ #include "BLI_utildefines.h" #include "python_utildefines.h" @@ -91,9 +93,10 @@ KX_GameObject::KX_GameObject( : SCA_IObject(), m_bDyna(false), m_layer(0), + m_currentLodLevel(0), + m_previousLodLevel(0), m_pBlenderObject(NULL), m_pBlenderGroupObject(NULL), - m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), m_objectColor(1.0, 1.0, 1.0, 1.0), @@ -291,6 +294,21 @@ void KX_GameObject::SetDupliGroupObject(KX_GameObject* obj) m_pDupliGroupObject = obj; } +void KX_GameObject::AddConstraint(bRigidBodyJointConstraint *cons) +{ + m_constraints.push_back(cons); +} + +std::vector<bRigidBodyJointConstraint*> KX_GameObject::GetConstraints() +{ + return m_constraints; +} + +void KX_GameObject::ClearConstraints() +{ + m_constraints.clear(); +} + KX_GameObject* KX_GameObject::GetParent() { KX_GameObject* result = NULL; @@ -545,13 +563,26 @@ void KX_GameObject::ActivateGraphicController(bool recurse) } } -void KX_GameObject::SetUserCollisionGroup(short group) +void KX_GameObject::SetUserCollisionGroup(unsigned short group) { m_userCollisionGroup = group; + if (m_pPhysicsController) + m_pPhysicsController->RefreshCollisions(); } -void KX_GameObject::SetUserCollisionMask(short mask) +void KX_GameObject::SetUserCollisionMask(unsigned short mask) { m_userCollisionMask = mask; + if (m_pPhysicsController) + m_pPhysicsController->RefreshCollisions(); +} + +unsigned short KX_GameObject::GetUserCollisionGroup() +{ + return m_userCollisionGroup; +} +unsigned short KX_GameObject::GetUserCollisionMask() +{ + return m_userCollisionMask; } bool KX_GameObject::CheckCollision(KX_GameObject* other) @@ -569,6 +600,13 @@ CValue* KX_GameObject::GetReplica() return replica; } +bool KX_GameObject::IsDynamicsSuspended() const +{ + if (m_pPhysicsController) + return m_pPhysicsController->IsSuspended(); + return false; +} + float KX_GameObject::getLinearDamping() const { if (m_pPhysicsController) @@ -768,35 +806,74 @@ void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh) m_lodmeshes.push_back(mesh); } + +static float calcHysteresis(KX_Scene *kxscene, LodLevel *lod) +{ + 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) { // Handle dupligroups - if (this->m_pInstanceObjects) { - KX_GameObject * instob; - int count = this->m_pInstanceObjects->GetCount(); + if (m_pInstanceObjects) { + KX_GameObject *instob; + int count = m_pInstanceObjects->GetCount(); for (int i = 0; i < count; i++) { - instob = (KX_GameObject*)this->m_pInstanceObjects->GetValue(i); + instob = (KX_GameObject*)m_pInstanceObjects->GetValue(i); instob->UpdateLod(cam_pos); } } - if (this->m_lodmeshes.empty()) return; + if (m_lodmeshes.empty()) + return; - MT_Vector3 delta = this->NodeGetWorldPosition() - cam_pos; + MT_Vector3 delta = NodeGetWorldPosition() - cam_pos; float distance2 = delta.length2(); int level = 0; - Object *bob = this->GetBlenderObject(); - LodLevel *lod = (LodLevel*) bob->lodlevels.first; + 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 || lod->next->distance * lod->next->distance > distance2) break; - } + if (!lod->source || lod->source->type != OB_MESH) + level--; - RAS_MeshObject *mesh = this->m_lodmeshes[level]; + if (!lod->next) + break; - if (mesh != this->m_meshes[0]) { - this->GetScene()->ReplaceMesh(this, mesh, true, false); + if (level == m_previousLodLevel || level == (m_previousLodLevel + 1)) { + hystvariance = calcHysteresis(kxscene, lod); + float newdistance = lod->next->distance + hystvariance; + if (newdistance * newdistance > distance2) + 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 = level; + if (mesh != m_meshes[0]) { + m_previousLodLevel = level; + GetScene()->ReplaceMesh(this, mesh, true, false); } } @@ -1494,70 +1571,17 @@ void KX_GameObject::RegisterCollisionCallbacks() } void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal) { - #ifdef WITH_PYTHON - Py_ssize_t len; - PyObject* collision_callbacks = m_collisionCallbacks; - - if (collision_callbacks && (len=PyList_GET_SIZE(collision_callbacks))) - { - // Argument tuples are created lazily, only when they are needed. - PyObject *args_3 = NULL; - PyObject *args_1 = NULL; // Only for compatibility with pre-2.74 callbacks that take 1 argument. - - PyObject *func; - PyObject *ret; - int co_argcount; - - // Iterate the list and run the callbacks - for (Py_ssize_t pos=0; pos < len; pos++) - { - func = PyList_GET_ITEM(collision_callbacks, pos); - - // Get the number of arguments, supporting functions, methods and generic callables. - if (PyMethod_Check(func)) { - // Take away the 'self' argument for methods. - co_argcount = ((PyCodeObject *)PyFunction_GET_CODE(PyMethod_GET_FUNCTION(func)))->co_argcount - 1; - } else if (PyFunction_Check(func)) { - co_argcount = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_argcount; - } else { - // We'll just assume the callable takes the correct number of arguments. - co_argcount = 3; - } +#ifdef WITH_PYTHON + if (!m_collisionCallbacks || PyList_GET_SIZE(m_collisionCallbacks) == 0) + return; - // Check whether the function expects the colliding object only, - // or also the point and normal. - if (co_argcount <= 1) { - // One argument, or *args (which gives co_argcount == 0) - if (args_1 == NULL) { - args_1 = PyTuple_New(1); - PyTuple_SET_ITEMS(args_1, collider->GetProxy()); - } - ret = PyObject_Call(func, args_1, NULL); - } else { - // More than one argument, assume we can give point & normal. - if (args_3 == NULL) { - args_3 = PyTuple_New(3); - PyTuple_SET_ITEMS(args_3, - collider->GetProxy(), - PyObjectFrom(point), - PyObjectFrom(normal)); - } - ret = PyObject_Call(func, args_3, NULL); - } + PyObject *args[] = {collider->GetProxy(), PyObjectFrom(point), PyObjectFrom(normal)}; + RunPythonCallBackList(m_collisionCallbacks, args, 1, ARRAY_SIZE(args)); - if (ret == NULL) { - PyErr_Print(); - PyErr_Clear(); - } - else { - Py_DECREF(ret); - } - } - - if (args_3) Py_DECREF(args_3); - if (args_1) Py_DECREF(args_1); + for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) { + Py_DECREF(args[i]); } - #endif +#endif } /* Suspend/ resume: for the dynamic behavior, there is a simple @@ -1889,7 +1913,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O}, - {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS}, + {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS}, {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS}, {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS}, {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS}, @@ -1927,6 +1951,7 @@ PyMethodDef KX_GameObject::Methods[] = { }; PyAttributeDef KX_GameObject::Attributes[] = { + KX_PYATTRIBUTE_INT_RO("currentLodLevel", KX_GameObject, m_currentLodLevel), KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name), KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), KX_PYATTRIBUTE_RO_FUNCTION("groupMembers", KX_GameObject, pyattr_get_group_members), @@ -1934,6 +1959,7 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("scene", KX_GameObject, pyattr_get_scene), KX_PYATTRIBUTE_RO_FUNCTION("life", KX_GameObject, pyattr_get_life), KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), + KX_PYATTRIBUTE_RO_FUNCTION("isSuspendDynamics", KX_GameObject, pyattr_get_is_suspend_dynamics), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max), KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), @@ -1945,6 +1971,8 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("scaling", KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling), KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset), KX_PYATTRIBUTE_RW_FUNCTION("collisionCallbacks", KX_GameObject, pyattr_get_collisionCallbacks, pyattr_set_collisionCallbacks), + KX_PYATTRIBUTE_RW_FUNCTION("collisionGroup", KX_GameObject, pyattr_get_collisionGroup, pyattr_set_collisionGroup), + KX_PYATTRIBUTE_RW_FUNCTION("collisionMask", KX_GameObject, pyattr_get_collisionMask, pyattr_set_collisionMask), 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), @@ -2291,6 +2319,56 @@ int KX_GameObject::pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIB return PY_SET_ATTR_SUCCESS; } +PyObject *KX_GameObject::pyattr_get_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + return PyLong_FromLong(self->GetUserCollisionGroup()); +} + +int KX_GameObject::pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + int val = PyLong_AsLong(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "gameOb.collisionGroup = int: KX_GameObject, expected an int bit field"); + return PY_SET_ATTR_FAIL; + } + + if (val < 0 || val > USHRT_MAX) { + PyErr_Format(PyExc_AttributeError, "gameOb.collisionGroup = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX); + return PY_SET_ATTR_FAIL; + } + + self->SetUserCollisionGroup(val); + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_GameObject::pyattr_get_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + return PyLong_FromLong(self->GetUserCollisionMask()); +} + +int KX_GameObject::pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + int val = PyLong_AsLong(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "gameOb.collisionMask = int: KX_GameObject, expected an int bit field"); + return PY_SET_ATTR_FAIL; + } + + if (val < 0 || val > USHRT_MAX) { + PyErr_Format(PyExc_AttributeError, "gameOb.collisionMask = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX); + return PY_SET_ATTR_FAIL; + } + + self->SetUserCollisionMask(val); + return PY_SET_ATTR_SUCCESS; +} + PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject *self = static_cast<KX_GameObject*>(self_v); @@ -2347,6 +2425,19 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd return PY_SET_ATTR_SUCCESS; } +PyObject *KX_GameObject::pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + + // Only objects with a physics controller can be suspended + if (!self->GetPhysicsController()) { + PyErr_SetString(PyExc_AttributeError, "This object has not Physics Controller"); + return NULL; + } + + return PyBool_FromLong(self->IsDynamicsSuspended()); +} + PyObject *KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast<KX_GameObject*>(self_v); @@ -2439,7 +2530,9 @@ int KX_GameObject::pyattr_set_record_animation(void *self_v, const KX_PYATTRIBUT PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetWorldPosition()); @@ -2461,7 +2554,9 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D PyObject *KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetLocalPosition()); @@ -2483,7 +2578,9 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); if (self->GetPhysicsController1()) @@ -2495,7 +2592,9 @@ PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIB PyObject *KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL); + return Matrix_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, 3, + mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetWorldOrientation()); @@ -2520,7 +2619,9 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT PyObject *KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL); + return Matrix_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, 3, + mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetLocalOrientation()); @@ -2544,7 +2645,9 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT PyObject *KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetWorldScaling()); @@ -2566,7 +2669,9 @@ int KX_GameObject::pyattr_set_worldScaling(void *self_v, const KX_PYATTRIBUTE_DE PyObject *KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetLocalScaling()); @@ -2668,7 +2773,9 @@ int KX_GameObject::pyattr_set_worldTransform(void *self_v, const KX_PYATTRIBUTE_ PyObject *KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetLinearVelocity(false)); @@ -2690,7 +2797,9 @@ int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRI PyObject *KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetLinearVelocity(true)); @@ -2712,7 +2821,9 @@ int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRI PyObject *KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetAngularVelocity(false)); @@ -2734,7 +2845,9 @@ int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTR PyObject *KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetAngularVelocity(true)); @@ -2855,7 +2968,9 @@ PyObject *KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE PyObject *KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 4, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->GetObjectColor()); @@ -3233,10 +3348,16 @@ PyObject *KX_GameObject::PyApplyImpulse(PyObject *args) -PyObject *KX_GameObject::PySuspendDynamics() +PyObject *KX_GameObject::PySuspendDynamics(PyObject *args) { + bool ghost = false; + + if (!PyArg_ParseTuple(args, "|b", &ghost)) + return NULL; + if (GetPhysicsController()) - GetPhysicsController()->SuspendDynamics(); + GetPhysicsController()->SuspendDynamics(ghost); + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 5800cbc6834..9c081b449ec 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -49,6 +49,7 @@ #include "CTR_HashedPtr.h" #include "KX_Scene.h" #include "KX_KetsjiEngine.h" /* for m_anim_framerate */ +#include "DNA_constraint_types.h" /* for constraint replication */ #include "DNA_object_types.h" #include "SCA_LogicManager.h" /* for ConvertPythonToGameObject to search object names */ @@ -88,18 +89,19 @@ protected: int m_layer; std::vector<RAS_MeshObject*> m_meshes; std::vector<RAS_MeshObject*> m_lodmeshes; + int m_currentLodLevel; + short m_previousLodLevel; SG_QList m_meshSlots; // head of mesh slots of this struct Object* m_pBlenderObject; struct Object* m_pBlenderGroupObject; - bool m_bSuspendDynamics; bool m_bUseObjectColor; bool m_bIsNegativeScaling; MT_Vector4 m_objectColor; // Bit fields for user control over physics collisions - short m_userCollisionGroup; - short m_userCollisionMask; + unsigned short m_userCollisionGroup; + unsigned short m_userCollisionMask; // visible = user setting // culled = while rendering, depending on camera @@ -116,6 +118,7 @@ protected: SG_Node* m_pSGNode; MT_CmMatrix4x4 m_OpenGL_4x4Matrix; + std::vector<bRigidBodyJointConstraint*> m_constraints; KX_ObstacleSimulation* m_pObstacleSimulation; @@ -192,6 +195,14 @@ public: void UpdateBlenderObjectMatrix(Object* blendobj=NULL); + /** + * Used for constraint replication for group instances. + * The list of constraints is filled during data conversion. + */ + void AddConstraint(bRigidBodyJointConstraint *cons); + std::vector<bRigidBodyJointConstraint*> GetConstraints(); + void ClearConstraints(); + /** * Get a pointer to the game object that is the parent of * this object. Or NULL if there is no parent. The returned @@ -506,8 +517,17 @@ public: */ void ActivateGraphicController(bool recurse); - void SetUserCollisionGroup(short filter); - void SetUserCollisionMask(short mask); + /** Set the object's collison group + * \param filter The group bitfield + */ + void SetUserCollisionGroup(unsigned short filter); + + /** Set the object's collison mask + * \param filter The mask bitfield + */ + void SetUserCollisionMask(unsigned short mask); + unsigned short GetUserCollisionGroup(); + unsigned short GetUserCollisionMask(); /** * Extra broadphase check for user controllable collisions */ @@ -607,6 +627,8 @@ public: return m_bDyna; } + bool IsDynamicsSuspended() const; + /** * Should we record animation for this object? */ @@ -892,7 +914,7 @@ public: * Change the layer of the object (when it is added in another layer * than the original layer) */ - void + virtual void SetLayer( int l ); @@ -983,7 +1005,7 @@ public: KX_PYMETHOD_O(KX_GameObject,SetState); KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); KX_PYMETHOD_O(KX_GameObject,GetAxisVect); - KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics); + KX_PYMETHOD_VARARGS(KX_GameObject,SuspendDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody); KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody); @@ -1027,6 +1049,7 @@ public: static PyObject* pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); @@ -1073,6 +1096,10 @@ public: static int pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_collisionCallbacks(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_collisionGroup(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_collisionMask(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_IpoConvert.cpp b/source/gameengine/Ketsji/KX_IpoConvert.cpp index 57130bf57b2..7b00760ee7b 100644 --- a/source/gameengine/Ketsji/KX_IpoConvert.cpp +++ b/source/gameengine/Ketsji/KX_IpoConvert.cpp @@ -269,52 +269,80 @@ SG_Controller *BL_CreateCameraIPO(struct bAction *action, KX_GameObject* camera return ipocontr; } -void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *converter) -{ - - if (blenderworld->adt) { - KX_WorldIpoController* ipocontr = new KX_WorldIpoController(); - -// Erwin, hook up the world ipo controller here -// Gino: hook it up to what ? -// is there a userinterface element for that ? -// for now, we have some new python hooks to access the data, for a work-around - - ipocontr->m_mist_start = blenderworld->miststa; - ipocontr->m_mist_dist = blenderworld->mistdist; - ipocontr->m_mist_rgb[0] = blenderworld->horr; - ipocontr->m_mist_rgb[1] = blenderworld->horg; - ipocontr->m_mist_rgb[2] = blenderworld->horb; +SG_Controller * BL_CreateWorldIPO( bAction *action, struct World *blenderworld, KX_BlenderSceneConverter *converter ) +{ + KX_WorldIpoController *ipocontr = NULL; - BL_InterpolatorList *adtList= GetAdtList(blenderworld->adt->action, converter); + if (blenderworld) { + BL_InterpolatorList *adtList = GetAdtList(action, converter); - // For each active channel in the adtList add an - // interpolator to the game object. - + // For each active channel in the adtList add an interpolator to the game object. KX_IInterpolator *interpolator; KX_IScalarInterpolator *interp; - + + for (int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("ambient_color", i))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_ambi_rgb[i], interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyAmbientColor(true); + } + } + for (int i=0; i<3; i++) { if ((interp = adtList->GetScalarInterpolator("horizon_color", i))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_rgb[i], interp); + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_hori_rgb[i], interp); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyMistColor(true); + ipocontr->SetModifyHorizonColor(true); } } - if ((interp = adtList->GetScalarInterpolator("mist.depth", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp); + if ((interp = adtList->GetScalarInterpolator("mist_settings.start", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyMistStart(true); + } + + if ((interp = adtList->GetScalarInterpolator("mist_settings.depth", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp); ipocontr->AddInterpolator(interpolator); ipocontr->SetModifyMistDist(true); } - if ((interp = adtList->GetScalarInterpolator("mist.start", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp); + if ((interp = adtList->GetScalarInterpolator("mist_settings.intensity", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_intensity, interp); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyMistStart(true); + ipocontr->SetModifyMistIntensity(true); + } + + if (ipocontr) { + ipocontr->m_mist_start = blenderworld->miststa; + ipocontr->m_mist_dist = blenderworld->mistdist; + ipocontr->m_mist_intensity = blenderworld->misi; + ipocontr->m_hori_rgb[0] = blenderworld->horr; + ipocontr->m_hori_rgb[1] = blenderworld->horg; + ipocontr->m_hori_rgb[2] = blenderworld->horb; + ipocontr->m_ambi_rgb[0] = blenderworld->ambr; + ipocontr->m_ambi_rgb[1] = blenderworld->ambg; + ipocontr->m_ambi_rgb[2] = blenderworld->ambb; } } + return ipocontr; } SG_Controller *BL_CreateMaterialIpo( @@ -368,7 +396,7 @@ SG_Controller *BL_CreateMaterialIpo( ipocontr->AddInterpolator(interpolator); } - if ((sinterp = adtList->GetScalarInterpolator("specularity", 0))) { + if ((sinterp = adtList->GetScalarInterpolator("specular_intensity", 0))) { if (!ipocontr) { ipocontr = new KX_MaterialIpoController(matname_hash); } @@ -376,7 +404,7 @@ SG_Controller *BL_CreateMaterialIpo( ipocontr->AddInterpolator(interpolator); } - if ((sinterp = adtList->GetScalarInterpolator("diffuse_reflection", 0))) { + if ((sinterp = adtList->GetScalarInterpolator("diffuse_intensity", 0))) { if (!ipocontr) { ipocontr = new KX_MaterialIpoController(matname_hash); } diff --git a/source/gameengine/Ketsji/KX_IpoConvert.h b/source/gameengine/Ketsji/KX_IpoConvert.h index a653e4e110b..6db43552811 100644 --- a/source/gameengine/Ketsji/KX_IpoConvert.h +++ b/source/gameengine/Ketsji/KX_IpoConvert.h @@ -50,7 +50,8 @@ SG_Controller *BL_CreateLampIPO(bAction *action, KX_GameObject* lightobj, KX_BlenderSceneConverter *converter); -void BL_ConvertWorldIpos(struct World* blenderworld, +SG_Controller *BL_CreateWorldIPO(bAction *action, + struct World *blenderworld, KX_BlenderSceneConverter *converter); SG_Controller *BL_CreateCameraIPO(bAction *action, diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index e453b757b7e..40af9b4ca39 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -312,10 +312,11 @@ void KX_KetsjiEngine::RenderDome() // for each scene, call the proceed functions { scene = *sceneit; + KX_SetActiveScene(scene); KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); // shadow buffers if (i == 0) { @@ -389,8 +390,10 @@ void KX_KetsjiEngine::RenderDome() ); } m_dome->Draw(); + // Draw Callback for the last scene #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); scene->RunDrawingCallbacks(scene->GetPostDrawCB()); #endif EndFrame(); @@ -475,7 +478,7 @@ void KX_KetsjiEngine::ClearFrame() if (doclear) { KX_Scene* firstscene = *m_scenes.begin(); - SetBackGround(firstscene->GetWorldInfo()); + firstscene->GetWorldInfo()->UpdateBackGround(); m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(), clearvp.GetRight(), clearvp.GetTop()); @@ -825,7 +828,7 @@ void KX_KetsjiEngine::Render() KX_Scene* scene = *sceneit; KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); // this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes //scene->UpdateMeshTransformations(); @@ -882,7 +885,7 @@ void KX_KetsjiEngine::Render() KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); if (scene->IsClearingZBuffer()) m_rasterizer->ClearDepthBuffer(); @@ -962,54 +965,6 @@ const STR_String& KX_KetsjiEngine::GetExitString() return m_exitstring; } - -void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi) -{ - if (wi->hasWorld()) - { - if (m_rasterizer->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) - { - m_rasterizer->SetBackColor( - wi->getBackColorRed(), - wi->getBackColorGreen(), - wi->getBackColorBlue(), - 0.0 - ); - } - } -} - - - -void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) -{ - if (wi->hasWorld()) - { - // ... - m_rasterizer->SetAmbientColor( - wi->getAmbientColorRed(), - wi->getAmbientColorGreen(), - wi->getAmbientColorBlue() - ); - - if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) - { - if (wi->hasMist()) - { - m_rasterizer->SetFog( - wi->getMistStart(), - wi->getMistDistance(), - wi->getMistColorRed(), - wi->getMistColorGreen(), - wi->getMistColorBlue() - ); - } - } - } -} - - - void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene) { m_overrideCam = true; @@ -1150,6 +1105,13 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) if (!cam) return; + + KX_SetActiveScene(scene); + +#ifdef WITH_PYTHON + scene->RunDrawingCallbacks(scene->GetPreDrawSetupCB()); +#endif + GetSceneViewport(scene, cam, area, viewport); // store the computed viewport in the scene @@ -1262,6 +1224,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) SG_SetActiveStage(SG_STAGE_RENDER); #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); // Run any pre-drawing python callbacks scene->RunDrawingCallbacks(scene->GetPreDrawCB()); #endif @@ -1280,12 +1243,16 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) */ void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene) { + KX_SetActiveScene(scene); + // We need to first make sure our viewport is correct (enabling multiple viewports can mess this up) m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight()); m_rasterizer->FlushDebugShapes(); scene->Render2DFilters(m_canvas); + #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); scene->RunDrawingCallbacks(scene->GetPostDrawCB()); #endif } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index e18b203b675..4392769ed02 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -205,14 +205,12 @@ private: void PostRenderScene(KX_Scene* scene); void RenderDebugProperties(); void RenderShadowBuffers(KX_Scene *scene); - void SetBackGround(KX_WorldInfo* worldinfo); public: KX_KetsjiEngine(class KX_ISystem* system); virtual ~KX_KetsjiEngine(); // set the devices and stuff. the client must take care of creating these - void SetWorldSettings(KX_WorldInfo* worldinfo); void SetKeyboardDevice(SCA_IInputDevice* keyboarddevice); void SetMouseDevice(SCA_IInputDevice* mousedevice); void SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice); diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 33cfec57fc0..0dec5715588 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -108,6 +108,7 @@ void KX_LightObject::UpdateScene(KX_Scene *kxscene) void KX_LightObject::SetLayer(int layer) { + KX_GameObject::SetLayer(layer); m_lightobj->m_layer = layer; } @@ -166,27 +167,31 @@ PyAttributeDef KX_LightObject::Attributes[] = { PyObject *KX_LightObject::pyattr_get_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_LightObject* self = static_cast<KX_LightObject*>(self_v); + KX_LightObject *self = static_cast<KX_LightObject *>(self_v); return PyLong_FromLong(self->m_lightobj->m_layer); } int KX_LightObject::pyattr_set_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_LightObject* self = static_cast<KX_LightObject*>(self_v); + KX_LightObject *self = static_cast<KX_LightObject *>(self_v); + int layer = PyLong_AsLong(value); - if (PyLong_Check(value)) { - int val = PyLong_AsLong(value); - if (val < 1) - val = 1; - else if (val > 20) - val = 20; + if (layer == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } - self->m_lightobj->m_layer = val; - return PY_SET_ATTR_SUCCESS; + if (layer < 1) { + PyErr_Format(PyExc_TypeError, "expected an integer greater than 1 for attribute \"%s\"", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } + else if(layer > MAX_LIGHT_LAYERS) { + PyErr_Format(PyExc_TypeError, "expected an integer less than %i for attribute \"%s\"", MAX_LIGHT_LAYERS, attrdef->m_name); + return PY_SET_ATTR_FAIL; } - PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); - return PY_SET_ATTR_FAIL; + self->SetLayer(layer); + return PY_SET_ATTR_SUCCESS; } PyObject *KX_LightObject::pyattr_get_energy(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 503ed7411e9..3a58584223d 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -34,6 +34,8 @@ #include "KX_GameObject.h" +#define MAX_LIGHT_LAYERS ((1 << 20) - 1) + struct GPULamp; struct Scene; struct Base; @@ -58,7 +60,7 @@ public: RAS_ILightObject* GetLightData() { return m_lightobj;} void UpdateScene(class KX_Scene *kxscene); - void SetLayer(int layer); + virtual void SetLayer(int layer); virtual int GetGameObjectType() { return OBJ_LIGHT; } diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp index a9617aa47b8..1faf8f17d54 100644 --- a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp @@ -32,21 +32,6 @@ bool KX_MaterialIpoController::Update(double currentTime) { if (m_modified) { - m_rgba[0]=0; - m_rgba[1]=0; - m_rgba[2]=0; - m_rgba[3]=0; - - m_specrgb[0] =0; - m_specrgb[1] =0; - m_specrgb[2] =0; - m_hard =0; - m_spec=0; - m_ref=0; - m_emit=0; - m_alpha = 0; - - T_InterpolatorList::iterator i; for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { (*i)->Execute(m_ipotime); diff --git a/source/gameengine/Ketsji/KX_MouseActuator.cpp b/source/gameengine/Ketsji/KX_MouseActuator.cpp index 62417b4df81..c372e6e9ce2 100644 --- a/source/gameengine/Ketsji/KX_MouseActuator.cpp +++ b/source/gameengine/Ketsji/KX_MouseActuator.cpp @@ -278,7 +278,10 @@ bool KX_MouseActuator::Update() setposition[1] = center_y; } - setMousePosition(setposition[0], setposition[1]); + // only trigger mouse event when it is necessary + if (m_oldposition[0] != position[0] || m_oldposition[1] != position[1]) { + setMousePosition(setposition[0], setposition[1]); + } m_oldposition[0] = position[0]; m_oldposition[1] = position[1]; diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 0eec86987be..12abcb250a7 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -75,7 +75,8 @@ KX_ObjectActuator( m_reference(refobj), m_active_combined_velocity (false), m_linear_damping_active(false), - m_angular_damping_active(false) + m_angular_damping_active(false), + m_jumping(false) { if (m_bitLocalFlag.ServoControl) { @@ -140,6 +141,7 @@ bool KX_ObjectActuator::Update() m_angular_damping_active = false; m_error_accumulator.setValue(0.0,0.0,0.0); m_previous_error.setValue(0.0,0.0,0.0); + m_jumping = false; return false; } else if (parent) @@ -223,6 +225,11 @@ bool KX_ObjectActuator::Update() else if (m_bitLocalFlag.CharacterMotion) { MT_Vector3 dir = m_dloc; + if (m_bitLocalFlag.DLoc) { + MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation(); + dir = basis * dir; + } + if (m_bitLocalFlag.AddOrSetCharLoc) { MT_Vector3 old_dir = character->GetWalkDirection(); @@ -236,21 +243,20 @@ bool KX_ObjectActuator::Update() } // We always want to set the walk direction since a walk direction of (0, 0, 0) should stop the character - if (m_bitLocalFlag.DLoc) - { - MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation(); - dir = basis*dir; - } character->SetWalkDirection(dir/parent->GetScene()->GetPhysicsEnvironment()->GetNumTimeSubSteps()); if (!m_bitLocalFlag.ZeroDRot) { parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0); } - if (m_bitLocalFlag.CharacterJump) - { - character->Jump(); + if (m_bitLocalFlag.CharacterJump) { + if (!m_jumping) { + character->Jump(); + m_jumping = true; + } + else if (character->OnGround()) + m_jumping = false; } } else { @@ -516,7 +522,9 @@ static Mathutils_Callback mathutils_obactu_vector_cb = { PyObject *KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV); } int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -532,7 +540,9 @@ int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *a PyObject *KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV); } int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index 1f2453e3700..b5622d97611 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -116,7 +116,8 @@ class KX_ObjectActuator : public SCA_IActuator bool m_active_combined_velocity; bool m_linear_damping_active; bool m_angular_damping_active; - + bool m_jumping; + public: enum KX_OBJECT_ACT_VEC_TYPE { KX_OBJECT_ACT_NODEF = 0, diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 94f5064261f..065251f5676 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -496,78 +496,46 @@ static PyObject *gPyCreateConstraint(PyObject *self, { /* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */ unsigned long long physicsid = 0, physicsid2 = 0; - int constrainttype=0, extrainfo=0; - int len = PyTuple_Size(args); - int success = 1; + int constrainttype = 0; int flag = 0; + float pivotX = 0.0f, pivotY = 0.0f, pivotZ = 0.0f, axisX = 0.0f, axisY = 0.0f, axisZ = 0.0f; - float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1; - if (len == 3) - { - success = PyArg_ParseTuple(args, "KKi", &physicsid, &physicsid2, &constrainttype); - } - else if (len == 6) - { - success = PyArg_ParseTuple(args, "KKifff", &physicsid, &physicsid2, &constrainttype, - &pivotX, &pivotY, &pivotZ); - } - else if (len == 9) - { - success = PyArg_ParseTuple(args, "KKiffffff", &physicsid, &physicsid2, &constrainttype, - &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ); - } - else if (len == 10) - { - success = PyArg_ParseTuple(args, "KKiffffffi", &physicsid, &physicsid2, &constrainttype, - &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ, &flag); - } + static const char *kwlist[] = {"physicsid_1", "physicsid_2", "constraint_type", "pivot_x", "pivot_y", "pivot_z", + "axis_X", "axis_y", "axis_z", "flag", NULL}; - /* XXX extrainfo seems to be nothing implemented. right now it works as a pivot with [X,0,0] */ - else if (len == 4) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "KKi|ffffffi:createConstraint", (char **)kwlist, + &physicsid, &physicsid2, &constrainttype, + &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ, &flag)) { - success = PyArg_ParseTuple(args,"KKii", &physicsid, &physicsid2, &constrainttype, &extrainfo); - pivotX=extrainfo; + return NULL; } - if (success) - { - if (PHY_GetActiveEnvironment()) - { - - PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid; - PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2; - if (physctrl) //TODO:check for existence of this pointer! - { - int constraintid =0; - - //convert from euler angle into axis - float radsPerDeg = 6.283185307179586232f / 360.f; + if (PHY_GetActiveEnvironment()) { + PHY_IPhysicsController *physctrl = (PHY_IPhysicsController*)physicsid; + PHY_IPhysicsController *physctrl2 = (PHY_IPhysicsController*)physicsid2; + if (physctrl) { //TODO:check for existence of this pointer! + //convert from euler angle into axis + const float deg2rad = 0.017453292f; - //we need to pass a full constraint frame, not just axis - //localConstraintFrameBasis - MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*axisX,radsPerDeg*axisY,radsPerDeg*axisZ)); - MT_Vector3 axis0 = localCFrame.getColumn(0); - MT_Vector3 axis1 = localCFrame.getColumn(1); - MT_Vector3 axis2 = localCFrame.getColumn(2); + //we need to pass a full constraint frame, not just axis + //localConstraintFrameBasis + MT_Matrix3x3 localCFrame(MT_Vector3(deg2rad*axisX, deg2rad*axisY, deg2rad*axisZ)); + MT_Vector3 axis0 = localCFrame.getColumn(0); + MT_Vector3 axis1 = localCFrame.getColumn(1); + MT_Vector3 axis2 = localCFrame.getColumn(2); - constraintid = PHY_GetActiveEnvironment()->CreateConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype, - pivotX,pivotY,pivotZ, - (float)axis0.x(),(float)axis0.y(),(float)axis0.z(), - (float)axis1.x(),(float)axis1.y(),(float)axis1.z(), - (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag); + int constraintid = PHY_GetActiveEnvironment()->CreateConstraint( + physctrl, physctrl2, (enum PHY_ConstraintType)constrainttype, pivotX, pivotY, pivotZ, + (float)axis0.x(), (float)axis0.y(), (float)axis0.z(), + (float)axis1.x(), (float)axis1.y(), (float)axis1.z(), + (float)axis2.x(), (float)axis2.y(), (float)axis2.z(), flag); - KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment()); + KX_ConstraintWrapper *wrap = new KX_ConstraintWrapper( + (enum PHY_ConstraintType)constrainttype, constraintid, PHY_GetActiveEnvironment()); - return wrap->NewProxy(true); - } - - + return wrap->NewProxy(true); } } - else { - return NULL; - } - Py_RETURN_NONE; } @@ -680,7 +648,7 @@ static struct PyMethodDef physicsconstraints_methods[] = { {"createConstraint",(PyCFunction) gPyCreateConstraint, - METH_VARARGS, (const char *)gPyCreateConstraint__doc__}, + METH_VARARGS|METH_KEYWORDS, (const char *)gPyCreateConstraint__doc__}, {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint, METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__}, diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index d7dd3fe5253..6fdc53f9c64 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -51,6 +51,8 @@ # include <Python.h> extern "C" { + # include "BLI_utildefines.h" + # include "python_utildefines.h" # include "bpy_internal_import.h" /* from the blender python api, but we want to import text too! */ # include "py_capi_utils.h" # include "mathutils.h" // 'mathutils' module copied here so the blenderlayer can use. @@ -354,7 +356,7 @@ static PyObject *gPyLoadGlobalDict(PyObject *) { char marshal_path[512]; char *marshal_buffer = NULL; - size_t marshal_length; + int marshal_length; FILE *fp = NULL; int result; @@ -365,7 +367,12 @@ static PyObject *gPyLoadGlobalDict(PyObject *) if (fp) { // obtain file size: fseek (fp, 0, SEEK_END); - marshal_length = (size_t)ftell(fp); + marshal_length = ftell(fp); + if (marshal_length == -1) { + printf("Warning: could not read position of '%s'\n", marshal_path); + fclose(fp); + Py_RETURN_NONE; + } rewind(fp); marshal_buffer = (char*)malloc (sizeof(char)*marshal_length); @@ -1029,109 +1036,22 @@ static PyObject *gPyGetStereoEye(PyObject *, PyObject *, PyObject *) static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value) { - MT_Vector4 vec; if (!PyVecTo(value, vec)) return NULL; - - if (gp_Canvas) - { - gp_Rasterizer->SetBackColor((float)vec[0], (float)vec[1], (float)vec[2], (float)vec[3]); - } KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (wi->hasWorld()) - wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]); - - Py_RETURN_NONE; -} - - - -static PyObject *gPySetMistColor(PyObject *, PyObject *value) -{ - - MT_Vector3 vec; - if (!PyVecTo(value, vec)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.SetBackgroundColor(color), World not available"); return NULL; } - gp_Rasterizer->SetFogColor((float)vec[0], (float)vec[1], (float)vec[2]); - - Py_RETURN_NONE; -} - -static PyObject *gPyDisableMist(PyObject *) -{ - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); - return NULL; - } - gp_Rasterizer->DisableFog(); - - Py_RETURN_NONE; -} -static PyObject *gPySetMistStart(PyObject *, PyObject *args) -{ + ShowDeprecationWarning("setBackgroundColor()", "KX_WorldInfo.background_color"); + wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]); - float miststart; - if (!PyArg_ParseTuple(args,"f:setMistStart",&miststart)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistStart(float), Rasterizer not available"); - return NULL; - } - - gp_Rasterizer->SetFogStart(miststart); - Py_RETURN_NONE; } - - -static PyObject *gPySetMistEnd(PyObject *, PyObject *args) -{ - - float mistend; - if (!PyArg_ParseTuple(args,"f:setMistEnd",&mistend)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistEnd(float), Rasterizer not available"); - return NULL; - } - - gp_Rasterizer->SetFogEnd(mistend); - - Py_RETURN_NONE; -} - - -static PyObject *gPySetAmbientColor(PyObject *, PyObject *value) -{ - - MT_Vector3 vec; - if (!PyVecTo(value, vec)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setAmbientColor(color), Rasterizer not available"); - return NULL; - } - gp_Rasterizer->SetAmbientColor((float)vec[0], (float)vec[1], (float)vec[2]); - - Py_RETURN_NONE; -} - - - - static PyObject *gPyMakeScreenshot(PyObject *, PyObject *args) { char* filename; @@ -1490,6 +1410,21 @@ static PyObject *gPyClearDebugList(PyObject *) Py_RETURN_NONE; } +static PyObject *gPyGetDisplayDimensions(PyObject *) +{ + PyObject *result; + int width, height; + + gp_Canvas->GetDisplayDimensions(width, height); + + result = PyTuple_New(2); + PyTuple_SET_ITEMS(result, + PyLong_FromLong(width), + PyLong_FromLong(height)); + + return result; +} + PyDoc_STRVAR(Rasterizer_module_documentation, "This is the Python API for the game engine of Rasterizer" ); @@ -1508,11 +1443,6 @@ static struct PyMethodDef rasterizer_methods[] = { {"setMousePosition",(PyCFunction) gPySetMousePosition, METH_VARARGS, "setMousePosition(int x,int y)"}, {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"}, - {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"}, - {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"}, - {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, - {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"}, - {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"}, {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"}, @@ -1538,6 +1468,8 @@ static struct PyMethodDef rasterizer_methods[] = { {"setWindowSize", (PyCFunction) gPySetWindowSize, METH_VARARGS, ""}, {"setFullScreen", (PyCFunction) gPySetFullScreen, METH_O, ""}, {"getFullScreen", (PyCFunction) gPyGetFullScreen, METH_NOARGS, ""}, + {"getDisplayDimensions", (PyCFunction) gPyGetDisplayDimensions, METH_NOARGS, + "Get the actual dimensions, in pixels, of the physical display (e.g., the monitor)."}, {"setMipmapping", (PyCFunction) gPySetMipmapping, METH_VARARGS, ""}, {"getMipmapping", (PyCFunction) gPyGetMipmapping, METH_NOARGS, ""}, {"setVsync", (PyCFunction) gPySetVsync, METH_VARARGS, ""}, @@ -2149,14 +2081,14 @@ PyObject *initGamePlayerPythonScripting(Main *maggie, int argc, char** argv) Py_SetProgramName(program_path_wchar); /* Update, Py3.3 resolves attempting to parse non-existing header */ - #if 0 +#if 0 /* Python 3.2 now looks for '2.xx/python/include/python3.2d/pyconfig.h' to * parse from the 'sysconfig' module which is used by 'site', * so for now disable site. alternatively we could copy the file. */ if (py_path_bundle != NULL) { Py_NoSiteFlag = 1; /* inhibits the automatic importing of 'site' */ } - #endif +#endif Py_FrozenFlag = 1; diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index 828fd62f205..b3511e4e61a 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -40,6 +40,7 @@ #include "BL_ArmatureConstraint.h" #include "BL_ArmatureObject.h" #include "BL_ArmatureChannel.h" +#include "KX_WorldInfo.h" #include "KX_ArmatureSensor.h" #include "KX_BlenderMaterial.h" #include "KX_CameraActuator.h" @@ -231,6 +232,7 @@ PyMODINIT_FUNC initGameTypesPythonBinding(void) PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator, init_getset); PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator, init_getset); PyType_Ready_Attr(dict, KX_Scene, init_getset); + PyType_Ready_Attr(dict, KX_WorldInfo, init_getset); PyType_Ready_Attr(dict, KX_NavMeshObject, init_getset); PyType_Ready_Attr(dict, KX_SceneActuator, init_getset); PyType_Ready_Attr(dict, KX_SoundActuator, init_getset); @@ -279,6 +281,7 @@ PyMODINIT_FUNC initGameTypesPythonBinding(void) /* Init mathutils callbacks */ KX_GameObject_Mathutils_Callback_Init(); KX_ObjectActuator_Mathutils_Callback_Init(); + KX_WorldInfo_Mathutils_Callback_Init(); #endif return m; diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 97ebd6d40a9..25755f7127b 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -43,6 +43,7 @@ #include "KX_FontObject.h" #include "RAS_IPolygonMaterial.h" #include "ListValue.h" +#include "KX_PythonCallBack.h" #include "SCA_LogicManager.h" #include "SCA_TimeEventManager.h" //#include "SCA_AlwaysEventManager.h" @@ -156,7 +157,9 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_networkDeviceInterface(ndi), m_active_camera(NULL), m_ueberExecutionPriority(0), - m_blenderScene(scene) + m_blenderScene(scene), + m_isActivedHysteresis(false), + m_lodHysteresisValue(0) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -235,6 +238,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_attr_dict = NULL; m_draw_call_pre = NULL; m_draw_call_post = NULL; + m_draw_setup_call_pre = NULL; #endif } @@ -532,6 +536,8 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal m_objectlist->Add(newobj->AddRef()); if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) m_lightlist->Add(newobj->AddRef()); + else if (newobj->GetGameObjectType()==SCA_IObject::OBJ_TEXT) + AddFont((KX_FontObject*)newobj); newobj->AddMeshUser(); // logic cannot be replicated, until the whole hierarchy is replicated. @@ -803,13 +809,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // we can now add the graphic controller to the physic engine replica->ActivateGraphicController(true); - // set references for dupli-group - // groupobj holds a list of all objects, that belongs to this group - groupobj->AddInstanceObjects(replica); - - // every object gets the reference to its dupli-group object - replica->SetDupliGroupObject(groupobj); - // done with replica replica->Release(); } @@ -817,38 +816,38 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // the logic must be replicated first because we need // the new logic bricks before relinking vector<KX_GameObject*>::iterator git; - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { - (*git)->ReParentLogic(); - } - - // relink any pointers as necessary, sort of a temporary solution - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { + for (git = m_logicHierarchicalGameObjects.begin(); git != m_logicHierarchicalGameObjects.end(); ++git) { + KX_GameObject *gameobj = *git; + + if (gameobj->GetBlenderGroupObject() == blgroupobj) { + // set references for dupli-group + // groupobj holds a list of all objects, that belongs to this group + groupobj->AddInstanceObjects(gameobj); + // every object gets the reference to its dupli-group object + gameobj->SetDupliGroupObject(groupobj); + } + + gameobj->ReParentLogic(); + + // relink any pointers as necessary, sort of a temporary solution // this will also relink the actuator to objects within the hierarchy - (*git)->Relink(&m_map_gameobject_to_replica); + gameobj->Relink(&m_map_gameobject_to_replica); // add the object in the layer of the parent - (*git)->SetLayer(groupobj->GetLayer()); - // If the object was a light, we need to update it's RAS_LightObject as well - if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) - { - KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git); - lightobj->SetLayer(groupobj->GetLayer()); - } - } + gameobj->SetLayer(groupobj->GetLayer()); - // replicate crosslinks etc. between logic bricks - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { - ReplicateLogic((*git)); - } + // replicate crosslinks etc. between logic bricks + ReplicateLogic(gameobj); - // now look if object in the hierarchy have dupli group and recurse - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { - if ((*git) != groupobj && (*git)->IsDupliGroup()) + // now look if object in the hierarchy have dupli group and recurse + /* Replicate all constraints. */ + if (gameobj->GetPhysicsController()) { + gameobj->GetPhysicsController()->ReplicateConstraints(gameobj, m_logicHierarchicalGameObjects); + gameobj->ClearConstraints(); + } + + if (gameobj != groupobj && gameobj->IsDupliGroup()) // can't instantiate group immediately as it destroys m_logicHierarchicalGameObjects - duplilist.push_back((*git)); + duplilist.push_back(gameobj); } for (git = duplilist.begin(); !(git == duplilist.end()); ++git) @@ -859,7 +858,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, - class CValue* parentobject, + class CValue* referenceobject, int lifespan) { @@ -868,7 +867,7 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, m_groupGameObjects.clear(); KX_GameObject* originalobj = (KX_GameObject*) originalobject; - KX_GameObject* parentobj = (KX_GameObject*) parentobject; + KX_GameObject* referenceobj = (KX_GameObject*) referenceobject; m_ueberExecutionPriority++; @@ -904,18 +903,20 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, replica->GetSGNode()->AddChild(childreplicanode); } - // At this stage all the objects in the hierarchy have been duplicated, - // we can update the scenegraph, we need it for the duplication of logic - MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition(); - replica->NodeSetLocalPosition(newpos); + if (referenceobj) { + // At this stage all the objects in the hierarchy have been duplicated, + // we can update the scenegraph, we need it for the duplication of logic + MT_Point3 newpos = referenceobj->NodeGetWorldPosition(); + replica->NodeSetLocalPosition(newpos); - MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation(); - replica->NodeSetLocalOrientation(newori); - - // get the rootnode's scale - MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); - // set the replica's relative scale with the rootnode's scale - replica->NodeSetRelativeScale(newscale); + MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation(); + replica->NodeSetLocalOrientation(newori); + + // get the rootnode's scale + MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); + // set the replica's relative scale with the rootnode's scale + replica->NodeSetRelativeScale(newscale); + } replica->GetSGNode()->UpdateWorldData(0); replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox()); @@ -935,13 +936,13 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, { // this will also relink the actuators in the hierarchy (*git)->Relink(&m_map_gameobject_to_replica); - // add the object in the layer of the parent - (*git)->SetLayer(parentobj->GetLayer()); - // If the object was a light, we need to update it's RAS_LightObject as well - if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) - { - KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git); - lightobj->SetLayer(parentobj->GetLayer()); + if (referenceobj) { + // add the object in the layer of the reference object + (*git)->SetLayer(referenceobj->GetLayer()); + } + else { + // We don't know what layer set, so we set all visible layers in the blender scene. + (*git)->SetLayer(m_blenderScene->lay); } } @@ -1755,6 +1756,26 @@ void KX_Scene::UpdateObjectLods(void) } } +void KX_Scene::SetLodHysteresis(bool active) +{ + m_isActivedHysteresis = active; +} + +bool KX_Scene::IsActivedLodHysteresis(void) +{ + return m_isActivedHysteresis; +} + +void KX_Scene::SetLodHysteresisValue(int hysteresisvalue) +{ + m_lodHysteresisValue = hysteresisvalue; +} + +int KX_Scene::GetLodHysteresisValue(void) +{ + return m_lodHysteresisValue; +} + void KX_Scene::UpdateObjectActivity(void) { if (m_activity_culling) { @@ -1871,15 +1892,6 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *from, KX_Sce brick->Replace_IScene(to); brick->Replace_NetworkScene(to->GetNetworkScene()); - /* near sensors have physics controllers */ - KX_TouchSensor *touch_sensor = dynamic_cast<class KX_TouchSensor *>(brick); - if (touch_sensor) { - KX_TouchEventManager *tmgr = (KX_TouchEventManager*)from->GetLogicManager()->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - touch_sensor->UnregisterSumo(tmgr); - touch_sensor->GetPhysicsController()->SetPhysicsEnvironment(to->GetPhysicsEnvironment()); - touch_sensor->RegisterSumo(tmgr); - } - // If we end up replacing a KX_TouchEventManager, we need to make sure // physics controllers are properly in place. In other words, do this // after merging physics controllers! @@ -1938,17 +1950,6 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene { SCA_IController *cont= *itc; MergeScene_LogicBrick(cont, from, to); - - vector<SCA_ISensor*> linkedsensors = cont->GetLinkedSensors(); - vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators(); - - for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());++ita) { - MergeScene_LogicBrick(*ita, from, to); - } - - for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());++its) { - MergeScene_LogicBrick(*its, from, to); - } } } @@ -2102,30 +2103,10 @@ void KX_Scene::Render2DFilters(RAS_ICanvas* canvas) void KX_Scene::RunDrawingCallbacks(PyObject *cb_list) { - Py_ssize_t len; - - if (cb_list && (len=PyList_GET_SIZE(cb_list))) - { - PyObject *args = PyTuple_New(0); // save python creating each call - PyObject *func; - PyObject *ret; - - // Iterate the list and run the callbacks - for (Py_ssize_t pos=0; pos < len; pos++) - { - func= PyList_GET_ITEM(cb_list, pos); - ret= PyObject_Call(func, args, NULL); - if (ret==NULL) { - PyErr_Print(); - PyErr_Clear(); - } - else { - Py_DECREF(ret); - } - } + if (!cb_list || PyList_GET_SIZE(cb_list) == 0) + return; - Py_DECREF(args); - } + RunPythonCallBackList(cb_list, NULL, 0, 0); } //---------------------------------------------------------------------------- @@ -2311,6 +2292,19 @@ PyObject *KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *at return self->GetLightList()->GetProxy(); } +PyObject *KX_Scene::pyattr_get_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + KX_WorldInfo *world = self->GetWorldInfo(); + + if (world->GetName() != "") { + return world->GetProxy(); + } + else { + Py_RETURN_NONE; + } +} + PyObject *KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { /* With refcounts in this case... @@ -2375,6 +2369,17 @@ PyObject *KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYAT return self->m_draw_call_post; } +PyObject *KX_Scene::pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + + if (self->m_draw_setup_call_pre == NULL) + self->m_draw_setup_call_pre = PyList_New(0); + + Py_INCREF(self->m_draw_setup_call_pre); + return self->m_draw_setup_call_pre; +} + int KX_Scene::pyattr_set_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_Scene* self = static_cast<KX_Scene*>(self_v); @@ -2409,6 +2414,22 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } +int KX_Scene::pyattr_set_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + + if (!PyList_CheckExact(value)) { + PyErr_SetString(PyExc_ValueError, "Expected a list"); + return PY_SET_ATTR_FAIL; + } + + Py_XDECREF(self->m_draw_setup_call_pre); + Py_INCREF(value); + + self->m_draw_setup_call_pre = value; + return PY_SET_ATTR_SUCCESS; +} + PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Scene* self = static_cast<KX_Scene*>(self_v); @@ -2434,9 +2455,11 @@ PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("objectsInactive", KX_Scene, pyattr_get_objects_inactive), KX_PYATTRIBUTE_RO_FUNCTION("lights", KX_Scene, pyattr_get_lights), KX_PYATTRIBUTE_RO_FUNCTION("cameras", KX_Scene, pyattr_get_cameras), + KX_PYATTRIBUTE_RO_FUNCTION("world", KX_Scene, pyattr_get_world), KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera), KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post), + KX_PYATTRIBUTE_RW_FUNCTION("pre_draw_setup", KX_Scene, pyattr_get_drawing_setup_callback_pre, pyattr_set_drawing_setup_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity), KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), @@ -2449,23 +2472,23 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, "addObject(object, other, time=0)\n" "Returns the added object.\n") { - PyObject *pyob, *pyother; - KX_GameObject *ob, *other; + PyObject *pyob, *pyreference = Py_None; + KX_GameObject *ob, *reference; int time = 0; - if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyother, &time)) + if (!PyArg_ParseTuple(args, "O|Oi:addObject", &pyob, &pyreference, &time)) return NULL; - if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, other, time): KX_Scene (first argument)") || - !ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") ) + if (!ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") || + !ConvertPythonToGameObject(pyreference, &reference, true, "scene.addObject(object, reference, time): KX_Scene (second argument)")) return NULL; if (!m_inactivelist->SearchValue(ob)) { - PyErr_Format(PyExc_ValueError, "scene.addObject(object, other, time): KX_Scene (first argument): object must be in an inactive layer"); + PyErr_Format(PyExc_ValueError, "scene.addObject(object, reference, time): KX_Scene (first argument): object must be in an inactive layer"); return NULL; } - SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time); + SCA_IObject *replica = AddReplicaObject((SCA_IObject*)ob, reference, time); // release here because AddReplicaObject AddRef's // the object is added to the scene so we don't want python to own a reference diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 2e1ee9f101d..a5645ea6448 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -107,6 +107,7 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene PyObject* m_attr_dict; PyObject* m_draw_call_pre; PyObject* m_draw_call_post; + PyObject* m_draw_setup_call_pre; #endif struct CullingInfo { @@ -295,6 +296,12 @@ protected: KX_ObstacleSimulation* m_obstacleSimulation; + /** + * LOD Hysteresis settings + */ + bool m_isActivedHysteresis; + int m_lodHysteresisValue; + public: KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, @@ -546,6 +553,12 @@ public: // Update the mesh for objects based on level of detail settings void UpdateObjectLods(void); + + // LoD Hysteresis functions + void SetLodHysteresis(bool active); + bool IsActivedLodHysteresis(); + void SetLodHysteresisValue(int hysteresisvalue); + int GetLodHysteresisValue(); // Update the activity box settings for objects in this scene, if needed. void UpdateObjectActivity(void); @@ -612,12 +625,15 @@ public: static PyObject* pyattr_get_objects_inactive(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_lights(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_cameras(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_world(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_drawing_setup_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); @@ -634,6 +650,7 @@ public: PyObject *GetPreDrawCB() { return m_draw_call_pre; } PyObject *GetPostDrawCB() { return m_draw_call_post; } + PyObject *GetPreDrawSetupCB() { return m_draw_setup_call_pre; } #endif /** diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.cpp b/source/gameengine/Ketsji/KX_SteeringActuator.cpp index 10d4273a2b4..83597f9125a 100644 --- a/source/gameengine/Ketsji/KX_SteeringActuator.cpp +++ b/source/gameengine/Ketsji/KX_SteeringActuator.cpp @@ -263,12 +263,12 @@ bool KX_SteeringActuator::Update(double curtime, bool frame) if (apply_steerforce) { - MT_Vector3 newvel; bool isdyna = obj->IsDynamic(); if (isdyna) m_steerVec.z() = 0; if (!m_steerVec.fuzzyZero()) m_steerVec.normalize(); + MT_Vector3 newvel = m_velocity * m_steerVec; //adjust velocity to avoid obstacles if (m_simulation && m_obstacle /*&& !newvel.fuzzyZero()*/) @@ -284,13 +284,10 @@ bool KX_SteeringActuator::Update(double curtime, bool frame) HandleActorFace(newvel); if (isdyna) { - //TODO: Take into account angular velocity on turns + //temporary solution: set 2D steering velocity directly to obj + //correct way is to apply physical force MT_Vector3 curvel = obj->GetLinearVelocity(); - newvel = (curvel.length() * m_steerVec) + (m_acceleration * delta) * m_steerVec; - if (newvel.length2() >= (m_velocity * m_velocity)) - newvel = m_velocity * m_steerVec; - if (m_lockzvel) newvel.z() = 0.0f; else diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index d10e51a491a..b42200783e4 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -54,19 +54,20 @@ KX_VehicleWrapper::~KX_VehicleWrapper() #ifdef WITH_PYTHON -static bool raise_exc_wheel(PHY_IVehicle* vehicle, int i, const char *method) +static bool raise_exc_wheel(PHY_IVehicle *vehicle, int i, const char *method) { - if ( i < 0 || i >= vehicle->GetNumWheels() ) { + if (i < 0 || i >= vehicle->GetNumWheels()) { PyErr_Format(PyExc_ValueError, - "%s(...): wheel index %d out of range (0 to %d).", method, i, vehicle->GetNumWheels()-1); - return -1; - } else { - return 0; + "%s(...): wheel index %d out of range (0 to %d).", method, i, vehicle->GetNumWheels() - 1); + return true; + } + else { + return false; } } #define WHEEL_INDEX_CHECK_OR_RETURN(i, method) \ - if (raise_exc_wheel(m_vehicle, i, method) == -1) { return NULL; } (void)0 + if (raise_exc_wheel(m_vehicle, i, method)) {return NULL;} (void)0 PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) @@ -86,8 +87,6 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) if (gameOb->GetSGNode()) { - PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode()); - MT_Vector3 attachPos,attachDir,attachAxle; if(!PyVecTo(pylistPos,attachPos)) { PyErr_SetString(PyExc_AttributeError, @@ -114,6 +113,7 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) return NULL; } + PHY_IMotionState *motionState = new KX_MotionState(gameOb->GetSGNode()); m_vehicle->AddWheel(motionState,attachPos,attachDir,attachAxle,suspensionRestLength,wheelRadius,hasSteering); } diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp index 444d6b0771b..8678b058761 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.cpp +++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp @@ -31,8 +31,464 @@ #include "KX_WorldInfo.h" +#include "KX_PythonInit.h" +#include "KX_PyMath.h" +#include "RAS_IRasterizer.h" +#include "GPU_material.h" + +/* This little block needed for linking to Blender... */ +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +/* This list includes only data type definitions */ +#include "DNA_scene_types.h" +#include "DNA_world_types.h" + +#include "BLI_math.h" + +#include "BKE_global.h" +#include "BKE_scene.h" +/* end of blender include block */ + + +KX_WorldInfo::KX_WorldInfo(Scene *blenderscene, World *blenderworld) +{ + if (blenderworld) { + m_name = blenderworld->id.name + 2; + m_do_color_management = BKE_scene_check_color_management_enabled(blenderscene); + m_hasworld = true; + m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false); + m_misttype = blenderworld->mistype; + m_miststart = blenderworld->miststa; + m_mistdistance = blenderworld->mistdist; + m_mistintensity = blenderworld->misi; + setMistColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); + setBackColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); + setAmbientColor(blenderworld->ambr, blenderworld->ambg, blenderworld->ambb); + } + else { + m_hasworld = false; + } +} KX_WorldInfo::~KX_WorldInfo() { } +const STR_String& KX_WorldInfo::GetName() +{ + return m_name; +} + +bool KX_WorldInfo::hasWorld() +{ + return m_hasworld; +} + +void KX_WorldInfo::setBackColor(float r, float g, float b) +{ + m_backgroundcolor[0] = r; + m_backgroundcolor[1] = g; + m_backgroundcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_backgroundcolor, m_backgroundcolor); + } + else { + copy_v3_v3(m_con_backgroundcolor, m_backgroundcolor); + } +} + +const float *KX_WorldInfo::getBackColor(void) const +{ + return m_backgroundcolor; +} + +void KX_WorldInfo::setMistType(short type) +{ + m_misttype = type; +} + +void KX_WorldInfo::setUseMist(bool enable) +{ + m_hasmist = enable; +} + +void KX_WorldInfo::setMistStart(float d) +{ + m_miststart = d; +} + +void KX_WorldInfo::setMistDistance(float d) +{ + m_mistdistance = d; +} + +void KX_WorldInfo::setMistIntensity(float intensity) +{ + m_mistintensity = intensity; +} +void KX_WorldInfo::setMistColor(float r, float g, float b) +{ + m_mistcolor[0] = r; + m_mistcolor[1] = g; + m_mistcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_mistcolor, m_mistcolor); + } + else { + copy_v3_v3(m_con_mistcolor, m_mistcolor); + } +} + +void KX_WorldInfo::setAmbientColor(float r, float g, float b) +{ + m_ambientcolor[0] = r; + m_ambientcolor[1] = g; + m_ambientcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_ambientcolor, m_ambientcolor); + } + else { + copy_v3_v3(m_con_ambientcolor, m_ambientcolor); + } +} + +void KX_WorldInfo::UpdateBackGround() +{ + if (m_hasworld) { + RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); + + if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetBackColor(m_con_backgroundcolor); + GPU_horizon_update_color(m_backgroundcolor); + } + } +} + +void KX_WorldInfo::UpdateWorldSettings() +{ + if (m_hasworld) { + RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); + + if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetAmbientColor(m_con_ambientcolor); + GPU_ambient_update_color(m_ambientcolor); + + if (m_hasmist) { + m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_con_mistcolor); + GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor); + m_rasterizer->EnableFog(true); + GPU_mist_update_enable(true); + } + else { + m_rasterizer->EnableFog(false); + GPU_mist_update_enable(false); + } + } + } +} + +#ifdef WITH_PYTHON + +/* ------------------------------------------------------------------------- + * Python functions + * ------------------------------------------------------------------------- */ +PyObject *KX_WorldInfo::py_repr(void) +{ + return PyUnicode_From_STR_String(GetName()); +} + +/* ------------------------------------------------------------------------- + * Python Integration Hooks + * ------------------------------------------------------------------------- */ +PyTypeObject KX_WorldInfo::Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "KX_WorldInfo", + sizeof(PyObjectPlus_Proxy), + 0, + py_base_dealloc, + 0, + 0, + 0, + 0, + py_base_repr, + 0,0,0,0,0,0,0,0,0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new +}; + +PyMethodDef KX_WorldInfo::Methods[] = { + {NULL,NULL} /* Sentinel */ +}; + +PyAttributeDef KX_WorldInfo::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RW("mistEnable", KX_WorldInfo, m_hasmist), + KX_PYATTRIBUTE_FLOAT_RW("mistStart", 0.0f, 10000.0f, KX_WorldInfo, m_miststart), + KX_PYATTRIBUTE_FLOAT_RW("mistDistance", 0.001f, 10000.0f, KX_WorldInfo, m_mistdistance), + KX_PYATTRIBUTE_FLOAT_RW("mistIntensity", 0.0f, 1.0f, KX_WorldInfo, m_mistintensity), + KX_PYATTRIBUTE_SHORT_RW("mistType", 0, 2, true, KX_WorldInfo, m_misttype), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_LINEAR", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_INV_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RW_FUNCTION("mistColor", KX_WorldInfo, pyattr_get_mist_color, pyattr_set_mist_color), + KX_PYATTRIBUTE_RW_FUNCTION("backgroundColor", KX_WorldInfo, pyattr_get_back_color, pyattr_set_back_color), + KX_PYATTRIBUTE_RW_FUNCTION("ambientColor", KX_WorldInfo, pyattr_get_ambient_color, pyattr_set_ambient_color), + { NULL } /* Sentinel */ +}; + +/* Attribute get/set functions */ + +#ifdef USE_MATHUTILS + +/*----------------------mathutils callbacks ----------------------------*/ + +/* subtype */ +#define MATHUTILS_VEC_CB_MIST_COLOR 1 +#define MATHUTILS_VEC_CB_BACK_COLOR 2 +#define MATHUTILS_VEC_CB_AMBIENT_COLOR 3 + +static unsigned char mathutils_world_vector_cb_index = -1; /* index for our callbacks */ + +static int mathutils_world_generic_check(BaseMathObject *bmo) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + if (self == NULL) + return -1; + + return 0; +} + +static int mathutils_world_vector_get(BaseMathObject *bmo, int subtype) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + copy_v3_v3(bmo->data, self->m_mistcolor); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + copy_v3_v3(bmo->data, self->m_backgroundcolor); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + copy_v3_v3(bmo->data, self->m_ambientcolor); + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_set(BaseMathObject *bmo, int subtype) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + self->setMistColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + self->setBackColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + self->setAmbientColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_get_index(BaseMathObject *bmo, int subtype, int index) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + { + const float *color = self->m_mistcolor; + bmo->data[index] = color[index]; + } + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + { + const float *color = self->m_backgroundcolor; + bmo->data[index] = color[index]; + } + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + { + const float *color = self->m_ambientcolor; + bmo->data[index] = color[index]; + } + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_set_index(BaseMathObject *bmo, int subtype, int index) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + float color[4]; + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + copy_v3_v3(color, self->m_mistcolor); + color[index] = bmo->data[index]; + self->setMistColor(color[0], color[1], color[2]); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + copy_v3_v3(color, self->m_backgroundcolor); + color[index] = bmo->data[index]; + self->setBackColor(color[0], color[1], color[2]); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + copy_v3_v3(color, self->m_ambientcolor); + color[index] = bmo->data[index]; + self->setAmbientColor(color[0], color[1], color[2]); + break; + default: + return -1; + } + return 0; +} + +static Mathutils_Callback mathutils_world_vector_cb = { + mathutils_world_generic_check, + mathutils_world_vector_get, + mathutils_world_vector_set, + mathutils_world_vector_get_index, + mathutils_world_vector_set_index +}; + +void KX_WorldInfo_Mathutils_Callback_Init() +{ + // register mathutils callbacks, ok to run more than once. + mathutils_world_vector_cb_index = Mathutils_RegisterCallback(&mathutils_world_vector_cb); +} +#endif // USE_MATHUTILS + + +PyObject *KX_WorldInfo::pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + PyObject *retvalue; + + const char* type = attrdef->m_name; + + if (!strcmp(type, "KX_MIST_QUADRATIC")) { + retvalue = PyLong_FromLong(KX_MIST_QUADRATIC); + } + else if (!strcmp(type, "KX_MIST_LINEAR")) { + retvalue = PyLong_FromLong(KX_MIST_LINEAR); + } + else if (!strcmp(type, "KX_MIST_INV_QUADRATIC")) { + retvalue = PyLong_FromLong(KX_MIST_INV_QUADRATIC); + } + else { + /* should never happen */ + PyErr_SetString(PyExc_TypeError, "invalid mist type"); + retvalue = NULL; + } + + return retvalue; +} + +PyObject *KX_WorldInfo::pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_MIST_COLOR); +#else + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + return PyObjectFrom(MT_Vector3(self->m_mistcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setMistColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +PyObject *KX_WorldInfo::pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_BACK_COLOR); +#else + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + return PyObjectFrom(MT_Vector3(self->m_backgroundcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setBackColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +PyObject *KX_WorldInfo::pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_AMBIENT_COLOR); +#else + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + return PyObjectFrom(MT_Vector3(self->m_ambientcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setAmbientColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +#endif /* WITH_PYTHON */ diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 90b16fe1242..0e8fe3c730a 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -33,41 +33,77 @@ #define __KX_WORLDINFO_H__ #include "MT_Scalar.h" +#include "KX_KetsjiEngine.h" +#include "PyObjectPlus.h" #ifdef WITH_CXX_GUARDEDALLOC #include "MEM_guardedalloc.h" #endif -class MT_CmMatrix4x4; +#ifdef USE_MATHUTILS +void KX_WorldInfo_Mathutils_Callback_Init(void); +#endif + +struct Scene; +struct World; -class KX_WorldInfo +class KX_WorldInfo : public PyObjectPlus { -public: - KX_WorldInfo() {} - virtual ~KX_WorldInfo(); + Py_Header - virtual bool hasWorld() = 0; - virtual bool hasMist() = 0; - virtual float getBackColorRed() = 0; - virtual float getBackColorGreen() = 0; - virtual float getBackColorBlue() = 0; - virtual float getMistStart() = 0; - virtual float getMistDistance() = 0; - virtual float getMistColorRed() = 0; - virtual float getMistColorGreen() = 0; - virtual float getMistColorBlue() = 0; + STR_String m_name; + bool m_do_color_management; + bool m_hasworld; + bool m_hasmist; + short m_misttype; + float m_miststart; + float m_mistdistance; + float m_mistintensity; + float m_mistcolor[3]; + float m_backgroundcolor[3]; + float m_ambientcolor[3]; + float m_con_mistcolor[3]; + float m_con_backgroundcolor[3]; + float m_con_ambientcolor[3]; - virtual float getAmbientColorRed() = 0; - virtual float getAmbientColorGreen() = 0; - virtual float getAmbientColorBlue() = 0; +public: + /** + * Mist options + */ + enum MistType { + KX_MIST_QUADRATIC, + KX_MIST_LINEAR, + KX_MIST_INV_QUADRATIC, + }; + + KX_WorldInfo(Scene *blenderscene, World *blenderworld); + ~KX_WorldInfo(); - virtual void setBackColor(float, float, float) = 0; - virtual void setMistStart(float) = 0; - virtual void setMistDistance(float) = 0; - virtual void setMistColorRed(float) = 0; - virtual void setMistColorGreen(float) = 0; - virtual void setMistColorBlue(float) = 0; + const STR_String &GetName(); + bool hasWorld(); + void setUseMist(bool enable); + void setMistType(short type); + void setMistStart(float d); + void setMistDistance(float d); + void setMistIntensity(float intensity); + void setMistColor(float r, float g, float b); + void setBackColor(float r, float g, float b); + const float *getBackColor() const; + void setAmbientColor(float r, float g, float b); + void UpdateBackGround(); + void UpdateWorldSettings(); +#ifdef WITH_PYTHON + /* attributes */ + static PyObject *pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + virtual PyObject *py_repr(void); +#endif #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_WorldInfo") diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.cpp b/source/gameengine/Ketsji/KX_WorldIpoController.cpp index 7f83a155643..1123e07ebcc 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.cpp +++ b/source/gameengine/Ketsji/KX_WorldIpoController.cpp @@ -33,6 +33,8 @@ #include "KX_WorldIpoController.h" #include "KX_ScalarInterpolator.h" #include "KX_WorldInfo.h" +#include "KX_PythonInit.h" +#include "KX_Scene.h" #if defined(_WIN64) typedef unsigned __int64 uint_ptr; @@ -42,31 +44,36 @@ typedef unsigned long uint_ptr; bool KX_WorldIpoController::Update(double currentTime) { - if (m_modified) - { + if (m_modified) { T_InterpolatorList::iterator i; for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { - (*i)->Execute(m_ipotime);//currentTime); + (*i)->Execute(m_ipotime); } - /* TODO, this will crash! */ - KX_WorldInfo *world = NULL; + KX_WorldInfo *world = KX_GetActiveScene()->GetWorldInfo(); if (m_modify_mist_start) { world->setMistStart(m_mist_start); } - if (m_modify_mist_color) { - world->setMistColorRed(m_mist_rgb[0]); - world->setMistColorGreen(m_mist_rgb[1]); - world->setMistColorBlue(m_mist_rgb[2]); - } - if (m_modify_mist_dist) { world->setMistDistance(m_mist_dist); } - m_modified=false; + if (m_modify_mist_intensity) { + world->setMistIntensity(m_mist_intensity); + } + + if (m_modify_horizon_color) { + world->setBackColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]); + world->setMistColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]); + } + + if (m_modify_ambient_color) { + world->setAmbientColor(m_ambi_rgb[0], m_ambi_rgb[1], m_ambi_rgb[2]); + } + + m_modified = false; } return false; } diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.h b/source/gameengine/Ketsji/KX_WorldIpoController.h index 63983b3129b..704f421573e 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.h +++ b/source/gameengine/Ketsji/KX_WorldIpoController.h @@ -39,24 +39,30 @@ class KX_WorldIpoController : public SG_Controller { public: - MT_Scalar m_mist_rgb[3]; MT_Scalar m_mist_start; MT_Scalar m_mist_dist; + MT_Scalar m_mist_intensity; + MT_Scalar m_hori_rgb[3]; + MT_Scalar m_ambi_rgb[3]; private: T_InterpolatorList m_interpolators; - unsigned short m_modify_mist_color : 1; unsigned short m_modify_mist_start : 1; unsigned short m_modify_mist_dist : 1; + unsigned short m_modify_mist_intensity : 1; + unsigned short m_modify_horizon_color : 1; + unsigned short m_modify_ambient_color : 1; bool m_modified; double m_ipotime; public: KX_WorldIpoController() : - m_modify_mist_color(false), m_modify_mist_start(false), m_modify_mist_dist(false), + m_modify_mist_intensity(false), + m_modify_horizon_color(false), + m_modify_ambient_color(false), m_modified(true), m_ipotime(0.0) {} @@ -76,14 +82,22 @@ public: m_modify_mist_start = modify; } - void SetModifyMistColor(bool modify) { - m_modify_mist_color = modify; - } - void SetModifyMistDist(bool modify) { m_modify_mist_dist = modify; } + void SetModifyMistIntensity(bool modify) { + m_modify_mist_intensity = modify; + } + + void SetModifyHorizonColor(bool modify) { + m_modify_horizon_color = modify; + } + + void SetModifyAmbientColor(bool modify) { + m_modify_ambient_color = modify; + } + void SetOption( int option, |