Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/gameengine/Ketsji')
-rw-r--r--source/gameengine/Ketsji/BL_Action.cpp9
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.cpp7
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.h3
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp53
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.h9
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp7
-rw-r--r--source/gameengine/Ketsji/KX_Camera.h2
-rw-r--r--source/gameengine/Ketsji/KX_CameraActuator.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp3
-rw-r--r--source/gameengine/Ketsji/KX_GameActuator.cpp5
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp360
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h44
-rw-r--r--source/gameengine/Ketsji/KX_IpoConvert.cpp88
-rw-r--r--source/gameengine/Ketsji/KX_IpoConvert.h3
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.cpp125
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h5
-rw-r--r--source/gameengine/Ketsji/KX_Light.cpp29
-rw-r--r--source/gameengine/Ketsji/KX_Light.h4
-rw-r--r--source/gameengine/Ketsji/KX_MaterialIpoController.cpp15
-rw-r--r--source/gameengine/Ketsji/KX_MouseActuator.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_MouseActuator.h5
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.cpp32
-rw-r--r--source/gameengine/Ketsji/KX_ObjectActuator.h3
-rw-r--r--source/gameengine/Ketsji/KX_PolyProxy.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.cpp90
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp245
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.h1
-rw-r--r--source/gameengine/Ketsji/KX_PythonInitTypes.cpp3
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp261
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h17
-rw-r--r--source/gameengine/Ketsji/KX_SteeringActuator.cpp11
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.cpp18
-rw-r--r--source/gameengine/Ketsji/KX_WorldInfo.cpp456
-rw-r--r--source/gameengine/Ketsji/KX_WorldInfo.h84
-rw-r--r--source/gameengine/Ketsji/KX_WorldIpoController.cpp31
-rw-r--r--source/gameengine/Ketsji/KX_WorldIpoController.h28
37 files changed, 1452 insertions, 626 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_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp
index 07adce73b4a..c3d0f9e9ad0 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.cpp
+++ b/source/gameengine/Ketsji/BL_ActionManager.cpp
@@ -28,7 +28,8 @@
#include "BL_ActionManager.h"
BL_ActionManager::BL_ActionManager(class KX_GameObject *obj):
- m_obj(obj)
+ m_obj(obj),
+ m_prevUpdate(-1.0f)
{
}
@@ -131,6 +132,10 @@ bool BL_ActionManager::IsActionDone(short layer)
void BL_ActionManager::Update(float curtime)
{
+ if (m_prevUpdate == curtime)
+ return;
+ m_prevUpdate = curtime;
+
BL_ActionMap::iterator it;
for (it = m_layers.begin(); it != m_layers.end(); )
{
diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h
index 148097f995e..45bcd104826 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.h
+++ b/source/gameengine/Ketsji/BL_ActionManager.h
@@ -51,6 +51,9 @@ private:
class KX_GameObject* m_obj;
BL_ActionMap m_layers;
+ // The last update time to avoid double animation update.
+ float m_prevUpdate;
+
/**
* Check if an action exists
*/
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_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp
index acf30b4866c..4dc30ae1672 100644
--- a/source/gameengine/Ketsji/KX_CameraActuator.cpp
+++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp
@@ -288,7 +288,7 @@ bool KX_CameraActuator::Update(double curtime, bool frame)
from[1] += fac * fp1[1];
from[2] += fac * fp1[2];
- /* alleen alstie ervoor ligt: cross testen en loodrechte bijtellen */
+ /* only for it lies: cross test and perpendicular bites up */
if (inp < 0.0f) {
if (fp1[0] * fp2[1] - fp1[1] * fp2[0] > 0.0f) {
from[0] -= fac * fp1[1];
@@ -300,7 +300,7 @@ bool KX_CameraActuator::Update(double curtime, bool frame)
}
}
- /* CONSTRAINT 5: minimum / maximum afstand */
+ /* CONSTRAINT 5: minimum / maximum distance */
rc[0] = (lookat[0]-from[0]);
rc[1] = (lookat[1]-from[1]);
@@ -323,7 +323,7 @@ bool KX_CameraActuator::Update(double curtime, bool frame)
}
- /* CONSTRAINT 7: track to schaduw */
+ /* CONSTRAINT 7: track to floor below actor */
rc[0] = (lookat[0]-from[0]);
rc[1] = (lookat[1]-from[1]);
rc[2] = (lookat[2]-from[2]);
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index f58fee88d48..07bed647b29 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -2044,6 +2044,9 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
cam->NodeUpdateGS(0.f);
scene->CalculateVisibleMeshes(m_rasterizer,cam);
+
+ m_engine->UpdateAnimations(scene);
+
scene->RenderBuckets(camtrans, m_rasterizer);
}
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 71af263bf46..5701d0e54a0 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"
@@ -70,7 +71,11 @@
#include "PyObjectPlus.h" /* python stuff */
#include "BLI_utildefines.h"
-#include "python_utildefines.h"
+
+#ifdef WITH_PYTHON
+# include "KX_PythonCallBack.h"
+# include "python_utildefines.h"
+#endif
// This file defines relationships between parents and children
// in the game engine.
@@ -92,9 +97,9 @@ KX_GameObject::KX_GameObject(
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),
@@ -292,6 +297,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;
@@ -546,13 +566,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)
@@ -570,6 +603,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)
@@ -769,35 +809,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--;
+
+ if (!lod->next)
+ break;
+
+ 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 = this->m_lodmeshes[level];
- this->m_currentLodLevel = level;
- if (mesh != this->m_meshes[0]) {
- this->GetScene()->ReplaceMesh(this, mesh, true, false);
+ RAS_MeshObject *mesh = m_lodmeshes[level];
+ m_currentLodLevel = level;
+ if (mesh != m_meshes[0]) {
+ m_previousLodLevel = level;
+ GetScene()->ReplaceMesh(this, mesh, true, false);
}
}
@@ -1495,70 +1574,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;
- }
-
- // 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);
- }
+#ifdef WITH_PYTHON
+ if (!m_collisionCallbacks || PyList_GET_SIZE(m_collisionCallbacks) == 0)
+ return;
- if (ret == NULL) {
- PyErr_Print();
- PyErr_Clear();
- }
- else {
- Py_DECREF(ret);
- }
- }
+ PyObject *args[] = {collider->GetProxy(), PyObjectFrom(point), PyObjectFrom(normal)};
+ RunPythonCallBackList(m_collisionCallbacks, args, 1, ARRAY_SIZE(args));
- 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
@@ -1890,7 +1916,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},
@@ -1936,8 +1962,11 @@ 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("angularVelocityMin", KX_GameObject, pyattr_get_ang_vel_min, pyattr_set_ang_vel_min),
+ KX_PYATTRIBUTE_RW_FUNCTION("angularVelocityMax", KX_GameObject, pyattr_get_ang_vel_max, pyattr_set_ang_vel_max),
KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible),
KX_PYATTRIBUTE_RW_FUNCTION("record_animation", KX_GameObject, pyattr_get_record_animation, pyattr_set_record_animation),
KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder),
@@ -1947,6 +1976,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),
@@ -2293,6 +2324,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);
@@ -2349,6 +2430,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);
@@ -2395,6 +2489,54 @@ int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_GameObject::pyattr_get_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+ PHY_IPhysicsController *spc = self->GetPhysicsController();
+ return PyFloat_FromDouble(spc ? spc->GetAngularVelocityMin() : 0.0f);
+}
+
+int KX_GameObject::pyattr_set_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+ PHY_IPhysicsController *spc = self->GetPhysicsController();
+ MT_Scalar val = PyFloat_AsDouble(value);
+ if (val < 0.0f) { /* also accounts for non float */
+ PyErr_SetString(PyExc_AttributeError,
+ "gameOb.angularVelocityMin = float: KX_GameObject, expected a nonnegative float");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ if (spc)
+ spc->SetAngularVelocityMin(val);
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_GameObject::pyattr_get_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+ PHY_IPhysicsController *spc = self->GetPhysicsController();
+ return PyFloat_FromDouble(spc ? spc->GetAngularVelocityMax() : 0.0f);
+}
+
+int KX_GameObject::pyattr_set_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject *self = static_cast<KX_GameObject*>(self_v);
+ PHY_IPhysicsController *spc = self->GetPhysicsController();
+ MT_Scalar val = PyFloat_AsDouble(value);
+ if (val < 0.0f) { /* also accounts for non float */
+ PyErr_SetString(PyExc_AttributeError,
+ "gameOb.angularVelocityMax = float: KX_GameObject, expected a nonnegative float");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ if (spc)
+ spc->SetAngularVelocityMax(val);
+
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject *KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
@@ -2441,7 +2583,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());
@@ -2463,7 +2607,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());
@@ -2485,7 +2631,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())
@@ -2497,7 +2645,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());
@@ -2522,7 +2672,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());
@@ -2546,7 +2698,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());
@@ -2568,7 +2722,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());
@@ -2670,7 +2826,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));
@@ -2692,7 +2850,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));
@@ -2714,7 +2874,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));
@@ -2736,7 +2898,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));
@@ -2857,7 +3021,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());
@@ -3235,10 +3401,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 7d1a934bcec..670fcd6fb6e 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 */
@@ -89,18 +90,18 @@ protected:
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
@@ -117,6 +118,7 @@ protected:
SG_Node* m_pSGNode;
MT_CmMatrix4x4 m_OpenGL_4x4Matrix;
+ std::vector<bRigidBodyJointConstraint*> m_constraints;
KX_ObstacleSimulation* m_pObstacleSimulation;
@@ -193,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
@@ -507,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
*/
@@ -608,6 +627,8 @@ public:
return m_bDyna;
}
+ bool IsDynamicsSuspended() const;
+
/**
* Should we record animation for this object?
*/
@@ -893,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
);
@@ -984,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);
@@ -1028,10 +1049,15 @@ 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);
static int pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
@@ -1074,6 +1100,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..be0cd8433f7 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());
@@ -687,13 +690,6 @@ bool KX_KetsjiEngine::NextFrame()
// update levels of detail
scene->UpdateObjectLods();
- if (!GetRestrictAnimationFPS())
- {
- m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
- SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
- scene->UpdateAnimations(m_frameTime);
- }
-
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
SG_SetActiveStage(SG_STAGE_PHYSICS2);
scene->GetPhysicsEnvironment()->BeginFrame();
@@ -738,26 +734,6 @@ bool KX_KetsjiEngine::NextFrame()
frames--;
}
- // Handle the animations independently of the logic time step
- if (GetRestrictAnimationFPS())
- {
- double clocktime = m_kxsystem->GetTimeInSeconds();
- m_logger->StartLog(tc_animations, clocktime, true);
- SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
-
- double anim_timestep = 1.0/KX_GetActiveScene()->GetAnimationFPS();
- if (clocktime - m_previousAnimTime > anim_timestep)
- {
- // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep)
- // printf("Anim fps: %f\n", 1.0/(m_clockTime - m_previousAnimTime));
- m_previousAnimTime = clocktime;
- for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
- {
- (*sceneit)->UpdateAnimations(clocktime);
- }
- }
- }
-
// Start logging time spend outside main loop
m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true);
@@ -825,7 +801,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 +858,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 +938,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;
@@ -1094,6 +1022,23 @@ void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect
}
}
+void KX_KetsjiEngine::UpdateAnimations(KX_Scene *scene)
+{
+ // Handle the animations independently of the logic time step
+ if (GetRestrictAnimationFPS()) {
+ double anim_timestep = 1.0 / KX_GetActiveScene()->GetAnimationFPS();
+ if (m_frameTime - m_previousAnimTime > anim_timestep || m_frameTime == m_previousAnimTime) {
+ // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep)
+ // printf("Anim fps: %f\n", 1.0/(m_frameTime - m_previousAnimTime));
+ m_previousAnimTime = m_frameTime;
+ for (KX_SceneList::iterator sceneit = m_scenes.begin(); sceneit != m_scenes.end(); ++sceneit)
+ (*sceneit)->UpdateAnimations(m_frameTime);
+ }
+ }
+ else
+ scene->UpdateAnimations(m_frameTime);
+}
+
void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
{
CListValue *lightlist = scene->GetLightList();
@@ -1127,6 +1072,12 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
/* update scene */
scene->CalculateVisibleMeshes(m_rasterizer, cam, raslight->GetShadowLayer());
+ m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
+ UpdateAnimations(scene);
+ m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_RENDER);
+
/* render */
m_rasterizer->ClearDepthBuffer();
m_rasterizer->ClearColorBuffer();
@@ -1150,6 +1101,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
@@ -1258,10 +1216,15 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
scene->CalculateVisibleMeshes(m_rasterizer,cam);
+ m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
+ SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
+ UpdateAnimations(scene);
+
m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true);
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..cd473451111 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);
@@ -274,6 +272,9 @@ public:
void SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat);
void SetCameraOverrideClipping(float near, float far);
void SetCameraOverrideLens(float lens);
+
+ // Update animations for object in this scene
+ void UpdateAnimations(KX_Scene *scene);
/**
* Sets display of all frames.
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 c372e6e9ce2..154ad1da3a1 100644
--- a/source/gameengine/Ketsji/KX_MouseActuator.cpp
+++ b/source/gameengine/Ketsji/KX_MouseActuator.cpp
@@ -337,7 +337,7 @@ void KX_MouseActuator::setMousePosition(float fx, float fy)
m_canvas->SetMousePosition(x, y);
}
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
/* ------------------------------------------------------------------------- */
/* Python functions */
@@ -536,4 +536,4 @@ PyObject* KX_MouseActuator::PyReset()
Py_RETURN_NONE;
}
-#endif
+#endif /* WITH_PYTHON */
diff --git a/source/gameengine/Ketsji/KX_MouseActuator.h b/source/gameengine/Ketsji/KX_MouseActuator.h
index bf90bd21dac..e244e271428 100644
--- a/source/gameengine/Ketsji/KX_MouseActuator.h
+++ b/source/gameengine/Ketsji/KX_MouseActuator.h
@@ -104,6 +104,9 @@ public:
virtual void getMousePosition(float*);
virtual void setMousePosition(float, float);
+
+#ifdef WITH_PYTHON
+
/* --------------------------------------------------------------------- */
/* Python interface ---------------------------------------------------- */
/* --------------------------------------------------------------------- */
@@ -122,6 +125,8 @@ public:
static PyObject* pyattr_get_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+#endif /* WITH_PYTHON */
+
};
#endif //__KX_MOUSEACTUATOR_DOC
diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
index c2c83266791..c3c693ed55f 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -36,6 +36,8 @@
# pragma warning(disable:4786)
#endif
+#include <stdio.h>
+
#include "MT_Point3.h"
#include "RAS_FramingManager.h"
#include "RAS_ICanvas.h"
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_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp
index ccc10eb06e3..4454543161b 100644
--- a/source/gameengine/Ketsji/KX_PolyProxy.cpp
+++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp
@@ -140,21 +140,21 @@ PyObject *KX_PolyProxy::pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *at
{
KX_PolyProxy* self = static_cast<KX_PolyProxy*>(self_v);
- return PyLong_FromLong(self->m_polygon->GetVertexOffset(0));
+ return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(0));
}
PyObject *KX_PolyProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self = static_cast<KX_PolyProxy*>(self_v);
- return PyLong_FromLong(self->m_polygon->GetVertexOffset(1));
+ return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(1));
}
PyObject *KX_PolyProxy::pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
KX_PolyProxy* self = static_cast<KX_PolyProxy*>(self_v);
- return PyLong_FromLong(self->m_polygon->GetVertexOffset(2));
+ return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(2));
}
PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
@@ -163,7 +163,7 @@ PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *at
if (3 < self->m_polygon->VertexCount())
{
- return PyLong_FromLong(self->m_polygon->GetVertexOffset(3));
+ return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(3));
}
return PyLong_FromLong(0);
}
@@ -243,7 +243,7 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex,
}
if (index < m_polygon->VertexCount())
{
- return PyLong_FromLong(m_polygon->GetVertexOffset(index));
+ return PyLong_FromLong(m_polygon->GetVertexOffsetAbsolute(index));
}
return PyLong_FromLong(0);
}
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
index 94f5064261f..bfac9a87512 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..a5fb2dede72 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.
@@ -136,6 +138,7 @@ extern "C" {
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_appdir.h"
+#include "BKE_blender.h"
#include "BLI_blenlib.h"
#include "GPU_material.h"
#include "MEM_guardedalloc.h"
@@ -354,7 +357,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 +368,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 +1037,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;
-}
+ ShowDeprecationWarning("setBackgroundColor()", "KX_WorldInfo.background_color");
+ wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]);
-static PyObject *gPySetMistStart(PyObject *, PyObject *args)
-{
-
- 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 +1411,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 +1444,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 +1469,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, ""},
@@ -2088,33 +2021,50 @@ PyMODINIT_FUNC initBGE(void)
PyObject *mod;
PyObject *submodule;
PyObject *sys_modules = PyThreadState_GET()->interp->modules;
+ const char *mod_full;
mod = PyModule_Create(&BGE_module_def);
- PyModule_AddObject(mod, "constraints", (submodule = initConstraintPythonBinding()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ /* skip "bge." */
+#define SUBMOD (mod_full + 4)
+
+ mod_full = "bge.app";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initApplicationPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+ mod_full = "bge.constraints";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initConstraintPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
Py_INCREF(submodule);
- PyModule_AddObject(mod, "events", (submodule = initGameKeysPythonBinding()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ mod_full = "bge.events";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initGameKeysPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
Py_INCREF(submodule);
- PyModule_AddObject(mod, "logic", (submodule = initGameLogicPythonBinding()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ mod_full = "bge.logic";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initGameLogicPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
Py_INCREF(submodule);
- PyModule_AddObject(mod, "render", (submodule = initRasterizerPythonBinding()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ mod_full = "bge.render";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initRasterizerPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
Py_INCREF(submodule);
- PyModule_AddObject(mod, "texture", (submodule = initVideoTexturePythonBinding()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ mod_full = "bge.texture";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initVideoTexturePythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
Py_INCREF(submodule);
- PyModule_AddObject(mod, "types", (submodule = initGameTypesPythonBinding()));
- PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
+ mod_full = "bge.types";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initGameTypesPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
Py_INCREF(submodule);
+#undef SUBMOD
+
return mod;
}
@@ -2149,14 +2099,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;
@@ -2606,6 +2556,77 @@ PyMODINIT_FUNC initGameKeysPythonBinding()
return m;
}
+
+
+/* ------------------------------------------------------------------------- */
+/* Application: application values that remain unchanged during runtime */
+/* ------------------------------------------------------------------------- */
+
+PyDoc_STRVAR(Application_module_documentation,
+ "This module contains application values that remain unchanged during runtime."
+ );
+
+static struct PyModuleDef Application_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "bge.app", /* m_name */
+ Application_module_documentation, /* m_doc */
+ 0, /* m_size */
+ NULL, /* m_methods */
+ 0, /* m_reload */
+ 0, /* m_traverse */
+ 0, /* m_clear */
+ 0, /* m_free */
+};
+
+PyMODINIT_FUNC initApplicationPythonBinding()
+{
+ PyObject *m;
+ PyObject *d;
+
+ m = PyModule_Create(&Application_module_def);
+
+ // Add some symbolic constants to the module
+ d = PyModule_GetDict(m);
+
+ PyDict_SetItemString(d, "version", Py_BuildValue("(iii)",
+ BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
+ PyDict_SetItemString(d, "version_string", PyUnicode_FromFormat("%d.%02d (sub %d)",
+ BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION));
+ PyDict_SetItemString(d, "version_char", PyUnicode_FromString(
+ STRINGIFY(BLENDER_VERSION_CHAR)));
+
+ PyDict_SetItemString(d, "has_texture_ffmpeg",
+#ifdef WITH_FFMPEG
+ Py_True
+#else
+ Py_False
+#endif
+ );
+ PyDict_SetItemString(d, "has_joystick",
+#ifdef WITH_SDL
+ Py_True
+#else
+ Py_False
+#endif
+ );
+ PyDict_SetItemString(d, "has_physics",
+#ifdef WITH_BULLET
+ Py_True
+#else
+ Py_False
+#endif
+ );
+
+ // Check for errors
+ if (PyErr_Occurred()) {
+ PyErr_Print();
+ PyErr_Clear();
+ }
+
+ return m;
+}
+
+
// utility function for loading and saving the globalDict
int saveGamePythonConfig( char **marshal_buffer)
{
diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h
index f74a4b3865f..06aeb5a4fca 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.h
+++ b/source/gameengine/Ketsji/KX_PythonInit.h
@@ -48,6 +48,7 @@ extern bool gUseVisibilityTemp;
#ifdef WITH_PYTHON
PyMODINIT_FUNC initBGE(void);
+PyMODINIT_FUNC initApplicationPythonBinding(void);
PyMODINIT_FUNC initGameLogicPythonBinding(void);
PyMODINIT_FUNC initGameKeysPythonBinding(void);
PyMODINIT_FUNC initRasterizerPythonBinding(void);
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 d1b10098237..d3ee219b2f4 100644
--- a/source/gameengine/Ketsji/KX_Scene.cpp
+++ b/source/gameengine/Ketsji/KX_Scene.cpp
@@ -35,6 +35,8 @@
# pragma warning (disable:4786)
#endif
+#include <stdio.h>
+
#include "KX_Scene.h"
#include "KX_PythonInit.h"
#include "MT_assert.h"
@@ -94,12 +96,14 @@
#include "KX_ObstacleSimulation.h"
#ifdef WITH_BULLET
-#include "KX_SoftBodyDeformer.h"
+# include "KX_SoftBodyDeformer.h"
#endif
-#include "KX_Light.h"
+#ifdef WITH_PYTHON
+# include "KX_PythonCallBack.h"
+#endif
-#include <stdio.h>
+#include "KX_Light.h"
#include "BLI_task.h"
@@ -156,7 +160,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 +241,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
}
@@ -805,13 +812,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();
}
@@ -819,38 +819,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)
@@ -861,7 +861,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)
{
@@ -870,7 +870,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++;
@@ -906,18 +906,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());
@@ -937,13 +939,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);
}
}
@@ -1078,6 +1080,16 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
group->RemoveInstanceObject(newobj);
newobj->RemoveMeshes();
+
+ switch (newobj->GetGameObjectType()) {
+ case SCA_IObject::OBJ_CAMERA:
+ m_cameras.remove((KX_Camera *)newobj);
+ break;
+ case SCA_IObject::OBJ_TEXT:
+ m_fonts.remove((KX_FontObject *)newobj);
+ break;
+ }
+
ret = 1;
if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT && m_lightlist->RemoveValue(newobj))
ret = newobj->Release();
@@ -1093,7 +1105,10 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
ret = newobj->Release();
if (m_animatedlist->RemoveValue(newobj))
ret = newobj->Release();
-
+
+ /* Warning 'newobj' maye be freed now, only compare, don't access */
+
+
if (newobj == m_active_camera)
{
//no AddRef done on m_active_camera so no Release
@@ -1101,12 +1116,6 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj)
m_active_camera = NULL;
}
- // in case this is a camera
- m_cameras.remove((KX_Camera*)newobj);
-
- // in case this is a font
- m_fonts.remove((KX_FontObject*)newobj);
-
/* currently does nothing, keep in case we need to Unregister something */
#if 0
if (m_sceneConverter)
@@ -1757,6 +1766,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) {
@@ -1873,15 +1902,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!
@@ -1940,17 +1960,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);
- }
}
}
@@ -2104,30 +2113,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);
}
//----------------------------------------------------------------------------
@@ -2313,6 +2302,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...
@@ -2377,6 +2379,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);
@@ -2411,6 +2424,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);
@@ -2436,9 +2465,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),
@@ -2451,23 +2482,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 f859b1ceae9..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()*/)
@@ -281,16 +281,13 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector3(0.0, 1.0, 0.0));
}
- HandleActorFace(m_steerVec);
+ 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..111d81cad2e 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::getBackColorConverted() const
+{
+ return m_con_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..22851d3e269 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 *getBackColorConverted() 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,