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.cpp21
-rw-r--r--source/gameengine/Ketsji/BL_Action.h2
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.cpp28
-rw-r--r--source/gameengine/Ketsji/BL_ActionManager.h15
-rw-r--r--source/gameengine/Ketsji/BL_BlenderShader.cpp6
-rw-r--r--source/gameengine/Ketsji/BL_Material.cpp10
-rw-r--r--source/gameengine/Ketsji/BL_Material.h2
-rw-r--r--source/gameengine/Ketsji/BL_Shader.cpp2
-rw-r--r--source/gameengine/Ketsji/BL_Shader.h2
-rw-r--r--source/gameengine/Ketsji/BL_Texture.cpp51
-rw-r--r--source/gameengine/Ketsji/CMakeLists.txt12
-rw-r--r--source/gameengine/Ketsji/KXNetwork/CMakeLists.txt1
-rw-r--r--source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp6
-rw-r--r--source/gameengine/Ketsji/KXNetwork/SConscript1
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.cpp345
-rw-r--r--source/gameengine/Ketsji/KX_BlenderMaterial.h34
-rw-r--r--source/gameengine/Ketsji/KX_Camera.cpp80
-rw-r--r--source/gameengine/Ketsji/KX_Camera.h14
-rw-r--r--source/gameengine/Ketsji/KX_CameraActuator.cpp16
-rw-r--r--source/gameengine/Ketsji/KX_CharacterWrapper.h2
-rw-r--r--source/gameengine/Ketsji/KX_ClientObjectInfo.h9
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintActuator.cpp17
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_ConstraintWrapper.h2
-rw-r--r--source/gameengine/Ketsji/KX_Dome.cpp6
-rw-r--r--source/gameengine/Ketsji/KX_Dome.h2
-rw-r--r--source/gameengine/Ketsji/KX_FontObject.cpp3
-rw-r--r--source/gameengine/Ketsji/KX_FontObject.h1
-rw-r--r--source/gameengine/Ketsji/KX_GameActuator.cpp5
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.cpp506
-rw-r--r--source/gameengine/Ketsji/KX_GameObject.h75
-rw-r--r--source/gameengine/Ketsji/KX_ISceneConverter.h10
-rw-r--r--source/gameengine/Ketsji/KX_IpoActuator.cpp2
-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.cpp249
-rw-r--r--source/gameengine/Ketsji/KX_KetsjiEngine.h13
-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_MeshProxy.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_MouseActuator.cpp60
-rw-r--r--source/gameengine/Ketsji/KX_MouseActuator.h5
-rw-r--r--source/gameengine/Ketsji/KX_MouseFocusSensor.cpp40
-rw-r--r--source/gameengine/Ketsji/KX_NavMeshObject.cpp14
-rw-r--r--source/gameengine/Ketsji/KX_NavMeshObject.h2
-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_ParentActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_PolyProxy.cpp10
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.cpp278
-rw-r--r--source/gameengine/Ketsji/KX_PyConstraintBinding.h3
-rw-r--r--source/gameengine/Ketsji/KX_PyMath.cpp31
-rw-r--r--source/gameengine/Ketsji/KX_PyMath.h9
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.cpp676
-rw-r--r--source/gameengine/Ketsji/KX_PythonInit.h26
-rw-r--r--source/gameengine/Ketsji/KX_PythonInitTypes.cpp43
-rw-r--r--source/gameengine/Ketsji/KX_PythonInitTypes.h3
-rw-r--r--source/gameengine/Ketsji/KX_PythonSeq.h2
-rw-r--r--source/gameengine/Ketsji/KX_RaySensor.cpp45
-rw-r--r--source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp4
-rw-r--r--source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_Scene.cpp311
-rw-r--r--source/gameengine/Ketsji/KX_Scene.h21
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.cpp204
-rw-r--r--source/gameengine/Ketsji/KX_SoundActuator.h12
-rw-r--r--source/gameengine/Ketsji/KX_SteeringActuator.cpp21
-rw-r--r--source/gameengine/Ketsji/KX_SteeringActuator.h4
-rw-r--r--source/gameengine/Ketsji/KX_TouchEventManager.cpp24
-rw-r--r--source/gameengine/Ketsji/KX_TouchEventManager.h24
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.cpp41
-rw-r--r--source/gameengine/Ketsji/KX_TouchSensor.h2
-rw-r--r--source/gameengine/Ketsji/KX_TrackToActuator.cpp2
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.cpp82
-rw-r--r--source/gameengine/Ketsji/KX_VehicleWrapper.h2
-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
-rw-r--r--source/gameengine/Ketsji/SConscript13
81 files changed, 3018 insertions, 1329 deletions
diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp
index a50c07a486a..12a1caee221 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) {
@@ -292,6 +301,18 @@ float BL_Action::GetFrame()
return m_localtime;
}
+const char *BL_Action::GetName()
+{
+ if (m_action != NULL) {
+ return m_action->id.name + 2;
+ }
+ else {
+ return "";
+ }
+
+
+}
+
void BL_Action::SetFrame(float frame)
{
// Clamp the frame to the start and end frame
diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h
index dd1cd1f69ff..379dd52df5b 100644
--- a/source/gameengine/Ketsji/BL_Action.h
+++ b/source/gameengine/Ketsji/BL_Action.h
@@ -112,6 +112,8 @@ public:
// Accessors
float GetFrame();
+ const char *GetName();
+
struct bAction *GetAction();
// Mutators
diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp
index 07adce73b4a..9e4690548d3 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.cpp
+++ b/source/gameengine/Ketsji/BL_ActionManager.cpp
@@ -26,9 +26,13 @@
#include "BL_Action.h"
#include "BL_ActionManager.h"
+#include "DNA_ID.h"
+
+#define IS_TAGGED(_id) ((_id) && (((ID *)_id)->flag & LIB_DOIT))
BL_ActionManager::BL_ActionManager(class KX_GameObject *obj):
- m_obj(obj)
+ m_obj(obj),
+ m_prevUpdate(-1.0f)
{
}
@@ -64,6 +68,12 @@ float BL_ActionManager::GetActionFrame(short layer)
return action ? action->GetFrame() : 0.f;
}
+const char *BL_ActionManager::GetActionName(short layer)
+{
+ BL_Action *action = GetAction(layer);
+ return action ? action->GetName() : "";
+}
+
void BL_ActionManager::SetActionFrame(short layer, float frame)
{
BL_Action *action = GetAction(layer);
@@ -122,6 +132,18 @@ void BL_ActionManager::StopAction(short layer)
if (action) action->Stop();
}
+void BL_ActionManager::RemoveTaggedActions()
+{
+ for (BL_ActionMap::iterator it = m_layers.begin(); it != m_layers.end();) {
+ if (IS_TAGGED(it->second->GetAction())) {
+ delete it->second;
+ m_layers.erase(it++);
+ }
+ else
+ ++it;
+ }
+}
+
bool BL_ActionManager::IsActionDone(short layer)
{
BL_Action *action = GetAction(layer);
@@ -131,6 +153,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 5b340257881..97d6d88cf22 100644
--- a/source/gameengine/Ketsji/BL_ActionManager.h
+++ b/source/gameengine/Ketsji/BL_ActionManager.h
@@ -20,7 +20,7 @@
* ***** END GPL LICENSE BLOCK *****
*/
-/** \file BL_ActionManager.cpp
+/** \file BL_ActionManager.h
* \ingroup ketsji
*/
@@ -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
*/
@@ -82,6 +85,11 @@ public:
float GetActionFrame(short layer);
/**
+ * Gets the name of the current action
+ */
+ const char *GetActionName(short layer);
+
+ /**
* Sets the current frame of an action
*/
void SetActionFrame(short layer, float frame);
@@ -107,6 +115,11 @@ public:
void StopAction(short layer);
/**
+ * Remove playing tagged actions.
+ */
+ void RemoveTaggedActions();
+
+ /**
* Check if an action has finished playing
*/
bool IsActionDone(short layer);
diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp
index bcdef85bc8a..b5151615f3b 100644
--- a/source/gameengine/Ketsji/BL_BlenderShader.cpp
+++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp
@@ -62,7 +62,7 @@ BL_BlenderShader::~BL_BlenderShader()
void BL_BlenderShader::ReloadMaterial()
{
- mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat) : NULL;
+ mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat, false) : NULL;
}
void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty)
@@ -77,7 +77,7 @@ void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty)
view.getValue((float*)viewmat);
viewinv.getValue((float*)viewinvmat);
- GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat, false);
+ GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat, NULL, false);
}
else
GPU_material_unbind(mGPUMat);
@@ -168,7 +168,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty )
obcol[0] = obcol[1] = obcol[2] = obcol[3] = 1.0f;
float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f;
- GPU_material_bind_uniforms(gpumat, obmat, obcol, auto_bump_scale);
+ GPU_material_bind_uniforms(gpumat, obmat, obcol, auto_bump_scale, NULL);
mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol);
}
diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp
index 006c1f7202c..4f707e6267f 100644
--- a/source/gameengine/Ketsji/BL_Material.cpp
+++ b/source/gameengine/Ketsji/BL_Material.cpp
@@ -47,10 +47,10 @@ BL_Material::BL_Material()
void BL_Material::Initialize()
{
- rgb[0] = 0;
- rgb[1] = 0;
- rgb[2] = 0;
- rgb[3] = 0;
+ rgb[0] = 0xFFFFFFFFL;
+ rgb[1] = 0xFFFFFFFFL;
+ rgb[2] = 0xFFFFFFFFL;
+ rgb[3] = 0xFFFFFFFFL;
IdMode = 0;
ras_mode = 0;
glslmat = 0;
@@ -69,7 +69,7 @@ void BL_Material::Initialize()
alpha = 1.f;
emit = 0.f;
material = 0;
- memset(&tface, 0, sizeof(tface));
+ memset(&mtexpoly, 0, sizeof(mtexpoly));
materialindex = 0;
amb=0.5f;
num_enabled = 0;
diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h
index 83f9b601e0d..9207a41f56d 100644
--- a/source/gameengine/Ketsji/BL_Material.h
+++ b/source/gameengine/Ketsji/BL_Material.h
@@ -84,7 +84,7 @@ public:
Material* material;
- MTFace tface; /* copy of the derived meshes tface */
+ MTexPoly mtexpoly; /* copy of the derived meshes tface */
Image* img[MAXTEX];
EnvMap* cubemap[MAXTEX];
diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp
index 872ac19351d..a59c3686a18 100644
--- a/source/gameengine/Ketsji/BL_Shader.cpp
+++ b/source/gameengine/Ketsji/BL_Shader.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "GL/glew.h"
+#include "glew-mx.h"
#include <iostream>
#include "BL_Shader.h"
diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h
index 4c671d0c9a3..e3dc4b19773 100644
--- a/source/gameengine/Ketsji/BL_Shader.h
+++ b/source/gameengine/Ketsji/BL_Shader.h
@@ -6,7 +6,7 @@
#ifndef __BL_SHADER_H__
#define __BL_SHADER_H__
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "BL_Material.h"
#include "BL_Texture.h"
// --
diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp
index 1578c745b9f..8f717c05c0f 100644
--- a/source/gameengine/Ketsji/BL_Texture.cpp
+++ b/source/gameengine/Ketsji/BL_Texture.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "GL/glew.h"
+#include "glew-mx.h"
#include <iostream>
#include <map>
@@ -170,7 +170,7 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap)
glGenTextures(1, (GLuint*)&mTexture);
#ifdef WITH_DDS
- if (ibuf->ftype & DDS)
+ if (ibuf->ftype == IMB_FTYPE_DDS)
InitGLCompressedTex(ibuf, mipmap);
else
InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap);
@@ -203,9 +203,21 @@ void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap)
glBindTexture(GL_TEXTURE_2D, mTexture );
if ( mipmap ) {
+ int i;
+ ImBuf *ibuf;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix );
+
+ ibuf = IMB_allocFromBuffer(pix, NULL, x, y);
+
+ IMB_makemipmap(ibuf, true);
+
+ for (i = 0; i < ibuf->miptot; i++) {
+ ImBuf *mip = IMB_getmipmap(ibuf, i);
+
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect);
+ }
+ IMB_freeImBuf(ibuf);
}
else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -239,26 +251,34 @@ void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap)
int nx= power_of_2_min_i(x);
int ny= power_of_2_min_i(y);
- unsigned int *newPixels = (unsigned int *)malloc(nx*ny*sizeof(unsigned int));
-
- gluScaleImage(GL_RGBA, x, y, GL_UNSIGNED_BYTE, pix, nx,ny, GL_UNSIGNED_BYTE, newPixels);
+ ImBuf *ibuf = IMB_allocFromBuffer(pix, NULL, x, y);
+ IMB_scaleImBuf(ibuf, nx, ny);
+
glBindTexture(GL_TEXTURE_2D, mTexture );
if ( mipmap ) {
+ int i;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
+
+ IMB_makemipmap(ibuf, true);
+
+ for (i = 0; i < ibuf->miptot; i++) {
+ ImBuf *mip = IMB_getmipmap(ibuf, i);
+
+ glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect);
+ }
}
else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, newPixels );
+ glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect );
}
if (GLEW_EXT_texture_filter_anisotropic)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
- free(newPixels);
+ IMB_freeImBuf(ibuf);
}
@@ -400,13 +420,16 @@ unsigned int BL_Texture::GetTextureType() const
int BL_Texture::GetMaxUnits()
{
if (g_max_units < 0) {
- GLint unit;
- if (GLEW_ARB_multitexture) {
+ GLint unit = 0;
+
+ if (GPU_glsl_support()) {
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &unit);
+ }
+ else if (GLEW_ARB_multitexture) {
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit);
- g_max_units = (MAXTEX>=unit)?unit:MAXTEX;
- } else {
- g_max_units = 0;
}
+
+ g_max_units = (MAXTEX >= unit) ? unit : MAXTEX;
}
return g_max_units;
diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt
index 03d1524b310..2607e2bb4b7 100644
--- a/source/gameengine/Ketsji/CMakeLists.txt
+++ b/source/gameengine/Ketsji/CMakeLists.txt
@@ -49,6 +49,7 @@ set(INC
../../blender/python/generic
../../blender/python/mathutils
../../../intern/container
+ ../../../intern/glew-mx
../../../intern/guardedalloc
../../../intern/string
)
@@ -229,7 +230,7 @@ set(SRC
)
-add_definitions(-DGLEW_STATIC)
+add_definitions(${GL_DEFINITIONS})
if(WITH_IMAGE_DDS)
add_definitions(-DWITH_DDS)
@@ -247,11 +248,12 @@ if(WITH_CODEC_FFMPEG)
endif()
if(WITH_AUDASPACE)
- list(APPEND INC
- ../../../intern/audaspace/intern
- ../../../intern/audaspace/FX
+ add_definitions(${AUDASPACE_DEFINITIONS})
+
+ list(APPEND INC_SYS
+ ${AUDASPACE_C_INCLUDE_DIRS}
+ ${AUDASPACE_PY_INCLUDE_DIRS}
)
- add_definitions(-DWITH_AUDASPACE)
endif()
if(WITH_BULLET)
diff --git a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
index 0c661cf2c87..cfc6ded4e65 100644
--- a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
+++ b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../../GameLogic
../../Network
../../SceneGraph
+ ../../../blender/blenlib
../../../../intern/container
../../../../intern/string
)
diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
index 6260596159d..1fadd9382e0 100644
--- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
+++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp
@@ -39,9 +39,9 @@
#include "NG_NetworkScene.h"
#include "NG_NetworkObject.h"
#include "SCA_IObject.h"
-#include "InputParser.h"
-#include "ListValue.h"
-#include "StringValue.h"
+#include "EXP_InputParser.h"
+#include "EXP_ListValue.h"
+#include "EXP_StringValue.h"
#ifdef NAN_NET_DEBUG
#include <iostream>
diff --git a/source/gameengine/Ketsji/KXNetwork/SConscript b/source/gameengine/Ketsji/KXNetwork/SConscript
index 355dcc4f78f..ab03e03e74d 100644
--- a/source/gameengine/Ketsji/KXNetwork/SConscript
+++ b/source/gameengine/Ketsji/KXNetwork/SConscript
@@ -39,6 +39,7 @@ incs = [
'#source/gameengine/Ketsji',
'#source/gameengine/Network',
'#source/gameengine/SceneGraph',
+ '../../../blender/blenlib',
]
incs = ' '.join(incs)
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
index 9ebdfea6156..d85d33d9834 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "KX_BlenderMaterial.h"
#include "BL_Material.h"
@@ -30,6 +30,7 @@
#include "KX_Light.h"
#include "KX_GameObject.h"
#include "KX_MeshProxy.h"
+#include "KX_PyMath.h"
#include "MT_Vector3.h"
#include "MT_Vector4.h"
@@ -52,6 +53,7 @@
#include "BKE_mesh.h"
// ------------------------------------
#include "BLI_utildefines.h"
+#include "BLI_math.h"
#define spit(x) std::cout << x << std::endl;
@@ -94,6 +96,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,16 +141,30 @@ 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
OnExit();
}
-MTFace* KX_BlenderMaterial::GetMTFace() const
+MTexPoly *KX_BlenderMaterial::GetMTexPoly() const
{
// fonts on polys
- return &mMaterial->tface;
+ return &mMaterial->mtexpoly;
}
unsigned int* KX_BlenderMaterial::GetMCol() const
@@ -160,7 +191,7 @@ Material *KX_BlenderMaterial::GetBlenderMaterial() const
Image *KX_BlenderMaterial::GetBlenderImage() const
{
- return mMaterial->tface.tpage;
+ return mMaterial->mtexpoly.tpage;
}
Scene* KX_BlenderMaterial::GetBlenderScene() const
@@ -793,17 +824,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)
@@ -813,6 +846,11 @@ void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val)
OnConstruction();
}
+BL_Material *KX_BlenderMaterial::GetBLMaterial()
+{
+ return mMaterial;
+}
+
void KX_BlenderMaterial::SetBlenderGLSLShader()
{
if (!mBlenderShader)
@@ -824,6 +862,111 @@ void KX_BlenderMaterial::SetBlenderGLSLShader()
}
}
+#ifdef USE_MATHUTILS
+
+#define MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR 1
+#define MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR 2
+
+static unsigned char mathutils_kxblendermaterial_color_cb_index = -1; /* index for our callbacks */
+
+static int mathutils_kxblendermaterial_generic_check(BaseMathObject *bmo)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user);
+ if (!self)
+ return -1;
+
+ return 0;
+}
+
+static int mathutils_kxblendermaterial_color_get(BaseMathObject *bmo, int subtype)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial*>BGE_PROXY_REF(bmo->cb_user);
+ if (!self)
+ return -1;
+
+ switch (subtype) {
+ case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR:
+ {
+ copy_v3_v3(bmo->data, self->GetBLMaterial()->matcolor);
+ break;
+ }
+ case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR:
+ {
+ copy_v3_v3(bmo->data, self->GetBLMaterial()->speccolor);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int mathutils_kxblendermaterial_color_set(BaseMathObject *bmo, int subtype)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user);
+ if (!self)
+ return -1;
+
+ switch (subtype) {
+ case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR:
+ {
+ BL_Material *mat = self->GetBLMaterial();
+ copy_v3_v3(mat->matcolor, bmo->data);
+ mat->material->r = bmo->data[0];
+ mat->material->g = bmo->data[1];
+ mat->material->b = bmo->data[2];
+ break;
+ }
+ case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR:
+ {
+ BL_Material *mat = self->GetBLMaterial();
+ copy_v3_v3(mat->speccolor, bmo->data);
+ mat->material->specr = bmo->data[0];
+ mat->material->specg = bmo->data[1];
+ mat->material->specb = bmo->data[2];
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int mathutils_kxblendermaterial_color_get_index(BaseMathObject *bmo, int subtype, int index)
+{
+ /* lazy, avoid repeteing the case statement */
+ if (mathutils_kxblendermaterial_color_get(bmo, subtype) == -1)
+ return -1;
+ return 0;
+}
+
+static int mathutils_kxblendermaterial_color_set_index(BaseMathObject *bmo, int subtype, int index)
+{
+ float f = bmo->data[index];
+
+ /* lazy, avoid repeateing the case statement */
+ if (mathutils_kxblendermaterial_color_get(bmo, subtype) == -1)
+ return -1;
+
+ bmo->data[index] = f;
+ return mathutils_kxblendermaterial_color_set(bmo, subtype);
+}
+
+static Mathutils_Callback mathutils_kxblendermaterial_color_cb = {
+ mathutils_kxblendermaterial_generic_check,
+ mathutils_kxblendermaterial_color_get,
+ mathutils_kxblendermaterial_color_set,
+ mathutils_kxblendermaterial_color_get_index,
+ mathutils_kxblendermaterial_color_set_index
+};
+
+
+void KX_BlenderMaterial_Mathutils_Callback_Init()
+{
+ // register mathutils callbacks, ok to run more than once.
+ mathutils_kxblendermaterial_color_cb_index = Mathutils_RegisterCallback(&mathutils_kxblendermaterial_color_cb);
+}
+
+#endif // USE_MATHUTILS
+
#ifdef WITH_PYTHON
PyMethodDef KX_BlenderMaterial::Methods[] =
@@ -838,6 +981,14 @@ PyAttributeDef KX_BlenderMaterial::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shader),
KX_PYATTRIBUTE_RO_FUNCTION("material_index", KX_BlenderMaterial, pyattr_get_materialIndex),
KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_blending, pyattr_set_blending),
+ KX_PYATTRIBUTE_RW_FUNCTION("alpha", KX_BlenderMaterial, pyattr_get_alpha, pyattr_set_alpha),
+ KX_PYATTRIBUTE_RW_FUNCTION("hardness", KX_BlenderMaterial, pyattr_get_hardness, pyattr_set_hardness),
+ KX_PYATTRIBUTE_RW_FUNCTION("specularIntensity", KX_BlenderMaterial, pyattr_get_specular_intensity, pyattr_set_specular_intensity),
+ KX_PYATTRIBUTE_RW_FUNCTION("specularColor", KX_BlenderMaterial, pyattr_get_specular_color, pyattr_set_specular_color),
+ KX_PYATTRIBUTE_RW_FUNCTION("diffuseIntensity", KX_BlenderMaterial, pyattr_get_diffuse_intensity, pyattr_set_diffuse_intensity),
+ KX_PYATTRIBUTE_RW_FUNCTION("diffuseColor", KX_BlenderMaterial, pyattr_get_diffuse_color, pyattr_set_diffuse_color),
+ KX_PYATTRIBUTE_RW_FUNCTION("emit", KX_BlenderMaterial, pyattr_get_emit, pyattr_set_emit),
+
{ NULL } //Sentinel
};
@@ -882,6 +1033,170 @@ PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRI
return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]);
}
+PyObject *KX_BlenderMaterial::pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyFloat_FromDouble(self->GetBLMaterial()->alpha);
+}
+
+int KX_BlenderMaterial::pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ float val = PyFloat_AsDouble(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ CLAMP(val, 0.0f, 1.0f);
+
+ BL_Material *mat = self->GetBLMaterial();
+ mat->alpha = mat->material->alpha = val;
+ return PY_SET_ATTR_SUCCESS;
+}
+PyObject *KX_BlenderMaterial::pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyLong_FromLong(self->GetBLMaterial()->hard);
+}
+
+int KX_BlenderMaterial::pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ int val = PyLong_AsLong(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "material.%s = int: KX_BlenderMaterial, expected a int", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ CLAMP(val, 1, 511);
+
+ BL_Material *mat = self->GetBLMaterial();
+ mat->hard = mat->material->har = val;
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_BlenderMaterial::pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyFloat_FromDouble(self->GetBLMaterial()->spec_f);
+}
+
+int KX_BlenderMaterial::pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ float val = PyFloat_AsDouble(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ CLAMP(val, 0.0f, 1.0f);
+
+ BL_Material *mat = self->GetBLMaterial();
+ mat->spec_f = mat->material->spec = val;
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_BlenderMaterial::pyattr_get_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+ return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR);
+#else
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->speccolor));
+#endif
+}
+
+int KX_BlenderMaterial::pyattr_set_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ MT_Vector3 color;
+ if (!PyVecTo(value, color))
+ return PY_SET_ATTR_FAIL;
+
+ BL_Material *mat = self->GetBLMaterial();
+ color.getValue(mat->speccolor);
+ mat->material->specr = color[0];
+ mat->material->specg = color[1];
+ mat->material->specb = color[2];
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_BlenderMaterial::pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyFloat_FromDouble(self->GetBLMaterial()->ref);
+}
+
+int KX_BlenderMaterial::pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ float val = PyFloat_AsDouble(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ CLAMP(val, 0.0f, 1.0f);
+
+ BL_Material *mat = self->GetBLMaterial();
+ mat->ref = mat->material->ref = val;
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_BlenderMaterial::pyattr_get_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+#ifdef USE_MATHUTILS
+ return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR);
+#else
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->matcolor));
+#endif
+}
+
+int KX_BlenderMaterial::pyattr_set_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ MT_Vector3 color;
+ if (!PyVecTo(value, color))
+ return PY_SET_ATTR_FAIL;
+
+ BL_Material *mat = self->GetBLMaterial();
+ color.getValue(mat->matcolor);
+ mat->material->r = color[0];
+ mat->material->g = color[1];
+ mat->material->b = color[2];
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_BlenderMaterial::pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ return PyFloat_FromDouble(self->GetBLMaterial()->emit);
+}
+
+int KX_BlenderMaterial::pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v);
+ float val = PyFloat_AsDouble(value);
+
+ if (val == -1 && PyErr_Occurred()) {
+ PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name);
+ return PY_SET_ATTR_FAIL;
+ }
+
+ CLAMP(val, 0.0f, 2.0f);
+
+ BL_Material *mat = self->GetBLMaterial();
+ mat->emit = mat->material->emit = val;
+ return PY_SET_ATTR_SUCCESS;
+}
+
int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
{
KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v);
diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h
index b7c64215eaf..df089cb7f99 100644
--- a/source/gameengine/Ketsji/KX_BlenderMaterial.h
+++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h
@@ -15,7 +15,7 @@
#include "BL_Shader.h"
#include "BL_BlenderShader.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "MT_Vector3.h"
#include "MT_Vector4.h"
@@ -30,6 +30,11 @@
struct MTFace;
class KX_Scene;
+
+#ifdef USE_MATHUTILS
+void KX_BlenderMaterial_Mathutils_Callback_Init(void);
+#endif
+
class KX_BlenderMaterial : public PyObjectPlus, public RAS_IPolyMaterial
{
Py_Header
@@ -79,7 +84,7 @@ public:
Material* GetBlenderMaterial() const;
Image* GetBlenderImage() const;
- MTFace* GetMTFace() const;
+ MTexPoly *GetMTexPoly() const;
unsigned int* GetMCol() const;
BL_Texture * getTex (unsigned int idx) {
return (idx < MAXTEX) ? mTextures + idx : NULL;
@@ -99,6 +104,8 @@ public:
virtual void Replace_IScene(SCA_IScene *val);
+ BL_Material *GetBLMaterial();
+
#ifdef WITH_PYTHON
// --------------------------------
virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(mMaterial->matname); }
@@ -107,6 +114,20 @@ public:
static PyObject *pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static PyObject *pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject *pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
KX_PYMETHOD_DOC(KX_BlenderMaterial, getShader);
KX_PYMETHOD_DOC(KX_BlenderMaterial, getMaterialIndex);
@@ -134,6 +155,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 4ab768e4240..644c71a68e4 100644
--- a/source/gameengine/Ketsji/KX_Camera.cpp
+++ b/source/gameengine/Ketsji/KX_Camera.cpp
@@ -31,11 +31,11 @@
*/
-#include "GL/glew.h"
+#include "glew-mx.h"
#include "KX_Camera.h"
#include "KX_Scene.h"
#include "KX_PythonInit.h"
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "KX_PyMath.h"
#include "RAS_ICanvas.h"
@@ -224,6 +224,22 @@ short KX_Camera::GetSensorFit() const
return m_camdata.m_sensor_fit;
}
+/**
+ * Gets the horizontal shift of the sensor - for camera matching.
+ */
+float KX_Camera::GetShiftHorizontal() const
+{
+ return m_camdata.m_shift_x;
+}
+
+/**
+ * Gets the vertical shift of the sensor - for camera matching.
+ */
+float KX_Camera::GetShiftVertical() const
+{
+ return m_camdata.m_shift_y;
+}
+
float KX_Camera::GetCameraNear() const
{
return m_camdata.m_clipstart;
@@ -463,6 +479,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;
}
@@ -528,7 +545,9 @@ PyAttributeDef KX_Camera::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("ortho_scale", KX_Camera, pyattr_get_ortho_scale, pyattr_set_ortho_scale),
KX_PYATTRIBUTE_RW_FUNCTION("near", KX_Camera, pyattr_get_near, pyattr_set_near),
KX_PYATTRIBUTE_RW_FUNCTION("far", KX_Camera, pyattr_get_far, pyattr_set_far),
-
+ KX_PYATTRIBUTE_RW_FUNCTION("shift_x", KX_Camera, pyattr_get_shift_x, pyattr_set_shift_x),
+ KX_PYATTRIBUTE_RW_FUNCTION("shift_y", KX_Camera, pyattr_get_shift_y, pyattr_set_shift_y),
+
KX_PYATTRIBUTE_RW_FUNCTION("useViewport", KX_Camera, pyattr_get_use_viewport, pyattr_set_use_viewport),
KX_PYATTRIBUTE_RW_FUNCTION("projection_matrix", KX_Camera, pyattr_get_projection_matrix, pyattr_set_projection_matrix),
@@ -747,7 +766,7 @@ int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef,
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -772,7 +791,7 @@ int KX_Camera::pyattr_set_fov(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float fov = PyFloat_AsDouble(value);
if (fov <= 0.0) {
- PyErr_SetString(PyExc_AttributeError, "camera.fov = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.fov = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -796,7 +815,7 @@ int KX_Camera::pyattr_set_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *at
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -816,7 +835,7 @@ int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef,
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -836,7 +855,7 @@ int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P
KX_Camera* self = static_cast<KX_Camera*>(self_v);
float param = PyFloat_AsDouble(value);
if (param == -1) {
- PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater then zero");
+ PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater than zero");
return PY_SET_ATTR_FAIL;
}
@@ -845,6 +864,45 @@ int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_Camera::pyattr_get_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Camera* self = static_cast<KX_Camera*>(self_v);
+ return PyFloat_FromDouble(self->m_camdata.m_shift_x);
+}
+
+int KX_Camera::pyattr_set_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_Camera* self = static_cast<KX_Camera*>(self_v);
+ float param = PyFloat_AsDouble(value);
+ if (param == -1) {
+ PyErr_SetString(PyExc_AttributeError, "camera.shift_x = float: KX_Camera, expected a float greater than zero");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->m_camdata.m_shift_x = param;
+ self->m_set_projection_matrix = false;
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_Camera::pyattr_get_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_Camera* self = static_cast<KX_Camera*>(self_v);
+ return PyFloat_FromDouble(self->m_camdata.m_shift_y);
+}
+
+int KX_Camera::pyattr_set_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_Camera* self = static_cast<KX_Camera*>(self_v);
+ float param = PyFloat_AsDouble(value);
+ if (param == -1) {
+ PyErr_SetString(PyExc_AttributeError, "camera.shift_y = float: KX_Camera, expected a float greater than zero");
+ return PY_SET_ATTR_FAIL;
+ }
+
+ self->m_camdata.m_shift_y = param;
+ self->m_set_projection_matrix = false;
+ return PY_SET_ATTR_SUCCESS;
+}
PyObject *KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
@@ -885,7 +943,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 +1052,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 +1095,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..8addf0b7aed 100644
--- a/source/gameengine/Ketsji/KX_Camera.h
+++ b/source/gameengine/Ketsji/KX_Camera.h
@@ -40,7 +40,7 @@
#include "MT_Vector3.h"
#include "MT_Point3.h"
#include "KX_GameObject.h"
-#include "IntValue.h"
+#include "EXP_IntValue.h"
#include "RAS_CameraData.h"
#ifdef WITH_PYTHON
@@ -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;
@@ -206,6 +206,10 @@ public:
float GetSensorHeight() const;
/** Gets the mode FOV is calculating from sensor dimensions */
short GetSensorFit() const;
+ /** Gets the horizontal shift of the sensor - for camera matching */
+ float GetShiftHorizontal() const;
+ /** Gets the vertical shift of the sensor - for camera matching */
+ float GetShiftVertical() const;
/** Gets the near clip distance. */
float GetCameraNear() const;
/** Gets the far clip distance. */
@@ -306,7 +310,11 @@ public:
static int pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
static PyObject* pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
-
+ static PyObject* pyattr_get_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+
static PyObject* pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
static int pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp
index acf30b4866c..f065e3f0001 100644
--- a/source/gameengine/Ketsji/KX_CameraActuator.cpp
+++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp
@@ -40,7 +40,7 @@
#include <float.h>
#include "KX_GameObject.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
@@ -288,19 +288,23 @@ 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) {
+ /* Don't do anything if the cross product is too small.
+ * The camera up-axis becomes unstable and starts to oscillate.
+ * The 0.01f threshold is arbitrary but seems to work well in practice. */
+ float cross = fp1[0] * fp2[1] - fp1[1] * fp2[0];
+ if (cross > 0.01f) {
from[0] -= fac * fp1[1];
from[1] += fac * fp1[0];
}
- else {
+ else if (cross < -0.01f) {
from[0] += fac * fp1[1];
from[1] -= fac * fp1[0];
}
}
- /* CONSTRAINT 5: minimum / maximum afstand */
+ /* CONSTRAINT 5: minimum / maximum distance */
rc[0] = (lookat[0]-from[0]);
rc[1] = (lookat[1]-from[1]);
@@ -323,7 +327,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_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h
index d4d8f195102..dd7ba680ec7 100644
--- a/source/gameengine/Ketsji/KX_CharacterWrapper.h
+++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h
@@ -6,7 +6,7 @@
#ifndef __KX_CHARACTERWRAPPER_H__
#define __KX_CHARACTERWRAPPER_H__
-#include "Value.h"
+#include "EXP_Value.h"
#include "PHY_DynamicTypes.h"
class PHY_ICharacter;
diff --git a/source/gameengine/Ketsji/KX_ClientObjectInfo.h b/source/gameengine/Ketsji/KX_ClientObjectInfo.h
index e947eb4be6d..81ae5b58009 100644
--- a/source/gameengine/Ketsji/KX_ClientObjectInfo.h
+++ b/source/gameengine/Ketsji/KX_ClientObjectInfo.h
@@ -52,19 +52,16 @@ struct KX_ClientObjectInfo
OBACTORSENSOR
} m_type;
KX_GameObject* m_gameobject;
- void* m_auxilary_info;
std::list<SCA_ISensor*> m_sensors;
public:
- KX_ClientObjectInfo(KX_GameObject *gameobject, clienttype type = STATIC, void *auxilary_info = NULL) :
+ KX_ClientObjectInfo(KX_GameObject *gameobject, clienttype type = STATIC) :
m_type(type),
- m_gameobject(gameobject),
- m_auxilary_info(auxilary_info)
+ m_gameobject(gameobject)
{}
KX_ClientObjectInfo(const KX_ClientObjectInfo &copy) :
m_type(copy.m_type),
- m_gameobject(copy.m_gameobject),
- m_auxilary_info(copy.m_auxilary_info)
+ m_gameobject(copy.m_gameobject)
{
}
diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
index e5662b54b83..e07660cef72 100644
--- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp
@@ -41,6 +41,7 @@
#include "KX_GameObject.h"
#include "KX_RayCast.h"
#include "KX_PythonInit.h" // KX_GetActiveScene
+#include "RAS_MeshObject.h"
#include <stdio.h>
@@ -129,15 +130,17 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo *client, KX_RayCast *resu
}
else
{
- if (m_option & KX_ACT_CONSTRAINT_MATERIAL)
- {
- if (client->m_auxilary_info)
- {
- bFound = !strcmp(m_property.Ptr(), ((char*)client->m_auxilary_info));
+ if (m_option & KX_ACT_CONSTRAINT_MATERIAL) {
+ for (unsigned int i = 0; i < m_hitObject->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = m_hitObject->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ bFound = strcmp(m_property.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (bFound)
+ break;
+ }
}
}
- else
- {
+ else {
bFound = m_hitObject->GetProperty(m_property) != NULL;
}
}
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
index 29d92762285..2f32b5e3216 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp
@@ -30,7 +30,7 @@
*/
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "KX_ConstraintWrapper.h"
#include "PHY_IPhysicsEnvironment.h"
diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
index b7124c76439..5e20b7a9aca 100644
--- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h
+++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h
@@ -32,7 +32,7 @@
#ifndef __KX_CONSTRAINTWRAPPER_H__
#define __KX_CONSTRAINTWRAPPER_H__
-#include "Value.h"
+#include "EXP_Value.h"
#include "PHY_DynamicTypes.h"
class KX_ConstraintWrapper : public PyObjectPlus
diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp
index c7f7f586865..07bed647b29 100644
--- a/source/gameengine/Ketsji/KX_Dome.cpp
+++ b/source/gameengine/Ketsji/KX_Dome.cpp
@@ -41,7 +41,7 @@
#include "RAS_CameraData.h"
#include "BLI_math.h"
-#include "GL/glew.h"
+#include "glew-mx.h"
// constructor
KX_Dome::KX_Dome (
@@ -2044,7 +2044,9 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i)
cam->NodeUpdateGS(0.f);
scene->CalculateVisibleMeshes(m_rasterizer,cam);
- scene->UpdateAnimations(m_engine->GetFrameTime());
+
+ m_engine->UpdateAnimations(scene);
+
scene->RenderBuckets(camtrans, m_rasterizer);
}
diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h
index a7e798a3944..420565e62f6 100644
--- a/source/gameengine/Ketsji/KX_Dome.h
+++ b/source/gameengine/Ketsji/KX_Dome.h
@@ -38,7 +38,7 @@
#include "RAS_IRasterizer.h"
#include "KX_KetsjiEngine.h"
-#include "GL/glew.h"
+#include "glew-mx.h"
#include <vector>
#include "MEM_guardedalloc.h"
diff --git a/source/gameengine/Ketsji/KX_FontObject.cpp b/source/gameengine/Ketsji/KX_FontObject.cpp
index 9789a8294ee..420f1f7eb98 100644
--- a/source/gameengine/Ketsji/KX_FontObject.cpp
+++ b/source/gameengine/Ketsji/KX_FontObject.cpp
@@ -35,7 +35,7 @@
#include "KX_Scene.h"
#include "KX_PythonInit.h"
#include "BLI_math.h"
-#include "StringValue.h"
+#include "EXP_StringValue.h"
#include "RAS_IRasterizer.h"
/* paths needed for font load */
@@ -118,7 +118,6 @@ CValue* KX_FontObject::GetReplica()
void KX_FontObject::ProcessReplica()
{
KX_GameObject::ProcessReplica();
- KX_GetActiveScene()->AddFont(this);
}
int GetFontId(VFont *vfont)
diff --git a/source/gameengine/Ketsji/KX_FontObject.h b/source/gameengine/Ketsji/KX_FontObject.h
index 209ab6ca69f..bf70eedfde6 100644
--- a/source/gameengine/Ketsji/KX_FontObject.h
+++ b/source/gameengine/Ketsji/KX_FontObject.h
@@ -54,6 +54,7 @@ public:
*/
virtual CValue* GetReplica();
virtual void ProcessReplica();
+ virtual int GetGameObjectType() { return OBJ_TEXT; }
protected:
std::vector<STR_String> m_text;
diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp
index c6087ac676d..a23af680104 100644
--- a/source/gameengine/Ketsji/KX_GameActuator.cpp
+++ b/source/gameengine/Ketsji/KX_GameActuator.cpp
@@ -178,6 +178,11 @@ bool KX_GameActuator::Update()
// obtain file size:
fseek (fp , 0 , SEEK_END);
marshal_length = ftell(fp);
+ if (marshal_length == -1) {
+ printf("warning: could not read position of '%s'\n", mashal_path);
+ fclose(fp);
+ break;
+ }
rewind(fp);
marshal_buffer = (char*) malloc (sizeof(char)*marshal_length);
diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp
index c681e0842c4..c3da80bc14f 100644
--- a/source/gameengine/Ketsji/KX_GameObject.cpp
+++ b/source/gameengine/Ketsji/KX_GameObject.cpp
@@ -36,14 +36,6 @@
# pragma warning( disable:4786 )
#endif
-#if defined(_WIN64) && !defined(FREE_WINDOWS64)
-typedef unsigned __int64 uint_ptr;
-#elif defined(FREE_WINDOWS64)
-typedef unsigned long long uint_ptr;
-#else
-typedef unsigned long uint_ptr;
-#endif
-
#include "RAS_IPolygonMaterial.h"
#include "KX_BlenderMaterial.h"
#include "KX_GameObject.h"
@@ -55,6 +47,7 @@ typedef unsigned long uint_ptr;
#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"
@@ -76,7 +69,13 @@ typedef unsigned long uint_ptr;
#include "BL_ActionManager.h"
#include "BL_Action.h"
-#include "PyObjectPlus.h" /* python stuff */
+#include "EXP_PyObjectPlus.h" /* python stuff */
+#include "BLI_utildefines.h"
+
+#ifdef WITH_PYTHON
+# include "EXP_PythonCallBack.h"
+# include "python_utildefines.h"
+#endif
// This file defines relationships between parents and children
// in the game engine.
@@ -97,9 +96,10 @@ KX_GameObject::KX_GameObject(
: SCA_IObject(),
m_bDyna(false),
m_layer(0),
+ m_currentLodLevel(0),
+ m_previousLodLevel(0),
m_pBlenderObject(NULL),
m_pBlenderGroupObject(NULL),
- m_bSuspendDynamics(false),
m_bUseObjectColor(false),
m_bIsNegativeScaling(false),
m_objectColor(1.0, 1.0, 1.0, 1.0),
@@ -297,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;
@@ -454,6 +469,11 @@ void KX_GameObject::StopAction(short layer)
GetActionManager()->StopAction(layer);
}
+void KX_GameObject::RemoveTaggedActions()
+{
+ GetActionManager()->RemoveTaggedActions();
+}
+
bool KX_GameObject::IsActionDone(short layer)
{
return GetActionManager()->IsActionDone(layer);
@@ -474,6 +494,11 @@ float KX_GameObject::GetActionFrame(short layer)
return GetActionManager()->GetActionFrame(layer);
}
+const char *KX_GameObject::GetActionName(short layer)
+{
+ return GetActionManager()->GetActionName(layer);
+}
+
void KX_GameObject::SetActionFrame(short layer, float frame)
{
GetActionManager()->SetActionFrame(layer, frame);
@@ -551,13 +576,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)
@@ -575,6 +613,46 @@ 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)
+ return m_pPhysicsController->GetLinearDamping();
+ return 0;
+}
+
+float KX_GameObject::getAngularDamping() const
+{
+ if (m_pPhysicsController)
+ return m_pPhysicsController->GetAngularDamping();
+ return 0;
+}
+
+void KX_GameObject::setLinearDamping(float damping)
+{
+ if (m_pPhysicsController)
+ m_pPhysicsController->SetLinearDamping(damping);
+}
+
+
+void KX_GameObject::setAngularDamping(float damping)
+{
+ if (m_pPhysicsController)
+ m_pPhysicsController->SetAngularDamping(damping);
+}
+
+
+void KX_GameObject::setDamping(float linear, float angular)
+{
+ if (m_pPhysicsController)
+ m_pPhysicsController->SetDamping(linear, angular);
+}
void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local)
@@ -741,35 +819,74 @@ void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh)
m_lodmeshes.push_back(mesh);
}
+
+static float calcHysteresis(KX_Scene *kxscene, LodLevel *lod)
+{
+ float hystvariance = 0.0f;
+
+ if (!kxscene->IsActivedLodHysteresis())
+ return hystvariance;
+
+ short hysteresis = 0;
+ // if exists, LoD level hysteresis will override scene hysteresis
+ if (lod->next->flags & OB_LOD_USE_HYST)
+ hysteresis = lod->next->obhysteresis;
+ else
+ hysteresis = kxscene->GetLodHysteresisValue();
+
+ return hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100;
+}
+
void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos)
{
// Handle dupligroups
- if (this->m_pInstanceObjects) {
- KX_GameObject * instob;
- int count = this->m_pInstanceObjects->GetCount();
+ if (m_pInstanceObjects) {
+ KX_GameObject *instob;
+ int count = m_pInstanceObjects->GetCount();
for (int i = 0; i < count; i++) {
- instob = (KX_GameObject*)this->m_pInstanceObjects->GetValue(i);
+ instob = (KX_GameObject*)m_pInstanceObjects->GetValue(i);
instob->UpdateLod(cam_pos);
}
}
- if (this->m_lodmeshes.empty()) return;
+ if (m_lodmeshes.empty())
+ return;
- MT_Vector3 delta = this->NodeGetWorldPosition() - cam_pos;
+ MT_Vector3 delta = NodeGetWorldPosition() - cam_pos;
float distance2 = delta.length2();
int level = 0;
- Object *bob = this->GetBlenderObject();
- LodLevel *lod = (LodLevel*) bob->lodlevels.first;
+ float hystvariance = 0.0f;
+ Object *bob = GetBlenderObject();
+ LodLevel *lod = (LodLevel *)bob->lodlevels.first;
+ KX_Scene *kxscene = GetScene();
+
for (; lod; lod = lod->next, level++) {
- if (!lod->source || lod->source->type != OB_MESH) level--;
- if (!lod->next || lod->next->distance * lod->next->distance > distance2) break;
- }
+ if (!lod->source || lod->source->type != OB_MESH)
+ level--;
- RAS_MeshObject *mesh = this->m_lodmeshes[level];
+ if (!lod->next)
+ break;
+
+ if (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;
+ }
+ }
- 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);
}
}
@@ -930,27 +1047,6 @@ KX_GameObject::SetVisible(
}
}
-bool KX_GameObject::GetCulled()
-{
- // If we're set to not cull, double-check with
- // the mesh slots first. This is kind of nasty, but
- // it allows us to get proper culling information.
- if (!m_bCulled)
- {
- SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots);
- for (mit.begin(); !mit.end(); ++mit)
- {
- if ((*mit)->m_bCulled)
- {
- m_bCulled = true;
- break;
- }
- }
- }
-
- return m_bCulled;
-}
-
static void setOccluder_recursive(SG_Node* node, bool v)
{
NodeList& children = node->GetSGChildren();
@@ -1486,36 +1582,27 @@ void KX_GameObject::RegisterCollisionCallbacks()
pe->AddSensor(spc);
}
}
-void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider)
+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)))
- {
- PyObject* args = Py_BuildValue("(O)", collider->GetProxy()); // save python creating each call
- PyObject *func;
- PyObject *ret;
+#ifdef WITH_PYTHON
+ if (!m_collisionCallbacks || PyList_GET_SIZE(m_collisionCallbacks) == 0)
+ return;
- // Iterate the list and run the callbacks
- for (Py_ssize_t pos=0; pos < len; pos++)
- {
- func = PyList_GET_ITEM(collision_callbacks, pos);
- ret = PyObject_Call(func, args, NULL);
+ /** Current logic controller is set by each python logic bricks before run,
+ * but if no python logic brick ran the logic manager can be wrong
+ * (if the user use muti scenes) and it will cause problems with function
+ * ConvertPythonToGameObject which use the current logic manager for object's name.
+ * Note: the scene is already set in logic frame loop.
+ */
+ SCA_ILogicBrick::m_sCurrentLogicManager = GetScene()->GetLogicManager();
- 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));
- Py_DECREF(args);
+ 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
@@ -1529,7 +1616,8 @@ void KX_GameObject::Resume(void)
{
if (m_suspended) {
SCA_IObject::Resume();
- if (GetPhysicsController())
+ // Child objects must be static, so we block changing to dynamic
+ if (GetPhysicsController() && !GetParent())
GetPhysicsController()->RestoreDynamics();
m_suspended = false;
@@ -1587,9 +1675,11 @@ CListValue* KX_GameObject::GetChildrenRecursive()
KX_Scene* KX_GameObject::GetScene()
{
SG_Node* node = this->GetSGNode();
- KX_Scene* scene = static_cast<KX_Scene*>(node->GetSGClientInfo());
-
- return scene;
+ if (node == NULL) {
+ // this happens for object in non active layers, rely on static scene then
+ return KX_GetActiveScene();
+ }
+ return static_cast<KX_Scene*>(node->GetSGClientInfo());
}
/* ---------------------------------------------------------------------
@@ -1823,7 +1913,7 @@ static Mathutils_Callback mathutils_kxgameob_matrix_cb = {
void KX_GameObject_Mathutils_Callback_Init(void)
{
- // register mathutils callbacks, ok to run more then once.
+ // register mathutils callbacks, ok to run more than once.
mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb);
mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb);
}
@@ -1842,10 +1932,11 @@ PyMethodDef KX_GameObject::Methods[] = {
{"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS},
{"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS},
{"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS},
+ {"setDamping", (PyCFunction) KX_GameObject::sPySetDamping, METH_VARARGS},
{"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},
@@ -1873,6 +1964,7 @@ PyMethodDef KX_GameObject::Methods[] = {
KX_PYMETHODTABLE_KEYWORDS(KX_GameObject, playAction),
KX_PYMETHODTABLE(KX_GameObject, stopAction),
KX_PYMETHODTABLE(KX_GameObject, getActionFrame),
+ KX_PYMETHODTABLE(KX_GameObject, getActionName),
KX_PYMETHODTABLE(KX_GameObject, setActionFrame),
KX_PYMETHODTABLE(KX_GameObject, isPlayingAction),
@@ -1883,6 +1975,7 @@ PyMethodDef KX_GameObject::Methods[] = {
};
PyAttributeDef KX_GameObject::Attributes[] = {
+ KX_PYATTRIBUTE_INT_RO("currentLodLevel", KX_GameObject, m_currentLodLevel),
KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name),
KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent),
KX_PYATTRIBUTE_RO_FUNCTION("groupMembers", KX_GameObject, pyattr_get_group_members),
@@ -1890,8 +1983,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),
@@ -1901,6 +1997,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),
@@ -1917,6 +2015,8 @@ PyAttributeDef KX_GameObject::Attributes[] = {
KX_PYATTRIBUTE_RW_FUNCTION("angularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_worldAngularVelocity),
KX_PYATTRIBUTE_RW_FUNCTION("localAngularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_localAngularVelocity),
KX_PYATTRIBUTE_RW_FUNCTION("worldAngularVelocity", KX_GameObject, pyattr_get_worldAngularVelocity, pyattr_set_worldAngularVelocity),
+ KX_PYATTRIBUTE_RW_FUNCTION("linearDamping", KX_GameObject, pyattr_get_linearDamping, pyattr_set_linearDamping),
+ KX_PYATTRIBUTE_RW_FUNCTION("angularDamping", KX_GameObject, pyattr_get_angularDamping, pyattr_set_angularDamping),
KX_PYATTRIBUTE_RO_FUNCTION("children", KX_GameObject, pyattr_get_children),
KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive),
KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict),
@@ -2245,6 +2345,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);
@@ -2301,6 +2451,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);
@@ -2347,6 +2510,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)
{
@@ -2393,7 +2604,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());
@@ -2415,7 +2628,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());
@@ -2437,7 +2652,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())
@@ -2449,7 +2666,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());
@@ -2474,7 +2693,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());
@@ -2498,7 +2719,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());
@@ -2520,7 +2743,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());
@@ -2622,7 +2847,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));
@@ -2644,7 +2871,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));
@@ -2666,7 +2895,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));
@@ -2688,7 +2919,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));
@@ -2707,6 +2940,34 @@ int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTR
return PY_SET_ATTR_SUCCESS;
}
+PyObject *KX_GameObject::pyattr_get_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ return PyFloat_FromDouble(self->getLinearDamping());
+}
+
+int KX_GameObject::pyattr_set_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ float val = PyFloat_AsDouble(value);
+ self->setLinearDamping(val);
+ return PY_SET_ATTR_SUCCESS;
+}
+
+PyObject *KX_GameObject::pyattr_get_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ return PyFloat_FromDouble(self->getAngularDamping());
+}
+
+int KX_GameObject::pyattr_set_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value)
+{
+ KX_GameObject* self = static_cast<KX_GameObject*>(self_v);
+ float val = PyFloat_AsDouble(value);
+ self->setAngularDamping(val);
+ return PY_SET_ATTR_SUCCESS;
+}
+
PyObject *KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef)
{
@@ -2781,7 +3042,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());
@@ -3003,6 +3266,18 @@ PyObject *KX_GameObject::PySetAngularVelocity(PyObject *args)
return NULL;
}
+PyObject *KX_GameObject::PySetDamping(PyObject *args)
+{
+ float linear;
+ float angular;
+
+ if (!PyArg_ParseTuple(args,"ff|i:setDamping", &linear, &angular))
+ return NULL;
+
+ setDamping(linear, angular);
+ Py_RETURN_NONE;
+}
+
PyObject *KX_GameObject::PySetVisible(PyObject *args)
{
int visible, recursive = 0;
@@ -3147,10 +3422,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;
}
@@ -3158,7 +3439,8 @@ PyObject *KX_GameObject::PySuspendDynamics()
PyObject *KX_GameObject::PyRestoreDynamics()
{
- if (GetPhysicsController())
+ // Child objects must be static, so we block changing to dynamic
+ if (GetPhysicsController() && !GetParent())
GetPhysicsController()->RestoreDynamics();
Py_RETURN_NONE;
}
@@ -3200,12 +3482,12 @@ PyObject *KX_GameObject::PyGetAxisVect(PyObject *value)
PyObject *KX_GameObject::PyGetPhysicsId()
{
PHY_IPhysicsController* ctrl = GetPhysicsController();
- uint_ptr physid=0;
+ unsigned long long physid = 0;
if (ctrl)
{
- physid= (uint_ptr)ctrl;
+ physid = (unsigned long long)ctrl;
}
- return PyLong_FromLong((long)physid);
+ return PyLong_FromUnsignedLongLong(physid);
}
PyObject *KX_GameObject::PyGetPropertyNames()
@@ -3648,7 +3930,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, stopAction,
"stopAction(layer=0)\n"
"Stop playing the action on the given layer\n")
{
- short layer=0;
+ short layer = 0;
if (!PyArg_ParseTuple(args, "|h:stopAction", &layer))
return NULL;
@@ -3664,7 +3946,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getActionFrame,
"getActionFrame(layer=0)\n"
"Gets the current frame of the action playing in the supplied layer\n")
{
- short layer=0;
+ short layer = 0;
if (!PyArg_ParseTuple(args, "|h:getActionFrame", &layer))
return NULL;
@@ -3674,11 +3956,25 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getActionFrame,
return PyFloat_FromDouble(GetActionFrame(layer));
}
+KX_PYMETHODDEF_DOC(KX_GameObject, getActionName,
+ "getActionName(layer=0)\n"
+ "Gets the name of the current action playing in the supplied layer\n")
+{
+ short layer = 0;
+
+ if (!PyArg_ParseTuple(args, "|h:getActionName", &layer))
+ return NULL;
+
+ layer_check(layer, "getActionName");
+
+ return PyUnicode_FromString(GetActionName(layer));
+}
+
KX_PYMETHODDEF_DOC(KX_GameObject, setActionFrame,
"setActionFrame(frame, layer=0)\n"
"Set the current frame of the action playing in the supplied layer\n")
{
- short layer=0;
+ short layer = 0;
float frame;
if (!PyArg_ParseTuple(args, "f|h:setActionFrame", &frame, &layer))
@@ -3695,7 +3991,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, isPlayingAction,
"isPlayingAction(layer=0)\n"
"Checks to see if there is an action playing in the given layer\n")
{
- short layer=0;
+ short layer = 0;
if (!PyArg_ParseTuple(args, "|h:isPlayingAction", &layer))
return NULL;
@@ -3793,11 +4089,11 @@ bool ConvertPythonToGameObject(PyObject *value, KX_GameObject **object, bool py_
}
}
- if ( PyObject_TypeCheck(value, &KX_GameObject::Type) ||
- PyObject_TypeCheck(value, &KX_LightObject::Type) ||
- PyObject_TypeCheck(value, &KX_Camera::Type) ||
- PyObject_TypeCheck(value, &KX_FontObject::Type) ||
- PyObject_TypeCheck(value, &KX_NavMeshObject::Type))
+ if (PyObject_TypeCheck(value, &KX_GameObject::Type) ||
+ PyObject_TypeCheck(value, &KX_LightObject::Type) ||
+ PyObject_TypeCheck(value, &KX_Camera::Type) ||
+ PyObject_TypeCheck(value, &KX_FontObject::Type) ||
+ PyObject_TypeCheck(value, &KX_NavMeshObject::Type))
{
*object = static_cast<KX_GameObject*>BGE_PROXY_REF(value);
diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h
index d4fa4851696..c10802a83b2 100644
--- a/source/gameengine/Ketsji/KX_GameObject.h
+++ b/source/gameengine/Ketsji/KX_GameObject.h
@@ -40,7 +40,7 @@
#include <stddef.h>
-#include "ListValue.h"
+#include "EXP_ListValue.h"
#include "SCA_IObject.h"
#include "SG_Node.h"
#include "MT_Transform.h"
@@ -49,6 +49,7 @@
#include "CTR_HashedPtr.h"
#include "KX_Scene.h"
#include "KX_KetsjiEngine.h" /* for m_anim_framerate */
+#include "DNA_constraint_types.h" /* for constraint replication */
#include "DNA_object_types.h"
#include "SCA_LogicManager.h" /* for ConvertPythonToGameObject to search object names */
@@ -88,18 +89,19 @@ protected:
int m_layer;
std::vector<RAS_MeshObject*> m_meshes;
std::vector<RAS_MeshObject*> m_lodmeshes;
+ int m_currentLodLevel;
+ short m_previousLodLevel;
SG_QList m_meshSlots; // head of mesh slots of this
struct Object* m_pBlenderObject;
struct Object* m_pBlenderGroupObject;
- bool m_bSuspendDynamics;
bool m_bUseObjectColor;
bool m_bIsNegativeScaling;
MT_Vector4 m_objectColor;
// Bit fields for user control over physics collisions
- short m_userCollisionGroup;
- short m_userCollisionMask;
+ unsigned short m_userCollisionGroup;
+ unsigned short m_userCollisionMask;
// visible = user setting
// culled = while rendering, depending on camera
@@ -116,6 +118,7 @@ protected:
SG_Node* m_pSGNode;
MT_CmMatrix4x4 m_OpenGL_4x4Matrix;
+ std::vector<bRigidBodyJointConstraint*> m_constraints;
KX_ObstacleSimulation* m_pObstacleSimulation;
@@ -192,6 +195,14 @@ public:
void
UpdateBlenderObjectMatrix(Object* blendobj=NULL);
+ /**
+ * Used for constraint replication for group instances.
+ * The list of constraints is filled during data conversion.
+ */
+ void AddConstraint(bRigidBodyJointConstraint *cons);
+ std::vector<bRigidBodyJointConstraint*> GetConstraints();
+ void ClearConstraints();
+
/**
* Get a pointer to the game object that is the parent of
* this object. Or NULL if there is no parent. The returned
@@ -266,6 +277,11 @@ public:
float GetActionFrame(short layer);
/**
+ * Gets the name of the current action
+ */
+ const char *GetActionName(short layer);
+
+ /**
* Sets the current frame of an action
*/
void SetActionFrame(short layer, float frame);
@@ -291,6 +307,11 @@ public:
void StopAction(short layer);
/**
+ * Remove playing tagged actions.
+ */
+ void RemoveTaggedActions();
+
+ /**
* Check if an action has finished playing
*/
bool IsActionDone(short layer);
@@ -506,8 +527,17 @@ public:
*/
void ActivateGraphicController(bool recurse);
- void SetUserCollisionGroup(short filter);
- void SetUserCollisionMask(short mask);
+ /** Set the object's collison group
+ * \param filter The group bitfield
+ */
+ void SetUserCollisionGroup(unsigned short filter);
+
+ /** Set the object's collison mask
+ * \param filter The mask bitfield
+ */
+ void SetUserCollisionMask(unsigned short mask);
+ unsigned short GetUserCollisionGroup();
+ unsigned short GetUserCollisionMask();
/**
* Extra broadphase check for user controllable collisions
*/
@@ -607,6 +637,8 @@ public:
return m_bDyna;
}
+ bool IsDynamicsSuspended() const;
+
/**
* Should we record animation for this object?
*/
@@ -684,6 +716,12 @@ public:
bool local
);
+ virtual float getLinearDamping() const;
+ virtual float getAngularDamping() const;
+ virtual void setLinearDamping(float damping);
+ virtual void setAngularDamping(float damping);
+ virtual void setDamping(float linear, float angular);
+
/**
* Update the physics object transform based upon the current SG_Node
* position.
@@ -852,10 +890,10 @@ public:
/**
* Was this object culled?
*/
- bool
+ inline bool
GetCulled(
void
- );
+ ) { return m_bCulled; }
/**
* Set culled flag of this object
@@ -886,7 +924,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
);
@@ -913,7 +951,7 @@ public:
void RegisterCollisionCallbacks();
void UnregisterCollisionCallbacks();
- void RunCollisionCallbacks(KX_GameObject *collider);
+ void RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal);
/**
* Stop making progress
*/
@@ -965,6 +1003,7 @@ public:
KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity);
KX_PYMETHOD_VARARGS(KX_GameObject,SetAngularVelocity);
KX_PYMETHOD_VARARGS(KX_GameObject,GetVelocity);
+ KX_PYMETHOD_VARARGS(KX_GameObject,SetDamping);
KX_PYMETHOD_NOARGS(KX_GameObject,GetReactionForce);
@@ -976,7 +1015,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);
@@ -1003,6 +1042,7 @@ public:
KX_PYMETHOD_DOC(KX_GameObject, playAction);
KX_PYMETHOD_DOC(KX_GameObject, stopAction);
KX_PYMETHOD_DOC(KX_GameObject, getActionFrame);
+ KX_PYMETHOD_DOC(KX_GameObject, getActionName);
KX_PYMETHOD_DOC(KX_GameObject, setActionFrame);
KX_PYMETHOD_DOC(KX_GameObject, isPlayingAction);
@@ -1020,10 +1060,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);
@@ -1066,10 +1111,18 @@ 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);
static int pyattr_set_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
+ static PyObject* pyattr_get_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
+ static int pyattr_set_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value);
/* Experimental! */
static PyObject* pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef);
diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h
index a07d4b2195c..2e1c16c6e32 100644
--- a/source/gameengine/Ketsji/KX_ISceneConverter.h
+++ b/source/gameengine/Ketsji/KX_ISceneConverter.h
@@ -33,7 +33,7 @@
#define __KX_ISCENECONVERTER_H__
#include "STR_String.h"
-#include "KX_Python.h"
+#include "EXP_Python.h"
#ifdef WITH_CXX_GUARDEDALLOC
#include "MEM_guardedalloc.h"
@@ -45,8 +45,8 @@ class KX_ISceneConverter
{
public:
- KX_ISceneConverter() :addInitFromFrame(false) {}//this addInitFromFrame is a back hack, todo remove
- virtual ~KX_ISceneConverter () {};
+ KX_ISceneConverter() {}
+ virtual ~KX_ISceneConverter () {}
/*
* scenename: name of the scene to be converted,
@@ -59,7 +59,7 @@ public:
class RAS_IRasterizer* rendertools,
class RAS_ICanvas* canvas,
bool libloading=false)=0;
-
+
virtual void RemoveScene(class KX_Scene *scene)=0;
// handle any pending merges from asynchronous loads
@@ -69,11 +69,9 @@ public:
virtual void SetNewFileName(const STR_String& filename) = 0;
virtual bool TryAndLoadNewFile() = 0;
- bool addInitFromFrame;//rcruiz
virtual void ResetPhysicsObjectsAnimationIpo(bool clearIpo) = 0;
-
///this generates ipo curves for position, rotation, allowing to use game physics in animation
virtual void WritePhysicsObjectToAnimationIpo(int frameNumber) = 0;
virtual void TestHandlesPhysicsObjectToAnimationIpo() = 0;
diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp
index 1597d7f8809..ec7a4146b7d 100644
--- a/source/gameengine/Ketsji/KX_IpoActuator.cpp
+++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp
@@ -36,7 +36,7 @@
#include "KX_IpoActuator.h"
#include "KX_GameObject.h"
-#include "FloatValue.h"
+#include "EXP_FloatValue.h"
#include "KX_KetsjiEngine.h"
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 14772cda113..72c512589a4 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp
@@ -41,11 +41,11 @@
#include "KX_KetsjiEngine.h"
-#include "ListValue.h"
-#include "IntValue.h"
-#include "VectorValue.h"
-#include "BoolValue.h"
-#include "FloatValue.h"
+#include "EXP_ListValue.h"
+#include "EXP_IntValue.h"
+#include "EXP_VectorValue.h"
+#include "EXP_BoolValue.h"
+#include "EXP_FloatValue.h"
#include "RAS_BucketManager.h"
#include "RAS_Rect.h"
@@ -62,11 +62,6 @@
#include "KX_PyConstraintBinding.h"
#include "PHY_IPhysicsEnvironment.h"
-#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
-# include "AUD_I3DDevice.h"
-#endif
-
#include "NG_NetworkScene.h"
#include "NG_NetworkDeviceInterface.h"
@@ -80,9 +75,6 @@
#include "KX_NavMeshObject.h"
-// If define: little test for Nzc: guarded drawing. If the canvas is
-// not valid, skip rendering this frame.
-//#define NZC_GUARDED_OUTPUT
#define DEFAULT_LOGIC_TIC_RATE 60.0
//#define DEFAULT_PHYSICS_TIC_RATE 60.0
@@ -140,6 +132,7 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system)
m_frameTime(0.f),
m_clockTime(0.f),
m_previousClockTime(0.f),
+ m_previousAnimTime(0.f),
m_exitcode(KX_EXIT_REQUEST_NO_REQUEST),
@@ -314,10 +307,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) {
@@ -391,8 +385,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();
@@ -477,7 +473,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());
@@ -686,6 +682,9 @@ bool KX_KetsjiEngine::NextFrame()
SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE);
scene->UpdateParents(m_frameTime);
+ // update levels of detail
+ scene->UpdateObjectLods();
+
m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
SG_SetActiveStage(SG_STAGE_PHYSICS2);
scene->GetPhysicsEnvironment()->BeginFrame();
@@ -730,64 +729,6 @@ bool KX_KetsjiEngine::NextFrame()
frames--;
}
- bool bUseAsyncLogicBricks= false;//true;
-
- if (bUseAsyncLogicBricks)
- {
- // Logic update sub frame: this will let some logic bricks run at the
- // full frame rate.
- for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit)
- // for each scene, call the proceed functions
- {
- KX_Scene* scene = *sceneit;
-
- if (!scene->IsSuspended())
- {
- // if the scene was suspended recalcutlate the delta tu "curtime"
- m_suspendedtime = scene->getSuspendedTime();
- if (scene->getSuspendedTime()!=0.0)
- scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime());
- m_suspendeddelta = scene->getSuspendedDelta();
-
- // set Python hooks for each scene
-#ifdef WITH_PYTHON
- PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
-#endif
- KX_SetActiveScene(scene);
-
- m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
- SG_SetActiveStage(SG_STAGE_PHYSICS1);
- scene->UpdateParents(m_clockTime);
-
- // Perform physics calculations on the scene. This can involve
- // many iterations of the physics solver.
- m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true);
- scene->GetPhysicsEnvironment()->ProceedDeltaTime(m_clockTime,timestep,timestep);
- // Update scenegraph after physics step. This maps physics calculations
- // into node positions.
- m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
- SG_SetActiveStage(SG_STAGE_PHYSICS2);
- scene->UpdateParents(m_clockTime);
-
- // Do some cleanup work for this logic frame
- m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true);
- scene->LogicUpdateFrame(m_clockTime, false);
-
- // Actuators can affect the scenegraph
- m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
- SG_SetActiveStage(SG_STAGE_ACTUATOR);
- scene->UpdateParents(m_clockTime);
-
- scene->setSuspendedTime(0.0);
- } // suspended
- else
- if (scene->getSuspendedTime()==0.0)
- scene->setSuspendedTime(m_clockTime);
-
- m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true);
- }
- }
-
// Start logging time spend outside main loop
m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true);
@@ -855,7 +796,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();
@@ -912,7 +853,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();
@@ -992,54 +933,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;
@@ -1124,6 +1017,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();
@@ -1155,14 +1065,13 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene)
raslight->BindShadowBuffer(m_canvas, cam, camtrans);
/* update scene */
- m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true);
scene->CalculateVisibleMeshes(m_rasterizer, cam, raslight->GetShadowLayer());
m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
- scene->UpdateAnimations(GetFrameTime());
-
+ 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();
@@ -1187,6 +1096,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
@@ -1238,6 +1154,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
nearfrust,
farfrust,
cam->GetSensorFit(),
+ cam->GetShiftHorizontal(),
+ cam->GetShiftVertical(),
frustum
);
if (!cam->GetViewport()) {
@@ -1258,6 +1176,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
cam->GetSensorWidth(),
cam->GetSensorHeight(),
cam->GetSensorFit(),
+ cam->GetShiftHorizontal(),
+ cam->GetShiftVertical(),
nearfrust,
farfrust,
frustum
@@ -1297,13 +1217,13 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam)
m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true);
SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE);
-
- scene->UpdateAnimations(GetFrameTime());
+ 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
@@ -1322,13 +1242,20 @@ 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();
+ m_rasterizer->FlushDebugShapes(scene);
scene->Render2DFilters(m_canvas);
+
#ifdef WITH_PYTHON
+ PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment());
scene->RunDrawingCallbacks(scene->GetPostDrawCB());
+
+ // Python draw callback can also call debug draw functions, so we have to clear debug shapes.
+ m_rasterizer->FlushDebugShapes(scene);
#endif
}
@@ -1734,18 +1661,17 @@ void KX_KetsjiEngine::AddScheduledScenes()
bool KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene)
{
- // Don't allow replacement if the new scene doesn't exists.
- // Allows smarter game design (used to have no check here).
- // Note that it creates a small backward compatbility issue
- // for a game that did a replace followed by a lib load with the
- // new scene in the lib => it won't work anymore, the lib
- // must be loaded before doing the replace.
- if (m_sceneconverter->GetBlenderSceneForName(newscene) != NULL)
- {
- m_replace_scenes.push_back(std::make_pair(oldscene,newscene));
- return true;
- }
- return false;
+ // Don't allow replacement if the new scene doesn't exists.
+ // Allows smarter game design (used to have no check here).
+ // Note that it creates a small backward compatbility issue
+ // for a game that did a replace followed by a lib load with the
+ // new scene in the lib => it won't work anymore, the lib
+ // must be loaded before doing the replace.
+ if (m_sceneconverter->GetBlenderSceneForName(newscene) != NULL) {
+ m_replace_scenes.push_back(std::make_pair(oldscene,newscene));
+ return true;
+ }
+ return false;
}
// replace scene is not the same as removing and adding because the
@@ -1767,21 +1693,20 @@ void KX_KetsjiEngine::ReplaceScheduledScenes()
int i=0;
/* Scenes are not supposed to be included twice... I think */
KX_SceneList::iterator sceneit;
- for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++)
- {
- KX_Scene* scene = *sceneit;
- if (scene->GetName() == oldscenename)
- {
- // avoid crash if the new scene doesn't exist, just do nothing
- Scene *blScene = m_sceneconverter->GetBlenderSceneForName(newscenename);
- if (blScene) {
- m_sceneconverter->RemoveScene(scene);
- KX_Scene* tmpscene = CreateScene(blScene);
- m_scenes[i]=tmpscene;
- PostProcessScene(tmpscene);
- } else {
- printf("warning: scene %s could not be found, not replaced!\n",newscenename.ReadPtr());
- }
+ for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++) {
+ KX_Scene* scene = *sceneit;
+ if (scene->GetName() == oldscenename) {
+ // avoid crash if the new scene doesn't exist, just do nothing
+ Scene *blScene = m_sceneconverter->GetBlenderSceneForName(newscenename);
+ if (blScene) {
+ m_sceneconverter->RemoveScene(scene);
+ KX_Scene* tmpscene = CreateScene(blScene);
+ m_scenes[i]=tmpscene;
+ PostProcessScene(tmpscene);
+ }
+ else {
+ printf("warning: scene %s could not be found, not replaced!\n",newscenename.ReadPtr());
+ }
}
i++;
}
@@ -1825,6 +1750,16 @@ void KX_KetsjiEngine::SetAnimRecordMode(bool animation_record, int startFrame)
m_currentFrame = startFrame;
}
+int KX_KetsjiEngine::getAnimRecordFrame() const
+{
+ return m_currentFrame;
+}
+
+void KX_KetsjiEngine::setAnimRecordFrame(int framenr)
+{
+ m_currentFrame = framenr;
+}
+
bool KX_KetsjiEngine::GetUseFixedTime(void) const
{
return m_bFixedTime;
diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h
index 2b80e3bd69a..04e09c8db15 100644
--- a/source/gameengine/Ketsji/KX_KetsjiEngine.h
+++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h
@@ -38,7 +38,7 @@
#include "STR_String.h"
#include "KX_ISystem.h"
#include "KX_Scene.h"
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "KX_WorldInfo.h"
#include <vector>
@@ -111,6 +111,7 @@ private:
double m_frameTime;//discrete timestamp of the 'game logic frame'
double m_clockTime;//current time
double m_previousClockTime;//previous clock time
+ double m_previousAnimTime; //the last time animations were updated
double m_remainingTime;
static int m_maxLogicFrame; /* maximum number of consecutive logic frame */
@@ -204,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);
@@ -226,6 +225,9 @@ public:
KX_ISceneConverter* GetSceneConverter() { return m_sceneconverter; }
void SetAnimRecordMode(bool animation_record, int startFrame);
+ int getAnimRecordFrame() const;
+ void setAnimRecordFrame(int framenr);
+
RAS_IRasterizer* GetRasterizer() { return m_rasterizer; }
RAS_ICanvas* GetCanvas() { return m_canvas; }
SCA_IInputDevice* GetKeyboardDevice() { return m_keyboarddevice; }
@@ -258,7 +260,7 @@ public:
void ConvertAndAddScene(const STR_String& scenename,bool overlay);
void RemoveScene(const STR_String& scenename);
- bool ReplaceScene(const STR_String& oldscene,const STR_String& newscene);
+ bool ReplaceScene(const STR_String& oldscene,const STR_String& newscene);
void SuspendScene(const STR_String& scenename);
void ResumeScene(const STR_String& scenename);
@@ -273,6 +275,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_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp
index a6f2f728674..c98766c9c81 100644
--- a/source/gameengine/Ketsji/KX_MeshProxy.cpp
+++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp
@@ -43,7 +43,7 @@
#include "KX_PyMath.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
PyTypeObject KX_MeshProxy::Type = {
PyVarObject_HEAD_INIT(NULL, 0)
diff --git a/source/gameengine/Ketsji/KX_MouseActuator.cpp b/source/gameengine/Ketsji/KX_MouseActuator.cpp
index aae5d18189a..154ad1da3a1 100644
--- a/source/gameengine/Ketsji/KX_MouseActuator.cpp
+++ b/source/gameengine/Ketsji/KX_MouseActuator.cpp
@@ -126,24 +126,33 @@ bool KX_MouseActuator::Update()
float movement[2];
MT_Vector3 rotation;
float setposition[2] = {0.0};
+ float center_x = 0.5, center_y = 0.5;
getMousePosition(position);
movement[0] = position[0];
movement[1] = position[1];
+ //preventing undesired drifting when resolution is odd
+ if ((m_canvas->GetWidth() % 2) != 0) {
+ center_x = ((m_canvas->GetWidth() - 1.0) / 2.0) / (m_canvas->GetWidth());
+ }
+ if ((m_canvas->GetHeight() % 2) != 0) {
+ center_y = ((m_canvas->GetHeight() - 1.0) / 2.0) / (m_canvas->GetHeight());
+ }
+
//preventing initial skipping.
if ((m_oldposition[0] <= -0.9) && (m_oldposition[1] <= -0.9)) {
if (m_reset_x) {
- m_oldposition[0] = 0.5;
+ m_oldposition[0] = center_x;
}
else {
m_oldposition[0] = position[0];
}
if (m_reset_y) {
- m_oldposition[1] = 0.5;
+ m_oldposition[1] = center_y;
}
else {
m_oldposition[1] = position[1];
@@ -156,8 +165,8 @@ bool KX_MouseActuator::Update()
if (m_use_axis_x) {
if (m_reset_x) {
- setposition[0] = 0.5;
- movement[0] -= 0.5;
+ setposition[0] = center_x;
+ movement[0] -= center_x;
}
else {
setposition[0] = position[0];
@@ -166,12 +175,10 @@ bool KX_MouseActuator::Update()
movement[0] *= -1.0;
- /* Don't apply the rotation when width resolution is odd (+ little movement) to
- avoid undesired drifting or when we are under a certain threshold for mouse
+ /* Don't apply the rotation when we are under a certain threshold for mouse
movement */
- if (!((m_canvas->GetWidth() % 2 != 0) && MT_abs(movement[0]) < 0.01) &&
- ((movement[0] > (m_threshold[0] / 10.0)) ||
+ if (((movement[0] > (m_threshold[0] / 10.0)) ||
((movement[0] * (-1.0)) > (m_threshold[0] / 10.0)))) {
movement[0] *= m_sensitivity[0];
@@ -209,15 +216,15 @@ bool KX_MouseActuator::Update()
}
}
else {
- setposition[0] = 0.5;
+ setposition[0] = center_x;
}
//Calculating Y axis.
if (m_use_axis_y) {
if (m_reset_y) {
- setposition[1] = 0.5;
- movement[1] -= 0.5;
+ setposition[1] = center_y;
+ movement[1] -= center_y;
}
else {
setposition[1] = position[1];
@@ -226,12 +233,10 @@ bool KX_MouseActuator::Update()
movement[1] *= -1.0;
- /* Don't apply the rotation when height resolution is odd (+ little movement) to
- avoid undesired drifting or when we are under a certain threshold for mouse
+ /* Don't apply the rotation when we are under a certain threshold for mouse
movement */
- if (!((m_canvas->GetHeight() % 2 != 0) && MT_abs(movement[1]) < 0.01) &&
- ((movement[1] > (m_threshold[1] / 10.0)) ||
+ if (((movement[1] > (m_threshold[1] / 10.0)) ||
((movement[1] * (-1.0)) > (m_threshold[1] / 10.0)))) {
movement[1] *= m_sensitivity[1];
@@ -270,10 +275,13 @@ bool KX_MouseActuator::Update()
}
}
else {
- setposition[1] = 0.5;
+ setposition[1] = center_y;
}
- setMousePosition(setposition[0], setposition[1]);
+ // only trigger mouse event when it is necessary
+ if (m_oldposition[0] != position[0] || m_oldposition[1] != position[1]) {
+ setMousePosition(setposition[0], setposition[1]);
+ }
m_oldposition[0] = position[0];
m_oldposition[1] = position[1];
@@ -311,7 +319,7 @@ void KX_MouseActuator::ProcessReplica()
void KX_MouseActuator::getMousePosition(float* pos)
{
- MT_assert(!m_mouse);
+ MT_assert(m_mouse);
const SCA_InputEvent & xevent = m_mouse->GetEventValue(SCA_IInputDevice::KX_MOUSEX);
const SCA_InputEvent & yevent = m_mouse->GetEventValue(SCA_IInputDevice::KX_MOUSEY);
@@ -329,7 +337,7 @@ void KX_MouseActuator::setMousePosition(float fx, float fy)
m_canvas->SetMousePosition(x, y);
}
-#ifndef DISABLE_PYTHON
+#ifdef WITH_PYTHON
/* ------------------------------------------------------------------------- */
/* Python functions */
@@ -399,8 +407,8 @@ int KX_MouseActuator::pyattr_set_limit_x(void *self_v, const KX_PYATTRIBUTE_DEF
if (PyList_Size(value) != 2)
return PY_SET_ATTR_FAIL;
- item1 = PyList_GetItem(value, 0);
- item2 = PyList_GetItem(value, 1);
+ item1 = PyList_GET_ITEM(value, 0);
+ item2 = PyList_GET_ITEM(value, 1);
if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
return PY_SET_ATTR_FAIL;
@@ -430,8 +438,8 @@ int KX_MouseActuator::pyattr_set_limit_y(void *self_v, const KX_PYATTRIBUTE_DEF
if (PyList_Size(value) != 2)
return PY_SET_ATTR_FAIL;
- item1 = PyList_GetItem(value, 0);
- item2 = PyList_GetItem(value, 1);
+ item1 = PyList_GET_ITEM(value, 0);
+ item2 = PyList_GET_ITEM(value, 1);
if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
return PY_SET_ATTR_FAIL;
@@ -461,8 +469,8 @@ int KX_MouseActuator::pyattr_set_angle(void *self_v, const KX_PYATTRIBUTE_DEF *a
if (PyList_Size(value) != 2)
return PY_SET_ATTR_FAIL;
- item1 = PyList_GetItem(value, 0);
- item2 = PyList_GetItem(value, 1);
+ item1 = PyList_GET_ITEM(value, 0);
+ item2 = PyList_GET_ITEM(value, 1);
if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) {
return PY_SET_ATTR_FAIL;
@@ -528,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 a9f6bb0d2ff..46f27e1a2df 100644
--- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
+++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp
@@ -36,10 +36,13 @@
# pragma warning(disable:4786)
#endif
+#include <stdio.h>
+
#include "MT_Point3.h"
#include "RAS_FramingManager.h"
#include "RAS_ICanvas.h"
#include "RAS_IRasterizer.h"
+#include "RAS_MeshObject.h"
#include "SCA_IScene.h"
#include "KX_Scene.h"
#include "KX_Camera.h"
@@ -163,15 +166,17 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *r
}
else
{
- if (m_bFindMaterial)
- {
- if (client_info->m_auxilary_info)
- {
- bFound = (m_propertyname== ((char*)client_info->m_auxilary_info));
+ if (m_bFindMaterial) {
+ for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = hitKXObj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ bFound = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (bFound)
+ break;
+ }
}
}
- else
- {
+ else {
bFound = hitKXObj->GetProperty(m_propertyname) != NULL;
}
}
@@ -195,6 +200,8 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *r
*/
bool KX_MouseFocusSensor::NeedRayCast(KX_ClientObjectInfo* client)
{
+ KX_GameObject *hitKXObj = client->m_gameobject;
+
if (client->m_type > KX_ClientObjectInfo::ACTOR)
{
// Unknown type of object, skip it.
@@ -206,14 +213,21 @@ bool KX_MouseFocusSensor::NeedRayCast(KX_ClientObjectInfo* client)
{
if (m_bFindMaterial)
{
- // not quite correct: an object may have multiple material
- // should check all the material and not only the first one
- if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info)))
+ bool found = false;
+ for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = hitKXObj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ found = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (found)
+ break;
+ }
+ }
+ if (!found)
return false;
}
else
{
- if (client->m_gameobject->GetProperty(m_propertyname) == NULL)
+ if (hitKXObj->GetProperty(m_propertyname) == NULL)
return false;
}
}
@@ -269,8 +283,8 @@ bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam)
m_kxengine->GetSceneViewport(m_kxscene, cam, area, viewport);
/* Check if the mouse is in the viewport */
- if (( m_x < viewport.m_x2 && // less then right
- m_x > viewport.m_x1 && // more then then left
+ if (( m_x < viewport.m_x2 && // less than right
+ m_x > viewport.m_x1 && // more than then left
m_y_inv < viewport.m_y2 && // below top
m_y_inv > viewport.m_y1) == 0) // above bottom
{
diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
index 8360681759a..b8907ca5c6b 100644
--- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp
+++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp
@@ -45,7 +45,7 @@ extern "C" {
#include "KX_PythonInit.h"
#include "KX_PyMath.h"
-#include "Value.h"
+#include "EXP_Value.h"
#include "Recast.h"
#include "DetourStatNavMeshBuilder.h"
#include "KX_ObstacleSimulation.h"
@@ -98,12 +98,14 @@ void KX_NavMeshObject::ProcessReplica()
{
KX_GameObject::ProcessReplica();
m_navMesh = NULL; /* without this, building frees the navmesh we copied from */
- BuildNavMesh();
+ if (!BuildNavMesh()) {
+ std::cout << "Error in " << __func__ << ": unable to build navigation mesh" << std::endl;
+ return;
+ }
KX_Scene* scene = KX_GetActiveScene();
KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation();
if (obssimulation)
obssimulation->AddObstaclesForNavMesh(this);
-
}
bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts,
@@ -321,7 +323,11 @@ bool KX_NavMeshObject::BuildNavMesh()
}
}
- buildMeshAdjacency(polys, npolys, nverts, vertsPerPoly);
+ if (!buildMeshAdjacency(polys, npolys, nverts, vertsPerPoly)) {
+ std::cout << __func__ << ": unable to build mesh adjacency information." << std::endl;
+ delete[] vertices;
+ return false;
+ }
float cs = 0.2f;
diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.h b/source/gameengine/Ketsji/KX_NavMeshObject.h
index 1599361b334..af178f9aaee 100644
--- a/source/gameengine/Ketsji/KX_NavMeshObject.h
+++ b/source/gameengine/Ketsji/KX_NavMeshObject.h
@@ -28,7 +28,7 @@
#define __KX_NAVMESHOBJECT_H__
#include "DetourStatNavMesh.h"
#include "KX_GameObject.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include <vector>
class RAS_MeshObject;
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_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp
index 6926fdb1d4c..6ffa2593792 100644
--- a/source/gameengine/Ketsji/KX_ParentActuator.cpp
+++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp
@@ -37,7 +37,7 @@
#include "KX_GameObject.h"
#include "KX_PythonInit.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
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 ebf1b9ec577..a0084662490 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp
@@ -41,7 +41,7 @@
#include "KX_GameObject.h" // ConvertPythonToGameObject()
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#ifdef WITH_BULLET
# include "LinearMath/btIDebugDraw.h"
@@ -56,38 +56,95 @@
// if there is a better way (without global), please do so!
static PHY_IPhysicsEnvironment* g_CurrentActivePhysicsEnvironment = NULL;
-static char PhysicsConstraints_module_documentation[] =
-"This is the Python API for the Physics Constraints";
-
-
-static char gPySetGravity__doc__[] = "setGravity(float x,float y,float z)";
-static char gPySetDebugMode__doc__[] = "setDebugMode(int mode)";
-
-static char gPySetNumIterations__doc__[] = "setNumIterations(int numiter) This sets the number of iterations for an iterative constraint solver";
-static char gPySetNumTimeSubSteps__doc__[] = "setNumTimeSubSteps(int numsubstep) This sets the number of substeps for each physics proceed. Tradeoff quality for performance.";
-
-
-static char gPySetDeactivationTime__doc__[] = "setDeactivationTime(float time) This sets the time after which a resting rigidbody gets deactived";
-static char gPySetDeactivationLinearTreshold__doc__[] = "setDeactivationLinearTreshold(float linearTreshold)";
-static char gPySetDeactivationAngularTreshold__doc__[] = "setDeactivationAngularTreshold(float angularTreshold)";
-static char gPySetContactBreakingTreshold__doc__[] = "setContactBreakingTreshold(float breakingTreshold) Reasonable default is 0.02 (if units are meters)";
-
-static char gPySetCcdMode__doc__[] = "setCcdMode(int ccdMode) Very experimental, not recommended";
-static char gPySetSorConstant__doc__[] = "setSorConstant(float sor) Very experimental, not recommended";
-static char gPySetSolverTau__doc__[] = "setTau(float tau) Very experimental, not recommended";
-static char gPySetSolverDamping__doc__[] = "setDamping(float damping) Very experimental, not recommended";
-static char gPySetLinearAirDamping__doc__[] = "setLinearAirDamping(float damping) Very experimental, not recommended";
-static char gPySetUseEpa__doc__[] = "setUseEpa(int epa) Very experimental, not recommended";
-static char gPySetSolverType__doc__[] = "setSolverType(int solverType) Very experimental, not recommended";
-
-
-static char gPyCreateConstraint__doc__[] = "createConstraint(ob1,ob2,float restLength,float restitution,float damping)";
-static char gPyGetVehicleConstraint__doc__[] = "getVehicleConstraint(int constraintId)";
-static char gPyGetCharacter__doc__[] = "getCharacter(KX_GameObject obj)";
-static char gPyRemoveConstraint__doc__[] = "removeConstraint(int constraintId)";
-static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId)";
-
+PyDoc_STRVAR(PhysicsConstraints_module_documentation,
+"This is the Python API for the Physics Constraints"
+);
+
+PyDoc_STRVAR(gPySetGravity__doc__,
+"setGravity(float x,float y,float z)\n"
+""
+);
+PyDoc_STRVAR(gPySetDebugMode__doc__,
+"setDebugMode(int mode)\n"
+""
+);
+
+PyDoc_STRVAR(gPySetNumIterations__doc__,
+"setNumIterations(int numiter)\n"
+"This sets the number of iterations for an iterative constraint solver"
+);
+PyDoc_STRVAR(gPySetNumTimeSubSteps__doc__,
+"setNumTimeSubSteps(int numsubstep)\n"
+"This sets the number of substeps for each physics proceed. Tradeoff quality for performance."
+);
+
+PyDoc_STRVAR(gPySetDeactivationTime__doc__,
+"setDeactivationTime(float time)\n"
+"This sets the time after which a resting rigidbody gets deactived"
+);
+PyDoc_STRVAR(gPySetDeactivationLinearTreshold__doc__,
+"setDeactivationLinearTreshold(float linearTreshold)\n"
+""
+);
+PyDoc_STRVAR(gPySetDeactivationAngularTreshold__doc__,
+"setDeactivationAngularTreshold(float angularTreshold)\n"
+""
+);
+PyDoc_STRVAR(gPySetContactBreakingTreshold__doc__,
+"setContactBreakingTreshold(float breakingTreshold)\n"
+"Reasonable default is 0.02 (if units are meters)"
+);
+
+PyDoc_STRVAR(gPySetCcdMode__doc__,
+"setCcdMode(int ccdMode)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetSorConstant__doc__,
+"setSorConstant(float sor)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetSolverTau__doc__,
+"setTau(float tau)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetSolverDamping__doc__,
+"setDamping(float damping)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetLinearAirDamping__doc__,
+"setLinearAirDamping(float damping)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetUseEpa__doc__,
+"setUseEpa(int epa)\n"
+"Very experimental, not recommended"
+);
+PyDoc_STRVAR(gPySetSolverType__doc__,
+"setSolverType(int solverType)\n"
+"Very experimental, not recommended"
+);
+
+PyDoc_STRVAR(gPyCreateConstraint__doc__,
+"createConstraint(ob1,ob2,float restLength,float restitution,float damping)\n"
+""
+);
+PyDoc_STRVAR(gPyGetVehicleConstraint__doc__,
+"getVehicleConstraint(int constraintId)\n"
+""
+);
+PyDoc_STRVAR(gPyGetCharacter__doc__,
+"getCharacter(KX_GameObject obj)\n"
+""
+);
+PyDoc_STRVAR(gPyRemoveConstraint__doc__,
+"removeConstraint(int constraintId)\n"
+""
+);
+PyDoc_STRVAR(gPyGetAppliedImpulse__doc__,
+"getAppliedImpulse(int constraintId)\n"
+""
+);
@@ -438,113 +495,47 @@ static PyObject *gPyCreateConstraint(PyObject *self,
PyObject *kwds)
{
/* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */
-#if defined(_WIN64)
- __int64 physicsid=0,physicsid2 = 0;
-#else
- long physicsid=0,physicsid2 = 0;
-#endif
- int constrainttype=0, extrainfo=0;
- int len = PyTuple_Size(args);
- int success = 1;
+ unsigned long long physicsid = 0, physicsid2 = 0;
+ 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)
- {
-#if defined(_WIN64)
- success = PyArg_ParseTuple(args,"LLi",&physicsid,&physicsid2,&constrainttype);
-#else
- success = PyArg_ParseTuple(args,"lli",&physicsid,&physicsid2,&constrainttype);
-#endif
- }
- else if (len == 6)
- {
-#if defined(_WIN64)
- success = PyArg_ParseTuple(args,"LLifff",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ);
-#else
- success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ);
-#endif
- }
- else if (len == 9)
- {
-#if defined(_WIN64)
- success = PyArg_ParseTuple(args,"LLiffffff",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
-#else
- success = PyArg_ParseTuple(args,"lliffffff",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ);
-#endif
- }
- else if (len == 10)
- {
-#if defined(_WIN64)
- success = PyArg_ParseTuple(args,"LLiffffffi",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
-#else
- success = PyArg_ParseTuple(args,"lliffffffi",&physicsid,&physicsid2,&constrainttype,
- &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag);
-#endif
- }
+ 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))
{
-#if defined(_WIN64)
- success = PyArg_ParseTuple(args,"LLii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
-#else
- success = PyArg_ParseTuple(args,"llii",&physicsid,&physicsid2,&constrainttype,&extrainfo);
-#endif
- 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!
- {
- PHY_ConstraintType ct = (PHY_ConstraintType) constrainttype;
- int constraintid =0;
-
- if (ct == PHY_GENERIC_6DOF_CONSTRAINT)
- {
- //convert from euler angle into axis
- float radsPerDeg = 6.283185307179586232f / 360.f;
-
- //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);
-
- 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);
- }
- else {
- constraintid = PHY_GetActiveEnvironment()->CreateConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ,0);
- }
-
- KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment());
-
- return wrap->NewProxy(true);
- }
-
-
+ 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(deg2rad*axisX, deg2rad*axisY, deg2rad*axisZ));
+ MT_Vector3 axis0 = localCFrame.getColumn(0);
+ MT_Vector3 axis1 = localCFrame.getColumn(1);
+ MT_Vector3 axis2 = localCFrame.getColumn(2);
+
+ 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());
+
+ return wrap->NewProxy(true);
}
}
- else {
- return NULL;
- }
-
Py_RETURN_NONE;
}
@@ -592,7 +583,7 @@ static PyObject *gPyRemoveConstraint(PyObject *self,
{
if (PHY_GetActiveEnvironment())
{
- PHY_GetActiveEnvironment()->RemoveConstraint(constraintid);
+ PHY_GetActiveEnvironment()->RemoveConstraintById(constraintid);
}
}
else {
@@ -657,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__},
@@ -677,7 +668,7 @@ static struct PyMethodDef physicsconstraints_methods[] = {
};
static struct PyModuleDef PhysicsConstraints_module_def = {
- {}, /* m_base */
+ PyModuleDef_HEAD_INIT,
"PhysicsConstraints", /* m_name */
PhysicsConstraints_module_documentation, /* m_doc */
0, /* m_size */
@@ -688,7 +679,7 @@ static struct PyModuleDef PhysicsConstraints_module_def = {
0, /* m_free */
};
-PyObject *initPythonConstraintBinding()
+PyMODINIT_FUNC initConstraintPythonBinding()
{
PyObject *ErrorObject;
@@ -696,19 +687,8 @@ PyObject *initPythonConstraintBinding()
PyObject *d;
PyObject *item;
- /* Use existing module where possible
- * be careful not to init any runtime vars after this */
- m = PyImport_ImportModule( "PhysicsConstraints" );
- if (m) {
- Py_DECREF(m);
- return m;
- }
- else {
- PyErr_Clear();
-
- m = PyModule_Create(&PhysicsConstraints_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m);
- }
+ m = PyModule_Create(&PhysicsConstraints_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m);
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
@@ -747,7 +727,7 @@ PyObject *initPythonConstraintBinding()
Py_FatalError("can't initialize module PhysicsConstraints");
}
- return d;
+ return m;
}
#if 0
diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.h b/source/gameengine/Ketsji/KX_PyConstraintBinding.h
index b4a520ce71b..2bf9f7e197d 100644
--- a/source/gameengine/Ketsji/KX_PyConstraintBinding.h
+++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.h
@@ -36,7 +36,8 @@
#include <Python.h>
-PyObject* initPythonConstraintBinding();
+PyMODINIT_FUNC initConstraintPythonBinding();
+
void PHY_SetActiveEnvironment(class PHY_IPhysicsEnvironment* env);
PHY_IPhysicsEnvironment* PHY_GetActiveEnvironment();
#endif /* WITH_PYTHON */
diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp
index 804e8de2ad1..ee05fd442ab 100644
--- a/source/gameengine/Ketsji/KX_PyMath.cpp
+++ b/source/gameengine/Ketsji/KX_PyMath.cpp
@@ -42,9 +42,9 @@
#include "MT_Matrix4x4.h"
#include "MT_Point2.h"
-#include "ListValue.h"
+#include "EXP_ListValue.h"
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "KX_PyMath.h"
bool PyOrientationTo(PyObject *pyval, MT_Matrix3x3 &rot, const char *error_prefix)
@@ -100,7 +100,7 @@ PyObject *PyObjectFrom(const MT_Matrix4x4 &mat)
#ifdef USE_MATHUTILS
float fmat[16];
mat.getValue(fmat);
- return Matrix_CreatePyObject(fmat, 4, 4, Py_NEW, NULL);
+ return Matrix_CreatePyObject(fmat, 4, 4, NULL);
#else
PyObject *collist = PyList_New(4);
PyObject *col;
@@ -124,7 +124,7 @@ PyObject *PyObjectFrom(const MT_Matrix3x3 &mat)
#ifdef USE_MATHUTILS
float fmat[9];
mat.getValue3x3(fmat);
- return Matrix_CreatePyObject(fmat, 3, 3, Py_NEW, NULL);
+ return Matrix_CreatePyObject(fmat, 3, 3, NULL);
#else
PyObject *collist = PyList_New(3);
PyObject *col;
@@ -148,7 +148,7 @@ PyObject *PyObjectFrom(const MT_Quaternion &qrot)
/* NOTE, were re-ordering here for Mathutils compat */
float fvec[4];
qrot.getValue(fvec);
- return Quaternion_CreatePyObject(fvec, Py_NEW, NULL);
+ return Quaternion_CreatePyObject(fvec, NULL);
}
#endif
@@ -157,7 +157,7 @@ PyObject *PyObjectFrom(const MT_Tuple4 &vec)
#ifdef USE_MATHUTILS
float fvec[4];
vec.getValue(fvec);
- return Vector_CreatePyObject(fvec, 4, Py_NEW, NULL);
+ return Vector_CreatePyObject(fvec, 4, NULL);
#else
PyObject *list = PyList_New(4);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
@@ -173,7 +173,7 @@ PyObject *PyObjectFrom(const MT_Tuple3 &vec)
#ifdef USE_MATHUTILS
float fvec[3];
vec.getValue(fvec);
- return Vector_CreatePyObject(fvec, 3, Py_NEW, NULL);
+ return Vector_CreatePyObject(fvec, 3, NULL);
#else
PyObject *list = PyList_New(3);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
@@ -188,7 +188,7 @@ PyObject *PyObjectFrom(const MT_Tuple2 &vec)
#ifdef USE_MATHUTILS
float fvec[2];
vec.getValue(fvec);
- return Vector_CreatePyObject(fvec, 2, Py_NEW, NULL);
+ return Vector_CreatePyObject(fvec, 2, NULL);
#else
PyObject *list = PyList_New(2);
PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
@@ -197,4 +197,19 @@ PyObject *PyObjectFrom(const MT_Tuple2 &vec)
#endif
}
+PyObject *PyColorFromVector(const MT_Vector3 &vec)
+{
+#ifdef USE_MATHUTILS
+ float fvec[3];
+ vec.getValue(fvec);
+ return Color_CreatePyObject(fvec, NULL);
+#else
+ PyObject *list = PyList_New(3);
+ PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0]));
+ PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1]));
+ PyList_SET_ITEM(list, 2, PyFloat_FromDouble(vec[2]));
+ return list;
+#endif
+}
+
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h
index 159506946e8..917fd0fcda6 100644
--- a/source/gameengine/Ketsji/KX_PyMath.h
+++ b/source/gameengine/Ketsji/KX_PyMath.h
@@ -41,8 +41,8 @@
#include "MT_Matrix3x3.h"
#include "MT_Matrix4x4.h"
-#include "KX_Python.h"
-#include "PyObjectPlus.h"
+#include "EXP_Python.h"
+#include "EXP_PyObjectPlus.h"
#ifdef WITH_PYTHON
#ifdef USE_MATHUTILS
@@ -273,4 +273,9 @@ PyObject *PyObjectFrom(const MT_Tuple4 &pos);
#endif
+/**
+ * Converts an MT_Vector3 to a python color object.
+ */
+PyObject *PyColorFromVector(const MT_Vector3 &vec);
+
#endif /* WITH_PYTHON */
diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp
index da8a0c0844e..2fef74ca33d 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.cpp
+++ b/source/gameengine/Ketsji/KX_PythonInit.cpp
@@ -30,7 +30,7 @@
* \ingroup ketsji
*/
-#include "GL/glew.h"
+#include "glew-mx.h"
#ifdef _MSC_VER
# pragma warning (disable:4786)
@@ -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.
@@ -59,7 +61,7 @@ extern "C" {
# include "marshal.h" /* python header for loading/saving dicts */
}
-#include "AUD_PyInit.h"
+#include "../../../../intern/audaspace/intern/AUD_PyInit.h"
#endif /* WITH_PYTHON */
@@ -110,8 +112,8 @@ extern "C" {
#include "RAS_2DFilterManager.h"
#include "MT_Vector3.h"
#include "MT_Point3.h"
-#include "ListValue.h"
-#include "InputParser.h"
+#include "EXP_ListValue.h"
+#include "EXP_InputParser.h"
#include "KX_Scene.h"
#include "NG_NetworkScene.h" //Needed for sendMessage()
@@ -121,7 +123,7 @@ extern "C" {
#include "KX_PyMath.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "KX_PythonInitTypes.h"
@@ -130,12 +132,17 @@ extern "C" {
#include "DNA_scene_types.h"
#include "PHY_IPhysicsEnvironment.h"
+
+extern "C" {
#include "BKE_main.h"
#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"
+}
/* for converting new scenes */
#include "KX_BlenderSceneConverter.h"
@@ -179,17 +186,17 @@ class KX_KetsjiEngine* KX_GetActiveEngine()
}
/* why is this in python? */
-void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)
+void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color)
{
if (gp_Rasterizer)
- gp_Rasterizer->DrawDebugLine(from,to,color);
+ gp_Rasterizer->DrawDebugLine(gp_KetsjiScene, from, to, color);
}
void KX_RasterizerDrawDebugCircle(const MT_Vector3& center, const MT_Scalar radius, const MT_Vector3& color,
const MT_Vector3& normal, int nsector)
{
if (gp_Rasterizer)
- gp_Rasterizer->DrawDebugCircle(center, radius, color, normal, nsector);
+ gp_Rasterizer->DrawDebugCircle(gp_KetsjiScene, center, radius, color, normal, nsector);
}
#ifdef WITH_PYTHON
@@ -214,13 +221,16 @@ static void KX_MACRO_addTypesToDict_fn(PyObject *dict, const char *name, long va
// temporarily python stuff, will be put in another place later !
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "SCA_PythonController.h"
// List of methods defined in the module
static PyObject *ErrorObject;
-static const char *gPyGetRandomFloat_doc="getRandomFloat returns a random floating point value in the range [0..1]";
+PyDoc_STRVAR(gPyGetRandomFloat_doc,
+"getRandomFloat()\n"
+"returns a random floating point value in the range [0..1]"
+);
static PyObject *gPyGetRandomFloat(PyObject *)
{
return PyFloat_FromDouble(MT_random());
@@ -238,15 +248,15 @@ static PyObject *gPySetGravity(PyObject *, PyObject *value)
Py_RETURN_NONE;
}
-static char gPyExpandPath_doc[] =
-"(path) - Converts a blender internal path into a proper file system path.\n\
-path - the string path to convert.\n\n\
-Use / as directory separator in path\n\
-You can use '//' at the start of the string to define a relative path;\n\
-Blender replaces that string by the directory of the current .blend or runtime\n\
-file to make a full path name.\n\
-The function also converts the directory separator to the local file system format.";
-
+PyDoc_STRVAR(gPyExpandPath_doc,
+"expandPath(path)\n"
+"Converts a blender internal path into a proper file system path.\n"
+" path - the string path to convert.\n"
+"Use / as directory separator in path\n"
+"You can use '//' at the start of the string to define a relative path."
+"Blender replaces that string by the directory of the current .blend or runtime file to make a full path name.\n"
+"The function also converts the directory separator to the local file system format."
+);
static PyObject *gPyExpandPath(PyObject *, PyObject *args)
{
char expanded[FILE_MAX];
@@ -260,10 +270,10 @@ static PyObject *gPyExpandPath(PyObject *, PyObject *args)
return PyC_UnicodeFromByte(expanded);
}
-static char gPyStartGame_doc[] =
-"startGame(blend)\n\
-Loads the blend file";
-
+PyDoc_STRVAR(gPyStartGame_doc,
+"startGame(blend)\n"
+"Loads the blend file"
+);
static PyObject *gPyStartGame(PyObject *, PyObject *args)
{
char* blendfile;
@@ -277,10 +287,10 @@ static PyObject *gPyStartGame(PyObject *, PyObject *args)
Py_RETURN_NONE;
}
-static char gPyEndGame_doc[] =
-"endGame()\n\
-Ends the current game";
-
+PyDoc_STRVAR(gPyEndGame_doc,
+"endGame()\n"
+"Ends the current game"
+);
static PyObject *gPyEndGame(PyObject *)
{
gp_KetsjiEngine->RequestExit(KX_EXIT_REQUEST_QUIT_GAME);
@@ -290,10 +300,10 @@ static PyObject *gPyEndGame(PyObject *)
Py_RETURN_NONE;
}
-static char gPyRestartGame_doc[] =
-"restartGame()\n\
-Restarts the current game by reloading the .blend file";
-
+PyDoc_STRVAR(gPyRestartGame_doc,
+"restartGame()\n"
+"Restarts the current game by reloading the .blend file"
+);
static PyObject *gPyRestartGame(PyObject *)
{
gp_KetsjiEngine->RequestExit(KX_EXIT_REQUEST_RESTART_GAME);
@@ -302,10 +312,10 @@ static PyObject *gPyRestartGame(PyObject *)
Py_RETURN_NONE;
}
-static char gPySaveGlobalDict_doc[] =
- "saveGlobalDict()\n"
- "Saves bge.logic.globalDict to a file";
-
+PyDoc_STRVAR(gPySaveGlobalDict_doc,
+"saveGlobalDict()\n"
+"Saves bge.logic.globalDict to a file"
+);
static PyObject *gPySaveGlobalDict(PyObject *)
{
char marshal_path[512];
@@ -339,15 +349,15 @@ static PyObject *gPySaveGlobalDict(PyObject *)
Py_RETURN_NONE;
}
-static char gPyLoadGlobalDict_doc[] =
- "LoadGlobalDict()\n"
- "Loads bge.logic.globalDict from a file";
-
+PyDoc_STRVAR(gPyLoadGlobalDict_doc,
+"LoadGlobalDict()\n"
+"Loads bge.logic.globalDict from a file"
+);
static PyObject *gPyLoadGlobalDict(PyObject *)
{
char marshal_path[512];
char *marshal_buffer = NULL;
- size_t marshal_length;
+ int marshal_length;
FILE *fp = NULL;
int result;
@@ -358,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);
@@ -380,23 +395,23 @@ static PyObject *gPyLoadGlobalDict(PyObject *)
Py_RETURN_NONE;
}
-static char gPyGetProfileInfo_doc[] =
+PyDoc_STRVAR(gPyGetProfileInfo_doc,
"getProfileInfo()\n"
-"returns a dictionary with profiling information";
-
+"returns a dictionary with profiling information"
+);
static PyObject *gPyGetProfileInfo(PyObject *)
{
return gp_KetsjiEngine->GetPyProfileDict();
}
-static char gPySendMessage_doc[] =
-"sendMessage(subject, [body, to, from])\n\
-sends a message in same manner as a message actuator\
-subject = Subject of the message\
-body = Message body\
-to = Name of object to send the message to\
-from = Name of object to send the string from";
-
+PyDoc_STRVAR(gPySendMessage_doc,
+"sendMessage(subject, [body, to, from])\n"
+"sends a message in same manner as a message actuator"
+" subject = Subject of the message"
+" body = Message body"
+" to = Name of object to send the message to"
+" from = Name of object to send the string from"
+);
static PyObject *gPySendMessage(PyObject *, PyObject *args)
{
char* subject;
@@ -511,6 +526,27 @@ static PyObject *gPyGetPhysicsTicRate(PyObject *)
return PyFloat_FromDouble(PHY_GetActiveEnvironment()->GetFixedTimeStep());
}
+static PyObject *gPySetAnimRecordFrame(PyObject *, PyObject *args)
+{
+ int anim_record_frame;
+
+ if (!PyArg_ParseTuple(args, "i:setAnimRecordFrame", &anim_record_frame))
+ return NULL;
+
+ if (anim_record_frame < 0 && (U.flag & USER_NONEGFRAMES)) {
+ PyErr_Format(PyExc_ValueError, "Frame number must be non-negative (was %i).", anim_record_frame);
+ return NULL;
+ }
+
+ gp_KetsjiEngine->setAnimRecordFrame(anim_record_frame);
+ Py_RETURN_NONE;
+}
+
+static PyObject *gPyGetAnimRecordFrame(PyObject *)
+{
+ return PyLong_FromLong(gp_KetsjiEngine->getAnimRecordFrame());
+}
+
static PyObject *gPyGetAverageFrameRate(PyObject *)
{
return PyFloat_FromDouble(KX_KetsjiEngine::GetAverageFrameRate());
@@ -556,11 +592,12 @@ static PyObject *gPyGetBlendFileList(PyObject *, PyObject *args)
return list;
}
-static char gPyAddScene_doc[] =
-"addScene(name, [overlay])\n\
-adds a scene to the game engine\n\
-name = Name of the scene\n\
-overlay = Overlay or underlay";
+PyDoc_STRVAR(gPyAddScene_doc,
+"addScene(name, [overlay])\n"
+"Adds a scene to the game engine.\n"
+" name = Name of the scene\n"
+" overlay = Overlay or underlay"
+);
static PyObject *gPyAddScene(PyObject *, PyObject *args)
{
char* name;
@@ -574,17 +611,19 @@ static PyObject *gPyAddScene(PyObject *, PyObject *args)
Py_RETURN_NONE;
}
-static const char *gPyGetCurrentScene_doc =
+PyDoc_STRVAR(gPyGetCurrentScene_doc,
"getCurrentScene()\n"
-"Gets a reference to the current scene.\n";
+"Gets a reference to the current scene."
+);
static PyObject *gPyGetCurrentScene(PyObject *self)
{
return gp_KetsjiScene->GetProxy();
}
-static const char *gPyGetSceneList_doc =
+PyDoc_STRVAR(gPyGetSceneList_doc,
"getSceneList()\n"
-"Return a list of converted scenes.\n";
+"Return a list of converted scenes."
+);
static PyObject *gPyGetSceneList(PyObject *self)
{
KX_KetsjiEngine* m_engine = KX_GetActiveEngine();
@@ -869,6 +908,8 @@ static struct PyMethodDef game_methods[] = {
{"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, (const char *)"Sets the logic tic rate"},
{"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, (const char *)"Gets the physics tic rate"},
{"setPhysicsTicRate", (PyCFunction) gPySetPhysicsTicRate, METH_VARARGS, (const char *)"Sets the physics tic rate"},
+ {"getAnimRecordFrame", (PyCFunction) gPyGetAnimRecordFrame, METH_NOARGS, (const char *)"Gets the current frame number used for animation recording"},
+ {"setAnimRecordFrame", (PyCFunction) gPySetAnimRecordFrame, METH_VARARGS, (const char *)"Sets the current frame number used for animation recording"},
{"getExitKey", (PyCFunction) gPyGetExitKey, METH_NOARGS, (const char *)"Gets the key used to exit the game engine"},
{"setExitKey", (PyCFunction) gPySetExitKey, METH_VARARGS, (const char *)"Sets the key used to exit the game engine"},
{"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, (const char *)"Gets the estimated average frame rate"},
@@ -1002,111 +1043,39 @@ static PyObject *gPyGetFocalLength(PyObject *, PyObject *, PyObject *)
Py_RETURN_NONE;
}
-static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value)
+static PyObject *gPyGetStereoEye(PyObject *, PyObject *, PyObject *)
{
-
- 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]);
+ int flag = RAS_IRasterizer::RAS_STEREO_LEFTEYE;
- 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");
+ PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getStereoEye(), Rasterizer 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;
-}
+ if (gp_Rasterizer->Stereo())
+ flag = gp_Rasterizer->GetEye();
-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;
+ return PyLong_FromLong(flag);
}
-
-
-static PyObject *gPySetMistEnd(PyObject *, PyObject *args)
+static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value)
{
-
- float mistend;
- if (!PyArg_ParseTuple(args,"f:setMistEnd",&mistend))
+ MT_Vector4 vec;
+ if (!PyVecTo(value, vec))
return NULL;
-
- if (!gp_Rasterizer) {
- PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistEnd(float), Rasterizer not available");
+
+ KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo();
+ if (!wi->hasWorld()) {
+ PyErr_SetString(PyExc_RuntimeError, "bge.render.SetBackgroundColor(color), World not available");
return NULL;
}
-
- gp_Rasterizer->SetFogEnd(mistend);
-
- Py_RETURN_NONE;
-}
+ ShowDeprecationWarning("setBackgroundColor()", "KX_WorldInfo.background_color");
+ wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]);
-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;
@@ -1192,10 +1161,6 @@ static PyObject *gPySetGLSLMaterialSetting(PyObject *,
else
gs->glslflag |= flag;
- /* temporarily store the glsl settings in the scene for the GLSL materials */
- GameData *gm= &(gp_KetsjiScene->GetBlenderScene()->gm);
- gm->flag = gs->glslflag;
-
/* display lists and GLSL materials need to be remade */
if (sceneflag != gs->glslflag) {
GPU_materials_free();
@@ -1203,11 +1168,14 @@ static PyObject *gPySetGLSLMaterialSetting(PyObject *,
KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes();
KX_SceneList::iterator it;
- for (it=scenes->begin(); it!=scenes->end(); it++)
+ for (it=scenes->begin(); it!=scenes->end(); it++) {
+ // temporarily store the glsl settings in the scene for the GLSL materials
+ (*it)->GetBlenderScene()->gm.flag = gs->glslflag;
if ((*it)->GetBucketManager()) {
(*it)->GetBucketManager()->ReleaseDisplayLists();
(*it)->GetBucketManager()->ReleaseMaterials();
}
+ }
}
}
@@ -1320,7 +1288,7 @@ static PyObject *gPyDrawLine(PyObject *, PyObject *args)
if (!PyVecTo(ob_color, color))
return NULL;
- gp_Rasterizer->DrawDebugLine(from,to,color);
+ gp_Rasterizer->DrawDebugLine(gp_KetsjiScene, from, to, color);
Py_RETURN_NONE;
}
@@ -1396,7 +1364,9 @@ static PyObject *gPySetVsync(PyObject *, PyObject *args)
static PyObject *gPyGetVsync(PyObject *)
{
- return PyLong_FromLong(gp_Canvas->GetSwapInterval());
+ int interval = 0;
+ gp_Canvas->GetSwapInterval(interval);
+ return PyLong_FromLong(interval);
}
static PyObject *gPyShowFramerate(PyObject *, PyObject *args)
@@ -1463,6 +1433,24 @@ 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"
+);
static struct PyMethodDef rasterizer_methods[] = {
{"getWindowWidth",(PyCFunction) gPyGetWindowWidth,
@@ -1478,11 +1466,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"},
@@ -1490,6 +1473,7 @@ static struct PyMethodDef rasterizer_methods[] = {
{"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_NOARGS, "get the eye separation for stereo mode"},
{"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"},
{"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"},
+ {"getStereoEye", (PyCFunction) gPyGetStereoEye, METH_VARARGS, "get the current stereoscopy eye being rendered"},
{"setMaterialMode",(PyCFunction) gPySetMaterialType,
METH_VARARGS, "set the material mode to use for OpenGL rendering"},
{"getMaterialMode",(PyCFunction) gPyGetMaterialType,
@@ -1507,6 +1491,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, ""},
@@ -1519,15 +1505,11 @@ static struct PyMethodDef rasterizer_methods[] = {
{ NULL, (PyCFunction) NULL, 0, NULL }
};
-// Initialization function for the module (*must* be called initGameLogic)
-static char GameLogic_module_documentation[] =
-"This is the Python API for the game engine of bge.logic"
-;
-static char Rasterizer_module_documentation[] =
-"This is the Python API for the game engine of Rasterizer"
-;
+PyDoc_STRVAR(GameLogic_module_documentation,
+"This is the Python API for the game engine of bge.logic"
+);
static struct PyModuleDef GameLogic_module_def = {
{}, /* m_base */
@@ -1541,33 +1523,20 @@ static struct PyModuleDef GameLogic_module_def = {
0, /* m_free */
};
-PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook
+PyMODINIT_FUNC initGameLogicPythonBinding()
{
PyObject *m;
PyObject *d;
PyObject *item; /* temp PyObject *storage */
-
- gp_KetsjiEngine = engine;
- gp_KetsjiScene = scene;
gUseVisibilityTemp=false;
-
+
PyObjectPlus::ClearDeprecationWarning(); /* Not that nice to call here but makes sure warnings are reset between loading scenes */
-
- /* Use existing module where possible
- * be careful not to init any runtime vars after this */
- m = PyImport_ImportModule( "GameLogic" );
- if (m) {
- Py_DECREF(m);
- return m;
- }
- else {
- PyErr_Clear();
- // Create the module and add the functions
- m = PyModule_Create(&GameLogic_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), GameLogic_module_def.m_name, m);
- }
-
+
+ m = PyModule_Create(&GameLogic_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), GameLogic_module_def.m_name, m);
+
+
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
@@ -1587,17 +1556,22 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack
PyObject* joylist = PyList_New(JOYINDEX_MAX);
for (int i=0; i<JOYINDEX_MAX; ++i) {
- SCA_Joystick* joy = SCA_Joystick::GetInstance(i);
+ SCA_Joystick *joy = SCA_Joystick::GetInstance(i);
+ PyObject *item;
+
if (joy && joy->Connected()) {
gp_PythonJoysticks[i] = new SCA_PythonJoystick(joy);
- PyObject* tmp = gp_PythonJoysticks[i]->NewProxy(true);
- Py_INCREF(tmp);
- PyList_SET_ITEM(joylist, i, tmp);
- } else {
- joy->ReleaseInstance();
- Py_INCREF(Py_None);
- PyList_SET_ITEM(joylist, i, Py_None);
+ item = gp_PythonJoysticks[i]->NewProxy(true);
}
+ else {
+ if (joy) {
+ joy->ReleaseInstance();
+ }
+ item = Py_None;
+ }
+
+ Py_INCREF(item);
+ PyList_SET_ITEM(joylist, i, item);
}
PyDict_SetItemString(d, "joysticks", joylist);
@@ -2047,7 +2021,77 @@ void removeImportMain(struct Main *maggie)
bpy_import_main_extra_remove(maggie);
}
-// Copied from bpy_interface.c
+
+PyDoc_STRVAR(BGE_module_documentation,
+ "This module contains submodules for the Blender Game Engine.\n"
+);
+
+static struct PyModuleDef BGE_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "bge", /* m_name */
+ BGE_module_documentation, /* m_doc */
+ 0, /* m_size */
+ NULL, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+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);
+
+ /* 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);
+
+ mod_full = "bge.events";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initGameKeysPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+ mod_full = "bge.logic";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initGameLogicPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+ mod_full = "bge.render";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initRasterizerPythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(submodule);
+
+ mod_full = "bge.texture";
+ PyModule_AddObject(mod, SUBMOD, (submodule = initVideoTexturePythonBinding()));
+ PyDict_SetItemString(sys_modules, mod_full, submodule);
+ Py_INCREF(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;
+}
+
+
+/* minimal required blender modules to run blenderplayer */
static struct _inittab bge_internal_modules[] = {
{"mathutils", PyInit_mathutils},
{"bgl", BPyInit_bgl},
@@ -2060,7 +2104,7 @@ static struct _inittab bge_internal_modules[] = {
* Python is not initialized.
* see bpy_interface.c's BPY_python_start() which shares the same functionality in blender.
*/
-PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv)
+PyObject *initGamePlayerPythonScripting(Main *maggie, int argc, char** argv)
{
/* Yet another gotcha in the py api
* Cant run PySys_SetArgv more than once because this adds the
@@ -2069,16 +2113,22 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
* somehow it remembers the sys.path - Campbell
*/
static bool first_time = true;
- const char * const py_path_bundle = BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL);
-
-#if 0 // TODO - py3
- STR_String pname = progname;
- Py_SetProgramName(pname.Ptr());
-#endif
-
+ const char * const py_path_bundle = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, NULL);
+
+ /* not essential but nice to set our name */
+ static wchar_t program_path_wchar[FILE_MAX]; /* python holds a reference */
+ BLI_strncpy_wchar_from_utf8(program_path_wchar, BKE_appdir_program_path(), ARRAY_SIZE(program_path_wchar));
+ Py_SetProgramName(program_path_wchar);
+
+ /* Update, Py3.3 resolves attempting to parse non-existing header */
+#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;
+ Py_NoSiteFlag = 1; /* inhibits the automatic importing of 'site' */
}
+#endif
Py_FrozenFlag = 1;
@@ -2102,12 +2152,16 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
PySys_SetObject("argv", py_argv);
Py_DECREF(py_argv);
}
-
+
/* Initialize thread support (also acquires lock) */
PyEval_InitThreads();
bpy_import_init(PyEval_GetBuiltins());
+ bpy_import_main_set(maggie);
+
+ initPySysObjects(maggie);
+
/* mathutils types are used by the BGE even if we don't import them */
{
PyObject *mod = PyImport_ImportModuleLevel("mathutils", NULL, NULL, NULL, 0);
@@ -2122,12 +2176,8 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur
}
#endif
- initPyTypes();
-
- bpy_import_main_set(maggie);
-
- initPySysObjects(maggie);
-
+ PyDict_SetItemString(PyImport_GetModuleDict(), "bge", initBGE());
+
first_time = false;
PyObjectPlus::ClearDeprecationWarning();
@@ -2164,12 +2214,13 @@ void exitGamePlayerPythonScripting()
/**
* Python is already initialized.
*/
-PyObject *initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie)
+PyObject *initGamePythonScripting(Main *maggie)
{
-#if 0 // XXX TODO Py3
- STR_String pname = progname;
- Py_SetProgramName(pname.Ptr());
-#endif
+ /* no need to Py_SetProgramName, it was already taken care of in BPY_python_start */
+
+ bpy_import_main_set(maggie);
+
+ initPySysObjects(maggie);
#ifdef WITH_AUDASPACE
/* accessing a SoundActuator's sound results in a crash if aud is not initialized... */
@@ -2179,11 +2230,7 @@ PyObject *initGamePythonScripting(const STR_String& progname, TPythonSecurityLev
}
#endif
- initPyTypes();
-
- bpy_import_main_set(maggie);
-
- initPySysObjects(maggie);
+ PyDict_SetItemString(PyImport_GetModuleDict(), "bge", initBGE());
PyObjectPlus::NullDeprecationWarning();
@@ -2216,51 +2263,32 @@ void exitGamePythonScripting()
void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene *startscene, Main *blenderdata,
PyObject *pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv)
{
- PyObject *dictionaryobject;
+ PyObject *modules, *dictionaryobject;
+
+ gp_Canvas = ketsjiengine->GetCanvas();
+ gp_Rasterizer = ketsjiengine->GetRasterizer();
+ gp_KetsjiEngine = ketsjiengine;
+ gp_KetsjiScene = startscene;
if (argv) /* player only */
- dictionaryobject= initGamePlayerPythonScripting("Ketsji", psl_Lowest, blenderdata, argc, argv);
+ dictionaryobject= initGamePlayerPythonScripting(blenderdata, argc, argv);
else
- dictionaryobject= initGamePythonScripting("Ketsji", psl_Lowest, blenderdata);
+ dictionaryobject= initGamePythonScripting(blenderdata);
ketsjiengine->SetPyNamespace(dictionaryobject);
- initRasterizer(ketsjiengine->GetRasterizer(), ketsjiengine->GetCanvas());
- *gameLogic = initGameLogic(ketsjiengine, startscene);
- /* is set in initGameLogic so only set here if we want it to persist between scenes */
+ modules = PyImport_GetModuleDict();
+
+ *gameLogic = PyDict_GetItemString(modules, "GameLogic");
+ /* is set in initGameLogicPythonBinding so only set here if we want it to persist between scenes */
if (pyGlobalDict)
PyDict_SetItemString(PyModule_GetDict(*gameLogic), "globalDict", pyGlobalDict); // Same as importing the module.
*gameLogic_keys = PyDict_Keys(PyModule_GetDict(*gameLogic));
-
- initGameKeys();
- initPythonConstraintBinding();
- initVideoTexture();
-
- /* could be done a lot more nicely, but for now a quick way to get bge.* working */
- PyRun_SimpleString("sys = __import__('sys');"
- "bge = type(sys)('bge');"
- "bge.__dict__.update({'logic':__import__('GameLogic'), "
- "'render':__import__('Rasterizer'), "
- "'events':__import__('GameKeys'), "
- "'constraints':__import__('PhysicsConstraints'), "
- "'physics':__import__('PhysicsConstraints'),"
- "'types':__import__('GameTypes'), "
- "'texture':__import__('VideoTexture')});"
- /* so we can do 'import bge.foo as bar' */
- "sys.modules.update({'bge': bge, "
- "'bge.logic':bge.logic, "
- "'bge.render':bge.render, "
- "'bge.events':bge.events, "
- "'bge.constraints':bge.constraints, "
- "'bge.physics':bge.physics,"
- "'bge.types':bge.types, "
- "'bge.texture':bge.texture})"
- );
}
static struct PyModuleDef Rasterizer_module_def = {
- {}, /* m_base */
+ PyModuleDef_HEAD_INIT,
"Rasterizer", /* m_name */
Rasterizer_module_documentation, /* m_doc */
0, /* m_size */
@@ -2271,29 +2299,14 @@ static struct PyModuleDef Rasterizer_module_def = {
0, /* m_free */
};
-PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
+PyMODINIT_FUNC initRasterizerPythonBinding()
{
- gp_Canvas = canvas;
- gp_Rasterizer = rasty;
-
-
PyObject *m;
PyObject *d;
- /* Use existing module where possible
- * be careful not to init any runtime vars after this */
- m = PyImport_ImportModule( "Rasterizer" );
- if (m) {
- Py_DECREF(m);
- return m;
- }
- else {
- PyErr_Clear();
+ m = PyModule_Create(&Rasterizer_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), Rasterizer_module_def.m_name, m);
- // Create the module and add the functions
- m = PyModule_Create(&Rasterizer_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), Rasterizer_module_def.m_name, m);
- }
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
@@ -2314,6 +2327,10 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
KX_MACRO_addTypesToDict(d, VSYNC_ON, VSYNC_ON);
KX_MACRO_addTypesToDict(d, VSYNC_ADAPTIVE, VSYNC_ADAPTIVE);
+ /* stereoscopy */
+ KX_MACRO_addTypesToDict(d, LEFT_EYE, RAS_IRasterizer::RAS_STEREO_LEFTEYE);
+ KX_MACRO_addTypesToDict(d, RIGHT_EYE, RAS_IRasterizer::RAS_STEREO_RIGHTEYE);
+
// XXXX Add constants here
// Check for errors
@@ -2322,7 +2339,7 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
Py_FatalError("can't initialize module Rasterizer");
}
- return d;
+ return m;
}
@@ -2331,13 +2348,14 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas)
/* GameKeys: symbolic constants for key mapping */
/* ------------------------------------------------------------------------- */
-static char GameKeys_module_documentation[] =
+PyDoc_STRVAR(GameKeys_module_documentation,
"This modules provides defines for key-codes"
-;
+);
-static char gPyEventToString_doc[] =
-"EventToString(event) - Take a valid event from the GameKeys module or Keyboard Sensor and return a name"
-;
+PyDoc_STRVAR(gPyEventToString_doc,
+"EventToString(event)\n"
+"Take a valid event from the GameKeys module or Keyboard Sensor and return a name"
+);
static PyObject *gPyEventToString(PyObject *, PyObject *value)
{
@@ -2365,9 +2383,11 @@ static PyObject *gPyEventToString(PyObject *, PyObject *value)
return ret;
}
-static char gPyEventToCharacter_doc[] =
-"EventToCharacter(event, is_shift) - Take a valid event from the GameKeys module or Keyboard Sensor and return a character"
-;
+
+PyDoc_STRVAR(gPyEventToCharacter_doc,
+"EventToCharacter(event, is_shift)\n"
+"Take a valid event from the GameKeys module or Keyboard Sensor and return a character"
+);
static PyObject *gPyEventToCharacter(PyObject *, PyObject *args)
{
@@ -2393,7 +2413,7 @@ static struct PyMethodDef gamekeys_methods[] = {
};
static struct PyModuleDef GameKeys_module_def = {
- {}, /* m_base */
+ PyModuleDef_HEAD_INIT,
"GameKeys", /* m_name */
GameKeys_module_documentation, /* m_doc */
0, /* m_size */
@@ -2404,24 +2424,13 @@ static struct PyModuleDef GameKeys_module_def = {
0, /* m_free */
};
-PyObject *initGameKeys()
+PyMODINIT_FUNC initGameKeysPythonBinding()
{
PyObject *m;
PyObject *d;
-
- /* Use existing module where possible */
- m = PyImport_ImportModule( "GameKeys" );
- if (m) {
- Py_DECREF(m);
- return m;
- }
- else {
- PyErr_Clear();
-
- // Create the module and add the functions
- m = PyModule_Create(&GameKeys_module_def);
- PyDict_SetItemString(PySys_GetObject("modules"), GameKeys_module_def.m_name, m);
- }
+
+ m = PyModule_Create(&GameKeys_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), GameKeys_module_def.m_name, m);
// Add some symbolic constants to the module
d = PyModule_GetDict(m);
@@ -2566,9 +2575,80 @@ PyObject *initGameKeys()
Py_FatalError("can't initialize module GameKeys");
}
- return d;
+ 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 719a74ee219..6550934a916 100644
--- a/source/gameengine/Ketsji/KX_PythonInit.h
+++ b/source/gameengine/Ketsji/KX_PythonInit.h
@@ -32,10 +32,13 @@
#ifndef __KX_PYTHONINIT_H__
#define __KX_PYTHONINIT_H__
-#include "KX_Python.h"
+#include "EXP_Python.h"
#include "STR_String.h"
#include "MT_Vector3.h"
+class KX_KetsjiEngine;
+class KX_Scene;
+
typedef enum {
psl_Lowest = 0,
psl_Highest,
@@ -44,13 +47,14 @@ typedef enum {
extern bool gUseVisibilityTemp;
#ifdef WITH_PYTHON
-PyObject *initGameLogic(class KX_KetsjiEngine *engine, class KX_Scene *ketsjiscene);
-PyObject *initGameKeys();
-PyObject *initRasterizer(class RAS_IRasterizer *rasty,class RAS_ICanvas *canvas);
-PyObject *initGamePlayerPythonScripting(const STR_String &progname, TPythonSecurityLevel level,
- struct Main *maggie, int argc, char **argv);
-PyObject *initVideoTexture(void);
-PyObject *initGamePythonScripting(const STR_String &progname, TPythonSecurityLevel level, struct Main *maggie);
+PyMODINIT_FUNC initBGE(void);
+PyMODINIT_FUNC initApplicationPythonBinding(void);
+PyMODINIT_FUNC initGameLogicPythonBinding(void);
+PyMODINIT_FUNC initGameKeysPythonBinding(void);
+PyMODINIT_FUNC initRasterizerPythonBinding(void);
+PyMODINIT_FUNC initVideoTexturePythonBinding(void);
+PyObject *initGamePlayerPythonScripting(struct Main *maggie, int argc, char **argv);
+PyObject *initGamePythonScripting(struct Main *maggie);
void exitGamePlayerPythonScripting();
void exitGamePythonScripting();
@@ -69,9 +73,9 @@ void removeImportMain(struct Main *maggie);
class KX_KetsjiEngine;
class KX_Scene;
-void KX_SetActiveScene(class KX_Scene *scene);
-class KX_Scene *KX_GetActiveScene();
-class KX_KetsjiEngine *KX_GetActiveEngine();
+void KX_SetActiveScene(KX_Scene *scene);
+KX_Scene *KX_GetActiveScene();
+KX_KetsjiEngine *KX_GetActiveEngine();
typedef int (*PyNextFrameFunc)(void *);
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp
index 7d38ce58eee..ef6ad4712a5 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"
@@ -163,21 +164,34 @@ static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *a
#define PyType_Ready_Attr(d, n, i) PyType_Ready_ADD(d, &n::Type, n::Attributes, NULL, i)
#define PyType_Ready_AttrPtr(d, n, i) PyType_Ready_ADD(d, &n::Type, n::Attributes, n::AttributesPtr, i)
-void initPyTypes(void)
+
+
+PyDoc_STRVAR(GameTypes_module_documentation,
+"This module provides access to the game engine data types."
+);
+static struct PyModuleDef GameTypes_module_def = {
+ PyModuleDef_HEAD_INIT,
+ "GameTypes", /* m_name */
+ GameTypes_module_documentation, /* m_doc */
+ 0, /* m_size */
+ NULL, /* m_methods */
+ NULL, /* m_reload */
+ NULL, /* m_traverse */
+ NULL, /* m_clear */
+ NULL, /* m_free */
+};
+
+
+PyMODINIT_FUNC initGameTypesPythonBinding(void)
{
+ PyObject *m;
+ PyObject *dict;
-/*
- * initPyObjectPlusType(BL_ActionActuator::Parents);
- * .....
- */
+ m = PyModule_Create(&GameTypes_module_def);
+ PyDict_SetItemString(PySys_GetObject("modules"), GameTypes_module_def.m_name, m);
+
+ dict = PyModule_GetDict(m);
- /* For now just do PyType_Ready */
- PyObject *mod = PyModule_New("GameTypes");
- PyObject *dict = PyModule_GetDict(mod);
- PyDict_SetItemString(PySys_GetObject("modules"), "GameTypes", mod);
- Py_DECREF(mod);
-
-
for (int init_getset= 1; init_getset > -1; init_getset--) { /* run twice, once to init the getsets another to run PyType_Ready */
PyType_Ready_Attr(dict, BL_ActionActuator, init_getset);
PyType_Ready_Attr(dict, BL_Shader, init_getset);
@@ -218,6 +232,7 @@ void initPyTypes(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);
@@ -266,7 +281,11 @@ void initPyTypes(void)
/* Init mathutils callbacks */
KX_GameObject_Mathutils_Callback_Init();
KX_ObjectActuator_Mathutils_Callback_Init();
+ KX_WorldInfo_Mathutils_Callback_Init();
+ KX_BlenderMaterial_Mathutils_Callback_Init();
#endif
+
+ return m;
}
#endif // WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.h b/source/gameengine/Ketsji/KX_PythonInitTypes.h
index d8ee4f75fdd..cfc49a1dc93 100644
--- a/source/gameengine/Ketsji/KX_PythonInitTypes.h
+++ b/source/gameengine/Ketsji/KX_PythonInitTypes.h
@@ -33,7 +33,8 @@
#define __KX_PYTHON_INIT_TYPES__
#ifdef WITH_PYTHON
-void initPyTypes(void);
+#include <Python.h>
+PyMODINIT_FUNC initGameTypesPythonBinding(void);
#endif
#endif /* __KX_PYTHON_INIT_TYPES__ */
diff --git a/source/gameengine/Ketsji/KX_PythonSeq.h b/source/gameengine/Ketsji/KX_PythonSeq.h
index 568d59119c0..33b5335ddf4 100644
--- a/source/gameengine/Ketsji/KX_PythonSeq.h
+++ b/source/gameengine/Ketsji/KX_PythonSeq.h
@@ -35,7 +35,7 @@
#ifdef WITH_PYTHON
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
// -------------------------
enum KX_PYGENSEQ_TYPE {
diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp
index 0f47dfd922b..c97d233a67b 100644
--- a/source/gameengine/Ketsji/KX_RaySensor.cpp
+++ b/source/gameengine/Ketsji/KX_RaySensor.cpp
@@ -46,6 +46,7 @@
#include "PHY_IPhysicsEnvironment.h"
#include "PHY_IPhysicsController.h"
#include "DNA_sensor_types.h"
+#include "RAS_MeshObject.h"
#include <stdio.h>
@@ -111,6 +112,7 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void
KX_GameObject* hitKXObj = client->m_gameobject;
bool bFound = false;
+ bool hitMaterial = false;
if (m_propertyname.Length() == 0)
{
@@ -118,15 +120,19 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void
}
else
{
- if (m_bFindMaterial)
- {
- if (client->m_auxilary_info)
- {
- bFound = (m_propertyname== ((char*)client->m_auxilary_info));
+ if (m_bFindMaterial) {
+ for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = hitKXObj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ bFound = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (bFound) {
+ hitMaterial = true;
+ break;
+ }
+ }
}
}
- else
- {
+ else {
bFound = hitKXObj->GetProperty(m_propertyname) != NULL;
}
}
@@ -143,7 +149,7 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void
m_hitNormal[1] = result->m_hitNormal[1];
m_hitNormal[2] = result->m_hitNormal[2];
- m_hitMaterial = (client->m_auxilary_info ? (char*)client->m_auxilary_info : "");
+ m_hitMaterial = hitMaterial;
}
// no multi-hit search yet
return true;
@@ -154,6 +160,8 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void
*/
bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo *client)
{
+ KX_GameObject *hitKXObj = client->m_gameobject;
+
if (client->m_type > KX_ClientObjectInfo::ACTOR)
{
// Unknown type of object, skip it.
@@ -163,16 +171,21 @@ bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo *client)
}
if (m_bXRay && m_propertyname.Length() != 0)
{
- if (m_bFindMaterial)
- {
- // not quite correct: an object may have multiple material
- // should check all the material and not only the first one
- if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info)))
+ if (m_bFindMaterial) {
+ bool found = false;
+ for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = hitKXObj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ found = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (found)
+ break;
+ }
+ }
+ if (!found)
return false;
}
- else
- {
- if (client->m_gameobject->GetProperty(m_propertyname) == NULL)
+ else {
+ if (hitKXObj->GetProperty(m_propertyname) == NULL)
return false;
}
}
diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
index f8f79269eaa..fdcfd22270b 100644
--- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp
@@ -38,7 +38,7 @@
#include "KX_SCA_AddObjectActuator.h"
#include "SCA_IScene.h"
#include "KX_GameObject.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
index e02eca3db63..96e1cc29de3 100644
--- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp
@@ -121,7 +121,9 @@ bool KX_SCA_DynamicActuator::Update()
switch (m_dyn_operation)
{
case 0:
- controller->RestoreDynamics();
+ // Child objects must be static, so we block changing to dynamic
+ if (!obj->GetParent())
+ controller->RestoreDynamics();
break;
case 1:
controller->SuspendDynamics();
diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
index b105256836b..6b6b090c1c4 100644
--- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp
@@ -43,7 +43,7 @@
#include "KX_SCA_ReplaceMeshActuator.h"
#include "KX_MeshProxy.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#ifdef WITH_PYTHON
diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp
index d0eab9de1c1..723736906a9 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"
@@ -42,7 +44,7 @@
#include "KX_BlenderMaterial.h"
#include "KX_FontObject.h"
#include "RAS_IPolygonMaterial.h"
-#include "ListValue.h"
+#include "EXP_ListValue.h"
#include "SCA_LogicManager.h"
#include "SCA_TimeEventManager.h"
//#include "SCA_AlwaysEventManager.h"
@@ -66,7 +68,7 @@
#include "RAS_ICanvas.h"
#include "RAS_BucketManager.h"
-#include "FloatValue.h"
+#include "EXP_FloatValue.h"
#include "SCA_IController.h"
#include "SCA_IActuator.h"
#include "SG_Node.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 "EXP_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;
@@ -218,7 +224,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice,
m_bucketmanager=new RAS_BucketManager();
- bool showObstacleSimulation = scene->gm.flag & GAME_SHOW_OBSTACLE_SIMULATION;
+ bool showObstacleSimulation = (scene->gm.flag & GAME_SHOW_OBSTACLE_SIMULATION) != 0;
switch (scene->gm.obstacleSimulation)
{
case OBSTSIMULATION_TOI_rays:
@@ -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
}
@@ -532,6 +539,8 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
m_objectlist->Add(newobj->AddRef());
if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT)
m_lightlist->Add(newobj->AddRef());
+ else if (newobj->GetGameObjectType()==SCA_IObject::OBJ_TEXT)
+ AddFont((KX_FontObject*)newobj);
newobj->AddMeshUser();
// logic cannot be replicated, until the whole hierarchy is replicated.
@@ -575,6 +584,10 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal
newctrl->SetNewClientInfo(newobj->getClientInfo());
newobj->SetPhysicsController(newctrl, newobj->IsDynamic());
newctrl->PostProcessReplica(motionstate, parentctrl);
+
+ // Child objects must be static
+ if (parent)
+ newctrl->SuspendDynamics();
}
return newobj;
@@ -803,13 +816,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();
}
@@ -829,12 +835,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
(*git)->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());
- }
}
// replicate crosslinks etc. between logic bricks
@@ -846,9 +846,24 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level)
// now look if object in the hierarchy have dupli group and recurse
for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git)
{
+ /* Replicate all constraints. */
+ if ((*git)->GetPhysicsController()) {
+ (*git)->GetPhysicsController()->ReplicateConstraints((*git), m_logicHierarchicalGameObjects);
+ (*git)->ClearConstraints();
+ }
+
if ((*git) != groupobj && (*git)->IsDupliGroup())
// can't instantiate group immediately as it destroys m_logicHierarchicalGameObjects
duplilist.push_back((*git));
+
+ if ((*git)->GetBlenderGroupObject() == blgroupobj) {
+ // set references for dupli-group
+ // groupobj holds a list of all objects, that belongs to this group
+ groupobj->AddInstanceObjects((*git));
+
+ // every object gets the reference to its dupli-group object
+ (*git)->SetDupliGroupObject(groupobj);
+ }
}
for (git = duplilist.begin(); !(git == duplilist.end()); ++git)
@@ -859,7 +874,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)
{
@@ -867,19 +882,18 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject,
m_map_gameobject_to_replica.clear();
m_groupGameObjects.clear();
- // todo: place a timebomb in the object, for temporarily objects :)
- // lifespan of zero means 'this object lives forever'
KX_GameObject* originalobj = (KX_GameObject*) originalobject;
- KX_GameObject* parentobj = (KX_GameObject*) parentobject;
+ KX_GameObject* referenceobj = (KX_GameObject*) referenceobject;
m_ueberExecutionPriority++;
// lets create a replica
KX_GameObject* replica = (KX_GameObject*) AddNodeReplicaObject(NULL,originalobj);
+ // add a timebomb to this object
+ // lifespan of zero means 'this object lives forever'
if (lifespan > 0)
{
- // add a timebomb to this object
// for now, convert between so called frames and realtime
m_tempObjectList->Add(replica->AddRef());
// this convert the life from frames to sort-of seconds, hard coded 0.02 that assumes we have 50 frames per second
@@ -905,19 +919,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();
+ MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation();
+ replica->NodeSetLocalOrientation(newori);
- // set the replica's relative scale with the rootnode's scale
- replica->NodeSetRelativeScale(newscale);
+ // 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 +952,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 +1093,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 +1118,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 +1129,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)
@@ -1502,6 +1524,15 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int
bool dbvt_culling = false;
if (m_dbvt_culling)
{
+ /* Reset KX_GameObject m_bCulled to true before doing culling
+ * since DBVT culling will only set it to false.
+ * This is similar to what RAS_BucketManager does for RAS_MeshSlot culling.
+ */
+ for (int i = 0; i < m_objectlist->GetCount(); i++) {
+ KX_GameObject *gameobj = static_cast<KX_GameObject*>(m_objectlist->GetValue(i));
+ gameobj->SetCulled(true);
+ }
+
// test culling through Bullet
MT_Vector4 planes[6];
// get the clip planes
@@ -1531,9 +1562,6 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int
MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer);
}
}
-
- // Now that we know visible meshes, update LoDs
- UpdateObjectLods();
}
// logic stuff
@@ -1642,20 +1670,6 @@ static void update_anim_thread_func(TaskPool *pool, void *taskdata, int UNUSED(t
void KX_Scene::UpdateAnimations(double curtime)
{
- KX_KetsjiEngine *engine = KX_GetActiveEngine();
-
- if (engine->GetRestrictAnimationFPS())
- {
- // Handle the animations independently of the logic time step
- double anim_timestep = 1.0 / GetAnimationFPS();
- if (curtime - m_previousAnimTime < anim_timestep)
- return;
-
- // 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 = curtime;
- }
-
TaskPool *pool = BLI_task_pool_create(KX_GetActiveEngine()->GetTaskScheduler(), &curtime);
for (int i=0; i<m_animatedlist->GetCount(); ++i) {
@@ -1755,6 +1769,10 @@ void KX_Scene::RenderFonts()
void KX_Scene::UpdateObjectLods(void)
{
KX_GameObject* gameobj;
+
+ if (!this->m_active_camera)
+ return;
+
MT_Vector3 cam_pos = this->m_active_camera->NodeGetWorldPosition();
for (int i = 0; i < this->GetObjectList()->GetCount(); i++) {
@@ -1765,6 +1783,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) {
@@ -1881,15 +1919,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!
@@ -1948,17 +1977,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);
- }
}
}
@@ -1993,12 +2011,20 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene
if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA)
to->AddCamera((KX_Camera*)gameobj);
+ // All armatures should be in the animated object list to be umpdated.
+ if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE)
+ to->AddAnimatedObject(gameobj);
+
/* Add the object to the scene's logic manager */
to->GetLogicManager()->RegisterGameObjectName(gameobj->GetName(), gameobj);
to->GetLogicManager()->RegisterGameObj(gameobj->GetBlenderObject(), gameobj);
- for (int i=0; i<gameobj->GetMeshCount(); ++i)
- to->GetLogicManager()->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), gameobj->GetBlenderObject());
+ for (int i = 0; i < gameobj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshobj = gameobj->GetMesh(i);
+ // Register the mesh object by name and blender object.
+ to->GetLogicManager()->RegisterGameMeshName(meshobj->GetName(), gameobj->GetBlenderObject());
+ to->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj);
+ }
}
bool KX_Scene::MergeScene(KX_Scene *other)
@@ -2042,6 +2068,28 @@ bool KX_Scene::MergeScene(KX_Scene *other)
MergeScene_GameObject(gameobj, this, other);
}
+ if (env) {
+ env->MergeEnvironment(env_other);
+ CListValue *otherObjects = other->GetObjectList();
+
+ // List of all physics objects to merge (needed by ReplicateConstraints).
+ std::vector<KX_GameObject *> physicsObjects;
+ for (unsigned int i = 0; i < otherObjects->GetCount(); ++i) {
+ KX_GameObject *gameobj = (KX_GameObject *)otherObjects->GetValue(i);
+ if (gameobj->GetPhysicsController()) {
+ physicsObjects.push_back(gameobj);
+ }
+ }
+
+ for (unsigned int i = 0; i < physicsObjects.size(); ++i) {
+ KX_GameObject *gameobj = physicsObjects[i];
+ // Replicate all constraints in the right physics environment.
+ gameobj->GetPhysicsController()->ReplicateConstraints(gameobj, physicsObjects);
+ gameobj->ClearConstraints();
+ }
+ }
+
+
GetTempObjectList()->MergeList(other->GetTempObjectList());
other->GetTempObjectList()->ReleaseAndRemoveAll();
@@ -2057,9 +2105,6 @@ bool KX_Scene::MergeScene(KX_Scene *other)
GetLightList()->MergeList(other->GetLightList());
other->GetLightList()->ReleaseAndRemoveAll();
- if (env)
- env->MergeEnvironment(env_other);
-
/* move materials across, assume they both use the same scene-converters
* Do this after lights are merged so materials can use the lights in shaders
*/
@@ -2112,30 +2157,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);
}
//----------------------------------------------------------------------------
@@ -2321,6 +2346,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...
@@ -2385,6 +2423,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);
@@ -2419,6 +2468,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);
@@ -2444,9 +2509,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),
@@ -2459,23 +2526,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 c5840c28041..4f7ad98f30d 100644
--- a/source/gameengine/Ketsji/KX_Scene.h
+++ b/source/gameengine/Ketsji/KX_Scene.h
@@ -49,7 +49,7 @@
#include "RAS_Rect.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "RAS_2DFilterManager.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 {
@@ -289,14 +290,18 @@ protected:
double m_suspendedtime;
double m_suspendeddelta;
- double m_previousAnimTime; //the last time animations were updated
-
struct Scene* m_blenderScene;
RAS_2DFilterManager m_filtermanager;
KX_ObstacleSimulation* m_obstacleSimulation;
+ /**
+ * LOD Hysteresis settings
+ */
+ bool m_isActivedHysteresis;
+ int m_lodHysteresisValue;
+
public:
KX_Scene(class SCA_IInputDevice* keyboarddevice,
class SCA_IInputDevice* mousedevice,
@@ -548,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);
@@ -614,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);
@@ -636,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_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp
index 4e5cd0ac5e1..02b1071e267 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp
@@ -37,10 +37,14 @@
#include "KX_SoundActuator.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
-# include "AUD_PingPongFactory.h"
-# include "AUD_IDevice.h"
-# include "AUD_I3DHandle.h"
+# ifdef WITH_SYSTEM_AUDASPACE
+typedef float sample_t;
+# include AUD_PYTHON_H
+# endif
+# include AUD_SOUND_H
+# include AUD_SPECIAL_H
+# include AUD_DEVICE_H
+# include AUD_HANDLE_H
#endif
#include "KX_GameObject.h"
@@ -53,7 +57,7 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
- boost::shared_ptr<AUD_IFactory> sound,
+ AUD_Sound* sound,
float volume,
float pitch,
bool is3d,
@@ -61,7 +65,8 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
KX_SOUNDACT_TYPE type)//,
: SCA_IActuator(gameobj, KX_ACT_SOUND)
{
- m_sound = sound;
+ m_sound = AUD_Sound_copy(sound);
+ m_handle = NULL;
m_volume = volume;
m_pitch = pitch;
m_is3d = is3d;
@@ -74,20 +79,30 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj,
KX_SoundActuator::~KX_SoundActuator()
{
- if (m_handle.get())
- m_handle->stop();
+ if(m_handle)
+ {
+ AUD_Handle_stop(m_handle);
+ }
+
+ if(m_sound)
+ {
+ AUD_Sound_free(m_sound);
+ }
}
void KX_SoundActuator::play()
{
- if (m_handle.get())
- m_handle->stop();
+ if(m_handle)
+ {
+ AUD_Handle_stop(m_handle);
+ m_handle = NULL;
+ }
- if (!m_sound.get())
+ if (!m_sound)
return;
// this is the sound that will be played and not deleted afterwards
- boost::shared_ptr<AUD_IFactory> sound = m_sound;
+ AUD_Sound* sound = m_sound;
bool loop = false;
@@ -95,7 +110,7 @@ void KX_SoundActuator::play()
{
case KX_SOUNDACT_LOOPBIDIRECTIONAL:
case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
- sound = boost::shared_ptr<AUD_IFactory>(new AUD_PingPongFactory(sound));
+ sound = AUD_Sound_pingpong(sound);
// fall through
case KX_SOUNDACT_LOOPEND:
case KX_SOUNDACT_LOOPSTOP:
@@ -107,36 +122,33 @@ void KX_SoundActuator::play()
break;
}
- try
- {
- m_handle = AUD_getDevice()->play(sound);
- }
- catch(AUD_Exception&)
- {
- // cannot play back, ignore
- return;
- }
+ AUD_Device* device = AUD_Device_getCurrent();
+ m_handle = AUD_Device_play(device, sound, false);
+ AUD_Device_free(device);
- boost::shared_ptr<AUD_I3DHandle> handle3d = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle);
+ // in case of pingpong, we have to free the sound
+ if(sound != m_sound)
+ AUD_Sound_free(sound);
- if (m_is3d && handle3d.get())
+ if (m_handle != NULL)
{
- handle3d->setRelative(true);
- handle3d->setVolumeMaximum(m_3d.max_gain);
- handle3d->setVolumeMinimum(m_3d.min_gain);
- handle3d->setDistanceReference(m_3d.reference_distance);
- handle3d->setDistanceMaximum(m_3d.max_distance);
- handle3d->setAttenuation(m_3d.rolloff_factor);
- handle3d->setConeAngleInner(m_3d.cone_inner_angle);
- handle3d->setConeAngleOuter(m_3d.cone_outer_angle);
- handle3d->setConeVolumeOuter(m_3d.cone_outer_gain);
- }
+ if (m_is3d)
+ {
+ AUD_Handle_setRelative(m_handle, true);
+ AUD_Handle_setVolumeMaximum(m_handle, m_3d.max_gain);
+ AUD_Handle_setVolumeMinimum(m_handle, m_3d.min_gain);
+ AUD_Handle_setDistanceReference(m_handle, m_3d.reference_distance);
+ AUD_Handle_setDistanceMaximum(m_handle, m_3d.max_distance);
+ AUD_Handle_setAttenuation(m_handle, m_3d.rolloff_factor);
+ AUD_Handle_setConeAngleInner(m_handle, m_3d.cone_inner_angle);
+ AUD_Handle_setConeAngleOuter(m_handle, m_3d.cone_outer_angle);
+ AUD_Handle_setConeVolumeOuter(m_handle, m_3d.cone_outer_gain);
+ }
- if (m_handle.get()) {
if (loop)
- m_handle->setLoopCount(-1);
- m_handle->setPitch(m_pitch);
- m_handle->setVolume(m_volume);
+ AUD_Handle_setLoopCount(m_handle, -1);
+ AUD_Handle_setPitch(m_handle, m_pitch);
+ AUD_Handle_setVolume(m_handle, m_volume);
}
m_isplaying = true;
@@ -152,7 +164,8 @@ CValue* KX_SoundActuator::GetReplica()
void KX_SoundActuator::ProcessReplica()
{
SCA_IActuator::ProcessReplica();
- m_handle = boost::shared_ptr<AUD_IHandle>();
+ m_handle = NULL;
+ m_sound = AUD_Sound_copy(m_sound);
}
bool KX_SoundActuator::Update(double curtime, bool frame)
@@ -167,11 +180,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
RemoveAllEvents();
- if (!m_sound.get())
+ if (!m_sound)
return false;
// actual audio device playing state
- bool isplaying = m_handle.get() ? (m_handle->getStatus() == AUD_STATUS_PLAYING) : false;
+ bool isplaying = m_handle ? (AUD_Handle_getStatus(m_handle) == AUD_STATUS_PLAYING) : false;
if (bNegativeEvent)
{
@@ -185,9 +198,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP:
{
// stop immediately
- if (m_handle.get())
- m_handle->stop();
- m_handle = boost::shared_ptr<AUD_IHandle>();
+ if (m_handle)
+ {
+ AUD_Handle_stop(m_handle);
+ m_handle = NULL;
+ }
break;
}
case KX_SOUNDACT_PLAYEND:
@@ -199,8 +214,8 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
case KX_SOUNDACT_LOOPBIDIRECTIONAL:
{
// stop the looping so that the sound stops when it finished
- if (m_handle.get())
- m_handle->setLoopCount(0);
+ if (m_handle)
+ AUD_Handle_setLoopCount(m_handle, 0);
break;
}
default:
@@ -227,13 +242,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
play();
}
// verify that the sound is still playing
- isplaying = m_handle.get() ? (m_handle->getStatus() == AUD_STATUS_PLAYING) : false;
+ isplaying = m_handle ? (AUD_Handle_getStatus(m_handle) == AUD_STATUS_PLAYING) : false;
if (isplaying)
{
- boost::shared_ptr<AUD_I3DHandle> handle3d = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle);
-
- if (m_is3d && handle3d.get())
+ if (m_is3d)
{
KX_Camera* cam = KX_GetActiveScene()->GetActiveCamera();
if (cam)
@@ -241,20 +254,19 @@ bool KX_SoundActuator::Update(double curtime, bool frame)
KX_GameObject* obj = (KX_GameObject*)this->GetParent();
MT_Point3 p;
MT_Matrix3x3 Mo;
- AUD_Vector3 v;
- float q[4];
+ float data[4];
Mo = cam->NodeGetWorldOrientation().inverse();
p = (obj->NodeGetWorldPosition() - cam->NodeGetWorldPosition());
p = Mo * p;
- p.getValue(v.get());
- handle3d->setSourceLocation(v);
+ p.getValue(data);
+ AUD_Handle_setLocation(m_handle, data);
p = (obj->GetLinearVelocity() - cam->GetLinearVelocity());
p = Mo * p;
- p.getValue(v.get());
- handle3d->setSourceVelocity(v);
- (Mo * obj->NodeGetWorldOrientation()).getRotation().getValue(q);
- handle3d->setSourceOrientation(AUD_Quaternion(q[3], q[0], q[1], q[2]));
+ p.getValue(data);
+ AUD_Handle_setVelocity(m_handle, data);
+ (Mo * obj->NodeGetWorldOrientation()).getRotation().getValue(data);
+ AUD_Handle_setOrientation(m_handle, data);
}
}
result = true;
@@ -329,11 +341,11 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, startSound,
"startSound()\n"
"\tStarts the sound.\n")
{
- switch (m_handle.get() ? m_handle->getStatus() : AUD_STATUS_INVALID) {
+ switch (m_handle ? AUD_Handle_getStatus(m_handle) : AUD_STATUS_INVALID) {
case AUD_STATUS_PLAYING:
break;
case AUD_STATUS_PAUSED:
- m_handle->resume();
+ AUD_Handle_resume(m_handle);
break;
default:
play();
@@ -345,8 +357,8 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, pauseSound,
"pauseSound()\n"
"\tPauses the sound.\n")
{
- if (m_handle.get())
- m_handle->pause();
+ if (m_handle)
+ AUD_Handle_pause(m_handle);
Py_RETURN_NONE;
}
@@ -354,9 +366,11 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound,
"stopSound()\n"
"\tStops the sound.\n")
{
- if (m_handle.get())
- m_handle->stop();
- m_handle = boost::shared_ptr<AUD_IHandle>();
+ if (m_handle)
+ {
+ AUD_Handle_stop(m_handle);
+ m_handle = NULL;
+ }
Py_RETURN_NONE;
}
@@ -404,8 +418,8 @@ PyObject *KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_P
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
float position = 0.0;
- if (actuator->m_handle.get())
- position = actuator->m_handle->getPosition();
+ if (actuator->m_handle)
+ position = AUD_Handle_getPosition(actuator->m_handle);
PyObject *result = PyFloat_FromDouble(position);
@@ -435,8 +449,8 @@ PyObject *KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRI
PyObject *KX_SoundActuator::pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef)
{
KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self);
- if (actuator->m_sound.get())
- return (PyObject *)AUD_getPythonFactory(&actuator->m_sound);
+ if (actuator->m_sound)
+ return (PyObject *)AUD_getPythonSound(actuator->m_sound);
else
Py_RETURN_NONE;
}
@@ -450,50 +464,49 @@ int KX_SoundActuator::pyattr_set_3d_property(void *self, const struct KX_PYATTRI
if (!PyArg_Parse(value, "f", &prop_value))
return PY_SET_ATTR_FAIL;
- boost::shared_ptr<AUD_I3DHandle> handle3d = boost::dynamic_pointer_cast<AUD_I3DHandle>(actuator->m_handle);
// if sound is working and 3D, set the new setting
if (!actuator->m_is3d)
return PY_SET_ATTR_FAIL;
if (!strcmp(prop, "volume_maximum")) {
actuator->m_3d.max_gain = prop_value;
- if (handle3d.get())
- handle3d->setVolumeMaximum(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setVolumeMaximum(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "volume_minimum")) {
actuator->m_3d.min_gain = prop_value;
- if (handle3d.get())
- handle3d->setVolumeMinimum(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setVolumeMinimum(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "distance_reference")) {
actuator->m_3d.reference_distance = prop_value;
- if (handle3d.get())
- handle3d->setDistanceReference(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setDistanceReference(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "distance_maximum")) {
actuator->m_3d.max_distance = prop_value;
- if (handle3d.get())
- handle3d->setDistanceMaximum(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setDistanceMaximum(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "attenuation")) {
actuator->m_3d.rolloff_factor = prop_value;
- if (handle3d.get())
- handle3d->setAttenuation(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setAttenuation(actuator->m_handle, prop_value);
} else if (!!strcmp(prop, "cone_angle_inner")) {
actuator->m_3d.cone_inner_angle = prop_value;
- if (handle3d.get())
- handle3d->setConeAngleInner(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setConeAngleInner(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "cone_angle_outer")) {
actuator->m_3d.cone_outer_angle = prop_value;
- if (handle3d.get())
- handle3d->setConeAngleOuter(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setConeAngleOuter(actuator->m_handle, prop_value);
} else if (!strcmp(prop, "cone_volume_outer")) {
actuator->m_3d.cone_outer_gain = prop_value;
- if (handle3d.get())
- handle3d->setConeVolumeOuter(prop_value);
+ if (actuator->m_handle)
+ AUD_Handle_setConeVolumeOuter(actuator->m_handle, prop_value);
} else {
return PY_SET_ATTR_FAIL;
@@ -510,8 +523,8 @@ int KX_SoundActuator::pyattr_set_audposition(void *self, const struct KX_PYATTRI
if (!PyArg_Parse(value, "f", &position))
return PY_SET_ATTR_FAIL;
- if (actuator->m_handle.get())
- actuator->m_handle->seek(position);
+ if (actuator->m_handle)
+ AUD_Handle_setPosition(actuator->m_handle, position);
return PY_SET_ATTR_SUCCESS;
}
@@ -523,8 +536,8 @@ int KX_SoundActuator::pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DE
return PY_SET_ATTR_FAIL;
actuator->m_volume = gain;
- if (actuator->m_handle.get())
- actuator->m_handle->setVolume(gain);
+ if (actuator->m_handle)
+ AUD_Handle_setVolume(actuator->m_handle, gain);
return PY_SET_ATTR_SUCCESS;
}
@@ -537,8 +550,8 @@ int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_D
return PY_SET_ATTR_FAIL;
actuator->m_pitch = pitch;
- if (actuator->m_handle.get())
- actuator->m_handle->setPitch(pitch);
+ if (actuator->m_handle)
+ AUD_Handle_setPitch(actuator->m_handle, pitch);
return PY_SET_ATTR_SUCCESS;
}
@@ -550,11 +563,12 @@ int KX_SoundActuator::pyattr_set_sound(void *self, const struct KX_PYATTRIBUTE_D
if (!PyArg_Parse(value, "O", &sound))
return PY_SET_ATTR_FAIL;
- boost::shared_ptr<AUD_IFactory>* snd = reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(AUD_getPythonSound((void *)sound));
+ AUD_Sound *snd = AUD_getSoundFromPython(sound);
+
if (snd)
{
- actuator->m_sound = *snd;
- delete snd;
+ AUD_Sound_free(actuator->m_sound);
+ actuator->m_sound = snd;
return PY_SET_ATTR_SUCCESS;
}
diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h
index 68eff56797b..5ec2fda722f 100644
--- a/source/gameengine/Ketsji/KX_SoundActuator.h
+++ b/source/gameengine/Ketsji/KX_SoundActuator.h
@@ -35,10 +35,8 @@
#include "SCA_IActuator.h"
#ifdef WITH_AUDASPACE
-# include "AUD_C-API.h"
-# include "AUD_IFactory.h"
-# include "AUD_IHandle.h"
-# include <boost/shared_ptr.hpp>
+# include AUD_SOUND_H
+# include AUD_HANDLE_H
#endif
#include "BKE_sound.h"
@@ -58,12 +56,12 @@ class KX_SoundActuator : public SCA_IActuator
{
Py_Header
bool m_isplaying;
- boost::shared_ptr<AUD_IFactory> m_sound;
+ AUD_Sound* m_sound;
float m_volume;
float m_pitch;
bool m_is3d;
KX_3DSoundSettings m_3d;
- boost::shared_ptr<AUD_IHandle> m_handle;
+ AUD_Handle* m_handle;
void play();
@@ -84,7 +82,7 @@ public:
KX_SOUNDACT_TYPE m_type;
KX_SoundActuator(SCA_IObject* gameobj,
- boost::shared_ptr<AUD_IFactory> sound,
+ AUD_Sound *sound,
float volume,
float pitch,
bool is3d,
diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.cpp b/source/gameengine/Ketsji/KX_SteeringActuator.cpp
index ff192299702..cd2cd2bae0b 100644
--- a/source/gameengine/Ketsji/KX_SteeringActuator.cpp
+++ b/source/gameengine/Ketsji/KX_SteeringActuator.cpp
@@ -41,7 +41,7 @@
/* Native functions */
/* ------------------------------------------------------------------------- */
-KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
+KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
int mode,
KX_GameObject *target,
KX_GameObject *navmesh,
@@ -54,7 +54,8 @@ KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
KX_ObstacleSimulation* simulation,
short facingmode,
bool normalup,
- bool enableVisualization)
+ bool enableVisualization,
+ bool lockzvel)
: SCA_IActuator(gameobj, KX_ACT_STEERING),
m_target(target),
m_mode(mode),
@@ -72,6 +73,7 @@ KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj,
m_normalUp(normalup),
m_pathLen(0),
m_pathUpdatePeriod(pathUpdatePeriod),
+ m_lockzvel(lockzvel),
m_wayPointIdx(-1),
m_steerVec(MT_Vector3(0, 0, 0))
{
@@ -266,14 +268,14 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
m_steerVec.z() = 0;
if (!m_steerVec.fuzzyZero())
m_steerVec.normalize();
- MT_Vector3 newvel = m_velocity*m_steerVec;
+ MT_Vector3 newvel = m_velocity * m_steerVec;
//adjust velocity to avoid obstacles
if (m_simulation && m_obstacle /*&& !newvel.fuzzyZero()*/)
{
if (m_enableVisualization)
KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector3(1.0, 0.0, 0.0));
- m_simulation->AdjustObstacleVelocity(m_obstacle, m_mode!=KX_STEERING_PATHFOLLOWING ? m_navmesh : NULL,
+ m_simulation->AdjustObstacleVelocity(m_obstacle, m_mode!=KX_STEERING_PATHFOLLOWING ? m_navmesh : NULL,
newvel, m_acceleration*delta, m_turnspeed/180.0f*M_PI*delta);
if (m_enableVisualization)
KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector3(0.0, 1.0, 0.0));
@@ -285,7 +287,12 @@ bool KX_SteeringActuator::Update(double curtime, bool frame)
//temporary solution: set 2D steering velocity directly to obj
//correct way is to apply physical force
MT_Vector3 curvel = obj->GetLinearVelocity();
- newvel.z() = curvel.z();
+
+ if (m_lockzvel)
+ newvel.z() = 0.0f;
+ else
+ newvel.z() = curvel.z();
+
obj->setLinearVelocity(newvel, false);
}
else
@@ -554,6 +561,7 @@ PyAttributeDef KX_SteeringActuator::Attributes[] = {
KX_PYATTRIBUTE_RO_FUNCTION("steeringVec", KX_SteeringActuator, pyattr_get_steeringVec),
KX_PYATTRIBUTE_SHORT_RW("facingMode", 0, 6, true, KX_SteeringActuator, m_facingMode),
KX_PYATTRIBUTE_INT_RW("pathUpdatePeriod", -1, 100000, true, KX_SteeringActuator, m_pathUpdatePeriod),
+ KX_PYATTRIBUTE_BOOL_RW("lockZVelocity", KX_SteeringActuator, m_lockzvel),
{ NULL } //Sentinel
};
@@ -602,8 +610,7 @@ int KX_SteeringActuator::pyattr_set_navmesh(void *self, const struct KX_PYATTRIB
if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SteeringActuator"))
return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error
- if (dynamic_cast<KX_NavMeshObject *>(gameobj) == NULL)
- {
+ if (dynamic_cast<KX_NavMeshObject *>(gameobj) == NULL) {
PyErr_Format(PyExc_TypeError, "KX_NavMeshObject is expected");
return PY_SET_ATTR_FAIL;
}
diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.h b/source/gameengine/Ketsji/KX_SteeringActuator.h
index 1e8ac9a54f0..3273471c166 100644
--- a/source/gameengine/Ketsji/KX_SteeringActuator.h
+++ b/source/gameengine/Ketsji/KX_SteeringActuator.h
@@ -62,6 +62,7 @@ class KX_SteeringActuator : public SCA_IActuator
int m_pathLen;
int m_pathUpdatePeriod;
double m_pathUpdateTime;
+ bool m_lockzvel;
int m_wayPointIdx;
MT_Matrix3x3 m_parentlocalmat;
MT_Vector3 m_steerVec;
@@ -89,7 +90,8 @@ public:
KX_ObstacleSimulation* simulation,
short facingmode,
bool normalup,
- bool enableVisualization);
+ bool enableVisualization,
+ bool lockzvel);
virtual ~KX_SteeringActuator();
virtual bool Update(double curtime, bool frame);
diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
index 7ec379eec26..eb774960d41 100644
--- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp
+++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp
@@ -60,7 +60,7 @@ bool KX_TouchEventManager::NewHandleCollision(void* object1, void* object2, cons
PHY_IPhysicsController* obj1 = static_cast<PHY_IPhysicsController*>(object1);
PHY_IPhysicsController* obj2 = static_cast<PHY_IPhysicsController*>(object2);
- m_newCollisions.insert(std::pair<PHY_IPhysicsController*, PHY_IPhysicsController*>(obj1, obj2));
+ m_newCollisions.insert(NewCollision(obj1, obj2, coll_data));
return false;
}
@@ -209,9 +209,11 @@ void KX_TouchEventManager::NextFrame()
}
}
// Run python callbacks
- kxObj1->RunCollisionCallbacks(kxObj2);
- kxObj2->RunCollisionCallbacks(kxObj1);
+ PHY_CollData *colldata = cit->colldata;
+ kxObj1->RunCollisionCallbacks(kxObj2, colldata->m_point1, colldata->m_normal);
+ kxObj2->RunCollisionCallbacks(kxObj1, colldata->m_point2, -colldata->m_normal);
+ delete cit->colldata;
}
m_newCollisions.clear();
@@ -219,3 +221,19 @@ void KX_TouchEventManager::NextFrame()
for (it.begin();!it.end();++it)
(*it)->Activate(m_logicmgr);
}
+
+
+KX_TouchEventManager::NewCollision::NewCollision(PHY_IPhysicsController *first,
+ PHY_IPhysicsController *second,
+ const PHY_CollData *colldata)
+ : first(first), second(second), colldata(new PHY_CollData(*colldata))
+{}
+
+KX_TouchEventManager::NewCollision::NewCollision(const NewCollision &to_copy)
+ : first(to_copy.first), second(to_copy.second), colldata(to_copy.colldata)
+{}
+
+bool KX_TouchEventManager::NewCollision::operator<(const NewCollision &other) const
+{
+ return first < other.first || second < other.second || colldata < other.colldata;
+}
diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.h b/source/gameengine/Ketsji/KX_TouchEventManager.h
index bd4903c1545..d9c6fdad307 100644
--- a/source/gameengine/Ketsji/KX_TouchEventManager.h
+++ b/source/gameengine/Ketsji/KX_TouchEventManager.h
@@ -45,7 +45,29 @@ class PHY_IPhysicsEnvironment;
class KX_TouchEventManager : public SCA_EventManager
{
- typedef std::pair<PHY_IPhysicsController*, PHY_IPhysicsController*> NewCollision;
+ /**
+ * Contains two colliding objects and the first contact point.
+ */
+ class NewCollision {
+ public:
+ PHY_IPhysicsController *first;
+ PHY_IPhysicsController *second;
+ PHY_CollData *colldata;
+
+ /**
+ * Creates a copy of the given PHY_CollData; freeing that copy should be done by the owner of
+ * the NewCollision object.
+ *
+ * This allows us to efficiently store NewCollision objects in a std::set without creating more
+ * copies of colldata, as the NewCollision copy constructor reuses the pointer and doesn't clone
+ * it again. */
+ NewCollision(PHY_IPhysicsController *first,
+ PHY_IPhysicsController *second,
+ const PHY_CollData *colldata);
+ NewCollision(const NewCollision &to_copy);
+ bool operator<(const NewCollision &other) const;
+ };
+
PHY_IPhysicsEnvironment* m_physEnv;
std::set<NewCollision> m_newCollisions;
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp
index 5cb1d5f3620..593d3e844e8 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.cpp
+++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp
@@ -41,6 +41,8 @@
#include "PHY_IPhysicsController.h"
+#include "RAS_MeshObject.h"
+
#include <iostream>
#include "PHY_IPhysicsEnvironment.h"
@@ -219,14 +221,17 @@ bool KX_TouchSensor::BroadPhaseSensorFilterCollision(void*obj1,void*obj2)
bool found = m_touchedpropname.IsEmpty();
if (!found)
{
- if (m_bFindMaterial)
- {
- if (client_info->m_auxilary_info)
- {
- found = (!strcmp(m_touchedpropname.Ptr(), (char*)client_info->m_auxilary_info));
+ if (m_bFindMaterial) {
+ for (unsigned int i = 0; i < otherobj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = otherobj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ found = strcmp(m_touchedpropname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (found)
+ break;
+ }
}
- } else
- {
+ }
+ else {
found = (otherobj->GetProperty(m_touchedpropname) != NULL);
}
}
@@ -255,16 +260,22 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll
{
bool found = m_touchedpropname.IsEmpty();
+ bool hitMaterial = false;
if (!found)
{
- if (m_bFindMaterial)
- {
- if (client_info->m_auxilary_info)
- {
- found = (!strcmp(m_touchedpropname.Ptr(), (char*)client_info->m_auxilary_info));
+ if (m_bFindMaterial) {
+ for (unsigned int i = 0; i < gameobj->GetMeshCount(); ++i) {
+ RAS_MeshObject *meshObj = gameobj->GetMesh(i);
+ for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) {
+ found = strcmp(m_touchedpropname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0;
+ if (found) {
+ hitMaterial = true;
+ break;
+ }
+ }
}
- } else
- {
+ }
+ else {
found = (gameobj->GetProperty(m_touchedpropname) != NULL);
}
}
@@ -278,7 +289,7 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll
}
m_bTriggered = true;
m_hitObject = gameobj;
- m_hitMaterial = (client_info->m_auxilary_info ? (char*)client_info->m_auxilary_info : "");
+ m_hitMaterial = hitMaterial;
//printf("KX_TouchSensor::HandleCollision\n");
}
diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h
index 0edca44296a..e1b5725a32b 100644
--- a/source/gameengine/Ketsji/KX_TouchSensor.h
+++ b/source/gameengine/Ketsji/KX_TouchSensor.h
@@ -34,7 +34,7 @@
#define __KX_TOUCHSENSOR_H__
#include "SCA_ISensor.h"
-#include "ListValue.h"
+#include "EXP_ListValue.h"
struct PHY_CollData;
diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
index 75baf5fac1d..3ed8eba759f 100644
--- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp
+++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp
@@ -44,7 +44,7 @@
#include <iostream>
#include "KX_GameObject.h"
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
/* ------------------------------------------------------------------------- */
/* Native functions */
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
index 535ed5ed39a..ee791a44782 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp
@@ -22,7 +22,7 @@
* \ingroup ketsji
*/
-#include "PyObjectPlus.h"
+#include "EXP_PyObjectPlus.h"
#include "KX_VehicleWrapper.h"
#include "PHY_IPhysicsEnvironment.h"
@@ -53,6 +53,23 @@ KX_VehicleWrapper::~KX_VehicleWrapper()
#ifdef WITH_PYTHON
+
+static bool raise_exc_wheel(PHY_IVehicle *vehicle, int i, const char *method)
+{
+ 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 true;
+ }
+ else {
+ return false;
+ }
+}
+
+#define WHEEL_INDEX_CHECK_OR_RETURN(i, method) \
+ if (raise_exc_wheel(m_vehicle, i, method)) {return NULL;} (void)0
+
+
PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
{
@@ -67,22 +84,36 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
KX_GameObject *gameOb;
if (!ConvertPythonToGameObject(wheelGameObject, &gameOb, false, "vehicle.addWheel(...): KX_VehicleWrapper (first argument)"))
return NULL;
-
if (gameOb->GetSGNode())
{
- PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode());
-
- /* TODO - no error checking here! - bad juju */
MT_Vector3 attachPos,attachDir,attachAxle;
- PyVecTo(pylistPos,attachPos);
- PyVecTo(pylistDir,attachDir);
- PyVecTo(pylistAxleDir,attachAxle);
+ if(!PyVecTo(pylistPos,attachPos)) {
+ PyErr_SetString(PyExc_AttributeError,
+ "addWheel(...) Unable to add wheel. attachPos must be a vector with 3 elements.");
+ return NULL;
+ }
+ if(!PyVecTo(pylistDir,attachDir)) {
+ PyErr_SetString(PyExc_AttributeError,
+ "addWheel(...) Unable to add wheel. downDir must be a vector with 3 elements.");
+ return NULL;
+ }
+ if(!PyVecTo(pylistAxleDir,attachAxle)) {
+ PyErr_SetString(PyExc_AttributeError,
+ "addWheel(...) Unable to add wheel. axleDir must be a vector with 3 elements.");
+ return NULL;
+ }
//someone reverse some conventions inside Bullet (axle winding)
attachAxle = -attachAxle;
- printf("attempt for addWheel: suspensionRestLength%f wheelRadius %f, hasSteering:%d\n",suspensionRestLength,wheelRadius,hasSteering);
+ if(wheelRadius<=0) {
+ PyErr_SetString(PyExc_AttributeError,
+ "addWheel(...) Unable to add wheel. wheelRadius must be positive.");
+ return NULL;
+ }
+
+ PHY_IMotionState *motionState = new KX_MotionState(gameOb->GetSGNode());
m_vehicle->AddWheel(motionState,attachPos,attachDir,attachAxle,suspensionRestLength,wheelRadius,hasSteering);
}
@@ -93,8 +124,6 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args)
}
-
-
PyObject *KX_VehicleWrapper::PyGetWheelPosition(PyObject *args)
{
@@ -103,6 +132,8 @@ PyObject *KX_VehicleWrapper::PyGetWheelPosition(PyObject *args)
if (PyArg_ParseTuple(args,"i:getWheelPosition",&wheelIndex))
{
float position[3];
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelPosition");
+
m_vehicle->GetWheelPosition(wheelIndex,position[0],position[1],position[2]);
MT_Vector3 pos(position[0],position[1],position[2]);
return PyObjectFrom(pos);
@@ -115,6 +146,8 @@ PyObject *KX_VehicleWrapper::PyGetWheelRotation(PyObject *args)
int wheelIndex;
if (PyArg_ParseTuple(args,"i:getWheelRotation",&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelRotation");
+
return PyFloat_FromDouble(m_vehicle->GetWheelRotation(wheelIndex));
}
return NULL;
@@ -126,6 +159,8 @@ PyObject *KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject *args)
if (PyArg_ParseTuple(args,"i:getWheelOrientationQuaternion",&wheelIndex))
{
float orn[4];
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelOrientationQuaternion");
+
m_vehicle->GetWheelOrientationQuaternion(wheelIndex,orn[0],orn[1],orn[2],orn[3]);
MT_Quaternion quatorn(orn[0],orn[1],orn[2],orn[3]);
MT_Matrix3x3 ornmat(quatorn);
@@ -148,7 +183,6 @@ PyObject *KX_VehicleWrapper::PyGetConstraintId(PyObject *args)
}
-
PyObject *KX_VehicleWrapper::PyApplyEngineForce(PyObject *args)
{
float force;
@@ -156,6 +190,8 @@ PyObject *KX_VehicleWrapper::PyApplyEngineForce(PyObject *args)
if (PyArg_ParseTuple(args,"fi:applyEngineForce",&force,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "applyEngineForce");
+
force *= -1.f;//someone reverse some conventions inside Bullet (axle winding)
m_vehicle->ApplyEngineForce(force,wheelIndex);
}
@@ -172,6 +208,8 @@ PyObject *KX_VehicleWrapper::PySetTyreFriction(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setTyreFriction",&wheelFriction,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setTyreFriction");
+
m_vehicle->SetWheelFriction(wheelFriction,wheelIndex);
}
else {
@@ -187,6 +225,8 @@ PyObject *KX_VehicleWrapper::PySetSuspensionStiffness(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setSuspensionStiffness",&suspensionStiffness,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionStiffness");
+
m_vehicle->SetSuspensionStiffness(suspensionStiffness,wheelIndex);
}
else {
@@ -202,6 +242,8 @@ PyObject *KX_VehicleWrapper::PySetSuspensionDamping(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setSuspensionDamping",&suspensionDamping,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionDamping");
+
m_vehicle->SetSuspensionDamping(suspensionDamping,wheelIndex);
} else {
return NULL;
@@ -216,6 +258,8 @@ PyObject *KX_VehicleWrapper::PySetSuspensionCompression(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setSuspensionCompression",&suspensionCompression,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionCompression");
+
m_vehicle->SetSuspensionCompression(suspensionCompression,wheelIndex);
} else {
return NULL;
@@ -230,6 +274,8 @@ PyObject *KX_VehicleWrapper::PySetRollInfluence(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setRollInfluence",&rollInfluence,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setRollInfluence");
+
m_vehicle->SetRollInfluence(rollInfluence,wheelIndex);
}
else {
@@ -246,6 +292,8 @@ PyObject *KX_VehicleWrapper::PyApplyBraking(PyObject *args)
if (PyArg_ParseTuple(args,"fi:applyBraking",&braking,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "applyBraking");
+
m_vehicle->ApplyBraking(braking,wheelIndex);
}
else {
@@ -255,8 +303,6 @@ PyObject *KX_VehicleWrapper::PyApplyBraking(PyObject *args)
}
-
-
PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args)
{
float steeringValue;
@@ -264,6 +310,8 @@ PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args)
if (PyArg_ParseTuple(args,"fi:setSteeringValue",&steeringValue,&wheelIndex))
{
+ WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSteeringValue");
+
m_vehicle->SetSteeringValue(steeringValue,wheelIndex);
}
else {
@@ -316,17 +364,11 @@ PyMethodDef KX_VehicleWrapper::Methods[] = {
{"setSteeringValue",(PyCFunction) KX_VehicleWrapper::sPySetSteeringValue, METH_VARARGS},
{"applyEngineForce",(PyCFunction) KX_VehicleWrapper::sPyApplyEngineForce, METH_VARARGS},
{"applyBraking",(PyCFunction) KX_VehicleWrapper::sPyApplyBraking, METH_VARARGS},
-
{"setTyreFriction",(PyCFunction) KX_VehicleWrapper::sPySetTyreFriction, METH_VARARGS},
-
{"setSuspensionStiffness",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionStiffness, METH_VARARGS},
-
{"setSuspensionDamping",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionDamping, METH_VARARGS},
-
{"setSuspensionCompression",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionCompression, METH_VARARGS},
-
{"setRollInfluence",(PyCFunction) KX_VehicleWrapper::sPySetRollInfluence, METH_VARARGS},
-
{NULL,NULL} //Sentinel
};
diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h
index c38f57d8b9f..22b9591f48b 100644
--- a/source/gameengine/Ketsji/KX_VehicleWrapper.h
+++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h
@@ -6,7 +6,7 @@
#ifndef __KX_VEHICLEWRAPPER_H__
#define __KX_VEHICLEWRAPPER_H__
-#include "Value.h"
+#include "EXP_Value.h"
class PHY_IVehicle;
class PHY_IMotionState;
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..b155faf2837 100644
--- a/source/gameengine/Ketsji/KX_WorldInfo.h
+++ b/source/gameengine/Ketsji/KX_WorldInfo.h
@@ -33,44 +33,72 @@
#define __KX_WORLDINFO_H__
#include "MT_Scalar.h"
+#include "KX_KetsjiEngine.h"
+#include "EXP_PyObjectPlus.h"
-#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+#ifdef USE_MATHUTILS
+void KX_WorldInfo_Mathutils_Callback_Init(void);
#endif
-class MT_CmMatrix4x4;
+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,
+ };
- 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;
+ KX_WorldInfo(Scene *blenderscene, World *blenderworld);
+ ~KX_WorldInfo();
+ 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_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_WorldInfo")
+#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
};
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,
diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript
index db5474cf2d7..d8dfd3d9bca 100644
--- a/source/gameengine/Ketsji/SConscript
+++ b/source/gameengine/Ketsji/SConscript
@@ -30,7 +30,8 @@ import sys
Import ('env')
sources = env.Glob('*.cpp')
-defs = [ 'GLEW_STATIC' ]
+defs = []
+defs += env['BF_GL_DEFINITIONS']
incs = [
'.',
@@ -38,9 +39,8 @@ incs = [
'#intern/guardedalloc',
'#intern/string',
'#source/blender',
- '#extern/glew/include',
- '#intern/audaspace/FX',
- '#intern/audaspace/intern',
+ env['BF_GLEW_INC'],
+ '#/intern/glew-mx',
'#intern/moto/include',
'#source/blender/blenfont',
'#source/blender/blenkernel',
@@ -85,6 +85,11 @@ if env['WITH_BF_PYTHON']:
incs += ' ' + env['BF_PYTHON_INC']
defs.append('WITH_PYTHON')
+if env['WITH_BF_AUDASPACE']:
+ defs += env['BF_AUDASPACE_DEF']
+ incs += ' ' + env['BF_AUDASPACE_C_INC']
+ incs += ' ' + env['BF_AUDASPACE_PY_INC']
+
if env['WITH_BF_FFMPEG']:
defs.append('WITH_FFMPEG')