diff options
Diffstat (limited to 'source/gameengine')
76 files changed, 3020 insertions, 2420 deletions
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index 511b61528f8..1a198920919 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -446,7 +446,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c rasterizer->SetEyeSeparation(scene->gm.eyeseparation); } - rasterizer->SetBackColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 0.0f); + rasterizer->SetBackColor(scene->gm.framing.col); } if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME) diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp index 3a31806fad4..e37818678d6 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp @@ -97,6 +97,11 @@ bool KX_BlenderCanvas::GetSwapInterval(int &intervalOut) return wm_window_get_swap_interval(m_win, &intervalOut); } +void KX_BlenderCanvas::GetDisplayDimensions(int &width, int &height) +{ + wm_get_screensize(&width, &height); +} + void KX_BlenderCanvas::ResizeWindow(int width, int height) { // Not implemented for the embedded player diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h index c150af21230..817a667d783 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h @@ -87,6 +87,8 @@ public: int &intervalOut ); + void GetDisplayDimensions(int &width, int &height); + void ResizeWindow( int width, diff --git a/source/gameengine/CMakeLists.txt b/source/gameengine/CMakeLists.txt index cf7895e98ea..62523175f46 100644 --- a/source/gameengine/CMakeLists.txt +++ b/source/gameengine/CMakeLists.txt @@ -23,6 +23,8 @@ # # ***** END GPL LICENSE BLOCK ***** +remove_extra_strict_flags() + # there are too many inter-includes so best define here if(WITH_PYTHON) blender_include_dirs_sys("${PYTHON_INCLUDE_DIRS}") diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp index e515574df8b..88d82e21d61 100644 --- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp +++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp @@ -334,7 +334,7 @@ PyObject *BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_P } switch (attr_order) { case BCA_IKWEIGHT: - return PyFloat_FromDouble((ikconstraint)?ikconstraint->weight : 0.0f); + return PyFloat_FromDouble(ikconstraint->weight); case BCA_IKTYPE: return PyLong_FromLong(ikconstraint->type); case BCA_IKFLAG: diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index bc2fc0179fd..795a7a9ae87 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -268,7 +268,7 @@ void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter) // get the persistent pose structure bPoseChannel* pchan; bConstraint* pcon; - bConstraintTypeInfo* cti; + const bConstraintTypeInfo* cti; Object* blendtarget; KX_GameObject* gametarget; KX_GameObject* gamesubtarget; diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 7e0588fc7d0..3da0863508b 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -98,7 +98,7 @@ #include "BLI_utildefines.h" #include "BLI_listbase.h" -#include "BlenderWorldInfo.h" +#include "KX_WorldInfo.h" #include "KX_KetsjiEngine.h" #include "KX_BlenderSceneConverter.h" @@ -995,7 +995,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, meshobj->m_sharedvertex_map.resize(totvert); Material* ma = 0; - bool collider = true; MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT]; unsigned int rgb[4] = {0}; @@ -1065,29 +1064,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, else ma = mesh->mat ? mesh->mat[mface->mat_nr]:NULL; - /* ckeck for texface since texface _only_ is used as a fallback */ - if (ma == NULL && tface == NULL) { + // Check for blender material + if (ma == NULL) { ma= &defmaterial; } { - bool visible = true; - bool twoside = false; RAS_MaterialBucket* bucket = material_from_mesh(ma, mface, tface, mcol, layers, lightlayer, rgb, uvs, tfaceName, scene, converter); // set render flags - if (ma) - { - visible = ((ma->game.flag & GEMAT_INVISIBLE)==0); - twoside = ((ma->game.flag & GEMAT_BACKCULL)==0); - collider = ((ma->game.flag & GEMAT_NOPHYSICS)==0); - } - else { - visible = true; - twoside = false; - collider = true; - } + bool visible = ((ma->game.flag & GEMAT_INVISIBLE)==0); + bool twoside = ((ma->game.flag & GEMAT_BACKCULL)==0); + bool collider = ((ma->game.flag & GEMAT_NOPHYSICS)==0); /* mark face as flat, so vertices are split */ bool flat = (mface->flag & ME_SMOOTH) == 0; @@ -1347,8 +1336,8 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, if (!(blenderobject->gameflag & OB_COLLISION)) { // Respond to all collisions so that Near sensors work on No Collision // objects. - gameobj->SetUserCollisionGroup(0xff); - gameobj->SetUserCollisionMask(0xff); + gameobj->SetUserCollisionGroup(0xffff); + gameobj->SetUserCollisionMask(0xffff); return; } @@ -1554,6 +1543,10 @@ static KX_GameObject *gameobject_from_blenderobject( } gameobj->AddLodMesh(BL_ConvertMesh(lodmesh, lodmatob, kxscene, converter, libloading)); } + if (blenderscene->gm.lodflag & SCE_LOD_USE_HYST) { + kxscene->SetLodHysteresis(true); + kxscene->SetLodHysteresisValue(blenderscene->gm.scehysteresis); + } } // for all objects: check whether they want to @@ -1647,7 +1640,7 @@ static KX_GameObject *gameobject_from_blenderobject( case OB_FONT: { - bool do_color_management = !(blenderscene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT); + bool do_color_management = BKE_scene_check_color_management_enabled(blenderscene); /* font objects have no bounding box */ gameobj = new KX_FontObject(kxscene,KX_Scene::m_callbacks, rendertools, ob, do_color_management); @@ -1741,6 +1734,16 @@ static KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist) } +static bool bl_isConstraintInList(KX_GameObject *gameobj, set<KX_GameObject*> convertedlist) +{ + set<KX_GameObject*>::iterator gobit; + for (gobit = convertedlist.begin(); gobit != convertedlist.end(); gobit++) { + if ((*gobit)->GetName() == gameobj->GetName()) + return true; + } + return false; +} + /* helper for BL_ConvertBlenderObjects, avoids code duplication * note: all var names match args are passed from the caller */ static void bl_ConvertBlenderObject_Single( @@ -1900,6 +1903,12 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // is not in a separate thread. BL_Texture::GetMaxUnits(); + /* We have to ensure that group definitions are only converted once + * push all converted group members to this set. + * This will happen when a group instance is made from a linked group instance + * and both are on the active layer. */ + set<KX_GameObject*> convertedlist; + if (alwaysUseExpandFraming) { frame_type = RAS_FrameSettings::e_frame_extend; aspect_width = canvas->GetWidth(); @@ -2031,6 +2040,11 @@ void BL_ConvertBlenderObjects(struct Main* maggie, converter, libloading); + /* Insert object to the constraint game object list + * so we can check later if there is a instance in the scene or + * an instance and its actual group definition. */ + convertedlist.insert((KX_GameObject*)gameobj->AddRef()); + bool isInActiveLayer = false; if (gameobj) { @@ -2270,97 +2284,54 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // create physics joints for (i=0;i<sumolist->GetCount();i++) { - KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); - struct Object* blenderobject = gameobj->GetBlenderObject(); - ListBase *conlist; + PHY_IPhysicsEnvironment *physEnv = kxscene->GetPhysicsEnvironment(); + KX_GameObject *gameobj = (KX_GameObject *)sumolist->GetValue(i); + struct Object *blenderobject = gameobj->GetBlenderObject(); + ListBase *conlist = get_active_constraints2(blenderobject); bConstraint *curcon; - if ((gameobj->GetLayer()&activeLayerBitInfo)==0) + if (!conlist) continue; - conlist = get_active_constraints2(blenderobject); - if (conlist) { - for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) { - if (curcon->type==CONSTRAINT_TYPE_RIGIDBODYJOINT) { - - bRigidBodyJointConstraint *dat=(bRigidBodyJointConstraint *)curcon->data; + for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) { + if (curcon->type != CONSTRAINT_TYPE_RIGIDBODYJOINT) + continue; - if (!dat->child && !(curcon->flag & CONSTRAINT_OFF)) { + bRigidBodyJointConstraint *dat = (bRigidBodyJointConstraint *)curcon->data; + + /* Skip if no target or a child object is selected or constraints are deactivated */ + if (!dat->tar || dat->child || (curcon->flag & CONSTRAINT_OFF)) + continue; - PHY_IPhysicsController* physctr2 = 0; + /* Store constraints of grouped and instanced objects for all layers */ + gameobj->AddConstraint(dat); + + /* Skipped already converted constraints. + * This will happen when a group instance is made from a linked group instance + * and both are on the active layer. */ + if (bl_isConstraintInList(gameobj, convertedlist)) + continue; - if (dat->tar) { - KX_GameObject *gotar=getGameOb(dat->tar->id.name+2,sumolist); - if (gotar && ((gotar->GetLayer()&activeLayerBitInfo)!=0) && gotar->GetPhysicsController()) - physctr2 = gotar->GetPhysicsController(); - } + KX_GameObject *gotar = getGameOb(dat->tar->id.name + 2, sumolist); - if (gameobj->GetPhysicsController()) { - PHY_IPhysicsController* physctrl = gameobj->GetPhysicsController(); - //we need to pass a full constraint frame, not just axis - - //localConstraintFrameBasis - MT_Matrix3x3 localCFrame(MT_Vector3(dat->axX,dat->axY,dat->axZ)); - MT_Vector3 axis0 = localCFrame.getColumn(0); - MT_Vector3 axis1 = localCFrame.getColumn(1); - MT_Vector3 axis2 = localCFrame.getColumn(2); - - int constraintId = kxscene->GetPhysicsEnvironment()->CreateConstraint(physctrl,physctr2,(PHY_ConstraintType)dat->type,(float)dat->pivX, - (float)dat->pivY,(float)dat->pivZ, - (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(),dat->flag); - if (constraintId) { - //if it is a generic 6DOF constraint, set all the limits accordingly - if (dat->type == PHY_GENERIC_6DOF_CONSTRAINT) { - int dof; - int dofbit=1; - for (dof=0;dof<6;dof++) { - if (dat->flag & dofbit) { - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,dat->minLimit[dof],dat->maxLimit[dof]); - } else { - //minLimit > maxLimit means free(disabled limit) for this degree of freedom - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1); - } - dofbit<<=1; - } - } else if (dat->type == PHY_CONE_TWIST_CONSTRAINT) { - int dof; - int dofbit = 1<<3; // bitflag use_angular_limit_x - - for (dof=3;dof<6;dof++) { - if (dat->flag & dofbit) { - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,dat->minLimit[dof],dat->maxLimit[dof]); - } else { - //maxLimit < 0 means free(disabled limit) for this degree of freedom - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1); - } - dofbit<<=1; - } - } else if (dat->type == PHY_LINEHINGE_CONSTRAINT) { - int dof = 3; // dof for angular x - int dofbit = 1<<3; // bitflag use_angular_limit_x - - if (dat->flag & dofbit) { - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof, - dat->minLimit[dof],dat->maxLimit[dof]); - } else { - //minLimit > maxLimit means free(disabled limit) for this degree of freedom - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1); - } - } - } - } - } - } + if (gotar && (gotar->GetLayer()&activeLayerBitInfo) && gotar->GetPhysicsController() && + (gameobj->GetLayer()&activeLayerBitInfo) && gameobj->GetPhysicsController()) + { + physEnv->SetupObjectConstraints(gameobj, gotar, dat); } } } + /* cleanup converted set of group objects */ + set<KX_GameObject*>::iterator gobit; + for (gobit = convertedlist.begin(); gobit != convertedlist.end(); gobit++) + (*gobit)->Release(); + + convertedlist.clear(); sumolist->Release(); // convert world - KX_WorldInfo* worldinfo = new BlenderWorldInfo(blenderscene, blenderscene->world); + KX_WorldInfo* worldinfo = new KX_WorldInfo(blenderscene, blenderscene->world); converter->RegisterWorldInfo(worldinfo); kxscene->SetWorldInfo(worldinfo); diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp deleted file mode 100644 index 75beb5d0e0e..00000000000 --- a/source/gameengine/Converter/BlenderWorldInfo.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can [0]istribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file gameengine/Converter/BlenderWorldInfo.cpp - * \ingroup bgeconv - */ - - -#include <stdio.h> // printf() - -#include "BlenderWorldInfo.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_object_types.h" -#include "DNA_material_types.h" -#include "DNA_image_types.h" -#include "DNA_lamp_types.h" -#include "DNA_group_types.h" -#include "DNA_scene_types.h" -#include "DNA_camera_types.h" -#include "DNA_property_types.h" -#include "DNA_text_types.h" -#include "DNA_sensor_types.h" -#include "DNA_controller_types.h" -#include "DNA_actuator_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_view3d_types.h" -#include "DNA_world_types.h" -#include "DNA_screen_types.h" - -#include "BLI_math.h" - -#include "BKE_global.h" -#include "BKE_scene.h" -/* end of blender include block */ - - -BlenderWorldInfo::BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld) -{ - if (blenderworld) { - m_hasworld = true; - - // do we have mist? - if ((blenderworld->mode) & WO_MIST) { - m_hasmist = true; - m_miststart = blenderworld->miststa; - m_mistdistance = blenderworld->mistdist; - copy_v3_v3(m_mistcolor, &blenderworld->horr); - } - else { - m_hasmist = false; - m_miststart = 0.0; - m_mistdistance = 0.0; - zero_v3(m_mistcolor); - } - - copy_v3_v3(m_backgroundcolor, &blenderworld->horr); - copy_v3_v3(m_ambientcolor, &blenderworld->ambr); - - if (BKE_scene_check_color_management_enabled(blenderscene)) { - linearrgb_to_srgb_v3_v3(m_mistcolor, m_mistcolor); - linearrgb_to_srgb_v3_v3(m_backgroundcolor, m_backgroundcolor); - linearrgb_to_srgb_v3_v3(m_ambientcolor, m_ambientcolor); - } - } - else { - m_hasworld = false; - } -} - -BlenderWorldInfo::~BlenderWorldInfo() -{ -} - -bool BlenderWorldInfo::hasWorld() -{ - return m_hasworld; -} - -bool BlenderWorldInfo::hasMist() -{ - return m_hasmist; -} - -float BlenderWorldInfo::getBackColorRed() -{ - return m_backgroundcolor[0]; -} - -float BlenderWorldInfo::getBackColorGreen() -{ - return m_backgroundcolor[1]; -} - -float BlenderWorldInfo::getBackColorBlue() -{ - return m_backgroundcolor[2]; -} - -float BlenderWorldInfo::getAmbientColorRed() -{ - return m_ambientcolor[0]; -} - -float BlenderWorldInfo::getAmbientColorGreen() -{ - return m_ambientcolor[1]; -} - -float BlenderWorldInfo::getAmbientColorBlue() -{ - return m_ambientcolor[2]; -} - -float BlenderWorldInfo::getMistStart() -{ - return m_miststart; -} - -float BlenderWorldInfo::getMistDistance() -{ - return m_mistdistance; -} - -float BlenderWorldInfo::getMistColorRed() -{ - return m_mistcolor[0]; -} - -float BlenderWorldInfo::getMistColorGreen() -{ - return m_mistcolor[1]; -} - -float BlenderWorldInfo::getMistColorBlue() -{ - return m_mistcolor[2]; -} - -void BlenderWorldInfo::setBackColor(float r, float g, float b) -{ - m_backgroundcolor[0] = r; - m_backgroundcolor[1] = g; - m_backgroundcolor[2] = b; -} - -void BlenderWorldInfo::setMistStart(float d) -{ - m_miststart = d; -} - -void BlenderWorldInfo::setMistDistance(float d) -{ - m_mistdistance = d; -} - -void BlenderWorldInfo::setMistColorRed(float d) -{ - m_mistcolor[0] = d; -} - -void BlenderWorldInfo::setMistColorGreen(float d) -{ - m_mistcolor[1] = d; -} - -void BlenderWorldInfo::setMistColorBlue(float d) -{ - m_mistcolor[2] = d; -} diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h deleted file mode 100644 index 2ac2d70b5d1..00000000000 --- a/source/gameengine/Converter/BlenderWorldInfo.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file BlenderWorldInfo.h - * \ingroup bgeconv - */ - -#ifndef __BLENDERWORLDINFO_H__ -#define __BLENDERWORLDINFO_H__ -#include "MT_CmMatrix4x4.h" -#include "KX_WorldInfo.h" - -class BlenderWorldInfo : public KX_WorldInfo -{ - bool m_hasworld; - float m_backgroundcolor[3]; - - bool m_hasmist; - float m_miststart; - float m_mistdistance; - float m_mistcolor[3]; - - float m_ambientcolor[3]; - -public: - BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld); - ~BlenderWorldInfo(); - - bool hasWorld(); - bool hasMist(); - float getBackColorRed(); - float getBackColorGreen(); - float getBackColorBlue(); - - float getAmbientColorRed(); - float getAmbientColorGreen(); - float getAmbientColorBlue(); - - float getMistStart(); - float getMistDistance(); - float getMistColorRed(); - float getMistColorGreen(); - float getMistColorBlue(); - - void setBackColor(float r, float g, float b); - void setMistStart(float d); - void setMistDistance(float d); - void setMistColorRed(float d); - void setMistColorGreen(float d); - void setMistColorBlue(float d); - - -#ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("GE:BlenderWorldInfo") -#endif -}; - -#endif /* __BLENDERWORLDINFO_H__ */ diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index 9c0d25e56ff..6d681dd166e 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -56,7 +56,7 @@ set(INC set(INC_SYS ../../../intern/moto/include ../../../extern/recastnavigation/Detour/Include - ../../../extern/Eigen3 + ${EIGEN3_INCLUDE_DIRS} ${PTHREADS_INCLUDE_DIRS} ${BOOST_INCLUDE_DIR} ) @@ -74,7 +74,6 @@ set(SRC BL_ShapeActionActuator.cpp BL_ShapeDeformer.cpp BL_SkinDeformer.cpp - BlenderWorldInfo.cpp KX_BlenderScalarInterpolator.cpp KX_BlenderSceneConverter.cpp KX_ConvertActuators.cpp @@ -96,7 +95,6 @@ set(SRC BL_ShapeActionActuator.h BL_ShapeDeformer.h BL_SkinDeformer.h - BlenderWorldInfo.h KX_BlenderScalarInterpolator.h KX_BlenderSceneConverter.h KX_ConvertActuators.h diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 09cc74d717f..9e53d9e1569 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -58,7 +58,7 @@ #include "KX_LibLoadStatus.h" #include "KX_BlenderScalarInterpolator.h" #include "BL_BlenderDataConversion.h" -#include "BlenderWorldInfo.h" +#include "KX_WorldInfo.h" /* This little block needed for linking to Blender... */ #ifdef WIN32 @@ -117,11 +117,9 @@ typedef struct ThreadInfo { } ThreadInfo; KX_BlenderSceneConverter::KX_BlenderSceneConverter( - struct Main* maggie, - class KX_KetsjiEngine* engine - ) - : m_maggie(maggie), - /*m_maggie_dyn(NULL),*/ + Main *maggie, + KX_KetsjiEngine *engine) + :m_maggie(maggie), m_ketsjiEngine(engine), m_alwaysUseExpandFraming(false), m_usemat(false), @@ -134,13 +132,11 @@ KX_BlenderSceneConverter::KX_BlenderSceneConverter( pthread_mutex_init(&m_threadinfo->merge_lock, NULL); } - KX_BlenderSceneConverter::~KX_BlenderSceneConverter() { // clears meshes, and hashmaps from blender to gameengine data - int i; // delete sumoshapes - + if (m_threadinfo) { vector<pthread_t>::iterator pit = m_threadinfo->threads.begin(); while (pit != m_threadinfo->threads.end()) { @@ -153,104 +149,83 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() } int numAdtLists = m_map_blender_to_gameAdtList.size(); - for (i=0; i<numAdtLists; i++) { - BL_InterpolatorList *adtList= *m_map_blender_to_gameAdtList.at(i); + for (int i = 0; i < numAdtLists; i++) { + BL_InterpolatorList *adtList = *m_map_blender_to_gameAdtList.at(i); delete (adtList); } - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itw = m_worldinfos.begin(); + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itw = m_worldinfos.begin(); while (itw != m_worldinfos.end()) { delete (*itw).second; itw++; } m_worldinfos.clear(); - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin(); + vector<pair<KX_Scene *,RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin(); while (itp != m_polymaterials.end()) { - //m_polymat_cache.erase((*itp).second->GetBlenderMaterial()); delete (*itp).second; itp++; } m_polymaterials.clear(); // delete after RAS_IPolyMaterial - vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin(); + vector<pair<KX_Scene *,BL_Material *> >::iterator itmat = m_materials.begin(); while (itmat != m_materials.end()) { - //m_mat_cache.erase((*itmat).second->material); delete (*itmat).second; itmat++; } m_materials.clear(); - - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin(); + vector<pair<KX_Scene *,RAS_MeshObject *> >::iterator itm = m_meshobjects.begin(); while (itm != m_meshobjects.end()) { delete (*itm).second; itm++; } m_meshobjects.clear(); - /* free any data that was dynamically loaded */ - while (m_DynamicMaggie.size() != 0) - { + while (m_DynamicMaggie.size() != 0) { FreeBlendFile(m_DynamicMaggie[0]); } m_DynamicMaggie.clear(); } -void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename) +void KX_BlenderSceneConverter::SetNewFileName(const STR_String &filename) { m_newfilename = filename; } - - bool KX_BlenderSceneConverter::TryAndLoadNewFile() { bool result = false; - // find the file -/* if () - { - result = true; - } - // if not, clear the newfilename - else - { - m_newfilename = ""; - } -*/ return result; } -Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name) +Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String &name) { Scene *sce; /** * Find the specified scene by name, or NULL if nothing matches. */ - if ((sce= (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2))) + if ((sce = (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2))) return sce; - for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) { - Main *main= *it; + for (vector<Main *>::iterator it=m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { + Main *main = *it; if ((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2))) return sce; } return NULL; - } -void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, - class RAS_IRasterizer* rendertools, - class RAS_ICanvas* canvas, - bool libloading) +void KX_BlenderSceneConverter::ConvertScene(KX_Scene *destinationscene, RAS_IRasterizer *rendertools, + RAS_ICanvas *canvas, bool libloading) { //find out which physics engine Scene *blenderscene = destinationscene->GetBlenderScene(); @@ -266,13 +241,12 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, // when doing threaded conversion, so it's disabled for now. // SG_SetActiveStage(SG_STAGE_CONVERTER); - switch (blenderscene->gm.physicsEngine) - { + switch (blenderscene->gm.physicsEngine) { #ifdef WITH_BULLET case WOPHY_BULLET: { SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/ - int visualizePhysics = SYS_GetCommandLineInt(syshandle,"show_physics",0); + int visualizePhysics = SYS_GetCommandLineInt(syshandle, "show_physics", 0); phy_env = CcdPhysicsEnvironment::Create(blenderscene, visualizePhysics); physics_engine = UseBullet; @@ -291,7 +265,8 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, destinationscene->SetPhysicsEnvironment(phy_env); - BL_ConvertBlenderObjects(m_maggie, + BL_ConvertBlenderObjects( + m_maggie, destinationscene, m_ketsjiEngine, physics_engine, @@ -299,8 +274,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, canvas, this, m_alwaysUseExpandFraming, - libloading - ); + libloading); //These lookup are not needed during game m_map_blender_to_gameactuator.clear(); @@ -326,30 +300,32 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) // delete the scene first as it will stop the use of entities delete scene; // delete the entities of this scene - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit; + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit; size = m_worldinfos.size(); - for (i=0, worldit=m_worldinfos.begin(); i<size; ) { + for (i = 0, worldit = m_worldinfos.begin(); i < size; ) { if ((*worldit).first == scene) { delete (*worldit).second; *worldit = m_worldinfos.back(); m_worldinfos.pop_back(); size--; - } else { + } + else { i++; worldit++; } } - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit; + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit; size = m_polymaterials.size(); - for (i=0, polymit=m_polymaterials.begin(); i<size; ) { + for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { if ((*polymit).first == scene) { m_polymat_cache[scene].erase((*polymit).second->GetBlenderMaterial()); delete (*polymit).second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); size--; - } else { + } + else { i++; polymit++; } @@ -357,16 +333,17 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) m_polymat_cache.erase(scene); - vector<pair<KX_Scene*,BL_Material*> >::iterator matit; + vector<pair<KX_Scene *, BL_Material *> >::iterator matit; size = m_materials.size(); - for (i=0, matit=m_materials.begin(); i<size; ) { + for (i = 0, matit = m_materials.begin(); i < size; ) { if ((*matit).first == scene) { m_mat_cache[scene].erase((*matit).second->material); delete (*matit).second; *matit = m_materials.back(); m_materials.pop_back(); size--; - } else { + } + else { i++; matit++; } @@ -374,15 +351,16 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) m_mat_cache.erase(scene); - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit; + vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit; size = m_meshobjects.size(); - for (i=0, meshit=m_meshobjects.begin(); i<size; ) { + for (i = 0, meshit = m_meshobjects.begin(); i < size; ) { if ((*meshit).first == scene) { delete (*meshit).second; *meshit = m_meshobjects.back(); m_meshobjects.pop_back(); size--; - } else { + } + else { i++; meshit++; } @@ -425,43 +403,34 @@ bool KX_BlenderSceneConverter::GetCacheMaterials() void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat) { // First make sure we don't register the material twice - vector<pair<KX_Scene*,BL_Material*> >::iterator it; + vector<pair<KX_Scene *, BL_Material *> >::iterator it; for (it = m_materials.begin(); it != m_materials.end(); ++it) if (it->second == mat) return; - m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat)); + m_materials.push_back(pair<KX_Scene *, BL_Material *> (m_currentScene, mat)); } - - -void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming( - bool to_what) +void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(bool to_what) { m_alwaysUseExpandFraming= to_what; } - - -void KX_BlenderSceneConverter::RegisterGameObject( - KX_GameObject *gameobject, - struct Object *for_blenderobject) +void KX_BlenderSceneConverter::RegisterGameObject(KX_GameObject *gameobject, Object *for_blenderobject) { /* only maintained while converting, freed during game runtime */ - m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject); + m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject), gameobject); } /* only need to run this during conversion since * m_map_blender_to_gameobject is freed after conversion */ -void KX_BlenderSceneConverter::UnregisterGameObject( - KX_GameObject *gameobject) +void KX_BlenderSceneConverter::UnregisterGameObject(KX_GameObject *gameobject) { - struct Object *bobp= gameobject->GetBlenderObject(); + Object *bobp = gameobject->GetBlenderObject(); if (bobp) { CHashedPtr bptr(bobp); - KX_GameObject **gobp= m_map_blender_to_gameobject[bptr]; - if (gobp && *gobp == gameobject) - { + KX_GameObject **gobp = m_map_blender_to_gameobject[bptr]; + if (gobp && *gobp == gameobject) { // also maintain m_map_blender_to_gameobject if the gameobject // being removed is matching the blender object m_map_blender_to_gameobject.remove(bptr); @@ -469,47 +438,41 @@ void KX_BlenderSceneConverter::UnregisterGameObject( } } -KX_GameObject *KX_BlenderSceneConverter::FindGameObject( - struct Object *for_blenderobject) +KX_GameObject *KX_BlenderSceneConverter::FindGameObject(Object *for_blenderobject) { - KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)]; - - return obp?*obp:NULL; + KX_GameObject **obp = m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)]; + + return obp ? *obp : NULL; } -void KX_BlenderSceneConverter::RegisterGameMesh( - RAS_MeshObject *gamemesh, - struct Mesh *for_blendermesh) +void KX_BlenderSceneConverter::RegisterGameMesh(RAS_MeshObject *gamemesh, Mesh *for_blendermesh) { if (for_blendermesh) { /* dynamically loaded meshes we don't want to keep lookups for */ m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh); } - m_meshobjects.push_back(pair<KX_Scene*,RAS_MeshObject*>(m_currentScene,gamemesh)); + m_meshobjects.push_back(pair<KX_Scene *, RAS_MeshObject *> (m_currentScene,gamemesh)); } - - -RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh( - struct Mesh *for_blendermesh/*, - unsigned int onlayer*/) +RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(Mesh *for_blendermesh) { - RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)]; - - if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) { + RAS_MeshObject **meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)]; + + if (meshp) { return *meshp; - } else { + } + else { return NULL; } -} +} void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat) { // First make sure we don't register the material twice - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator it; + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator it; for (it = m_polymaterials.begin(); it != m_polymaterials.end(); ++it) if (it->second == polymat) return; - m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat)); + m_polymaterials.push_back(pair<KX_Scene *, RAS_IPolyMaterial *> (m_currentScene, polymat)); } void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, RAS_IPolyMaterial *polymat) @@ -518,94 +481,82 @@ void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, m_polymat_cache[scene][mat] = polymat; } -RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, struct Material *mat) +RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, Material *mat) { return (m_use_mat_cache) ? m_polymat_cache[scene][mat] : NULL; } -void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, struct Material *mat, BL_Material *blmat) +void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, Material *mat, BL_Material *blmat) { if (m_use_mat_cache && mat) m_mat_cache[scene][mat] = blmat; } - -BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, struct Material *mat) +BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, Material *mat) { return (m_use_mat_cache) ? m_mat_cache[scene][mat] : NULL; } - -void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, struct bAction *for_act) +void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, bAction *for_act) { m_map_blender_to_gameAdtList.insert(CHashedPtr(for_act), actList); } -BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(struct bAction *for_act) +BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(bAction *for_act) { BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_act)]; - return listp?*listp:NULL; + return listp ? *listp : NULL; } - -void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, struct bActuator *for_actuator) +void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, bActuator *for_actuator) { m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act); } -SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(struct bActuator *for_actuator) +SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(bActuator *for_actuator) { SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)]; - return actp?*actp:NULL; + return actp ? *actp : NULL; } - -void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, struct bController *for_controller) +void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, bController *for_controller) { m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont); } -SCA_IController *KX_BlenderSceneConverter::FindGameController(struct bController *for_controller) +SCA_IController *KX_BlenderSceneConverter::FindGameController(bController *for_controller) { SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)]; - return contp?*contp:NULL; + return contp ? *contp : NULL; } - - void KX_BlenderSceneConverter::RegisterWorldInfo(KX_WorldInfo *worldinfo) { - m_worldinfos.push_back(pair<KX_Scene*,KX_WorldInfo*>(m_currentScene,worldinfo)); + m_worldinfos.push_back(pair<KX_Scene *, KX_WorldInfo *> (m_currentScene, worldinfo)); } -void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) +void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) { //TODO this entire function is deprecated, written for 2.4x //the functionality should be rewritten, currently it does nothing - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;i<numScenes;i++) - { - KX_Scene* scene = scenes->at(i); - //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetRootParentList(); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); + CListValue *parentList = scene->GetRootParentList(); int numObjects = parentList->GetCount(); int g; - for (g=0;g<numObjects;g++) - { - KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); if (gameObj->IsRecordAnimation()) { - - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject) - { + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject) { #if 0 //erase existing ipo's Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2); - if (ipo) - { //clear the curve data + if (ipo) { //clear the curve data if (clearIpo) {//rcruiz IpoCurve *icu1; @@ -630,64 +581,52 @@ void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) localDel_ipoCurve( tmpicu ); } } - } else - { ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB); + } + else { + ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB); blenderObject->ipo = ipo; - } #endif } } - } - - } - - - } -void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() +void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() { //TODO the functionality should be rewritten } - - ///this generates ipo curves for position, rotation, allowing to use game physics in animation -void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) +// this generates ipo curves for position, rotation, allowing to use game physics in animation +void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) { - - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;i<numScenes;i++) - { - KX_Scene* scene = scenes->at(i); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetObjectList(); + CListValue *parentList = scene->GetObjectList(); int numObjects = parentList->GetCount(); int g; - for (g=0;g<numObjects;g++) - { - KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject && blenderObject->parent==NULL && gameObj->IsRecordAnimation()) { - - if (blenderObject->adt==NULL) - BKE_id_add_animdata(&blenderObject->id); - - if (blenderObject->adt) - { - const MT_Point3& position = gameObj->NodeGetWorldPosition(); + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject && blenderObject->parent == NULL && gameObj->IsRecordAnimation()) { + if (blenderObject->adt == NULL) + BKE_animdata_add_id(&blenderObject->id); + + if (blenderObject->adt) { + const MT_Point3 &position = gameObj->NodeGetWorldPosition(); //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); + const MT_Matrix3x3 &orn = gameObj->NodeGetWorldOrientation(); position.getValue(blenderObject->loc); float tmat[3][3]; - for (int r=0;r<3;r++) - for (int c=0;c<3;c++) + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) tmat[r][c] = (float)orn[c][r]; mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat); @@ -772,27 +711,22 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) } } - -void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() +void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() { - - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;i<numScenes;i++) - { - KX_Scene* scene = scenes->at(i); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetRootParentList(); + CListValue *parentList = scene->GetRootParentList(); int numObjects = parentList->GetCount(); int g; - for (g=0;g<numObjects;g++) - { - KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); if (gameObj->IsRecordAnimation()) { - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject && blenderObject->adt) - { + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject && blenderObject->adt) { bAction *act = verify_adt_action(&blenderObject->id, false); FCurve *fcu; @@ -832,14 +766,14 @@ PyObject *KX_BlenderSceneConverter::GetPyNamespace() } #endif -vector<Main*> &KX_BlenderSceneConverter::GetMainDynamic() +vector<Main *> &KX_BlenderSceneConverter::GetMainDynamic() { return m_DynamicMaggie; } -Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) +Main *KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) { - for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) + for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) if (BLI_path_cmp((*it)->name, path) == 0) return *it; @@ -848,22 +782,21 @@ Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) void KX_BlenderSceneConverter::MergeAsyncLoads() { - vector<KX_Scene*> *merge_scenes; + vector<KX_Scene *> *merge_scenes; - vector<KX_LibLoadStatus*>::iterator mit; - vector<KX_Scene*>::iterator sit; + vector<KX_LibLoadStatus *>::iterator mit; + vector<KX_Scene *>::iterator sit; pthread_mutex_lock(&m_threadinfo->merge_lock); - for (mit=m_mergequeue.begin(); mit!=m_mergequeue.end(); ++mit) { - merge_scenes = (vector<KX_Scene*>*)(*mit)->GetData(); + for (mit = m_mergequeue.begin(); mit != m_mergequeue.end(); ++mit) { + merge_scenes = (vector<KX_Scene *> *)(*mit)->GetData(); for (sit=merge_scenes->begin(); sit!=merge_scenes->end(); ++sit) { (*mit)->GetMergeScene()->MergeScene(*sit); delete (*sit); } - delete merge_scenes; (*mit)->SetData(NULL); @@ -885,17 +818,17 @@ void KX_BlenderSceneConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status) static void *async_convert(void *ptr) { KX_Scene *new_scene = NULL; - KX_LibLoadStatus *status = (KX_LibLoadStatus*)ptr; - vector<Scene*> *scenes = (vector<Scene*>*)status->GetData(); - vector<KX_Scene*> *merge_scenes = new vector<KX_Scene*>(); // Deleted in MergeAsyncLoads + KX_LibLoadStatus *status = (KX_LibLoadStatus *)ptr; + vector<Scene *> *scenes = (vector<Scene *> *)status->GetData(); + vector<KX_Scene *> *merge_scenes = new vector<KX_Scene *>(); // Deleted in MergeAsyncLoads - for (unsigned int i=0; i<scenes->size(); ++i) { + for (unsigned int i = 0; i < scenes->size(); ++i) { new_scene = status->GetEngine()->CreateScene((*scenes)[i], true); if (new_scene) merge_scenes->push_back(new_scene); - status->AddProgress((1.f/scenes->size())*0.9f); // We'll call conversion 90% and merging 10% for now + status->AddProgress((1.0f / scenes->size()) * 0.9f); // We'll call conversion 90% and merging 10% for now } delete scenes; @@ -922,28 +855,21 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFilePath(const char *filepa return LinkBlendFile(bpy_openlib, filepath, group, scene_merge, err_str, options); } -static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const char *path, int idcode) +static void load_datablocks(Main *main_tmp, BlendHandle *bpy_openlib, const char *path, int idcode) { - Main *main_tmp= NULL; /* created only for linking, then freed */ LinkNode *names = NULL; - short flag= 0; /* don't need any special options */ - - /* here appending/linking starts */ - main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); int totnames_dummy; - names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy); + names = BLO_blendhandle_get_datablock_names(bpy_openlib, idcode, &totnames_dummy); - int i=0; - LinkNode *n= names; + int i = 0; + LinkNode *n = names; while (n) { BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode); - n= (LinkNode *)n->next; + n = (LinkNode *)n->next; i++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ - - BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); } KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) @@ -956,42 +882,48 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl // TIMEIT_START(bge_link_blend_file); KX_LibLoadStatus *status; - + /* only scene and mesh supported right now */ - if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) { + if (idcode != ID_SCE && idcode != ID_ME && idcode != ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); - *err_str= err_local; + *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } if (GetMainDynamicPath(path)) { snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path); - *err_str= err_local; + *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } - if (bpy_openlib==NULL) { + if (bpy_openlib == NULL) { snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path); - *err_str= err_local; + *err_str = err_local; return NULL; } - + main_newlib = BKE_main_new(); BKE_reports_init(&reports, RPT_STORE); - load_datablocks(main_newlib, bpy_openlib, path, idcode); + short flag = 0; /* don't need any special options */ + /* created only for linking, then freed */ + Main *main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); + + load_datablocks(main_tmp, bpy_openlib, path, idcode); - if (idcode==ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { - load_datablocks(main_newlib, bpy_openlib, path, ID_TXT); + if (idcode == ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { + load_datablocks(main_tmp, bpy_openlib, path, ID_TXT); } /* now do another round of linking for Scenes so all actions are properly loaded */ - if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { - load_datablocks(main_newlib, bpy_openlib, path, ID_AC); + if (idcode == ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { + load_datablocks(main_tmp, bpy_openlib, path, ID_AC); } - + + BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); + BLO_blendhandle_close(bpy_openlib); BKE_reports_clear(&reports); @@ -1004,42 +936,43 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl status = new KX_LibLoadStatus(this, m_ketsjiEngine, scene_merge, path); - if (idcode==ID_ME) { + if (idcode == ID_ME) { /* Convert all new meshes into BGE meshes */ - ID* mesh; + ID *mesh; - for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) { + for (mesh = (ID *)main_newlib->mesh.first; mesh; mesh = (ID *)mesh->next ) { if (options & LIB_LOAD_VERBOSE) - printf("MeshName: %s\n", mesh->name+2); + printf("MeshName: %s\n", mesh->name + 2); RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders - scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); + scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj); } } - else if (idcode==ID_AC) { + else if (idcode == ID_AC) { /* Convert all actions */ ID *action; - for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { + for (action= (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) - printf("ActionName: %s\n", action->name+2); - scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); + printf("ActionName: %s\n", action->name + 2); + scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } - else if (idcode==ID_SCE) { + else if (idcode == ID_SCE) { /* Merge all new linked in scene into the existing one */ ID *scene; // scenes gets deleted by the thread when it's done using it (look in async_convert()) - vector<Scene*> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene*>() : NULL; + vector<Scene *> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene *>() : NULL; - for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) { + for (scene = (ID *)main_newlib->scene.first; scene; scene = (ID *)scene->next ) { if (options & LIB_LOAD_VERBOSE) - printf("SceneName: %s\n", scene->name+2); + printf("SceneName: %s\n", scene->name + 2); if (options & LIB_LOAD_ASYNC) { - scenes->push_back((Scene*)scene); - } else { + scenes->push_back((Scene *)scene); + } + else { /* merge into the base scene */ - KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene, true); + KX_Scene* other = m_ketsjiEngine->CreateScene((Scene *)scene, true); scene_merge->MergeScene(other); // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene @@ -1050,7 +983,7 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl if (options & LIB_LOAD_ASYNC) { pthread_t id; status->SetData(scenes); - pthread_create(&id, NULL, &async_convert, (void*)status); + pthread_create(&id, NULL, &async_convert, (void *)status); m_threadinfo->threads.push_back(id); } @@ -1064,17 +997,16 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl if (options & LIB_LOAD_LOAD_ACTIONS) { ID *action; - for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { + for (action = (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) - printf("ActionName: %s\n", action->name+2); - scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); + printf("ActionName: %s\n", action->name + 2); + scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } } if (!(options & LIB_LOAD_ASYNC)) status->Finish(); - // TIMEIT_END(bge_link_blend_file); @@ -1084,22 +1016,22 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl /* Note m_map_*** are all ok and don't need to be freed * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */ -bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) +bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie) { - int maggie_index= -1; - int i=0; + int maggie_index = -1; + int i = 0; - if (maggie==NULL) + if (maggie == NULL) return false; /* tag all false except the one we remove */ - for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) { - Main *main= *it; + for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { + Main *main = *it; if (main != maggie) { BKE_main_id_tag_all(main, false); } else { - maggie_index= i; + maggie_index = i; } i++; } @@ -1111,15 +1043,12 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index); BKE_main_id_tag_all(maggie, true); - /* free all tagged objects */ - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); - - for (int scene_idx=0;scene_idx<numScenes;scene_idx++) - { - KX_Scene* scene = scenes->at(scene_idx); + for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { + KX_Scene *scene = scenes->at(scene_idx); if (IS_TAGGED(scene->GetBlenderScene())) { m_ketsjiEngine->RemoveScene(scene->GetName()); m_mat_cache.erase(scene); @@ -1128,16 +1057,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) numScenes--; } else { - /* in case the mesh might be refered to later */ { - CTR_Map<STR_HashedString,void*> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap(); + CTR_Map<STR_HashedString, void *> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap(); - for (int i=0; i<mapStringToMeshes.size(); i++) - { - RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i); - if (meshobj && IS_TAGGED(meshobj->GetMesh())) - { + for (int i = 0; i < mapStringToMeshes.size(); i++) { + RAS_MeshObject *meshobj = (RAS_MeshObject *) *mapStringToMeshes.at(i); + if (meshobj && IS_TAGGED(meshobj->GetMesh())) { STR_HashedString mn = meshobj->GetName(); mapStringToMeshes.remove(mn); m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh())); @@ -1148,15 +1074,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) /* Now unregister actions */ { - CTR_Map<STR_HashedString,void*> &mapStringToActions = scene->GetLogicManager()->GetActionMap(); + CTR_Map<STR_HashedString, void *> &mapStringToActions = scene->GetLogicManager()->GetActionMap(); - for (int i=0; i<mapStringToActions.size(); i++) - { - ID *action= (ID*) *mapStringToActions.at(i); + for (int i = 0; i < mapStringToActions.size(); i++) { + ID *action = (ID*) *mapStringToActions.at(i); - if (IS_TAGGED(action)) - { - STR_HashedString an = action->name+2; + if (IS_TAGGED(action)) { + STR_HashedString an = action->name + 2; mapStringToActions.remove(an); i--; } @@ -1166,16 +1090,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) //scene->FreeTagged(); /* removed tagged objects and meshes*/ CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL}; - for (int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++) - { - CListValue *obs= obj_lists[ob_ls_idx]; - RAS_MeshObject* mesh; + for (int ob_ls_idx = 0; obj_lists[ob_ls_idx]; ob_ls_idx++) { + CListValue *obs = obj_lists[ob_ls_idx]; + RAS_MeshObject *mesh; - for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) - { - KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx); + for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) { + KX_GameObject *gameobj = (KX_GameObject*)obs->GetValue(ob_idx); if (IS_TAGGED(gameobj->GetBlenderObject())) { - int size_before = obs->GetCount(); /* Eventually calls RemoveNodeDestructObject @@ -1190,9 +1111,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } else { /* free the mesh, we could be referecing a linked one! */ - int mesh_index= gameobj->GetMeshCount(); + int mesh_index = gameobj->GetMeshCount(); while (mesh_index--) { - mesh= gameobj->GetMesh(mesh_index); + mesh = gameobj->GetMesh(mesh_index); if (IS_TAGGED(mesh->GetMesh())) { gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */ break; @@ -1210,11 +1131,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } /* make sure action actuators are not referencing tagged actions */ - for (unsigned int act_idx=0; act_idx<gameobj->GetActuators().size(); act_idx++) - { - if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) - { - BL_ActionActuator *act = (BL_ActionActuator*)gameobj->GetActuators()[act_idx]; + for (unsigned int act_idx = 0; act_idx < gameobj->GetActuators().size(); act_idx++) { + if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) { + BL_ActionActuator *act = (BL_ActionActuator *)gameobj->GetActuators()[act_idx]; if (IS_TAGGED(act->GetAction())) act->SetAction(NULL); } @@ -1225,7 +1144,6 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } } - int size; // delete the entities of this scene @@ -1248,24 +1166,24 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) /* Worlds don't reference original blender data so we need to make a set from them */ - typedef std::set<KX_WorldInfo*> KX_WorldInfoSet; + typedef std::set<KX_WorldInfo *> KX_WorldInfoSet; KX_WorldInfoSet worldset; - for (int scene_idx=0;scene_idx<numScenes;scene_idx++) - { - KX_Scene* scene = scenes->at(scene_idx); + for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { + KX_Scene *scene = scenes->at(scene_idx); if (scene->GetWorldInfo()) - worldset.insert( scene->GetWorldInfo() ); + worldset.insert(scene->GetWorldInfo()); } - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit; + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit; size = m_worldinfos.size(); - for (i=0, worldit=m_worldinfos.begin(); i<size; ) { + for (i = 0, worldit = m_worldinfos.begin(); i < size;) { if ((*worldit).second && (worldset.count((*worldit).second)) == 0) { delete (*worldit).second; *worldit = m_worldinfos.back(); m_worldinfos.pop_back(); size--; - } else { + } + else { i++; worldit++; } @@ -1273,20 +1191,15 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) worldset.clear(); /* done freeing the worlds */ - - - - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit; + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit; size = m_polymaterials.size(); + for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { + RAS_IPolyMaterial *mat = (*polymit).second; + Material *bmat = NULL; - - for (i=0, polymit=m_polymaterials.begin(); i<size; ) { - RAS_IPolyMaterial *mat= (*polymit).second; - Material *bmat= NULL; - - KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat); - bmat= bl_mat->GetBlenderMaterial(); + KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial *>(mat); + bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { /* only remove from bucket */ @@ -1297,63 +1210,57 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) polymit++; } - - - for (i=0, polymit=m_polymaterials.begin(); i<size; ) { - RAS_IPolyMaterial *mat= (*polymit).second; - Material *bmat= NULL; + for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { + RAS_IPolyMaterial *mat = (*polymit).second; + Material *bmat = NULL; KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat); - bmat= bl_mat->GetBlenderMaterial(); - - if (bmat) { - //printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2); - } - else { - //printf("LOST MAT !!!"); - } + bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { + // Remove the poly material coresponding to this Blender Material. + m_polymat_cache[polymit->first].erase(bmat); delete (*polymit).second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); size--; - //printf("tagged !\n"); } else { i++; polymit++; - //printf("(un)tagged !\n"); } } - vector<pair<KX_Scene*,BL_Material*> >::iterator matit; + vector<pair<KX_Scene *, BL_Material *> >::iterator matit; size = m_materials.size(); - for (i=0, matit=m_materials.begin(); i<size; ) { - BL_Material *mat= (*matit).second; + for (i = 0, matit = m_materials.begin(); i < size; ) { + BL_Material *mat = (*matit).second; if (IS_TAGGED(mat->material)) { + // Remove the bl material coresponding to this Blender Material. + m_mat_cache[matit->first].erase(mat->material); delete (*matit).second; *matit = m_materials.back(); m_materials.pop_back(); size--; - } else { + } + else { i++; matit++; } } - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit; + vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit; RAS_BucketManager::BucketList::iterator bit; list<RAS_MeshSlot>::iterator msit; RAS_BucketManager::BucketList buckets; size = m_meshobjects.size(); - for (i=0, meshit=m_meshobjects.begin(); i<size; ) { - RAS_MeshObject *me= (*meshit).second; + for (i = 0, meshit = m_meshobjects.begin(); i < size;) { + RAS_MeshObject *me = (*meshit).second; if (IS_TAGGED(me->GetMesh())) { // Before deleting the mesh object, make sure the rasterizer is // no longer referencing it. buckets = meshit->first->GetBucketManager()->GetSolidBuckets(); - for (bit=buckets.begin(); bit!=buckets.end(); bit++) { + for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { @@ -1366,7 +1273,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) // And now the alpha buckets buckets = meshit->first->GetBucketManager()->GetAlphaBuckets(); - for (bit=buckets.begin(); bit!=buckets.end(); bit++) { + for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { @@ -1382,7 +1289,8 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) *meshit = m_meshobjects.back(); m_meshobjects.pop_back(); size--; - } else { + } + else { i++; meshit++; } @@ -1409,24 +1317,23 @@ bool KX_BlenderSceneConverter::FreeBlendFile(const char *path) bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from) { - { - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itp = m_worldinfos.begin(); + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itp = m_worldinfos.begin(); while (itp != m_worldinfos.end()) { - if ((*itp).first==from) - (*itp).first= to; + if ((*itp).first == from) + (*itp).first = to; itp++; } } { - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin(); + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin(); while (itp != m_polymaterials.end()) { - if ((*itp).first==from) { - (*itp).first= to; + if ((*itp).first == from) { + (*itp).first = to; /* also switch internal data */ - RAS_IPolyMaterial*mat= (*itp).second; + RAS_IPolyMaterial *mat = (*itp).second; mat->Replace_IScene(to); } itp++; @@ -1434,29 +1341,39 @@ bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from) } { - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itp = m_meshobjects.begin(); + vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator itp = m_meshobjects.begin(); while (itp != m_meshobjects.end()) { - if ((*itp).first==from) - (*itp).first= to; + if ((*itp).first == from) + (*itp).first = to; itp++; } } { - vector<pair<KX_Scene*,BL_Material*> >::iterator itp = m_materials.begin(); + vector<pair<KX_Scene *, BL_Material *> >::iterator itp = m_materials.begin(); while (itp != m_materials.end()) { - if ((*itp).first==from) - (*itp).first= to; + if ((*itp).first == from) + (*itp).first = to; itp++; } } - + + MaterialCache::iterator matcacheit = m_mat_cache.find(from); + // Merge cached BL_Material map. + m_mat_cache[to].insert(matcacheit->second.begin(), matcacheit->second.end()); + m_mat_cache.erase(matcacheit); + + PolyMaterialCache::iterator polymatcacheit = m_polymat_cache.find(from); + // Merge cached RAS_IPolyMaterial map. + m_polymat_cache[to].insert(polymatcacheit->second.begin(), polymatcacheit->second.end()); + m_polymat_cache.erase(polymatcacheit); + return true; } /* This function merges a mesh from the current scene into another main * it does not convert */ -RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name) +RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, const char *name) { /* Find a mesh in the current main */ ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2)); @@ -1464,7 +1381,7 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, if (me == NULL) { // The mesh wasn't in the current main, try any dynamic (i.e., LibLoaded) ones - vector<Main*>::iterator it; + vector<Main *>::iterator it; for (it = GetMainDynamic().begin(); it != GetMainDynamic().end(); it++) { me = static_cast<ID *>(BLI_findstring(&(*it)->mesh, name, offsetof(ID, name) + 2)); @@ -1474,12 +1391,12 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, break; } } - - if (me==NULL) { + + if (me == NULL) { printf("Could not be found \"%s\"\n", name); return NULL; } - + /* Watch this!, if its used in the original scene can cause big troubles */ if (me->us > 0) { #ifdef DEBUG @@ -1491,34 +1408,32 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, BLI_remlink(&from_maggie->mesh, me); /* even if we made the copy it needs to be removed */ BLI_addtail(&maggie->mesh, me); - /* Must copy the materials this uses else we cant free them */ { - Mesh *mesh= (Mesh *)me; - + Mesh *mesh = (Mesh *)me; + /* ensure all materials are tagged */ - for (int i=0; i<mesh->totcol; i++) + for (int i = 0; i < mesh->totcol; i++) { if (mesh->mat[i]) mesh->mat[i]->id.flag &= ~LIB_DOIT; - - for (int i=0; i<mesh->totcol; i++) - { - Material *mat_old= mesh->mat[i]; - + } + + for (int i = 0; i < mesh->totcol; i++) { + Material *mat_old = mesh->mat[i]; + /* if its tagged its a replaced material */ - if (mat_old && (mat_old->id.flag & LIB_DOIT)==0) - { - Material *mat_old= mesh->mat[i]; - Material *mat_new= BKE_material_copy( mat_old ); - + if (mat_old && (mat_old->id.flag & LIB_DOIT) == 0) { + Material *mat_old = mesh->mat[i]; + Material *mat_new = BKE_material_copy(mat_old); + mat_new->id.flag |= LIB_DOIT; mat_old->id.us--; - + BLI_remlink(&G.main->mat, mat_new); // BKE_material_copy uses G.main, and there is no BKE_material_copy_ex BLI_addtail(&maggie->mat, mat_new); - + mesh->mat[i] = mat_new; - + /* the same material may be used twice */ for (int j = i + 1; j < mesh->totcol; j++) { if (mesh->mat[j] == mat_old) { diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 0d706fcd924..854ae5b28dc 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -105,7 +105,7 @@ void BL_ConvertSensors(struct Object* blenderobject, bSensor* sens = (bSensor*)blenderobject->sensors.first; bool pos_pulsemode = false; bool neg_pulsemode = false; - int frequency = 0; + int skipped_ticks = 0; bool invert = false; bool level = false; bool tap = false; @@ -119,542 +119,542 @@ void BL_ConvertSensors(struct Object* blenderobject, sens = (bSensor*)blenderobject->sensors.first; while (sens) { - SCA_ISensor* gamesensor=NULL; - /* All sensors have a pulse toggle, frequency, and invert field. */ - /* These are extracted here, and set when the sensor is added to the */ - /* list. */ - pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0; - neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0; - - frequency = sens->freq; - invert = !(sens->invert == 0); - level = !(sens->level == 0); - tap = !(sens->tap == 0); - - switch (sens->type) - { - case SENS_ALWAYS: - { - - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) - { - gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj); - } - - break; - } - - case SENS_DELAY: + if (!(sens->flag & SENS_DEACTIVATE)) { + SCA_ISensor* gamesensor=NULL; + /* All sensors have a pulse toggle, skipped ticks parameter, and invert field. */ + /* These are extracted here, and set when the sensor is added to the */ + /* list. */ + pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0; + neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0; + + skipped_ticks = sens->freq; + invert = !(sens->invert == 0); + level = !(sens->level == 0); + tap = !(sens->tap == 0); + + switch (sens->type) { - // we can reuse the Always event manager for the delay sensor - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + case SENS_ALWAYS: { - bDelaySensor* delaysensor = (bDelaySensor*)sens->data; - gamesensor = new SCA_DelaySensor(eventmgr, - gameobj, - delaysensor->delay, - delaysensor->duration, - (delaysensor->flag & SENS_DELAY_REPEAT) != 0); + + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) + { + gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj); + } + + break; } - break; - } - case SENS_COLLISION: - { - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - if (eventmgr) + case SENS_DELAY: { - // collision sensor can sense both materials and properties. - - bool bFindMaterial = false, bTouchPulse = false; - - bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data; - - bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL); - bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE); - - - const STR_String touchPropOrMatName = bFindMaterial ? - blendertouchsensor->materialName : blendertouchsensor->name; - - - if (gameobj->GetPhysicsController()) + // we can reuse the Always event manager for the delay sensor + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) { - gamesensor = new KX_TouchSensor(eventmgr, + bDelaySensor* delaysensor = (bDelaySensor*)sens->data; + gamesensor = new SCA_DelaySensor(eventmgr, gameobj, - bFindMaterial, - bTouchPulse, - touchPropOrMatName); + delaysensor->delay, + delaysensor->duration, + (delaysensor->flag & SENS_DELAY_REPEAT) != 0); } - - } - - break; - } - case SENS_MESSAGE: - { - KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*) - logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR); - if (eventmgr) { - bMessageSensor* msgSens = (bMessageSensor*) sens->data; - - /* Get our NetworkScene */ - NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene(); - /* filter on the incoming subjects, might be empty */ - const STR_String subject = msgSens->subject; - - gamesensor = new KX_NetworkMessageSensor( - eventmgr, // our eventmanager - NetworkScene, // our NetworkScene - gameobj, // the sensor controlling object - subject); // subject to filter on + break; } - break; - } - case SENS_NEAR: - { - - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - if (eventmgr) + + case SENS_COLLISION: { - bNearSensor* blendernearsensor = (bNearSensor*)sens->data; - const STR_String nearpropertyname = (char *)blendernearsensor->name; - - //DT_ShapeHandle shape = DT_Sphere(0.0); - - // this sumoObject is not deleted by a gameobj, so delete it ourself - // later (memleaks)! - float radius = blendernearsensor->dist; - const MT_Vector3& wpos = gameobj->NodeGetWorldPosition(); - bool bFindMaterial = false; - PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,wpos); - - //will be done in KX_TouchEventManager::RegisterSensor() - //if (isInActiveLayer) - // kxscene->GetPhysicsEnvironment()->addSensor(physCtrl); - - - - gamesensor = new KX_NearSensor(eventmgr,gameobj, - blendernearsensor->dist, - blendernearsensor->resetdist, - bFindMaterial, - nearpropertyname, - physCtrl); - + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); + if (eventmgr) + { + // collision sensor can sense both materials and properties. + + bool bFindMaterial = false, bTouchPulse = false; + + bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data; + + bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL); + bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE); + + + const STR_String touchPropOrMatName = bFindMaterial ? + blendertouchsensor->materialName : blendertouchsensor->name; + + + if (gameobj->GetPhysicsController()) + { + gamesensor = new KX_TouchSensor(eventmgr, + gameobj, + bFindMaterial, + bTouchPulse, + touchPropOrMatName); + } + + } + + break; } - break; - } - - - case SENS_KEYBOARD: - { - /* temporary input device, for converting the code for the keyboard sensor */ - - bKeyboardSensor* blenderkeybdsensor = (bKeyboardSensor*)sens->data; - SCA_KeyboardManager* eventmgr = (SCA_KeyboardManager*) logicmgr->FindEventManager(SCA_EventManager::KEYBOARD_EVENTMGR); - if (eventmgr) + case SENS_MESSAGE: { - gamesensor = new SCA_KeyboardSensor(eventmgr, - ConvertKeyCode(blenderkeybdsensor->key), - ConvertKeyCode(blenderkeybdsensor->qual), - ConvertKeyCode(blenderkeybdsensor->qual2), - (blenderkeybdsensor->type == SENS_ALL_KEYS), - blenderkeybdsensor->targetName, - blenderkeybdsensor->toggleName, - gameobj, - KX_KetsjiEngine::GetExitKey()); // blenderkeybdsensor->pad); - - } - - break; - } - case SENS_MOUSE: - { - int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF; - int trackfocus = 0; - bMouseSensor *bmouse = (bMouseSensor *)sens->data; - - /* There are two main types of mouse sensors. If there is - * no focus-related behavior requested, we can make do - * with a basic sensor. This cuts down memory usage and - * gives a slight performance gain. */ - - SCA_MouseManager *eventmgr - = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR); - if (eventmgr) { - - /* Determine key mode. There is at most one active mode. */ - switch (bmouse->type) { - case BL_SENS_MOUSE_LEFT_BUTTON: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_LEFTBUTTON; - break; - case BL_SENS_MOUSE_MIDDLE_BUTTON: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MIDDLEBUTTON; - break; - case BL_SENS_MOUSE_RIGHT_BUTTON: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_RIGHTBUTTON; - break; - case BL_SENS_MOUSE_WHEEL_UP: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELUP; - break; - case BL_SENS_MOUSE_WHEEL_DOWN: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELDOWN; - break; - case BL_SENS_MOUSE_MOVEMENT: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MOVEMENT; - break; - case BL_SENS_MOUSE_MOUSEOVER: - trackfocus = 1; - break; - case BL_SENS_MOUSE_MOUSEOVER_ANY: - trackfocus = 2; - break; - - default: - ; /* error */ + KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*) + logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR); + if (eventmgr) { + bMessageSensor* msgSens = (bMessageSensor*) sens->data; + + /* Get our NetworkScene */ + NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene(); + /* filter on the incoming subjects, might be empty */ + const STR_String subject = msgSens->subject; + + gamesensor = new KX_NetworkMessageSensor( + eventmgr, // our eventmanager + NetworkScene, // our NetworkScene + gameobj, // the sensor controlling object + subject); // subject to filter on } - - /* initial mouse position */ - int startx = canvas->GetWidth()/2; - int starty = canvas->GetHeight()/2; - - if (!trackfocus) { - /* plain, simple mouse sensor */ - gamesensor = new SCA_MouseSensor(eventmgr, - startx,starty, - keytype, - gameobj); - } else { - /* give us a focus-aware sensor */ - bool bFindMaterial = (bmouse->mode & SENS_COLLISION_MATERIAL); - bool bXRay = (bmouse->flag & SENS_RAY_XRAY); - STR_String checkname = (bFindMaterial? bmouse->matname : bmouse->propname); - - gamesensor = new KX_MouseFocusSensor(eventmgr, - startx, - starty, - keytype, - trackfocus, - (bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false, - checkname, + break; + } + case SENS_NEAR: + { + + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); + if (eventmgr) + { + bNearSensor* blendernearsensor = (bNearSensor*)sens->data; + const STR_String nearpropertyname = (char *)blendernearsensor->name; + + //DT_ShapeHandle shape = DT_Sphere(0.0); + + // this sumoObject is not deleted by a gameobj, so delete it ourself + // later (memleaks)! + float radius = blendernearsensor->dist; + const MT_Vector3& wpos = gameobj->NodeGetWorldPosition(); + bool bFindMaterial = false; + PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,wpos); + + //will be done in KX_TouchEventManager::RegisterSensor() + //if (isInActiveLayer) + // kxscene->GetPhysicsEnvironment()->addSensor(physCtrl); + + + + gamesensor = new KX_NearSensor(eventmgr,gameobj, + blendernearsensor->dist, + blendernearsensor->resetdist, bFindMaterial, - bXRay, - kxscene, - kxengine, - gameobj); + nearpropertyname, + physCtrl); + } - } else { - // cout << "\n Could't find mouse event manager..."; - should throw an error here... + break; } - break; - } - case SENS_PROPERTY: - { - bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data; - SCA_EventManager* eventmgr - = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + + + case SENS_KEYBOARD: { - STR_String propname=blenderpropsensor->name; - STR_String propval=blenderpropsensor->value; - STR_String propmaxval=blenderpropsensor->maxvalue; - - SCA_PropertySensor::KX_PROPSENSOR_TYPE - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NODEF; - - /* Better do an explicit conversion here! (was implicit */ - /* before...) */ - switch (blenderpropsensor->type) { - case SENS_PROP_EQUAL: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL; - break; - case SENS_PROP_NEQUAL: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL; - break; - case SENS_PROP_INTERVAL: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_INTERVAL; - break; - case SENS_PROP_CHANGED: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_CHANGED; - break; - case SENS_PROP_EXPRESSION: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION; - /* error */ - break; - case SENS_PROP_LESSTHAN: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_LESSTHAN; - break; - case SENS_PROP_GREATERTHAN: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_GREATERTHAN; - break; - default: - ; /* error */ + /* temporary input device, for converting the code for the keyboard sensor */ + + bKeyboardSensor* blenderkeybdsensor = (bKeyboardSensor*)sens->data; + SCA_KeyboardManager* eventmgr = (SCA_KeyboardManager*) logicmgr->FindEventManager(SCA_EventManager::KEYBOARD_EVENTMGR); + if (eventmgr) + { + gamesensor = new SCA_KeyboardSensor(eventmgr, + ConvertKeyCode(blenderkeybdsensor->key), + ConvertKeyCode(blenderkeybdsensor->qual), + ConvertKeyCode(blenderkeybdsensor->qual2), + (blenderkeybdsensor->type == SENS_ALL_KEYS), + blenderkeybdsensor->targetName, + blenderkeybdsensor->toggleName, + gameobj, + KX_KetsjiEngine::GetExitKey()); // blenderkeybdsensor->pad); + } - gamesensor = new SCA_PropertySensor(eventmgr,gameobj,propname,propval,propmaxval,propchecktype); + + break; } - - break; - } - case SENS_ACTUATOR: - { - bActuatorSensor* blenderactsensor = (bActuatorSensor*) sens->data; - // we will reuse the property event manager, there is nothing special with this sensor - SCA_EventManager* eventmgr - = logicmgr->FindEventManager(SCA_EventManager::ACTUATOR_EVENTMGR); - if (eventmgr) + case SENS_MOUSE: + { + int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF; + int trackfocus = 0; + bMouseSensor *bmouse = (bMouseSensor *)sens->data; + + /* There are two main types of mouse sensors. If there is + * no focus-related behavior requested, we can make do + * with a basic sensor. This cuts down memory usage and + * gives a slight performance gain. */ + + SCA_MouseManager *eventmgr + = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR); + if (eventmgr) { + + /* Determine key mode. There is at most one active mode. */ + switch (bmouse->type) { + case BL_SENS_MOUSE_LEFT_BUTTON: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_LEFTBUTTON; + break; + case BL_SENS_MOUSE_MIDDLE_BUTTON: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MIDDLEBUTTON; + break; + case BL_SENS_MOUSE_RIGHT_BUTTON: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_RIGHTBUTTON; + break; + case BL_SENS_MOUSE_WHEEL_UP: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELUP; + break; + case BL_SENS_MOUSE_WHEEL_DOWN: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELDOWN; + break; + case BL_SENS_MOUSE_MOVEMENT: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MOVEMENT; + break; + case BL_SENS_MOUSE_MOUSEOVER: + trackfocus = 1; + break; + case BL_SENS_MOUSE_MOUSEOVER_ANY: + trackfocus = 2; + break; + + default: + ; /* error */ + } + + /* initial mouse position */ + int startx = canvas->GetWidth()/2; + int starty = canvas->GetHeight()/2; + + if (!trackfocus) { + /* plain, simple mouse sensor */ + gamesensor = new SCA_MouseSensor(eventmgr, + startx,starty, + keytype, + gameobj); + } else { + /* give us a focus-aware sensor */ + bool bFindMaterial = (bmouse->mode & SENS_COLLISION_MATERIAL); + bool bXRay = (bmouse->flag & SENS_RAY_XRAY); + STR_String checkname = (bFindMaterial? bmouse->matname : bmouse->propname); + + gamesensor = new KX_MouseFocusSensor(eventmgr, + startx, + starty, + keytype, + trackfocus, + (bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false, + checkname, + bFindMaterial, + bXRay, + kxscene, + kxengine, + gameobj); + } + } else { + // cout << "\n Could't find mouse event manager..."; - should throw an error here... + } + break; + } + case SENS_PROPERTY: { - STR_String propname=blenderactsensor->name; - gamesensor = new SCA_ActuatorSensor(eventmgr,gameobj,propname); + bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data; + SCA_EventManager* eventmgr + = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) + { + STR_String propname=blenderpropsensor->name; + STR_String propval=blenderpropsensor->value; + STR_String propmaxval=blenderpropsensor->maxvalue; + + SCA_PropertySensor::KX_PROPSENSOR_TYPE + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NODEF; + + /* Better do an explicit conversion here! (was implicit */ + /* before...) */ + switch (blenderpropsensor->type) { + case SENS_PROP_EQUAL: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL; + break; + case SENS_PROP_NEQUAL: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL; + break; + case SENS_PROP_INTERVAL: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_INTERVAL; + break; + case SENS_PROP_CHANGED: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_CHANGED; + break; + case SENS_PROP_EXPRESSION: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION; + /* error */ + break; + case SENS_PROP_LESSTHAN: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_LESSTHAN; + break; + case SENS_PROP_GREATERTHAN: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_GREATERTHAN; + break; + default: + ; /* error */ + } + gamesensor = new SCA_PropertySensor(eventmgr,gameobj,propname,propval,propmaxval,propchecktype); + } + + break; } - break; - } - - case SENS_ARMATURE: - { - bArmatureSensor* blenderarmsensor = (bArmatureSensor*) sens->data; - // we will reuse the property event manager, there is nothing special with this sensor - SCA_EventManager* eventmgr - = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + case SENS_ACTUATOR: { - STR_String bonename=blenderarmsensor->posechannel; - STR_String constraintname=blenderarmsensor->constraint; - gamesensor = new KX_ArmatureSensor(eventmgr,gameobj,bonename,constraintname, blenderarmsensor->type, blenderarmsensor->value); + bActuatorSensor* blenderactsensor = (bActuatorSensor*) sens->data; + // we will reuse the property event manager, there is nothing special with this sensor + SCA_EventManager* eventmgr + = logicmgr->FindEventManager(SCA_EventManager::ACTUATOR_EVENTMGR); + if (eventmgr) + { + STR_String propname=blenderactsensor->name; + gamesensor = new SCA_ActuatorSensor(eventmgr,gameobj,propname); + } + break; } - break; - } - case SENS_RADAR: - { - - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - if (eventmgr) + case SENS_ARMATURE: { - bRadarSensor* blenderradarsensor = (bRadarSensor*) sens->data; - const STR_String radarpropertyname = blenderradarsensor->name; - - int radaraxis = blenderradarsensor->axis; - - MT_Scalar coneheight = blenderradarsensor->range; - - // janco: the angle was doubled, so should I divide the factor in 2 - // or the blenderradarsensor->angle? - // nzc: the angle is the opening angle. We need to init with - // the axis-hull angle,so /2.0. - MT_Scalar factor = tan(blenderradarsensor->angle * 0.5f); - //MT_Scalar coneradius = coneheight * (factor / 2); - MT_Scalar coneradius = coneheight * factor; - - - // this sumoObject is not deleted by a gameobj, so delete it ourself - // later (memleaks)! - MT_Scalar smallmargin = 0.0; - MT_Scalar largemargin = 0.0; - - bool bFindMaterial = false; - PHY_IPhysicsController* ctrl = kxscene->GetPhysicsEnvironment()->CreateConeController((float)coneradius, (float)coneheight); - - gamesensor = new KX_RadarSensor( - eventmgr, - gameobj, - ctrl, - coneradius, - coneheight, - radaraxis, - smallmargin, - largemargin, - bFindMaterial, - radarpropertyname); - + bArmatureSensor* blenderarmsensor = (bArmatureSensor*) sens->data; + // we will reuse the property event manager, there is nothing special with this sensor + SCA_EventManager* eventmgr + = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) + { + STR_String bonename=blenderarmsensor->posechannel; + STR_String constraintname=blenderarmsensor->constraint; + gamesensor = new KX_ArmatureSensor(eventmgr,gameobj,bonename,constraintname, blenderarmsensor->type, blenderarmsensor->value); + } + break; } - - break; - } - case SENS_RAY: - { - bRaySensor* blenderraysensor = (bRaySensor*) sens->data; - - //blenderradarsensor->angle; - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + + case SENS_RADAR: { - bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL); - bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY); - - STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname); - - // don't want to get rays of length 0.0 or so - double distance = (blenderraysensor->range < 0.01f ? 0.01f : blenderraysensor->range); - int axis = blenderraysensor->axisflag; - - - gamesensor = new KX_RaySensor(eventmgr, - gameobj, - checkname, - bFindMaterial, - bXRay, - distance, - axis, - kxscene); + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); + if (eventmgr) + { + bRadarSensor* blenderradarsensor = (bRadarSensor*) sens->data; + const STR_String radarpropertyname = blenderradarsensor->name; + + int radaraxis = blenderradarsensor->axis; + + MT_Scalar coneheight = blenderradarsensor->range; + + // janco: the angle was doubled, so should I divide the factor in 2 + // or the blenderradarsensor->angle? + // nzc: the angle is the opening angle. We need to init with + // the axis-hull angle,so /2.0. + MT_Scalar factor = tan(blenderradarsensor->angle * 0.5f); + //MT_Scalar coneradius = coneheight * (factor / 2); + MT_Scalar coneradius = coneheight * factor; + + + // this sumoObject is not deleted by a gameobj, so delete it ourself + // later (memleaks)! + MT_Scalar smallmargin = 0.0; + MT_Scalar largemargin = 0.0; + + bool bFindMaterial = false; + PHY_IPhysicsController* ctrl = kxscene->GetPhysicsEnvironment()->CreateConeController((float)coneradius, (float)coneheight); + + gamesensor = new KX_RadarSensor( + eventmgr, + gameobj, + ctrl, + coneradius, + coneheight, + radaraxis, + smallmargin, + largemargin, + bFindMaterial, + radarpropertyname); + + } + + break; } - break; - } - - case SENS_RANDOM: - { - bRandomSensor* blenderrndsensor = (bRandomSensor*) sens->data; - // some files didn't write randomsensor, avoid crash now for NULL ptr's - if (blenderrndsensor) + case SENS_RAY: { + bRaySensor* blenderraysensor = (bRaySensor*) sens->data; + + //blenderradarsensor->angle; SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); if (eventmgr) { - int randomSeed = blenderrndsensor->seed; - if (randomSeed == 0) + bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL); + bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY); + + STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname); + + // don't want to get rays of length 0.0 or so + double distance = (blenderraysensor->range < 0.01f ? 0.01f : blenderraysensor->range); + int axis = blenderraysensor->axisflag; + + + gamesensor = new KX_RaySensor(eventmgr, + gameobj, + checkname, + bFindMaterial, + bXRay, + distance, + axis, + kxscene); + + } + break; + } + + case SENS_RANDOM: + { + bRandomSensor* blenderrndsensor = (bRandomSensor*) sens->data; + // some files didn't write randomsensor, avoid crash now for NULL ptr's + if (blenderrndsensor) + { + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) { - randomSeed = (int)(kxengine->GetRealTime()*100000.0); - randomSeed ^= (intptr_t)blenderrndsensor; + int randomSeed = blenderrndsensor->seed; + if (randomSeed == 0) + { + randomSeed = (int)(kxengine->GetRealTime()*100000.0); + randomSeed ^= (intptr_t)blenderrndsensor; + } + gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed); } - gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed); } + break; } - break; - } - case SENS_JOYSTICK: - { - int joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_NODEF; - - bJoystickSensor* bjoy = (bJoystickSensor*) sens->data; - - SCA_JoystickManager *eventmgr - = (SCA_JoystickManager*) logicmgr->FindEventManager(SCA_EventManager::JOY_EVENTMGR); - if (eventmgr) + case SENS_JOYSTICK: { - int axis =0; - int axisf =0; - int button =0; - int hat =0; - int hatf =0; - int prec =0; - - switch (bjoy->type) { - case SENS_JOY_AXIS: - axis = bjoy->axis; - axisf = bjoy->axisf; - prec = bjoy->precision; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS; - break; - case SENS_JOY_BUTTON: - button = bjoy->button; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_BUTTON; - break; - case SENS_JOY_HAT: - hat = bjoy->hat; - hatf = bjoy->hatf; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_HAT; - break; - case SENS_JOY_AXIS_SINGLE: - axis = bjoy->axis_single; - prec = bjoy->precision; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS_SINGLE; - break; - default: - printf("Error: bad case statement\n"); - break; + int joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_NODEF; + + bJoystickSensor* bjoy = (bJoystickSensor*) sens->data; + + SCA_JoystickManager *eventmgr + = (SCA_JoystickManager*) logicmgr->FindEventManager(SCA_EventManager::JOY_EVENTMGR); + if (eventmgr) + { + int axis =0; + int axisf =0; + int button =0; + int hat =0; + int hatf =0; + int prec =0; + + switch (bjoy->type) { + case SENS_JOY_AXIS: + axis = bjoy->axis; + axisf = bjoy->axisf; + prec = bjoy->precision; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS; + break; + case SENS_JOY_BUTTON: + button = bjoy->button; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_BUTTON; + break; + case SENS_JOY_HAT: + hat = bjoy->hat; + hatf = bjoy->hatf; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_HAT; + break; + case SENS_JOY_AXIS_SINGLE: + axis = bjoy->axis_single; + prec = bjoy->precision; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS_SINGLE; + break; + default: + printf("Error: bad case statement\n"); + break; + } + gamesensor = new SCA_JoystickSensor( + eventmgr, + gameobj, + bjoy->joyindex, + joysticktype, + axis,axisf, + prec, + button, + hat,hatf, + (bjoy->flag & SENS_JOY_ANY_EVENT)); } - gamesensor = new SCA_JoystickSensor( - eventmgr, - gameobj, - bjoy->joyindex, - joysticktype, - axis,axisf, - prec, - button, - hat,hatf, - (bjoy->flag & SENS_JOY_ANY_EVENT)); - } - else + else + { + printf("Error there was a problem finding the event manager\n"); + } + + break; + } + default: { - printf("Error there was a problem finding the event manager\n"); } - - break; } - default: - { - } - } - if (gamesensor && !(sens->flag & SENS_DEACTIVATE)) - { - gamesensor->SetExecutePriority(executePriority++); - STR_String uniquename = sens->name; - uniquename += "#SENS#"; - uniqueint++; - CIntValue* uniqueval = new CIntValue(uniqueint); - uniquename += uniqueval->GetText(); - uniqueval->Release(); - - /* Conversion succeeded, so we can set the generic props here. */ - gamesensor->SetPulseMode(pos_pulsemode, - neg_pulsemode, - frequency); - gamesensor->SetInvert(invert); - gamesensor->SetLevel(level); - gamesensor->SetTap(tap); - gamesensor->SetName(sens->name); - - gameobj->AddSensor(gamesensor); - - // only register to manager if it's in an active layer - // Make registration dynamic: only when sensor is activated - //if (isInActiveLayer) - // gamesensor->RegisterToManager(); - - gamesensor->ReserveController(sens->totlinks); - for (int i=0;i<sens->totlinks;i++) + if (gamesensor) { - bController* linkedcont = (bController*) sens->links[i]; - if (linkedcont) { - // If the controller is deactived doesn't register it - if (!(linkedcont->flag & CONT_DEACTIVATE)) { - SCA_IController* gamecont = converter->FindGameController(linkedcont); - - if (gamecont) { - logicmgr->RegisterToSensor(gamecont,gamesensor); - } - else { - printf("Warning, sensor \"%s\" could not find its controller " - "(link %d of %d) from object \"%s\"\n" - "\tthere has been an error converting the blender controller for the game engine," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + gamesensor->SetExecutePriority(executePriority++); + STR_String uniquename = sens->name; + uniquename += "#SENS#"; + uniqueint++; + CIntValue* uniqueval = new CIntValue(uniqueint); + uniquename += uniqueval->GetText(); + uniqueval->Release(); + + /* Conversion succeeded, so we can set the generic props here. */ + gamesensor->SetPulseMode(pos_pulsemode, + neg_pulsemode, + skipped_ticks); + gamesensor->SetInvert(invert); + gamesensor->SetLevel(level); + gamesensor->SetTap(tap); + gamesensor->SetName(sens->name); + + gameobj->AddSensor(gamesensor); + + // only register to manager if it's in an active layer + // Make registration dynamic: only when sensor is activated + //if (isInActiveLayer) + // gamesensor->RegisterToManager(); + + gamesensor->ReserveController(sens->totlinks); + for (int i=0;i<sens->totlinks;i++) + { + bController* linkedcont = (bController*) sens->links[i]; + if (linkedcont) { + // If the controller is deactived doesn't register it + if (!(linkedcont->flag & CONT_DEACTIVATE)) { + SCA_IController* gamecont = converter->FindGameController(linkedcont); + + if (gamecont) { + logicmgr->RegisterToSensor(gamecont,gamesensor); + } + else { + printf("Warning, sensor \"%s\" could not find its controller " + "(link %d of %d) from object \"%s\"\n" + "\tthere has been an error converting the blender controller for the game engine," + "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + } } } + else { + printf("Warning, sensor \"%s\" has lost a link to a controller " + "(link %d of %d) from object \"%s\"\n" + "\tpossible causes are partially appended objects or an error reading the file," + "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + } } - else { - printf("Warning, sensor \"%s\" has lost a link to a controller " - "(link %d of %d) from object \"%s\"\n" - "\tpossible causes are partially appended objects or an error reading the file," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + // special case: Keyboard sensor with no link + // this combination is usually used for key logging. + if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { + // Force the registration so that the sensor runs + gamesensor->IncLink(); } + + // done with gamesensor + gamesensor->Release(); + } - // special case: Keyboard sensor with no link - // this combination is usually used for key logging. - if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { - // Force the registration so that the sensor runs - gamesensor->IncLink(); - } - - // done with gamesensor - gamesensor->Release(); - } - else if (gamesensor) - gamesensor->Release(); sens=sens->next; } diff --git a/source/gameengine/Expressions/CMakeLists.txt b/source/gameengine/Expressions/CMakeLists.txt index 6907f314503..48c10d75a17 100644 --- a/source/gameengine/Expressions/CMakeLists.txt +++ b/source/gameengine/Expressions/CMakeLists.txt @@ -55,6 +55,7 @@ set(SRC StringValue.cpp Value.cpp VectorValue.cpp + KX_PythonCallBack.cpp BoolValue.h ConstExpr.h @@ -77,6 +78,7 @@ set(SRC Value.h VectorValue.h VoidValue.h + KX_PythonCallBack.h ) blender_add_lib(ge_logic_expressions "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/Expressions/KX_PythonCallBack.cpp b/source/gameengine/Expressions/KX_PythonCallBack.cpp new file mode 100644 index 00000000000..fbc250a1b3d --- /dev/null +++ b/source/gameengine/Expressions/KX_PythonCallBack.cpp @@ -0,0 +1,119 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Porteries Tristan. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file gameengine/Expressions/KX_PythonCallBack.cpp + * \ingroup expressions + */ + +#include "KX_PythonCallBack.h" +#include <iostream> +#include <stdarg.h> + +#include "BLI_alloca.h" + +/** Check if a python value is a function and have the correct number of arguments. + * \param value The python value to check. + * \param minargcount The minimum of arguments possible. + * \param maxargcount The maximum of arguments possible. + * \param r_argcount The number of argument of this function, this variable will be + * changed in the function. + */ +static PyObject *CheckPythonFunction(PyObject *value, unsigned int minargcount, unsigned int maxargcount, unsigned int &r_argcount) +{ + if (PyMethod_Check(value)) { + PyCodeObject *code = ((PyCodeObject *)PyFunction_GET_CODE(PyMethod_GET_FUNCTION(value))); + // *args support + r_argcount = (code->co_flags & CO_VARARGS) ? maxargcount : (code->co_argcount - 1); + } + else if (PyFunction_Check(value)) { + PyCodeObject *code = ((PyCodeObject *)PyFunction_GET_CODE(value)); + // *args support + r_argcount = (code->co_flags & CO_VARARGS) ? maxargcount : code->co_argcount; + } + else { // is not a methode or a function + PyErr_Format(PyExc_TypeError, "items must be functions or methodes, not %s", + Py_TYPE(value)->tp_name); + return NULL; + } + + if (r_argcount < minargcount || r_argcount > maxargcount) { + // wrong number of arguments + PyErr_Format(PyExc_TypeError, "methode or function (%s) has invalid number of arguments (%i) must be between %i and %i", + Py_TYPE(value)->tp_name, r_argcount, minargcount, maxargcount); + return NULL; + } + + return value; +} + +/** Create a python tuple to call a python function + * \param argcount The lenght of the tuple. + * \param arglist The fully list of python arguments [size >= argcount]. + */ +static PyObject *CreatePythonTuple(unsigned int argcount, PyObject **arglist) +{ + PyObject *tuple = PyTuple_New(argcount); + + for (unsigned int i = 0; i < argcount; ++i) { + PyObject *item = arglist[i]; + // increment reference and copy it in a new tuple + Py_INCREF(item); + PyTuple_SET_ITEM(tuple, i, item); + } + + return tuple; +} + +void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount) +{ + unsigned int size = PyList_Size(functionlist); + PyObject **argTuples = (PyObject **)BLI_array_alloca(argTuples, maxargcount - minargcount + 1); + memset(argTuples, 0, sizeof(PyObject *) * (maxargcount - minargcount + 1)); + + for (unsigned int i = 0; i < size; ++i) { + unsigned int funcargcount = 0; + + PyObject *item = PyList_GET_ITEM(functionlist, i); + PyObject *func = CheckPythonFunction(item, minargcount, maxargcount, funcargcount); + if (!func) { // this item fails the check + PyErr_Print(); + PyErr_Clear(); + continue; + } + + // get correct argument tuple. + PyObject *tuple = argTuples[funcargcount - minargcount]; + if (!tuple) + argTuples[funcargcount - minargcount] = tuple = CreatePythonTuple(funcargcount, arglist); + + PyObject *ret = PyObject_Call(func, tuple, NULL); + if (!ret) { // if ret is NULL this seems that the function doesn't work ! + PyErr_Print(); + PyErr_Clear(); + } + else + Py_DECREF(ret); + } + + for (unsigned int i = 0; i <= (maxargcount - minargcount); ++i) + Py_XDECREF(argTuples[i]); +} diff --git a/source/gameengine/Expressions/KX_PythonCallBack.h b/source/gameengine/Expressions/KX_PythonCallBack.h new file mode 100644 index 00000000000..2ff6e305d67 --- /dev/null +++ b/source/gameengine/Expressions/KX_PythonCallBack.h @@ -0,0 +1,40 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Porteries Tristan. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file KX_PythonCallBack.h + * \ingroup expressions + */ + +#ifndef __KX_PYTHON_CALLBACK_H__ +#define __KX_PYTHON_CALLBACK_H__ + +#include "KX_Python.h" + +/** Execute each functions with at least one argument + * \param functionlist The python list which contains callbacks. + * \param arglist The first item in the tuple to execute callbacks (can be NULL for no arguments). + * \param minargcount The minimum of quantity of arguments possible. + * \param maxargcount The maximum of quantity of arguments possible. + */ +void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount); + +#endif // __KX_PYTHON_CALLBACK_H__ diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index a65d61bc98b..31a17bd0cbf 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -148,12 +148,18 @@ PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the ent PyObject *PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyTypeObject *base_type; - PyObjectPlus_Proxy *base = NULL; - if (!PyArg_ParseTuple(args, "O:Base PyObjectPlus", &base)) + /* one or more args is needed */ + if (!PyTuple_GET_SIZE(args)) { + PyErr_SetString(PyExc_TypeError, + "Expected at least one argument"); return NULL; + } + + PyObjectPlus_Proxy *base = (PyObjectPlus_Proxy *)PyTuple_GET_ITEM(args, 0); - /* the 'base' PyObject may be subclassed (multiple times even) + /** + * the 'base' PyObject may be subclassed (multiple times even) * we need to find the first C++ defined class to check 'type' * is a subclass of the base arguments type. * @@ -162,12 +168,13 @@ PyObject *PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject * eg. * * # CustomOb is called 'type' in this C code + * \code{.py} * class CustomOb(GameTypes.KX_GameObject): * pass * * # this calls py_base_new(...), the type of 'CustomOb' is checked to be a subclass of the 'cont.owner' type * ob = CustomOb(cont.owner) - * + * \endcode * */ base_type= Py_TYPE(base); while (base_type && !BGE_PROXY_CHECK_TYPE(base_type)) diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 34b814d7416..c3ce98ed27a 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -111,6 +111,8 @@ typedef struct PyObjectPlus_Proxy { /* Opposite of BGE_PROXY_REF */ #define BGE_PROXY_FROM_REF(_self) (((PyObjectPlus *)_self)->GetProxy()) +/* Same as 'BGE_PROXY_REF' but doesn't incref. */ +#define BGE_PROXY_FROM_REF_BORROW(_self) _bge_proxy_from_ref_borrow((void *)_self) // This must be the first line of each @@ -631,6 +633,17 @@ public: #ifdef WITH_PYTHON PyObject *PyUnicode_From_STR_String(const STR_String& str); + +inline PyObject *_bge_proxy_from_ref_borrow(void *self_v) +{ + PyObject *self_proxy = BGE_PROXY_FROM_REF(self_v); + /* this is typically _very_ bad practice, + * however we know the proxy is owned by 'self_v' */ + self_proxy->ob_refcnt--; + return self_proxy; +} + #endif + #endif /* __PYOBJECTPLUS_H__ */ diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index 3ffe128c3b3..21e2c1cbcfc 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -221,6 +221,7 @@ public: OBJ_ARMATURE=0, OBJ_CAMERA=1, OBJ_LIGHT=2, + OBJ_TEXT=3 } ObjectTypes; }; diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 1cb17af8325..66dd69f93c4 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -67,7 +67,7 @@ SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj, m_neg_ticks = 0; m_pos_pulsemode = false; m_neg_pulsemode = false; - m_pulse_frequency = 0; + m_skipped_ticks = 0; m_state = false; m_prev_state = false; @@ -102,11 +102,11 @@ bool SCA_ISensor::IsPositiveTrigger() void SCA_ISensor::SetPulseMode(bool posmode, bool negmode, - int freq) + int skippedticks) { m_pos_pulsemode = posmode; m_neg_pulsemode = negmode; - m_pulse_frequency = freq; + m_skipped_ticks = skippedticks; } void SCA_ISensor::SetInvert(bool inv) @@ -263,7 +263,7 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr) * not set :( */ if (m_pos_pulsemode) { m_pos_ticks++; - if (m_pos_ticks > m_pulse_frequency) { + if (m_pos_ticks > m_skipped_ticks) { if ( m_state ) { ActivateControllers(logicmgr); @@ -276,7 +276,7 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr) if (m_neg_pulsemode && !m_tap) { m_neg_ticks++; - if (m_neg_ticks > m_pulse_frequency) { + if (m_neg_ticks > m_skipped_ticks) { if (!m_state ) { ActivateControllers(logicmgr); @@ -367,7 +367,7 @@ PyMethodDef SCA_ISensor::Methods[] = { PyAttributeDef SCA_ISensor::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("usePosPulseMode",SCA_ISensor,m_pos_pulsemode), KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode), - KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency), + KX_PYATTRIBUTE_INT_RW("skippedTicks",0,100000,true,SCA_ISensor,m_skipped_ticks), KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert), KX_PYATTRIBUTE_BOOL_RW_CHECK("level",SCA_ISensor,m_level,pyattr_check_level), KX_PYATTRIBUTE_BOOL_RW_CHECK("tap",SCA_ISensor,m_tap,pyattr_check_tap), @@ -376,6 +376,7 @@ PyAttributeDef SCA_ISensor::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("status", SCA_ISensor, pyattr_get_status), KX_PYATTRIBUTE_RO_FUNCTION("pos_ticks", SCA_ISensor, pyattr_get_posTicks), KX_PYATTRIBUTE_RO_FUNCTION("neg_ticks", SCA_ISensor, pyattr_get_negTicks), + KX_PYATTRIBUTE_RW_FUNCTION("frequency", SCA_ISensor, pyattr_get_frequency, pyattr_set_frequency), { NULL } //Sentinel }; @@ -444,6 +445,27 @@ int SCA_ISensor::pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrde self->m_level = false; return 0; } + +PyObject *SCA_ISensor::pyattr_get_frequency(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_ISensor *self = static_cast<SCA_ISensor*>(self_v); + ShowDeprecationWarning("SCA_ISensor.frequency", "SCA_ISensor.skippedTicks"); + return PyLong_FromLong(self->m_skipped_ticks); +} + +int SCA_ISensor::pyattr_set_frequency(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + SCA_ISensor *self = static_cast<SCA_ISensor*>(self_v); + ShowDeprecationWarning("SCA_ISensor.frequency", "SCA_ISensor.skippedTicks"); + if (PyLong_Check(value)) { + self->m_skipped_ticks = PyLong_AsLong(value); + return PY_SET_ATTR_SUCCESS; + } + else { + PyErr_SetString(PyExc_TypeError, "sensor.frequency = int: Sensor, expected an integer"); + return PY_SET_ATTR_FAIL; + } +} #endif // WITH_PYTHON /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 7bbba7aaafe..1e82f3ab11f 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -57,8 +57,8 @@ protected: /** Pulse negative pulses? */ bool m_neg_pulsemode; - /** Repeat frequency in pulse mode. */ - int m_pulse_frequency; + /** Number of skipped ticks between two active pulses. */ + int m_skipped_ticks; /** Number of ticks since the last positive pulse. */ int m_pos_ticks; @@ -125,7 +125,7 @@ public: */ void SetPulseMode(bool posmode, bool negmode, - int freq); + int skippedticks); /** Set inversion of pulses on or off. */ void SetInvert(bool inv); @@ -201,6 +201,8 @@ public: static PyObject* pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_negTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_frequency(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_frequency(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 6f34f8710c1..6841d2a8ea1 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -265,13 +265,8 @@ bool SCA_PropertySensor::CheckPropertyCondition() //the concept of Edge and Level triggering has unwanted effect for KX_PROPSENSOR_CHANGED //see Game Engine bugtracker [ #3809 ] - if (m_checktype != KX_PROPSENSOR_CHANGED) - { - m_recentresult=result; - } else - { - m_recentresult=result;//true; - } + m_recentresult = result; + return result; } diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 4e93556453a..2fe4d18a7fc 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -107,7 +107,7 @@ bool SCA_RandomSensor::Evaluate() bool evaluateResult = false; - if (++m_interval > m_pulse_frequency) { + if (++m_interval > m_skipped_ticks) { bool drawResult = false; m_interval = 0; if (m_iteration > 31) { diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h index acbea477e38..34cc9759a08 100644 --- a/source/gameengine/GamePlayer/common/GPC_Canvas.h +++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h @@ -71,6 +71,8 @@ public: virtual void ResizeWindow(int width, int height) {} + virtual void GetDisplayDimensions(int &width, int &height) {} + /** * \section Methods inherited from abstract base class RAS_ICanvas. */ diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt index a1bc7e88840..dfa115e085c 100644 --- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt +++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt @@ -46,6 +46,7 @@ set(INC ../../../blender/imbuf ../../../blender/makesdna ../../../blender/makesrna + ../../../blender/pointcache ../../../../intern/container ../../../../intern/ghost ../../../../intern/glew-mx diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 6b69a991968..b8ce67743de 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -636,7 +636,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) if (!m_networkdevice) goto initFailed; - sound_init(m_maggie); + BKE_sound_init(m_maggie); // create a ketsjisystem (only needed for timing and stuff) m_kxsystem = new GPG_System (m_system); @@ -672,7 +672,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) return m_engineInitialized; initFailed: - sound_exit(); + BKE_sound_exit(); delete m_kxsystem; delete m_networkdevice; delete m_mouse; @@ -847,7 +847,7 @@ void GPG_Application::exitEngine() if (!m_engineInitialized) return; - sound_exit(); + BKE_sound_exit(); if (m_ketsjiengine) { stopEngine(); diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp b/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp index 556f85804ea..09eb1691dae 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp @@ -121,6 +121,18 @@ bool GPG_Canvas::GetSwapInterval(int& intervalOut) return false; } +void GPG_Canvas::GetDisplayDimensions(int &width, int &height) + { + unsigned int uiwidth; + unsigned int uiheight; + + GHOST_ISystem *system = GHOST_ISystem::getSystem(); + system->getMainDisplayDimensions(uiwidth, uiheight); + + width = uiwidth; + height = uiheight; +} + void GPG_Canvas::ResizeWindow(int width, int height) { if (m_window->getState() == GHOST_kWindowStateFullScreen) diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h index 337c2cedf55..18afbf6cd9e 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h @@ -63,6 +63,8 @@ public: virtual float GetMouseNormalizedX(int x); virtual float GetMouseNormalizedY(int y); + virtual void GetDisplayDimensions(int &width, int &height); + virtual void ResizeWindow(int width, int height); virtual void SetFullScreen(bool enable); virtual bool GetFullScreen(); diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 915fe614957..6d97447dff0 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -74,11 +74,14 @@ extern "C" #include "BKE_report.h" #include "BKE_library.h" #include "BKE_modifier.h" +#include "BKE_material.h" #include "BKE_text.h" #include "BKE_sound.h" #include "IMB_imbuf.h" #include "IMB_moviecache.h" + +#include "PTC_api.h" #ifdef __APPLE__ int GHOST_HACK_getFirstFile(char buf[]); @@ -451,6 +454,7 @@ int main(int argc, char** argv) RNA_init(); init_nodesystem(); + PTC_alembic_init(); initglobals(); @@ -517,9 +521,12 @@ int main(int argc, char** argv) // enable fast mipmap generation U.use_gpu_mipmap = 1; - sound_init_once(); + BKE_sound_init_once(); + + // Initialize a default material for meshes without materials. + init_def_material(); - set_free_windowmanager_cb(wm_free); + BKE_library_callback_free_window_manager_set(wm_free); /* if running blenderplayer the last argument can't be parsed since it has to be the filename. else it is bundled */ isBlenderPlayer = !BLO_is_a_runtime(argv[0]); diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 610abcd0357..27adc000413 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -57,6 +57,7 @@ incs = [ '#source/blender/include', '#source/blender/makesdna', '#source/blender/makesrna', + '#source/blender/pointcache', '#source/gameengine/Rasterizer', '#source/gameengine/GameLogic', '#source/gameengine/Expressions', diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp index a50c07a486a..9bae119107e 100644 --- a/source/gameengine/Ketsji/BL_Action.cpp +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -49,6 +49,7 @@ extern "C" { // Needed for material IPOs #include "BKE_material.h" #include "DNA_material_types.h" +#include "DNA_scene_types.h" } #include "MEM_guardedalloc.h" @@ -162,6 +163,14 @@ bool BL_Action::Play(const char* name, m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); + // World + sg_contr = BL_CreateWorldIPO(m_action, kxscene->GetBlenderScene()->world, kxscene->GetSceneConverter()); + if (sg_contr) { + m_sg_contr_list.push_back(sg_contr); + m_obj->GetSGNode()->AddSGController(sg_contr); + sg_contr->SetObject(m_obj->GetSGNode()); + } + // Try obcolor sg_contr = BL_CreateObColorIPO(m_action, m_obj, kxscene->GetSceneConverter()); if (sg_contr) { diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index 58739e7ef81..e1a28961a68 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -203,9 +203,21 @@ void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap) glBindTexture(GL_TEXTURE_2D, mTexture ); if ( mipmap ) { + int i; + ImBuf *ibuf; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix ); + + ibuf = IMB_allocFromBuffer(pix, NULL, x, y); + + IMB_makemipmap(ibuf, true); + + for (i = 0; i < ibuf->miptot; i++) { + ImBuf *mip = IMB_getmipmap(ibuf, i); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } + IMB_freeImBuf(ibuf); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -245,9 +257,17 @@ void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap) glBindTexture(GL_TEXTURE_2D, mTexture ); if ( mipmap ) { + int i; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect ); + + IMB_makemipmap(ibuf, true); + + for (i = 0; i < ibuf->miptot; i++) { + ImBuf *mip = IMB_getmipmap(ibuf, i); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 9f0b582045f..7ec2673bf1f 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -94,6 +94,21 @@ void KX_BlenderMaterial::Initialize( ((data->ras_mode &TEX)), game ); + Material *ma = data->material; + + // Save material data to restore on exit + mSavedData.r = ma->r; + mSavedData.g = ma->g; + mSavedData.b = ma->b; + mSavedData.a = ma->alpha; + mSavedData.specr = ma->specr; + mSavedData.specg = ma->specg; + mSavedData.specb = ma->specb; + mSavedData.spec = ma->spec; + mSavedData.ref = ma->ref; + mSavedData.hardness = ma->har; + mSavedData.emit = ma->emit; + mMaterial = data; mShader = 0; mBlenderShader = 0; @@ -124,6 +139,20 @@ void KX_BlenderMaterial::Initialize( KX_BlenderMaterial::~KX_BlenderMaterial() { + Material *ma = mMaterial->material; + // Restore Blender material data + ma->r = mSavedData.r; + ma->g = mSavedData.g; + ma->b = mSavedData.b; + ma->alpha = mSavedData.a; + ma->specr = mSavedData.specr; + ma->specg = mSavedData.specg; + ma->specb = mSavedData.specb; + ma->spec = mSavedData.spec; + ma->ref = mSavedData.ref; + ma->har = mSavedData.hardness; + ma->emit = mSavedData.emit; + // cleanup work if (mConstructed) // clean only if material was actually used @@ -793,17 +822,19 @@ void KX_BlenderMaterial::UpdateIPO( ) { // only works one deep now - mMaterial->speccolor[0] = (float)(specrgb)[0]; - mMaterial->speccolor[1] = (float)(specrgb)[1]; - mMaterial->speccolor[2] = (float)(specrgb)[2]; - mMaterial->matcolor[0] = (float)(rgba[0]); - mMaterial->matcolor[1] = (float)(rgba[1]); - mMaterial->matcolor[2] = (float)(rgba[2]); - mMaterial->alpha = (float)(alpha); - mMaterial->hard = (float)(hard); - mMaterial->emit = (float)(emit); - mMaterial->spec_f = (float)(spec); - mMaterial->ref = (float)(ref); + + // GLSL Multitexture Input + mMaterial->material->specr = mMaterial->speccolor[0] = (float)(specrgb)[0]; + mMaterial->material->specg = mMaterial->speccolor[1] = (float)(specrgb)[1]; + mMaterial->material->specb = mMaterial->speccolor[2] = (float)(specrgb)[2]; + mMaterial->material->r = mMaterial->matcolor[0] = (float)(rgba[0]); + mMaterial->material->g = mMaterial->matcolor[1] = (float)(rgba[1]); + mMaterial->material->b = mMaterial->matcolor[2] = (float)(rgba[2]); + mMaterial->material->alpha = mMaterial->alpha = (float)(rgba[3]); + mMaterial->material->har = mMaterial->hard = (float)(hard); + mMaterial->material->emit = mMaterial->emit = (float)(emit); + mMaterial->material->spec = mMaterial->spec_f = (float)(spec); + mMaterial->material->ref = mMaterial->ref = (float)(ref); } void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index b7c64215eaf..23921588d6a 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -134,6 +134,15 @@ private: bool mConstructed; // if false, don't clean on exit int mLightLayer; + struct { + float r, g, b, a; + float specr, specg, specb; + float spec; + float ref; + float hardness; + float emit; + } mSavedData; + void InitTextures(); void SetBlenderGLSLShader(); diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index ce2fe5f5ad8..4456345e1d9 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -463,6 +463,7 @@ bool KX_Camera::GetFrustumCulling() const void KX_Camera::EnableViewport(bool viewport) { + InvalidateProjectionMatrix(false); // We need to reset projection matrix m_camdata.m_viewport = viewport; } @@ -885,7 +886,7 @@ int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_D PyObject *KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyObjectFrom(self->GetModelviewMatrix()); + return PyObjectFrom(self->GetWorldToCamera()); } PyObject *KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -994,7 +995,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, GLdouble modelmatrix[16]; GLdouble projmatrix[16]; - MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); m_modelmatrix.getValue(modelmatrix); @@ -1037,7 +1038,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect, GLdouble modelmatrix[16]; GLdouble projmatrix[16]; - MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); m_modelmatrix.getValue(modelmatrix); diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 454c4a54ec1..eeb836c44b8 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -192,7 +192,7 @@ public: void InvalidateProjectionMatrix(bool valid = false); /** Gets the modelview matrix that is used by the rasterizer. - * \warning If the Camera is a dynamic object then this method may return garbage. Use GetCameraToWorld() instead. + * \warning If the Camera is a dynamic object then this method may return garbage. Use GetWorldToCamera() instead. */ const MT_Matrix4x4& GetModelviewMatrix() const; diff --git a/source/gameengine/Ketsji/KX_FontObject.cpp b/source/gameengine/Ketsji/KX_FontObject.cpp index 9789a8294ee..f3b098f407a 100644 --- a/source/gameengine/Ketsji/KX_FontObject.cpp +++ b/source/gameengine/Ketsji/KX_FontObject.cpp @@ -118,7 +118,6 @@ CValue* KX_FontObject::GetReplica() void KX_FontObject::ProcessReplica() { KX_GameObject::ProcessReplica(); - KX_GetActiveScene()->AddFont(this); } int GetFontId(VFont *vfont) diff --git a/source/gameengine/Ketsji/KX_FontObject.h b/source/gameengine/Ketsji/KX_FontObject.h index 209ab6ca69f..bf70eedfde6 100644 --- a/source/gameengine/Ketsji/KX_FontObject.h +++ b/source/gameengine/Ketsji/KX_FontObject.h @@ -54,6 +54,7 @@ public: */ virtual CValue* GetReplica(); virtual void ProcessReplica(); + virtual int GetGameObjectType() { return OBJ_TEXT; } protected: std::vector<STR_String> m_text; diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index c6087ac676d..a23af680104 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -178,6 +178,11 @@ bool KX_GameActuator::Update() // obtain file size: fseek (fp , 0 , SEEK_END); marshal_length = ftell(fp); + if (marshal_length == -1) { + printf("warning: could not read position of '%s'\n", mashal_path); + fclose(fp); + break; + } rewind(fp); marshal_buffer = (char*) malloc (sizeof(char)*marshal_length); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 8d22c9132fd..e77960b99b1 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -47,6 +47,7 @@ #include "KX_MeshProxy.h" #include "KX_PolyProxy.h" #include <stdio.h> // printf +#include <climits> // USHRT_MAX #include "SG_Controller.h" #include "PHY_IGraphicController.h" #include "SG_Node.h" @@ -68,6 +69,7 @@ #include "BL_ActionManager.h" #include "BL_Action.h" +#include "KX_PythonCallBack.h" #include "PyObjectPlus.h" /* python stuff */ #include "BLI_utildefines.h" #include "python_utildefines.h" @@ -91,9 +93,10 @@ KX_GameObject::KX_GameObject( : SCA_IObject(), m_bDyna(false), m_layer(0), + m_currentLodLevel(0), + m_previousLodLevel(0), m_pBlenderObject(NULL), m_pBlenderGroupObject(NULL), - m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), m_objectColor(1.0, 1.0, 1.0, 1.0), @@ -291,6 +294,21 @@ void KX_GameObject::SetDupliGroupObject(KX_GameObject* obj) m_pDupliGroupObject = obj; } +void KX_GameObject::AddConstraint(bRigidBodyJointConstraint *cons) +{ + m_constraints.push_back(cons); +} + +std::vector<bRigidBodyJointConstraint*> KX_GameObject::GetConstraints() +{ + return m_constraints; +} + +void KX_GameObject::ClearConstraints() +{ + m_constraints.clear(); +} + KX_GameObject* KX_GameObject::GetParent() { KX_GameObject* result = NULL; @@ -545,13 +563,26 @@ void KX_GameObject::ActivateGraphicController(bool recurse) } } -void KX_GameObject::SetUserCollisionGroup(short group) +void KX_GameObject::SetUserCollisionGroup(unsigned short group) { m_userCollisionGroup = group; + if (m_pPhysicsController) + m_pPhysicsController->RefreshCollisions(); } -void KX_GameObject::SetUserCollisionMask(short mask) +void KX_GameObject::SetUserCollisionMask(unsigned short mask) { m_userCollisionMask = mask; + if (m_pPhysicsController) + m_pPhysicsController->RefreshCollisions(); +} + +unsigned short KX_GameObject::GetUserCollisionGroup() +{ + return m_userCollisionGroup; +} +unsigned short KX_GameObject::GetUserCollisionMask() +{ + return m_userCollisionMask; } bool KX_GameObject::CheckCollision(KX_GameObject* other) @@ -569,6 +600,13 @@ CValue* KX_GameObject::GetReplica() return replica; } +bool KX_GameObject::IsDynamicsSuspended() const +{ + if (m_pPhysicsController) + return m_pPhysicsController->IsSuspended(); + return false; +} + float KX_GameObject::getLinearDamping() const { if (m_pPhysicsController) @@ -768,35 +806,74 @@ void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh) m_lodmeshes.push_back(mesh); } + +static float calcHysteresis(KX_Scene *kxscene, LodLevel *lod) +{ + float hystvariance = 0.0f; + + if (!kxscene->IsActivedLodHysteresis()) + return hystvariance; + + short hysteresis = 0; + // if exists, LoD level hysteresis will override scene hysteresis + if (lod->next->flags & OB_LOD_USE_HYST) + hysteresis = lod->next->obhysteresis; + else + hysteresis = kxscene->GetLodHysteresisValue(); + + return hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100; +} + void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos) { // Handle dupligroups - if (this->m_pInstanceObjects) { - KX_GameObject * instob; - int count = this->m_pInstanceObjects->GetCount(); + if (m_pInstanceObjects) { + KX_GameObject *instob; + int count = m_pInstanceObjects->GetCount(); for (int i = 0; i < count; i++) { - instob = (KX_GameObject*)this->m_pInstanceObjects->GetValue(i); + instob = (KX_GameObject*)m_pInstanceObjects->GetValue(i); instob->UpdateLod(cam_pos); } } - if (this->m_lodmeshes.empty()) return; + if (m_lodmeshes.empty()) + return; - MT_Vector3 delta = this->NodeGetWorldPosition() - cam_pos; + MT_Vector3 delta = NodeGetWorldPosition() - cam_pos; float distance2 = delta.length2(); int level = 0; - Object *bob = this->GetBlenderObject(); - LodLevel *lod = (LodLevel*) bob->lodlevels.first; + float hystvariance = 0.0f; + Object *bob = GetBlenderObject(); + LodLevel *lod = (LodLevel *)bob->lodlevels.first; + KX_Scene *kxscene = GetScene(); + for (; lod; lod = lod->next, level++) { - if (!lod->source || lod->source->type != OB_MESH) level--; - if (!lod->next || lod->next->distance * lod->next->distance > distance2) break; - } + if (!lod->source || lod->source->type != OB_MESH) + level--; - RAS_MeshObject *mesh = this->m_lodmeshes[level]; + if (!lod->next) + break; - if (mesh != this->m_meshes[0]) { - this->GetScene()->ReplaceMesh(this, mesh, true, false); + if (level == m_previousLodLevel || level == (m_previousLodLevel + 1)) { + hystvariance = calcHysteresis(kxscene, lod); + float newdistance = lod->next->distance + hystvariance; + if (newdistance * newdistance > distance2) + break; + } + else if (level == (m_previousLodLevel - 1)) { + hystvariance = calcHysteresis(kxscene, lod); + float newdistance = lod->next->distance - hystvariance; + if (newdistance * newdistance > distance2) + break; + } + } + + RAS_MeshObject *mesh = m_lodmeshes[level]; + m_currentLodLevel = level; + if (mesh != m_meshes[0]) { + m_previousLodLevel = level; + GetScene()->ReplaceMesh(this, mesh, true, false); } } @@ -1494,70 +1571,17 @@ void KX_GameObject::RegisterCollisionCallbacks() } void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal) { - #ifdef WITH_PYTHON - Py_ssize_t len; - PyObject* collision_callbacks = m_collisionCallbacks; - - if (collision_callbacks && (len=PyList_GET_SIZE(collision_callbacks))) - { - // Argument tuples are created lazily, only when they are needed. - PyObject *args_3 = NULL; - PyObject *args_1 = NULL; // Only for compatibility with pre-2.74 callbacks that take 1 argument. - - PyObject *func; - PyObject *ret; - int co_argcount; - - // Iterate the list and run the callbacks - for (Py_ssize_t pos=0; pos < len; pos++) - { - func = PyList_GET_ITEM(collision_callbacks, pos); - - // Get the number of arguments, supporting functions, methods and generic callables. - if (PyMethod_Check(func)) { - // Take away the 'self' argument for methods. - co_argcount = ((PyCodeObject *)PyFunction_GET_CODE(PyMethod_GET_FUNCTION(func)))->co_argcount - 1; - } else if (PyFunction_Check(func)) { - co_argcount = ((PyCodeObject *)PyFunction_GET_CODE(func))->co_argcount; - } else { - // We'll just assume the callable takes the correct number of arguments. - co_argcount = 3; - } +#ifdef WITH_PYTHON + if (!m_collisionCallbacks || PyList_GET_SIZE(m_collisionCallbacks) == 0) + return; - // Check whether the function expects the colliding object only, - // or also the point and normal. - if (co_argcount <= 1) { - // One argument, or *args (which gives co_argcount == 0) - if (args_1 == NULL) { - args_1 = PyTuple_New(1); - PyTuple_SET_ITEMS(args_1, collider->GetProxy()); - } - ret = PyObject_Call(func, args_1, NULL); - } else { - // More than one argument, assume we can give point & normal. - if (args_3 == NULL) { - args_3 = PyTuple_New(3); - PyTuple_SET_ITEMS(args_3, - collider->GetProxy(), - PyObjectFrom(point), - PyObjectFrom(normal)); - } - ret = PyObject_Call(func, args_3, NULL); - } + PyObject *args[] = {collider->GetProxy(), PyObjectFrom(point), PyObjectFrom(normal)}; + RunPythonCallBackList(m_collisionCallbacks, args, 1, ARRAY_SIZE(args)); - if (ret == NULL) { - PyErr_Print(); - PyErr_Clear(); - } - else { - Py_DECREF(ret); - } - } - - if (args_3) Py_DECREF(args_3); - if (args_1) Py_DECREF(args_1); + for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) { + Py_DECREF(args[i]); } - #endif +#endif } /* Suspend/ resume: for the dynamic behavior, there is a simple @@ -1889,7 +1913,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O}, - {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS}, + {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS}, {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS}, {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS}, {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS}, @@ -1927,6 +1951,7 @@ PyMethodDef KX_GameObject::Methods[] = { }; PyAttributeDef KX_GameObject::Attributes[] = { + KX_PYATTRIBUTE_INT_RO("currentLodLevel", KX_GameObject, m_currentLodLevel), KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name), KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), KX_PYATTRIBUTE_RO_FUNCTION("groupMembers", KX_GameObject, pyattr_get_group_members), @@ -1934,6 +1959,7 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("scene", KX_GameObject, pyattr_get_scene), KX_PYATTRIBUTE_RO_FUNCTION("life", KX_GameObject, pyattr_get_life), KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), + KX_PYATTRIBUTE_RO_FUNCTION("isSuspendDynamics", KX_GameObject, pyattr_get_is_suspend_dynamics), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max), KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), @@ -1945,6 +1971,8 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("scaling", KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling), KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset), KX_PYATTRIBUTE_RW_FUNCTION("collisionCallbacks", KX_GameObject, pyattr_get_collisionCallbacks, pyattr_set_collisionCallbacks), + KX_PYATTRIBUTE_RW_FUNCTION("collisionGroup", KX_GameObject, pyattr_get_collisionGroup, pyattr_set_collisionGroup), + KX_PYATTRIBUTE_RW_FUNCTION("collisionMask", KX_GameObject, pyattr_get_collisionMask, pyattr_set_collisionMask), KX_PYATTRIBUTE_RW_FUNCTION("state", KX_GameObject, pyattr_get_state, pyattr_set_state), KX_PYATTRIBUTE_RO_FUNCTION("meshes", KX_GameObject, pyattr_get_meshes), KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation), @@ -2291,6 +2319,56 @@ int KX_GameObject::pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIB return PY_SET_ATTR_SUCCESS; } +PyObject *KX_GameObject::pyattr_get_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + return PyLong_FromLong(self->GetUserCollisionGroup()); +} + +int KX_GameObject::pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + int val = PyLong_AsLong(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "gameOb.collisionGroup = int: KX_GameObject, expected an int bit field"); + return PY_SET_ATTR_FAIL; + } + + if (val < 0 || val > USHRT_MAX) { + PyErr_Format(PyExc_AttributeError, "gameOb.collisionGroup = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX); + return PY_SET_ATTR_FAIL; + } + + self->SetUserCollisionGroup(val); + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_GameObject::pyattr_get_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + return PyLong_FromLong(self->GetUserCollisionMask()); +} + +int KX_GameObject::pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + int val = PyLong_AsLong(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "gameOb.collisionMask = int: KX_GameObject, expected an int bit field"); + return PY_SET_ATTR_FAIL; + } + + if (val < 0 || val > USHRT_MAX) { + PyErr_Format(PyExc_AttributeError, "gameOb.collisionMask = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX); + return PY_SET_ATTR_FAIL; + } + + self->SetUserCollisionMask(val); + return PY_SET_ATTR_SUCCESS; +} + PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject *self = static_cast<KX_GameObject*>(self_v); @@ -2347,6 +2425,19 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd return PY_SET_ATTR_SUCCESS; } +PyObject *KX_GameObject::pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + + // Only objects with a physics controller can be suspended + if (!self->GetPhysicsController()) { + PyErr_SetString(PyExc_AttributeError, "This object has not Physics Controller"); + return NULL; + } + + return PyBool_FromLong(self->IsDynamicsSuspended()); +} + PyObject *KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast<KX_GameObject*>(self_v); @@ -2439,7 +2530,9 @@ int KX_GameObject::pyattr_set_record_animation(void *self_v, const KX_PYATTRIBUT PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetWorldPosition()); @@ -2461,7 +2554,9 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D PyObject *KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetLocalPosition()); @@ -2483,7 +2578,9 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); if (self->GetPhysicsController1()) @@ -2495,7 +2592,9 @@ PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIB PyObject *KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL); + return Matrix_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, 3, + mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetWorldOrientation()); @@ -2520,7 +2619,9 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT PyObject *KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL); + return Matrix_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, 3, + mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetLocalOrientation()); @@ -2544,7 +2645,9 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT PyObject *KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetWorldScaling()); @@ -2566,7 +2669,9 @@ int KX_GameObject::pyattr_set_worldScaling(void *self_v, const KX_PYATTRIBUTE_DE PyObject *KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetLocalScaling()); @@ -2668,7 +2773,9 @@ int KX_GameObject::pyattr_set_worldTransform(void *self_v, const KX_PYATTRIBUTE_ PyObject *KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetLinearVelocity(false)); @@ -2690,7 +2797,9 @@ int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRI PyObject *KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetLinearVelocity(true)); @@ -2712,7 +2821,9 @@ int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRI PyObject *KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetAngularVelocity(false)); @@ -2734,7 +2845,9 @@ int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTR PyObject *KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetAngularVelocity(true)); @@ -2855,7 +2968,9 @@ PyObject *KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE PyObject *KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 4, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->GetObjectColor()); @@ -3233,10 +3348,16 @@ PyObject *KX_GameObject::PyApplyImpulse(PyObject *args) -PyObject *KX_GameObject::PySuspendDynamics() +PyObject *KX_GameObject::PySuspendDynamics(PyObject *args) { + bool ghost = false; + + if (!PyArg_ParseTuple(args, "|b", &ghost)) + return NULL; + if (GetPhysicsController()) - GetPhysicsController()->SuspendDynamics(); + GetPhysicsController()->SuspendDynamics(ghost); + Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index 5800cbc6834..9c081b449ec 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -49,6 +49,7 @@ #include "CTR_HashedPtr.h" #include "KX_Scene.h" #include "KX_KetsjiEngine.h" /* for m_anim_framerate */ +#include "DNA_constraint_types.h" /* for constraint replication */ #include "DNA_object_types.h" #include "SCA_LogicManager.h" /* for ConvertPythonToGameObject to search object names */ @@ -88,18 +89,19 @@ protected: int m_layer; std::vector<RAS_MeshObject*> m_meshes; std::vector<RAS_MeshObject*> m_lodmeshes; + int m_currentLodLevel; + short m_previousLodLevel; SG_QList m_meshSlots; // head of mesh slots of this struct Object* m_pBlenderObject; struct Object* m_pBlenderGroupObject; - bool m_bSuspendDynamics; bool m_bUseObjectColor; bool m_bIsNegativeScaling; MT_Vector4 m_objectColor; // Bit fields for user control over physics collisions - short m_userCollisionGroup; - short m_userCollisionMask; + unsigned short m_userCollisionGroup; + unsigned short m_userCollisionMask; // visible = user setting // culled = while rendering, depending on camera @@ -116,6 +118,7 @@ protected: SG_Node* m_pSGNode; MT_CmMatrix4x4 m_OpenGL_4x4Matrix; + std::vector<bRigidBodyJointConstraint*> m_constraints; KX_ObstacleSimulation* m_pObstacleSimulation; @@ -192,6 +195,14 @@ public: void UpdateBlenderObjectMatrix(Object* blendobj=NULL); + /** + * Used for constraint replication for group instances. + * The list of constraints is filled during data conversion. + */ + void AddConstraint(bRigidBodyJointConstraint *cons); + std::vector<bRigidBodyJointConstraint*> GetConstraints(); + void ClearConstraints(); + /** * Get a pointer to the game object that is the parent of * this object. Or NULL if there is no parent. The returned @@ -506,8 +517,17 @@ public: */ void ActivateGraphicController(bool recurse); - void SetUserCollisionGroup(short filter); - void SetUserCollisionMask(short mask); + /** Set the object's collison group + * \param filter The group bitfield + */ + void SetUserCollisionGroup(unsigned short filter); + + /** Set the object's collison mask + * \param filter The mask bitfield + */ + void SetUserCollisionMask(unsigned short mask); + unsigned short GetUserCollisionGroup(); + unsigned short GetUserCollisionMask(); /** * Extra broadphase check for user controllable collisions */ @@ -607,6 +627,8 @@ public: return m_bDyna; } + bool IsDynamicsSuspended() const; + /** * Should we record animation for this object? */ @@ -892,7 +914,7 @@ public: * Change the layer of the object (when it is added in another layer * than the original layer) */ - void + virtual void SetLayer( int l ); @@ -983,7 +1005,7 @@ public: KX_PYMETHOD_O(KX_GameObject,SetState); KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); KX_PYMETHOD_O(KX_GameObject,GetAxisVect); - KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics); + KX_PYMETHOD_VARARGS(KX_GameObject,SuspendDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody); KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody); @@ -1027,6 +1049,7 @@ public: static PyObject* pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); @@ -1073,6 +1096,10 @@ public: static int pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_collisionCallbacks(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_collisionGroup(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_collisionMask(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_IpoConvert.cpp b/source/gameengine/Ketsji/KX_IpoConvert.cpp index 57130bf57b2..7b00760ee7b 100644 --- a/source/gameengine/Ketsji/KX_IpoConvert.cpp +++ b/source/gameengine/Ketsji/KX_IpoConvert.cpp @@ -269,52 +269,80 @@ SG_Controller *BL_CreateCameraIPO(struct bAction *action, KX_GameObject* camera return ipocontr; } -void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *converter) -{ - - if (blenderworld->adt) { - KX_WorldIpoController* ipocontr = new KX_WorldIpoController(); - -// Erwin, hook up the world ipo controller here -// Gino: hook it up to what ? -// is there a userinterface element for that ? -// for now, we have some new python hooks to access the data, for a work-around - - ipocontr->m_mist_start = blenderworld->miststa; - ipocontr->m_mist_dist = blenderworld->mistdist; - ipocontr->m_mist_rgb[0] = blenderworld->horr; - ipocontr->m_mist_rgb[1] = blenderworld->horg; - ipocontr->m_mist_rgb[2] = blenderworld->horb; +SG_Controller * BL_CreateWorldIPO( bAction *action, struct World *blenderworld, KX_BlenderSceneConverter *converter ) +{ + KX_WorldIpoController *ipocontr = NULL; - BL_InterpolatorList *adtList= GetAdtList(blenderworld->adt->action, converter); + if (blenderworld) { + BL_InterpolatorList *adtList = GetAdtList(action, converter); - // For each active channel in the adtList add an - // interpolator to the game object. - + // For each active channel in the adtList add an interpolator to the game object. KX_IInterpolator *interpolator; KX_IScalarInterpolator *interp; - + + for (int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("ambient_color", i))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_ambi_rgb[i], interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyAmbientColor(true); + } + } + for (int i=0; i<3; i++) { if ((interp = adtList->GetScalarInterpolator("horizon_color", i))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_rgb[i], interp); + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_hori_rgb[i], interp); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyMistColor(true); + ipocontr->SetModifyHorizonColor(true); } } - if ((interp = adtList->GetScalarInterpolator("mist.depth", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp); + if ((interp = adtList->GetScalarInterpolator("mist_settings.start", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyMistStart(true); + } + + if ((interp = adtList->GetScalarInterpolator("mist_settings.depth", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp); ipocontr->AddInterpolator(interpolator); ipocontr->SetModifyMistDist(true); } - if ((interp = adtList->GetScalarInterpolator("mist.start", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp); + if ((interp = adtList->GetScalarInterpolator("mist_settings.intensity", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_intensity, interp); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyMistStart(true); + ipocontr->SetModifyMistIntensity(true); + } + + if (ipocontr) { + ipocontr->m_mist_start = blenderworld->miststa; + ipocontr->m_mist_dist = blenderworld->mistdist; + ipocontr->m_mist_intensity = blenderworld->misi; + ipocontr->m_hori_rgb[0] = blenderworld->horr; + ipocontr->m_hori_rgb[1] = blenderworld->horg; + ipocontr->m_hori_rgb[2] = blenderworld->horb; + ipocontr->m_ambi_rgb[0] = blenderworld->ambr; + ipocontr->m_ambi_rgb[1] = blenderworld->ambg; + ipocontr->m_ambi_rgb[2] = blenderworld->ambb; } } + return ipocontr; } SG_Controller *BL_CreateMaterialIpo( @@ -368,7 +396,7 @@ SG_Controller *BL_CreateMaterialIpo( ipocontr->AddInterpolator(interpolator); } - if ((sinterp = adtList->GetScalarInterpolator("specularity", 0))) { + if ((sinterp = adtList->GetScalarInterpolator("specular_intensity", 0))) { if (!ipocontr) { ipocontr = new KX_MaterialIpoController(matname_hash); } @@ -376,7 +404,7 @@ SG_Controller *BL_CreateMaterialIpo( ipocontr->AddInterpolator(interpolator); } - if ((sinterp = adtList->GetScalarInterpolator("diffuse_reflection", 0))) { + if ((sinterp = adtList->GetScalarInterpolator("diffuse_intensity", 0))) { if (!ipocontr) { ipocontr = new KX_MaterialIpoController(matname_hash); } diff --git a/source/gameengine/Ketsji/KX_IpoConvert.h b/source/gameengine/Ketsji/KX_IpoConvert.h index a653e4e110b..6db43552811 100644 --- a/source/gameengine/Ketsji/KX_IpoConvert.h +++ b/source/gameengine/Ketsji/KX_IpoConvert.h @@ -50,7 +50,8 @@ SG_Controller *BL_CreateLampIPO(bAction *action, KX_GameObject* lightobj, KX_BlenderSceneConverter *converter); -void BL_ConvertWorldIpos(struct World* blenderworld, +SG_Controller *BL_CreateWorldIPO(bAction *action, + struct World *blenderworld, KX_BlenderSceneConverter *converter); SG_Controller *BL_CreateCameraIPO(bAction *action, diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index e453b757b7e..40af9b4ca39 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -312,10 +312,11 @@ void KX_KetsjiEngine::RenderDome() // for each scene, call the proceed functions { scene = *sceneit; + KX_SetActiveScene(scene); KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); // shadow buffers if (i == 0) { @@ -389,8 +390,10 @@ void KX_KetsjiEngine::RenderDome() ); } m_dome->Draw(); + // Draw Callback for the last scene #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); scene->RunDrawingCallbacks(scene->GetPostDrawCB()); #endif EndFrame(); @@ -475,7 +478,7 @@ void KX_KetsjiEngine::ClearFrame() if (doclear) { KX_Scene* firstscene = *m_scenes.begin(); - SetBackGround(firstscene->GetWorldInfo()); + firstscene->GetWorldInfo()->UpdateBackGround(); m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(), clearvp.GetRight(), clearvp.GetTop()); @@ -825,7 +828,7 @@ void KX_KetsjiEngine::Render() KX_Scene* scene = *sceneit; KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); // this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes //scene->UpdateMeshTransformations(); @@ -882,7 +885,7 @@ void KX_KetsjiEngine::Render() KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); if (scene->IsClearingZBuffer()) m_rasterizer->ClearDepthBuffer(); @@ -962,54 +965,6 @@ const STR_String& KX_KetsjiEngine::GetExitString() return m_exitstring; } - -void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi) -{ - if (wi->hasWorld()) - { - if (m_rasterizer->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) - { - m_rasterizer->SetBackColor( - wi->getBackColorRed(), - wi->getBackColorGreen(), - wi->getBackColorBlue(), - 0.0 - ); - } - } -} - - - -void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) -{ - if (wi->hasWorld()) - { - // ... - m_rasterizer->SetAmbientColor( - wi->getAmbientColorRed(), - wi->getAmbientColorGreen(), - wi->getAmbientColorBlue() - ); - - if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) - { - if (wi->hasMist()) - { - m_rasterizer->SetFog( - wi->getMistStart(), - wi->getMistDistance(), - wi->getMistColorRed(), - wi->getMistColorGreen(), - wi->getMistColorBlue() - ); - } - } - } -} - - - void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene) { m_overrideCam = true; @@ -1150,6 +1105,13 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) if (!cam) return; + + KX_SetActiveScene(scene); + +#ifdef WITH_PYTHON + scene->RunDrawingCallbacks(scene->GetPreDrawSetupCB()); +#endif + GetSceneViewport(scene, cam, area, viewport); // store the computed viewport in the scene @@ -1262,6 +1224,7 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) SG_SetActiveStage(SG_STAGE_RENDER); #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); // Run any pre-drawing python callbacks scene->RunDrawingCallbacks(scene->GetPreDrawCB()); #endif @@ -1280,12 +1243,16 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) */ void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene) { + KX_SetActiveScene(scene); + // We need to first make sure our viewport is correct (enabling multiple viewports can mess this up) m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight()); m_rasterizer->FlushDebugShapes(); scene->Render2DFilters(m_canvas); + #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); scene->RunDrawingCallbacks(scene->GetPostDrawCB()); #endif } diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index e18b203b675..4392769ed02 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -205,14 +205,12 @@ private: void PostRenderScene(KX_Scene* scene); void RenderDebugProperties(); void RenderShadowBuffers(KX_Scene *scene); - void SetBackGround(KX_WorldInfo* worldinfo); public: KX_KetsjiEngine(class KX_ISystem* system); virtual ~KX_KetsjiEngine(); // set the devices and stuff. the client must take care of creating these - void SetWorldSettings(KX_WorldInfo* worldinfo); void SetKeyboardDevice(SCA_IInputDevice* keyboarddevice); void SetMouseDevice(SCA_IInputDevice* mousedevice); void SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice); diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 33cfec57fc0..0dec5715588 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -108,6 +108,7 @@ void KX_LightObject::UpdateScene(KX_Scene *kxscene) void KX_LightObject::SetLayer(int layer) { + KX_GameObject::SetLayer(layer); m_lightobj->m_layer = layer; } @@ -166,27 +167,31 @@ PyAttributeDef KX_LightObject::Attributes[] = { PyObject *KX_LightObject::pyattr_get_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_LightObject* self = static_cast<KX_LightObject*>(self_v); + KX_LightObject *self = static_cast<KX_LightObject *>(self_v); return PyLong_FromLong(self->m_lightobj->m_layer); } int KX_LightObject::pyattr_set_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_LightObject* self = static_cast<KX_LightObject*>(self_v); + KX_LightObject *self = static_cast<KX_LightObject *>(self_v); + int layer = PyLong_AsLong(value); - if (PyLong_Check(value)) { - int val = PyLong_AsLong(value); - if (val < 1) - val = 1; - else if (val > 20) - val = 20; + if (layer == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } - self->m_lightobj->m_layer = val; - return PY_SET_ATTR_SUCCESS; + if (layer < 1) { + PyErr_Format(PyExc_TypeError, "expected an integer greater than 1 for attribute \"%s\"", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } + else if(layer > MAX_LIGHT_LAYERS) { + PyErr_Format(PyExc_TypeError, "expected an integer less than %i for attribute \"%s\"", MAX_LIGHT_LAYERS, attrdef->m_name); + return PY_SET_ATTR_FAIL; } - PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); - return PY_SET_ATTR_FAIL; + self->SetLayer(layer); + return PY_SET_ATTR_SUCCESS; } PyObject *KX_LightObject::pyattr_get_energy(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 503ed7411e9..3a58584223d 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -34,6 +34,8 @@ #include "KX_GameObject.h" +#define MAX_LIGHT_LAYERS ((1 << 20) - 1) + struct GPULamp; struct Scene; struct Base; @@ -58,7 +60,7 @@ public: RAS_ILightObject* GetLightData() { return m_lightobj;} void UpdateScene(class KX_Scene *kxscene); - void SetLayer(int layer); + virtual void SetLayer(int layer); virtual int GetGameObjectType() { return OBJ_LIGHT; } diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp index a9617aa47b8..1faf8f17d54 100644 --- a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp @@ -32,21 +32,6 @@ bool KX_MaterialIpoController::Update(double currentTime) { if (m_modified) { - m_rgba[0]=0; - m_rgba[1]=0; - m_rgba[2]=0; - m_rgba[3]=0; - - m_specrgb[0] =0; - m_specrgb[1] =0; - m_specrgb[2] =0; - m_hard =0; - m_spec=0; - m_ref=0; - m_emit=0; - m_alpha = 0; - - T_InterpolatorList::iterator i; for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { (*i)->Execute(m_ipotime); diff --git a/source/gameengine/Ketsji/KX_MouseActuator.cpp b/source/gameengine/Ketsji/KX_MouseActuator.cpp index 62417b4df81..c372e6e9ce2 100644 --- a/source/gameengine/Ketsji/KX_MouseActuator.cpp +++ b/source/gameengine/Ketsji/KX_MouseActuator.cpp @@ -278,7 +278,10 @@ bool KX_MouseActuator::Update() setposition[1] = center_y; } - setMousePosition(setposition[0], setposition[1]); + // only trigger mouse event when it is necessary + if (m_oldposition[0] != position[0] || m_oldposition[1] != position[1]) { + setMousePosition(setposition[0], setposition[1]); + } m_oldposition[0] = position[0]; m_oldposition[1] = position[1]; diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 0eec86987be..12abcb250a7 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -75,7 +75,8 @@ KX_ObjectActuator( m_reference(refobj), m_active_combined_velocity (false), m_linear_damping_active(false), - m_angular_damping_active(false) + m_angular_damping_active(false), + m_jumping(false) { if (m_bitLocalFlag.ServoControl) { @@ -140,6 +141,7 @@ bool KX_ObjectActuator::Update() m_angular_damping_active = false; m_error_accumulator.setValue(0.0,0.0,0.0); m_previous_error.setValue(0.0,0.0,0.0); + m_jumping = false; return false; } else if (parent) @@ -223,6 +225,11 @@ bool KX_ObjectActuator::Update() else if (m_bitLocalFlag.CharacterMotion) { MT_Vector3 dir = m_dloc; + if (m_bitLocalFlag.DLoc) { + MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation(); + dir = basis * dir; + } + if (m_bitLocalFlag.AddOrSetCharLoc) { MT_Vector3 old_dir = character->GetWalkDirection(); @@ -236,21 +243,20 @@ bool KX_ObjectActuator::Update() } // We always want to set the walk direction since a walk direction of (0, 0, 0) should stop the character - if (m_bitLocalFlag.DLoc) - { - MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation(); - dir = basis*dir; - } character->SetWalkDirection(dir/parent->GetScene()->GetPhysicsEnvironment()->GetNumTimeSubSteps()); if (!m_bitLocalFlag.ZeroDRot) { parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0); } - if (m_bitLocalFlag.CharacterJump) - { - character->Jump(); + if (m_bitLocalFlag.CharacterJump) { + if (!m_jumping) { + character->Jump(); + m_jumping = true; + } + else if (character->OnGround()) + m_jumping = false; } } else { @@ -516,7 +522,9 @@ static Mathutils_Callback mathutils_obactu_vector_cb = { PyObject *KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV); } int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -532,7 +540,9 @@ int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *a PyObject *KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV); } int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index 1f2453e3700..b5622d97611 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -116,7 +116,8 @@ class KX_ObjectActuator : public SCA_IActuator bool m_active_combined_velocity; bool m_linear_damping_active; bool m_angular_damping_active; - + bool m_jumping; + public: enum KX_OBJECT_ACT_VEC_TYPE { KX_OBJECT_ACT_NODEF = 0, diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 94f5064261f..065251f5676 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -496,78 +496,46 @@ static PyObject *gPyCreateConstraint(PyObject *self, { /* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */ unsigned long long physicsid = 0, physicsid2 = 0; - int constrainttype=0, extrainfo=0; - int len = PyTuple_Size(args); - int success = 1; + int constrainttype = 0; int flag = 0; + float pivotX = 0.0f, pivotY = 0.0f, pivotZ = 0.0f, axisX = 0.0f, axisY = 0.0f, axisZ = 0.0f; - float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1; - if (len == 3) - { - success = PyArg_ParseTuple(args, "KKi", &physicsid, &physicsid2, &constrainttype); - } - else if (len == 6) - { - success = PyArg_ParseTuple(args, "KKifff", &physicsid, &physicsid2, &constrainttype, - &pivotX, &pivotY, &pivotZ); - } - else if (len == 9) - { - success = PyArg_ParseTuple(args, "KKiffffff", &physicsid, &physicsid2, &constrainttype, - &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ); - } - else if (len == 10) - { - success = PyArg_ParseTuple(args, "KKiffffffi", &physicsid, &physicsid2, &constrainttype, - &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ, &flag); - } + static const char *kwlist[] = {"physicsid_1", "physicsid_2", "constraint_type", "pivot_x", "pivot_y", "pivot_z", + "axis_X", "axis_y", "axis_z", "flag", NULL}; - /* XXX extrainfo seems to be nothing implemented. right now it works as a pivot with [X,0,0] */ - else if (len == 4) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "KKi|ffffffi:createConstraint", (char **)kwlist, + &physicsid, &physicsid2, &constrainttype, + &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ, &flag)) { - success = PyArg_ParseTuple(args,"KKii", &physicsid, &physicsid2, &constrainttype, &extrainfo); - pivotX=extrainfo; + return NULL; } - if (success) - { - if (PHY_GetActiveEnvironment()) - { - - PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid; - PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2; - if (physctrl) //TODO:check for existence of this pointer! - { - int constraintid =0; - - //convert from euler angle into axis - float radsPerDeg = 6.283185307179586232f / 360.f; + if (PHY_GetActiveEnvironment()) { + PHY_IPhysicsController *physctrl = (PHY_IPhysicsController*)physicsid; + PHY_IPhysicsController *physctrl2 = (PHY_IPhysicsController*)physicsid2; + if (physctrl) { //TODO:check for existence of this pointer! + //convert from euler angle into axis + const float deg2rad = 0.017453292f; - //we need to pass a full constraint frame, not just axis - //localConstraintFrameBasis - MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*axisX,radsPerDeg*axisY,radsPerDeg*axisZ)); - MT_Vector3 axis0 = localCFrame.getColumn(0); - MT_Vector3 axis1 = localCFrame.getColumn(1); - MT_Vector3 axis2 = localCFrame.getColumn(2); + //we need to pass a full constraint frame, not just axis + //localConstraintFrameBasis + MT_Matrix3x3 localCFrame(MT_Vector3(deg2rad*axisX, deg2rad*axisY, deg2rad*axisZ)); + MT_Vector3 axis0 = localCFrame.getColumn(0); + MT_Vector3 axis1 = localCFrame.getColumn(1); + MT_Vector3 axis2 = localCFrame.getColumn(2); - constraintid = PHY_GetActiveEnvironment()->CreateConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype, - pivotX,pivotY,pivotZ, - (float)axis0.x(),(float)axis0.y(),(float)axis0.z(), - (float)axis1.x(),(float)axis1.y(),(float)axis1.z(), - (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag); + int constraintid = PHY_GetActiveEnvironment()->CreateConstraint( + physctrl, physctrl2, (enum PHY_ConstraintType)constrainttype, pivotX, pivotY, pivotZ, + (float)axis0.x(), (float)axis0.y(), (float)axis0.z(), + (float)axis1.x(), (float)axis1.y(), (float)axis1.z(), + (float)axis2.x(), (float)axis2.y(), (float)axis2.z(), flag); - KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment()); + KX_ConstraintWrapper *wrap = new KX_ConstraintWrapper( + (enum PHY_ConstraintType)constrainttype, constraintid, PHY_GetActiveEnvironment()); - return wrap->NewProxy(true); - } - - + return wrap->NewProxy(true); } } - else { - return NULL; - } - Py_RETURN_NONE; } @@ -680,7 +648,7 @@ static struct PyMethodDef physicsconstraints_methods[] = { {"createConstraint",(PyCFunction) gPyCreateConstraint, - METH_VARARGS, (const char *)gPyCreateConstraint__doc__}, + METH_VARARGS|METH_KEYWORDS, (const char *)gPyCreateConstraint__doc__}, {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint, METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__}, diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index d7dd3fe5253..6fdc53f9c64 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -51,6 +51,8 @@ # include <Python.h> extern "C" { + # include "BLI_utildefines.h" + # include "python_utildefines.h" # include "bpy_internal_import.h" /* from the blender python api, but we want to import text too! */ # include "py_capi_utils.h" # include "mathutils.h" // 'mathutils' module copied here so the blenderlayer can use. @@ -354,7 +356,7 @@ static PyObject *gPyLoadGlobalDict(PyObject *) { char marshal_path[512]; char *marshal_buffer = NULL; - size_t marshal_length; + int marshal_length; FILE *fp = NULL; int result; @@ -365,7 +367,12 @@ static PyObject *gPyLoadGlobalDict(PyObject *) if (fp) { // obtain file size: fseek (fp, 0, SEEK_END); - marshal_length = (size_t)ftell(fp); + marshal_length = ftell(fp); + if (marshal_length == -1) { + printf("Warning: could not read position of '%s'\n", marshal_path); + fclose(fp); + Py_RETURN_NONE; + } rewind(fp); marshal_buffer = (char*)malloc (sizeof(char)*marshal_length); @@ -1029,109 +1036,22 @@ static PyObject *gPyGetStereoEye(PyObject *, PyObject *, PyObject *) static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value) { - MT_Vector4 vec; if (!PyVecTo(value, vec)) return NULL; - - if (gp_Canvas) - { - gp_Rasterizer->SetBackColor((float)vec[0], (float)vec[1], (float)vec[2], (float)vec[3]); - } KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (wi->hasWorld()) - wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]); - - Py_RETURN_NONE; -} - - - -static PyObject *gPySetMistColor(PyObject *, PyObject *value) -{ - - MT_Vector3 vec; - if (!PyVecTo(value, vec)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.SetBackgroundColor(color), World not available"); return NULL; } - gp_Rasterizer->SetFogColor((float)vec[0], (float)vec[1], (float)vec[2]); - - Py_RETURN_NONE; -} - -static PyObject *gPyDisableMist(PyObject *) -{ - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); - return NULL; - } - gp_Rasterizer->DisableFog(); - - Py_RETURN_NONE; -} -static PyObject *gPySetMistStart(PyObject *, PyObject *args) -{ + ShowDeprecationWarning("setBackgroundColor()", "KX_WorldInfo.background_color"); + wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]); - float miststart; - if (!PyArg_ParseTuple(args,"f:setMistStart",&miststart)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistStart(float), Rasterizer not available"); - return NULL; - } - - gp_Rasterizer->SetFogStart(miststart); - Py_RETURN_NONE; } - - -static PyObject *gPySetMistEnd(PyObject *, PyObject *args) -{ - - float mistend; - if (!PyArg_ParseTuple(args,"f:setMistEnd",&mistend)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistEnd(float), Rasterizer not available"); - return NULL; - } - - gp_Rasterizer->SetFogEnd(mistend); - - Py_RETURN_NONE; -} - - -static PyObject *gPySetAmbientColor(PyObject *, PyObject *value) -{ - - MT_Vector3 vec; - if (!PyVecTo(value, vec)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setAmbientColor(color), Rasterizer not available"); - return NULL; - } - gp_Rasterizer->SetAmbientColor((float)vec[0], (float)vec[1], (float)vec[2]); - - Py_RETURN_NONE; -} - - - - static PyObject *gPyMakeScreenshot(PyObject *, PyObject *args) { char* filename; @@ -1490,6 +1410,21 @@ static PyObject *gPyClearDebugList(PyObject *) Py_RETURN_NONE; } +static PyObject *gPyGetDisplayDimensions(PyObject *) +{ + PyObject *result; + int width, height; + + gp_Canvas->GetDisplayDimensions(width, height); + + result = PyTuple_New(2); + PyTuple_SET_ITEMS(result, + PyLong_FromLong(width), + PyLong_FromLong(height)); + + return result; +} + PyDoc_STRVAR(Rasterizer_module_documentation, "This is the Python API for the game engine of Rasterizer" ); @@ -1508,11 +1443,6 @@ static struct PyMethodDef rasterizer_methods[] = { {"setMousePosition",(PyCFunction) gPySetMousePosition, METH_VARARGS, "setMousePosition(int x,int y)"}, {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"}, - {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"}, - {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"}, - {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, - {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"}, - {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"}, {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"}, @@ -1538,6 +1468,8 @@ static struct PyMethodDef rasterizer_methods[] = { {"setWindowSize", (PyCFunction) gPySetWindowSize, METH_VARARGS, ""}, {"setFullScreen", (PyCFunction) gPySetFullScreen, METH_O, ""}, {"getFullScreen", (PyCFunction) gPyGetFullScreen, METH_NOARGS, ""}, + {"getDisplayDimensions", (PyCFunction) gPyGetDisplayDimensions, METH_NOARGS, + "Get the actual dimensions, in pixels, of the physical display (e.g., the monitor)."}, {"setMipmapping", (PyCFunction) gPySetMipmapping, METH_VARARGS, ""}, {"getMipmapping", (PyCFunction) gPyGetMipmapping, METH_NOARGS, ""}, {"setVsync", (PyCFunction) gPySetVsync, METH_VARARGS, ""}, @@ -2149,14 +2081,14 @@ PyObject *initGamePlayerPythonScripting(Main *maggie, int argc, char** argv) Py_SetProgramName(program_path_wchar); /* Update, Py3.3 resolves attempting to parse non-existing header */ - #if 0 +#if 0 /* Python 3.2 now looks for '2.xx/python/include/python3.2d/pyconfig.h' to * parse from the 'sysconfig' module which is used by 'site', * so for now disable site. alternatively we could copy the file. */ if (py_path_bundle != NULL) { Py_NoSiteFlag = 1; /* inhibits the automatic importing of 'site' */ } - #endif +#endif Py_FrozenFlag = 1; diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index 828fd62f205..b3511e4e61a 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -40,6 +40,7 @@ #include "BL_ArmatureConstraint.h" #include "BL_ArmatureObject.h" #include "BL_ArmatureChannel.h" +#include "KX_WorldInfo.h" #include "KX_ArmatureSensor.h" #include "KX_BlenderMaterial.h" #include "KX_CameraActuator.h" @@ -231,6 +232,7 @@ PyMODINIT_FUNC initGameTypesPythonBinding(void) PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator, init_getset); PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator, init_getset); PyType_Ready_Attr(dict, KX_Scene, init_getset); + PyType_Ready_Attr(dict, KX_WorldInfo, init_getset); PyType_Ready_Attr(dict, KX_NavMeshObject, init_getset); PyType_Ready_Attr(dict, KX_SceneActuator, init_getset); PyType_Ready_Attr(dict, KX_SoundActuator, init_getset); @@ -279,6 +281,7 @@ PyMODINIT_FUNC initGameTypesPythonBinding(void) /* Init mathutils callbacks */ KX_GameObject_Mathutils_Callback_Init(); KX_ObjectActuator_Mathutils_Callback_Init(); + KX_WorldInfo_Mathutils_Callback_Init(); #endif return m; diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 97ebd6d40a9..25755f7127b 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -43,6 +43,7 @@ #include "KX_FontObject.h" #include "RAS_IPolygonMaterial.h" #include "ListValue.h" +#include "KX_PythonCallBack.h" #include "SCA_LogicManager.h" #include "SCA_TimeEventManager.h" //#include "SCA_AlwaysEventManager.h" @@ -156,7 +157,9 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_networkDeviceInterface(ndi), m_active_camera(NULL), m_ueberExecutionPriority(0), - m_blenderScene(scene) + m_blenderScene(scene), + m_isActivedHysteresis(false), + m_lodHysteresisValue(0) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -235,6 +238,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_attr_dict = NULL; m_draw_call_pre = NULL; m_draw_call_post = NULL; + m_draw_setup_call_pre = NULL; #endif } @@ -532,6 +536,8 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal m_objectlist->Add(newobj->AddRef()); if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) m_lightlist->Add(newobj->AddRef()); + else if (newobj->GetGameObjectType()==SCA_IObject::OBJ_TEXT) + AddFont((KX_FontObject*)newobj); newobj->AddMeshUser(); // logic cannot be replicated, until the whole hierarchy is replicated. @@ -803,13 +809,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // we can now add the graphic controller to the physic engine replica->ActivateGraphicController(true); - // set references for dupli-group - // groupobj holds a list of all objects, that belongs to this group - groupobj->AddInstanceObjects(replica); - - // every object gets the reference to its dupli-group object - replica->SetDupliGroupObject(groupobj); - // done with replica replica->Release(); } @@ -817,38 +816,38 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // the logic must be replicated first because we need // the new logic bricks before relinking vector<KX_GameObject*>::iterator git; - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { - (*git)->ReParentLogic(); - } - - // relink any pointers as necessary, sort of a temporary solution - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { + for (git = m_logicHierarchicalGameObjects.begin(); git != m_logicHierarchicalGameObjects.end(); ++git) { + KX_GameObject *gameobj = *git; + + if (gameobj->GetBlenderGroupObject() == blgroupobj) { + // set references for dupli-group + // groupobj holds a list of all objects, that belongs to this group + groupobj->AddInstanceObjects(gameobj); + // every object gets the reference to its dupli-group object + gameobj->SetDupliGroupObject(groupobj); + } + + gameobj->ReParentLogic(); + + // relink any pointers as necessary, sort of a temporary solution // this will also relink the actuator to objects within the hierarchy - (*git)->Relink(&m_map_gameobject_to_replica); + gameobj->Relink(&m_map_gameobject_to_replica); // add the object in the layer of the parent - (*git)->SetLayer(groupobj->GetLayer()); - // If the object was a light, we need to update it's RAS_LightObject as well - if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) - { - KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git); - lightobj->SetLayer(groupobj->GetLayer()); - } - } + gameobj->SetLayer(groupobj->GetLayer()); - // replicate crosslinks etc. between logic bricks - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { - ReplicateLogic((*git)); - } + // replicate crosslinks etc. between logic bricks + ReplicateLogic(gameobj); - // now look if object in the hierarchy have dupli group and recurse - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { - if ((*git) != groupobj && (*git)->IsDupliGroup()) + // now look if object in the hierarchy have dupli group and recurse + /* Replicate all constraints. */ + if (gameobj->GetPhysicsController()) { + gameobj->GetPhysicsController()->ReplicateConstraints(gameobj, m_logicHierarchicalGameObjects); + gameobj->ClearConstraints(); + } + + if (gameobj != groupobj && gameobj->IsDupliGroup()) // can't instantiate group immediately as it destroys m_logicHierarchicalGameObjects - duplilist.push_back((*git)); + duplilist.push_back(gameobj); } for (git = duplilist.begin(); !(git == duplilist.end()); ++git) @@ -859,7 +858,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, - class CValue* parentobject, + class CValue* referenceobject, int lifespan) { @@ -868,7 +867,7 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, m_groupGameObjects.clear(); KX_GameObject* originalobj = (KX_GameObject*) originalobject; - KX_GameObject* parentobj = (KX_GameObject*) parentobject; + KX_GameObject* referenceobj = (KX_GameObject*) referenceobject; m_ueberExecutionPriority++; @@ -904,18 +903,20 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, replica->GetSGNode()->AddChild(childreplicanode); } - // At this stage all the objects in the hierarchy have been duplicated, - // we can update the scenegraph, we need it for the duplication of logic - MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition(); - replica->NodeSetLocalPosition(newpos); + if (referenceobj) { + // At this stage all the objects in the hierarchy have been duplicated, + // we can update the scenegraph, we need it for the duplication of logic + MT_Point3 newpos = referenceobj->NodeGetWorldPosition(); + replica->NodeSetLocalPosition(newpos); - MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation(); - replica->NodeSetLocalOrientation(newori); - - // get the rootnode's scale - MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); - // set the replica's relative scale with the rootnode's scale - replica->NodeSetRelativeScale(newscale); + MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation(); + replica->NodeSetLocalOrientation(newori); + + // get the rootnode's scale + MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); + // set the replica's relative scale with the rootnode's scale + replica->NodeSetRelativeScale(newscale); + } replica->GetSGNode()->UpdateWorldData(0); replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox()); @@ -935,13 +936,13 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, { // this will also relink the actuators in the hierarchy (*git)->Relink(&m_map_gameobject_to_replica); - // add the object in the layer of the parent - (*git)->SetLayer(parentobj->GetLayer()); - // If the object was a light, we need to update it's RAS_LightObject as well - if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) - { - KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git); - lightobj->SetLayer(parentobj->GetLayer()); + if (referenceobj) { + // add the object in the layer of the reference object + (*git)->SetLayer(referenceobj->GetLayer()); + } + else { + // We don't know what layer set, so we set all visible layers in the blender scene. + (*git)->SetLayer(m_blenderScene->lay); } } @@ -1755,6 +1756,26 @@ void KX_Scene::UpdateObjectLods(void) } } +void KX_Scene::SetLodHysteresis(bool active) +{ + m_isActivedHysteresis = active; +} + +bool KX_Scene::IsActivedLodHysteresis(void) +{ + return m_isActivedHysteresis; +} + +void KX_Scene::SetLodHysteresisValue(int hysteresisvalue) +{ + m_lodHysteresisValue = hysteresisvalue; +} + +int KX_Scene::GetLodHysteresisValue(void) +{ + return m_lodHysteresisValue; +} + void KX_Scene::UpdateObjectActivity(void) { if (m_activity_culling) { @@ -1871,15 +1892,6 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *from, KX_Sce brick->Replace_IScene(to); brick->Replace_NetworkScene(to->GetNetworkScene()); - /* near sensors have physics controllers */ - KX_TouchSensor *touch_sensor = dynamic_cast<class KX_TouchSensor *>(brick); - if (touch_sensor) { - KX_TouchEventManager *tmgr = (KX_TouchEventManager*)from->GetLogicManager()->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - touch_sensor->UnregisterSumo(tmgr); - touch_sensor->GetPhysicsController()->SetPhysicsEnvironment(to->GetPhysicsEnvironment()); - touch_sensor->RegisterSumo(tmgr); - } - // If we end up replacing a KX_TouchEventManager, we need to make sure // physics controllers are properly in place. In other words, do this // after merging physics controllers! @@ -1938,17 +1950,6 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene { SCA_IController *cont= *itc; MergeScene_LogicBrick(cont, from, to); - - vector<SCA_ISensor*> linkedsensors = cont->GetLinkedSensors(); - vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators(); - - for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());++ita) { - MergeScene_LogicBrick(*ita, from, to); - } - - for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());++its) { - MergeScene_LogicBrick(*its, from, to); - } } } @@ -2102,30 +2103,10 @@ void KX_Scene::Render2DFilters(RAS_ICanvas* canvas) void KX_Scene::RunDrawingCallbacks(PyObject *cb_list) { - Py_ssize_t len; - - if (cb_list && (len=PyList_GET_SIZE(cb_list))) - { - PyObject *args = PyTuple_New(0); // save python creating each call - PyObject *func; - PyObject *ret; - - // Iterate the list and run the callbacks - for (Py_ssize_t pos=0; pos < len; pos++) - { - func= PyList_GET_ITEM(cb_list, pos); - ret= PyObject_Call(func, args, NULL); - if (ret==NULL) { - PyErr_Print(); - PyErr_Clear(); - } - else { - Py_DECREF(ret); - } - } + if (!cb_list || PyList_GET_SIZE(cb_list) == 0) + return; - Py_DECREF(args); - } + RunPythonCallBackList(cb_list, NULL, 0, 0); } //---------------------------------------------------------------------------- @@ -2311,6 +2292,19 @@ PyObject *KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *at return self->GetLightList()->GetProxy(); } +PyObject *KX_Scene::pyattr_get_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + KX_WorldInfo *world = self->GetWorldInfo(); + + if (world->GetName() != "") { + return world->GetProxy(); + } + else { + Py_RETURN_NONE; + } +} + PyObject *KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { /* With refcounts in this case... @@ -2375,6 +2369,17 @@ PyObject *KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYAT return self->m_draw_call_post; } +PyObject *KX_Scene::pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + + if (self->m_draw_setup_call_pre == NULL) + self->m_draw_setup_call_pre = PyList_New(0); + + Py_INCREF(self->m_draw_setup_call_pre); + return self->m_draw_setup_call_pre; +} + int KX_Scene::pyattr_set_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_Scene* self = static_cast<KX_Scene*>(self_v); @@ -2409,6 +2414,22 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } +int KX_Scene::pyattr_set_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + + if (!PyList_CheckExact(value)) { + PyErr_SetString(PyExc_ValueError, "Expected a list"); + return PY_SET_ATTR_FAIL; + } + + Py_XDECREF(self->m_draw_setup_call_pre); + Py_INCREF(value); + + self->m_draw_setup_call_pre = value; + return PY_SET_ATTR_SUCCESS; +} + PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Scene* self = static_cast<KX_Scene*>(self_v); @@ -2434,9 +2455,11 @@ PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("objectsInactive", KX_Scene, pyattr_get_objects_inactive), KX_PYATTRIBUTE_RO_FUNCTION("lights", KX_Scene, pyattr_get_lights), KX_PYATTRIBUTE_RO_FUNCTION("cameras", KX_Scene, pyattr_get_cameras), + KX_PYATTRIBUTE_RO_FUNCTION("world", KX_Scene, pyattr_get_world), KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera), KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post), + KX_PYATTRIBUTE_RW_FUNCTION("pre_draw_setup", KX_Scene, pyattr_get_drawing_setup_callback_pre, pyattr_set_drawing_setup_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity), KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), @@ -2449,23 +2472,23 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, "addObject(object, other, time=0)\n" "Returns the added object.\n") { - PyObject *pyob, *pyother; - KX_GameObject *ob, *other; + PyObject *pyob, *pyreference = Py_None; + KX_GameObject *ob, *reference; int time = 0; - if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyother, &time)) + if (!PyArg_ParseTuple(args, "O|Oi:addObject", &pyob, &pyreference, &time)) return NULL; - if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, other, time): KX_Scene (first argument)") || - !ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") ) + if (!ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") || + !ConvertPythonToGameObject(pyreference, &reference, true, "scene.addObject(object, reference, time): KX_Scene (second argument)")) return NULL; if (!m_inactivelist->SearchValue(ob)) { - PyErr_Format(PyExc_ValueError, "scene.addObject(object, other, time): KX_Scene (first argument): object must be in an inactive layer"); + PyErr_Format(PyExc_ValueError, "scene.addObject(object, reference, time): KX_Scene (first argument): object must be in an inactive layer"); return NULL; } - SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time); + SCA_IObject *replica = AddReplicaObject((SCA_IObject*)ob, reference, time); // release here because AddReplicaObject AddRef's // the object is added to the scene so we don't want python to own a reference diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 2e1ee9f101d..a5645ea6448 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -107,6 +107,7 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene PyObject* m_attr_dict; PyObject* m_draw_call_pre; PyObject* m_draw_call_post; + PyObject* m_draw_setup_call_pre; #endif struct CullingInfo { @@ -295,6 +296,12 @@ protected: KX_ObstacleSimulation* m_obstacleSimulation; + /** + * LOD Hysteresis settings + */ + bool m_isActivedHysteresis; + int m_lodHysteresisValue; + public: KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, @@ -546,6 +553,12 @@ public: // Update the mesh for objects based on level of detail settings void UpdateObjectLods(void); + + // LoD Hysteresis functions + void SetLodHysteresis(bool active); + bool IsActivedLodHysteresis(); + void SetLodHysteresisValue(int hysteresisvalue); + int GetLodHysteresisValue(); // Update the activity box settings for objects in this scene, if needed. void UpdateObjectActivity(void); @@ -612,12 +625,15 @@ public: static PyObject* pyattr_get_objects_inactive(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_lights(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_cameras(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_world(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_drawing_setup_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); @@ -634,6 +650,7 @@ public: PyObject *GetPreDrawCB() { return m_draw_call_pre; } PyObject *GetPostDrawCB() { return m_draw_call_post; } + PyObject *GetPreDrawSetupCB() { return m_draw_setup_call_pre; } #endif /** diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.cpp b/source/gameengine/Ketsji/KX_SteeringActuator.cpp index 10d4273a2b4..83597f9125a 100644 --- a/source/gameengine/Ketsji/KX_SteeringActuator.cpp +++ b/source/gameengine/Ketsji/KX_SteeringActuator.cpp @@ -263,12 +263,12 @@ bool KX_SteeringActuator::Update(double curtime, bool frame) if (apply_steerforce) { - MT_Vector3 newvel; bool isdyna = obj->IsDynamic(); if (isdyna) m_steerVec.z() = 0; if (!m_steerVec.fuzzyZero()) m_steerVec.normalize(); + MT_Vector3 newvel = m_velocity * m_steerVec; //adjust velocity to avoid obstacles if (m_simulation && m_obstacle /*&& !newvel.fuzzyZero()*/) @@ -284,13 +284,10 @@ bool KX_SteeringActuator::Update(double curtime, bool frame) HandleActorFace(newvel); if (isdyna) { - //TODO: Take into account angular velocity on turns + //temporary solution: set 2D steering velocity directly to obj + //correct way is to apply physical force MT_Vector3 curvel = obj->GetLinearVelocity(); - newvel = (curvel.length() * m_steerVec) + (m_acceleration * delta) * m_steerVec; - if (newvel.length2() >= (m_velocity * m_velocity)) - newvel = m_velocity * m_steerVec; - if (m_lockzvel) newvel.z() = 0.0f; else diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index d10e51a491a..b42200783e4 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -54,19 +54,20 @@ KX_VehicleWrapper::~KX_VehicleWrapper() #ifdef WITH_PYTHON -static bool raise_exc_wheel(PHY_IVehicle* vehicle, int i, const char *method) +static bool raise_exc_wheel(PHY_IVehicle *vehicle, int i, const char *method) { - if ( i < 0 || i >= vehicle->GetNumWheels() ) { + if (i < 0 || i >= vehicle->GetNumWheels()) { PyErr_Format(PyExc_ValueError, - "%s(...): wheel index %d out of range (0 to %d).", method, i, vehicle->GetNumWheels()-1); - return -1; - } else { - return 0; + "%s(...): wheel index %d out of range (0 to %d).", method, i, vehicle->GetNumWheels() - 1); + return true; + } + else { + return false; } } #define WHEEL_INDEX_CHECK_OR_RETURN(i, method) \ - if (raise_exc_wheel(m_vehicle, i, method) == -1) { return NULL; } (void)0 + if (raise_exc_wheel(m_vehicle, i, method)) {return NULL;} (void)0 PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) @@ -86,8 +87,6 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) if (gameOb->GetSGNode()) { - PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode()); - MT_Vector3 attachPos,attachDir,attachAxle; if(!PyVecTo(pylistPos,attachPos)) { PyErr_SetString(PyExc_AttributeError, @@ -114,6 +113,7 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) return NULL; } + PHY_IMotionState *motionState = new KX_MotionState(gameOb->GetSGNode()); m_vehicle->AddWheel(motionState,attachPos,attachDir,attachAxle,suspensionRestLength,wheelRadius,hasSteering); } diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp index 444d6b0771b..8678b058761 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.cpp +++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp @@ -31,8 +31,464 @@ #include "KX_WorldInfo.h" +#include "KX_PythonInit.h" +#include "KX_PyMath.h" +#include "RAS_IRasterizer.h" +#include "GPU_material.h" + +/* This little block needed for linking to Blender... */ +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +/* This list includes only data type definitions */ +#include "DNA_scene_types.h" +#include "DNA_world_types.h" + +#include "BLI_math.h" + +#include "BKE_global.h" +#include "BKE_scene.h" +/* end of blender include block */ + + +KX_WorldInfo::KX_WorldInfo(Scene *blenderscene, World *blenderworld) +{ + if (blenderworld) { + m_name = blenderworld->id.name + 2; + m_do_color_management = BKE_scene_check_color_management_enabled(blenderscene); + m_hasworld = true; + m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false); + m_misttype = blenderworld->mistype; + m_miststart = blenderworld->miststa; + m_mistdistance = blenderworld->mistdist; + m_mistintensity = blenderworld->misi; + setMistColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); + setBackColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); + setAmbientColor(blenderworld->ambr, blenderworld->ambg, blenderworld->ambb); + } + else { + m_hasworld = false; + } +} KX_WorldInfo::~KX_WorldInfo() { } +const STR_String& KX_WorldInfo::GetName() +{ + return m_name; +} + +bool KX_WorldInfo::hasWorld() +{ + return m_hasworld; +} + +void KX_WorldInfo::setBackColor(float r, float g, float b) +{ + m_backgroundcolor[0] = r; + m_backgroundcolor[1] = g; + m_backgroundcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_backgroundcolor, m_backgroundcolor); + } + else { + copy_v3_v3(m_con_backgroundcolor, m_backgroundcolor); + } +} + +const float *KX_WorldInfo::getBackColor(void) const +{ + return m_backgroundcolor; +} + +void KX_WorldInfo::setMistType(short type) +{ + m_misttype = type; +} + +void KX_WorldInfo::setUseMist(bool enable) +{ + m_hasmist = enable; +} + +void KX_WorldInfo::setMistStart(float d) +{ + m_miststart = d; +} + +void KX_WorldInfo::setMistDistance(float d) +{ + m_mistdistance = d; +} + +void KX_WorldInfo::setMistIntensity(float intensity) +{ + m_mistintensity = intensity; +} +void KX_WorldInfo::setMistColor(float r, float g, float b) +{ + m_mistcolor[0] = r; + m_mistcolor[1] = g; + m_mistcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_mistcolor, m_mistcolor); + } + else { + copy_v3_v3(m_con_mistcolor, m_mistcolor); + } +} + +void KX_WorldInfo::setAmbientColor(float r, float g, float b) +{ + m_ambientcolor[0] = r; + m_ambientcolor[1] = g; + m_ambientcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_ambientcolor, m_ambientcolor); + } + else { + copy_v3_v3(m_con_ambientcolor, m_ambientcolor); + } +} + +void KX_WorldInfo::UpdateBackGround() +{ + if (m_hasworld) { + RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); + + if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetBackColor(m_con_backgroundcolor); + GPU_horizon_update_color(m_backgroundcolor); + } + } +} + +void KX_WorldInfo::UpdateWorldSettings() +{ + if (m_hasworld) { + RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); + + if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetAmbientColor(m_con_ambientcolor); + GPU_ambient_update_color(m_ambientcolor); + + if (m_hasmist) { + m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_con_mistcolor); + GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor); + m_rasterizer->EnableFog(true); + GPU_mist_update_enable(true); + } + else { + m_rasterizer->EnableFog(false); + GPU_mist_update_enable(false); + } + } + } +} + +#ifdef WITH_PYTHON + +/* ------------------------------------------------------------------------- + * Python functions + * ------------------------------------------------------------------------- */ +PyObject *KX_WorldInfo::py_repr(void) +{ + return PyUnicode_From_STR_String(GetName()); +} + +/* ------------------------------------------------------------------------- + * Python Integration Hooks + * ------------------------------------------------------------------------- */ +PyTypeObject KX_WorldInfo::Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "KX_WorldInfo", + sizeof(PyObjectPlus_Proxy), + 0, + py_base_dealloc, + 0, + 0, + 0, + 0, + py_base_repr, + 0,0,0,0,0,0,0,0,0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new +}; + +PyMethodDef KX_WorldInfo::Methods[] = { + {NULL,NULL} /* Sentinel */ +}; + +PyAttributeDef KX_WorldInfo::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RW("mistEnable", KX_WorldInfo, m_hasmist), + KX_PYATTRIBUTE_FLOAT_RW("mistStart", 0.0f, 10000.0f, KX_WorldInfo, m_miststart), + KX_PYATTRIBUTE_FLOAT_RW("mistDistance", 0.001f, 10000.0f, KX_WorldInfo, m_mistdistance), + KX_PYATTRIBUTE_FLOAT_RW("mistIntensity", 0.0f, 1.0f, KX_WorldInfo, m_mistintensity), + KX_PYATTRIBUTE_SHORT_RW("mistType", 0, 2, true, KX_WorldInfo, m_misttype), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_LINEAR", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_INV_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RW_FUNCTION("mistColor", KX_WorldInfo, pyattr_get_mist_color, pyattr_set_mist_color), + KX_PYATTRIBUTE_RW_FUNCTION("backgroundColor", KX_WorldInfo, pyattr_get_back_color, pyattr_set_back_color), + KX_PYATTRIBUTE_RW_FUNCTION("ambientColor", KX_WorldInfo, pyattr_get_ambient_color, pyattr_set_ambient_color), + { NULL } /* Sentinel */ +}; + +/* Attribute get/set functions */ + +#ifdef USE_MATHUTILS + +/*----------------------mathutils callbacks ----------------------------*/ + +/* subtype */ +#define MATHUTILS_VEC_CB_MIST_COLOR 1 +#define MATHUTILS_VEC_CB_BACK_COLOR 2 +#define MATHUTILS_VEC_CB_AMBIENT_COLOR 3 + +static unsigned char mathutils_world_vector_cb_index = -1; /* index for our callbacks */ + +static int mathutils_world_generic_check(BaseMathObject *bmo) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + if (self == NULL) + return -1; + + return 0; +} + +static int mathutils_world_vector_get(BaseMathObject *bmo, int subtype) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + copy_v3_v3(bmo->data, self->m_mistcolor); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + copy_v3_v3(bmo->data, self->m_backgroundcolor); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + copy_v3_v3(bmo->data, self->m_ambientcolor); + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_set(BaseMathObject *bmo, int subtype) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + self->setMistColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + self->setBackColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + self->setAmbientColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_get_index(BaseMathObject *bmo, int subtype, int index) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + { + const float *color = self->m_mistcolor; + bmo->data[index] = color[index]; + } + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + { + const float *color = self->m_backgroundcolor; + bmo->data[index] = color[index]; + } + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + { + const float *color = self->m_ambientcolor; + bmo->data[index] = color[index]; + } + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_set_index(BaseMathObject *bmo, int subtype, int index) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + float color[4]; + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + copy_v3_v3(color, self->m_mistcolor); + color[index] = bmo->data[index]; + self->setMistColor(color[0], color[1], color[2]); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + copy_v3_v3(color, self->m_backgroundcolor); + color[index] = bmo->data[index]; + self->setBackColor(color[0], color[1], color[2]); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + copy_v3_v3(color, self->m_ambientcolor); + color[index] = bmo->data[index]; + self->setAmbientColor(color[0], color[1], color[2]); + break; + default: + return -1; + } + return 0; +} + +static Mathutils_Callback mathutils_world_vector_cb = { + mathutils_world_generic_check, + mathutils_world_vector_get, + mathutils_world_vector_set, + mathutils_world_vector_get_index, + mathutils_world_vector_set_index +}; + +void KX_WorldInfo_Mathutils_Callback_Init() +{ + // register mathutils callbacks, ok to run more than once. + mathutils_world_vector_cb_index = Mathutils_RegisterCallback(&mathutils_world_vector_cb); +} +#endif // USE_MATHUTILS + + +PyObject *KX_WorldInfo::pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + PyObject *retvalue; + + const char* type = attrdef->m_name; + + if (!strcmp(type, "KX_MIST_QUADRATIC")) { + retvalue = PyLong_FromLong(KX_MIST_QUADRATIC); + } + else if (!strcmp(type, "KX_MIST_LINEAR")) { + retvalue = PyLong_FromLong(KX_MIST_LINEAR); + } + else if (!strcmp(type, "KX_MIST_INV_QUADRATIC")) { + retvalue = PyLong_FromLong(KX_MIST_INV_QUADRATIC); + } + else { + /* should never happen */ + PyErr_SetString(PyExc_TypeError, "invalid mist type"); + retvalue = NULL; + } + + return retvalue; +} + +PyObject *KX_WorldInfo::pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_MIST_COLOR); +#else + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + return PyObjectFrom(MT_Vector3(self->m_mistcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setMistColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +PyObject *KX_WorldInfo::pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_BACK_COLOR); +#else + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + return PyObjectFrom(MT_Vector3(self->m_backgroundcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setBackColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +PyObject *KX_WorldInfo::pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_AMBIENT_COLOR); +#else + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + return PyObjectFrom(MT_Vector3(self->m_ambientcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setAmbientColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +#endif /* WITH_PYTHON */ diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 90b16fe1242..0e8fe3c730a 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -33,41 +33,77 @@ #define __KX_WORLDINFO_H__ #include "MT_Scalar.h" +#include "KX_KetsjiEngine.h" +#include "PyObjectPlus.h" #ifdef WITH_CXX_GUARDEDALLOC #include "MEM_guardedalloc.h" #endif -class MT_CmMatrix4x4; +#ifdef USE_MATHUTILS +void KX_WorldInfo_Mathutils_Callback_Init(void); +#endif + +struct Scene; +struct World; -class KX_WorldInfo +class KX_WorldInfo : public PyObjectPlus { -public: - KX_WorldInfo() {} - virtual ~KX_WorldInfo(); + Py_Header - virtual bool hasWorld() = 0; - virtual bool hasMist() = 0; - virtual float getBackColorRed() = 0; - virtual float getBackColorGreen() = 0; - virtual float getBackColorBlue() = 0; - virtual float getMistStart() = 0; - virtual float getMistDistance() = 0; - virtual float getMistColorRed() = 0; - virtual float getMistColorGreen() = 0; - virtual float getMistColorBlue() = 0; + STR_String m_name; + bool m_do_color_management; + bool m_hasworld; + bool m_hasmist; + short m_misttype; + float m_miststart; + float m_mistdistance; + float m_mistintensity; + float m_mistcolor[3]; + float m_backgroundcolor[3]; + float m_ambientcolor[3]; + float m_con_mistcolor[3]; + float m_con_backgroundcolor[3]; + float m_con_ambientcolor[3]; - virtual float getAmbientColorRed() = 0; - virtual float getAmbientColorGreen() = 0; - virtual float getAmbientColorBlue() = 0; +public: + /** + * Mist options + */ + enum MistType { + KX_MIST_QUADRATIC, + KX_MIST_LINEAR, + KX_MIST_INV_QUADRATIC, + }; + + KX_WorldInfo(Scene *blenderscene, World *blenderworld); + ~KX_WorldInfo(); - virtual void setBackColor(float, float, float) = 0; - virtual void setMistStart(float) = 0; - virtual void setMistDistance(float) = 0; - virtual void setMistColorRed(float) = 0; - virtual void setMistColorGreen(float) = 0; - virtual void setMistColorBlue(float) = 0; + const STR_String &GetName(); + bool hasWorld(); + void setUseMist(bool enable); + void setMistType(short type); + void setMistStart(float d); + void setMistDistance(float d); + void setMistIntensity(float intensity); + void setMistColor(float r, float g, float b); + void setBackColor(float r, float g, float b); + const float *getBackColor() const; + void setAmbientColor(float r, float g, float b); + void UpdateBackGround(); + void UpdateWorldSettings(); +#ifdef WITH_PYTHON + /* attributes */ + static PyObject *pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + virtual PyObject *py_repr(void); +#endif #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_WorldInfo") diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.cpp b/source/gameengine/Ketsji/KX_WorldIpoController.cpp index 7f83a155643..1123e07ebcc 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.cpp +++ b/source/gameengine/Ketsji/KX_WorldIpoController.cpp @@ -33,6 +33,8 @@ #include "KX_WorldIpoController.h" #include "KX_ScalarInterpolator.h" #include "KX_WorldInfo.h" +#include "KX_PythonInit.h" +#include "KX_Scene.h" #if defined(_WIN64) typedef unsigned __int64 uint_ptr; @@ -42,31 +44,36 @@ typedef unsigned long uint_ptr; bool KX_WorldIpoController::Update(double currentTime) { - if (m_modified) - { + if (m_modified) { T_InterpolatorList::iterator i; for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { - (*i)->Execute(m_ipotime);//currentTime); + (*i)->Execute(m_ipotime); } - /* TODO, this will crash! */ - KX_WorldInfo *world = NULL; + KX_WorldInfo *world = KX_GetActiveScene()->GetWorldInfo(); if (m_modify_mist_start) { world->setMistStart(m_mist_start); } - if (m_modify_mist_color) { - world->setMistColorRed(m_mist_rgb[0]); - world->setMistColorGreen(m_mist_rgb[1]); - world->setMistColorBlue(m_mist_rgb[2]); - } - if (m_modify_mist_dist) { world->setMistDistance(m_mist_dist); } - m_modified=false; + if (m_modify_mist_intensity) { + world->setMistIntensity(m_mist_intensity); + } + + if (m_modify_horizon_color) { + world->setBackColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]); + world->setMistColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]); + } + + if (m_modify_ambient_color) { + world->setAmbientColor(m_ambi_rgb[0], m_ambi_rgb[1], m_ambi_rgb[2]); + } + + m_modified = false; } return false; } diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.h b/source/gameengine/Ketsji/KX_WorldIpoController.h index 63983b3129b..704f421573e 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.h +++ b/source/gameengine/Ketsji/KX_WorldIpoController.h @@ -39,24 +39,30 @@ class KX_WorldIpoController : public SG_Controller { public: - MT_Scalar m_mist_rgb[3]; MT_Scalar m_mist_start; MT_Scalar m_mist_dist; + MT_Scalar m_mist_intensity; + MT_Scalar m_hori_rgb[3]; + MT_Scalar m_ambi_rgb[3]; private: T_InterpolatorList m_interpolators; - unsigned short m_modify_mist_color : 1; unsigned short m_modify_mist_start : 1; unsigned short m_modify_mist_dist : 1; + unsigned short m_modify_mist_intensity : 1; + unsigned short m_modify_horizon_color : 1; + unsigned short m_modify_ambient_color : 1; bool m_modified; double m_ipotime; public: KX_WorldIpoController() : - m_modify_mist_color(false), m_modify_mist_start(false), m_modify_mist_dist(false), + m_modify_mist_intensity(false), + m_modify_horizon_color(false), + m_modify_ambient_color(false), m_modified(true), m_ipotime(0.0) {} @@ -76,14 +82,22 @@ public: m_modify_mist_start = modify; } - void SetModifyMistColor(bool modify) { - m_modify_mist_color = modify; - } - void SetModifyMistDist(bool modify) { m_modify_mist_dist = modify; } + void SetModifyMistIntensity(bool modify) { + m_modify_mist_intensity = modify; + } + + void SetModifyHorizonColor(bool modify) { + m_modify_horizon_color = modify; + } + + void SetModifyAmbientColor(bool modify) { + m_modify_ambient_color = modify; + } + void SetOption( int option, diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 44c4e284e7c..8ea2b4f299d 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -39,7 +39,6 @@ subject to the following restrictions: #include "LinearMath/btConvexHull.h" #include "BulletCollision/Gimpact/btGImpactShape.h" - #include "BulletSoftBody/btSoftRigidDynamicsWorld.h" #include "DNA_mesh_types.h" @@ -65,7 +64,6 @@ extern bool gDisableDeactivation; float gLinearSleepingTreshold; float gAngularSleepingTreshold; - BlenderBulletCharacterController::BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight) : btKinematicCharacterController(ghost,shape,stepHeight,2), m_motionState(motionState), @@ -118,6 +116,18 @@ const btVector3& BlenderBulletCharacterController::getWalkDirection() return m_walkDirection; } +bool CleanPairCallback::processOverlap(btBroadphasePair &pair) +{ + if ((pair.m_pProxy0 == m_cleanProxy) || (pair.m_pProxy1 == m_cleanProxy)) { + m_pairCache->cleanOverlappingPair(pair, m_dispatcher); + CcdPhysicsController *ctrl0 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy0->m_clientObject)->getUserPointer()); + CcdPhysicsController *ctrl1 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy1->m_clientObject)->getUserPointer()); + ctrl0->GetCollisionObject()->activate(false); + ctrl1->GetCollisionObject()->activate(false); + } + return false; +} + CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) :m_cci(ci) { @@ -588,20 +598,13 @@ void CcdPhysicsController::CreateRigidbody() static void DeleteBulletShape(btCollisionShape* shape, bool free) { - if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) - { - // shapes based on meshes use an interface that contains the vertices. - btTriangleMeshShape* meshShape = static_cast<btTriangleMeshShape*>(shape); - btStridingMeshInterface* meshInterface = meshShape->getMeshInterface(); - if (meshInterface) - delete meshInterface; - } - else if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) - { - btGImpactMeshShape* meshShape = static_cast<btGImpactMeshShape*>(shape); - btStridingMeshInterface* meshInterface = meshShape->getMeshInterface(); - if (meshInterface) - delete meshInterface; + if (shape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) { + /* If we use Bullet scaled shape (btScaledBvhTriangleMeshShape) we have to + * free the child of the unscaled shape (btTriangleMeshShape) here. + */ + btTriangleMeshShape *meshShape = ((btScaledBvhTriangleMeshShape *)shape)->getChildShape(); + if (meshShape) + delete meshShape; } if (free) { delete shape; @@ -634,48 +637,41 @@ bool CcdPhysicsController::DeleteControllerShape( ) bool CcdPhysicsController::ReplaceControllerShape(btCollisionShape *newShape) { - - /* Note, deleting the previous collision shape must be done already */ - /* if (m_collisionShape) DeleteControllerShape(); */ + if (m_collisionShape) + DeleteControllerShape(); + + // If newShape is NULL it means to create a new Bullet shape. + if (!newShape) + newShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin, m_cci.m_bGimpact, !m_cci.m_bSoft); m_object->setCollisionShape(newShape); - m_collisionShape= newShape; - m_cci.m_collisionShape= newShape; - - if (GetSoftBody()) { + m_collisionShape = newShape; + m_cci.m_collisionShape = newShape; + + btSoftBody *softBody = GetSoftBody(); + if (softBody) { + btSoftRigidDynamicsWorld *world = GetPhysicsEnvironment()->GetDynamicsWorld(); + // remove the old softBody + world->removeSoftBody(softBody); + // soft body must be recreated - m_cci.m_physicsEnv->RemoveCcdPhysicsController(this); delete m_object; m_object = NULL; // force complete reinitialization m_softbodyMappingDone = false; m_prototypeTransformInitialized = false; m_softBodyTransformInitialized = false; + CreateSoftbody(); assert(m_object); - // reinsert the new body - m_cci.m_physicsEnv->AddCcdPhysicsController(this); - } - - /* Copied from CcdPhysicsEnvironment::addCcdPhysicsController() */ - - /* without this, an object can rest on the old physics mesh - * and not move to account for the physics mesh, even with 'nosleep' */ - btSoftRigidDynamicsWorld* dw= GetPhysicsEnvironment()->GetDynamicsWorld(); - btCollisionObjectArray &obarr= dw->getCollisionObjectArray(); - btCollisionObject *ob; - btBroadphaseProxy* proxy; - - for (int i= 0; i < obarr.size(); i++) { - ob= obarr[i]; - if (ob->getCollisionShape() == newShape) { - proxy = ob->getBroadphaseHandle(); - - if (proxy) - dw->getPairCache()->cleanProxyFromPairs(proxy,dw->getDispatcher()); - } + + btSoftBody *newSoftBody = GetSoftBody(); + // set the user + newSoftBody->setUserPointer(this); + // add the new softbody + world->addSoftBody(newSoftBody); } - + return true; } @@ -850,36 +846,6 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta m_cci.m_physicsEnv->AddCcdPhysicsController(this); -/* SM_Object* dynaparent=0; - SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl; - - if (sumoparentctrl) - { - dynaparent = sumoparentctrl->GetSumoObject(); - } - - SM_Object* orgsumoobject = m_sumoObj; - - - m_sumoObj = new SM_Object( - orgsumoobject->getShapeHandle(), - orgsumoobject->getMaterialProps(), - orgsumoobject->getShapeProps(), - dynaparent); - - m_sumoObj->setRigidBody(orgsumoobject->isRigidBody()); - - m_sumoObj->setMargin(orgsumoobject->getMargin()); - m_sumoObj->setPosition(orgsumoobject->getPosition()); - m_sumoObj->setOrientation(orgsumoobject->getOrientation()); - //if it is a dyna, register for a callback - m_sumoObj->registerCallback(*this); - - m_sumoScene->add(* (m_sumoObj)); - */ - - - } void CcdPhysicsController::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment *env) @@ -1082,6 +1048,25 @@ void CcdPhysicsController::ResolveCombinedVelocities(float linvelX,float linvel { } +void CcdPhysicsController::RefreshCollisions() +{ + // the object is in an inactive layer so it's useless to update it and can cause problems + if (!GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this)) + return; + + btSoftRigidDynamicsWorld *dw = GetPhysicsEnvironment()->GetDynamicsWorld(); + btBroadphaseProxy *proxy = m_object->getBroadphaseHandle(); + btDispatcher *dispatcher = dw->getDispatcher(); + btOverlappingPairCache *pairCache = dw->getPairCache(); + + CleanPairCallback cleanPairs(proxy, pairCache, dispatcher); + pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher); + + // Forcibly recreate the physics object + btBroadphaseProxy* handle = m_object->getBroadphaseHandle(); + GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, GetMass(), m_object->getCollisionFlags(), handle->m_collisionFilterGroup, handle->m_collisionFilterMask); +} + void CcdPhysicsController::SuspendDynamics(bool ghost) { btRigidBody *body = GetRigidBody(); @@ -1546,8 +1531,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child) const btCollisionShape* childShape = childBody->getCollisionShape(); if (!rootShape || !childShape || - rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE || - childShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE) return; btCompoundShape* compoundShape = (btCompoundShape*)rootShape; // compute relative transformation between parent and child @@ -1597,7 +1581,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child) // must update the broadphase cache, GetPhysicsEnvironment()->RefreshCcdPhysicsController(this); // remove the children - GetPhysicsEnvironment()->DisableCcdPhysicsController(childCtrl); + GetPhysicsEnvironment()->RemoveCcdPhysicsController(childCtrl); } /* Reverse function of the above, it will remove a shape from a compound shape @@ -1653,7 +1637,7 @@ void CcdPhysicsController::RemoveCompoundChild(PHY_IPhysicsController* child) // must update the broadphase cache, GetPhysicsEnvironment()->RefreshCcdPhysicsController(this); // reactivate the children - GetPhysicsEnvironment()->EnableCcdPhysicsController(childCtrl); + GetPhysicsEnvironment()->AddCcdPhysicsController(childCtrl); } PHY_IPhysicsController* CcdPhysicsController::GetReplica() @@ -1713,33 +1697,50 @@ PHY_IPhysicsController* CcdPhysicsController::GetReplicaForSensors() * 2) from_gameobj - creates the phys mesh from the DerivedMesh where possible, else the RAS_MeshObject * 3) this - update the phys mesh from DerivedMesh or RAS_MeshObject * - * Most of the logic behind this is in shapeInfo->UpdateMesh(...) + * Most of the logic behind this is in m_shapeInfo->UpdateMesh(...) */ bool CcdPhysicsController::ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject *from_meshobj) { - CcdShapeConstructionInfo *shapeInfo; - - shapeInfo = this->GetShapeInfo(); - - if (shapeInfo->m_shapeType != PHY_SHAPE_MESH/* || spc->GetSoftBody()*/) + if (m_shapeInfo->m_shapeType != PHY_SHAPE_MESH) return false; - this->DeleteControllerShape(); - - if (from_gameobj==NULL && from_meshobj==NULL) - from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)this->GetNewClientInfo()); + if (!from_gameobj && !from_meshobj) + from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)GetNewClientInfo()); /* updates the arrays used for making the new bullet mesh */ - shapeInfo->UpdateMesh(from_gameobj, from_meshobj); + m_shapeInfo->UpdateMesh(from_gameobj, from_meshobj); /* create the new bullet mesh */ - CcdConstructionInfo& cci = this->GetConstructionInfo(); - btCollisionShape* bm= shapeInfo->CreateBulletShape(cci.m_margin, cci.m_bGimpact, !cci.m_bSoft); + GetPhysicsEnvironment()->UpdateCcdPhysicsControllerShape(m_shapeInfo); - this->ReplaceControllerShape(bm); return true; } +void CcdPhysicsController::ReplicateConstraints(KX_GameObject *replica, std::vector<KX_GameObject*> constobj) +{ + if (replica->GetConstraints().size() == 0 || !replica->GetPhysicsController()) + return; + + PHY_IPhysicsEnvironment *physEnv = GetPhysicsEnvironment(); + + vector<bRigidBodyJointConstraint*> constraints = replica->GetConstraints(); + vector<bRigidBodyJointConstraint*>::iterator consit; + + /* Object could have some constraints, iterate over all of theme to ensure that every constraint is recreated. */ + for (consit = constraints.begin(); consit != constraints.end(); ++consit) { + /* Try to find the constraint targets in the list of group objects. */ + bRigidBodyJointConstraint *dat = (*consit); + vector<KX_GameObject*>::iterator memit; + for (memit = constobj.begin(); memit != constobj.end(); ++memit) { + KX_GameObject *member = (*memit); + /* If the group member is the actual target for the constraint. */ + if (dat->tar->id.name + 2 == member->GetName() && member->GetPhysicsController()) + physEnv->SetupObjectConstraints(replica, member, dat); + } + } + +} + /////////////////////////////////////////////////////////// ///A small utility class, DefaultMotionState /// @@ -1821,7 +1822,7 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes return NULL; } -bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool polytope) +bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject *meshobj, DerivedMesh *dm, bool polytope) { int numpolys, numverts; @@ -1833,7 +1834,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool free_dm = false; // No mesh object or mesh has no polys - if (!meshobj || meshobj->HasColliderPolygon()==false) { + if (!meshobj || !meshobj->HasColliderPolygon()) { m_vertexArray.clear(); m_polygonIndexArray.clear(); m_triFaceArray.clear(); @@ -1856,80 +1857,83 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, /* double lookup */ const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if (index_mf_to_mpoly == NULL) { + if (!index_mf_to_mpoly) { index_mp_to_orig = NULL; } m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; /* Convert blender geometry into bullet mesh, need these vars for mapping */ - vector<bool> vert_tag_array(numverts, false); - unsigned int tot_bt_verts= 0; + std::vector<bool> vert_tag_array(numverts, false); + unsigned int tot_bt_verts = 0; - if (polytope) - { + if (polytope) { // Tag verts we're using - for (int p2=0; p2<numpolys; p2++) - { - MFace* mf = &mface[p2]; + for (int p2 = 0; p2 < numpolys; p2++) { + MFace *mf = &mface[p2]; const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon* poly = meshobj->GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collision flag set - if (poly->IsCollider()) - { - if (vert_tag_array[mf->v1] == false) {vert_tag_array[mf->v1] = true; tot_bt_verts++;} - if (vert_tag_array[mf->v2] == false) {vert_tag_array[mf->v2] = true; tot_bt_verts++;} - if (vert_tag_array[mf->v3] == false) {vert_tag_array[mf->v3] = true; tot_bt_verts++;} - if (mf->v4 && vert_tag_array[mf->v4] == false) {vert_tag_array[mf->v4] = true; tot_bt_verts++;} + if (poly->IsCollider()) { + if (!vert_tag_array[mf->v1]) { + vert_tag_array[mf->v1] = true; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v2]) { + vert_tag_array[mf->v2] = true; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v3]) { + vert_tag_array[mf->v3] = true; + tot_bt_verts++; + } + if (mf->v4 && !vert_tag_array[mf->v4]) { + vert_tag_array[mf->v4] = true; + tot_bt_verts++; + } } } - + /* Can happen with ngons */ if (!tot_bt_verts) { goto cleanup_empty_mesh; } - m_vertexArray.resize(tot_bt_verts*3); + m_vertexArray.resize(tot_bt_verts * 3); - btScalar *bt= &m_vertexArray[0]; + btScalar *bt = &m_vertexArray[0]; - for (int p2=0; p2<numpolys; p2++) - { - MFace* mf = &mface[p2]; + for (int p2 = 0; p2 < numpolys; p2++) { + MFace *mf = &mface[p2]; const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon* poly= meshobj->GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { - if (vert_tag_array[mf->v1]==true) - { - const float* vtx = mvert[mf->v1].co; + if (poly->IsCollider()) { + if (vert_tag_array[mf->v1]) { + const float *vtx = mvert[mf->v1].co; vert_tag_array[mf->v1] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; } - if (vert_tag_array[mf->v2]==true) - { - const float* vtx = mvert[mf->v2].co; + if (vert_tag_array[mf->v2]) { + const float *vtx = mvert[mf->v2].co; vert_tag_array[mf->v2] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; } - if (vert_tag_array[mf->v3]==true) - { - const float* vtx = mvert[mf->v3].co; + if (vert_tag_array[mf->v3]) { + const float *vtx = mvert[mf->v3].co; vert_tag_array[mf->v3] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; } - if (mf->v4 && vert_tag_array[mf->v4]==true) - { - const float* vtx = mvert[mf->v4].co; + if (mf->v4 && vert_tag_array[mf->v4]) { + const float *vtx = mvert[mf->v4].co; vert_tag_array[mf->v4] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; @@ -1939,28 +1943,38 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, } } else { - unsigned int tot_bt_tris= 0; - vector<int> vert_remap_array(numverts, 0); - + unsigned int tot_bt_tris = 0; + std::vector<int> vert_remap_array(numverts, 0); + // Tag verts we're using - for (int p2=0; p2<numpolys; p2++) - { - MFace* mf = &mface[p2]; + for (int p2 = 0; p2 < numpolys; p2++) { + MFace *mf = &mface[p2]; const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon* poly= meshobj->GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collision flag set - if (poly->IsCollider()) - { - if (vert_tag_array[mf->v1]==false) - {vert_tag_array[mf->v1] = true;vert_remap_array[mf->v1] = tot_bt_verts;tot_bt_verts++;} - if (vert_tag_array[mf->v2]==false) - {vert_tag_array[mf->v2] = true;vert_remap_array[mf->v2] = tot_bt_verts;tot_bt_verts++;} - if (vert_tag_array[mf->v3]==false) - {vert_tag_array[mf->v3] = true;vert_remap_array[mf->v3] = tot_bt_verts;tot_bt_verts++;} - if (mf->v4 && vert_tag_array[mf->v4]==false) - {vert_tag_array[mf->v4] = true;vert_remap_array[mf->v4] = tot_bt_verts;tot_bt_verts++;} - tot_bt_tris += (mf->v4 ? 2:1); /* a quad or a tri */ + if (poly->IsCollider()) { + if (!vert_tag_array[mf->v1]) { + vert_tag_array[mf->v1] = true; + vert_remap_array[mf->v1] = tot_bt_verts; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v2]) { + vert_tag_array[mf->v2] = true; + vert_remap_array[mf->v2] = tot_bt_verts; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v3]) { + vert_tag_array[mf->v3] = true; + vert_remap_array[mf->v3] = tot_bt_verts; + tot_bt_verts++; + } + if (mf->v4 && !vert_tag_array[mf->v4]) { + vert_tag_array[mf->v4] = true; + vert_remap_array[mf->v4] = tot_bt_verts; + tot_bt_verts++; + } + tot_bt_tris += (mf->v4 ? 2 : 1); /* a quad or a tri */ } } @@ -1969,43 +1983,39 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, goto cleanup_empty_mesh; } - m_vertexArray.resize(tot_bt_verts*3); + m_vertexArray.resize(tot_bt_verts * 3); m_polygonIndexArray.resize(tot_bt_tris); - m_triFaceArray.resize(tot_bt_tris*3); - btScalar *bt= &m_vertexArray[0]; - int *poly_index_pt= &m_polygonIndexArray[0]; - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + btScalar *bt = &m_vertexArray[0]; + int *poly_index_pt = &m_polygonIndexArray[0]; + int *tri_pt = &m_triFaceArray[0]; UVco *uv_pt = NULL; - if (tface) - { - m_triFaceUVcoArray.resize(tot_bt_tris*3); + if (tface) { + m_triFaceUVcoArray.resize(tot_bt_tris * 3); uv_pt = &m_triFaceUVcoArray[0]; - } - else + } + else m_triFaceUVcoArray.clear(); - for (int p2=0; p2<numpolys; p2++) - { - MFace* mf = &mface[p2]; - MTFace* tf = (tface) ? &tface[p2] : NULL; + for (int p2 = 0; p2 < numpolys; p2++) { + MFace *mf = &mface[p2]; + MTFace *tf = (tface) ? &tface[p2] : NULL; const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon* poly= meshobj->GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { - MVert *v1= &mvert[mf->v1]; - MVert *v2= &mvert[mf->v2]; - MVert *v3= &mvert[mf->v3]; + if (poly->IsCollider()) { + MVert *v1 = &mvert[mf->v1]; + MVert *v2 = &mvert[mf->v2]; + MVert *v3 = &mvert[mf->v3]; // the face indices tri_pt[0] = vert_remap_array[mf->v1]; tri_pt[1] = vert_remap_array[mf->v2]; tri_pt[2] = vert_remap_array[mf->v3]; - tri_pt= tri_pt+3; - if (tf) - { + tri_pt = tri_pt + 3; + if (tf) { uv_pt[0].uv[0] = tf->uv[0][0]; uv_pt[0].uv[1] = tf->uv[0][1]; uv_pt[1].uv[0] = tf->uv[1][0]; @@ -2020,19 +2030,19 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, poly_index_pt++; // the vertex location - if (vert_tag_array[mf->v1]==true) { /* *** v1 *** */ + if (vert_tag_array[mf->v1]) { /* *** v1 *** */ vert_tag_array[mf->v1] = false; *bt++ = v1->co[0]; *bt++ = v1->co[1]; *bt++ = v1->co[2]; } - if (vert_tag_array[mf->v2]==true) { /* *** v2 *** */ + if (vert_tag_array[mf->v2]) { /* *** v2 *** */ vert_tag_array[mf->v2] = false; *bt++ = v2->co[0]; *bt++ = v2->co[1]; *bt++ = v2->co[2]; } - if (vert_tag_array[mf->v3]==true) { /* *** v3 *** */ + if (vert_tag_array[mf->v3]) { /* *** v3 *** */ vert_tag_array[mf->v3] = false; *bt++ = v3->co[0]; *bt++ = v3->co[1]; @@ -2041,12 +2051,12 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, if (mf->v4) { - MVert *v4= &mvert[mf->v4]; + MVert *v4 = &mvert[mf->v4]; tri_pt[0] = vert_remap_array[mf->v1]; tri_pt[1] = vert_remap_array[mf->v3]; tri_pt[2] = vert_remap_array[mf->v4]; - tri_pt= tri_pt+3; + tri_pt = tri_pt + 3; if (tf) { uv_pt[0].uv[0] = tf->uv[0][0]; @@ -2063,7 +2073,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, poly_index_pt++; // the vertex location - if (vert_tag_array[mf->v4] == true) { /* *** v4 *** */ + if (vert_tag_array[mf->v4]) { /* *** v4 *** */ vert_tag_array[mf->v4] = false; *bt++ = v4->co[0]; *bt++ = v4->co[1]; @@ -2077,27 +2087,27 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, /* If this ever gets confusing, print out an OBJ file for debugging */ #if 0 printf("# vert count %d\n", m_vertexArray.size()); - for (i=0; i<m_vertexArray.size(); i+=1) { + for (i = 0; i < m_vertexArray.size(); i += 1) { printf("v %.6f %.6f %.6f\n", m_vertexArray[i].x(), m_vertexArray[i].y(), m_vertexArray[i].z()); } printf("# face count %d\n", m_triFaceArray.size()); - for (i=0; i<m_triFaceArray.size(); i+=3) { - printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1); + for (i = 0; i < m_triFaceArray.size(); i += 3) { + printf("f %d %d %d\n", m_triFaceArray[i] + 1, m_triFaceArray[i + 1] + 1, m_triFaceArray[i + 2] + 1); } #endif } #if 0 - if (validpolys==false) + if (validpolys == false) { // should not happen m_shapeType = PHY_SHAPE_NONE; return false; } #endif - + m_meshObject = meshobj; if (free_dm) { dm->release(dm); @@ -2105,10 +2115,9 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, } // sharing only on static mesh at present, if you change that, you must also change in FindMesh - if (!polytope && !dm) - { + if (!polytope && !dm) { // triangle shape can be shared, store the mesh object in the map - m_meshShapeMap.insert(std::pair<RAS_MeshObject*,CcdShapeConstructionInfo*>(meshobj,this)); + m_meshShapeMap.insert(std::pair<RAS_MeshObject *, CcdShapeConstructionInfo *>(meshobj, this)); } return true; @@ -2131,51 +2140,50 @@ cleanup_empty_mesh: /* Updates the arrays used by CreateBulletShape(), * take care that recalcLocalAabb() runs after CreateBulletShape is called. * */ -bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RAS_MeshObject* meshobj) +bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RAS_MeshObject *meshobj) { int numpolys; int numverts; - unsigned int tot_bt_tris= 0; - unsigned int tot_bt_verts= 0; + unsigned int tot_bt_tris = 0; + unsigned int tot_bt_verts = 0; int i, j; int v_orig; /* Use for looping over verts in a face as a try or 2 tris */ - const int quad_verts[7]= {0,1,2, 0,2,3, -1}; - const int tri_verts[4]= {0,1,2, -1}; + const int quad_verts[7] = {0, 1, 2, 0, 2, 3, -1}; + const int tri_verts[4] = {0, 1, 2, -1}; const int *fv_pt; - if (gameobj==NULL && meshobj==NULL) + if (!gameobj && !meshobj) return false; - + if (m_shapeType != PHY_SHAPE_MESH) return false; - RAS_Deformer *deformer= gameobj ? gameobj->GetDeformer():NULL; - DerivedMesh* dm = NULL; + RAS_Deformer *deformer = gameobj ? gameobj->GetDeformer() : NULL; + DerivedMesh *dm = NULL; if (deformer) dm = deformer->GetPhysicsMesh(); - + /* get the mesh from the object if not defined */ - if (meshobj==NULL) { - + if (!meshobj) { /* modifier mesh */ if (dm) - meshobj= deformer->GetRasMesh(); - + meshobj = deformer->GetRasMesh(); + /* game object first mesh */ - if (meshobj==NULL) { + if (!meshobj) { if (gameobj->GetMeshCount() > 0) { - meshobj= gameobj->GetMesh(0); + meshobj = gameobj->GetMesh(0); } } } - - if (dm && deformer->GetRasMesh() == meshobj) - { /* + + if (dm && deformer->GetRasMesh() == meshobj) { + /* * Derived Mesh Update * * */ @@ -2187,41 +2195,38 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA /* double lookup */ const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if (index_mf_to_mpoly == NULL) { + const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); + if (!index_mf_to_mpoly) { index_mp_to_orig = NULL; } MFace *mf; MVert *mv; - int flen; - - if (CustomData_has_layer(&dm->faceData, CD_MTFACE)) - { + if (CustomData_has_layer(&dm->faceData, CD_MTFACE)) { MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE); MTFace *tf; - vector<bool> vert_tag_array(numverts, false); - vector<int> vert_remap_array(numverts, 0); + std::vector<bool> vert_tag_array(numverts, false); + std::vector<int> vert_remap_array(numverts, 0); + + for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) { + if (tf->mode & TF_DYNAMIC) { + int flen; - for (mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++) { - if (tf->mode & TF_DYNAMIC) - { if (mf->v4) { - tot_bt_tris+= 2; - flen= 4; - } else { + tot_bt_tris += 2; + flen = 4; + } + else { tot_bt_tris++; - flen= 3; + flen = 3; } - for (j=0; j<flen; j++) - { + for (j = 0; j < flen; j++) { v_orig = (*(&mf->v1 + j)); - if (vert_tag_array[v_orig]==false) - { + if (!vert_tag_array[v_orig]) { vert_tag_array[v_orig] = true; vert_remap_array[v_orig] = tot_bt_verts; tot_bt_verts++; @@ -2230,42 +2235,38 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA } } - m_vertexArray.resize(tot_bt_verts*3); - btScalar *bt= &m_vertexArray[0]; + m_vertexArray.resize(tot_bt_verts * 3); + btScalar *bt = &m_vertexArray[0]; - m_triFaceArray.resize(tot_bt_tris*3); - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + int *tri_pt = &m_triFaceArray[0]; - m_triFaceUVcoArray.resize(tot_bt_tris*3); - UVco *uv_pt= &m_triFaceUVcoArray[0]; + m_triFaceUVcoArray.resize(tot_bt_tris * 3); + UVco *uv_pt = &m_triFaceUVcoArray[0]; m_polygonIndexArray.resize(tot_bt_tris); - int *poly_index_pt= &m_polygonIndexArray[0]; + int *poly_index_pt = &m_polygonIndexArray[0]; - for (mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++) - { - if (tf->mode & TF_DYNAMIC) - { + for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) { + if (tf->mode & TF_DYNAMIC) { int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; if (mf->v4) { - fv_pt= quad_verts; + fv_pt = quad_verts; *poly_index_pt++ = origi; *poly_index_pt++ = origi; - flen= 4; - } else { - fv_pt= tri_verts; + } + else { + fv_pt = tri_verts; *poly_index_pt++ = origi; - flen= 3; } - for (; *fv_pt > -1; fv_pt++) - { + for (; *fv_pt > -1; fv_pt++) { v_orig = (*(&mf->v1 + (*fv_pt))); if (vert_tag_array[v_orig]) { - mv= mvert + v_orig; + mv = mvert + v_orig; *bt++ = mv->co[0]; *bt++ = mv->co[1]; *bt++ = mv->co[2]; @@ -2283,37 +2284,37 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA else { /* no need for a vertex mapping. simple/fast */ - tot_bt_verts= numverts; + tot_bt_verts = numverts; - for (mf= mface, i=0; i < numpolys; mf++, i++) { - tot_bt_tris += (mf->v4 ? 2:1); + for (mf = mface, i = 0; i < numpolys; mf++, i++) { + tot_bt_tris += (mf->v4 ? 2 : 1); } - m_vertexArray.resize(tot_bt_verts*3); - btScalar *bt= &m_vertexArray[0]; + m_vertexArray.resize(tot_bt_verts * 3); + btScalar *bt = &m_vertexArray[0]; - m_triFaceArray.resize(tot_bt_tris*3); - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + int *tri_pt = &m_triFaceArray[0]; m_polygonIndexArray.resize(tot_bt_tris); - int *poly_index_pt= &m_polygonIndexArray[0]; + int *poly_index_pt = &m_polygonIndexArray[0]; m_triFaceUVcoArray.clear(); - for (mv= mvert, i=0; i < numverts; mv++, i++) { + for (mv = mvert, i = 0; i < numverts; mv++, i++) { *bt++ = mv->co[0]; *bt++ = mv->co[1]; *bt++ = mv->co[2]; } - for (mf= mface, i=0; i < numpolys; mf++, i++) { + for (mf = mface, i = 0; i < numpolys; mf++, i++) { int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; if (mf->v4) { - fv_pt= quad_verts; + fv_pt = quad_verts; *poly_index_pt++ = origi; *poly_index_pt++ = origi; } else { - fv_pt= tri_verts; + fv_pt = tri_verts; *poly_index_pt++ = origi; } @@ -2322,51 +2323,46 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA } } } - else { /* - * RAS Mesh Update - * - * */ - + else { /* + * RAS Mesh Update + * + * */ /* Note!, gameobj can be NULL here */ /* transverts are only used for deformed RAS_Meshes, the RAS_TexVert data * is too hard to get at, see below for details */ - float (*transverts)[3] = NULL; - int transverts_tot= 0; /* with deformed meshes - should always be greater than the max orginal index, or we get crashes */ + float(*transverts)[3] = NULL; + int transverts_tot = 0; /* with deformed meshes - should always be greater than the max orginal index, or we get crashes */ if (deformer) { /* map locations from the deformed array * * Could call deformer->Update(); but rely on redraw updating. * */ - transverts= deformer->GetTransVerts(&transverts_tot); + transverts = deformer->GetTransVerts(&transverts_tot); } // Tag verts we're using - numpolys= meshobj->NumPolygons(); - numverts= meshobj->m_sharedvertex_map.size(); + numpolys = meshobj->NumPolygons(); + numverts = meshobj->m_sharedvertex_map.size(); const float *xyz; - vector<bool> vert_tag_array(numverts, false); - vector<int> vert_remap_array(numverts, 0); + std::vector<bool> vert_tag_array(numverts, false); + std::vector<int> vert_remap_array(numverts, 0); - for (int p=0; p<numpolys; p++) - { - RAS_Polygon* poly= meshobj->GetPolygon(p); - if (poly->IsCollider()) - { - for (i=0; i < poly->VertexCount(); i++) - { - v_orig= poly->GetVertex(i)->getOrigIndex(); - if (vert_tag_array[v_orig]==false) - { + for (int p = 0; p < numpolys; p++) { + RAS_Polygon *poly = meshobj->GetPolygon(p); + if (poly->IsCollider()) { + for (i = 0; i < poly->VertexCount(); i++) { + v_orig = poly->GetVertex(i)->getOrigIndex(); + if (!vert_tag_array[v_orig]) { vert_tag_array[v_orig] = true; vert_remap_array[v_orig] = tot_bt_verts; tot_bt_verts++; } } - tot_bt_tris += (poly->VertexCount()==4 ? 2:1); + tot_bt_tris += (poly->VertexCount() == 4 ? 2 : 1); } } @@ -2374,32 +2370,29 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA if (tot_bt_tris == 0 || tot_bt_verts == 0) return false; - m_vertexArray.resize(tot_bt_verts*3); - btScalar *bt= &m_vertexArray[0]; + m_vertexArray.resize(tot_bt_verts * 3); + btScalar *bt = &m_vertexArray[0]; - m_triFaceArray.resize(tot_bt_tris*3); - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + int *tri_pt = &m_triFaceArray[0]; /* cant be used for anything useful in this case, since we don't rely on the original mesh * will just be an array like pythons range(tot_bt_tris) */ m_polygonIndexArray.resize(tot_bt_tris); - for (int p=0; p<numpolys; p++) - { - RAS_Polygon* poly= meshobj->GetPolygon(p); + int p = 0; + int t = 0; + while (t < tot_bt_tris) { + RAS_Polygon *poly = meshobj->GetPolygon(p); - if (poly->IsCollider()) - { + if (poly->IsCollider()) { /* quad or tri loop */ - fv_pt= (poly->VertexCount()==3 ? tri_verts:quad_verts); + fv_pt = (poly->VertexCount() == 3 ? tri_verts : quad_verts); - for (; *fv_pt > -1; fv_pt++) - { - v_orig= poly->GetVertex(*fv_pt)->getOrigIndex(); - - if (vert_tag_array[v_orig]) - { + for (; *fv_pt > -1; fv_pt++) { + v_orig = poly->GetVertex(*fv_pt)->getOrigIndex(); + if (vert_tag_array[v_orig]) { if (transverts) { /* deformed mesh, using RAS_TexVert locations would be too troublesome * because they are use the gameob as a hash in the material slot */ @@ -2409,55 +2402,60 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA } else { /* static mesh python may have modified */ - xyz= meshobj->GetVertexLocation( v_orig ); + xyz = meshobj->GetVertexLocation(v_orig); *bt++ = xyz[0]; *bt++ = xyz[1]; *bt++ = xyz[2]; } - vert_tag_array[v_orig] = false; } - *tri_pt++ = vert_remap_array[v_orig]; } } - - m_polygonIndexArray[p] = p; /* dumb counting */ + // first triangle + m_polygonIndexArray[t] = p; + + // if the poly is a quad we transform it in two triangles + if (poly->VertexCount() == 4) { + t++; + // second triangle + m_polygonIndexArray[t] = p; + } + t++; + p++; } } - + #if 0 /* needs #include <cstdio> */ printf("# vert count %d\n", m_vertexArray.size()); - for (int i=0; i<m_vertexArray.size(); i+=3) { - printf("v %.6f %.6f %.6f\n", m_vertexArray[i], m_vertexArray[i+1], m_vertexArray[i+2]); + for (int i = 0; i < m_vertexArray.size(); i += 3) { + printf("v %.6f %.6f %.6f\n", m_vertexArray[i], m_vertexArray[i + 1], m_vertexArray[i + 2]); } printf("# face count %d\n", m_triFaceArray.size()); - for (int i=0; i<m_triFaceArray.size(); i+=3) { - printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1); + for (int i = 0; i < m_triFaceArray.size(); i += 3) { + printf("f %d %d %d\n", m_triFaceArray[i] + 1, m_triFaceArray[i + 1] + 1, m_triFaceArray[i + 2] + 1); } #endif - /* force recreation of the m_unscaledShape. + /* force recreation of the m_triangleIndexVertexArray. * If this has multiple users we cant delete */ - if (m_unscaledShape) { - // don't free now so it can re-allocate under the same location and not break pointers. - // DeleteBulletShape(m_unscaledShape); - m_forceReInstance= true; + if (m_triangleIndexVertexArray) { + m_forceReInstance = true; } // Make sure to also replace the mesh in the shape map! Otherwise we leave dangling references when we free. // Note, this whole business could cause issues with shared meshes. If we update one mesh, do we replace // them all? - std::map<RAS_MeshObject*,CcdShapeConstructionInfo*>::iterator mit = m_meshShapeMap.find(m_meshObject); + std::map<RAS_MeshObject *, CcdShapeConstructionInfo *>::iterator mit = m_meshShapeMap.find(m_meshObject); if (mit != m_meshShapeMap.end()) { m_meshShapeMap.erase(mit); m_meshShapeMap[meshobj] = this; } - m_meshObject= meshobj; - + m_meshObject = meshobj; + if (dm) { dm->needsFree = 1; dm->release(dm); @@ -2465,8 +2463,6 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA return true; } - - bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo) { if (shapeInfo == NULL) @@ -2529,74 +2525,61 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, b // 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering // One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1 // and btScaledBvhTriangleMeshShape otherwise. - if (useGimpact) - { - btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray( + if (useGimpact) { + if (!m_triangleIndexVertexArray || m_forceReInstance) { + if (m_triangleIndexVertexArray) + delete m_triangleIndexVertexArray; + + m_triangleIndexVertexArray = new btTriangleIndexVertexArray( m_polygonIndexArray.size(), - &m_triFaceArray[0], - 3*sizeof(int), - m_vertexArray.size()/3, + m_triFaceArray.data(), + 3 * sizeof(int), + m_vertexArray.size() / 3, &m_vertexArray[0], - 3*sizeof(btScalar) - ); - btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(indexVertexArrays); - gimpactShape->setMargin(margin); - gimpactShape->updateBound(); - collisionShape = gimpactShape; - - - } else - { - if (!m_unscaledShape || m_forceReInstance) - { - - btTriangleIndexVertexArray* indexVertexArrays = 0; + 3 * sizeof(btScalar)); + m_forceReInstance = false; + } + btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(m_triangleIndexVertexArray); + gimpactShape->setMargin(margin); + gimpactShape->updateBound(); + collisionShape = gimpactShape; + } + else { + if (!m_triangleIndexVertexArray || m_forceReInstance) { ///enable welding, only for the objects that need it (such as soft bodies) - if (0.f != m_weldingThreshold1) - { - btTriangleMesh* collisionMeshData = new btTriangleMesh(true,false); + if (0.0f != m_weldingThreshold1) { + btTriangleMesh *collisionMeshData = new btTriangleMesh(true, false); collisionMeshData->m_weldingThreshold = m_weldingThreshold1; - bool removeDuplicateVertices=true; + bool removeDuplicateVertices = true; // m_vertexArray not in multiple of 3 anymore, use m_triFaceArray - for (unsigned int i=0; i<m_triFaceArray.size(); i+=3) { - btScalar *bt = &m_vertexArray[3*m_triFaceArray[i]]; + for (unsigned int i = 0; i < m_triFaceArray.size(); i += 3) { + btScalar *bt = &m_vertexArray[3 * m_triFaceArray[i]]; btVector3 v1(bt[0], bt[1], bt[2]); - bt = &m_vertexArray[3*m_triFaceArray[i+1]]; + bt = &m_vertexArray[3 * m_triFaceArray[i + 1]]; btVector3 v2(bt[0], bt[1], bt[2]); - bt = &m_vertexArray[3*m_triFaceArray[i+2]]; + bt = &m_vertexArray[3 * m_triFaceArray[i + 2]]; btVector3 v3(bt[0], bt[1], bt[2]); collisionMeshData->addTriangle(v1, v2, v3, removeDuplicateVertices); } - indexVertexArrays = collisionMeshData; - - } else - { - indexVertexArrays = new btTriangleIndexVertexArray( + m_triangleIndexVertexArray = collisionMeshData; + } + else { + m_triangleIndexVertexArray = new btTriangleIndexVertexArray( m_polygonIndexArray.size(), - &m_triFaceArray[0], - 3*sizeof(int), - m_vertexArray.size()/3, + m_triFaceArray.data(), + 3 * sizeof(int), + m_vertexArray.size() / 3, &m_vertexArray[0], - 3*sizeof(btScalar)); - } - - // this shape will be shared and not deleted until shapeInfo is deleted - - // for UpdateMesh, reuse the last memory location so instancing wont crash. - if (m_unscaledShape) { - DeleteBulletShape(m_unscaledShape, false); - m_unscaledShape->~btBvhTriangleMeshShape(); - m_unscaledShape = new(m_unscaledShape) btBvhTriangleMeshShape( indexVertexArrays, true, useBvh ); - } else { - m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true, useBvh ); + 3 * sizeof(btScalar)); } - m_forceReInstance= false; - } else if (useBvh && m_unscaledShape->getOptimizedBvh() == NULL) { - // the existing unscaledShape was not build with Bvh, do it now - m_unscaledShape->buildOptimizedBvh(); + + m_forceReInstance = false; } - collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); + + btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(m_triangleIndexVertexArray, true, useBvh); + unscaledShape->setMargin(margin); + collisionShape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f)); collisionShape->setMargin(margin); } break; @@ -2638,10 +2621,9 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo() (*sit)->Release(); } m_shapeArray.clear(); - if (m_unscaledShape) - { - DeleteBulletShape(m_unscaledShape, true); - } + + if (m_triangleIndexVertexArray) + delete m_triangleIndexVertexArray; m_vertexArray.clear(); if (m_shapeType == PHY_SHAPE_MESH && m_meshObject != NULL) { diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index de40624d7bb..b1d38763fbb 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -79,7 +79,7 @@ public: m_userData(NULL), m_refCount(1), m_meshObject(NULL), - m_unscaledShape(NULL), + m_triangleIndexVertexArray(NULL), m_forceReInstance(false), m_weldingThreshold1(0.f), m_shapeProxy(NULL) @@ -110,10 +110,11 @@ public: void AddShape(CcdShapeConstructionInfo* shapeInfo); - btTriangleMeshShape* GetMeshShape(void) + btStridingMeshInterface *GetMeshInterface() { - return (m_unscaledShape); + return m_triangleIndexVertexArray; } + CcdShapeConstructionInfo* GetChildShape(int i) { if (i < 0 || i >= (int)m_shapeArray.size()) @@ -195,8 +196,8 @@ protected: int m_refCount; // this class is shared between replicas // keep track of users so that we can release it RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh - btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape, - // the actual shape is of type btScaledBvhTriangleMeshShape + // The list of vertexes and indexes for the triangle mesh, shared between Bullet shape. + btTriangleIndexVertexArray *m_triangleIndexVertexArray; std::vector<CcdShapeConstructionInfo*> m_shapeArray; // for compound shapes bool m_forceReInstance; //use gimpact for concave dynamic/moving collision detection float m_weldingThreshold1; //welding closeby vertices together can improve softbody stability etc. @@ -447,6 +448,23 @@ public: #endif }; +class CleanPairCallback : public btOverlapCallback +{ + btBroadphaseProxy *m_cleanProxy; + btOverlappingPairCache *m_pairCache; + btDispatcher *m_dispatcher; + +public: + CleanPairCallback(btBroadphaseProxy *cleanProxy, btOverlappingPairCache *pairCache, btDispatcher *dispatcher) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + + virtual bool processOverlap(btBroadphasePair &pair); +}; + ///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution. class CcdPhysicsController : public PHY_IPhysicsController { @@ -498,6 +516,11 @@ protected: return (--m_registerCount == 0) ? true : false; } + bool Registered() const + { + return (m_registerCount != 0); + } + void addCcdConstraintRef(btTypedConstraint* c); void removeCcdConstraintRef(btTypedConstraint* c); btTypedConstraint* getCcdConstraintRef(int index); @@ -513,7 +536,15 @@ protected: CcdPhysicsController (const CcdConstructionInfo& ci); + /** + * Delete the current Bullet shape used in the rigid body. + */ bool DeleteControllerShape(); + + /** + * Delete the old Bullet shape and set the new Bullet shape : newShape + * \param newShape The new Bullet shape to set, if is NULL we create a new Bullet shape + */ bool ReplaceControllerShape(btCollisionShape *newShape); virtual ~CcdPhysicsController(); @@ -598,7 +629,7 @@ protected: virtual void ResolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); - + virtual void RefreshCollisions(); virtual void SuspendDynamics(bool ghost); virtual void RestoreDynamics(); @@ -626,8 +657,12 @@ protected: virtual void CalcXform() {} virtual void SetMargin(float margin) { - if (m_collisionShape) - m_collisionShape->setMargin(btScalar(margin)); + if (m_collisionShape) { + m_collisionShape->setMargin(margin); + // if the shape use a unscaled shape we have also to set the correct margin in it + if (m_collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) + ((btScaledBvhTriangleMeshShape *)m_collisionShape)->getChildShape()->setMargin(margin); + } } virtual float GetMargin() const { @@ -712,6 +747,11 @@ protected: return GetConstructionInfo().m_bDyna; } + virtual bool IsSuspended() const + { + return m_suspended; + } + virtual bool IsCompound() { return GetConstructionInfo().m_shapeInfo->m_shapeType == PHY_SHAPE_COMPOUND; @@ -719,6 +759,9 @@ protected: virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj); + /* Method to replicate rigid body joint contraints for group instances. */ + virtual void ReplicateConstraints(KX_GameObject *gameobj, std::vector<KX_GameObject*> constobj); + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:CcdPhysicsController") #endif diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index ac74029fbe3..3670d79a01e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -461,6 +461,19 @@ m_scalingPropagated(false) void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) { + // the controller is already added we do nothing + if (!m_controllers.insert(ctrl).second) { + return; + } + + /* In the case of compound child controller (see also RemoveCcdPhysicsController) + * we add the controller to the trigger controlers list : m_triggerControllers + * if it use collision callbacks. + */ + if (ctrl->Registered()) { + m_triggerControllers.insert(ctrl); + } + btRigidBody* body = ctrl->GetRigidBody(); btCollisionObject* obj = ctrl->GetCollisionObject(); @@ -469,8 +482,6 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) if (body) body->setGravity( m_gravity ); - m_controllers.insert(ctrl); - if (body) { //use explicit group/filter for finer control over collision in bullet => near/radar sensor @@ -505,10 +516,32 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctrl) { + // if the physics controller is already removed we do nothing + if (!m_controllers.erase(ctrl)) { + return false; + } + + /* In the case of compound child controller which use collision callbacks + * we remove it from the m_triggerControllers list but leave m_registerCount + * to know in AddCcdPhysicsController if we have to add it in m_triggerControllers + * and to avoid an useless added in RequestCollisionCallback, indeed we can't register + * more than one time a controller. + */ + if (ctrl->Registered()) { + m_triggerControllers.erase(ctrl); + } + //also remove constraint btRigidBody* body = ctrl->GetRigidBody(); if (body) { + btBroadphaseProxy *proxy = ctrl->GetCollisionObject()->getBroadphaseHandle(); + btDispatcher *dispatcher = m_dynamicsWorld->getDispatcher(); + btOverlappingPairCache *pairCache = m_dynamicsWorld->getPairCache(); + + CleanPairCallback cleanPairs(proxy, pairCache, dispatcher); + pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher); + for (int i = ctrl->getNumCcdConstraintRefs() - 1; i >= 0; i--) { btTypedConstraint* con = ctrl->getCcdConstraintRef(i); @@ -548,13 +581,8 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr } } } - if (ctrl->m_registerCount != 0) - printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount); - - //remove it from the triggers - m_triggerControllers.erase(ctrl); - return (m_controllers.erase(ctrl) != 0); + return true; } void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask) @@ -562,6 +590,7 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr // this function is used when the collisionning group of a controller is changed // remove and add the collistioning object btRigidBody* body = ctrl->GetRigidBody(); + btSoftBody *softBody = ctrl->GetSoftBody(); btCollisionObject* obj = ctrl->GetCollisionObject(); if (obj) { @@ -575,6 +604,9 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr body->setMassProps(newMass, inertia); m_dynamicsWorld->addRigidBody(body, newCollisionGroup, newCollisionMask); } + else if (softBody) { + m_dynamicsWorld->addSoftBody(softBody); + } else { m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask); } @@ -586,43 +618,6 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr ctrl->m_cci.m_collisionFlags = newCollisionFlags; } -void CcdPhysicsEnvironment::EnableCcdPhysicsController(CcdPhysicsController* ctrl) -{ - if (m_controllers.insert(ctrl).second) - { - btCollisionObject* obj = ctrl->GetCollisionObject(); - obj->setUserPointer(ctrl); - // update the position of the object from the user - if (ctrl->GetMotionState()) - { - btTransform xform = CcdPhysicsController::GetTransformFromMotionState(ctrl->GetMotionState()); - ctrl->SetCenterOfMassTransform(xform); - } - m_dynamicsWorld->addCollisionObject(obj, - ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); - } -} - -void CcdPhysicsEnvironment::DisableCcdPhysicsController(CcdPhysicsController* ctrl) -{ - if (m_controllers.erase(ctrl)) - { - btRigidBody* body = ctrl->GetRigidBody(); - if (body) - { - m_dynamicsWorld->removeRigidBody(body); - } else - { - if (ctrl->GetSoftBody()) - { - } else - { - m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject()); - } - } - } -} - void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ctrl) { btCollisionObject* obj = ctrl->GetCollisionObject(); @@ -636,6 +631,11 @@ void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ct } } +bool CcdPhysicsEnvironment::IsActiveCcdPhysicsController(CcdPhysicsController *ctrl) +{ + return (m_controllers.find(ctrl) != m_controllers.end()); +} + void CcdPhysicsEnvironment::AddCcdGraphicController(CcdGraphicController* ctrl) { if (m_cullingTree && !ctrl->GetBroadphaseHandle()) @@ -671,6 +671,19 @@ void CcdPhysicsEnvironment::RemoveCcdGraphicController(CcdGraphicController* ctr } } +void CcdPhysicsEnvironment::UpdateCcdPhysicsControllerShape(CcdShapeConstructionInfo *shapeInfo) +{ + for (std::set<CcdPhysicsController *>::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it) { + CcdPhysicsController *ctrl = *it; + + if (ctrl->GetShapeInfo() != shapeInfo) + continue; + + ctrl->ReplaceControllerShape(NULL); + RefreshCcdPhysicsController(ctrl); + } +} + void CcdPhysicsEnvironment::BeginFrame() { @@ -752,8 +765,8 @@ public: void CcdPhysicsEnvironment::ProcessFhSprings(double curTime,float interval) { std::set<CcdPhysicsController*>::iterator it; - // dynamic of Fh spring is based on a timestep of 1/60 - int numIter = (int)(interval*60.0001f); + // Add epsilon to the tick rate for numerical stability + int numIter = (int)(interval*(KX_KetsjiEngine::GetTicRate() + 0.001f)); for (it=m_controllers.begin(); it!=m_controllers.end(); it++) { @@ -1156,17 +1169,8 @@ static bool GetHitTriangle(btCollisionShape* shape, CcdShapeConstructionInfo* sh int indexstride; int numfaces; PHY_ScalarType indicestype; - btStridingMeshInterface* meshInterface = NULL; - btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape(); + btStridingMeshInterface* meshInterface = shapeInfo->GetMeshInterface(); - if (triangleShape) - meshInterface = triangleShape->getMeshInterface(); - else - { - // other possibility is gImpact - if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) - meshInterface = (static_cast<btGImpactMeshShape*>(shape))->getMeshInterface(); - } if (!meshInterface) return false; @@ -2188,15 +2192,8 @@ btTypedConstraint* CcdPhysicsEnvironment::GetConstraintById(int constraintId) void CcdPhysicsEnvironment::AddSensor(PHY_IPhysicsController* ctrl) { - CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl; - // addSensor() is a "light" function for bullet because it is used - // dynamically when the sensor is activated. Use enableCcdPhysicsController() instead - //if (m_controllers.insert(ctrl1).second) - //{ - // addCcdPhysicsController(ctrl1); - //} - EnableCcdPhysicsController(ctrl1); + AddCcdPhysicsController(ctrl1); } bool CcdPhysicsEnvironment::RemoveCollisionCallback(PHY_IPhysicsController* ctrl) @@ -2211,7 +2208,7 @@ bool CcdPhysicsEnvironment::RemoveCollisionCallback(PHY_IPhysicsController* ctrl void CcdPhysicsEnvironment::RemoveSensor(PHY_IPhysicsController* ctrl) { - DisableCcdPhysicsController((CcdPhysicsController*)ctrl); + RemoveCcdPhysicsController((CcdPhysicsController*)ctrl); } void CcdPhysicsEnvironment::AddTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) @@ -2644,9 +2641,6 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl if (!rb0) return 0; - // If either of the controllers is missing, we can't do anything. - if (!c0 || !c1) return 0; - btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) : rb0->getCenterOfMassTransform() * pivotInA; btVector3 axisInA(axisX,axisY,axisZ); @@ -2658,6 +2652,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl { case PHY_POINT2POINT_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; btPoint2PointConstraint* p2p = 0; @@ -2686,6 +2682,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl case PHY_GENERIC_6DOF_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; + btGeneric6DofConstraint* genericConstraint = 0; if (rb1) @@ -2739,7 +2738,7 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl *rb0,s_fixedObject2, frameInA,frameInB,useReferenceFrameA); } - + if (genericConstraint) { //m_constraints.push_back(genericConstraint); @@ -2756,6 +2755,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl } case PHY_CONE_TWIST_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; + btConeTwistConstraint* coneTwistContraint = 0; @@ -2807,7 +2809,7 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl *rb0,s_fixedObject2, frameInA,frameInB); } - + if (coneTwistContraint) { //m_constraints.push_back(genericConstraint); @@ -2830,6 +2832,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl case PHY_LINEHINGE_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; + btHingeConstraint* hinge = 0; if (rb1) @@ -3517,20 +3522,23 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject if (isbulletdyna) gameobj->SetRecordAnimation(true); + physicscontroller->SetNewClientInfo(gameobj->getClientInfo()); + // don't add automatically sensor object, they are added when a collision sensor is registered if (!isbulletsensor && (blenderobject->lay & activeLayerBitInfo) != 0) { this->AddCcdPhysicsController( physicscontroller); } - physicscontroller->SetNewClientInfo(gameobj->getClientInfo()); + { btRigidBody* rbody = physicscontroller->GetRigidBody(); if (rbody) { + rbody->setLinearFactor(ci.m_linearFactor); + if (isbulletrigidbody) { - rbody->setLinearFactor(ci.m_linearFactor); rbody->setAngularFactor(ci.m_angularFactor); } @@ -3591,3 +3599,79 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject } #endif } + + +void CcdPhysicsEnvironment::SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest, + bRigidBodyJointConstraint *dat) +{ + PHY_IPhysicsController *phy_src = obj_src->GetPhysicsController(); + PHY_IPhysicsController *phy_dest = obj_dest->GetPhysicsController(); + PHY_IPhysicsEnvironment *phys_env = obj_src->GetScene()->GetPhysicsEnvironment(); + + /* We need to pass a full constraint frame, not just axis. */ + MT_Matrix3x3 localCFrame(MT_Vector3(dat->axX,dat->axY,dat->axZ)); + MT_Vector3 axis0 = localCFrame.getColumn(0); + MT_Vector3 axis1 = localCFrame.getColumn(1); + MT_Vector3 axis2 = localCFrame.getColumn(2); + MT_Vector3 scale = obj_src->NodeGetWorldScaling(); + + /* Apply not only the pivot and axis values, but also take scale into count + * this is not working well, if only one or two axis are scaled, but works ok on + * homogeneous scaling. */ + int constraintId = phys_env->CreateConstraint( + phy_src, phy_dest, (PHY_ConstraintType)dat->type, + (float)(dat->pivX * scale.x()), (float)(dat->pivY * scale.y()), (float)(dat->pivZ * scale.z()), + (float)(axis0.x() * scale.x()), (float)(axis0.y() * scale.y()), (float)(axis0.z() * scale.z()), + (float)(axis1.x() * scale.x()), (float)(axis1.y() * scale.y()), (float)(axis1.z() * scale.z()), + (float)(axis2.x() * scale.x()), (float)(axis2.y() * scale.y()), (float)(axis2.z() * scale.z()), + dat->flag); + + /* PHY_POINT2POINT_CONSTRAINT = 1, + * PHY_LINEHINGE_CONSTRAINT = 2, + * PHY_ANGULAR_CONSTRAINT = 3, + * PHY_CONE_TWIST_CONSTRAINT = 4, + * PHY_VEHICLE_CONSTRAINT = 11, + * PHY_GENERIC_6DOF_CONSTRAINT = 12 */ + + if (!constraintId) + return; + + int dof = 0; + int dof_max = 0; + int dofbit = 0; + + switch (dat->type) { + /* Set all the limits for generic 6DOF constraint. */ + case PHY_GENERIC_6DOF_CONSTRAINT: + dof_max = 6; + dofbit = 1; + break; + /* Set XYZ angular limits for cone twist constraint. */ + case PHY_CONE_TWIST_CONSTRAINT: + dof = 3; + dof_max = 6; + dofbit = 1 << 3; + break; + /* Set only X angular limits for line hinge and angular constraint. */ + case PHY_LINEHINGE_CONSTRAINT: + case PHY_ANGULAR_CONSTRAINT: + dof = 3; + dof_max = 4; + dofbit = 1 << 3; + break; + default: + break; + } + + for (; dof < dof_max; dof++) { + if (dat->flag & dofbit) { + phys_env->SetConstraintParam(constraintId, dof, dat->minLimit[dof], dat->maxLimit[dof]); + } + else { + /* minLimit > maxLimit means free (no limit) for this degree of freedom. */ + phys_env->SetConstraintParam(constraintId, dof, 1.0f, -1.0f); + } + dofbit <<= 1; + } + +} diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index ff8a3f4f9f9..94aea215478 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -22,6 +22,8 @@ subject to the following restrictions: #define __CCDPHYSICSENVIRONMENT_H__ #include "PHY_IPhysicsEnvironment.h" +#include "KX_KetsjiEngine.h" + #include <vector> #include <set> #include <map> @@ -52,6 +54,7 @@ class btOverlappingPairCache; class btIDebugDraw; class PHY_IVehicle; class CcdOverlapFilterCallBack; +class CcdShapeConstructionInfo; /** CcdPhysicsEnvironment is an experimental mainloop for physics simulation using optional continuous collision detection. * Physics Environment takes care of stepping the simulation and is a container for physics entities. @@ -131,8 +134,7 @@ protected: virtual void SetFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep) { - //based on DEFAULT_PHYSICS_TIC_RATE of 60 hertz - SetNumTimeSubSteps((int)(fixedTimeStep / 60.f)); + SetNumTimeSubSteps((int)(fixedTimeStep / KX_KetsjiEngine::GetTicRate())); } //returns 0.f if no fixed timestep is used @@ -220,16 +222,22 @@ protected: void UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask); - void DisableCcdPhysicsController(CcdPhysicsController* ctrl); - - void EnableCcdPhysicsController(CcdPhysicsController* ctrl); - void RefreshCcdPhysicsController(CcdPhysicsController* ctrl); + bool IsActiveCcdPhysicsController(CcdPhysicsController *ctrl); + void AddCcdGraphicController(CcdGraphicController* ctrl); void RemoveCcdGraphicController(CcdGraphicController* ctrl); + /** + * Update all physics controllers shape which use the same shape construction info. + * Call RecreateControllerShape on controllers which use the same shape + * construction info that argument shapeInfo. + * You need to call this function when the shape construction info changed. + */ + void UpdateCcdPhysicsControllerShape(CcdShapeConstructionInfo *shapeInfo); + btBroadphaseInterface* GetBroadphase(); btDbvtBroadphase* GetCullingTree() { return m_cullingTree; } @@ -274,6 +282,10 @@ protected: bool isCompoundChild, bool hasCompoundChildren); + /* Set the rigid body joints constraints values for converted objects and replicated group instances. */ + virtual void SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest, + bRigidBodyJointConstraint *dat); + protected: diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h index 1717f8d90cb..3e2337f01ea 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsController.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h @@ -32,6 +32,7 @@ #ifndef __PHY_IPHYSICSCONTROLLER_H__ #define __PHY_IPHYSICSCONTROLLER_H__ +#include <vector> #include "PHY_IController.h" class PHY_IMotionState; @@ -95,6 +96,7 @@ class PHY_IPhysicsController : public PHY_IController virtual void SetAngularDamping(float damping)=0; virtual void SetDamping(float linear, float angular)=0; + virtual void RefreshCollisions() = 0; virtual void SuspendDynamics(bool ghost=false)=0; virtual void RestoreDynamics()=0; @@ -132,9 +134,12 @@ class PHY_IPhysicsController : public PHY_IController virtual bool IsDynamic() = 0; virtual bool IsCompound() = 0; + virtual bool IsSuspended() const = 0; virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj) = 0; + /* Method to replicate rigid body joint contraints for group instances. */ + virtual void ReplicateConstraints(KX_GameObject *gameobj, std::vector<KX_GameObject*> constobj) = 0; #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_IPhysicsController") diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index dd762b02b4e..44b61136d3f 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -55,6 +55,7 @@ class KX_Scene; struct PHY_ShapeProps; struct PHY_MaterialProps; class PHY_IMotionState; +struct bRigidBodyJointConstraint; /** * pass back information from rayTest @@ -213,6 +214,9 @@ class PHY_IPhysicsEnvironment bool isCompoundChild, bool hasCompoundChildren) = 0; + /* Set the rigid body joints constraints values for converted objects and replicated group instances. */ + virtual void SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest, + bRigidBodyJointConstraint *dat) {} #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_IPhysicsEnvironment") diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h index d90cbea286e..471c2c97fa1 100644 --- a/source/gameengine/Rasterizer/RAS_ICanvas.h +++ b/source/gameengine/Rasterizer/RAS_ICanvas.h @@ -237,6 +237,8 @@ public: const char* filename )=0; + virtual void GetDisplayDimensions(int &width, int &height) = 0; + virtual void ResizeWindow( diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index d7b52213191..aadecd56992 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -297,15 +297,11 @@ public: /** * Fog */ - virtual void SetFog(float start, float dist, float r, float g, float b) = 0; - virtual void SetFogColor(float r, float g,float b) = 0; - virtual void SetFogStart(float start) = 0; - virtual void SetFogEnd(float end) = 0; + virtual void SetFog(short type, float start, float dist, float intensity, float color[3]) = 0; virtual void DisplayFog() = 0; - virtual void DisableFog() = 0; - virtual bool IsFogEnabled() = 0; + virtual void EnableFog(bool enable) = 0; - virtual void SetBackColor(float red, float green, float blue, float alpha) = 0; + virtual void SetBackColor(float color[3]) = 0; /** * \param drawingmode = KX_BOUNDINGBOX, KX_WIREFRAME, KX_SOLID, KX_SHADED or KX_TEXTURED. @@ -380,7 +376,7 @@ public: */ virtual void SetEmissive(float eX, float eY, float eZ, float e) = 0; - virtual void SetAmbientColor(float red, float green, float blue) = 0; + virtual void SetAmbientColor(float color[3]) = 0; virtual void SetAmbient(float factor) = 0; /** diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index b3da5e1f812..34184f73953 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -79,10 +79,6 @@ void RAS_ListSlot::RemoveList() void RAS_ListSlot::DrawList() { - if (m_flag &LIST_STREAM || m_flag& LIST_NOCREATE) { - RemoveList(); - return; - } if (m_flag &LIST_MODIFY) { if (m_flag &LIST_CREATE) { if (m_list == 0) { @@ -115,7 +111,7 @@ void RAS_ListSlot::SetModified(bool mod) if (mod && !(m_flag & LIST_MODIFY)) { spit("Modifying list (" << m_list << ")"); m_flag = m_flag &~ LIST_END; - m_flag |= LIST_STREAM; + m_flag |= LIST_MODIFY; } } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index d394c72b2a2..5e1c662bc17 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -35,12 +35,9 @@ public: enum RAS_ListSlotFlags { LIST_CREATE =1, LIST_MODIFY =2, - LIST_STREAM =4, - LIST_NOCREATE =8, - LIST_BEGIN =16, - LIST_END =32, - LIST_REGEN =64, - LIST_DERIVEDMESH=128, + LIST_BEGIN =4, + LIST_END =8, + LIST_DERIVEDMESH=16, }; struct DerivedMesh; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 116a11339d9..95c153a7e2a 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -194,113 +194,52 @@ bool RAS_OpenGLRasterizer::Init() } -void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue) +void RAS_OpenGLRasterizer::SetAmbientColor(float color[3]) { - m_ambr = red; - m_ambg = green; - m_ambb = blue; + m_ambr = color[0]; + m_ambg = color[1]; + m_ambb = color[2]; } - void RAS_OpenGLRasterizer::SetAmbient(float factor) { - float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f }; + float ambient[] = {m_ambr * factor, m_ambg * factor, m_ambb * factor, 1.0f}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); } - -void RAS_OpenGLRasterizer::SetBackColor(float red, - float green, - float blue, - float alpha) -{ - m_redback = red; - m_greenback = green; - m_blueback = blue; - m_alphaback = alpha; -} - - - -void RAS_OpenGLRasterizer::SetFogColor(float r, - float g, - float b) -{ - m_fogr = r; - m_fogg = g; - m_fogb = b; - m_fogenabled = true; -} - - - -void RAS_OpenGLRasterizer::SetFogStart(float start) +void RAS_OpenGLRasterizer::SetBackColor(float color[3]) { - m_fogstart = start; - m_fogenabled = true; + m_redback = color[0]; + m_greenback = color[1]; + m_blueback = color[2]; + m_alphaback = 1.0f; } - - -void RAS_OpenGLRasterizer::SetFogEnd(float fogend) +void RAS_OpenGLRasterizer::SetFog(short type, float start, float dist, float intensity, float color[3]) { - m_fogdist = fogend; - m_fogenabled = true; + float params[4] = {color[0], color[1], color[2], 1.0f}; + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogf(GL_FOG_DENSITY, intensity / 10.0f); + glFogf(GL_FOG_START, start); + glFogf(GL_FOG_END, start + dist); + glFogfv(GL_FOG_COLOR, params); } - - -void RAS_OpenGLRasterizer::SetFog(float start, - float dist, - float r, - float g, - float b) +void RAS_OpenGLRasterizer::EnableFog(bool enable) { - m_fogstart = start; - m_fogdist = dist; - m_fogr = r; - m_fogg = g; - m_fogb = b; - m_fogenabled = true; + m_fogenabled = enable; } - - -void RAS_OpenGLRasterizer::DisableFog() -{ - m_fogenabled = false; -} - -bool RAS_OpenGLRasterizer::IsFogEnabled() -{ - return m_fogenabled; -} - - void RAS_OpenGLRasterizer::DisplayFog() { - if ((m_drawingmode >= KX_SOLID) && m_fogenabled) - { - float params[5]; - glFogi(GL_FOG_MODE, GL_LINEAR); - glFogf(GL_FOG_DENSITY, 0.1f); - glFogf(GL_FOG_START, m_fogstart); - glFogf(GL_FOG_END, m_fogstart + m_fogdist); - params[0] = m_fogr; - params[1] = m_fogg; - params[2] = m_fogb; - params[3] = 0.0; - glFogfv(GL_FOG_COLOR, params); + if ((m_drawingmode >= KX_SOLID) && m_fogenabled) { glEnable(GL_FOG); - } - else - { + } + else { glDisable(GL_FOG); } } - - bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat) { return mat.Activate(this, m_materialCachingInfo); @@ -1135,12 +1074,17 @@ void RAS_OpenGLRasterizer::SetMipmapping(MipmapOption val) RAS_IRasterizer::MipmapOption RAS_OpenGLRasterizer::GetMipmapping() { - if (GPU_get_linear_mipmap()) - return RAS_IRasterizer::RAS_MIPMAP_LINEAR; - else if (GPU_get_mipmap()) - return RAS_IRasterizer::RAS_MIPMAP_NEAREST; - else + if (GPU_get_mipmap()) { + if (GPU_get_linear_mipmap()) { + return RAS_IRasterizer::RAS_MIPMAP_LINEAR; + } + else { + return RAS_IRasterizer::RAS_MIPMAP_NEAREST; + } + } + else { return RAS_IRasterizer::RAS_MIPMAP_NONE; + } } void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 1334ddb2a26..b034315e3d6 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -80,12 +80,7 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer /* fogging vars */ bool m_fogenabled; - float m_fogstart; - float m_fogdist; - float m_fogr; - float m_fogg; - float m_fogb; - + float m_redback; float m_greenback; float m_blueback; @@ -198,16 +193,12 @@ public: virtual const MT_Point3& GetCameraPosition(); virtual bool GetCameraOrtho(); - virtual void SetFog(float start, float dist, float r, float g, float b); - virtual void SetFogColor(float r, float g, float b); - virtual void SetFogStart(float fogstart); - virtual void SetFogEnd(float fogend); - void DisableFog(); + virtual void SetFog(short type, float start, float dist, float intensity, float color[3]); + virtual void EnableFog(bool enable); virtual void DisplayFog(); - virtual bool IsFogEnabled(); - virtual void SetBackColor(float red, float green, float blue, float alpha); - + virtual void SetBackColor(float color[3]); + virtual void SetDrawingMode(int drawingmode); virtual int GetDrawingMode(); @@ -227,7 +218,7 @@ public: virtual void SetDiffuse(float difX, float difY, float difZ, float diffuse); virtual void SetEmissive(float eX, float eY, float eZ, float e); - virtual void SetAmbientColor(float red, float green, float blue); + virtual void SetAmbientColor(float color[3]); virtual void SetAmbient(float factor); virtual void SetPolygonOffset(float mult, float add); diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 57b2e85845c..2b2a6e0778b 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -75,8 +75,8 @@ ImageRender::ImageRender (KX_Scene *scene, KX_Camera * camera) : m_mirrorHalfWidth(0.f), m_mirrorHalfHeight(0.f) { - // initialize background color - setBackground(0, 0, 255, 255); + // initialize background color to scene background color as default + setBackgroundFromScene(m_scene); // retrieve rendering objects m_engine = KX_GetActiveEngine(); m_rasterizer = m_engine->GetRasterizer(); @@ -100,6 +100,18 @@ void ImageRender::setBackground (int red, int green, int blue, int alpha) m_background[3] = (alpha < 0) ? 0.f : (alpha > 255) ? 1.f : float(alpha)/255.f; } +// set background color from scene +void ImageRender::setBackgroundFromScene (KX_Scene *scene) +{ + if (scene) { + const float *background_color = scene->GetWorldInfo()->getBackColor(); + setBackground((int) (background_color[0] * 255.0f), (int) (background_color[1] * 255.0f), (int) (background_color[2] * 255.0f), 255); + } + else { + setBackground(0, 0, 255, 255); + } +} + // capture image from viewport void ImageRender::calcImage (unsigned int texId, double ts) @@ -200,7 +212,7 @@ void ImageRender::Render() m_canvas->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]); m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); m_rasterizer->BeginFrame(m_engine->GetClockTime()); - m_engine->SetWorldSettings(m_scene->GetWorldInfo()); + m_scene->GetWorldInfo()->UpdateWorldSettings(); m_rasterizer->SetAuxilaryClientInfo(m_scene); m_rasterizer->DisplayFog(); // matrix calculation, don't apply any of the stereo mode @@ -272,6 +284,12 @@ void ImageRender::Render() // restore the stereo mode now that the matrix is computed m_rasterizer->SetStereoMode(stereomode); + if (stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) { + // In QUAD buffer stereo mode, the GE render pass ends with the right eye on the right buffer + // but we need to draw on the left buffer to capture the render + // TODO: implement an explicit function in rasterizer to restore the left buffer. + m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE); + } m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera); m_scene->RenderBuckets(camtrans, m_rasterizer); @@ -727,7 +745,8 @@ ImageRender::ImageRender (KX_Scene *scene, KX_GameObject *observer, KX_GameObjec m_mirrorX = m_mirrorY.cross(m_mirrorZ); m_render = true; - setBackground(0, 0, 255, 255); + // set mirror background color to scene background color as default + setBackgroundFromScene(m_scene); } diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h index 98dceeaafe1..bdf442c82d0 100644 --- a/source/gameengine/VideoTexture/ImageRender.h +++ b/source/gameengine/VideoTexture/ImageRender.h @@ -100,7 +100,7 @@ protected: void Render(); void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam); void RenderFrame(KX_Scene* scene, KX_Camera* cam); - void SetBackGround(KX_WorldInfo* wi); + void setBackgroundFromScene(KX_Scene *scene); void SetWorldSettings(KX_WorldInfo* wi); }; diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index 9640c5544da..c31faf5a463 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -79,9 +79,21 @@ void loadTexture(unsigned int texId, unsigned int *texture, short *size, glBindTexture(GL_TEXTURE_2D, texId); 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, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, texture); + + ibuf = IMB_allocFromBuffer(texture, NULL, size[0], size[1]); + + 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 { |