diff options
author | Martin Poirier <theeth@yahoo.com> | 2008-08-05 06:27:09 +0400 |
---|---|---|
committer | Martin Poirier <theeth@yahoo.com> | 2008-08-05 06:27:09 +0400 |
commit | e2380665259eb0f74376ffda2ab791ba8e1bb9ef (patch) | |
tree | ac5134d6f03956f51e4498e828143482d36287fa /source/gameengine | |
parent | d4b646103a6cae433d58bf7e2f4953f81358835b (diff) | |
parent | 07bc1e56fec864748c160af02659e3fcff317be9 (diff) |
Merging with trunk
15568 - 15963
Diffstat (limited to 'source/gameengine')
140 files changed, 2829 insertions, 1624 deletions
diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp index 5f37de24ed6..1604dfe5cce 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp @@ -101,6 +101,13 @@ int KX_BlenderCanvas::GetHeight( return scrarea_get_win_height(m_area); } +RAS_Rect & +KX_BlenderCanvas:: +GetWindowArea( +){ + return m_area_rect; +} + void KX_BlenderCanvas:: SetViewPort( @@ -112,6 +119,11 @@ SetViewPort( int minx = scrarea_get_win_x(m_area); int miny = scrarea_get_win_y(m_area); + m_area_rect.SetLeft(minx + x1); + m_area_rect.SetBottom(miny + y1); + m_area_rect.SetRight(minx + x2); + m_area_rect.SetTop(miny + y2); + glViewport(minx + x1, miny + y1, vp_width, vp_height); glScissor(minx + x1, miny + y1, vp_width, vp_height); } diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h index b155d39e149..bc202a8558c 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h @@ -117,6 +117,10 @@ public: return m_displayarea; }; + RAS_Rect & + GetWindowArea( + ); + void SetViewPort( int x1, int y1, @@ -159,6 +163,7 @@ public: private: /** Blender area the game engine is running within */ struct ScrArea* m_area; + RAS_Rect m_area_rect; }; #endif // __KX_BLENDERCANVAS diff --git a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp index ed6ea7c5f6a..da52be56d1b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderGL.cpp @@ -170,6 +170,7 @@ void BL_RenderText(int mode,const char* textstr,int textlen,struct MTFace* tface void DisableForText() { if(glIsEnabled(GL_BLEND)) glDisable(GL_BLEND); + if(glIsEnabled(GL_ALPHA_TEST)) glDisable(GL_ALPHA_TEST); if(glIsEnabled(GL_LIGHTING)) { glDisable(GL_LIGHTING); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp b/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp deleted file mode 100644 index d173b1c66d9..00000000000 --- a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/** - * $Id$ - * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ***** - */ - -#include "KX_BlenderPolyMaterial.h" -#include "BKE_mesh.h" - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif -#if 0 -KX_BlenderPolyMaterial::KX_BlenderPolyMaterial(const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep, - int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - struct MTFace* tface) - : RAS_IPolyMaterial(texname, - false, - matname, - tile, - tilexrep, - tileyrep, - mode, - transparant, - zsort, - lightlayer, - bIsTriangle, - clientobject), - m_tface(tface) -{ -} - -void KX_BlenderPolyMaterial::Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const -{ - - - if (GetCachingInfo() != cachingInfo) - { - if (!cachingInfo) - { - set_tpage(NULL); - } - cachingInfo = GetCachingInfo(); - - if ((m_drawingmode & 4)&& (rasty->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED)) - { - update_realtime_texture((struct MTFace*) m_tface, rasty->GetTime()); - set_tpage(m_tface); - rasty->EnableTextures(true); - } - else - { - set_tpage(NULL); - rasty->EnableTextures(false); - } - - if(m_drawingmode & RAS_IRasterizer::KX_TWOSIDE) - { - rasty->SetCullFace(false); - } - else - { - rasty->SetCullFace(true); - } - - if (m_drawingmode & RAS_IRasterizer::KX_LINES) { - rasty->SetLines(true); - } - else { - rasty->SetLines(false); - } - } - - rasty->SetSpecularity(m_specular[0],m_specular[1],m_specular[2],m_specularity); - rasty->SetShinyness(m_shininess); - rasty->SetDiffuse(m_diffuse[0], m_diffuse[1],m_diffuse[2], 1.0); -} - - -#endif - - diff --git a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h b/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h deleted file mode 100644 index 35823b2125b..00000000000 --- a/source/gameengine/BlenderRoutines/KX_BlenderPolyMaterial.h +++ /dev/null @@ -1,99 +0,0 @@ -/** - * $Id$ - * - * ***** 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 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 ***** - */ -#ifndef __KX_BLENDERPOLYMATERIAL -#define __KX_BLENDERPOLYMATERIAL - -#include "RAS_MaterialBucket.h" -#include "RAS_IRasterizer.h" - -struct MTFace; -extern "C" int set_tpage(MTFace* tface); /* Worst hack ever */ - -#if 0 -class KX_BlenderPolyMaterial : public RAS_IPolyMaterial -{ - /** Blender texture face structure. */ - MTFace* m_tface; - -public: - - KX_BlenderPolyMaterial(const STR_String &texname, - bool ba, - const STR_String& matname, - int tile, - int tilexrep, - int tileyrep, - int mode, - bool transparant, - bool zsort, - int lightlayer, - bool bIsTriangle, - void* clientobject, - struct MTFace* tface); - - /** - * Returns the caching information for this material, - * This can be used to speed up the rasterizing process. - * @return The caching information. - */ - virtual TCachingInfo GetCachingInfo(void) const; - - /** - * Activates the material in the (OpenGL) rasterizer. - * On entry, the cachingInfo contains info about the last activated material. - * On exit, the cachingInfo should contain updated info about this material. - * @param rasty The rasterizer in which the material should be active. - * @param cachingInfo The information about the material used to speed up rasterizing. - */ - virtual void Activate(RAS_IRasterizer* rasty, TCachingInfo& cachingInfo) const; - - /** - * Returns the Blender texture face structure that is used for this material. - * @return The material's texture face. - */ - MTFace* GetMTFace(void) const; -protected: -private: -}; - - -inline MTFace* KX_BlenderPolyMaterial::GetMTFace(void) const -{ - return m_tface; -} - -inline RAS_IPolyMaterial::TCachingInfo KX_BlenderPolyMaterial::GetCachingInfo(void) const -{ - return GetMTFace(); -} - -#endif - -#endif // __KX_BLENDERPOLYMATERIAL - diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index 220d174d464..e4eff163d5b 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -40,7 +40,6 @@ // it needs the gameobject and the sumo physics scene for a raycast #include "KX_GameObject.h" -#include "KX_BlenderPolyMaterial.h" #include "KX_PolygonMaterial.h" #include "KX_BlenderMaterial.h" diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 5d6dd694765..2ee8b54a014 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -57,24 +57,12 @@ BL_ActionActuator::~BL_ActionActuator() { - - if (m_pose) { - free_pose_channels(m_pose); - MEM_freeN(m_pose); - m_pose = NULL; - }; - - if (m_userpose){ - free_pose_channels(m_userpose); - MEM_freeN(m_userpose); - m_userpose=NULL; - } - if (m_blendpose) { - free_pose_channels(m_blendpose); - MEM_freeN(m_blendpose); - m_blendpose = NULL; - }; - + if (m_pose) + free_pose(m_pose); + if (m_userpose) + free_pose(m_userpose); + if (m_blendpose) + free_pose(m_blendpose); } void BL_ActionActuator::ProcessReplica(){ diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index f73d5b42a01..09f1d9d4d87 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -82,10 +82,8 @@ void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica) BL_ArmatureObject::~BL_ArmatureObject() { - if (m_mrdPose){ - free_pose_channels(m_mrdPose); - MEM_freeN(m_mrdPose); - } + if (m_mrdPose) + free_pose(m_mrdPose); } /* note, you can only call this for exisiting Armature objects, and not mix it with other Armatures */ @@ -172,12 +170,13 @@ void BL_ArmatureObject::GetMRDPose(bPose **pose) // copy_pose (&m_mrdPose, m_pose, 0); //} - if (!*pose) + if (!*pose) { // must duplicate the constraints too otherwise we have corruption in free_pose_channels() // because it will free the blender constraints. // Ideally, blender should rememeber that the constraints were not copied so that // free_pose_channels() would not free them. copy_pose(pose, m_objArma->pose, 1); + } else extract_pose_from_pose(*pose, m_objArma->pose); diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index f3e22cd297a..f44318120e8 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -136,8 +136,12 @@ #include "BKE_mesh.h" #include "MT_Point3.h" +#include "BLI_arithb.h" + extern "C" { - #include "BKE_customdata.h" +#include "BKE_customdata.h" +#include "BKE_cdderivedmesh.h" +#include "BKE_DerivedMesh.h" } #include "BKE_material.h" /* give_current_material */ @@ -309,7 +313,6 @@ typedef struct MTF_localLayer // ------------------------------------ BL_Material* ConvertMaterial( - Mesh* mesh, Material *mat, MTFace* tface, const char *tfaceName, @@ -323,15 +326,16 @@ BL_Material* ConvertMaterial( //this needs some type of manager BL_Material *material = new BL_Material(); - int numchan = -1; + int numchan = -1, texalpha = 0; bool validmat = (mat!=0); - bool validface = (mesh->mtface && tface); + bool validface = (tface!=0); short type = 0; if( validmat ) type = 1; // material color material->IdMode = DEFAULT_BLENDER; + material->glslmat = (validmat)? glslmat: false; // -------------------------------- if(validmat) { @@ -367,12 +371,13 @@ BL_Material* ConvertMaterial( if(i==0 && facetex ) { Image*tmp = (Image*)(tface->tpage); + if(tmp) { material->img[i] = tmp; material->texname[i] = material->img[i]->id.name; material->flag[i] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; material->flag[i] |= ( tface->transp &TF_ADD )?CALCALPHA:0; - material->ras_mode|= ( tface->transp &(TF_ADD | TF_ALPHA))?TRANSP:0; + if(material->img[i]->flag & IMA_REFLECT) material->mapping[i].mapping |= USEREFL; else @@ -430,6 +435,8 @@ BL_Material* ConvertMaterial( material->flag[i] |= ( mttmp->mapto & MAP_ALPHA )?TEXALPHA:0; material->flag[i] |= ( mttmp->texflag& MTEX_NEGATIVE )?TEXNEG:0; + if(!glslmat && (material->flag[i] & TEXALPHA)) + texalpha = 1; } } else if(mttmp->tex->type == TEX_ENVMAP) { @@ -546,17 +553,7 @@ BL_Material* ConvertMaterial( material->ref = mat->ref; material->amb = mat->amb; - // set alpha testing without z-sorting - if( ( validface && (!(tface->transp &~ TF_CLIP))) && mat->mode & MA_ZTRA) { - // sets the RAS_IPolyMaterial::m_flag |RAS_FORCEALPHA - // this is so we don't have the overhead of the z-sorting code - material->ras_mode|=ALPHA_TEST; - } - else{ - // use regular z-sorting - material->ras_mode |= ((mat->mode & MA_ZTRA) != 0)?ZSORT:0; - } - material->ras_mode |= ((mat->mode & MA_WIRE) != 0)?WIRE:0; + material->ras_mode |= (mat->mode & MA_WIRE)? WIRE: 0; } else { int valid = 0; @@ -574,7 +571,6 @@ BL_Material* ConvertMaterial( material->mapping[0].mapping |= ( (material->img[0]->flag & IMA_REFLECT)!=0 )?USEREFL:0; material->flag[0] |= ( tface->transp &TF_ALPHA )?USEALPHA:0; material->flag[0] |= ( tface->transp &TF_ADD )?CALCALPHA:0; - material->ras_mode|= ( tface->transp & (TF_ADD|TF_ALPHA))?TRANSP:0; valid++; } } @@ -607,10 +603,6 @@ BL_Material* ConvertMaterial( material->ras_mode |= ( (tface->mode & TF_DYNAMIC)!= 0 )?COLLIDER:0; material->transp = tface->transp; - - if(tface->transp&~TF_CLIP) - material->ras_mode |= TRANSP; - material->tile = tface->tile; material->mode = tface->mode; @@ -631,7 +623,16 @@ BL_Material* ConvertMaterial( material->tile = 0; } + // with ztransp enabled, enforce alpha blending mode + if(validmat && (mat->mode & MA_ZTRA) && (material->transp == TF_SOLID)) + material->transp = TF_ALPHA; + // always zsort alpha + add + if((material->transp == TF_ALPHA || material->transp == TF_ADD || texalpha) + && (material->transp != TF_CLIP)) { + material->ras_mode |= ALPHA; + material->ras_mode |= (material->mode & TF_ALPHASORT)? ZSORT: 0; + } // get uv sets if(validmat) @@ -711,132 +712,54 @@ BL_Material* ConvertMaterial( } -static void BL_ComputeTriTangentSpace(const MT_Vector3 &v1, const MT_Vector3 &v2, const MT_Vector3 &v3, - const MT_Vector2 &uv1, const MT_Vector2 &uv2, const MT_Vector2 &uv3, - MFace* mface, MT_Vector3 *tan1, MT_Vector3 *tan2) -{ - MT_Vector3 dx1(v2 - v1), dx2(v3 - v1); - MT_Vector2 duv1(uv2 - uv1), duv2(uv3 - uv1); - - MT_Scalar r = 1.0 / (duv1.x() * duv2.y() - duv2.x() * duv1.y()); - duv1 *= r; - duv2 *= r; - MT_Vector3 sdir(duv2.y() * dx1 - duv1.y() * dx2); - MT_Vector3 tdir(duv1.x() * dx2 - duv2.x() * dx1); - - tan1[mface->v1] += sdir; - tan1[mface->v2] += sdir; - tan1[mface->v3] += sdir; - - tan2[mface->v1] += tdir; - tan2[mface->v2] += tdir; - tan2[mface->v3] += tdir; -} - -static MT_Vector4* BL_ComputeMeshTangentSpace(Mesh* mesh) -{ - MFace* mface = static_cast<MFace*>(mesh->mface); - MTFace* tface = static_cast<MTFace*>(mesh->mtface); - - MT_Vector3 *tan1 = new MT_Vector3[mesh->totvert]; - MT_Vector3 *tan2 = new MT_Vector3[mesh->totvert]; - - int v; - for (v = 0; v < mesh->totvert; v++) - { - tan1[v] = MT_Vector3(0.0, 0.0, 0.0); - tan2[v] = MT_Vector3(0.0, 0.0, 0.0); - } - - for (int p = 0; p < mesh->totface; p++, mface++, tface++) - { - MT_Vector3 v1(mesh->mvert[mface->v1].co), - v2(mesh->mvert[mface->v2].co), - v3(mesh->mvert[mface->v3].co); - - MT_Vector2 uv1(tface->uv[0]), - uv2(tface->uv[1]), - uv3(tface->uv[2]); - - BL_ComputeTriTangentSpace(v1, v2, v3, uv1, uv2, uv3, mface, tan1, tan2); - if (mface->v4) - { - MT_Vector3 v4(mesh->mvert[mface->v4].co); - MT_Vector2 uv4(tface->uv[3]); - - BL_ComputeTriTangentSpace(v1, v3, v4, uv1, uv3, uv4, mface, tan1, tan2); - } - } - - MT_Vector4 *tangent = new MT_Vector4[mesh->totvert]; - for (v = 0; v < mesh->totvert; v++) - { - const MT_Vector3 no(mesh->mvert[v].no[0]/32767.0, - mesh->mvert[v].no[1]/32767.0, - mesh->mvert[v].no[2]/32767.0); - // Gram-Schmidt orthogonalize - MT_Vector3 t(tan1[v] - no.cross(no.cross(tan1[v]))); - if (!MT_fuzzyZero(t)) - t /= t.length(); - - tangent[v].x() = t.x(); - tangent[v].y() = t.y(); - tangent[v].z() = t.z(); - // Calculate handedness - tangent[v].w() = no.dot(tan1[v].cross(tan2[v])) < 0.0 ? -1.0 : 1.0; - } - - delete [] tan1; - delete [] tan2; - - return tangent; -} - RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* rendertools, KX_Scene* scene, KX_BlenderSceneConverter *converter) { RAS_MeshObject *meshobj; - bool skinMesh = false; - + bool skinMesh = false; int lightlayer = blenderobj->lay; - - MFace* mface = static_cast<MFace*>(mesh->mface); - MTFace* tface = static_cast<MTFace*>(mesh->mtface); + + // Get DerivedMesh data + DerivedMesh *dm = CDDM_from_mesh(mesh, blenderobj); + + MVert *mvert = dm->getVertArray(dm); + int totvert = dm->getNumVerts(dm); + + MFace *mface = dm->getFaceArray(dm); + MTFace *tface = static_cast<MTFace*>(dm->getFaceDataArray(dm, CD_MTFACE)); + MCol *mcol = static_cast<MCol*>(dm->getFaceDataArray(dm, CD_MCOL)); + float (*tangent)[3] = NULL; + int totface = dm->getNumFaces(dm); const char *tfaceName = ""; - MCol* mmcol = mesh->mcol; - MT_assert(mface || mesh->totface == 0); + if(tface) { + DM_add_tangent_layer(dm); + tangent = (float(*)[3])dm->getFaceDataArray(dm, CD_TANGENT); + } // Determine if we need to make a skinned mesh - if (mesh->dvert || mesh->key){ + if (mesh->dvert || mesh->key) { meshobj = new BL_SkinMeshObject(mesh, lightlayer); skinMesh = true; } - else { + else meshobj = new RAS_MeshObject(mesh, lightlayer); - } - MT_Vector4 *tangent = 0; - if (tface) - tangent = BL_ComputeMeshTangentSpace(mesh); - // Extract avaiable layers MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE]; - for (int lay=0; lay<MAX_MTFACE; lay++) - { + for (int lay=0; lay<MAX_MTFACE; lay++) { layers[lay].face = 0; layers[lay].name = ""; } - int validLayers = 0; - for (int i=0; i<mesh->fdata.totlayer; i++) + for (int i=0; i<dm->faceData.totlayer; i++) { - if (mesh->fdata.layers[i].type == CD_MTFACE) + if (dm->faceData.layers[i].type == CD_MTFACE) { assert(validLayers <= 8); - layers[validLayers].face = (MTFace*)mesh->fdata.layers[i].data;; - layers[validLayers].name = mesh->fdata.layers[i].name; + layers[validLayers].face = (MTFace*)(dm->faceData.layers[i].data); + layers[validLayers].name = dm->faceData.layers[i].name; if(tface == layers[validLayers].face) tfaceName = layers[validLayers].name; validLayers++; @@ -844,271 +767,269 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } meshobj->SetName(mesh->id.name); - meshobj->m_xyz_index_to_vertex_index_mapping.resize(mesh->totvert); - for (int f=0;f<mesh->totface;f++,mface++) + meshobj->m_xyz_index_to_vertex_index_mapping.resize(totvert); + + for (int f=0;f<totface;f++,mface++) { - + Material* ma = 0; bool collider = true; - - // only add valid polygons - if (mface->v3) - { - MT_Point2 uv0(0.0,0.0),uv1(0.0,0.0),uv2(0.0,0.0),uv3(0.0,0.0); - MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0); - // rgb3 is set from the adjoint face in a square - unsigned int rgb0,rgb1,rgb2,rgb3 = 0; - MT_Vector3 no0(mesh->mvert[mface->v1].no[0], mesh->mvert[mface->v1].no[1], mesh->mvert[mface->v1].no[2]), - no1(mesh->mvert[mface->v2].no[0], mesh->mvert[mface->v2].no[1], mesh->mvert[mface->v2].no[2]), - no2(mesh->mvert[mface->v3].no[0], mesh->mvert[mface->v3].no[1], mesh->mvert[mface->v3].no[2]), - no3(0.0, 0.0, 0.0); - MT_Point3 pt0(mesh->mvert[mface->v1].co), - pt1(mesh->mvert[mface->v2].co), - pt2(mesh->mvert[mface->v3].co), - pt3(0.0, 0.0, 0.0); - MT_Vector4 tan0(0.0, 0.0, 0.0, 0.0), - tan1(0.0, 0.0, 0.0, 0.0), - tan2(0.0, 0.0, 0.0, 0.0), - tan3(0.0, 0.0, 0.0, 0.0); - - no0 /= 32767.0; - no1 /= 32767.0; - no2 /= 32767.0; - if (mface->v4) - { - pt3 = MT_Point3(mesh->mvert[mface->v4].co); - no3 = MT_Vector3(mesh->mvert[mface->v4].no[0], mesh->mvert[mface->v4].no[1], mesh->mvert[mface->v4].no[2]); - no3 /= 32767.0; + MT_Point2 uv0(0.0,0.0),uv1(0.0,0.0),uv2(0.0,0.0),uv3(0.0,0.0); + MT_Point2 uv20(0.0,0.0),uv21(0.0,0.0),uv22(0.0,0.0),uv23(0.0,0.0); + unsigned int rgb0,rgb1,rgb2,rgb3 = 0; + + MT_Vector3 no0, no1, no2, no3; + MT_Point3 pt0, pt1, pt2, pt3; + MT_Vector4 tan0, tan1, tan2, tan3; + + /* get coordinates, normals and tangents */ + pt0 = MT_Point3(mvert[mface->v1].co); + pt1 = MT_Point3(mvert[mface->v2].co); + pt2 = MT_Point3(mvert[mface->v3].co); + pt3 = (mface->v4)? MT_Point3(mvert[mface->v4].co): MT_Point3(0.0, 0.0, 0.0); + + if(mface->flag & ME_SMOOTH) { + float n0[3], n1[3], n2[3], n3[3]; + + NormalShortToFloat(n0, mvert[mface->v1].no); + NormalShortToFloat(n1, mvert[mface->v2].no); + NormalShortToFloat(n2, mvert[mface->v3].no); + no0 = n0; + no1 = n1; + no2 = n2; + + if(mface->v4) { + NormalShortToFloat(n3, mvert[mface->v4].no); + no3 = n3; } + else + no3 = MT_Vector3(0.0, 0.0, 0.0); + } + else { + float fno[3]; + + if(mface->v4) + CalcNormFloat4(mvert[mface->v1].co, mvert[mface->v2].co, + mvert[mface->v3].co, mvert[mface->v4].co, fno); + else + CalcNormFloat(mvert[mface->v1].co, mvert[mface->v2].co, + mvert[mface->v3].co, fno); + + no0 = no1 = no2 = no3 = MT_Vector3(fno); + } + + if(tangent) { + tan0 = tangent[f*4 + 0]; + tan1 = tangent[f*4 + 1]; + tan2 = tangent[f*4 + 2]; + + if (mface->v4) + tan3 = tangent[f*4 + 3]; + } + + /* get material */ + ma = give_current_material(blenderobj, mface->mat_nr+1); - if(!(mface->flag & ME_SMOOTH)) - { - MT_Vector3 norm = ((pt1-pt0).cross(pt2-pt0)).safe_normalized(); - norm[0] = ((int) (10*norm[0]))/10.0; - norm[1] = ((int) (10*norm[1]))/10.0; - norm[2] = ((int) (10*norm[2]))/10.0; - no0=no1=no2=no3= norm; - + { + bool polyvisible = true; + RAS_IPolyMaterial* polymat = NULL; + BL_Material *bl_mat = NULL; + + if(converter->GetMaterials()) { + /* do Blender Multitexture and Blender GLSL materials */ + unsigned int rgb[4]; + MT_Point2 uv[4]; + + /* first is the BL_Material */ + bl_mat = ConvertMaterial(ma, tface, tfaceName, mface, mcol, + lightlayer, blenderobj, layers, converter->GetGLSLMaterials()); + + bl_mat->material_index = (int)mface->mat_nr; + + polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); + collider = ((bl_mat->ras_mode & COLLIDER)!=0); + + /* vertex colors and uv's were stored in bl_mat temporarily */ + bl_mat->GetConversionRGB(rgb); + rgb0 = rgb[0]; rgb1 = rgb[1]; + rgb2 = rgb[2]; rgb3 = rgb[3]; + + bl_mat->GetConversionUV(uv); + uv0 = uv[0]; uv1 = uv[1]; + uv2 = uv[2]; uv3 = uv[3]; + + bl_mat->GetConversionUV2(uv); + uv20 = uv[0]; uv21 = uv[1]; + uv22 = uv[2]; uv23 = uv[3]; + + /* then the KX_BlenderMaterial */ + polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); } + else { + /* do Texture Face materials */ + Image* bima = (tface)? (Image*)tface->tpage: NULL; + STR_String imastr = (tface)? (bima? (bima)->id.name : "" ) : ""; - { - Material* ma = 0; - bool polyvisible = true; - RAS_IPolyMaterial* polymat = NULL; - BL_Material *bl_mat = NULL; - - if(converter->GetMaterials()) - { - if(mesh->totcol > 1) - ma = mesh->mat[mface->mat_nr]; - else - ma = give_current_material(blenderobj, 1); - - bl_mat = ConvertMaterial(mesh, ma, tface, tfaceName, mface, mmcol, lightlayer, blenderobj, layers, converter->GetGLSLMaterials()); - // set the index were dealing with - bl_mat->material_index = (int)mface->mat_nr; - - polyvisible = ((bl_mat->ras_mode & POLY_VIS)!=0); - collider = ((bl_mat->ras_mode & COLLIDER)!=0); + char transp=0; + short mode=0, tile=0; + int tilexrep=4,tileyrep = 4; + + if (bima) { + tilexrep = bima->xrep; + tileyrep = bima->yrep; + } + + /* get tface properties if available */ + if(tface) { + /* TF_DYNAMIC means the polygon is a collision face */ + collider = ((tface->mode & TF_DYNAMIC) != 0); + transp = tface->transp; + tile = tface->tile; + mode = tface->mode; - polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer, blenderobj ); + polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); - unsigned int rgb[4]; - bl_mat->GetConversionRGB(rgb); - rgb0 = rgb[0]; rgb1 = rgb[1]; - rgb2 = rgb[2]; rgb3 = rgb[3]; - MT_Point2 uv[4]; - bl_mat->GetConversionUV(uv); - uv0 = uv[0]; uv1 = uv[1]; - uv2 = uv[2]; uv3 = uv[3]; - - bl_mat->GetConversionUV2(uv); - uv20 = uv[0]; uv21 = uv[1]; - uv22 = uv[2]; uv23 = uv[3]; - - if(tangent){ - tan0 = tangent[mface->v1]; - tan1 = tangent[mface->v2]; - tan2 = tangent[mface->v3]; - if (mface->v4) - tan3 = tangent[mface->v4]; - } + uv0 = MT_Point2(tface->uv[0]); + uv1 = MT_Point2(tface->uv[1]); + uv2 = MT_Point2(tface->uv[2]); + + if (mface->v4) + uv3 = MT_Point2(tface->uv[3]); + } + else { + /* no texfaces, set COLLSION true and everything else FALSE */ + mode = default_face_mode; + transp = TF_SOLID; + tile = 0; } - else - { - ma = give_current_material(blenderobj, 1); - Image* bima = ((mesh->mtface && tface) ? (Image*) tface->tpage : NULL); - - STR_String imastr = - ((mesh->mtface && tface) ? - (bima? (bima)->id.name : "" ) : "" ); - - char transp=0; - short mode=0, tile=0; - int tilexrep=4,tileyrep = 4; + /* get vertex colors */ + if (mcol) { + /* we have vertex colors */ + rgb0 = KX_Mcol2uint_new(mcol[0]); + rgb1 = KX_Mcol2uint_new(mcol[1]); + rgb2 = KX_Mcol2uint_new(mcol[2]); - if (bima) - { - tilexrep = bima->xrep; - tileyrep = bima->yrep; - - } + if (mface->v4) + rgb3 = KX_Mcol2uint_new(mcol[3]); + } + else { + /* no vertex colors, take from material, otherwise white */ + unsigned int color = 0xFFFFFFFFL; - if (mesh->mtface && tface) + if (ma) { - // Use texface colors if available - //TF_DYNAMIC means the polygon is a collision face - collider = ((tface->mode & TF_DYNAMIC) != 0); - transp = tface->transp &~ TF_CLIP; - tile = tface->tile; - mode = tface->mode; - - polyvisible = !((mface->flag & ME_HIDE)||(tface->mode & TF_INVISIBLE)); + union + { + unsigned char cp[4]; + unsigned int integer; + } col_converter; - uv0 = MT_Point2(tface->uv[0]); - uv1 = MT_Point2(tface->uv[1]); - uv2 = MT_Point2(tface->uv[2]); - - if (mface->v4) - uv3 = MT_Point2(tface->uv[3]); - } - else - { - // no texfaces, set COLLSION true and everything else FALSE + col_converter.cp[3] = (unsigned char) (ma->r*255.0); + col_converter.cp[2] = (unsigned char) (ma->g*255.0); + col_converter.cp[1] = (unsigned char) (ma->b*255.0); + col_converter.cp[0] = (unsigned char) (ma->alpha*255.0); - mode = default_face_mode; - transp = TF_SOLID; - tile = 0; + color = col_converter.integer; } - if (mmcol) - { - // Use vertex colors - rgb0 = KX_Mcol2uint_new(mmcol[0]); - rgb1 = KX_Mcol2uint_new(mmcol[1]); - rgb2 = KX_Mcol2uint_new(mmcol[2]); - - if (mface->v4) - rgb3 = KX_Mcol2uint_new(mmcol[3]); - } - else { - // no vertex colors: take from material if we have one, - // otherwise set to white - unsigned int color = 0xFFFFFFFFL; + rgb0 = KX_rgbaint2uint_new(color); + rgb1 = KX_rgbaint2uint_new(color); + rgb2 = KX_rgbaint2uint_new(color); + + if (mface->v4) + rgb3 = KX_rgbaint2uint_new(color); + } + + bool istriangle = (mface->v4==0); - if (ma) - { - union - { - unsigned char cp[4]; - unsigned int integer; - } col_converter; - - col_converter.cp[3] = (unsigned char) (ma->r*255.0); - col_converter.cp[2] = (unsigned char) (ma->g*255.0); - col_converter.cp[1] = (unsigned char) (ma->b*255.0); - col_converter.cp[0] = (unsigned char) (ma->alpha*255.0); - - color = col_converter.integer; - } + // only zsort alpha + add + bool alpha = (transp == TF_ALPHA || transp == TF_ADD); + bool zsort = (mode & TF_ALPHASORT)? alpha: 0; + + polymat = new KX_PolygonMaterial(imastr, ma, + tile, tilexrep, tileyrep, + mode, transp, alpha, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mcol); - rgb0 = KX_rgbaint2uint_new(color); - rgb1 = KX_rgbaint2uint_new(color); - rgb2 = KX_rgbaint2uint_new(color); - - if (mface->v4) - rgb3 = KX_rgbaint2uint_new(color); - } - - bool istriangle = (mface->v4==0); - bool zsort = ma?(ma->mode & MA_ZTRA) != 0:false; - - polymat = new KX_PolygonMaterial(imastr, ma, - tile, tilexrep, tileyrep, - mode, transp, zsort, lightlayer, istriangle, blenderobj, tface, (unsigned int*)mmcol); - - if (ma) - { - polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; - polymat->m_shininess = (float)ma->har/4.0; // 0 < ma->har <= 512 - polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); + if (ma) { + polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; + polymat->m_shininess = (float)ma->har/4.0; // 0 < ma->har <= 512 + polymat->m_diffuse = MT_Vector3(ma->r, ma->g, ma->b)*(ma->emit + ma->ref); + } + else { + polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f); + polymat->m_shininess = 35.0; + } + } - } else - { - polymat->m_specular = MT_Vector3(0.0f,0.0f,0.0f); - polymat->m_shininess = 35.0; - } + // see if a bucket was reused or a new one was created + // this way only one KX_BlenderMaterial object has to exist per bucket + bool bucketCreated; + RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated); + if (bucketCreated) { + // this is needed to free up memory afterwards + converter->RegisterPolyMaterial(polymat); + if(converter->GetMaterials()) { + converter->RegisterBlenderMaterial(bl_mat); } - - // see if a bucket was reused or a new one was created - // this way only one KX_BlenderMaterial object has to exist per bucket - bool bucketCreated; - RAS_MaterialBucket* bucket = scene->FindBucket(polymat, bucketCreated); - if (bucketCreated) { - // this is needed to free up memory afterwards - converter->RegisterPolyMaterial(polymat); - if(converter->GetMaterials()) { - converter->RegisterBlenderMaterial(bl_mat); - } - } else { - // delete the material objects since they are no longer needed - // from now on, use the polygon material from the material bucket - delete polymat; - if(converter->GetMaterials()) { - delete bl_mat; - } - polymat = bucket->GetPolyMaterial(); + } else { + // delete the material objects since they are no longer needed + // from now on, use the polygon material from the material bucket + delete polymat; + if(converter->GetMaterials()) { + delete bl_mat; } - - int nverts = mface->v4?4:3; - int vtxarray = meshobj->FindVertexArray(nverts,polymat); - RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); + polymat = bucket->GetPolyMaterial(); + } + + int nverts = mface->v4?4:3; + int vtxarray = meshobj->FindVertexArray(nverts,polymat); + RAS_Polygon* poly = new RAS_Polygon(bucket,polyvisible,nverts,vtxarray); - bool flat; + bool flat; - if (skinMesh) { - /* If the face is set to solid, all fnors are the same */ - if (mface->flag & ME_SMOOTH) - flat = false; - else - flat = true; - } - else + if (skinMesh) { + /* If the face is set to solid, all fnors are the same */ + if (mface->flag & ME_SMOOTH) flat = false; + else + flat = true; + } + else + flat = false; - poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); - poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); - poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); - if (nverts==4) - poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); + poly->SetVertex(0,meshobj->FindOrAddVertex(vtxarray,pt0,uv0,uv20,tan0,rgb0,no0,flat,polymat,mface->v1)); + poly->SetVertex(1,meshobj->FindOrAddVertex(vtxarray,pt1,uv1,uv21,tan1,rgb1,no1,flat,polymat,mface->v2)); + poly->SetVertex(2,meshobj->FindOrAddVertex(vtxarray,pt2,uv2,uv22,tan2,rgb2,no2,flat,polymat,mface->v3)); + if (nverts==4) + poly->SetVertex(3,meshobj->FindOrAddVertex(vtxarray,pt3,uv3,uv23,tan3,rgb3,no3,flat,polymat,mface->v4)); - meshobj->AddPolygon(poly); - if (poly->IsCollider()) + meshobj->AddPolygon(poly); + if (poly->IsCollider()) + { + RAS_TriangleIndex idx; + idx.m_index[0] = mface->v1; + idx.m_index[1] = mface->v2; + idx.m_index[2] = mface->v3; + idx.m_collider = collider; + meshobj->m_triangle_indices.push_back(idx); + if (nverts==4) { - RAS_TriangleIndex idx; - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v2; - idx.m_index[2] = mface->v3; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - if (nverts==4) - { - idx.m_index[0] = mface->v1; - idx.m_index[1] = mface->v3; - idx.m_index[2] = mface->v4; - idx.m_collider = collider; - meshobj->m_triangle_indices.push_back(idx); - } + idx.m_index[0] = mface->v1; + idx.m_index[1] = mface->v3; + idx.m_index[2] = mface->v4; + idx.m_collider = collider; + meshobj->m_triangle_indices.push_back(idx); } - -// poly->SetVisibleWireframeEdges(mface->edcode); - poly->SetCollider(collider); } + +// poly->SetVisibleWireframeEdges(mface->edcode); + poly->SetCollider(collider); } + if (tface) tface++; - if (mmcol) - mmcol+=4; + if (mcol) + mcol+=4; for (int lay=0; lay<MAX_MTFACE; lay++) { @@ -1127,11 +1048,10 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* (*mit)->GetPolyMaterial()->OnConstruction(); } - if(tangent) - delete [] tangent; - if (layers) delete []layers; + + dm->release(dm); return meshobj; } @@ -1819,7 +1739,7 @@ KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist){ return 0; } -#include "BLI_arithb.h" + // convert blender objects into ketsji gameobjects void BL_ConvertBlenderObjects(struct Main* maggie, const STR_String& scenename, @@ -1847,7 +1767,10 @@ void BL_ConvertBlenderObjects(struct Main* maggie, int aspect_width; int aspect_height; vector<MT_Vector3> inivel,iniang; - + set<Group*> grouplist; // list of groups to be converted + set<Object*> allblobj; // all objects converted + set<Object*> groupobj; // objects from groups (never in active layer) + if (alwaysUseExpandFraming) { frame_type = RAS_FrameSettings::e_frame_extend; aspect_width = canvas->GetWidth(); @@ -1919,6 +1842,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for (SETLOOPER(blenderscene, base)) { Object* blenderobject = base->object; + allblobj.insert(blenderobject); + KX_GameObject* gameobj = gameobject_from_blenderobject( base->object, kxscene, @@ -1932,7 +1857,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, if (converter->addInitFromFrame) if (!isInActiveLayer) addobj=false; - + if (gameobj&&addobj) { MT_Point3 posPrev; @@ -1984,10 +1909,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeUpdateGS(0,true); BL_ConvertIpos(blenderobject,gameobj,converter); - // TODO: expand to multiple ipos per mesh - Material *mat = give_current_material(blenderobject, 1); - if(mat) BL_ConvertMaterialIpos(mat, gameobj, converter); - + BL_ConvertMaterialIpos(blenderobject, gameobj, converter); + sumolist->Add(gameobj->AddRef()); BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer); @@ -2024,8 +1947,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // needed for python scripting logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj); - // needed for dynamic object morphing - logicmgr->RegisterGameObj(gameobj, blenderobject); + // needed for group duplication + logicmgr->RegisterGameObj(blenderobject, gameobj); for (int i = 0; i < gameobj->GetMeshCount(); i++) logicmgr->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), blenderobject); @@ -2046,7 +1969,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->NodeUpdateGS(0,true); gameobj->Bucketize(); - + } else { @@ -2054,6 +1977,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, //at the end of this function if it is not a root object inactivelist->Add(gameobj->AddRef()); } + if (gameobj->IsDupliGroup()) + grouplist.insert(blenderobject->dup_group); if (converter->addInitFromFrame){ gameobj->NodeSetLocalPosition(posPrev); gameobj->NodeSetLocalOrientation(angor); @@ -2073,7 +1998,188 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } - if (blenderscene->camera) { + if (!grouplist.empty()) + { + // now convert the group referenced by dupli group object + // keep track of all groups already converted + set<Group*> allgrouplist = grouplist; + set<Group*> tempglist; + // recurse + while (!grouplist.empty()) + { + set<Group*>::iterator git; + tempglist.clear(); + tempglist.swap(grouplist); + for (git=tempglist.begin(); git!=tempglist.end(); git++) + { + Group* group = *git; + GroupObject* go; + for(go=(GroupObject*)group->gobject.first; go; go=(GroupObject*)go->next) + { + Object* blenderobject = go->ob; + if (converter->FindGameObject(blenderobject) == NULL) + { + allblobj.insert(blenderobject); + groupobj.insert(blenderobject); + KX_GameObject* gameobj = gameobject_from_blenderobject( + blenderobject, + kxscene, + rendertools, + converter, + blenderscene); + + // this code is copied from above except that + // object from groups are never in active layer + bool isInActiveLayer = false; + bool addobj=true; + + if (converter->addInitFromFrame) + if (!isInActiveLayer) + addobj=false; + + if (gameobj&&addobj) + { + MT_Point3 posPrev; + MT_Matrix3x3 angor; + if (converter->addInitFromFrame) + blenderscene->r.cfra=blenderscene->r.sfra; + + MT_Point3 pos = MT_Point3( + blenderobject->loc[0]+blenderobject->dloc[0], + blenderobject->loc[1]+blenderobject->dloc[1], + blenderobject->loc[2]+blenderobject->dloc[2] + ); + MT_Vector3 eulxyz = MT_Vector3( + blenderobject->rot[0], + blenderobject->rot[1], + blenderobject->rot[2] + ); + MT_Vector3 scale = MT_Vector3( + blenderobject->size[0], + blenderobject->size[1], + blenderobject->size[2] + ); + if (converter->addInitFromFrame){//rcruiz + float eulxyzPrev[3]; + blenderscene->r.cfra=blenderscene->r.sfra-1; + update_for_newframe(); + MT_Vector3 tmp=pos-MT_Point3(blenderobject->loc[0]+blenderobject->dloc[0], + blenderobject->loc[1]+blenderobject->dloc[1], + blenderobject->loc[2]+blenderobject->dloc[2] + ); + eulxyzPrev[0]=blenderobject->rot[0]; + eulxyzPrev[1]=blenderobject->rot[1]; + eulxyzPrev[2]=blenderobject->rot[2]; + + double fps = (double) blenderscene->r.frs_sec/ + (double) blenderscene->r.frs_sec_base; + + tmp.scale(fps, fps, fps); + inivel.push_back(tmp); + tmp=eulxyz-eulxyzPrev; + tmp.scale(fps, fps, fps); + iniang.push_back(tmp); + blenderscene->r.cfra=blenderscene->r.sfra; + update_for_newframe(); + } + + gameobj->NodeSetLocalPosition(pos); + gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz)); + gameobj->NodeSetLocalScale(scale); + gameobj->NodeUpdateGS(0,true); + + BL_ConvertIpos(blenderobject,gameobj,converter); + BL_ConvertMaterialIpos(blenderobject,gameobj, converter); + + sumolist->Add(gameobj->AddRef()); + + BL_ConvertProperties(blenderobject,gameobj,timemgr,kxscene,isInActiveLayer); + + + gameobj->SetName(blenderobject->id.name); + + // templist to find Root Parents (object with no parents) + templist->Add(gameobj->AddRef()); + + // update children/parent hierarchy + if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame)) + { + // blender has an additional 'parentinverse' offset in each object + SG_Node* parentinversenode = new SG_Node(NULL,NULL,SG_Callbacks()); + + // define a normal parent relationship for this node. + KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New(); + parentinversenode->SetParentRelation(parent_relation); + + parentChildLink pclink; + pclink.m_blenderchild = blenderobject; + pclink.m_gamechildnode = parentinversenode; + vec_parent_child.push_back(pclink); + + float* fl = (float*) blenderobject->parentinv; + MT_Transform parinvtrans(fl); + parentinversenode->SetLocalPosition(parinvtrans.getOrigin()); + parentinversenode->SetLocalOrientation(parinvtrans.getBasis()); + + parentinversenode->AddChild(gameobj->GetSGNode()); + } + + // needed for python scripting + logicmgr->RegisterGameObjectName(gameobj->GetName(),gameobj); + + // needed for group duplication + logicmgr->RegisterGameObj(blenderobject, gameobj); + for (int i = 0; i < gameobj->GetMeshCount(); i++) + logicmgr->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), blenderobject); + + converter->RegisterGameObject(gameobj, blenderobject); + // this was put in rapidly, needs to be looked at more closely + // only draw/use objects in active 'blender' layers + + logicbrick_conversionlist->Add(gameobj->AddRef()); + + if (converter->addInitFromFrame){ + posPrev=gameobj->NodeGetWorldPosition(); + angor=gameobj->NodeGetWorldOrientation(); + } + if (isInActiveLayer) + { + objectlist->Add(gameobj->AddRef()); + //tf.Add(gameobj->GetSGNode()); + + gameobj->NodeUpdateGS(0,true); + gameobj->Bucketize(); + + } + else + { + //we must store this object otherwise it will be deleted + //at the end of this function if it is not a root object + inactivelist->Add(gameobj->AddRef()); + + } + if (gameobj->IsDupliGroup()) + { + // check that the group is not already converted + if (allgrouplist.insert(blenderobject->dup_group).second) + grouplist.insert(blenderobject->dup_group); + } + if (converter->addInitFromFrame){ + gameobj->NodeSetLocalPosition(posPrev); + gameobj->NodeSetLocalOrientation(angor); + } + + } + if (gameobj) + gameobj->Release(); + } + } + } + } + } + + // non-camera objects not supported as camera currently + if (blenderscene->camera && blenderscene->camera->type == OB_CAMERA) { KX_Camera *gamecamera= (KX_Camera*) converter->FindGameObject(blenderscene->camera); if(gamecamera) @@ -2081,15 +2187,18 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } // Set up armatures - for(SETLOOPER(blenderscene, base)){ - if (base->object->type==OB_MESH){ - Mesh *me = (Mesh*)base->object->data; + set<Object*>::iterator oit; + for(oit=allblobj.begin(); oit!=allblobj.end(); oit++) + { + Object* blenderobj = *oit; + if (blenderobj->type==OB_MESH){ + Mesh *me = (Mesh*)blenderobj->data; if (me->dvert){ - KX_GameObject *obj = converter->FindGameObject(base->object); + KX_GameObject *obj = converter->FindGameObject(blenderobj); - if (base->object->parent && base->object->parent->type==OB_ARMATURE && base->object->partype==PARSKEL){ - KX_GameObject *par = converter->FindGameObject(base->object->parent); + if (obj && blenderobj->parent && blenderobj->parent->type==OB_ARMATURE && blenderobj->partype==PARSKEL){ + KX_GameObject *par = converter->FindGameObject(blenderobj->parent); if (par) ((BL_SkinDeformer*)(((BL_DeformableGameObject*)obj)->m_pDeformer))->SetArmature((BL_ArmatureObject*) par); } @@ -2174,7 +2283,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { meshobj = gameobj->GetMesh(0); } - BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,activeLayerBitInfo,physics_engine,converter,processCompoundChildren); + int layerMask = (groupobj.find(blenderobject) == groupobj.end()) ? activeLayerBitInfo : 0; + BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren); } processCompoundChildren = true; @@ -2189,7 +2299,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { meshobj = gameobj->GetMesh(0); } - BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,activeLayerBitInfo,physics_engine,converter,processCompoundChildren); + int layerMask = (groupobj.find(blenderobject) == groupobj.end()) ? activeLayerBitInfo : 0; + BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren); } @@ -2311,29 +2422,32 @@ void BL_ConvertBlenderObjects(struct Main* maggie, { KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i)); struct Object* blenderobj = converter->FindBlenderObject(gameobj); - bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0; - BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,executePriority, activeLayerBitInfo,isInActiveLayer,rendertools,converter); + int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; + bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; + BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,executePriority, layerMask,isInActiveLayer,rendertools,converter); } for ( i=0;i<logicbrick_conversionlist->GetCount();i++) { KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i)); struct Object* blenderobj = converter->FindBlenderObject(gameobj); - bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0; - BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,executePriority,activeLayerBitInfo,isInActiveLayer,converter); + int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; + bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; + BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,executePriority,layerMask,isInActiveLayer,converter); } for ( i=0;i<logicbrick_conversionlist->GetCount();i++) { KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i)); struct Object* blenderobj = converter->FindBlenderObject(gameobj); - bool isInActiveLayer = (blenderobj->lay & activeLayerBitInfo)!=0; - BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,activeLayerBitInfo,isInActiveLayer,canvas,converter); + int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; + bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; + BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter); + // set the init state to all objects + gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state); } - // apply the initial state to controllers - for ( i=0;i<logicbrick_conversionlist->GetCount();i++) + // apply the initial state to controllers, only on the active objects as this registers the sensors + for ( i=0;i<objectlist->GetCount();i++) { - KX_GameObject* gameobj = static_cast<KX_GameObject*>(logicbrick_conversionlist->GetValue(i)); - struct Object* blenderobj = converter->FindBlenderObject(gameobj); - gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state); + KX_GameObject* gameobj = static_cast<KX_GameObject*>(objectlist->GetValue(i)); gameobj->ResetState(); } @@ -2344,5 +2458,19 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // Calculate the scene btree - // too slow - commented out. //kxscene->SetNodeTree(tf.MakeTree()); + + // instantiate dupli group, we will loop trough the object + // that are in active layers. Note that duplicating group + // has the effect of adding objects at the end of objectlist. + // Only loop through the first part of the list. + int objcount = objectlist->GetCount(); + for (i=0;i<objcount;i++) + { + KX_GameObject* gameobj = (KX_GameObject*) objectlist->GetValue(i); + if (gameobj->IsDupliGroup()) + { + kxscene->DupliGroupRecurse(gameobj, 0); + } + } } diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h index 57a404ad72b..315ad18c42c 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.h +++ b/source/gameengine/Converter/BL_DeformableGameObject.h @@ -60,6 +60,7 @@ public: { if (m_pDeformer) m_pDeformer->Relink (map); + KX_GameObject::Relink(map); }; void ProcessReplica(KX_GameObject* replica); diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 41bf565a4d8..7fb5d7ff829 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -442,15 +442,15 @@ PyMethodDef BL_ShapeActionActuator::Methods[] = { {"setProperty", (PyCFunction) BL_ShapeActionActuator::sPySetProperty, METH_VARARGS, SetProperty_doc}, {"setBlendtime", (PyCFunction) BL_ShapeActionActuator::sPySetBlendtime, METH_VARARGS, SetBlendtime_doc}, - {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_VARARGS, GetAction_doc}, - {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_VARARGS, GetStart_doc}, - {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_VARARGS, GetEnd_doc}, - {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_VARARGS, GetBlendin_doc}, - {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_VARARGS, GetPriority_doc}, - {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_VARARGS, GetFrame_doc}, - {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc}, - {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_VARARGS, GetType_doc}, - {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_VARARGS, SetType_doc}, + {"getAction", (PyCFunction) BL_ShapeActionActuator::sPyGetAction, METH_NOARGS, GetAction_doc}, + {"getStart", (PyCFunction) BL_ShapeActionActuator::sPyGetStart, METH_NOARGS, GetStart_doc}, + {"getEnd", (PyCFunction) BL_ShapeActionActuator::sPyGetEnd, METH_NOARGS, GetEnd_doc}, + {"getBlendin", (PyCFunction) BL_ShapeActionActuator::sPyGetBlendin, METH_NOARGS, GetBlendin_doc}, + {"getPriority", (PyCFunction) BL_ShapeActionActuator::sPyGetPriority, METH_NOARGS, GetPriority_doc}, + {"getFrame", (PyCFunction) BL_ShapeActionActuator::sPyGetFrame, METH_NOARGS, GetFrame_doc}, + {"getProperty", (PyCFunction) BL_ShapeActionActuator::sPyGetProperty, METH_NOARGS, GetProperty_doc}, + {"getType", (PyCFunction) BL_ShapeActionActuator::sPyGetType, METH_NOARGS, GetType_doc}, + {"setType", (PyCFunction) BL_ShapeActionActuator::sPySetType, METH_NOARGS, SetType_doc}, {NULL,NULL} //Sentinel }; @@ -463,9 +463,7 @@ char BL_ShapeActionActuator::GetAction_doc[] = "getAction()\n" "\tReturns a string containing the name of the current action.\n"; -PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetAction(PyObject* self) { PyObject *result; if (m_action){ @@ -484,9 +482,7 @@ char BL_ShapeActionActuator::GetProperty_doc[] = "getProperty()\n" "\tReturns the name of the property to be used in FromProp mode.\n"; -PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetProperty(PyObject* self) { PyObject *result; result = Py_BuildValue("s", (const char *)m_propname); @@ -499,9 +495,7 @@ char BL_ShapeActionActuator::GetFrame_doc[] = "getFrame()\n" "\tReturns the current frame number.\n"; -PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetFrame(PyObject* self) { PyObject *result; result = Py_BuildValue("f", m_localtime); @@ -514,9 +508,7 @@ char BL_ShapeActionActuator::GetEnd_doc[] = "getEnd()\n" "\tReturns the last frame of the action.\n"; -PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetEnd(PyObject* self) { PyObject *result; result = Py_BuildValue("f", m_endframe); @@ -529,9 +521,7 @@ char BL_ShapeActionActuator::GetStart_doc[] = "getStart()\n" "\tReturns the starting frame of the action.\n"; -PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetStart(PyObject* self) { PyObject *result; result = Py_BuildValue("f", m_startframe); @@ -545,9 +535,7 @@ char BL_ShapeActionActuator::GetBlendin_doc[] = "\tReturns the number of interpolation animation frames to be\n" "\tgenerated when this actuator is triggered.\n"; -PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetBlendin(PyObject* self) { PyObject *result; result = Py_BuildValue("f", m_blendin); @@ -561,9 +549,7 @@ char BL_ShapeActionActuator::GetPriority_doc[] = "\tReturns the priority for this actuator. Actuators with lower\n" "\tPriority numbers will override actuators with higher numbers.\n"; -PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetPriority(PyObject* self) { PyObject *result; result = Py_BuildValue("i", m_priority); @@ -605,6 +591,7 @@ PyObject* BL_ShapeActionActuator::PySetAction(PyObject* self, } } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -627,6 +614,7 @@ PyObject* BL_ShapeActionActuator::PySetStart(PyObject* self, m_startframe = start; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -649,6 +637,7 @@ PyObject* BL_ShapeActionActuator::PySetEnd(PyObject* self, m_endframe = end; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -672,6 +661,7 @@ PyObject* BL_ShapeActionActuator::PySetBlendin(PyObject* self, m_blendin = blendin; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -700,6 +690,7 @@ PyObject* BL_ShapeActionActuator::PySetBlendtime(PyObject* self, m_blendframe = m_blendin; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -724,6 +715,7 @@ PyObject* BL_ShapeActionActuator::PySetPriority(PyObject* self, m_priority = priority; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -750,6 +742,7 @@ PyObject* BL_ShapeActionActuator::PySetFrame(PyObject* self, m_localtime=m_endframe; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -773,6 +766,7 @@ PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self, m_propname = string; } else { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -784,9 +778,7 @@ PyObject* BL_ShapeActionActuator::PySetProperty(PyObject* self, char BL_ShapeActionActuator::GetType_doc[] = "getType()\n" "\tReturns the operation mode of the actuator.\n"; -PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* BL_ShapeActionActuator::PyGetType(PyObject* self) { return Py_BuildValue("h", m_playtype); } @@ -801,6 +793,7 @@ PyObject* BL_ShapeActionActuator::PySetType(PyObject* self, short typeArg; if (!PyArg_ParseTuple(args, "h", &typeArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index 434a62a1233..10cbe9f1ac3 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -1,5 +1,5 @@ /** - * $Id$ + * $Id:BL_ShapeActionActuator.h 15330 2008-06-23 16:37:51Z theeth $ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -87,15 +87,15 @@ public: KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetBlendtime); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetChannel); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetAction); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetBlendin); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetPriority); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetStart); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetEnd); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetFrame); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetProperty); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetAction); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetBlendin); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetPriority); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetStart); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetEnd); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetFrame); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetProperty); // KX_PYMETHOD(BL_ActionActuator,GetChannel); - KX_PYMETHOD_DOC(BL_ShapeActionActuator,GetType); + KX_PYMETHOD_DOC_NOARGS(BL_ShapeActionActuator,GetType); KX_PYMETHOD_DOC(BL_ShapeActionActuator,SetType); virtual PyObject* _getattr(const STR_String& attr); diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index f2af0d9294e..d3fbb795b23 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -109,6 +109,13 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void) vector<IpoCurve*>::iterator it; void *poin; int type; + // the shape drivers use the bone matrix as input. Must + // update the matrix now + Object* par_arma = m_armobj->GetArmatureObject(); + m_armobj->ApplyPose(); + where_is_pose( par_arma ); + PoseApplied(true); + for (it=m_shapeDrivers.begin(); it!=m_shapeDrivers.end(); it++) { // no need to set a specific time: this curve has a driver IpoCurve *icu = *it; diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index d3442fe5298..f96c40c098f 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -66,7 +66,8 @@ BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj, m_armobj(arma), m_lastArmaUpdate(-1), m_defbase(&bmeshobj->defbase), - m_releaseobject(false) + m_releaseobject(false), + m_poseApplied(false) { Mat4CpyMat4(m_obmat, bmeshobj->obmat); }; @@ -98,32 +99,28 @@ BL_SkinDeformer::~BL_SkinDeformer() m_armobj->Release(); } -bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *) +bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) { size_t i, j; - if (!Update()) - // no need to update the cache - return false; + // update the vertex in m_transverts + Update(); - // Update all materials at once, so we can do the above update test - // without ending up with some materials not updated - for(RAS_MaterialBucket::Set::iterator mit = m_pMeshObject->GetFirstMaterial(); - mit != m_pMeshObject->GetLastMaterial(); ++ mit) { - RAS_IPolyMaterial *mat = (*mit)->GetPolyMaterial(); + // The vertex cache can only be updated for this deformer: + // Duplicated objects with more than one ploymaterial (=multiple mesh slot per object) + // share the same mesh (=the same cache). As the rendering is done per polymaterial + // cycling through the objects, the entire mesh cache cannot be updated in one shot. + vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); - vecVertexArray& vertexarrays = m_pMeshObject->GetVertexCache(mat); + // For each array + for (i=0; i<vertexarrays.size(); i++) { + KX_VertexArray& vertexarray = (*vertexarrays[i]); - // For each array - for (i=0; i<vertexarrays.size(); i++) { - KX_VertexArray& vertexarray = (*vertexarrays[i]); - - // For each vertex - // copy the untransformed data from the original mvert - for (j=0; j<vertexarray.size(); j++) { - RAS_TexVert& v = vertexarray[j]; - v.SetXYZ(m_transverts[v.getOrigIndex()]); - } + // For each vertex + // copy the untransformed data from the original mvert + for (j=0; j<vertexarray.size(); j++) { + RAS_TexVert& v = vertexarray[j]; + v.SetXYZ(m_transverts[v.getOrigIndex()]); } } @@ -153,9 +150,11 @@ bool BL_SkinDeformer::Update(void) /* XXX note: where_is_pose() (from BKE_armature.h) calculates all matrices needed to start deforming */ /* but it requires the blender object pointer... */ - Object* par_arma = m_armobj->GetArmatureObject(); - where_is_pose( par_arma ); + if (!PoseApplied()){ + m_armobj->ApplyPose(); + where_is_pose( par_arma ); + } /* store verts locally */ VerifyStorage(); @@ -180,7 +179,8 @@ bool BL_SkinDeformer::Update(void) /* Update the current frame */ m_lastArmaUpdate=m_armobj->GetLastFrame(); - + /* reset for next frame */ + PoseApplied(false); /* indicate that the m_transverts and normals are up to date */ return true; } diff --git a/source/gameengine/Converter/BL_SkinDeformer.h b/source/gameengine/Converter/BL_SkinDeformer.h index f35db8273c4..d3fc5ae2a81 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -81,10 +81,13 @@ public: virtual ~BL_SkinDeformer(); bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); + bool PoseApplied() + { return m_poseApplied; } + void PoseApplied(bool applied) + { m_poseApplied = applied; } bool PoseUpdated(void) { if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()) { - m_armobj->ApplyPose(); return true; } return false; @@ -102,6 +105,7 @@ protected: ListBase* m_defbase; float m_obmat[4][4]; // the reference matrix for skeleton deform bool m_releaseobject; + bool m_poseApplied; }; diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index 1cc1b2e27a3..53ac730d203 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -503,7 +503,7 @@ void BL_ConvertActuators(char* maggiename, case ACT_PROPERTY: { bPropertyActuator* propact = (bPropertyActuator*) bact->data; - CValue* destinationObj = NULL; + SCA_IObject* destinationObj = NULL; /* here the destinationobject is searched. problem with multiple scenes: other scenes @@ -628,6 +628,8 @@ void BL_ConvertActuators(char* maggiename, /* convert settings... degrees in the ui become radians */ /* internally */ if (conact->type == ACT_CONST_TYPE_ORI) { + min = (MT_2_PI * conact->minloc[0])/360.0; + max = (MT_2_PI * conact->maxloc[0])/360.0; switch (conact->mode) { case ACT_CONST_DIRPX: locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIX; @@ -656,18 +658,18 @@ void BL_ConvertActuators(char* maggiename, min = conact->minloc[2]; max = conact->maxloc[2]; break; - case ACT_CONST_DIRMX: - locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRMX; + case ACT_CONST_DIRNX: + locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNX; min = conact->minloc[0]; max = conact->maxloc[0]; break; - case ACT_CONST_DIRMY: - locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRMY; + case ACT_CONST_DIRNY: + locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNY; min = conact->minloc[1]; max = conact->maxloc[1]; break; - case ACT_CONST_DIRMZ: - locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRMZ; + case ACT_CONST_DIRNZ: + locrot = KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNZ; min = conact->minloc[2]; max = conact->maxloc[2]; break; diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 7c9df688d45..5e433bb821b 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -733,9 +733,9 @@ void BL_ConvertSensors(struct Object* blenderobject, gameobj->AddSensor(gamesensor); // only register to manager if it's in an active layer - - if (isInActiveLayer) - gamesensor->RegisterToManager(); + // Make registration dynamic: only when sensor is activated + //if (isInActiveLayer) + // gamesensor->RegisterToManager(); for (int i=0;i<sens->totlinks;i++) diff --git a/source/gameengine/Converter/KX_IpoConvert.cpp b/source/gameengine/Converter/KX_IpoConvert.cpp index 75ca59d01e7..7410beecaf4 100644 --- a/source/gameengine/Converter/KX_IpoConvert.cpp +++ b/source/gameengine/Converter/KX_IpoConvert.cpp @@ -36,6 +36,7 @@ #pragma warning (disable:4786) #endif +#include "BKE_material.h" /* give_current_material */ #include "KX_GameObject.h" #include "KX_IpoConvert.h" @@ -68,6 +69,8 @@ #include "SG_Node.h" +#include "STR_HashedString.h" + static BL_InterpolatorList *GetIpoList(struct Ipo *for_ipo, KX_BlenderSceneConverter *converter) { BL_InterpolatorList *ipoList= converter->FindInterpolatorList(for_ipo); @@ -560,16 +563,15 @@ void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *co } } - -void BL_ConvertMaterialIpos( - Material* blendermaterial, +static void ConvertMaterialIpos( + Material* blendermaterial, + dword matname_hash, KX_GameObject* gameobj, KX_BlenderSceneConverter *converter ) { if (blendermaterial->ipo) { - - KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(); + KX_MaterialIpoController* ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); @@ -596,7 +598,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_COL_R); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -610,7 +612,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_COL_G); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -624,7 +626,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_COL_B); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -638,7 +640,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_ALPHA); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -653,7 +655,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC_R ); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -667,7 +669,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC_G); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -681,7 +683,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC_B); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -696,7 +698,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_HARD); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -710,7 +712,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_SPEC); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -725,7 +727,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_REF); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -739,7 +741,7 @@ void BL_ConvertMaterialIpos( ipo = ipoList->GetScalarInterpolator(MA_EMIT); if (ipo) { if (!ipocontr) { - ipocontr = new KX_MaterialIpoController(); + ipocontr = new KX_MaterialIpoController(matname_hash); gameobj->GetSGNode()->AddSGController(ipocontr); ipocontr->SetObject(gameobj->GetSGNode()); } @@ -752,3 +754,28 @@ void BL_ConvertMaterialIpos( } } +void BL_ConvertMaterialIpos( + struct Object* blenderobject, + KX_GameObject* gameobj, + KX_BlenderSceneConverter *converter + ) +{ + if (blenderobject->totcol==1) + { + Material *mat = give_current_material(blenderobject, 1); + // if there is only one material attached to the mesh then set material_index in BL_ConvertMaterialIpos to NULL + // --> this makes the UpdateMaterialData function in KX_GameObject.cpp use the old hack of using SetObjectColor + // because this yields a better performance as not all the vertex colors need to be edited + if(mat) ConvertMaterialIpos(mat, NULL, gameobj, converter); + } + else + { + for (int material_index=1; material_index <= blenderobject->totcol; material_index++) + { + Material *mat = give_current_material(blenderobject, material_index); + STR_HashedString matname = mat->id.name; + if(mat) ConvertMaterialIpos(mat, matname.hash(), gameobj, converter); + } + } +} + diff --git a/source/gameengine/Converter/KX_IpoConvert.h b/source/gameengine/Converter/KX_IpoConvert.h index afcb1b22821..4ec9bd31062 100644 --- a/source/gameengine/Converter/KX_IpoConvert.h +++ b/source/gameengine/Converter/KX_IpoConvert.h @@ -46,7 +46,7 @@ void BL_ConvertCameraIpos(struct Camera* blendercamera, class KX_GameObject* cameraobj, class KX_BlenderSceneConverter *converter); -void BL_ConvertMaterialIpos(struct Material* blendermaterial, +void BL_ConvertMaterialIpos(struct Object* blenderobject, class KX_GameObject* materialobj, class KX_BlenderSceneConverter *converter); diff --git a/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp b/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp index 28ca1fd673f..9a47c262889 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp @@ -1,5 +1,5 @@ /** - * $Id$ + * $Id:SCA_ActuatorEventManager.cpp 15567 2008-07-14 14:09:36Z theeth $ * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or @@ -48,19 +48,10 @@ SCA_ActuatorEventManager::~SCA_ActuatorEventManager() } - - -void SCA_ActuatorEventManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -} - - - void SCA_ActuatorEventManager::NextFrame() { // check for changed actuator - for (vector<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) { (*it)->Activate(m_logicmgr,NULL); } @@ -69,7 +60,7 @@ void SCA_ActuatorEventManager::NextFrame() void SCA_ActuatorEventManager::UpdateFrame() { // update the state of actuator before executing them - for (vector<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) { ((SCA_ActuatorSensor*)(*it))->Update(); } diff --git a/source/gameengine/GameLogic/SCA_ActuatorEventManager.h b/source/gameengine/GameLogic/SCA_ActuatorEventManager.h index b5108764197..6454decfc62 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorEventManager.h +++ b/source/gameengine/GameLogic/SCA_ActuatorEventManager.h @@ -1,5 +1,5 @@ /** - * $Id$ + * $Id:SCA_ActuatorEventManager.h 15567 2008-07-14 14:09:36Z theeth $ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -44,7 +44,6 @@ public: virtual ~SCA_ActuatorEventManager(); virtual void NextFrame(); virtual void UpdateFrame(); - virtual void RegisterSensor(SCA_ISensor* sensor); //SCA_LogicManager* GetLogicManager() { return m_logicmgr;} }; diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index e1c8ef87dd1..8bba37d045a 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -1,7 +1,7 @@ /** * Actuator sensor * - * $Id$ + * $Id:SCA_ActuatorSensor.cpp 15567 2008-07-14 14:09:36Z theeth $ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -149,7 +149,7 @@ PyParentObject SCA_ActuatorSensor::Parents[] = { }; PyMethodDef SCA_ActuatorSensor::Methods[] = { - {"getActuator", (PyCFunction) SCA_ActuatorSensor::sPyGetActuator, METH_VARARGS, GetActuator_doc}, + {"getActuator", (PyCFunction) SCA_ActuatorSensor::sPyGetActuator, METH_NOARGS, GetActuator_doc}, {"setActuator", (PyCFunction) SCA_ActuatorSensor::sPySetActuator, METH_VARARGS, SetActuator_doc}, {NULL,NULL} //Sentinel }; @@ -162,7 +162,7 @@ PyObject* SCA_ActuatorSensor::_getattr(const STR_String& attr) { char SCA_ActuatorSensor::GetActuator_doc[] = "getActuator()\n" "\tReturn the Actuator with which the sensor operates.\n"; -PyObject* SCA_ActuatorSensor::PyGetActuator(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* SCA_ActuatorSensor::PyGetActuator(PyObject* self) { return PyString_FromString(m_checkactname); } @@ -180,6 +180,7 @@ PyObject* SCA_ActuatorSensor::PySetActuator(PyObject* self, PyObject* args, PyOb char *actNameArg = NULL; if (!PyArg_ParseTuple(args, "s", &actNameArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h index 6086c5bfce0..568e7158af2 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h @@ -1,7 +1,7 @@ /** * Actuator sensor * - * $Id$ + * $Id:SCA_ActuatorSensor.h 15567 2008-07-14 14:09:36Z theeth $ * * ***** BEGIN GPL LICENSE BLOCK ***** * @@ -66,7 +66,7 @@ public: /* 3. setProperty */ KX_PYMETHOD_DOC(SCA_ActuatorSensor,SetActuator); /* 4. getProperty */ - KX_PYMETHOD_DOC(SCA_ActuatorSensor,GetActuator); + KX_PYMETHOD_DOC_NOARGS(SCA_ActuatorSensor,GetActuator); }; diff --git a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp index ab3bc2cc4ee..4cd2dfba994 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp @@ -51,16 +51,9 @@ SCA_AlwaysEventManager::SCA_AlwaysEventManager(class SCA_LogicManager* logicmgr) void SCA_AlwaysEventManager::NextFrame() { - for (vector<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) { - SCA_ISensor* sensor = *i; - sensor->Activate(m_logicmgr, NULL); + (*i)->Activate(m_logicmgr, NULL); } } - - -void SCA_AlwaysEventManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -} diff --git a/source/gameengine/GameLogic/SCA_AlwaysEventManager.h b/source/gameengine/GameLogic/SCA_AlwaysEventManager.h index 28c71512875..a619eecddd4 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysEventManager.h +++ b/source/gameengine/GameLogic/SCA_AlwaysEventManager.h @@ -39,7 +39,6 @@ class SCA_AlwaysEventManager : public SCA_EventManager public: SCA_AlwaysEventManager(class SCA_LogicManager* logicmgr); virtual void NextFrame(); - virtual void RegisterSensor(SCA_ISensor* sensor); }; diff --git a/source/gameengine/GameLogic/SCA_EventManager.cpp b/source/gameengine/GameLogic/SCA_EventManager.cpp index 0169864a133..e4fd0379597 100644 --- a/source/gameengine/GameLogic/SCA_EventManager.cpp +++ b/source/gameengine/GameLogic/SCA_EventManager.cpp @@ -45,17 +45,14 @@ SCA_EventManager::~SCA_EventManager() { } - +void SCA_EventManager::RegisterSensor(class SCA_ISensor* sensor) +{ + m_sensors.insert(sensor); +} void SCA_EventManager::RemoveSensor(class SCA_ISensor* sensor) { - std::vector<SCA_ISensor*>::iterator i = - std::find(m_sensors.begin(), m_sensors.end(), sensor); - if (!(i == m_sensors.end())) - { - std::swap(*i, m_sensors.back()); - m_sensors.pop_back(); - } + m_sensors.erase(sensor); } void SCA_EventManager::NextFrame(double curtime, double fixedtime) diff --git a/source/gameengine/GameLogic/SCA_EventManager.h b/source/gameengine/GameLogic/SCA_EventManager.h index 9cc1718cd1e..9dbb5a6d24f 100644 --- a/source/gameengine/GameLogic/SCA_EventManager.h +++ b/source/gameengine/GameLogic/SCA_EventManager.h @@ -30,12 +30,14 @@ #define __KX_EVENTMANAGER #include <vector> +#include <set> #include <algorithm> class SCA_EventManager { protected: - std::vector <class SCA_ISensor*> m_sensors; + // use a set to speed-up insertion/removal + std::set <class SCA_ISensor*> m_sensors; public: enum EVENT_MANAGER_TYPE { @@ -61,7 +63,7 @@ public: virtual void NextFrame(); virtual void UpdateFrame(); virtual void EndFrame(); - virtual void RegisterSensor(class SCA_ISensor* sensor)=0; + virtual void RegisterSensor(class SCA_ISensor* sensor); int GetType(); protected: diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index f6efd485adb..e73358bc1e8 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -82,7 +82,10 @@ void SCA_ILogicBrick::ReParent(SCA_IObject* parent) m_gameobj = parent; } - +void SCA_ILogicBrick::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + // nothing to do +} CValue* SCA_ILogicBrick::Calc(VALUE_OPERATOR op, CValue *val) { diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index 80bc6ae3b86..c28711ac0f6 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -32,6 +32,8 @@ #include "Value.h" #include "SCA_IObject.h" #include "BoolValue.h" +#include "GEN_Map.h" +#include "GEN_HashedPtr.h" class SCA_ILogicBrick : public CValue { @@ -59,6 +61,7 @@ public: SCA_IObject* GetParent(); virtual void ReParent(SCA_IObject* parent); + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); // act as a BoolValue (with value IsPositiveTrigger) virtual CValue* Calc(VALUE_OPERATOR op, CValue *val); diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index c5bb4a41552..b0f8decee26 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -306,7 +306,7 @@ const MT_Point3& SCA_IObject::ConvertPythonPylist(PyObject* pylist) } #endif -void SCA_IObject::Suspend(void) +void SCA_IObject::Suspend() { if ((!m_ignore_activity_culling) && (!m_suspended)) { @@ -337,12 +337,31 @@ void SCA_IObject::Resume(void) void SCA_IObject::SetState(unsigned int state) { - m_state = state; - // update the status of the controllers + unsigned int tmpstate; SCA_ControllerList::iterator contit; - for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + + // we will update the state in two steps: + // 1) set the new state bits that are 1 + // 2) clr the new state bits that are 0 + // This to ensure continuity if a sensor is attached to two states + // that are switching state: no need to deactive and reactive the sensor + + tmpstate = m_state | state; + if (tmpstate != m_state) + { + // update the status of the controllers + for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + { + (*contit)->ApplyState(tmpstate); + } + } + m_state = state; + if (m_state != tmpstate) { - (*contit)->ApplyState(m_state); + for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + { + (*contit)->ApplyState(m_state); + } } } diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 68341b57435..2dc49924062 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -41,7 +41,8 @@ void SCA_ISensor::ReParent(SCA_IObject* parent) { SCA_ILogicBrick::ReParent(parent); - m_eventmgr->RegisterSensor(this); + // will be done when the sensor is activated + //m_eventmgr->RegisterSensor(this); this->SetActive(false); } @@ -133,6 +134,7 @@ void SCA_ISensor::DecLink() { { // sensor is detached from all controllers, initialize it so that it // is fresh as at startup when it is reattached again. + UnregisterToManager(); Init(); } } @@ -168,23 +170,23 @@ PyMethodDef SCA_ISensor::Methods[] = { {"isPositive", (PyCFunction) SCA_ISensor::sPyIsPositive, METH_VARARGS, IsPositive_doc}, {"getUsePosPulseMode", (PyCFunction) SCA_ISensor::sPyGetUsePosPulseMode, - METH_VARARGS, GetUsePosPulseMode_doc}, + METH_NOARGS, GetUsePosPulseMode_doc}, {"setUsePosPulseMode", (PyCFunction) SCA_ISensor::sPySetUsePosPulseMode, METH_VARARGS, SetUsePosPulseMode_doc}, {"getFrequency", (PyCFunction) SCA_ISensor::sPyGetFrequency, - METH_VARARGS, GetFrequency_doc}, + METH_NOARGS, GetFrequency_doc}, {"setFrequency", (PyCFunction) SCA_ISensor::sPySetFrequency, METH_VARARGS, SetFrequency_doc}, {"getUseNegPulseMode", (PyCFunction) SCA_ISensor::sPyGetUseNegPulseMode, - METH_VARARGS, GetUseNegPulseMode_doc}, + METH_NOARGS, GetUseNegPulseMode_doc}, {"setUseNegPulseMode", (PyCFunction) SCA_ISensor::sPySetUseNegPulseMode, METH_VARARGS, SetUseNegPulseMode_doc}, {"getInvert", (PyCFunction) SCA_ISensor::sPyGetInvert, - METH_VARARGS, GetInvert_doc}, + METH_NOARGS, GetInvert_doc}, {"setInvert", (PyCFunction) SCA_ISensor::sPySetInvert, METH_VARARGS, SetInvert_doc}, {"getLevel", (PyCFunction) SCA_ISensor::sPyGetLevel, - METH_VARARGS, GetLevel_doc}, + METH_NOARGS, GetLevel_doc}, {"setLevel", (PyCFunction) SCA_ISensor::sPySetLevel, METH_VARARGS, SetLevel_doc}, {NULL,NULL} //Sentinel @@ -203,6 +205,11 @@ void SCA_ISensor::RegisterToManager() m_eventmgr->RegisterSensor(this); } +void SCA_ISensor::UnregisterToManager() +{ + m_eventmgr->RemoveSensor(this); +} + void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) { @@ -259,7 +266,7 @@ PyObject* SCA_ISensor::PyIsPositive(PyObject* self, PyObject* args, PyObject* kw char SCA_ISensor::GetUsePosPulseMode_doc[] = "getUsePosPulseMode()\n" "\tReturns whether positive pulse mode is active.\n"; -PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* SCA_ISensor::PyGetUsePosPulseMode(PyObject* self) { return BoolToPyArg(m_pos_pulsemode); } @@ -286,7 +293,7 @@ PyObject* SCA_ISensor::PySetUsePosPulseMode(PyObject* self, PyObject* args, PyOb char SCA_ISensor::GetFrequency_doc[] = "getFrequency()\n" "\tReturns the frequency of the updates in pulse mode.\n" ; -PyObject* SCA_ISensor::PyGetFrequency(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* SCA_ISensor::PyGetFrequency(PyObject* self) { return PyInt_FromLong(m_pulse_frequency); } @@ -321,7 +328,7 @@ PyObject* SCA_ISensor::PySetFrequency(PyObject* self, PyObject* args, PyObject* char SCA_ISensor::GetInvert_doc[] = "getInvert()\n" "\tReturns whether or not pulses from this sensor are inverted.\n" ; -PyObject* SCA_ISensor::PyGetInvert(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* SCA_ISensor::PyGetInvert(PyObject* self) { return BoolToPyArg(m_invert); } @@ -342,11 +349,10 @@ char SCA_ISensor::GetLevel_doc[] = "getLevel()\n" "\tReturns whether this sensor is a level detector or a edge detector.\n" "\tIt makes a difference only in case of logic state transition (state actuator).\n" -"\tA level detector will immediately generate a pulse if the condition for the\n" -"\tdetector is met when entering the state. A edge detector will wait for an off-on\n" -"\ttransition to occur.\n" -"\tOnly some sensors implement this feature: keyboard.\n"; -PyObject* SCA_ISensor::PyGetLevel(PyObject* self, PyObject* args, PyObject* kwds) +"\tA level detector will immediately generate a pulse, negative or positive\n" +"\tdepending on the sensor condition, as soon as the state is activated.\n" +"\tA edge detector will wait for a state change before generating a pulse.\n"; +PyObject* SCA_ISensor::PyGetLevel(PyObject* self) { return BoolToPyArg(m_level); } @@ -366,7 +372,7 @@ PyObject* SCA_ISensor::PySetLevel(PyObject* self, PyObject* args, PyObject* kwds char SCA_ISensor::GetUseNegPulseMode_doc[] = "getUseNegPulseMode()\n" "\tReturns whether negative pulse mode is active.\n"; -PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self, PyObject* args, PyObject* kwds) +PyObject* SCA_ISensor::PyGetUseNegPulseMode(PyObject* self) { return BoolToPyArg(m_neg_pulsemode); } diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 4ce49e71507..d5dabbce3ee 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -115,6 +115,8 @@ public: void SetLevel(bool lvl); void RegisterToManager(); + void UnregisterToManager(); + virtual float GetNumber(); /** Stop sensing for a while. */ @@ -129,22 +131,22 @@ public: void ClrLink() { m_links = 0; } void IncLink() - { m_links++; } + { if (!m_links++) RegisterToManager(); } void DecLink(); bool IsNoLink() const { return !m_links; } /* Python functions: */ KX_PYMETHOD_DOC(SCA_ISensor,IsPositive); - KX_PYMETHOD_DOC(SCA_ISensor,GetUsePosPulseMode); + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUsePosPulseMode); KX_PYMETHOD_DOC(SCA_ISensor,SetUsePosPulseMode); - KX_PYMETHOD_DOC(SCA_ISensor,GetFrequency); + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetFrequency); KX_PYMETHOD_DOC(SCA_ISensor,SetFrequency); - KX_PYMETHOD_DOC(SCA_ISensor,GetUseNegPulseMode); + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetUseNegPulseMode); KX_PYMETHOD_DOC(SCA_ISensor,SetUseNegPulseMode); - KX_PYMETHOD_DOC(SCA_ISensor,GetInvert); + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetInvert); KX_PYMETHOD_DOC(SCA_ISensor,SetInvert); - KX_PYMETHOD_DOC(SCA_ISensor,GetLevel); + KX_PYMETHOD_DOC_NOARGS(SCA_ISensor,GetLevel); KX_PYMETHOD_DOC(SCA_ISensor,SetLevel); }; diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.cpp b/source/gameengine/GameLogic/SCA_JoystickManager.cpp index 7bf2049e56e..8ff28ba0b51 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickManager.cpp @@ -52,9 +52,10 @@ SCA_JoystickManager::~SCA_JoystickManager() void SCA_JoystickManager::NextFrame(double curtime,double deltatime) { - for (unsigned int i = 0; i < m_sensors.size(); i++) + set<SCA_ISensor*>::iterator it; + for (it = m_sensors.begin(); it != m_sensors.end(); it++) { - SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*) m_sensors[i]; + SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it); if(!joysensor->IsSuspended()) { m_joystick->HandleEvents(); @@ -64,12 +65,6 @@ void SCA_JoystickManager::NextFrame(double curtime,double deltatime) } -void SCA_JoystickManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -} - - SCA_Joystick *SCA_JoystickManager::GetJoystickDevice() { /* diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.h b/source/gameengine/GameLogic/SCA_JoystickManager.h index 3c4df64677e..f2bb27965fa 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.h +++ b/source/gameengine/GameLogic/SCA_JoystickManager.h @@ -45,7 +45,6 @@ public: SCA_JoystickManager(class SCA_LogicManager* logicmgr); virtual ~SCA_JoystickManager(); virtual void NextFrame(double curtime,double deltatime); - virtual void RegisterSensor(SCA_ISensor* sensor); SCA_Joystick* GetJoystickDevice(void); }; diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp index 259b06134d7..6a96442b124 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp @@ -62,23 +62,14 @@ void SCA_KeyboardManager::NextFrame() { //const SCA_InputEvent& event = GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode)=0; // cerr << "SCA_KeyboardManager::NextFrame"<< endl; - for (unsigned int i=0;i<m_sensors.size();i++) + set<SCA_ISensor*>::iterator it; + for (it=m_sensors.begin(); it != m_sensors.end(); it++) { - SCA_KeyboardSensor* keysensor = (SCA_KeyboardSensor*)m_sensors[i]; - keysensor->Activate(m_logicmanager,NULL); + (*it)->Activate(m_logicmanager,NULL); } } - - -void SCA_KeyboardManager::RegisterSensor(SCA_ISensor* keysensor) -{ - m_sensors.push_back(keysensor); -} - - - bool SCA_KeyboardManager::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode) { return false; diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.h b/source/gameengine/GameLogic/SCA_KeyboardManager.h index b4a50f56025..8f3cc0ab715 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardManager.h +++ b/source/gameengine/GameLogic/SCA_KeyboardManager.h @@ -55,7 +55,6 @@ public: bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode); virtual void NextFrame(); - virtual void RegisterSensor(class SCA_ISensor* sensor); SCA_IInputDevice* GetInputDevice(); }; diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index f50161cbecb..91e66aea359 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -127,12 +127,17 @@ void SCA_LogicManager::RegisterGameMeshName(const STR_String& gamemeshname, void -void SCA_LogicManager::RegisterGameObj(CValue* gameobj, void* blendobj) +void SCA_LogicManager::RegisterGameObj(void* blendobj, CValue* gameobj) { - m_map_gameobj_to_blendobj.insert(CHashedPtr(gameobj), blendobj); + m_map_blendobj_to_gameobj.insert(CHashedPtr(blendobj), gameobj); } - +void SCA_LogicManager::UnregisterGameObj(void* blendobj, CValue* gameobj) +{ + void **obp = m_map_blendobj_to_gameobj[CHashedPtr(blendobj)]; + if (obp && (CValue*)(*obp) == gameobj) + m_map_blendobj_to_gameobj.remove(CHashedPtr(blendobj)); +} CValue* SCA_LogicManager::GetGameObjectByName(const STR_String& gameobjname) { @@ -146,10 +151,10 @@ CValue* SCA_LogicManager::GetGameObjectByName(const STR_String& gameobjname) } -void* SCA_LogicManager::FindBlendObjByGameObj(CValue* gameobject) +CValue* SCA_LogicManager::FindGameObjByBlendObj(void* blendobj) { - void **obp= m_map_gameobj_to_blendobj[CHashedPtr(gameobject)]; - return obp?*obp:NULL; + void **obp= m_map_blendobj_to_gameobj[CHashedPtr(blendobj)]; + return obp?(CValue*)(*obp):NULL; } @@ -171,12 +176,7 @@ void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor) (*c)->UnlinkSensor(sensor); } m_sensorcontrollermapje.erase(sensor); - - for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin(); - !(ie==m_eventmanagers.end());ie++) - { - (*ie)->RemoveSensor(sensor); - } + sensor->UnregisterToManager(); } void SCA_LogicManager::RemoveController(SCA_IController* controller) diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h index 39d8b865977..e0d3d506702 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.h +++ b/source/gameengine/GameLogic/SCA_LogicManager.h @@ -109,7 +109,7 @@ class SCA_LogicManager GEN_Map<STR_HashedString,void*> m_mapStringToActions; GEN_Map<STR_HashedString,void*> m_map_gamemeshname_to_blendobj; - GEN_Map<CHashedPtr,void*> m_map_gameobj_to_blendobj; + GEN_Map<CHashedPtr,void*> m_map_blendobj_to_gameobj; vector<SmartActuatorPtr> m_removedActuators; public: @@ -152,8 +152,9 @@ public: void RegisterGameMeshName(const STR_String& gamemeshname, void* blendobj); void* FindBlendObjByGameMeshName(const STR_String& gamemeshname); - void RegisterGameObj(CValue* gameobj, void* blendobj); - void* FindBlendObjByGameObj(CValue* gameobj); + void RegisterGameObj(void* blendobj, CValue* gameobj); + void UnregisterGameObj(void* blendobj, CValue* gameobj); + CValue* FindGameObjByBlendObj(void* blendobj); }; #endif //__KX_LOGICMANAGER diff --git a/source/gameengine/GameLogic/SCA_MouseManager.cpp b/source/gameengine/GameLogic/SCA_MouseManager.cpp index b4251d8ab53..ca875dad07c 100644 --- a/source/gameengine/GameLogic/SCA_MouseManager.cpp +++ b/source/gameengine/GameLogic/SCA_MouseManager.cpp @@ -75,9 +75,10 @@ void SCA_MouseManager::NextFrame() { if (m_mousedevice) { - for (unsigned int i = 0; i < m_sensors.size(); i++) + set<SCA_ISensor*>::iterator it; + for (it=m_sensors.begin(); it!=m_sensors.end(); it++) { - SCA_MouseSensor* mousesensor = (SCA_MouseSensor*) m_sensors[i]; + SCA_MouseSensor* mousesensor = (SCA_MouseSensor*)(*it); // (0,0) is the Upper Left corner in our local window // coordinates if (!mousesensor->IsSuspended()) @@ -98,15 +99,6 @@ void SCA_MouseManager::NextFrame() } } - - -void SCA_MouseManager::RegisterSensor(SCA_ISensor* keysensor) -{ - m_sensors.push_back(keysensor); -} - - - bool SCA_MouseManager::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode) { /* We should guard for non-mouse events maybe? A rather silly side */ diff --git a/source/gameengine/GameLogic/SCA_MouseManager.h b/source/gameengine/GameLogic/SCA_MouseManager.h index bc8254486ad..efa4c639ce7 100644 --- a/source/gameengine/GameLogic/SCA_MouseManager.h +++ b/source/gameengine/GameLogic/SCA_MouseManager.h @@ -62,7 +62,6 @@ public: */ bool IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode); virtual void NextFrame(); - virtual void RegisterSensor(class SCA_ISensor* sensor); SCA_IInputDevice* GetInputDevice(); }; diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index ebe1cd51863..7062f2cef6a 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -42,7 +42,7 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,CValue* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T ) +SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,SCA_IObject* sourceObj,const STR_String& propname,const STR_String& expr,int acttype,PyTypeObject* T ) : SCA_IActuator(gameobj,T), m_type(acttype), m_propname(propname), @@ -51,14 +51,14 @@ SCA_PropertyActuator::SCA_PropertyActuator(SCA_IObject* gameobj,CValue* sourceOb { // protect ourselves against someone else deleting the source object // don't protect against ourselves: it would create a dead lock - if (m_sourceObj && m_sourceObj != GetParent()) - m_sourceObj->AddRef(); + if (m_sourceObj) + m_sourceObj->RegisterActuator(this); } SCA_PropertyActuator::~SCA_PropertyActuator() { - if (m_sourceObj && m_sourceObj != GetParent()) - m_sourceObj->Release(); + if (m_sourceObj) + m_sourceObj->UnregisterActuator(this); } bool SCA_PropertyActuator::Update() @@ -185,10 +185,31 @@ void SCA_PropertyActuator::ProcessReplica() // no need to check for self reference like in the constructor: // the replica will always have a different parent if (m_sourceObj) - m_sourceObj->AddRef(); + m_sourceObj->RegisterActuator(this); SCA_IActuator::ProcessReplica(); } +bool SCA_PropertyActuator::UnlinkObject(SCA_IObject* clientobj) +{ + if (clientobj == m_sourceObj) + { + // this object is being deleted, we cannot continue to track it. + m_sourceObj = NULL; + return true; + } + return false; +} + +void SCA_PropertyActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_sourceObj]; + if (h_obj) { + if (m_sourceObj) + m_sourceObj->UnregisterActuator(this); + m_sourceObj = (SCA_IObject*)(*h_obj); + m_sourceObj->RegisterActuator(this); + } +} /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h index f8305901c51..1e435684572 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.h +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h @@ -52,7 +52,7 @@ class SCA_PropertyActuator : public SCA_IActuator int m_type; STR_String m_propname; STR_String m_exprtxt; - CValue* m_sourceObj; // for copy property actuator + SCA_IObject* m_sourceObj; // for copy property actuator public: @@ -60,7 +60,7 @@ public: SCA_PropertyActuator( SCA_IObject* gameobj, - CValue* sourceObj, + SCA_IObject* sourceObj, const STR_String& propname, const STR_String& expr, int acttype, @@ -74,7 +74,9 @@ public: GetReplica( ); - void ProcessReplica(); + virtual void ProcessReplica(); + virtual bool UnlinkObject(SCA_IObject* clientobj); + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); virtual bool Update(); diff --git a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp index fc56d101728..e5e3f9cced5 100644 --- a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp @@ -47,19 +47,10 @@ SCA_PropertyEventManager::~SCA_PropertyEventManager() } - - -void SCA_PropertyEventManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -} - - - void SCA_PropertyEventManager::NextFrame() { // check for changed properties - for (vector<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) { (*it)->Activate(m_logicmgr,NULL); } diff --git a/source/gameengine/GameLogic/SCA_PropertyEventManager.h b/source/gameengine/GameLogic/SCA_PropertyEventManager.h index aaa303a52c8..f166065b198 100644 --- a/source/gameengine/GameLogic/SCA_PropertyEventManager.h +++ b/source/gameengine/GameLogic/SCA_PropertyEventManager.h @@ -43,7 +43,6 @@ public: SCA_PropertyEventManager(class SCA_LogicManager* logicmgr); virtual ~SCA_PropertyEventManager(); virtual void NextFrame(); - virtual void RegisterSensor(SCA_ISensor* sensor); //SCA_LogicManager* GetLogicManager() { return m_logicmgr;} }; diff --git a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp index 02020a52a17..156478d866d 100644 --- a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp @@ -50,16 +50,9 @@ SCA_RandomEventManager::SCA_RandomEventManager(class SCA_LogicManager* logicmgr) void SCA_RandomEventManager::NextFrame() { - for (vector<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) { - SCA_ISensor *sensor = *i; - sensor->Activate(m_logicmgr, NULL); + (*i)->Activate(m_logicmgr, NULL); } } - - -void SCA_RandomEventManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -}; diff --git a/source/gameengine/GameLogic/SCA_RandomEventManager.h b/source/gameengine/GameLogic/SCA_RandomEventManager.h index 8c75ef665fa..79138c23c62 100644 --- a/source/gameengine/GameLogic/SCA_RandomEventManager.h +++ b/source/gameengine/GameLogic/SCA_RandomEventManager.h @@ -45,7 +45,6 @@ public: SCA_RandomEventManager(class SCA_LogicManager* logicmgr); virtual void NextFrame(); - virtual void RegisterSensor(SCA_ISensor* sensor); }; #endif //__KX_RANDOMEVENTMGR diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp index 643f1247a52..b7fadd3d62c 100644 --- a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp @@ -65,6 +65,11 @@ void SCA_TimeEventManager::RegisterSensor(SCA_ISensor* sensor) // not yet } +void SCA_TimeEventManager::RemoveSensor(SCA_ISensor* sensor) +{ + // empty +} + void SCA_TimeEventManager::NextFrame(double curtime, double fixedtime) diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.h b/source/gameengine/GameLogic/SCA_TimeEventManager.h index 2fd39661a2d..bd57e12eb44 100644 --- a/source/gameengine/GameLogic/SCA_TimeEventManager.h +++ b/source/gameengine/GameLogic/SCA_TimeEventManager.h @@ -45,6 +45,7 @@ public: virtual void NextFrame(double curtime, double fixedtime); virtual void RegisterSensor(class SCA_ISensor* sensor); + virtual void RemoveSensor(class SCA_ISensor* sensor); void AddTimeProperty(CValue* timeval); void RemoveTimeProperty(CValue* timeval); }; diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h index f82166dfa88..87719041f65 100644 --- a/source/gameengine/GamePlayer/common/GPC_Canvas.h +++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h @@ -130,6 +130,12 @@ public: ) { return m_displayarea; }; + + RAS_Rect & + GetWindowArea( + ) { + return m_displayarea; + } void BeginFrame( diff --git a/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h b/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h index bb1abd71505..bf8cb720811 100644 --- a/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h +++ b/source/gameengine/GamePlayer/common/windows/GPW_Canvas.h @@ -36,7 +36,7 @@ #include <iostream> #include <windows.h> -#include <gl/gl.h> +//#include <gl/gl.h> #include "GPC_Canvas.h" diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index dd45d522b9f..a9a0771936c 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -1,6 +1,10 @@ #include "DNA_customdata_types.h" #include "DNA_material_types.h" +#include "DNA_scene_types.h" + +#include "BKE_global.h" +#include "BKE_main.h" #include "BL_BlenderShader.h" #include "BL_Material.h" @@ -10,30 +14,51 @@ #include "GPU_material.h" #endif +#include "RAS_BucketManager.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" + + /* this is evil, but we need the scene to create materials with + * lights from the correct scene .. */ +static struct Scene *GetSceneForName(const STR_String& scenename) +{ + Scene *sce; + + for (sce= (Scene*)G.main->scene.first; sce; sce= (Scene*)sce->id.next) + if (scenename == (sce->id.name+2)) + return sce; -const bool BL_BlenderShader::Ok()const + return (Scene*)G.main->scene.first; +} + +bool BL_BlenderShader::Ok() { #ifdef BLENDER_GLSL - return (mGPUMat != 0); + VerifyShader(); + + return (mMat && mMat->gpumaterial); #else return 0; #endif } -BL_BlenderShader::BL_BlenderShader(struct Material *ma, int lightlayer) +BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer) : #ifdef BLENDER_GLSL - mGPUMat(0), + mScene(scene), + mMat(ma), + mGPUMat(NULL), #endif mBound(false), mLightLayer(lightlayer) { #ifdef BLENDER_GLSL - if(ma) { - GPU_material_from_blender(ma); - mGPUMat = ma->gpumaterial; + mBlenderScene = GetSceneForName(scene->GetName()); + mBlendMode = GPU_BLEND_SOLID; + + if(mMat) { + GPU_material_from_blender(mBlenderScene, mMat); + mGPUMat = mMat->gpumaterial; } #endif } @@ -41,17 +66,29 @@ BL_BlenderShader::BL_BlenderShader(struct Material *ma, int lightlayer) BL_BlenderShader::~BL_BlenderShader() { #ifdef BLENDER_GLSL - if(mGPUMat) { - GPU_material_unbind(mGPUMat); - mGPUMat = 0; - } + if(mMat && mMat->gpumaterial) + GPU_material_unbind(mMat->gpumaterial); +#endif +} + +bool BL_BlenderShader::VerifyShader() +{ +#ifdef BLENDER_GLSL + if(mMat && !mMat->gpumaterial) + GPU_material_from_blender(mBlenderScene, mMat); + + mGPUMat = mMat->gpumaterial; + + return (mMat && mGPUMat); +#else + return false; #endif } void BL_BlenderShader::SetProg(bool enable) { #ifdef BLENDER_GLSL - if(mGPUMat) { + if(VerifyShader()) { if(enable) { GPU_material_bind(mGPUMat, mLightLayer); mBound = true; @@ -70,7 +107,7 @@ int BL_BlenderShader::GetAttribNum() GPUVertexAttribs attribs; int i, enabled = 0; - if(!mGPUMat) + if(!VerifyShader()) return enabled; GPU_material_vertex_attributes(mGPUMat, &attribs); @@ -96,7 +133,7 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) ras->SetAttribNum(0); - if(!mGPUMat) + if(!VerifyShader()) return; if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { @@ -142,9 +179,11 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) { #ifdef BLENDER_GLSL - float obmat[4][4], viewmat[4][4], viewinvmat[4][4]; + float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4]; + + VerifyShader(); - if(!mGPUMat || !mBound) + if(!mGPUMat) // || !mBound) return; MT_Matrix4x4 model; @@ -158,10 +197,22 @@ void BL_BlenderShader::Update( const KX_MeshSlot & ms, RAS_IRasterizer* rasty ) view.invert(); view.getValue((float*)viewinvmat); - GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat); + if(ms.m_bObjectColor) + ms.m_RGBAcolor.getValue((float*)obcol); + else + obcol[0]= obcol[1]= obcol[2]= obcol[3]= 1.0f; + + GPU_material_bind_uniforms(mGPUMat, obmat, viewmat, viewinvmat, obcol); + + mBlendMode = GPU_material_blend_mode(mGPUMat, obcol); #endif } +int BL_BlenderShader::GetBlendMode() +{ + return mBlendMode; +} + bool BL_BlenderShader::Equals(BL_BlenderShader *blshader) { #ifdef BLENDER_GLSL diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index b758d1a9cba..da9765dafa4 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -14,7 +14,10 @@ #include "RAS_IPolygonMaterial.h" +#include "KX_Scene.h" + struct Material; +struct Scene; class BL_Material; #define BL_MAX_ATTRIB 16 @@ -27,21 +30,28 @@ class BL_BlenderShader { private: #ifdef BLENDER_GLSL + KX_Scene *mScene; + struct Scene *mBlenderScene; + struct Material *mMat; GPUMaterial *mGPUMat; #endif bool mBound; int mLightLayer; + int mBlendMode; + + bool VerifyShader(); public: - BL_BlenderShader(struct Material *ma, int lightlayer); + BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer); virtual ~BL_BlenderShader(); - const bool Ok()const; + bool Ok(); void SetProg(bool enable); int GetAttribNum(); void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); void Update(const class KX_MeshSlot & ms, class RAS_IRasterizer* rasty); + int GetBlendMode(); bool Equals(BL_BlenderShader *blshader); }; diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index 568f7e171de..dcb66ea2579 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -129,8 +129,7 @@ enum BL_flag TEXALPHA=8, // use alpha combiner functions TEXNEG=16, // negate blending HASIPO=32, - USENEGALPHA=64, - ALPHA_TEST=128 + USENEGALPHA=64 }; // BL_Material::ras_mode @@ -139,7 +138,7 @@ enum BL_ras_mode POLY_VIS=1, COLLIDER=2, ZSORT=4, - TRANSP=8, + ALPHA=8, TRIANGLE=16, USE_LIGHT=32, WIRE=64 diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index f24ef4322f0..f0ef84032f7 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -384,8 +384,6 @@ void BL_Texture::DisableUnit() void BL_Texture::DisableAllTextures() { - glDisable(GL_BLEND); - for(int i=0; i<MAXTEX; i++) { if(GLEW_ARB_multitexture) glActiveTextureARB(GL_TEXTURE0_ARB+i); diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp index 7b5b7fdf78c..eee8e9f6827 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp @@ -55,28 +55,13 @@ KX_NetworkEventManager::~KX_NetworkEventManager() //printf("KX_NetworkEventManager destructor\n"); } -void KX_NetworkEventManager::RegisterSensor(class SCA_ISensor* sensor) -{ - //printf("KX_NetworkEventManager RegisterSensor\n"); - m_sensors.push_back(sensor); -} - -void KX_NetworkEventManager::RemoveSensor(class SCA_ISensor* sensor) -{ - //printf("KX_NetworkEventManager RemoveSensor\n"); - // Network specific RemoveSensor stuff goes here - - // parent - SCA_EventManager::RemoveSensor(sensor); -} - void KX_NetworkEventManager::NextFrame() { // printf("KX_NetworkEventManager::proceed %.2f - %.2f\n", curtime, deltatime); // each frame, the logicmanager will call the network // eventmanager to look for network events, and process it's // 'network' sensors - vector<class SCA_ISensor*>::iterator it; + set<class SCA_ISensor*>::iterator it; for (it = m_sensors.begin(); !(it==m_sensors.end()); it++) { // printf("KX_NetworkEventManager::proceed sensor %.2f\n", curtime); diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h index 0b097ba2ef6..ae88f1d4987 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.h @@ -42,9 +42,6 @@ public: class NG_NetworkDeviceInterface *ndi); virtual ~KX_NetworkEventManager (); - virtual void RegisterSensor(class SCA_ISensor* sensor); - virtual void RemoveSensor(class SCA_ISensor* sensor); - virtual void NextFrame(); virtual void EndFrame(); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 0f445a9f32e..a67e5b26667 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -38,6 +38,7 @@ extern "C" { // ------------------------------------ #define spit(x) std::cout << x << std::endl; +BL_Shader *KX_BlenderMaterial::mLastShader = NULL; BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL; //static PyObject *gTextureDict = 0; @@ -58,7 +59,8 @@ KX_BlenderMaterial::KX_BlenderMaterial( data->tilexrep[0], data->tileyrep[0], data->mode, - ((data->ras_mode &TRANSP)!=0), + data->transp, + ((data->ras_mode &ALPHA)!=0), ((data->ras_mode &ZSORT)!=0), lightlayer, ((data->ras_mode &TRIANGLE)!=0), @@ -79,7 +81,6 @@ KX_BlenderMaterial::KX_BlenderMaterial( m_flag |=RAS_BLENDERMAT; m_flag |=(mMaterial->IdMode>=ONETEX)?RAS_MULTITEX:0; m_flag |=(mMaterial->ras_mode & USE_LIGHT)!=0?RAS_MULTILIGHT:0; - m_flag |=(mMaterial->ras_mode &ALPHA_TEST)!=0?RAS_FORCEALPHA:0; // figure max int enabled = mMaterial->num_enabled; @@ -158,12 +159,29 @@ void KX_BlenderMaterial::OnConstruction() mConstructed = true; } +void KX_BlenderMaterial::EndFrame() +{ + if(mLastBlenderShader) { + mLastBlenderShader->SetProg(false); + mLastBlenderShader = NULL; + } + + if(mLastShader) { + mLastShader->SetProg(false); + mLastShader = NULL; + } +} + void KX_BlenderMaterial::OnExit() { if( mShader ) { - //note, the shader here is allocated, per unique material - //and this function is called per face - mShader->SetProg(false); + //note, the shader here is allocated, per unique material + //and this function is called per face + if(mShader == mLastShader) { + mShader->SetProg(false); + mLastShader = NULL; + } + delete mShader; mShader = 0; } @@ -197,13 +215,19 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) int i; if( !enable || !mShader->Ok() ) { // frame cleanup. - mShader->SetProg(false); + if(mShader == mLastShader) { + mShader->SetProg(false); + mLastShader = NULL; + } + + ras->SetBlendingMode(TF_SOLID); BL_Texture::DisableAllTextures(); return; } BL_Texture::DisableAllTextures(); mShader->SetProg(true); + mLastShader = mShader; BL_Texture::ActivateFirst(); @@ -217,9 +241,12 @@ void KX_BlenderMaterial::setShaderData( bool enable, RAS_IRasterizer *ras) } if(!mUserDefBlend) { - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); } else { + ras->SetBlendingMode(TF_SOLID); + ras->SetBlendingMode(-1); // indicates custom mode + // tested to be valid enums glEnable(GL_BLEND); glBlendFunc(mBlendFunc[0], mBlendFunc[1]); @@ -234,11 +261,14 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras mLastBlenderShader->SetProg(false); mLastBlenderShader= NULL; } + + ras->SetBlendingMode(TF_SOLID); BL_Texture::DisableAllTextures(); return; } if(!mBlenderShader->Equals(mLastBlenderShader)) { + ras->SetBlendingMode(mMaterial->transp); BL_Texture::DisableAllTextures(); if(mLastBlenderShader) @@ -251,17 +281,17 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) { - if(GLEW_ARB_shader_objects && mShader) - mShader->SetProg(false); - BL_Texture::DisableAllTextures(); - if( !enable ) + + if( !enable ) { + ras->SetBlendingMode(TF_SOLID); return; + } BL_Texture::ActivateFirst(); if( mMaterial->IdMode == DEFAULT_BLENDER ) { - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); return; } @@ -271,7 +301,7 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) mTextures[0].ActivateTexture(); mTextures[0].setTexEnv(0, true); mTextures[0].SetMapping(mMaterial->mapping[0].mapping); - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); } return; } @@ -294,9 +324,12 @@ void KX_BlenderMaterial::setTexData( bool enable, RAS_IRasterizer *ras) } if(!mUserDefBlend) { - setDefaultBlending(); + ras->SetBlendingMode(mMaterial->transp); } else { + ras->SetBlendingMode(TF_SOLID); + ras->SetBlendingMode(-1); // indicates custom mode + glEnable(GL_BLEND); glBlendFunc(mBlendFunc[0], mBlendFunc[1]); } @@ -356,6 +389,11 @@ KX_BlenderMaterial::ActivateBlenderShaders( { KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); + if(mLastShader) { + mLastShader->SetProg(false); + mLastShader= NULL; + } + // reset... if(tmp->mMaterial->IsShared()) cachingInfo =0; @@ -402,6 +440,11 @@ KX_BlenderMaterial::ActivateMat( { KX_BlenderMaterial *tmp = const_cast<KX_BlenderMaterial*>(this); + if(mLastShader) { + mLastShader->SetProg(false); + mLastShader= NULL; + } + if(mLastBlenderShader) { mLastBlenderShader->SetProg(false); mLastBlenderShader= NULL; @@ -451,7 +494,10 @@ KX_BlenderMaterial::Activate( return dopass; } else { - mShader->SetProg(false); + if(mShader == mLastShader) { + mShader->SetProg(false); + mLastShader = NULL; + } mPass = 0; dopass = false; return dopass; @@ -499,10 +545,22 @@ bool KX_BlenderMaterial::UsesLighting(RAS_IRasterizer *rasty) const void KX_BlenderMaterial::ActivateMeshSlot(const KX_MeshSlot & ms, RAS_IRasterizer* rasty) const { - if(mShader && GLEW_ARB_shader_objects) + if(mShader && GLEW_ARB_shader_objects) { mShader->Update(ms, rasty); - else if(mBlenderShader && GLEW_ARB_shader_objects) + } + else if(mBlenderShader && GLEW_ARB_shader_objects) { + int blendmode; + mBlenderShader->Update(ms, rasty); + + /* we do blend modes here, because they can change per object + * with the same material due to obcolor */ + blendmode = mBlenderShader->GetBlendMode(); + if((blendmode == TF_SOLID || blendmode == TF_ALPHA) && mMaterial->transp != TF_SOLID) + blendmode = mMaterial->transp; + + rasty->SetBlendingMode(blendmode); + } } void KX_BlenderMaterial::ActivatGLMaterials( RAS_IRasterizer* rasty )const @@ -582,31 +640,6 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const ras->EnableTextures(false); } -bool KX_BlenderMaterial::setDefaultBlending() -{ - if( mMaterial->transp &TF_ADD) { - glEnable(GL_BLEND); - glBlendFunc(GL_ONE, GL_ONE); - glDisable ( GL_ALPHA_TEST ); - return true; - } - - if( mMaterial->transp & TF_ALPHA ) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable ( GL_ALPHA_TEST ); - return true; - } - - if( mMaterial->transp & TF_CLIP ) { - glDisable(GL_BLEND); - glEnable ( GL_ALPHA_TEST ); - glAlphaFunc(GL_GREATER, 0.5f); - return false; - } - return false; -} - void KX_BlenderMaterial::setTexMatrixData(int i) { glMatrixMode(GL_TEXTURE); @@ -831,12 +864,14 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") void KX_BlenderMaterial::SetBlenderGLSLShader(void) { if(!mBlenderShader) - mBlenderShader = new BL_BlenderShader(mMaterial->material, m_lightlayer); + mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, m_lightlayer); if(!mBlenderShader->Ok()) { delete mBlenderShader; mBlenderShader = 0; } + else + m_flag |= RAS_BLENDERGLSL; } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index bf6d2095e7c..0d7657b8cdb 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -90,11 +90,13 @@ public: // -------------------------------- // pre calculate to avoid pops/lag at startup virtual void OnConstruction( ); + + static void EndFrame(); + private: BL_Material* mMaterial; BL_Shader* mShader; BL_BlenderShader* mBlenderShader; - static BL_BlenderShader *mLastBlenderShader; KX_Scene* mScene; BL_Texture mTextures[MAXTEX]; // texture array bool mUserDefBlend; @@ -114,7 +116,6 @@ private: void setBlenderShaderData( bool enable, RAS_IRasterizer *ras); void setShaderData( bool enable, RAS_IRasterizer *ras); - bool setDefaultBlending(); void setObjectMatrixData(int i, RAS_IRasterizer *ras); void setTexMatrixData(int i); @@ -123,6 +124,10 @@ private: // cleanup stuff void OnExit(); + // shader chacing + static BL_BlenderShader *mLastBlenderShader; + static BL_Shader *mLastShader; + mutable int mPass; }; diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index 70443ced7a9..539eaec4a7b 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -13,11 +13,13 @@ #include "KX_ClientObjectInfo.h" #include "PHY_IPhysicsEnvironment.h" +#include "CcdPhysicsEnvironment.h" KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna) : KX_IPhysicsController(dyna,(PHY_IPhysicsController*)this), -CcdPhysicsController(ci) +CcdPhysicsController(ci), +m_savedCollisionFlags(0) { } @@ -131,9 +133,10 @@ void KX_BulletPhysicsController::getOrientation(MT_Quaternion& orn) CcdPhysicsController::getOrientation(myorn[0],myorn[1],myorn[2],myorn[3]); orn = MT_Quaternion(myorn[0],myorn[1],myorn[2],myorn[3]); } -void KX_BulletPhysicsController::setOrientation(const MT_Quaternion& orn) +void KX_BulletPhysicsController::setOrientation(const MT_Matrix3x3& orn) { - CcdPhysicsController::setOrientation(orn.x(),orn.y(),orn.z(),orn.w()); + btMatrix3x3 btmat(orn[0][0], orn[0][1], orn[0][2], orn[1][0], orn[1][1], orn[1][2], orn[2][0], orn[2][1], orn[2][2]); + CcdPhysicsController::setWorldOrientation(btmat); } void KX_BulletPhysicsController::setPosition(const MT_Point3& pos) { @@ -161,14 +164,37 @@ void KX_BulletPhysicsController::setRigidBody(bool rigid) { } -void KX_BulletPhysicsController::SuspendDynamics() +void KX_BulletPhysicsController::SuspendDynamics(bool ghost) { - GetRigidBody()->setActivationState(DISABLE_SIMULATION); - + btRigidBody *body = GetRigidBody(); + if (body->getActivationState() != DISABLE_SIMULATION) + { + btBroadphaseProxy* handle = body->getBroadphaseHandle(); + m_savedCollisionFlags = body->getCollisionFlags(); + m_savedMass = GetMass(); + m_savedCollisionFilterGroup = handle->m_collisionFilterGroup; + m_savedCollisionFilterMask = handle->m_collisionFilterMask; + body->setActivationState(DISABLE_SIMULATION); + GetPhysicsEnvironment()->updateCcdPhysicsController(this, + 0.0, + btCollisionObject::CF_STATIC_OBJECT|((ghost)?btCollisionObject::CF_NO_CONTACT_RESPONSE:(m_savedCollisionFlags&btCollisionObject::CF_NO_CONTACT_RESPONSE)), + btBroadphaseProxy::StaticFilter, + btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); + } } + void KX_BulletPhysicsController::RestoreDynamics() { - GetRigidBody()->forceActivationState(ACTIVE_TAG); + btRigidBody *body = GetRigidBody(); + if (body->getActivationState() == DISABLE_SIMULATION) + { + GetPhysicsEnvironment()->updateCcdPhysicsController(this, + m_savedMass, + m_savedCollisionFlags, + m_savedCollisionFilterGroup, + m_savedCollisionFilterMask); + GetRigidBody()->forceActivationState(ACTIVE_TAG); + } } SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode) diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index 0853755dffa..2efe0474b30 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -7,6 +7,11 @@ class KX_BulletPhysicsController : public KX_IPhysicsController ,public CcdPhysicsController { +private: + int m_savedCollisionFlags; + short int m_savedCollisionFilterGroup; + short int m_savedCollisionFilterMask; + MT_Scalar m_savedMass; public: @@ -30,7 +35,7 @@ public: virtual void SetAngularVelocity(const MT_Vector3& ang_vel,bool local); virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local); virtual void getOrientation(MT_Quaternion& orn); - virtual void setOrientation(const MT_Quaternion& orn); + virtual void setOrientation(const MT_Matrix3x3& orn); virtual void setPosition(const MT_Point3& pos); virtual void setScaling(const MT_Vector3& scaling); virtual MT_Scalar GetMass(); @@ -39,7 +44,7 @@ public: virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); - virtual void SuspendDynamics(); + virtual void SuspendDynamics(bool ghost); virtual void RestoreDynamics(); virtual SG_Controller* GetReplica(class SG_Node* destnode); diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 27f4870de10..0a97b6f0a2f 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -49,7 +49,7 @@ STR_String KX_CameraActuator::Y_AXIS_STRING = "y"; KX_CameraActuator::KX_CameraActuator( SCA_IObject* gameobj, - CValue *obj, + SCA_IObject *obj, MT_Scalar hght, MT_Scalar minhght, MT_Scalar maxhght, @@ -63,11 +63,14 @@ KX_CameraActuator::KX_CameraActuator( m_maxHeight (maxhght), m_x (xytog) { + if (m_ob) + m_ob->RegisterActuator(this); } KX_CameraActuator::~KX_CameraActuator() { - //nothing to do + if (m_ob) + m_ob->UnregisterActuator(this); } CValue* @@ -81,9 +84,36 @@ GetReplica( return replica; }; +void KX_CameraActuator::ProcessReplica() +{ + if (m_ob) + m_ob->RegisterActuator(this); + SCA_IActuator::ProcessReplica(); +} +bool KX_CameraActuator::UnlinkObject(SCA_IObject* clientobj) +{ + if (clientobj == m_ob) + { + // this object is being deleted, we cannot continue to track it. + m_ob = NULL; + return true; + } + return false; +} +void KX_CameraActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_ob]; + if (h_obj) { + if (m_ob) + m_ob->UnregisterActuator(this); + m_ob = (SCA_IObject*)(*h_obj); + m_ob->RegisterActuator(this); + } +} + /* three functions copied from blender arith... don't know if there's an equivalent */ static float Kx_Normalize(float *n) @@ -181,8 +211,14 @@ static void Kx_VecUpMat3(float *vec, float mat[][3], short axis) bool KX_CameraActuator::Update(double curtime, bool frame) { - bool result = true; + /* wondering... is it really neccesary/desirable to suppress negative */ + /* events here? */ + bool bNegativeEvent = IsNegativeEvent(); + RemoveAllEvents(); + if (bNegativeEvent || !m_ob) + return false; + KX_GameObject *obj = (KX_GameObject*) GetParent(); MT_Point3 from = obj->NodeGetWorldPosition(); MT_Matrix3x3 frommat = obj->NodeGetWorldOrientation(); @@ -195,13 +231,6 @@ bool KX_CameraActuator::Update(double curtime, bool frame) float mindistsq, maxdistsq, distsq; float mat[3][3]; - /* wondering... is it really neccesary/desirable to suppress negative */ - /* events here? */ - bool bNegativeEvent = IsNegativeEvent(); - RemoveAllEvents(); - - if (bNegativeEvent) return false; - /* The rules: */ /* CONSTRAINT 1: not implemented */ /* CONSTRAINT 2: can camera see actor? */ @@ -315,7 +344,7 @@ bool KX_CameraActuator::Update(double curtime, bool frame) actormat[2][0]= mat[0][2]; actormat[2][1]= mat[1][2]; actormat[2][2]= mat[2][2]; obj->NodeSetLocalOrientation(actormat); - return result; + return true; } CValue *KX_CameraActuator::findObject(char *obName) @@ -404,7 +433,11 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self, PyObject* gameobj; if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj)) { - m_ob = (CValue*)gameobj; + if (m_ob) + m_ob->UnregisterActuator(this); + m_ob = (SCA_IObject*)gameobj; + if (m_ob) + m_ob->RegisterActuator(this); Py_Return; } PyErr_Clear(); @@ -412,10 +445,13 @@ PyObject* KX_CameraActuator::PySetObject(PyObject* self, char* objectname; if (PyArg_ParseTuple(args, "s", &objectname)) { - CValue *object = (CValue*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname)); + SCA_IObject *object = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname)); if(object) { + if (m_ob != NULL) + m_ob->UnregisterActuator(this); m_ob = object; + m_ob->RegisterActuator(this); Py_Return; } } diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h index eb007e403ec..488b36922b0 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.h +++ b/source/gameengine/Ketsji/KX_CameraActuator.h @@ -49,7 +49,7 @@ class KX_CameraActuator : public SCA_IActuator Py_Header; private : /** Object that will be tracked. */ - CValue *m_ob; + SCA_IObject *m_ob; /** height (float), */ //const MT_Scalar m_height; @@ -87,7 +87,7 @@ private : SCA_IObject *gameobj, //const CValue *ob, - CValue *ob, + SCA_IObject *ob, MT_Scalar hght, MT_Scalar minhght, MT_Scalar maxhght, @@ -103,6 +103,7 @@ private : /** Methods Inherited from CValue */ CValue* GetReplica(); + virtual void ProcessReplica(); /** Methods inherited from SCA_IActuator */ @@ -110,7 +111,10 @@ private : double curtime, bool frame ); + virtual bool UnlinkObject(SCA_IObject* clientobj); + /** Methods inherited from SCA_ILogicBrick */ + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index 80288a72485..2401d69d3a3 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -88,11 +88,17 @@ KX_ConstraintActuator::KX_ConstraintActuator(SCA_IObject *gameobj, } else { m_refDirection /= len; } + m_minimumBound = cos(minBound); + m_maximumBound = cos(maxBound); + m_minimumSine = sin(minBound); + m_maximumSine = sin(maxBound); } break; default: m_minimumBound = minBound; m_maximumBound = maxBound; + m_minimumSine = 0.f; + m_maximumSine = 0.f; break; } @@ -153,9 +159,9 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) KX_GameObject *obj = (KX_GameObject*) GetParent(); MT_Point3 position = obj->NodeGetWorldPosition(); MT_Point3 newposition; - MT_Vector3 direction; + MT_Vector3 direction, refDirection; MT_Matrix3x3 rotation = obj->NodeGetWorldOrientation(); - MT_Scalar filter, newdistance; + MT_Scalar filter, newdistance, cosangle; int axis, sign; if (m_posDampTime) { @@ -178,16 +184,52 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) direction[2] = rotation[2][1]; axis = 1; break; - case KX_ACT_CONSTRAINT_ORIZ: + default: direction[0] = rotation[0][2]; direction[1] = rotation[1][2]; direction[2] = rotation[2][2]; axis = 2; break; } - // apply damping on the direction + if ((m_maximumBound < (1.0f-FLT_EPSILON)) || (m_minimumBound < (1.0f-FLT_EPSILON))) { + // reference direction needs to be evaluated + // 1. get the cosine between current direction and target + cosangle = direction.dot(m_refDirection); + if (cosangle >= (m_maximumBound-FLT_EPSILON) && cosangle <= (m_minimumBound+FLT_EPSILON)) { + // no change to do + result = true; + goto CHECK_TIME; + } + // 2. define a new reference direction + // compute local axis with reference direction as X and + // Y in direction X refDirection plane + MT_Vector3 zaxis = m_refDirection.cross(direction); + if (MT_fuzzyZero2(zaxis.length2())) { + // direction and refDirection are identical, + // choose any other direction to define plane + if (direction[0] < 0.9999) + zaxis = m_refDirection.cross(MT_Vector3(1.0,0.0,0.0)); + else + zaxis = m_refDirection.cross(MT_Vector3(0.0,1.0,0.0)); + } + MT_Vector3 yaxis = zaxis.cross(m_refDirection); + yaxis.normalize(); + if (cosangle > m_minimumBound) { + // angle is too close to reference direction, + // choose a new reference that is exactly at minimum angle + refDirection = m_minimumBound * m_refDirection + m_minimumSine * yaxis; + } else { + // angle is too large, choose new reference direction at maximum angle + refDirection = m_maximumBound * m_refDirection + m_maximumSine * yaxis; + } + } else { + refDirection = m_refDirection; + } if (m_posDampTime) { - direction = filter*direction + (1.0-filter)*m_refDirection; + // apply damping on the direction + direction = filter*direction + (1.0-filter)*refDirection; + } else { + direction = refDirection; } obj->AlignAxisToVect(direction, axis); result = true; @@ -195,9 +237,9 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) case KX_ACT_CONSTRAINT_DIRPX: case KX_ACT_CONSTRAINT_DIRPY: case KX_ACT_CONSTRAINT_DIRPZ: - case KX_ACT_CONSTRAINT_DIRMX: - case KX_ACT_CONSTRAINT_DIRMY: - case KX_ACT_CONSTRAINT_DIRMZ: + case KX_ACT_CONSTRAINT_DIRNX: + case KX_ACT_CONSTRAINT_DIRNY: + case KX_ACT_CONSTRAINT_DIRNZ: switch (m_locrot) { case KX_ACT_CONSTRAINT_DIRPX: direction[0] = rotation[0][0]; @@ -220,21 +262,21 @@ bool KX_ConstraintActuator::Update(double curtime, bool frame) axis = 2; sign = 1; break; - case KX_ACT_CONSTRAINT_DIRMX: + case KX_ACT_CONSTRAINT_DIRNX: direction[0] = -rotation[0][0]; direction[1] = -rotation[1][0]; direction[2] = -rotation[2][0]; axis = 0; sign = 0; break; - case KX_ACT_CONSTRAINT_DIRMY: + case KX_ACT_CONSTRAINT_DIRNY: direction[0] = -rotation[0][1]; direction[1] = -rotation[1][1]; direction[2] = -rotation[2][1]; axis = 1; sign = 0; break; - case KX_ACT_CONSTRAINT_DIRMZ: + case KX_ACT_CONSTRAINT_DIRNZ: direction[0] = -rotation[0][2]; direction[1] = -rotation[1][2]; direction[2] = -rotation[2][2]; @@ -395,27 +437,27 @@ PyParentObject KX_ConstraintActuator::Parents[] = { PyMethodDef KX_ConstraintActuator::Methods[] = { {"setDamp", (PyCFunction) KX_ConstraintActuator::sPySetDamp, METH_VARARGS, SetDamp_doc}, - {"getDamp", (PyCFunction) KX_ConstraintActuator::sPyGetDamp, METH_VARARGS, GetDamp_doc}, + {"getDamp", (PyCFunction) KX_ConstraintActuator::sPyGetDamp, METH_NOARGS, GetDamp_doc}, {"setRotDamp", (PyCFunction) KX_ConstraintActuator::sPySetRotDamp, METH_VARARGS, SetRotDamp_doc}, - {"getRotDamp", (PyCFunction) KX_ConstraintActuator::sPyGetRotDamp, METH_VARARGS, GetRotDamp_doc}, + {"getRotDamp", (PyCFunction) KX_ConstraintActuator::sPyGetRotDamp, METH_NOARGS, GetRotDamp_doc}, {"setDirection", (PyCFunction) KX_ConstraintActuator::sPySetDirection, METH_VARARGS, SetDirection_doc}, - {"getDirection", (PyCFunction) KX_ConstraintActuator::sPyGetDirection, METH_VARARGS, GetDirection_doc}, + {"getDirection", (PyCFunction) KX_ConstraintActuator::sPyGetDirection, METH_NOARGS, GetDirection_doc}, {"setOption", (PyCFunction) KX_ConstraintActuator::sPySetOption, METH_VARARGS, SetOption_doc}, - {"getOption", (PyCFunction) KX_ConstraintActuator::sPyGetOption, METH_VARARGS, GetOption_doc}, + {"getOption", (PyCFunction) KX_ConstraintActuator::sPyGetOption, METH_NOARGS, GetOption_doc}, {"setTime", (PyCFunction) KX_ConstraintActuator::sPySetTime, METH_VARARGS, SetTime_doc}, - {"getTime", (PyCFunction) KX_ConstraintActuator::sPyGetTime, METH_VARARGS, GetTime_doc}, + {"getTime", (PyCFunction) KX_ConstraintActuator::sPyGetTime, METH_NOARGS, GetTime_doc}, {"setProperty", (PyCFunction) KX_ConstraintActuator::sPySetProperty, METH_VARARGS, SetProperty_doc}, - {"getProperty", (PyCFunction) KX_ConstraintActuator::sPyGetProperty, METH_VARARGS, GetProperty_doc}, + {"getProperty", (PyCFunction) KX_ConstraintActuator::sPyGetProperty, METH_NOARGS, GetProperty_doc}, {"setMin", (PyCFunction) KX_ConstraintActuator::sPySetMin, METH_VARARGS, SetMin_doc}, - {"getMin", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_VARARGS, GetMin_doc}, + {"getMin", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_NOARGS, GetMin_doc}, {"setDistance", (PyCFunction) KX_ConstraintActuator::sPySetMin, METH_VARARGS, SetDistance_doc}, - {"getDistance", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_VARARGS, GetDistance_doc}, + {"getDistance", (PyCFunction) KX_ConstraintActuator::sPyGetMin, METH_NOARGS, GetDistance_doc}, {"setMax", (PyCFunction) KX_ConstraintActuator::sPySetMax, METH_VARARGS, SetMax_doc}, - {"getMax", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_VARARGS, GetMax_doc}, + {"getMax", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_NOARGS, GetMax_doc}, {"setRayLength", (PyCFunction) KX_ConstraintActuator::sPySetMax, METH_VARARGS, SetRayLength_doc}, - {"getRayLength", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_VARARGS, GetRayLength_doc}, + {"getRayLength", (PyCFunction) KX_ConstraintActuator::sPyGetMax, METH_NOARGS, GetRayLength_doc}, {"setLimit", (PyCFunction) KX_ConstraintActuator::sPySetLimit, METH_VARARGS, SetLimit_doc}, - {"getLimit", (PyCFunction) KX_ConstraintActuator::sPyGetLimit, METH_VARARGS, GetLimit_doc}, + {"getLimit", (PyCFunction) KX_ConstraintActuator::sPyGetLimit, METH_NOARGS, GetLimit_doc}, {NULL,NULL} //Sentinel }; @@ -434,6 +476,7 @@ PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self, PyObject* kwds) { int dampArg; if(!PyArg_ParseTuple(args, "i", &dampArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -446,9 +489,7 @@ PyObject* KX_ConstraintActuator::PySetDamp(PyObject* self, char KX_ConstraintActuator::GetDamp_doc[] = "getDamp()\n" "\tReturns the damping parameter.\n"; -PyObject* KX_ConstraintActuator::PyGetDamp(PyObject* self, - PyObject* args, - PyObject* kwds){ +PyObject* KX_ConstraintActuator::PyGetDamp(PyObject* self){ return PyInt_FromLong(m_posDampTime); } @@ -463,6 +504,7 @@ PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self, PyObject* kwds) { int dampArg; if(!PyArg_ParseTuple(args, "i", &dampArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -475,9 +517,7 @@ PyObject* KX_ConstraintActuator::PySetRotDamp(PyObject* self, char KX_ConstraintActuator::GetRotDamp_doc[] = "getRotDamp()\n" "\tReturns the damping time for application of the constraint.\n"; -PyObject* KX_ConstraintActuator::PyGetRotDamp(PyObject* self, - PyObject* args, - PyObject* kwds){ +PyObject* KX_ConstraintActuator::PyGetRotDamp(PyObject* self){ return PyInt_FromLong(m_rotDampTime); } @@ -494,6 +534,7 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self, MT_Vector3 dir; if(!PyArg_ParseTuple(args, "(fff)", &x, &y, &z)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } dir[0] = x; @@ -512,9 +553,7 @@ PyObject* KX_ConstraintActuator::PySetDirection(PyObject* self, char KX_ConstraintActuator::GetDirection_doc[] = "getDirection()\n" "\tReturns the reference direction of the orientation constraint as a 3-tuple.\n"; -PyObject* KX_ConstraintActuator::PyGetDirection(PyObject* self, - PyObject* args, - PyObject* kwds){ +PyObject* KX_ConstraintActuator::PyGetDirection(PyObject* self){ PyObject *retVal = PyList_New(3); PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_refDirection[0])); @@ -538,6 +577,7 @@ PyObject* KX_ConstraintActuator::PySetOption(PyObject* self, PyObject* kwds) { int option; if(!PyArg_ParseTuple(args, "i", &option)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -549,9 +589,7 @@ PyObject* KX_ConstraintActuator::PySetOption(PyObject* self, char KX_ConstraintActuator::GetOption_doc[] = "getOption()\n" "\tReturns the option parameter.\n"; -PyObject* KX_ConstraintActuator::PyGetOption(PyObject* self, - PyObject* args, - PyObject* kwds){ +PyObject* KX_ConstraintActuator::PyGetOption(PyObject* self){ return PyInt_FromLong(m_option); } @@ -567,6 +605,7 @@ PyObject* KX_ConstraintActuator::PySetTime(PyObject* self, PyObject* kwds) { int t; if(!PyArg_ParseTuple(args, "i", &t)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -580,9 +619,7 @@ PyObject* KX_ConstraintActuator::PySetTime(PyObject* self, char KX_ConstraintActuator::GetTime_doc[] = "getTime()\n" "\tReturns the time parameter.\n"; -PyObject* KX_ConstraintActuator::PyGetTime(PyObject* self, - PyObject* args, - PyObject* kwds){ +PyObject* KX_ConstraintActuator::PyGetTime(PyObject* self){ return PyInt_FromLong(m_activeTime); } @@ -597,6 +634,7 @@ PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self, PyObject* kwds) { char *property; if (!PyArg_ParseTuple(args, "s", &property)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } if (property == NULL) { @@ -612,9 +650,7 @@ PyObject* KX_ConstraintActuator::PySetProperty(PyObject* self, char KX_ConstraintActuator::GetProperty_doc[] = "getProperty()\n" "\tReturns the property parameter.\n"; -PyObject* KX_ConstraintActuator::PyGetProperty(PyObject* self, - PyObject* args, - PyObject* kwds){ +PyObject* KX_ConstraintActuator::PyGetProperty(PyObject* self){ return PyString_FromString(m_property); } @@ -634,6 +670,7 @@ PyObject* KX_ConstraintActuator::PySetMin(PyObject* self, PyObject* kwds) { float minArg; if(!PyArg_ParseTuple(args, "f", &minArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -659,9 +696,7 @@ char KX_ConstraintActuator::GetMin_doc[] = "getMin()\n" "\tReturns the lower value of the interval to which the value\n" "\tis clipped.\n"; -PyObject* KX_ConstraintActuator::PyGetMin(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PyGetMin(PyObject* self) { return PyFloat_FromDouble(m_minimumBound); } @@ -681,6 +716,7 @@ PyObject* KX_ConstraintActuator::PySetMax(PyObject* self, PyObject* kwds){ float maxArg; if(!PyArg_ParseTuple(args, "f", &maxArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -706,9 +742,7 @@ char KX_ConstraintActuator::GetMax_doc[] = "getMax()\n" "\tReturns the upper value of the interval to which the value\n" "\tis clipped.\n"; -PyObject* KX_ConstraintActuator::PyGetMax(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PyGetMax(PyObject* self) { return PyFloat_FromDouble(m_maximumBound); } @@ -736,6 +770,7 @@ PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self, PyObject* kwds) { int locrotArg; if(!PyArg_ParseTuple(args, "i", &locrotArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -747,9 +782,7 @@ PyObject* KX_ConstraintActuator::PySetLimit(PyObject* self, char KX_ConstraintActuator::GetLimit_doc[] = "getLimit()\n" "\tReturns the type of constraint.\n"; -PyObject* KX_ConstraintActuator::PyGetLimit(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ConstraintActuator::PyGetLimit(PyObject* self) { return PyInt_FromLong(m_locrot); } diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index 5a1d4d23217..d9f39124cac 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -48,6 +48,10 @@ protected: float m_minimumBound; // max (float) float m_maximumBound; + // sinus of minimum angle + float m_minimumSine; + // sinus of maximum angle + float m_maximumSine; // reference direction MT_Vector3 m_refDirection; // locrotxyz choice (pick one): only one choice allowed at a time! @@ -80,9 +84,9 @@ protected: KX_ACT_CONSTRAINT_DIRPX, KX_ACT_CONSTRAINT_DIRPY, KX_ACT_CONSTRAINT_DIRPZ, - KX_ACT_CONSTRAINT_DIRMX, - KX_ACT_CONSTRAINT_DIRMY, - KX_ACT_CONSTRAINT_DIRMZ, + KX_ACT_CONSTRAINT_DIRNX, + KX_ACT_CONSTRAINT_DIRNY, + KX_ACT_CONSTRAINT_DIRNZ, KX_ACT_CONSTRAINT_ORIX, KX_ACT_CONSTRAINT_ORIY, KX_ACT_CONSTRAINT_ORIZ, @@ -127,27 +131,27 @@ protected: virtual PyObject* _getattr(const STR_String& attr); KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDamp); - KX_PYMETHOD_DOC(KX_ConstraintActuator,GetDamp); + KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetDamp); KX_PYMETHOD_DOC(KX_ConstraintActuator,SetRotDamp); - KX_PYMETHOD_DOC(KX_ConstraintActuator,GetRotDamp); + KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetRotDamp); KX_PYMETHOD_DOC(KX_ConstraintActuator,SetDirection); - KX_PYMETHOD_DOC(KX_ConstraintActuator,GetDirection); + KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetDirection); KX_PYMETHOD_DOC(KX_ConstraintActuator,SetOption); - KX_PYMETHOD_DOC(KX_ConstraintActuator,GetOption); + KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetOption); KX_PYMETHOD_DOC(KX_ConstraintActuator,SetTime); - KX_PYMETHOD_DOC(KX_ConstraintActuator,GetTime); + KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetTime); KX_PYMETHOD_DOC(KX_ConstraintActuator,SetProperty); - KX_PYMETHOD_DOC(KX_ConstraintActuator,GetProperty); + KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetProperty); KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMin); - KX_PYMETHOD_DOC(KX_ConstraintActuator,GetMin); + KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetMin); static char SetDistance_doc[]; static char GetDistance_doc[]; KX_PYMETHOD_DOC(KX_ConstraintActuator,SetMax); - KX_PYMETHOD_DOC(KX_ConstraintActuator,GetMax); + KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetMax); static char SetRayLength_doc[]; static char GetRayLength_doc[]; KX_PYMETHOD_DOC(KX_ConstraintActuator,SetLimit); - KX_PYMETHOD_DOC(KX_ConstraintActuator,GetLimit); + KX_PYMETHOD_DOC_NOARGS(KX_ConstraintActuator,GetLimit); }; #endif //__KX_CONSTRAINTACTUATOR diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index 2ac4f909077..6fcd3df2afc 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -61,6 +61,8 @@ typedef unsigned long uint_ptr; #include "KX_RayCast.h" #include "KX_PythonInit.h" #include "KX_PyMath.h" +#include "SCA_IActuator.h" +#include "SCA_ISensor.h" // This file defines relationships between parents and children // in the game engine. @@ -75,10 +77,10 @@ KX_GameObject::KX_GameObject( SCA_IObject(T), m_bDyna(false), m_layer(0), + m_pBlenderObject(NULL), m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), - m_pBlenderObject(NULL), m_bVisible(true), m_pPhysicsController1(NULL), m_pPhysicsEnvironment(NULL), @@ -94,12 +96,9 @@ KX_GameObject::KX_GameObject( KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New(); m_pSGNode->SetParentRelation(parent_relation); - - }; - KX_GameObject::~KX_GameObject() { // is this delete somewhere ? @@ -163,6 +162,7 @@ STR_String KX_GameObject::GetName() void KX_GameObject::SetName(STR_String name) { m_name = name; + }; // Set the name of the value @@ -222,6 +222,10 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) RemoveParent(scene); obj->GetSGNode()->AddChild(GetSGNode()); + if (m_pPhysicsController1) + { + m_pPhysicsController1->SuspendDynamics(true); + } // Set us to our new scale, position, and orientation scale1[0] = scale1[0]/scale2[0]; scale1[1] = scale1[1]/scale2[1]; @@ -258,6 +262,10 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) if (!rootlist->SearchValue(this)) // object was not in root list, add it now and increment ref count rootlist->Add(AddRef()); + if (m_pPhysicsController1) + { + m_pPhysicsController1->RestoreDynamics(); + } } } @@ -267,6 +275,7 @@ void KX_GameObject::ProcessReplica(KX_GameObject* replica) replica->m_pSGNode = NULL; replica->m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info); replica->m_pClient_info->m_gameobject = replica; + replica->m_state = 0; } @@ -432,6 +441,7 @@ void KX_GameObject::UpdateIPO(float curframetime, // IPO update void KX_GameObject::UpdateMaterialData( + dword matname_hash, MT_Vector4 rgba, MT_Vector3 specrgb, MT_Scalar hard, @@ -443,16 +453,35 @@ KX_GameObject::UpdateMaterialData( ) { int mesh = 0; + if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { RAS_MaterialBucket::Set::iterator mit = m_meshes[mesh]->GetFirstMaterial(); for(; mit != m_meshes[mesh]->GetLastMaterial(); ++mit) { RAS_IPolyMaterial* poly = (*mit)->GetPolyMaterial(); - if(poly->GetFlag() & RAS_BLENDERMAT ) + if(poly->GetFlag() & RAS_BLENDERMAT) { - SetObjectColor(rgba); KX_BlenderMaterial *m = static_cast<KX_BlenderMaterial*>(poly); - m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); + + if (matname_hash == NULL) + { + m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); + // if mesh has only one material attached to it then use original hack with no need to edit vertices (better performance) + if(!(poly->GetFlag() & RAS_BLENDERGLSL)) + SetObjectColor(rgba); + } + else + { + if (matname_hash == poly->GetMaterialNameHash()) + { + m->UpdateIPO(rgba, specrgb,hard,spec,ref,emit, alpha); + m_meshes[mesh]->SetVertexColor(poly,rgba); + + // no break here, because one blender material can be split into several game engine materials + // (e.g. one uvsphere material is split into one material at poles with ras_mode TRIANGLE and one material for the body + // if here was a break then would miss some vertices if material was split + } + } } } } @@ -714,8 +743,12 @@ MT_Vector3 KX_GameObject::GetAngularVelocity(bool local) void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans) { - if (m_pPhysicsController1) + if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent())) { + // don't update physic controller if the object is a child: + // 1) the transformation will not be right + // 2) in this case, the physic controller is necessarily a static object + // that is updated from the normal kinematic synchronization m_pPhysicsController1->setPosition(trans); } @@ -727,25 +760,22 @@ void KX_GameObject::NodeSetLocalPosition(const MT_Point3& trans) void KX_GameObject::NodeSetLocalOrientation(const MT_Matrix3x3& rot) { - if (m_pPhysicsController1) + if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent())) { - m_pPhysicsController1->setOrientation(rot.getRotation()); + // see note above + m_pPhysicsController1->setOrientation(rot); } if (GetSGNode()) GetSGNode()->SetLocalOrientation(rot); - else - { - int i; - i=0; - } } void KX_GameObject::NodeSetLocalScale(const MT_Vector3& scale) { - if (m_pPhysicsController1) + if (m_pPhysicsController1 && (!GetSGNode() || !GetSGNode()->GetSGParent())) { + // see note above m_pPhysicsController1->setScaling(scale); } @@ -832,7 +862,7 @@ void KX_GameObject::Resume(void) } } -void KX_GameObject::Suspend(void) +void KX_GameObject::Suspend() { if ((!m_ignore_activity_culling) && (!m_suspended)) { @@ -875,6 +905,8 @@ PyMethodDef KX_GameObject::Methods[] = { {"getParent", (PyCFunction)KX_GameObject::sPyGetParent,METH_NOARGS}, {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O}, {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS}, + {"getChildren", (PyCFunction)KX_GameObject::sPyGetChildren,METH_NOARGS}, + {"getChildrenRecursive", (PyCFunction)KX_GameObject::sPyGetChildrenRecursive,METH_NOARGS}, {"getMesh", (PyCFunction)KX_GameObject::sPyGetMesh,METH_VARARGS}, {"getPhysicsId", (PyCFunction)KX_GameObject::sPyGetPhysicsId,METH_NOARGS}, {"getPropertyNames", (PyCFunction)KX_GameObject::sPyGetPropertyNames,METH_NOARGS}, @@ -882,6 +914,7 @@ PyMethodDef KX_GameObject::Methods[] = { KX_PYMETHODTABLE(KX_GameObject, rayCastTo), KX_PYMETHODTABLE(KX_GameObject, rayCast), KX_PYMETHODTABLE(KX_GameObject, getDistanceTo), + KX_PYMETHODTABLE(KX_GameObject, getVectTo), {NULL,NULL} //Sentinel }; @@ -1292,20 +1325,58 @@ PyObject* KX_GameObject::PyRemoveParent(PyObject* self) Py_RETURN_NONE; } + +static void walk_children(SG_Node* node, CListValue* list, bool recursive) +{ + NodeList& children = node->GetSGChildren(); + + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* childnode = (*childit); + CValue* childobj = (CValue*)childnode->GetSGClientObject(); + if (childobj != NULL) // This is a GameObject + { + // add to the list + list->Add(childobj->AddRef()); + } + + // if the childobj is NULL then this may be an inverse parent link + // so a non recursive search should still look down this node. + if (recursive || childobj==NULL) { + walk_children(childnode, list, recursive); + } + } +} + +PyObject* KX_GameObject::PyGetChildren(PyObject* self) +{ + CListValue* list = new CListValue(); + walk_children(m_pSGNode, list, 0); + return list; +} + +PyObject* KX_GameObject::PyGetChildrenRecursive(PyObject* self) +{ + CListValue* list = new CListValue(); + walk_children(m_pSGNode, list, 1); + return list; +} + PyObject* KX_GameObject::PyGetMesh(PyObject* self, PyObject* args, PyObject* kwds) { int mesh = 0; - if (PyArg_ParseTuple(args, "|i", &mesh)) + if (!PyArg_ParseTuple(args, "|i", &mesh)) + return NULL; // python sets a simple error + + if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) { - if (((unsigned int)mesh < m_meshes.size()) && mesh >= 0) - { - KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]); - return meshproxy; - } + KX_MeshProxy* meshproxy = new KX_MeshProxy(m_meshes[mesh]); + return meshproxy; } + Py_RETURN_NONE; } @@ -1420,6 +1491,7 @@ PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* self, if (PyVecTo(pyvect, vect)) { AlignAxisToVect(vect,axis,fac); + NodeUpdateGS(0.f,true); Py_RETURN_NONE; } } @@ -1485,6 +1557,54 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getDistanceTo, return NULL; } +KX_PYMETHODDEF_DOC(KX_GameObject, getVectTo, +"getVectTo(other): get vector and the distance to another point/KX_GameObject\n" +"Returns a 3-tuple with (distance,worldVector,localVector)\n") +{ + MT_Point3 toPoint, fromPoint; + MT_Vector3 toDir, locToDir; + MT_Scalar distance; + + PyObject *returnValue; + PyObject *pyother; + + if (!PyVecArgTo(args, toPoint)) + { + PyErr_Clear(); + if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &pyother)) + { + KX_GameObject *other = static_cast<KX_GameObject*>(pyother); + toPoint = other->NodeGetWorldPosition(); + }else + { + PyErr_SetString(PyExc_TypeError, "Expected a 3D Vector or GameObject type"); + return NULL; + } + } + + fromPoint = NodeGetWorldPosition(); + toDir = toPoint-fromPoint; + distance = toDir.length(); + + if (MT_fuzzyZero(distance)) + { + //cout << "getVectTo() Error: Null vector!\n"; + locToDir = toDir = MT_Vector3(0.0,0.0,0.0); + distance = 0.0; + } else { + toDir.normalize(); + locToDir = toDir * NodeGetWorldOrientation(); + } + + returnValue = PyTuple_New(3); + if (returnValue) { // very unlikely to fail, python sets a memory error here. + PyTuple_SET_ITEM(returnValue, 0, PyFloat_FromDouble(distance)); + PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(toDir)); + PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(locToDir)); + } + return returnValue; +} + bool KX_GameObject::RayHit(KX_ClientObjectInfo* client, MT_Point3& hit_point, MT_Vector3& hit_normal, void * const data) { @@ -1517,8 +1637,9 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, float dist = 0.0f; char *propName = NULL; - if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName)) - return NULL; + if (!PyArg_ParseTuple(args,"O|fs", &pyarg, &dist, &propName)) { + return NULL; // python sets simple error + } if (!PyVecTo(pyarg, toPoint)) { @@ -1565,11 +1686,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, } KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, -"rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or None if no hit\n" + "rayCast(to,from,dist,prop): cast a ray and return tuple (object,hit,normal) of contact point with object within dist that matches prop or (None,None,None) tuple if no hit\n" " prop = property name that object must have; can be omitted => detect any object\n" " dist = max distance to look (can be negative => look behind); 0 or omitted => detect up to to\n" " from = 3-tuple or object reference for origin of ray (if object, use center of object)\n" -" Can None or omitted => start from self object center\n" +" Can be None or omitted => start from self object center\n" " to = 3-tuple or object reference for destination of ray (if object, use center of object)\n" "Note: the object on which you call this method matters: the ray will ignore it if it goes through it\n") { @@ -1581,8 +1702,9 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, char *propName = NULL; KX_GameObject *other; - if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) - return NULL; + if (!PyArg_ParseTuple(args,"O|Ofs", &pyto, &pyfrom, &dist, &propName)) { + return NULL; // Python sets a simple error + } if (!PyVecTo(pyto, toPoint)) { @@ -1640,16 +1762,12 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, if (m_pHitObject) { PyObject* returnValue = PyTuple_New(3); - if (!returnValue) - return NULL; - PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); - PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint)); - PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal)); + if (returnValue) { // unlikely this would ever fail, if it does python sets an error + PyTuple_SET_ITEM(returnValue, 0, m_pHitObject->AddRef()); + PyTuple_SET_ITEM(returnValue, 1, PyObjectFrom(resultPoint)); + PyTuple_SET_ITEM(returnValue, 2, PyObjectFrom(resultNormal)); + } return returnValue; - //return Py_BuildValue("(O,(fff),(fff))", - // m_pHitObject->AddRef(), // trick: KX_GameObject are not true Python object, they use a difference reference count system - // resultPoint[0], resultPoint[1], resultPoint[2], - // resultNormal[0], resultNormal[1], resultNormal[2]); } return Py_BuildValue("OOO", Py_None, Py_None, Py_None); //Py_RETURN_NONE; @@ -1660,6 +1778,20 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, * --------------------------------------------------------------------- */ void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter) { - /* intentionally empty ? */ + // we will relink the sensors and actuators that use object references + // if the object is part of the replicated hierarchy, use the new + // object reference instead + SCA_SensorList& sensorlist = GetSensors(); + SCA_SensorList::iterator sit; + for (sit=sensorlist.begin(); sit != sensorlist.end(); sit++) + { + (*sit)->Relink(map_parameter); + } + SCA_ActuatorList& actuatorlist = GetActuators(); + SCA_ActuatorList::iterator ait; + for (ait=actuatorlist.begin(); ait != actuatorlist.end(); ait++) + { + (*ait)->Relink(map_parameter); + } } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index ddbf863aa1a..4e435e9ddf4 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -47,6 +47,7 @@ #include "KX_Scene.h" #include "KX_KetsjiEngine.h" /* for m_anim_framerate */ #include "KX_IPhysicsController.h" /* for suspend/resume */ +#include "DNA_object_types.h" #define KX_OB_DYNAMIC 1 @@ -392,6 +393,13 @@ public: m_pBlenderObject = obj; } + bool IsDupliGroup() + { + return (m_pBlenderObject && + (m_pBlenderObject->transflag & OB_DUPLIGROUP) && + m_pBlenderObject->dup_group != NULL) ? true : false; + } + /** * Set the Scene graph node for this game object. * warning - it is your responsibility to make sure @@ -513,6 +521,7 @@ public: */ void UpdateMaterialData( + dword matname_hash, MT_Vector4 rgba, MT_Vector3 specrgb, MT_Scalar hard, @@ -738,6 +747,8 @@ public: KX_PYMETHOD_NOARGS(KX_GameObject,GetParent); KX_PYMETHOD_O(KX_GameObject,SetParent); KX_PYMETHOD_NOARGS(KX_GameObject,RemoveParent); + KX_PYMETHOD_NOARGS(KX_GameObject,GetChildren); + KX_PYMETHOD_NOARGS(KX_GameObject,GetChildrenRecursive); KX_PYMETHOD(KX_GameObject,GetMesh); KX_PYMETHOD_NOARGS(KX_GameObject,GetPhysicsId); KX_PYMETHOD_NOARGS(KX_GameObject,GetPropertyNames); @@ -745,6 +756,7 @@ public: KX_PYMETHOD_DOC(KX_GameObject,rayCastTo); KX_PYMETHOD_DOC(KX_GameObject,rayCast); KX_PYMETHOD_DOC(KX_GameObject,getDistanceTo); + KX_PYMETHOD_DOC(KX_GameObject,getVectTo); private : diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h index 2ec66a883eb..ecfdb8c4275 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.h +++ b/source/gameengine/Ketsji/KX_IPhysicsController.h @@ -71,14 +71,15 @@ public: virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) = 0; virtual void getOrientation(MT_Quaternion& orn)=0; - virtual void setOrientation(const MT_Quaternion& orn)=0; + virtual void setOrientation(const MT_Matrix3x3& orn)=0; + //virtual void setOrientation(const MT_Quaternion& orn)=0; virtual void setPosition(const MT_Point3& pos)=0; virtual void setScaling(const MT_Vector3& scaling)=0; virtual MT_Scalar GetMass()=0; virtual MT_Vector3 getReactionForce()=0; virtual void setRigidBody(bool rigid)=0; - virtual void SuspendDynamics()=0; + virtual void SuspendDynamics(bool ghost=false)=0; virtual void RestoreDynamics()=0; virtual SG_Controller* GetReplica(class SG_Node* destnode)=0; diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index b7103f49aee..af3add8a323 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -430,27 +430,27 @@ PyMethodDef KX_IpoActuator::Methods[] = { {"setStart", (PyCFunction) KX_IpoActuator::sPySetStart, METH_VARARGS, SetStart_doc}, {"getStart", (PyCFunction) KX_IpoActuator::sPyGetStart, - METH_VARARGS, GetStart_doc}, + METH_NOARGS, GetStart_doc}, {"setEnd", (PyCFunction) KX_IpoActuator::sPySetEnd, METH_VARARGS, SetEnd_doc}, {"getEnd", (PyCFunction) KX_IpoActuator::sPyGetEnd, - METH_VARARGS, GetEnd_doc}, + METH_NOARGS, GetEnd_doc}, {"setIpoAsForce", (PyCFunction) KX_IpoActuator::sPySetIpoAsForce, METH_VARARGS, SetIpoAsForce_doc}, {"getIpoAsForce", (PyCFunction) KX_IpoActuator::sPyGetIpoAsForce, - METH_VARARGS, GetIpoAsForce_doc}, + METH_NOARGS, GetIpoAsForce_doc}, {"setIpoAdd", (PyCFunction) KX_IpoActuator::sPySetIpoAdd, METH_VARARGS, SetIpoAdd_doc}, {"getIpoAdd", (PyCFunction) KX_IpoActuator::sPyGetIpoAdd, - METH_VARARGS, GetIpoAdd_doc}, + METH_NOARGS, GetIpoAdd_doc}, {"setType", (PyCFunction) KX_IpoActuator::sPySetType, METH_VARARGS, SetType_doc}, {"getType", (PyCFunction) KX_IpoActuator::sPyGetType, - METH_VARARGS, GetType_doc}, + METH_NOARGS, GetType_doc}, {"setForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPySetForceIpoActsLocal, METH_VARARGS, SetForceIpoActsLocal_doc}, {"getForceIpoActsLocal", (PyCFunction) KX_IpoActuator::sPyGetForceIpoActsLocal, - METH_VARARGS, GetForceIpoActsLocal_doc}, + METH_NOARGS, GetForceIpoActsLocal_doc}, {NULL,NULL} //Sentinel }; @@ -480,6 +480,7 @@ PyObject* KX_IpoActuator::PySet(PyObject* self, int startFrame, stopFrame; if(!PyArg_ParseTuple(args, "siii", &mode, &startFrame, &stopFrame, &forceToggle)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } modenum = string2mode(mode); @@ -515,6 +516,7 @@ PyObject* KX_IpoActuator::PySetProperty(PyObject* self, /* args: property */ char *propertyName; if(!PyArg_ParseTuple(args, "s", &propertyName)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -533,6 +535,7 @@ PyObject* KX_IpoActuator::PySetStart(PyObject* self, PyObject* kwds) { float startArg; if(!PyArg_ParseTuple(args, "f", &startArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -544,9 +547,7 @@ PyObject* KX_IpoActuator::PySetStart(PyObject* self, char KX_IpoActuator::GetStart_doc[] = "getStart()\n" "\tReturns the frame from which the ipo starts playing.\n"; -PyObject* KX_IpoActuator::PyGetStart(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PyGetStart(PyObject* self) { return PyFloat_FromDouble(m_startframe); } @@ -560,6 +561,7 @@ PyObject* KX_IpoActuator::PySetEnd(PyObject* self, PyObject* kwds) { float endArg; if(!PyArg_ParseTuple(args, "f", &endArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -571,9 +573,7 @@ PyObject* KX_IpoActuator::PySetEnd(PyObject* self, char KX_IpoActuator::GetEnd_doc[] = "getEnd()\n" "\tReturns the frame at which the ipo stops playing.\n"; -PyObject* KX_IpoActuator::PyGetEnd(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PyGetEnd(PyObject* self) { return PyFloat_FromDouble(m_endframe); } @@ -588,6 +588,7 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self, int boolArg; if (!PyArg_ParseTuple(args, "i", &boolArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -601,9 +602,7 @@ PyObject* KX_IpoActuator::PySetIpoAsForce(PyObject* self, char KX_IpoActuator::GetIpoAsForce_doc[] = "getIpoAsForce()\n" "\tReturns whether to interpret the ipo as a force rather than a displacement.\n"; -PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PyGetIpoAsForce(PyObject* self) { return BoolToPyArg(m_ipo_as_force); } @@ -618,6 +617,7 @@ PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self, int boolArg; if (!PyArg_ParseTuple(args, "i", &boolArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -631,9 +631,7 @@ PyObject* KX_IpoActuator::PySetIpoAdd(PyObject* self, char KX_IpoActuator::GetIpoAdd_doc[] = "getIpoAsAdd()\n" "\tReturns whether to interpret the ipo as additive rather than absolute.\n"; -PyObject* KX_IpoActuator::PyGetIpoAdd(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PyGetIpoAdd(PyObject* self) { return BoolToPyArg(m_ipo_add); } @@ -648,6 +646,7 @@ PyObject* KX_IpoActuator::PySetType(PyObject* self, int typeArg; if (!PyArg_ParseTuple(args, "i", &typeArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -662,9 +661,7 @@ PyObject* KX_IpoActuator::PySetType(PyObject* self, char KX_IpoActuator::GetType_doc[] = "getType()\n" "\tReturns the operation mode of the actuator.\n"; -PyObject* KX_IpoActuator::PyGetType(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PyGetType(PyObject* self) { return PyInt_FromLong(m_type); } @@ -681,6 +678,7 @@ PyObject* KX_IpoActuator::PySetForceIpoActsLocal(PyObject* self, int boolArg; if (!PyArg_ParseTuple(args, "i", &boolArg)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } @@ -693,9 +691,7 @@ char KX_IpoActuator::GetForceIpoActsLocal_doc[] = "getForceIpoActsLocal()\n" "\tReturn whether to apply the force in the object's local\n" "\tcoordinates rather than the world global coordinates.\n"; -PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_IpoActuator::PyGetForceIpoActsLocal(PyObject* self) { return BoolToPyArg(m_ipo_local); } diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h index ae554fb0fce..d6f52f8d59d 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.h +++ b/source/gameengine/Ketsji/KX_IpoActuator.h @@ -143,17 +143,17 @@ public: KX_PYMETHOD_DOC(KX_IpoActuator,SetProperty); /* KX_PYMETHOD_DOC(KX_IpoActuator,SetKey2Key); */ KX_PYMETHOD_DOC(KX_IpoActuator,SetStart); - KX_PYMETHOD_DOC(KX_IpoActuator,GetStart); + KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetStart); KX_PYMETHOD_DOC(KX_IpoActuator,SetEnd); - KX_PYMETHOD_DOC(KX_IpoActuator,GetEnd); + KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetEnd); KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAsForce); - KX_PYMETHOD_DOC(KX_IpoActuator,GetIpoAsForce); + KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetIpoAsForce); KX_PYMETHOD_DOC(KX_IpoActuator,SetIpoAdd); - KX_PYMETHOD_DOC(KX_IpoActuator,GetIpoAdd); + KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetIpoAdd); KX_PYMETHOD_DOC(KX_IpoActuator,SetType); - KX_PYMETHOD_DOC(KX_IpoActuator,GetType); + KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetType); KX_PYMETHOD_DOC(KX_IpoActuator,SetForceIpoActsLocal); - KX_PYMETHOD_DOC(KX_IpoActuator,GetForceIpoActsLocal); + KX_PYMETHOD_DOC_NOARGS(KX_IpoActuator,GetForceIpoActsLocal); }; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index db099d56b55..1d6cc975ab5 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -118,7 +118,6 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_bInitialized(false), m_activecam(0), m_bFixedTime(false), - m_game2ipo(false), m_firstframe(true), @@ -148,6 +147,8 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_showBackground(false), m_show_debug_properties(false), + m_game2ipo(false), + // Default behavior is to hide the cursor every frame. m_hideCursor(false), diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp index c0757a32b9c..2ce5d469380 100644 --- a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp @@ -37,6 +37,7 @@ bool KX_MaterialIpoController::Update(double currentTime) //kxgameobj->SetObjectColor(m_rgba); kxgameobj->UpdateMaterialData( + m_matname_hash, m_rgba, m_specrgb, m_hard, diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.h b/source/gameengine/Ketsji/KX_MaterialIpoController.h index e76ddeefb04..4d2e258bf94 100644 --- a/source/gameengine/Ketsji/KX_MaterialIpoController.h +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.h @@ -7,6 +7,8 @@ #include "SG_Spatial.h" #include "KX_IInterpolator.h" +#include "STR_String.h" //typedef dword + class KX_MaterialIpoController : public SG_Controller { public: @@ -23,10 +25,12 @@ private: bool m_modified; double m_ipotime; + dword m_matname_hash; public: - KX_MaterialIpoController() : + KX_MaterialIpoController(dword matname_hash) : m_modified(true), - m_ipotime(0.0) + m_ipotime(0.0), + m_matname_hash(matname_hash) {} virtual ~KX_MaterialIpoController(); virtual SG_Controller* GetReplica(class SG_Node* destnode); diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index d69871275b9..140dd37f5c6 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -98,6 +98,14 @@ void KX_NearSensor::RegisterSumo(KX_TouchEventManager *touchman) } } +void KX_NearSensor::UnregisterSumo(KX_TouchEventManager* touchman) +{ + if (m_physCtrl) + { + touchman->GetPhysicsEnvironment()->removeSensor(m_physCtrl); + } +} + CValue* KX_NearSensor::GetReplica() { KX_NearSensor* replica = new KX_NearSensor(*this); @@ -135,9 +143,6 @@ CValue* KX_NearSensor::GetReplica() void KX_NearSensor::ReParent(SCA_IObject* parent) { - - SCA_ISensor::ReParent(parent); - m_client_info->m_gameobject = static_cast<KX_GameObject*>(parent); m_client_info->m_sensors.push_back(this); @@ -151,6 +156,7 @@ void KX_NearSensor::ReParent(SCA_IObject* parent) */ ((KX_GameObject*)GetParent())->GetSGNode()->ComputeWorldTransforms(NULL); SynchronizeTransform(); + SCA_ISensor::ReParent(parent); } diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index c6724caccc3..3f7078ef9fd 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -77,6 +77,7 @@ public: const PHY_CollData * coll_data); virtual bool BroadPhaseFilterCollision(void*obj1,void*obj2); virtual void RegisterSumo(KX_TouchEventManager *touchman); + virtual void UnregisterSumo(KX_TouchEventManager* touchman); virtual PyObject* _getattr(const STR_String& attr); diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 9ac0b4d4703..5cd4d089c14 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -304,27 +304,27 @@ PyParentObject KX_ObjectActuator::Parents[] = { }; PyMethodDef KX_ObjectActuator::Methods[] = { - {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_VARARGS}, + {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_NOARGS}, {"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS}, - {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_VARARGS}, + {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_NOARGS}, {"setTorque", (PyCFunction) KX_ObjectActuator::sPySetTorque, METH_VARARGS}, - {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_VARARGS}, + {"getDLoc", (PyCFunction) KX_ObjectActuator::sPyGetDLoc, METH_NOARGS}, {"setDLoc", (PyCFunction) KX_ObjectActuator::sPySetDLoc, METH_VARARGS}, - {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_VARARGS}, + {"getDRot", (PyCFunction) KX_ObjectActuator::sPyGetDRot, METH_NOARGS}, {"setDRot", (PyCFunction) KX_ObjectActuator::sPySetDRot, METH_VARARGS}, - {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_VARARGS}, + {"getLinearVelocity", (PyCFunction) KX_ObjectActuator::sPyGetLinearVelocity, METH_NOARGS}, {"setLinearVelocity", (PyCFunction) KX_ObjectActuator::sPySetLinearVelocity, METH_VARARGS}, - {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_VARARGS}, + {"getAngularVelocity", (PyCFunction) KX_ObjectActuator::sPyGetAngularVelocity, METH_NOARGS}, {"setAngularVelocity", (PyCFunction) KX_ObjectActuator::sPySetAngularVelocity, METH_VARARGS}, {"setDamping", (PyCFunction) KX_ObjectActuator::sPySetDamping, METH_VARARGS}, - {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_VARARGS}, + {"getDamping", (PyCFunction) KX_ObjectActuator::sPyGetDamping, METH_NOARGS}, {"setForceLimitX", (PyCFunction) KX_ObjectActuator::sPySetForceLimitX, METH_VARARGS}, - {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_VARARGS}, + {"getForceLimitX", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitX, METH_NOARGS}, {"setForceLimitY", (PyCFunction) KX_ObjectActuator::sPySetForceLimitY, METH_VARARGS}, - {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_VARARGS}, + {"getForceLimitY", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitY, METH_NOARGS}, {"setForceLimitZ", (PyCFunction) KX_ObjectActuator::sPySetForceLimitZ, METH_VARARGS}, - {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_VARARGS}, - {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_VARARGS}, + {"getForceLimitZ", (PyCFunction) KX_ObjectActuator::sPyGetForceLimitZ, METH_NOARGS}, + {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_NOARGS}, {"getPID", (PyCFunction) KX_ObjectActuator::sPySetPID, METH_VARARGS}, @@ -340,9 +340,7 @@ PyObject* KX_ObjectActuator::_getattr(const STR_String& attr) { /* Removed! */ /* 2. getForce */ -PyObject* KX_ObjectActuator::PyGetForce(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PyGetForce(PyObject* self) { PyObject *retVal = PyList_New(4); @@ -362,6 +360,7 @@ PyObject* KX_ObjectActuator::PySetForce(PyObject* self, int bToggle = 0; if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_force.setValue(vecArg); @@ -371,9 +370,7 @@ PyObject* KX_ObjectActuator::PySetForce(PyObject* self, } /* 4. getTorque */ -PyObject* KX_ObjectActuator::PyGetTorque(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PyGetTorque(PyObject* self) { PyObject *retVal = PyList_New(4); @@ -393,6 +390,7 @@ PyObject* KX_ObjectActuator::PySetTorque(PyObject* self, int bToggle = 0; if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_torque.setValue(vecArg); @@ -402,9 +400,7 @@ PyObject* KX_ObjectActuator::PySetTorque(PyObject* self, } /* 6. getDLoc */ -PyObject* KX_ObjectActuator::PyGetDLoc(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PyGetDLoc(PyObject* self) { PyObject *retVal = PyList_New(4); @@ -424,6 +420,7 @@ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self, int bToggle = 0; if(!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_dloc.setValue(vecArg); @@ -433,9 +430,7 @@ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* self, } /* 8. getDRot */ -PyObject* KX_ObjectActuator::PyGetDRot(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PyGetDRot(PyObject* self) { PyObject *retVal = PyList_New(4); @@ -455,6 +450,7 @@ PyObject* KX_ObjectActuator::PySetDRot(PyObject* self, int bToggle = 0; if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_drot.setValue(vecArg); @@ -464,9 +460,7 @@ PyObject* KX_ObjectActuator::PySetDRot(PyObject* self, } /* 10. getLinearVelocity */ -PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ObjectActuator::PyGetLinearVelocity(PyObject* self) { PyObject *retVal = PyList_New(4); PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); @@ -485,6 +479,7 @@ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self, int bToggle = 0; if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_linear_velocity.setValue(vecArg); @@ -495,9 +490,7 @@ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* self, /* 12. getAngularVelocity */ -PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ObjectActuator::PyGetAngularVelocity(PyObject* self) { PyObject *retVal = PyList_New(4); PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0])); @@ -515,6 +508,7 @@ PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* self, int bToggle = 0; if (!PyArg_ParseTuple(args, "fffi", &vecArg[0], &vecArg[1], &vecArg[2], &bToggle)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_angular_velocity.setValue(vecArg); @@ -529,6 +523,7 @@ PyObject* KX_ObjectActuator::PySetDamping(PyObject* self, PyObject* kwds) { int damping = 0; if (!PyArg_ParseTuple(args, "i", &damping) || damping < 0 || damping > 1000) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_damping = damping; @@ -536,15 +531,11 @@ PyObject* KX_ObjectActuator::PySetDamping(PyObject* self, } /* 13. getVelocityDamping */ -PyObject* KX_ObjectActuator::PyGetDamping(PyObject* self, - PyObject* args, - PyObject* kwds) { +PyObject* KX_ObjectActuator::PyGetDamping(PyObject* self) { return Py_BuildValue("i",m_damping); } /* 6. getForceLimitX */ -PyObject* KX_ObjectActuator::PyGetForceLimitX(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PyGetForceLimitX(PyObject* self) { PyObject *retVal = PyList_New(3); @@ -562,6 +553,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self, float vecArg[2]; int bToggle = 0; if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_drot[0] = vecArg[0]; @@ -571,9 +563,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* self, } /* 6. getForceLimitY */ -PyObject* KX_ObjectActuator::PyGetForceLimitY(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PyGetForceLimitY(PyObject* self) { PyObject *retVal = PyList_New(3); @@ -591,6 +581,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self, float vecArg[2]; int bToggle = 0; if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_drot[1] = vecArg[0]; @@ -600,9 +591,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* self, } /* 6. getForceLimitZ */ -PyObject* KX_ObjectActuator::PyGetForceLimitZ(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PyGetForceLimitZ(PyObject* self) { PyObject *retVal = PyList_New(3); @@ -620,6 +609,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self, float vecArg[2]; int bToggle = 0; if(!PyArg_ParseTuple(args, "ffi", &vecArg[0], &vecArg[1], &bToggle)) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_drot[2] = vecArg[0]; @@ -629,9 +619,7 @@ PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* self, } /* 4. getPID */ -PyObject* KX_ObjectActuator::PyGetPID(PyObject* self, - PyObject* args, - PyObject* kwds) +PyObject* KX_ObjectActuator::PyGetPID(PyObject* self) { PyObject *retVal = PyList_New(3); @@ -648,6 +636,7 @@ PyObject* KX_ObjectActuator::PySetPID(PyObject* self, { float vecArg[3]; if (!PyArg_ParseTuple(args, "fff", &vecArg[0], &vecArg[1], &vecArg[2])) { + PyErr_SetString(PyExc_TypeError, "Invalid arguments"); return NULL; } m_torque.setValue(vecArg); diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index bb74756551f..aa686f41233 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -155,27 +155,27 @@ public: virtual PyObject* _getattr(const STR_String& attr); - KX_PYMETHOD(KX_ObjectActuator,GetForce); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForce); KX_PYMETHOD(KX_ObjectActuator,SetForce); - KX_PYMETHOD(KX_ObjectActuator,GetTorque); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetTorque); KX_PYMETHOD(KX_ObjectActuator,SetTorque); - KX_PYMETHOD(KX_ObjectActuator,GetDLoc); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDLoc); KX_PYMETHOD(KX_ObjectActuator,SetDLoc); - KX_PYMETHOD(KX_ObjectActuator,GetDRot); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDRot); KX_PYMETHOD(KX_ObjectActuator,SetDRot); - KX_PYMETHOD(KX_ObjectActuator,GetLinearVelocity); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetLinearVelocity); KX_PYMETHOD(KX_ObjectActuator,SetLinearVelocity); - KX_PYMETHOD(KX_ObjectActuator,GetAngularVelocity); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetAngularVelocity); KX_PYMETHOD(KX_ObjectActuator,SetAngularVelocity); KX_PYMETHOD(KX_ObjectActuator,SetDamping); - KX_PYMETHOD(KX_ObjectActuator,GetDamping); - KX_PYMETHOD(KX_ObjectActuator,GetForceLimitX); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetDamping); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitX); KX_PYMETHOD(KX_ObjectActuator,SetForceLimitX); - KX_PYMETHOD(KX_ObjectActuator,GetForceLimitY); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitY); KX_PYMETHOD(KX_ObjectActuator,SetForceLimitY); - KX_PYMETHOD(KX_ObjectActuator,GetForceLimitZ); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForceLimitZ); KX_PYMETHOD(KX_ObjectActuator,SetForceLimitZ); - KX_PYMETHOD(KX_ObjectActuator,GetPID); + KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetPID); KX_PYMETHOD(KX_ObjectActuator,SetPID); }; diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp index 4e45ce484e3..05feb11a2bc 100644 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_OdePhysicsController.cpp @@ -133,8 +133,9 @@ void KX_OdePhysicsController::SetLinearVelocity(const MT_Vector3& lin_vel,bool l ODEPhysicsController::SetLinearVelocity(lin_vel[0],lin_vel[1],lin_vel[2],local); } -void KX_OdePhysicsController::setOrientation(const MT_Quaternion& orn) +void KX_OdePhysicsController::setOrientation(const MT_Matrix3x3& rot) { + MT_Quaternion orn = rot.getRotation(); ODEPhysicsController::setOrientation(orn[0],orn[1],orn[2],orn[3]); } @@ -177,7 +178,7 @@ void KX_OdePhysicsController::setRigidBody(bool rigid) } -void KX_OdePhysicsController::SuspendDynamics() +void KX_OdePhysicsController::SuspendDynamics(bool) { ODEPhysicsController::SuspendDynamics(); } diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.h b/source/gameengine/Ketsji/KX_OdePhysicsController.h index 07a0bee9775..18f9edc6835 100644 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.h +++ b/source/gameengine/Ketsji/KX_OdePhysicsController.h @@ -67,14 +67,14 @@ public: virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local); virtual void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); virtual void getOrientation(MT_Quaternion& orn); - virtual void setOrientation(const MT_Quaternion& orn); + virtual void setOrientation(const MT_Matrix3x3& orn); virtual void setPosition(const MT_Point3& pos); virtual void setScaling(const MT_Vector3& scaling); virtual MT_Scalar GetMass(); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); - virtual void SuspendDynamics(); + virtual void SuspendDynamics(bool); virtual void RestoreDynamics(); diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 8b379bcd44f..fd1b56838e2 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -46,19 +46,22 @@ KX_ParentActuator::KX_ParentActuator(SCA_IObject *gameobj, int mode, - CValue *ob, + SCA_IObject *ob, PyTypeObject* T) : SCA_IActuator(gameobj, T), m_mode(mode), m_ob(ob) { + if (m_ob) + m_ob->RegisterActuator(this); } KX_ParentActuator::~KX_ParentActuator() { - /* intentionally empty */ + if (m_ob) + m_ob->UnregisterActuator(this); } @@ -73,6 +76,36 @@ CValue* KX_ParentActuator::GetReplica() return replica; } +void KX_ParentActuator::ProcessReplica() +{ + if (m_ob) + m_ob->RegisterActuator(this); + SCA_IActuator::ProcessReplica(); +} + + +bool KX_ParentActuator::UnlinkObject(SCA_IObject* clientobj) +{ + if (clientobj == m_ob) + { + // this object is being deleted, we cannot continue to track it. + m_ob = NULL; + return true; + } + return false; +} + +void KX_ParentActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_ob]; + if (h_obj) { + if (m_ob) + m_ob->UnregisterActuator(this); + m_ob = (SCA_IObject*)(*h_obj); + m_ob->RegisterActuator(this); + } +} + bool KX_ParentActuator::Update() @@ -87,7 +120,8 @@ bool KX_ParentActuator::Update() KX_Scene *scene = PHY_GetActiveScene(); switch (m_mode) { case KX_PARENT_SET: - obj->SetParent(scene, (KX_GameObject*)m_ob); + if (m_ob) + obj->SetParent(scene, (KX_GameObject*)m_ob); break; case KX_PARENT_REMOVE: obj->RemoveParent(scene); @@ -148,7 +182,11 @@ PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* args, PyObjec PyObject* gameobj; if (PyArg_ParseTuple(args, "O!", &KX_GameObject::Type, &gameobj)) { - m_ob = (CValue*)gameobj; + if (m_ob != NULL) + m_ob->UnregisterActuator(this); + m_ob = (SCA_IObject*)gameobj; + if (m_ob) + m_ob->RegisterActuator(this); Py_Return; } PyErr_Clear(); @@ -156,10 +194,13 @@ PyObject* KX_ParentActuator::PySetObject(PyObject* self, PyObject* args, PyObjec char* objectname; if (PyArg_ParseTuple(args, "s", &objectname)) { - CValue *object = (CValue*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname)); + SCA_IObject *object = (SCA_IObject*)SCA_ILogicBrick::m_sCurrentLogicManager->GetGameObjectByName(STR_String(objectname)); if(object) { + if (m_ob != NULL) + m_ob->UnregisterActuator(this); m_ob = object; + m_ob->RegisterActuator(this); Py_Return; } } diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index 86dcd4e6c12..93b07cd424b 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -47,7 +47,7 @@ class KX_ParentActuator : public SCA_IActuator int m_mode; /** Object to set as parent */ - CValue *m_ob; + SCA_IObject *m_ob; @@ -62,12 +62,15 @@ class KX_ParentActuator : public SCA_IActuator KX_ParentActuator(class SCA_IObject* gameobj, int mode, - CValue *ob, + SCA_IObject *ob, PyTypeObject* T=&Type); virtual ~KX_ParentActuator(); virtual bool Update(); virtual CValue* GetReplica(); + virtual void ProcessReplica(); + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); + virtual bool UnlinkObject(SCA_IObject* clientobj); /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 93d6d5bb70d..144f74a1a4c 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -59,7 +59,8 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, @@ -74,7 +75,8 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, tilexrep, tileyrep, mode, - transparant, + transp, + alpha, zsort, lightlayer, bIsTriangle, @@ -245,7 +247,7 @@ PyObject* KX_PolygonMaterial::_getattr(const STR_String& attr) if (attr == "drawingmode") return PyInt_FromLong(m_drawingmode); if (attr == "transparent") - return PyInt_FromLong(m_transparant); + return PyInt_FromLong(m_alpha); if (attr == "zsort") return PyInt_FromLong(m_zsort); if (attr == "lightlayer") @@ -312,7 +314,7 @@ int KX_PolygonMaterial::_setattr(const STR_String &attr, PyObject *pyvalue) if (attr == "transparent") { - m_transparant = value; + m_alpha = value; return 0; } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 19015494e06..11c8baa8b1f 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -64,7 +64,8 @@ public: int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index e1715c9275f..4e383e9b3d4 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -84,7 +84,10 @@ bool PyMatTo(PyObject* pymat, T& mat) } } else noerror = false; - + + if (noerror==false) + PyErr_SetString(PyExc_TypeError, "could not be converted to a matrix (sequence of sequences)"); + return noerror; } @@ -97,9 +100,13 @@ bool PyVecTo(PyObject* pyval, T& vec) if (PySequence_Check(pyval)) { unsigned int numitems = PySequence_Size(pyval); - if (numitems != Size(vec)) + if (numitems != Size(vec)) { + char err[128]; + sprintf(err, "error setting vector, %d args, should be %d", numitems, Size(vec)); + PyErr_SetString(PyExc_AttributeError, err); return false; - + } + for (unsigned int x = 0; x < numitems; x++) { PyObject *item = PySequence_GetItem(pyval, x); /* new ref */ @@ -107,7 +114,17 @@ bool PyVecTo(PyObject* pyval, T& vec) Py_DECREF(item); } + if (PyErr_Occurred()) { + PyErr_SetString(PyExc_AttributeError, "one or more of the items in the sequence was not a float"); + return false; + } + return true; + } else + { + char err[128]; + sprintf(err, "not a sequence type, expected a sequence of numbers size %d", Size(vec)); + PyErr_SetString(PyExc_AttributeError, err); } return false; diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 61ed8b6a8e4..b66c3e42606 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -756,6 +756,15 @@ PyObject* initGameLogic(KX_Scene* scene) // quick hack to get gravity hook KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ROTX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTX); KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ROTY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTY); KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ROTZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ROTZ); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRPX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRPX); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRPY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRPY); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRPY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRPY); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRNX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNX); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRNY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNY); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_DIRNY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DIRNY); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIX, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIX); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIY, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIY); + KX_MACRO_addTypesToDict(d, KX_CONSTRAINTACT_ORIZ, KX_ConstraintActuator::KX_ACT_CONSTRAINT_ORIZ); /* 4. Ipo actuator, simple part */ KX_MACRO_addTypesToDict(d, KX_IPOACT_PLAY, KX_IpoActuator::KX_ACT_IPO_PLAY); diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 987e0b946b2..de4979ac4c9 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -80,10 +80,7 @@ CValue* KX_RadarSensor::GetReplica() { KX_RadarSensor* replica = new KX_RadarSensor(*this); replica->m_colliders = new CListValue(); - replica->m_bCollision = false; - replica->m_bTriggered= false; - replica->m_hitObject = NULL; - replica->m_bLastTriggered = false; + replica->Init(); // this will copy properties and so on... CValue::AddDataToReplica(replica); @@ -92,6 +89,10 @@ CValue* KX_RadarSensor::GetReplica() if (replica->m_physCtrl) { replica->m_physCtrl = replica->m_physCtrl->GetReplica(); + if (replica->m_physCtrl) + { + replica->m_physCtrl->setNewClientInfo(replica->m_client_info); + } } //todo: make sure replication works fine! @@ -175,8 +176,10 @@ void KX_RadarSensor::SynchronizeTransform() if (m_physCtrl) { - m_physCtrl->setPosition(trans.getOrigin().x(),trans.getOrigin().y(),trans.getOrigin().z()); - m_physCtrl->setOrientation(trans.getRotation().x(),trans.getRotation().y(),trans.getRotation().z(),trans.getRotation().w()); + MT_Quaternion orn = trans.getRotation(); + MT_Point3 pos = trans.getOrigin(); + m_physCtrl->setPosition(pos[0],pos[1],pos[2]); + m_physCtrl->setOrientation(orn[0],orn[1],orn[2],orn[3]); m_physCtrl->calcXform(); } diff --git a/source/gameengine/Ketsji/KX_RayEventManager.cpp b/source/gameengine/Ketsji/KX_RayEventManager.cpp index 4101c6b547e..1af29151adf 100644 --- a/source/gameengine/Ketsji/KX_RayEventManager.cpp +++ b/source/gameengine/Ketsji/KX_RayEventManager.cpp @@ -44,14 +44,9 @@ using namespace std; void KX_RayEventManager::NextFrame() { - for (vector<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) { - SCA_ISensor *sensor = *i; - sensor->Activate(m_logicmgr, NULL); + (*i)->Activate(m_logicmgr, NULL); } } -void KX_RayEventManager::RegisterSensor(SCA_ISensor* sensor) -{ - m_sensors.push_back(sensor); -}; diff --git a/source/gameengine/Ketsji/KX_RayEventManager.h b/source/gameengine/Ketsji/KX_RayEventManager.h index 3630f9682b9..b816d4d5250 100644 --- a/source/gameengine/Ketsji/KX_RayEventManager.h +++ b/source/gameengine/Ketsji/KX_RayEventManager.h @@ -45,7 +45,6 @@ public: m_logicmgr(logicmgr) {} virtual void NextFrame(); - virtual void RegisterSensor(SCA_ISensor* sensor); }; #endif //__KX_RAYEVENTMGR diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index e5ee4cbddf1..e36891b56f4 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -137,6 +137,17 @@ bool KX_SCA_AddObjectActuator::UnlinkObject(SCA_IObject* clientobj) return false; } +void KX_SCA_AddObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_OriginalObject]; + if (h_obj) { + if (m_OriginalObject) + m_OriginalObject->UnregisterActuator(this); + m_OriginalObject = (SCA_IObject*)(*h_obj); + m_OriginalObject->RegisterActuator(this); + } +} + /* ------------------------------------------------------------------------- */ /* Python functions */ diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index 42123b94a68..1359f39278d 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -95,6 +95,9 @@ public: virtual bool UnlinkObject(SCA_IObject* clientobj); + virtual void + Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); + virtual bool Update(); diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 065800379d8..2828663c63d 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -37,6 +37,7 @@ #include "MT_assert.h" #include "KX_KetsjiEngine.h" +#include "KX_BlenderMaterial.h" #include "RAS_IPolygonMaterial.h" #include "ListValue.h" #include "SCA_LogicManager.h" @@ -66,6 +67,8 @@ #include "SG_Controller.h" #include "SG_IObject.h" #include "SG_Tree.h" +#include "DNA_group_types.h" +#include "BKE_anim.h" #include "KX_SG_NodeRelationships.h" @@ -90,6 +93,9 @@ void* KX_SceneReplicationFunc(SG_IObject* node,void* gameobj,void* scene) { KX_GameObject* replica = ((KX_Scene*)scene)->AddNodeReplicaObject(node,(KX_GameObject*)gameobj); + if(replica) + replica->Release(); + return (void*)replica; } @@ -114,13 +120,13 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, PyObjectPlus(&KX_Scene::Type), m_keyboardmgr(NULL), m_mousemgr(NULL), + m_sceneConverter(NULL), m_physicsEnvironment(0), m_sceneName(sceneName), m_adi(adi), m_networkDeviceInterface(ndi), m_active_camera(NULL), - m_ueberExecutionPriority(0), - m_sceneConverter(NULL) + m_ueberExecutionPriority(0) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -429,6 +435,11 @@ void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gam KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CValue* gameobj) { + // for group duplication, limit the duplication of the hierarchy to the + // objects that are part of the group. + if (!IsObjectInGroup(gameobj)) + return NULL; + KX_GameObject* orgobj = (KX_GameObject*)gameobj; KX_GameObject* newobj = (KX_GameObject*)orgobj->GetReplica(); m_map_gameobject_to_replica.insert(orgobj, newobj); @@ -506,6 +517,11 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal // hierarchy that's because first ALL bricks must exist in the new // replica of the hierarchy in order to make cross-links work properly // ! +// It is VERY important that the order of sensors and actuators in +// the replicated object is preserved: it is is used to reconnect the logic. +// This method is more robust then using the bricks name in case of complex +// group replication. The replication of logic bricks is done in +// SCA_IObject::ReParentLogic(), make sure it preserves the order of the bricks. void KX_Scene::ReplicateLogic(KX_GameObject* newobj) { // also relink the controller to sensors/actuators @@ -528,37 +544,38 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj) for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());its++) { SCA_ISensor* oldsensor = (*its); - STR_String name = oldsensor->GetName(); - //find this name in the list - SCA_ISensor* newsensor = newobj->FindSensor(name); + SCA_IObject* oldsensorobj = oldsensor->GetParent(); + SCA_IObject* newsensorobj = NULL; - if (newsensor) + // the original owner of the sensor has been replicated? + void **h_obj = m_map_gameobject_to_replica[oldsensorobj]; + if (h_obj) + newsensorobj = (SCA_IObject*)(*h_obj); + if (!newsensorobj) { - // relink this newsensor to the controller - m_logicmgr->RegisterToSensor(cont,newsensor); + // no, then the sensor points outside the hierachy, keep it the same + if (m_objectlist->SearchValue(oldsensorobj)) + // only replicate links that points to active objects + m_logicmgr->RegisterToSensor(cont,oldsensor); } else { - // it can be linked somewhere in the hierarchy or... - for (vector<KX_GameObject*>::iterator git = m_logicHierarchicalGameObjects.begin(); - !(git==m_logicHierarchicalGameObjects.end());++git) - { - newsensor = (*git)->FindSensor(name); - if (newsensor) - break; - } + // yes, then the new sensor has the same position + SCA_SensorList& sensorlist = oldsensorobj->GetSensors(); + SCA_SensorList::iterator sit; + SCA_ISensor* newsensor = NULL; + int sensorpos; - if (newsensor) + for (sensorpos=0, sit=sensorlist.begin(); sit!=sensorlist.end(); sit++, sensorpos++) { - // relink this newsensor to the controller somewhere else within this - // hierarchy - m_logicmgr->RegisterToSensor(cont,newsensor); - } - else - { - // must be an external sensor, so... - m_logicmgr->RegisterToSensor(cont,oldsensor); + if ((*sit) == oldsensor) + { + newsensor = newsensorobj->GetSensors().at(sensorpos); + break; + } } + assert(newsensor != NULL); + m_logicmgr->RegisterToSensor(cont,newsensor); } } @@ -566,38 +583,40 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj) for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());ita++) { SCA_IActuator* oldactuator = (*ita); - STR_String name = oldactuator->GetName(); - //find this name in the list - SCA_IActuator* newactuator = newobj->FindActuator(name); - if (newactuator) + SCA_IObject* oldactuatorobj = oldactuator->GetParent(); + SCA_IObject* newactuatorobj = NULL; + + // the original owner of the sensor has been replicated? + void **h_obj = m_map_gameobject_to_replica[oldactuatorobj]; + if (h_obj) + newactuatorobj = (SCA_IObject*)(*h_obj); + + if (!newactuatorobj) { - // relink this newsensor to the controller - m_logicmgr->RegisterToActuator(cont,newactuator); - newactuator->SetUeberExecutePriority(m_ueberExecutionPriority); + // no, then the sensor points outside the hierachy, keep it the same + if (m_objectlist->SearchValue(oldactuatorobj)) + // only replicate links that points to active objects + m_logicmgr->RegisterToActuator(cont,oldactuator); } else { - // it can be linked somewhere in the hierarchy or... - for (vector<KX_GameObject*>::iterator git = m_logicHierarchicalGameObjects.begin(); - !(git==m_logicHierarchicalGameObjects.end());++git) - { - newactuator= (*git)->FindActuator(name); - if (newactuator) - break; - } + // yes, then the new sensor has the same position + SCA_ActuatorList& actuatorlist = oldactuatorobj->GetActuators(); + SCA_ActuatorList::iterator ait; + SCA_IActuator* newactuator = NULL; + int actuatorpos; - if (newactuator) - { - // relink this actuator to the controller somewhere else within this - // hierarchy - m_logicmgr->RegisterToActuator(cont,newactuator); - newactuator->SetUeberExecutePriority(m_ueberExecutionPriority); - } - else + for (actuatorpos=0, ait=actuatorlist.begin(); ait!=actuatorlist.end(); ait++, actuatorpos++) { - // must be an external actuator, so... - m_logicmgr->RegisterToActuator(cont,oldactuator); + if ((*ait) == oldactuator) + { + newactuator = newactuatorobj->GetActuators().at(actuatorpos); + break; + } } + assert(newactuator != NULL); + m_logicmgr->RegisterToActuator(cont,newactuator); + newactuator->SetUeberExecutePriority(m_ueberExecutionPriority); } } } @@ -605,6 +624,154 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj) newobj->ResetState(); } +void KX_Scene::DupliGroupRecurse(CValue* obj, int level) +{ + KX_GameObject* groupobj = (KX_GameObject*) obj; + KX_GameObject* replica; + KX_GameObject* gameobj; + Object* blgroupobj = groupobj->GetBlenderObject(); + Group* group; + GroupObject *go; + vector<KX_GameObject*> duplilist; + + if (!groupobj->IsDupliGroup() || + level>MAX_DUPLI_RECUR) + return; + + // we will add one group at a time + m_logicHierarchicalGameObjects.clear(); + m_map_gameobject_to_replica.clear(); + m_ueberExecutionPriority++; + // for groups will do something special: + // we will force the creation of objects to those in the group only + // Again, this is match what Blender is doing (it doesn't care of parent relationship) + m_groupGameObjects.clear(); + + group = blgroupobj->dup_group; + for(go=(GroupObject*)group->gobject.first; go; go=(GroupObject*)go->next) + { + Object* blenderobj = go->ob; + if (blgroupobj == blenderobj) + // this check is also in group_duplilist() + continue; + gameobj = (KX_GameObject*)m_logicmgr->FindGameObjByBlendObj(blenderobj); + if (gameobj == NULL) + { + // this object has not been converted!!! + // Should not happen as dupli group are created automatically + continue; + } + if ((blenderobj->lay & group->layer)==0) + { + // object is not visible in the 3D view, will not be instantiated + continue; + } + m_groupGameObjects.insert(gameobj); + } + + set<CValue*>::iterator oit; + for (oit=m_groupGameObjects.begin(); oit != m_groupGameObjects.end(); oit++) + { + gameobj = (KX_GameObject*)(*oit); + + KX_GameObject *parent = gameobj->GetParent(); + if (parent != NULL) + { + parent->Release(); // GetParent() increased the refcount + + // this object is not a top parent. Either it is the child of another + // object in the group and it will be added automatically when the parent + // is added. Or it is the child of an object outside the group and the group + // is inconsistent, skip it anyway + continue; + } + replica = (KX_GameObject*) AddNodeReplicaObject(NULL,gameobj); + // add to 'rootparent' list (this is the list of top hierarchy objects, updated each frame) + m_parentlist->Add(replica->AddRef()); + + // recurse replication into children nodes + NodeList& children = gameobj->GetSGNode()->GetSGChildren(); + + replica->GetSGNode()->ClearSGChildren(); + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* orgnode = (*childit); + SG_Node* childreplicanode = orgnode->GetSGReplica(); + if (childreplicanode) + replica->GetSGNode()->AddChild(childreplicanode); + } + // don't replicate logic now: we assume that the objects in the group can have + // logic relationship, even outside parent relationship + // In order to match 3D view, the position of groupobj is used as a + // transformation matrix instead of the new position. This means that + // the group reference point is 0,0,0 + + // get the rootnode's scale + MT_Vector3 newscale = groupobj->NodeGetWorldScaling(); + // set the replica's relative scale with the rootnode's scale + replica->NodeSetRelativeScale(newscale); + + MT_Matrix3x3 newori = groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldOrientation(); + replica->NodeSetLocalOrientation(newori); + + MT_Point3 newpos = groupobj->NodeGetWorldPosition() + + newscale*(groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldPosition()); + replica->NodeSetLocalPosition(newpos); + + if (replica->GetPhysicsController()) + { + // not required, already done in NodeSetLocalOrientation.. + //replica->GetPhysicsController()->setPosition(newpos); + //replica->GetPhysicsController()->setOrientation(newori.getRotation()); + // Scaling has been set relatively hereabove, this does not + // set the scaling of the controller. I don't know why it's just the + // relative scale and not the full scale that has to be put here... + replica->GetPhysicsController()->setScaling(newscale); + } + + replica->GetSGNode()->UpdateWorldData(0); + replica->GetSGNode()->SetBBox(gameobj->GetSGNode()->BBox()); + replica->GetSGNode()->SetRadius(gameobj->GetSGNode()->Radius()); + // done with replica + replica->Release(); + } + + // 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) + { + // this will also relink the actuator to objects within the hierarchy + (*git)->Relink(&m_map_gameobject_to_replica); + // add the object in the layer of the parent + (*git)->SetLayer(groupobj->GetLayer()); + } + + // replicate crosslinks etc. between logic bricks + for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) + { + ReplicateLogic((*git)); + } + + // 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()) + // can't instantiate group immediately as it destroys m_logicHierarchicalGameObjects + duplilist.push_back((*git)); + } + + for (git = duplilist.begin(); !(git == duplilist.end()); ++git) + { + DupliGroupRecurse((*git), level+1); + } +} SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, @@ -614,6 +781,7 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, m_logicHierarchicalGameObjects.clear(); m_map_gameobject_to_replica.clear(); + m_groupGameObjects.clear(); // todo: place a timebomb in the object, for temporarily objects :) // lifespan of zero means 'this object lives forever' @@ -647,24 +815,26 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, { SG_Node* orgnode = (*childit); SG_Node* childreplicanode = orgnode->GetSGReplica(); - replica->GetSGNode()->AddChild(childreplicanode); + if (childreplicanode) + replica->GetSGNode()->AddChild(childreplicanode); } - // relink any pointers as necessary, sort of a temporary solution + // now replicate logic 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) + { + // 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()); } - // now replicate logic - for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) - { - (*git)->ReParentLogic(); - } - // replicate crosslinks etc. between logic bricks for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) { @@ -685,8 +855,9 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, if (replica->GetPhysicsController()) { - replica->GetPhysicsController()->setPosition(newpos); - replica->GetPhysicsController()->setOrientation(newori.getRotation()); + // not needed, already done in NodeSetLocalPosition() + //replica->GetPhysicsController()->setPosition(newpos); + //replica->GetPhysicsController()->setOrientation(newori.getRotation()); replica->GetPhysicsController()->setScaling(newscale); } @@ -697,6 +868,20 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, replica->GetSGNode()->UpdateWorldData(0); replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox()); replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius()); + // check if there are objects with dupligroup in the hierarchy + vector<KX_GameObject*> duplilist; + for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) + { + if ((*git)->IsDupliGroup()) + { + // separate list as m_logicHierarchicalGameObjects is also used by DupliGroupRecurse() + duplilist.push_back(*git); + } + } + for (git = duplilist.begin();!(git==duplilist.end());++git) + { + DupliGroupRecurse(*git, 0); + } // don't release replica here because we are returning it, not done with it... return replica; } @@ -743,6 +928,12 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) int ret; KX_GameObject* newobj = (KX_GameObject*) gameobj; + // keep the blender->game object association up to date + // note that all the replicas of an object will have the same + // blender object, that's why we need to check the game object + // as only the deletion of the original object must be recorded + m_logicmgr->UnregisterGameObj(newobj->GetBlenderObject(), gameobj); + //todo: look at this //GetPhysicsEnvironment()->RemovePhysicsController(gameobj->getPhysicsController()); @@ -801,6 +992,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) //m_active_camera->Release(); m_active_camera = NULL; } + // in case this is a camera m_cameras.remove((KX_Camera*)newobj); @@ -1057,14 +1249,10 @@ void KX_Scene::MarkSubTreeVisible(SG_Tree *node, RAS_IRasterizer* rasty, bool vi if (visible) { int nummeshes = gameobj->GetMeshCount(); - MT_Transform t( cam->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform()); - + // this adds the vertices to the display list for (int m=0;m<nummeshes;m++) - { - // this adds the vertices to the display list - (gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode()); - } + (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode()); } gameobj->MarkVisible(visible); } @@ -1121,12 +1309,11 @@ void KX_Scene::MarkVisible(RAS_IRasterizer* rasty, KX_GameObject* gameobj,KX_Cam if (vis) { int nummeshes = gameobj->GetMeshCount(); - MT_Transform t(cam->GetWorldToCamera() * gameobj->GetSGNode()->GetWorldTransform()); for (int m=0;m<nummeshes;m++) { // this adds the vertices to the display list - (gameobj->GetMesh(m))->SchedulePolygons(t, rasty->GetDrawingMode()); + (gameobj->GetMesh(m))->SchedulePolygons(rasty->GetDrawingMode()); } // Visibility/ non-visibility are marked // elsewhere now. @@ -1239,7 +1426,7 @@ void KX_Scene::UpdateParents(double curtime) RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat, bool &bucketCreated) { - return m_bucketmanager->RAS_BucketManagerFindBucket(polymat, bucketCreated); + return m_bucketmanager->FindBucket(polymat, bucketCreated); } @@ -1249,10 +1436,9 @@ void KX_Scene::RenderBuckets(const MT_Transform & cameratransform, class RAS_IRenderTools* rendertools) { m_bucketmanager->Renderbuckets(cameratransform,rasty,rendertools); + KX_BlenderMaterial::EndFrame(); } - - void KX_Scene::UpdateObjectActivity(void) { if (m_activity_culling) { diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 28dee1b5893..80a2abe287a 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -216,6 +216,16 @@ protected: */ std::vector<KX_GameObject*> m_logicHierarchicalGameObjects; + /** + * This temporary variable will contain the list of + * object that can be added during group instantiation. + * objects outside this list will not be added (can + * happen with children that are outside the group). + * Used in AddReplicaObject. If the list is empty, it + * means don't care. + */ + std::set<CValue*> m_groupGameObjects; + /** * Pointer to system variable passed in in constructor * only used in constructor so we do not need to keep it @@ -291,6 +301,12 @@ public: * Update all transforms according to the scenegraph. */ void UpdateParents(double curtime); + void DupliGroupRecurse(CValue* gameobj, int level); + bool IsObjectInGroup(CValue* gameobj) + { + return (m_groupGameObjects.empty() || + m_groupGameObjects.find(gameobj) != m_groupGameObjects.end()); + } SCA_IObject* AddReplicaObject(CValue* gameobj, CValue* locationobj, int lifespan=0); diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index 8f7cffd506f..d6164dc812a 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -58,13 +58,16 @@ KX_SceneActuator::KX_SceneActuator(SCA_IObject *gameobj, m_KetsjiEngine=ketsjiEngine; m_camera = camera; m_nextSceneName = nextSceneName; + if (m_camera) + m_camera->RegisterActuator(this); } /* End of constructor */ KX_SceneActuator::~KX_SceneActuator() { - // there's nothing to be done here, really.... + if (m_camera) + m_camera->UnregisterActuator(this); } /* end of destructor */ @@ -79,6 +82,34 @@ CValue* KX_SceneActuator::GetReplica() return replica; } +void KX_SceneActuator::ProcessReplica() +{ + if (m_camera) + m_camera->RegisterActuator(this); + SCA_IActuator::ProcessReplica(); +} + +bool KX_SceneActuator::UnlinkObject(SCA_IObject* clientobj) +{ + if (clientobj == (SCA_IObject*)m_camera) + { + // this object is being deleted, we cannot continue to track it. + m_camera = NULL; + return true; + } + return false; +} + +void KX_SceneActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_camera]; + if (h_obj) { + if (m_camera) + m_camera->UnregisterActuator(this); + m_camera = (KX_Camera*)(*h_obj); + m_camera->RegisterActuator(this); + } +} bool KX_SceneActuator::Update() @@ -332,7 +363,11 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self, PyObject *cam; if (PyArg_ParseTuple(args, "O!", &KX_Camera::Type, &cam)) { + if (m_camera) + m_camera->UnregisterActuator(this); m_camera = (KX_Camera*) cam; + if (m_camera) + m_camera->RegisterActuator(this); Py_Return; } PyErr_Clear(); @@ -345,7 +380,13 @@ PyObject* KX_SceneActuator::PySetCamera(PyObject* self, } KX_Camera *camOb = FindCamera(camName); - if (camOb) m_camera = camOb; + if (camOb) + { + if (m_camera) + m_camera->UnregisterActuator(this); + m_camera = camOb; + m_camera->RegisterActuator(this); + } Py_Return; } diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h index cfc79b93f8e..55aaf629d7c 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.h +++ b/source/gameengine/Ketsji/KX_SceneActuator.h @@ -82,6 +82,9 @@ class KX_SceneActuator : public SCA_IActuator virtual ~KX_SceneActuator(); virtual CValue* GetReplica(); + virtual void ProcessReplica(); + virtual bool UnlinkObject(SCA_IObject* clientobj); + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); virtual bool Update(); diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp index 6ea5461dbaa..4032a795ce3 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.cpp @@ -101,7 +101,7 @@ void KX_SumoPhysicsController::SetSumoTransform(bool nondynaonly) } -void KX_SumoPhysicsController::SuspendDynamics() +void KX_SumoPhysicsController::SuspendDynamics(bool) { SumoPhysicsController::SuspendDynamics(); } @@ -170,8 +170,9 @@ void KX_SumoPhysicsController::setMargin(float collisionMargin) } -void KX_SumoPhysicsController::setOrientation(const MT_Quaternion& orn) +void KX_SumoPhysicsController::setOrientation(const MT_Matrix3x3& rot) { + MT_Quaternion orn = rot.getRotation(); SumoPhysicsController::setOrientation( orn[0],orn[1],orn[2],orn[3]); diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h index 8c061ae4056..1dd930bf3d9 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h @@ -76,10 +76,10 @@ public: void resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); - void SuspendDynamics(); + void SuspendDynamics(bool); void RestoreDynamics(); virtual void getOrientation(MT_Quaternion& orn); - virtual void setOrientation(const MT_Quaternion& orn); + virtual void setOrientation(const MT_Matrix3x3& orn); virtual void setPosition(const MT_Point3& pos); virtual void setScaling(const MT_Vector3& scaling); diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp index 423543eef5c..7528fdbbc34 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp +++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp @@ -100,16 +100,24 @@ bool KX_TouchEventManager::newBroadphaseResponse(void *client_data, void KX_TouchEventManager::RegisterSensor(SCA_ISensor* sensor) { KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(sensor); - m_sensors.push_back(touchsensor); + m_sensors.insert(touchsensor); touchsensor->RegisterSumo(this); } +void KX_TouchEventManager::RemoveSensor(SCA_ISensor* sensor) +{ + KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(sensor); + m_sensors.erase(touchsensor); + + touchsensor->UnregisterSumo(this); +} + void KX_TouchEventManager::EndFrame() { - vector<SCA_ISensor*>::iterator it; + set<SCA_ISensor*>::iterator it; for ( it = m_sensors.begin(); !(it==m_sensors.end());it++) { @@ -124,7 +132,7 @@ void KX_TouchEventManager::NextFrame() { if (m_sensors.size() > 0) { - vector<SCA_ISensor*>::iterator it; + set<SCA_ISensor*>::iterator it; for (it = m_sensors.begin();!(it==m_sensors.end());++it) static_cast<KX_TouchSensor*>(*it)->SynchronizeTransform(); @@ -157,20 +165,3 @@ void KX_TouchEventManager::NextFrame() (*it)->Activate(m_logicmgr,NULL); } } - - - -void KX_TouchEventManager::RemoveSensor(class SCA_ISensor* sensor) -{ - std::vector<SCA_ISensor*>::iterator i = - std::find(m_sensors.begin(), m_sensors.end(), sensor); - if (!(i == m_sensors.end())) - { - std::swap(*i, m_sensors.back()); - m_sensors.pop_back(); - } - - // remove the sensor forever :) - SCA_EventManager::RemoveSensor(sensor); -} - diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.h b/source/gameengine/Ketsji/KX_TouchEventManager.h index 20ed6126bd0..cc77bccfc31 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.h +++ b/source/gameengine/Ketsji/KX_TouchEventManager.h @@ -71,8 +71,8 @@ public: PHY_IPhysicsEnvironment* physEnv); virtual void NextFrame(); virtual void EndFrame(); - virtual void RemoveSensor(class SCA_ISensor* sensor); virtual void RegisterSensor(SCA_ISensor* sensor); + virtual void RemoveSensor(SCA_ISensor* sensor); SCA_LogicManager* GetLogicManager() { return m_logicmgr;} PHY_IPhysicsEnvironment *GetPhysicsEnvironment() { return m_physEnv; } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index ce3aa1de2ef..60e1d87d318 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -153,6 +153,14 @@ void KX_TouchSensor::RegisterSumo(KX_TouchEventManager *touchman) } } +void KX_TouchSensor::UnregisterSumo(KX_TouchEventManager* touchman) +{ + if (m_physCtrl) + { + touchman->GetPhysicsEnvironment()->removeCollisionCallback(m_physCtrl); + } +} + bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_CollData* colldata) { // KX_TouchEventManager* toucheventmgr = (KX_TouchEventManager*)m_eventmgr; diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index 056440ccd6c..b611d296939 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -76,6 +76,7 @@ public: virtual void ReParent(SCA_IObject* parent); virtual void RegisterSumo(KX_TouchEventManager* touchman); + virtual void UnregisterSumo(KX_TouchEventManager* touchman); // virtual DT_Bool HandleCollision(void* obj1,void* obj2, // const DT_CollData * coll_data); diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 731a610c2eb..f5b463abf02 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -146,19 +146,19 @@ void compatible_eulFast(float *eul, float *oldrot) { float dx, dy, dz; - /* verschillen van ong 360 graden corrigeren */ + /* angular difference of 360 degrees */ dx= eul[0] - oldrot[0]; dy= eul[1] - oldrot[1]; dz= eul[2] - oldrot[2]; - if( fabs(dx) > 5.1) { + if( fabs(dx) > MT_PI) { if(dx > 0.0) eul[0] -= MT_2_PI; else eul[0]+= MT_2_PI; } - if( fabs(dy) > 5.1) { + if( fabs(dy) > MT_PI) { if(dy > 0.0) eul[1] -= MT_2_PI; else eul[1]+= MT_2_PI; } - if( fabs(dz) > 5.1 ) { + if( fabs(dz) > MT_PI ) { if(dz > 0.0) eul[2] -= MT_2_PI; else eul[2]+= MT_2_PI; } } @@ -195,6 +195,8 @@ void KX_TrackToActuator::ProcessReplica() // the replica is tracking the same object => register it if (m_object) m_object->RegisterActuator(this); + if (m_parentobj) + m_parentobj->AddRef(); SCA_IActuator::ProcessReplica(); } @@ -210,6 +212,26 @@ bool KX_TrackToActuator::UnlinkObject(SCA_IObject* clientobj) return false; } +void KX_TrackToActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_object]; + if (h_obj) { + if (m_object) + m_object->UnregisterActuator(this); + m_object = (SCA_IObject*)(*h_obj); + m_object->RegisterActuator(this); + } + + void **h_parobj = (*obj_map)[m_parentobj]; + if (h_parobj) { + if (m_parentobj) + m_parentobj->Release(); + m_parentobj= (KX_GameObject*)(*h_parobj); + m_parentobj->AddRef(); + } +} + + bool KX_TrackToActuator::Update(double curtime, bool frame) { bool result = false; diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h index a03aa115baa..1d1cf46d21b 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.h +++ b/source/gameengine/Ketsji/KX_TrackToActuator.h @@ -68,6 +68,7 @@ class KX_TrackToActuator : public SCA_IActuator virtual void ProcessReplica(); virtual bool UnlinkObject(SCA_IObject* clientobj); + virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); virtual bool Update(double curtime, bool frame); /* Python part */ diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h index ec1b7702ffd..7c61902f8e2 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h @@ -65,6 +65,7 @@ public: { } virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl) {} + virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl) {} virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;} virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight) { return 0;} diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index e444c4c73be..5c70b071661 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -337,12 +337,33 @@ void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float { m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } - - m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal); + // not required + //m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal); btTransform xform = m_body->getCenterOfMassTransform(); xform.setRotation(btQuaternion(quatImag0,quatImag1,quatImag2,quatReal)); m_body->setCenterOfMassTransform(xform); - m_bulletMotionState->setWorldTransform(xform); + // not required + //m_bulletMotionState->setWorldTransform(xform); + } + +} + +void CcdPhysicsController::setWorldOrientation(const btMatrix3x3& orn) +{ + if (m_body) + { + m_body->activate(true); + if (m_body->isStaticObject()) + { + m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + } + // not required + //m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal); + btTransform xform = m_body->getCenterOfMassTransform(); + xform.setBasis(orn); + m_body->setCenterOfMassTransform(xform); + // not required + //m_bulletMotionState->setWorldTransform(xform); } } @@ -356,12 +377,13 @@ void CcdPhysicsController::setPosition(float posX,float posY,float posZ) { m_body->setCollisionFlags(m_body->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } - - m_MotionState->setWorldPosition(posX,posY,posZ); + // not required, this function is only used to update the physic controller + //m_MotionState->setWorldPosition(posX,posY,posZ); btTransform xform = m_body->getCenterOfMassTransform(); xform.setOrigin(btVector3(posX,posY,posZ)); m_body->setCenterOfMassTransform(xform); - m_bulletMotionState->setWorldTransform(xform); + // not required + //m_bulletMotionState->setWorldTransform(xform); } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 37fa465351f..64f1876e199 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -106,6 +106,7 @@ class CcdPhysicsController : public PHY_IPhysicsController btRigidBody* m_body; class PHY_IMotionState* m_MotionState; btMotionState* m_bulletMotionState; + friend class CcdPhysicsEnvironment; // needed when updating the controller void* m_newClientInfo; @@ -115,6 +116,9 @@ class CcdPhysicsController : public PHY_IPhysicsController void CreateRigidbody(); + protected: + void setWorldOrientation(const btMatrix3x3& mat); + public: int m_collisionDelay; @@ -194,7 +198,6 @@ class CcdPhysicsController : public PHY_IPhysicsController return m_cci.m_collisionFilterMask; } - virtual void calcXform() {} ; virtual void SetMargin(float margin) {}; virtual float GetMargin() const {return 0.f;}; diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index c9d346e316d..ea14c5430e2 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -368,7 +368,7 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) body->setUserPointer(ctrl); body->setGravity( m_gravity ); - m_controllers.push_back(ctrl); + m_controllers.insert(ctrl); //use explicit group/filter for finer control over collision in bullet => near/radar sensor m_dynamicsWorld->addRigidBody(body, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); @@ -434,39 +434,47 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctrl) { - //also remove constraint - - m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); + m_controllers.erase(ctrl); + //remove it from the triggers + m_triggerControllers.erase(ctrl); +} - { - std::vector<CcdPhysicsController*>::iterator i = - std::find(m_controllers.begin(), m_controllers.end(), ctrl); - if (!(i == m_controllers.end())) - { - std::swap(*i, m_controllers.back()); - m_controllers.pop_back(); - } - } +void CcdPhysicsEnvironment::updateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask) +{ + // this function is used when the collisionning group of a controller is changed + // remove and add the collistioning object + btRigidBody* body = ctrl->GetRigidBody(); + btVector3 inertia; + + m_dynamicsWorld->removeCollisionObject(body); + body->setCollisionFlags(newCollisionFlags); + body->getCollisionShape()->calculateLocalInertia(newMass, inertia); + body->setMassProps(newMass, inertia); + m_dynamicsWorld->addCollisionObject(body, newCollisionGroup, newCollisionMask); + // to avoid nasty interaction, we must update the property of the controller as well + ctrl->m_cci.m_mass = newMass; + ctrl->m_cci.m_collisionFilterGroup = newCollisionGroup; + ctrl->m_cci.m_collisionFilterMask = newCollisionMask; + ctrl->m_cci.m_collisionFlags = newCollisionFlags; +} - //remove it from the triggers +void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctrl) +{ + if (m_controllers.insert(ctrl).second) { - std::vector<CcdPhysicsController*>::iterator i = - std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl); - if (!(i == m_triggerControllers.end())) - { - std::swap(*i, m_triggerControllers.back()); - m_triggerControllers.pop_back(); - } + btRigidBody* body = ctrl->GetRigidBody(); + body->setUserPointer(ctrl); + m_dynamicsWorld->addCollisionObject(body, + ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); } - - } + void CcdPhysicsEnvironment::beginFrame() { @@ -475,12 +483,12 @@ void CcdPhysicsEnvironment::beginFrame() bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) { + std::set<CcdPhysicsController*>::iterator it; + int i; - int i,numCtrl = GetNumControllers(); - for (i=0;i<numCtrl;i++) + for (it=m_controllers.begin(); it!=m_controllers.end(); it++) { - CcdPhysicsController* ctrl = GetPhysicsController(i); - ctrl->SynchronizeMotionStates(timeStep); + (*it)->SynchronizeMotionStates(timeStep); } float subStep = timeStep / float(m_numTimeSubSteps); @@ -489,11 +497,9 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) m_dynamicsWorld->stepSimulation(subStep,0);//perform always a full simulation step } - numCtrl = GetNumControllers(); - for (i=0;i<numCtrl;i++) + for (it=m_controllers.begin(); it!=m_controllers.end(); it++) { - CcdPhysicsController* ctrl = GetPhysicsController(i); - ctrl->SynchronizeMotionStates(timeStep); + (*it)->SynchronizeMotionStates(timeStep); } for (i=0;i<m_wrapperVehicles.size();i++) @@ -820,20 +826,6 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment() } -int CcdPhysicsEnvironment::GetNumControllers() -{ - return m_controllers.size(); -} - - -CcdPhysicsController* CcdPhysicsEnvironment::GetPhysicsController( int index) -{ - return m_controllers[index]; -} - - - - void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float value0,float value1) { btTypedConstraint* typedConstraint = getConstraintById(constraintId); @@ -873,12 +865,14 @@ void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) { CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl; - std::vector<CcdPhysicsController*>::iterator i = - std::find(m_controllers.begin(), m_controllers.end(), ctrl); - if ((i == m_controllers.end())) - { - addCcdPhysicsController(ctrl1); - } + // 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); + //Collision filter/mask is now set at the time of the creation of the controller //force collision detection with everything, including static objects (might hurt performance!) //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterMask = btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::SensorTrigger; @@ -891,21 +885,15 @@ void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) void CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) { - std::vector<CcdPhysicsController*>::iterator i = - std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl); - if (!(i == m_triggerControllers.end())) - { - std::swap(*i, m_triggerControllers.back()); - m_triggerControllers.pop_back(); - } + m_triggerControllers.erase((CcdPhysicsController*)ctrl); } void CcdPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl) { - removeCollisionCallback(ctrl); - //printf("removeSensor\n"); + removeCcdPhysicsController((CcdPhysicsController*)ctrl); } + void CcdPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) { /* printf("addTouchCallback\n(response class = %i)\n",response_class); @@ -943,10 +931,9 @@ void CcdPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctr CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl); //printf("requestCollisionCallback\n"); - m_triggerControllers.push_back(ccdCtrl); + m_triggerControllers.insert(ccdCtrl); } - void CcdPhysicsEnvironment::CallbackTriggers() { @@ -979,11 +966,10 @@ void CcdPhysicsEnvironment::CallbackTriggers() CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer()); CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(obj1->getUserPointer()); - std::vector<CcdPhysicsController*>::iterator i = - std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl0); + std::set<CcdPhysicsController*>::const_iterator i = m_triggerControllers.find(ctrl0); if (i == m_triggerControllers.end()) { - i = std::find(m_triggerControllers.begin(), m_triggerControllers.end(), ctrl1); + i = m_triggerControllers.find(ctrl1); } if (!(i == m_triggerControllers.end())) @@ -1093,7 +1079,6 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radi CcdPhysicsController* sphereController = new CcdPhysicsController(cinfo); - return sphereController; } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index 9f14cf6cbef..fd96522037e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -18,6 +18,7 @@ subject to the following restrictions: #include "PHY_IPhysicsEnvironment.h" #include <vector> +#include <set> class CcdPhysicsController; #include "LinearMath/btVector3.h" #include "LinearMath/btTransform.h" @@ -183,6 +184,15 @@ protected: void removeCcdPhysicsController(CcdPhysicsController* ctrl); + void updateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask); + + void disableCcdPhysicsController(CcdPhysicsController* ctrl) + { + removeCcdPhysicsController(ctrl); + } + + void enableCcdPhysicsController(CcdPhysicsController* ctrl); + btBroadphaseInterface* getBroadphase(); @@ -200,12 +210,6 @@ protected: } - int GetNumControllers(); - - CcdPhysicsController* GetPhysicsController( int index); - - - const btPersistentManifold* GetManifold(int index) const; @@ -220,9 +224,9 @@ protected: - std::vector<CcdPhysicsController*> m_controllers; + std::set<CcdPhysicsController*> m_controllers; - std::vector<CcdPhysicsController*> m_triggerControllers; + std::set<CcdPhysicsController*> m_triggerControllers; PHY_ResponseCallback m_triggerCallbacks[PHY_NUM_RESPONSE]; void* m_triggerCallbacksUserPtrs[PHY_NUM_RESPONSE]; diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index f0761618e4e..b5a61f72e4a 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -80,6 +80,7 @@ public: { } virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl) {} + virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl) {} virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;} virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight) { return 0;} diff --git a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp index b5bf67b14ea..f0791bbf89f 100644 --- a/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp +++ b/source/gameengine/Physics/Sumo/Fuzzics/src/SM_Scene.cpp @@ -98,12 +98,17 @@ void SM_Scene::addTouchCallback(int response_class, DT_ResponseCallback callback void SM_Scene::addSensor(SM_Object& object) { - object.calcXform(); - m_objectList.push_back(&object); - DT_AddObject(m_scene, object.getObjectHandle()); - DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[SENSOR_RESPONSE]); - DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass[SENSOR_RESPONSE]); - DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[SENSOR_RESPONSE]); + T_ObjectList::iterator i = + std::find(m_objectList.begin(), m_objectList.end(), &object); + if (i == m_objectList.end()) + { + object.calcXform(); + m_objectList.push_back(&object); + DT_AddObject(m_scene, object.getObjectHandle()); + DT_SetResponseClass(m_respTable, object.getObjectHandle(), m_ResponseClass[SENSOR_RESPONSE]); + DT_SetResponseClass(m_secondaryRespTable, object.getObjectHandle(), m_secondaryResponseClass [SENSOR_RESPONSE]); + DT_SetResponseClass(m_fixRespTable, object.getObjectHandle(), m_fixResponseClass[SENSOR_RESPONSE]); + } } void SM_Scene::add(SM_Object& object) { diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp index 16ba45a0be5..65018d2523e 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp @@ -228,6 +228,12 @@ void SumoPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ct m_sumoScene->requestCollisionCallback(*smObject); } } + +void SumoPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) +{ + // intentionally empty +} + PHY_IPhysicsController* SumoPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position) { DT_ShapeHandle shape = DT_NewSphere(0.0); diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h index ce5cd70e8cc..8b9fb463034 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h @@ -84,6 +84,7 @@ public: virtual void removeSensor(PHY_IPhysicsController* ctrl); virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user); virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl); + virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl); virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position); virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight); diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index c148210903f..5b275066665 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -104,6 +104,7 @@ class PHY_IPhysicsEnvironment virtual void removeSensor(PHY_IPhysicsController* ctrl)=0; virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user)=0; virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl)=0; + virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl)=0; //These two methods are *solely* used to create controllers for sensor! Don't use for anything else virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) =0; virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight)=0; diff --git a/source/gameengine/PyDoc/BL_ShapeActionActuator.py b/source/gameengine/PyDoc/BL_ShapeActionActuator.py new file mode 100644 index 00000000000..63cce253fa4 --- /dev/null +++ b/source/gameengine/PyDoc/BL_ShapeActionActuator.py @@ -0,0 +1,158 @@ +# $Id$ +# Documentation for BL_ShapeActionActuator +from SCA_IActuator import * + +class BL_ShapeActionActuator(SCA_IActuator): + """ + ShapeAction Actuators apply an shape action to an mesh object. + """ + def setAction(action, reset = True): + """ + Sets the current action. + + @param action: The name of the action to set as the current action. + @type action: string + @param reset: Optional parameter indicating whether to reset the + blend timer or not. A value of 1 indicates that the + timer should be reset. A value of 0 will leave it + unchanged. If reset is not specified, the timer will + be reset. + """ + + def setStart(start): + """ + Specifies the starting frame of the animation. + + @param start: the starting frame of the animation + @type start: float + """ + + def setEnd(end): + """ + Specifies the ending frame of the animation. + + @param end: the ending frame of the animation + @type end: float + """ + def setBlendin(blendin): + """ + Specifies the number of frames of animation to generate + when making transitions between actions. + + @param blendin: the number of frames in transition. + @type blendin: float + """ + + def setPriority(priority): + """ + Sets the priority of this actuator. + + @param priority: Specifies the new priority. Actuators will lower + priority numbers will override actuators with higher + numbers. + @type priority: integer + """ + def setFrame(frame): + """ + Sets the current frame for the animation. + + @param frame: Specifies the new current frame for the animation + @type frame: float + """ + + def setProperty(prop): + """ + Sets the property to be used in FromProp playback mode. + + @param prop: the name of the property to use. + @type prop: string. + """ + + def setBlendtime(blendtime): + """ + Sets the internal frame timer. + + Allows the script to directly modify the internal timer + used when generating transitions between actions. + + @param blendtime: The new time. This parameter must be in the range from 0.0 to 1.0. + @type blendtime: float + """ + + def setType(mode): + """ + Sets the operation mode of the actuator + + @param mode: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND + @type mode: integer + """ + + def setContinue(cont): + """ + Set the actions continue option True or False. see getContinue. + + @param cont: The continue option. + @type cont: bool + """ + + def getType(): + """ + Returns the operation mode of the actuator + + @rtype: integer + @return: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND + """ + + def getContinue(): + """ + When True, the action will always play from where last left off, otherwise negative events to this actuator will reset it to its start frame. + + @rtype: bool + """ + + def getAction(): + """ + getAction() returns the name of the action associated with this actuator. + + @rtype: string + """ + + def getStart(): + """ + Returns the starting frame of the action. + + @rtype: float + """ + def getEnd(): + """ + Returns the last frame of the action. + + @rtype: float + """ + def getBlendin(): + """ + Returns the number of interpolation animation frames to be generated when this actuator is triggered. + + @rtype: float + """ + def getPriority(): + """ + Returns the priority for this actuator. Actuators with lower Priority numbers will + override actuators with higher numbers. + + @rtype: integer + """ + def getFrame(): + """ + Returns the current frame number. + + @rtype: float + """ + def getProperty(): + """ + Returns the name of the property to be used in FromProp mode. + + @rtype: string + """ + + diff --git a/source/gameengine/PyDoc/KX_ActuatorSensor.py b/source/gameengine/PyDoc/KX_ActuatorSensor.py new file mode 100644 index 00000000000..f9aef86f7f0 --- /dev/null +++ b/source/gameengine/PyDoc/KX_ActuatorSensor.py @@ -0,0 +1,24 @@ +# $Id$ +# Documentation for KX_ActuatorSensor +from SCA_IActuator import * + +class KX_ActuatorSensor(SCA_ISensor): + """ + Actuator sensor detect change in actuator state of the parent object. + It generates a positive pulse if the corresponding actuator is activated + and a negative pulse if the actuator is deactivated. + """ + def getActuator(): + """ + Return the Actuator with which the sensor operates. + + @rtype: string + """ + def setActuator(name): + """ + Sets the Actuator with which to operate. If there is no Actuator + of this name, the function has no effect. + + @param name: actuator name + @type name: string + """ diff --git a/source/gameengine/PyDoc/KX_ConstraintActuator.py b/source/gameengine/PyDoc/KX_ConstraintActuator.py index 9630690e572..b1c6f3c0f4e 100644 --- a/source/gameengine/PyDoc/KX_ConstraintActuator.py +++ b/source/gameengine/PyDoc/KX_ConstraintActuator.py @@ -4,7 +4,7 @@ from SCA_IActuator import * class KX_ConstraintActuator(SCA_IActuator): """ - A constraint actuator limits the position or orientation of an object. + A constraint actuator limits the position, rotation, distance or orientation of an object. """ def setDamp(time): """ @@ -24,7 +24,7 @@ class KX_ConstraintActuator(SCA_IActuator): """ Sets the lower bound of the constraint. - For rotational constraints, lower is specified in degrees. + For rotational and orientation constraints, lower is specified in degrees. @type lower: float """ @@ -32,7 +32,7 @@ class KX_ConstraintActuator(SCA_IActuator): """ Gets the lower bound of the constraint. - For rotational constraints, the lower bound is returned in radians. + For rotational and orientation constraints, the lower bound is returned in radians. @rtype: float """ @@ -40,7 +40,7 @@ class KX_ConstraintActuator(SCA_IActuator): """ Sets the upper bound of the constraint. - For rotational constraints, upper is specified in degrees. + For rotational and orientation constraints, upper is specified in degrees. @type upper: float """ @@ -48,7 +48,7 @@ class KX_ConstraintActuator(SCA_IActuator): """ Gets the upper bound of the constraint. - For rotational constraints, the upper bound is returned in radians. + For rotational and orientation constraints, the upper bound is returned in radians. @rtype: float """ @@ -60,6 +60,9 @@ class KX_ConstraintActuator(SCA_IActuator): @param limit: Position constraints: KX_CONSTRAINTACT_LOCX, KX_CONSTRAINTACT_LOCY, KX_CONSTRAINTACT_LOCZ, Rotation constraints: KX_CONSTRAINTACT_ROTX, KX_CONSTRAINTACT_ROTY or KX_CONSTRAINTACT_ROTZ + Distance contraints: KX_ACT_CONSTRAINT_DIRPX, KX_ACT_CONSTRAINT_DIRPY, KX_ACT_CONSTRAINT_DIRPZ, + KX_ACT_CONSTRAINT_DIRNX, KX_ACT_CONSTRAINT_DIRNY, KX_ACT_CONSTRAINT_DIRNZ, + Orientation constraints: KX_ACT_CONSTRAINT_ORIX, KX_ACT_CONSTRAINT_ORIY, KX_ACT_CONSTRAINT_ORIZ """ def getLimit(): """ @@ -68,5 +71,110 @@ class KX_ConstraintActuator(SCA_IActuator): See module L{GameLogic} for valid constraints. @return: Position constraints: KX_CONSTRAINTACT_LOCX, KX_CONSTRAINTACT_LOCY, KX_CONSTRAINTACT_LOCZ, - Rotation constraints: KX_CONSTRAINTACT_ROTX, KX_CONSTRAINTACT_ROTY or KX_CONSTRAINTACT_ROTZ + Rotation constraints: KX_CONSTRAINTACT_ROTX, KX_CONSTRAINTACT_ROTY, KX_CONSTRAINTACT_ROTZ, + Distance contraints: KX_ACT_CONSTRAINT_DIRPX, KX_ACT_CONSTRAINT_DIRPY, KX_ACT_CONSTRAINT_DIRPZ, + KX_ACT_CONSTRAINT_DIRNX, KX_ACT_CONSTRAINT_DIRNY, KX_ACT_CONSTRAINT_DIRNZ, + Orientation constraints: KX_ACT_CONSTRAINT_ORIX, KX_ACT_CONSTRAINT_ORIY, KX_ACT_CONSTRAINT_ORIZ """ + def setRotDamp(duration): + """ + Sets the time constant of the orientation constraint. + + @param duration: If the duration is negative, it is set to 0. + @type duration: integer + """ + def getRotDamp(): + """ + Returns the damping time for application of the constraint. + + @rtype: integer + """ + def setDirection(vector): + """ + Sets the reference direction in world coordinate for the orientation constraint + + @type vector: 3-tuple + """ + def getDirection(): + """ + Returns the reference direction of the orientation constraint in world coordinate. + + @rtype: 3-tuple + """ + def setOption(option): + """ + Sets several options of the distance constraint. + + @type option: integer + @param option: Binary combination of the following values: + 64 : Activate alignment to surface + 128 : Detect material rather than property + 256 : No deactivation if ray does not hit target + 512 : Activate distance control + """ + def getOption(): + """ + Returns the option parameter. + + @rtype: integer + """ + def setTime(duration): + """ + Sets the activation time of the actuator. + + @type duration: integer + @param duration: The actuator disables itself after this many frame. + If set to 0 or negative, the actuator is not limited in time. + """ + def getTime(): + """ + Returns the time parameter. + + @rtype: integer + """ + def setProperty(property): + """ + Sets the name of the property or material for the ray detection of the distance constraint. + + @type property: string + @param property: If empty, the ray will detect any collisioning object. + """ + def getProperty(): + """ + Returns the property parameter. + + @rtype: string + """ + def setDistance(distance): + """ + Sets the target distance in distance constraint. + + @type distance: float + """ + def getDistance(): + """ + Returns the distance parameter. + + @rtype: float + """ + def setRayLength(length): + """ + Sets the maximum ray length of the distance constraint. + + @type length: float + """ + def getRayLength(): + """ + Returns the length of the ray + + @rtype: float + """ + + + + + + + + + diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py index 37c188b7f22..a5ba5b1d634 100644 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ b/source/gameengine/PyDoc/KX_GameObject.py @@ -214,6 +214,18 @@ class KX_GameObject: """ Removes this objects parent. """ + def getChildren(): + """ + Return a list of immediate children of this object. + @rtype: list + @return: a list of all this objects children. + """ + def getChildrenRecursive(): + """ + Return a list of children of this object, including all their childrens children. + @rtype: list + @return: a list of all this objects children recursivly. + """ def getMesh(mesh): """ Gets the mesh object for this object. @@ -241,6 +253,16 @@ class KX_GameObject: @type other: L{KX_GameObject} or list [x, y, z] @rtype: float """ + def getVectTo(other): + """ + Returns the vector and the distance to another object or point. + The vector is normalized unless the distance is 0, in which a NULL vector is returned. + + @param other: a point or another L{KX_GameObject} to get the vector and distance to. + @type other: L{KX_GameObject} or list [x, y, z] + @rtype: 3-tuple (float, 3-tuple (x,y,z), 3-tuple (x,y,z)) + @return: (distance, globalVector(3), localVector(3)) + """ def rayCastTo(other,dist,prop): """ Look towards another point/object and find first object hit within dist that matches prop. diff --git a/source/gameengine/PyDoc/KX_IpoActuator.py b/source/gameengine/PyDoc/KX_IpoActuator.py index da8d05ddd5e..1cdab829385 100644 --- a/source/gameengine/PyDoc/KX_IpoActuator.py +++ b/source/gameengine/PyDoc/KX_IpoActuator.py @@ -6,7 +6,7 @@ class KX_IpoActuator(SCA_IActuator): """ IPO actuator activates an animation. """ - def set(mode, startframe, endframe, force): + def set(mode, startframe, endframe, mode): """ Sets the properties of the actuator. @@ -16,8 +16,8 @@ class KX_IpoActuator(SCA_IActuator): @type startframe: integer @param endframe: last frame to use @type endframe: integer - @param force: interpret this ipo as a force - @type force: boolean (KX_TRUE, KX_FALSE) + @param mode: special mode + @type mode: integer (0=normal, 1=interpret location as force, 2=additive) """ def setProperty(property): """ @@ -62,6 +62,19 @@ class KX_IpoActuator(SCA_IActuator): @rtype: boolean """ + def setIpoAdd(add): + """ + Set whether to interpret the ipo as additive rather than absolute. + + @type add: boolean + @param add: KX_TRUE or KX_FALSE + """ + def getIpoAdd(): + """ + Returns whether to interpret the ipo as additive rather than absolute. + + @rtype: boolean + """ def setType(mode): """ Sets the operation mode of the actuator. diff --git a/source/gameengine/PyDoc/KX_ObjectActuator.py b/source/gameengine/PyDoc/KX_ObjectActuator.py index 532c18eea5c..db577d21e6f 100644 --- a/source/gameengine/PyDoc/KX_ObjectActuator.py +++ b/source/gameengine/PyDoc/KX_ObjectActuator.py @@ -6,6 +6,7 @@ class KX_ObjectActuator(SCA_IActuator): """ The object actuator ("Motion Actuator") applies force, torque, displacement, angular displacement, velocity, or angular velocity to an object. + Servo control allows to regulate force to achieve a certain speed target. """ def getForce(): """ @@ -107,15 +108,17 @@ class KX_ObjectActuator(SCA_IActuator): def getLinearVelocity(): """ Returns the linear velocity applied by the actuator. + For the servo control actuator, this is the target speed. @rtype: list [vx, vy, vz, local] @return: A four item list, containing the vector velocity, and whether the velocity is applied in local coordinates (True) or world - coordinates (False) + coordinates (False) """ def setLinearVelocity(vx, vy, vz, local): """ Sets the linear velocity applied by the actuator. + For the servo control actuator, sets the target speed. @type vx: float @param vx: the x component of the velocity vector. @@ -124,8 +127,8 @@ class KX_ObjectActuator(SCA_IActuator): @type vz: float @param vz: the z component of the velocity vector. @type local: boolean - @param local: - False: the velocity vector is applied in world coordinates. - - True: the velocity vector is applied in local coordinates. + @param local: - False: the velocity vector is in world coordinates. + - True: the velocity vector is in local coordinates. """ def getAngularVelocity(): """ @@ -150,5 +153,100 @@ class KX_ObjectActuator(SCA_IActuator): @param local: - False: the velocity vector is applied in world coordinates. - True: the velocity vector is applied in local coordinates. """ + def getDamping(): + """ + Returns the damping parameter of the servo controller. + + @rtype: integer + @return: the time constant of the servo controller in frame unit. + """ + def setDamping(damp): + """ + Sets the damping parameter of the servo controller. + + @type damp: integer + @param damp: the damping parameter in frame unit. + """ + def getForceLimitX(): + """ + Returns the min/max force limit along the X axis used by the servo controller. + + @rtype: list [min, max, enabled] + @return: A three item list, containing the min and max limits of the force as float + and whether the limits are active(true) or inactive(true) + """ + def setForceLimitX(min, max, enable): + """ + Sets the min/max force limit along the X axis and activates or deactivates the limits in the servo controller. + + @type min: float + @param min: the minimum value of the force along the X axis. + @type max: float + @param max: the maximum value of the force along the X axis. + @type enable: boolean + @param enable: - True: the force will be limited to the min/max + - False: the force will not be limited + """ + def getForceLimitY(): + """ + Returns the min/max force limit along the Y axis used by the servo controller. + + @rtype: list [min, max, enabled] + @return: A three item list, containing the min and max limits of the force as float + and whether the limits are active(true) or inactive(true) + """ + def setForceLimitY(min, max, enable): + """ + Sets the min/max force limit along the Y axis and activates or deactivates the limits in the servo controller. + + @type min: float + @param min: the minimum value of the force along the Y axis. + @type max: float + @param max: the maximum value of the force along the Y axis. + @type enable: boolean + @param enable: - True: the force will be limited to the min/max + - False: the force will not be limited + """ + def getForceLimitZ(): + """ + Returns the min/max force limit along the Z axis used by the servo controller. + + @rtype: list [min, max, enabled] + @return: A three item list, containing the min and max limits of the force as float + and whether the limits are active(true) or inactive(true) + """ + def setForceLimitZ(min, max, enable): + """ + Sets the min/max force limit along the Z axis and activates or deactivates the limits in the servo controller. + + @type min: float + @param min: the minimum value of the force along the Z axis. + @type max: float + @param max: the maximum value of the force along the Z axis. + @type enable: boolean + @param enable: - True: the force will be limited to the min/max + - False: the force will not be limited + """ + def getPID(): + """ + Returns the PID coefficient of the servo controller. + + @rtype: list [P, I, D] + @return: A three item list, containing the PID coefficient as floats: + P : proportional coefficient + I : Integral coefficient + D : Derivate coefficient + """ + def setPID(P, I, D): + """ + Sets the PID coefficients of the servo controller. + + @type P: flat + @param P: proportional coefficient + @type I: float + @param I: Integral coefficient + @type D: float + @param D: Derivate coefficient + """ diff --git a/source/gameengine/PyDoc/KX_StateActuator.py b/source/gameengine/PyDoc/KX_StateActuator.py new file mode 100644 index 00000000000..fb6ae5a3621 --- /dev/null +++ b/source/gameengine/PyDoc/KX_StateActuator.py @@ -0,0 +1,26 @@ +# $Id$ +# Documentation for KX_StateActuator +from SCA_IActuator import * + +class KX_StateActuator(SCA_IActuator): + """ + State actuator changes the state mask of parent object. + """ + def setOperation(op): + """ + Set the type of bit operation to be applied on object state mask. + Use setMask() to specify the bits that will be modified. + + @param op: bit operation (0=Copy, 1=Add, 2=Substract, 3=Invert) + @type op: integer + """ + def setMask(mask): + """ + Set the value that defines the bits that will be modified by the operation. + The bits that are 1 in the value will be updated in the object state, + the bits that are 0 are will be left unmodified expect for the Copy operation + which copies the value to the object state. + + @param mask: bits that will be modified + @type mask: integer + """ diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py index b96d8c8c075..0ebc2debb31 100644 --- a/source/gameengine/PyDoc/SCA_ISensor.py +++ b/source/gameengine/PyDoc/SCA_ISensor.py @@ -59,4 +59,22 @@ class SCA_ISensor(SCA_ILogicBrick): @type invert: boolean @param invert: true if activates on negative events; false if activates on positive events. """ + def getLevel(): + """ + Returns whether this sensor is a level detector or a edge detector. + It makes a difference only in case of logic state transition (state actuator). + A level detector will immediately generate a pulse, negative or positive + depending on the sensor condition, as soon as the state is activated. + A edge detector will wait for a state change before generating a pulse. + + @rtype: boolean + @return: true if sensor is level sensitive, false if it is edge sensitive + """ + def setLevel(level): + """ + Set whether to detect level or edge transition when entering a state. + + @param level: Detect level instead of edge? (KX_TRUE, KX_FALSE) + @type level: boolean + """ diff --git a/source/gameengine/Rasterizer/Makefile b/source/gameengine/Rasterizer/Makefile index 1ca3e3b0283..e3b1f274ee5 100644 --- a/source/gameengine/Rasterizer/Makefile +++ b/source/gameengine/Rasterizer/Makefile @@ -41,6 +41,9 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I../../kernel/gen_system CPPFLAGS += -I../BlenderRoutines +CPPFLAGS += -I../Expressions + +CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) ifeq ($(OS),darwin) CPPFLAGS += -fpascal-strings diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp index 958fead33ce..ef206332057 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp @@ -43,6 +43,7 @@ #include "STR_String.h" #include "RAS_ICanvas.h" +#include "RAS_Rect.h" #include "RAS_2DFilterManager.h" #include <iostream> @@ -158,7 +159,8 @@ void RAS_2DFilterManager::AnalyseShader(int passindex, vector<STR_String>& propN texflag[passindex] = 0; if(glGetUniformLocationARB(m_filters[passindex], "bgl_DepthTexture") != -1) { - texflag[passindex] |= 0x1; + if(GLEW_ARB_depth_texture) + texflag[passindex] |= 0x1; } if(glGetUniformLocationARB(m_filters[passindex], "bgl_LuminanceTexture") != -1) { @@ -261,7 +263,7 @@ void RAS_2DFilterManager::SetupTextures(bool depth, bool luminance) glGenTextures(1, (GLuint*)&texname[0]); glBindTexture(GL_TEXTURE_2D, texname[0]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texturewidth, textureheight, 0, GL_RGB, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texturewidth, textureheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -293,10 +295,13 @@ void RAS_2DFilterManager::SetupTextures(bool depth, bool luminance) } } -void RAS_2DFilterManager::UpdateOffsetMatrix(int width, int height) +void RAS_2DFilterManager::UpdateOffsetMatrix(RAS_ICanvas* canvas) { - canvaswidth = texturewidth = width; - canvasheight = textureheight = height; + RAS_Rect canvas_rect = canvas->GetWindowArea(); + canvaswidth = canvas->GetWidth(); + canvasheight = canvas->GetHeight(); + texturewidth = canvaswidth + canvas_rect.GetLeft(); + textureheight = canvasheight + canvas_rect.GetBottom(); GLint i,j; i = 0; @@ -352,7 +357,7 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) if(canvaswidth != canvas->GetWidth() || canvasheight != canvas->GetHeight()) { - UpdateOffsetMatrix(canvas->GetWidth(), canvas->GetHeight()); + UpdateOffsetMatrix(canvas); SetupTextures(need_depth, need_luminance); } GLuint viewport[4]={0}; @@ -360,19 +365,21 @@ void RAS_2DFilterManager::RenderFilters(RAS_ICanvas* canvas) if(need_depth){ glActiveTextureARB(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, texname[1]); - glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, 0,0, texturewidth,textureheight, 0); + glCopyTexImage2D(GL_TEXTURE_2D,0,GL_DEPTH_COMPONENT, 0, 0, texturewidth,textureheight, 0); } if(need_luminance){ glActiveTextureARB(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, texname[2]); - glCopyTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE16, 0,0, texturewidth,textureheight, 0); + glCopyTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE16, 0, 0 , texturewidth,textureheight, 0); } glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); - glViewport(0, 0, texturewidth, textureheight); + glViewport(0,0, texturewidth, textureheight); glDisable(GL_DEPTH_TEST); + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.h b/source/gameengine/Rasterizer/RAS_2DFilterManager.h index 9d8326b96de..f5998e1f093 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.h +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.h @@ -42,7 +42,7 @@ private: void SetupTextures(bool depth, bool luminance); void FreeTextures(); - void UpdateOffsetMatrix(int width, int height); + void UpdateOffsetMatrix(RAS_ICanvas* canvas); float textureoffsets[18]; float view[4]; diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index b4492ca03a9..82bdce44519 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -94,7 +94,6 @@ void RAS_BucketManager::RenderAlphaBuckets( const MT_Scalar cam_origin = cameratrans.getOrigin()[2]; for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { - (*bit)->ClearScheduledPolygons(); for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { if ((*mit).m_bVisible) @@ -133,28 +132,15 @@ void RAS_BucketManager::Renderbuckets( rasty->ClearCachingInfo(); RAS_MaterialBucket::StartFrame(); - for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) - { - (*bucket)->ClearScheduledPolygons(); - } for (bucket = m_MaterialBuckets.begin(); bucket != m_MaterialBuckets.end(); ++bucket) - { - RAS_IPolyMaterial *tmp = (*bucket)->GetPolyMaterial(); - if(tmp->IsZSort() || tmp->GetFlag() &RAS_FORCEALPHA ) - rasty->SetAlphaTest(true); - else - rasty->SetAlphaTest(false); - (*bucket)->Render(cameratrans,rasty,rendertools); - } - rasty->SetAlphaTest(false); RenderAlphaBuckets(cameratrans, rasty, rendertools); RAS_MaterialBucket::EndFrame(); } -RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) +RAS_MaterialBucket* RAS_BucketManager::FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated) { bucketCreated = false; BucketList::iterator it; @@ -172,7 +158,7 @@ RAS_MaterialBucket* RAS_BucketManager::RAS_BucketManagerFindBucket(RAS_IPolyMate RAS_MaterialBucket *bucket = new RAS_MaterialBucket(material); bucketCreated = true; - if (bucket->IsTransparant()) + if (bucket->IsAlpha()) m_AlphaBuckets.push_back(bucket); else m_MaterialBuckets.push_back(bucket); @@ -195,3 +181,28 @@ void RAS_BucketManager::RAS_BucketManagerClearAll() m_MaterialBuckets.clear(); m_AlphaBuckets.clear(); } + +void RAS_BucketManager::ReleaseDisplayLists() +{ + BucketList::iterator bit; + RAS_MaterialBucket::T_MeshSlotList::iterator mit; + + for (bit = m_MaterialBuckets.begin(); bit != m_MaterialBuckets.end(); ++bit) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } + } + } + + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { + for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { + if(mit->m_DisplayList) { + mit->m_DisplayList->Release(); + mit->m_DisplayList = NULL; + } + } + } +} + diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h index 010478b1d5b..08b67ed022f 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.h +++ b/source/gameengine/Rasterizer/RAS_BucketManager.h @@ -58,8 +58,9 @@ public: RAS_IRasterizer* rasty, class RAS_IRenderTools* rendertools); - RAS_MaterialBucket* RAS_BucketManagerFindBucket(RAS_IPolyMaterial * material, bool &bucketCreated); + RAS_MaterialBucket* FindBucket(RAS_IPolyMaterial * material, bool &bucketCreated); + void ReleaseDisplayLists(); private: void RAS_BucketManagerClearAll(); diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h index 0327a3f4763..e3af43fb839 100644 --- a/source/gameengine/Rasterizer/RAS_CameraData.h +++ b/source/gameengine/Rasterizer/RAS_CameraData.h @@ -42,7 +42,7 @@ struct RAS_CameraData int m_viewporttop; float m_focallength; - RAS_CameraData(float lens = 35., float clipstart = 0.1, float clipend = 100., bool perspective = true, + RAS_CameraData(float lens = 35.0, float clipstart = 0.1, float clipend = 5000.0, bool perspective = true, float focallength = 0.0f, bool viewport = false, int viewportleft = 0, int viewportbottom = 0, int viewportright = 0, int viewporttop = 0) : m_lens(lens), diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h index d799dc9c9bb..f3f817a943d 100644 --- a/source/gameengine/Rasterizer/RAS_ICanvas.h +++ b/source/gameengine/Rasterizer/RAS_ICanvas.h @@ -137,6 +137,14 @@ public: ) = 0; /** + * Used to get canvas area within blender. + */ + virtual + RAS_Rect & + GetWindowArea( + ) = 0; + + /** * Set the visible vieport */ diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index cb10ba6bf37..4ee06d96603 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -39,7 +39,8 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, @@ -51,7 +52,8 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, m_tilexrep(tilexrep), m_tileyrep(tileyrep), m_drawingmode (mode), - m_transparant(transparant), + m_transp(transp), + m_alpha(alpha), m_zsort(zsort), m_lightlayer(lightlayer), m_bIsTriangle(bIsTriangle), @@ -74,6 +76,7 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const this->m_multimode == lhs.m_multimode && this->m_flag == lhs.m_flag && this->m_drawingmode == lhs.m_drawingmode && + this->m_transp == lhs.m_transp && this->m_lightlayer == lhs.m_lightlayer && this->m_texturename.hash() == lhs.m_texturename.hash() && this->m_materialname.hash() == lhs.m_materialname.hash() @@ -85,7 +88,8 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const this->m_tile == lhs.m_tile && this->m_tilexrep == lhs.m_tilexrep && this->m_tileyrep == lhs.m_tileyrep && - this->m_transparant == lhs.m_transparant && + this->m_transp == lhs.m_transp && + this->m_alpha == lhs.m_alpha && this->m_zsort == lhs.m_zsort && this->m_drawingmode == lhs.m_drawingmode && this->m_bIsTriangle == lhs.m_bIsTriangle && @@ -109,9 +113,9 @@ int RAS_IPolyMaterial::GetLightLayer() const return m_lightlayer; } -bool RAS_IPolyMaterial::IsTransparant() const +bool RAS_IPolyMaterial::IsAlpha() const { - return m_transparant; + return m_alpha || m_zsort; } bool RAS_IPolyMaterial::IsZSort() const @@ -139,6 +143,11 @@ const STR_String& RAS_IPolyMaterial::GetMaterialName() const return m_materialname; } +dword RAS_IPolyMaterial::GetMaterialNameHash() const +{ + return m_materialname.hash(); +} + const STR_String& RAS_IPolyMaterial::GetTextureName() const { return m_texturename; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index d2d1dba99d9..8fc53e6b038 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -52,7 +52,7 @@ enum MaterialProps RAS_AUTOGEN =128, RAS_NORMAL =256, RAS_DEFMULTI =512, - RAS_FORCEALPHA =1024 + RAS_BLENDERGLSL =1024 }; /** @@ -67,7 +67,8 @@ protected: int m_tile; int m_tilexrep,m_tileyrep; int m_drawingmode; // tface->mode - bool m_transparant; + int m_transp; + bool m_alpha; bool m_zsort; int m_lightlayer; bool m_bIsTriangle; @@ -102,7 +103,8 @@ public: int tilexrep, int tileyrep, int mode, - bool transparant, + int transp, + bool alpha, bool zsort, int lightlayer, bool bIsTriangle, @@ -132,12 +134,13 @@ public: virtual bool Equals(const RAS_IPolyMaterial& lhs) const; bool Less(const RAS_IPolyMaterial& rhs) const; int GetLightLayer() const; - bool IsTransparant() const; + bool IsAlpha() const; bool IsZSort() const; bool UsesTriangles() const; unsigned int hash() const; int GetDrawingMode() const; const STR_String& GetMaterialName() const; + dword GetMaterialNameHash() const; const STR_String& GetTextureName() const; const unsigned int GetFlag() const; diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index d4a9177a85d..9e03212283e 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -372,10 +372,6 @@ public: virtual void SetAmbientColor(float red, float green, float blue)=0; virtual void SetAmbient(float factor)=0; - /** - * Sets alpha testing - */ - virtual void SetAlphaTest(bool enable)=0; /** * Sets a polygon offset. z depth will be: z1 = mult*z0 + add @@ -398,8 +394,10 @@ public: virtual void DisableMotionBlur()=0; virtual float GetMotionBlurValue()=0; - virtual int GetMotionBlurState()=0; - virtual void SetMotionBlurState(int newstate)=0; + virtual int GetMotionBlurState()=0; + virtual void SetMotionBlurState(int newstate)=0; + + virtual void SetBlendingMode(int blendmode)=0; }; #endif //__RAS_IRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index e295d69e48e..0015b6a251f 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -76,26 +76,11 @@ KX_MeshSlot::~KX_MeshSlot() RAS_MaterialBucket::RAS_MaterialBucket(RAS_IPolyMaterial* mat) :m_bModified(true) { - m_bScheduled=true; m_material = mat; } -void RAS_MaterialBucket::SchedulePolygons(int drawingmode) -{ - m_bScheduled = true; -} - - - -void RAS_MaterialBucket::ClearScheduledPolygons() -{ - m_bScheduled = false; -} - - - RAS_IPolyMaterial* RAS_MaterialBucket::GetPolyMaterial() const { return m_material; @@ -134,9 +119,14 @@ void RAS_MaterialBucket::MarkVisibleMeshSlot(KX_MeshSlot& ms, (*it).m_RGBAcolor= rgbavec; } -bool RAS_MaterialBucket::IsTransparant() const +bool RAS_MaterialBucket::IsAlpha() const +{ + return (m_material->IsAlpha()); +} + +bool RAS_MaterialBucket::IsZSort() const { - return (m_material->IsTransparant()); + return (m_material->IsZSort()); } diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 13d8a53714a..4eef889c533 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -125,11 +125,9 @@ public: class RAS_IRasterizer* rasty, class RAS_IRenderTools* rendertools); - void SchedulePolygons(int drawingmode); - void ClearScheduledPolygons(); - RAS_IPolyMaterial* GetPolyMaterial() const; - bool IsTransparant() const; + bool IsAlpha() const; + bool IsZSort() const; static void StartFrame(); static void EndFrame(); @@ -162,7 +160,6 @@ public: private: T_MeshSlotList m_meshSlots; - bool m_bScheduled; bool m_bModified; RAS_IPolyMaterial* m_material; double* m_pOGLMatrix; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 4420f16c56d..af5228e4c35 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -35,6 +35,8 @@ #include "MT_MinMax.h" #include "MT_Point3.h" +#include <algorithm> + STR_String RAS_MeshObject::s_emptyname = ""; @@ -201,28 +203,35 @@ void RAS_MeshObject::DebugColor(unsigned int abgr) m_debugcolor = abgr; } - +void RAS_MeshObject::SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba) +{ + const vecVertexArray & vertexvec = GetVertexCache(mat); + + for (vector<KX_VertexArray*>::const_iterator it = vertexvec.begin(); it != vertexvec.end(); ++it) + { + KX_VertexArray::iterator vit; + for (vit=(*it)->begin(); vit != (*it)->end(); vit++) + { + vit->SetRGBA(rgba); + } + } +} void RAS_MeshObject::SchedulePoly(const KX_VertexIndex& idx, int numverts, RAS_IPolyMaterial* mat) { - //int indexpos = m_IndexArrayCount[idx.m_vtxarray]; - //m_IndexArrayCount[idx.m_vtxarray] = indexpos + 3; - KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[0]); ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[1]); ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[2]); - if (!mat->UsesTriangles()) //if (!m_bUseTriangles) - { - //m_IndexArrayCount[idx.m_vtxarray] = indexpos+4; + + if (!mat->UsesTriangles()) ao->m_IndexArrayCache1[idx.m_vtxarray]->push_back(idx.m_indexarray[3]); - } } - void RAS_MeshObject::ScheduleWireframePoly(const KX_VertexIndex& idx, int numverts, int edgecode, @@ -409,7 +418,6 @@ void RAS_MeshObject::Bucketize(double* oglmatrix, for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) { RAS_MaterialBucket* bucket = *it; - bucket->SchedulePolygons(0); // KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); bucket->SetMeshSlot(ms); } @@ -434,7 +442,6 @@ void RAS_MeshObject::MarkVisible(double* oglmatrix, for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) { RAS_MaterialBucket* bucket = *it; - bucket->SchedulePolygons(0); // KX_ArrayOptimizer* oa = GetArrayOptimizer(bucket->GetPolyMaterial()); bucket->MarkVisibleMeshSlot(ms,visible,useObjectColor,rgbavec); } @@ -453,7 +460,6 @@ void RAS_MeshObject::RemoveFromBuckets(double* oglmatrix, { RAS_MaterialBucket* bucket = *it; // RAS_IPolyMaterial* polymat = bucket->GetPolyMaterial(); - bucket->SchedulePolygons(0); //KX_ArrayOptimizer* oa = GetArrayOptimizer(polymat); bucket->RemoveMeshSlot(ms); } @@ -572,31 +578,36 @@ void RAS_MeshObject::UpdateMaterialList() struct RAS_MeshObject::polygonSlot { - float m_z; - RAS_Polygon *m_poly; - - polygonSlot(float z, RAS_Polygon* poly) : - m_z(z), - m_poly(poly) - {} - /** - * pnorm and pval form the plane equation that the distance from is used to - * sort against. - */ - polygonSlot(const MT_Vector3 &pnorm, const MT_Scalar &pval, RAS_MeshObject *mesh, RAS_Polygon* poly) : - m_poly(poly) + float m_z; + int m_index[4]; + + polygonSlot() {} + + /* pnorm is the normal from the plane equation that the distance from is + * used to sort again. */ + void get(const KX_VertexArray& vertexarray, const KX_IndexArray& indexarray, + int offset, int nvert, const MT_Vector3& pnorm) { - const KX_VertexIndex &base = m_poly->GetIndexBase(); - RAS_TexVert *vert = mesh->GetVertex(base.m_vtxarray, base.m_indexarray[0], poly->GetMaterial()->GetPolyMaterial()); - m_z = MT_dot(pnorm, vert->getLocalXYZ()) + pval; - - for(int i = 1; i < m_poly->VertexCount(); i++) - { - vert = mesh->GetVertex(base.m_vtxarray, base.m_indexarray[i], poly->GetMaterial()->GetPolyMaterial()); - float z = MT_dot(pnorm, vert->getLocalXYZ()) + pval; - m_z += z; + MT_Vector3 center(0, 0, 0); + int i; + + for(i=0; i<nvert; i++) { + m_index[i] = indexarray[offset+i]; + center += vertexarray[m_index[i]].getLocalXYZ(); } - m_z /= m_poly->VertexCount(); + + /* note we don't divide center by the number of vertices, since all + * polygons have the same number of vertices, and that we leave out + * the 4-th component of the plane equation since it is constant. */ + m_z = MT_dot(pnorm, center); + } + + void set(KX_IndexArray& indexarray, int offset, int nvert) + { + int i; + + for(i=0; i<nvert; i++) + indexarray[offset+i] = m_index[i]; } }; @@ -616,100 +627,100 @@ struct RAS_MeshObject::fronttoback } }; - void RAS_MeshObject::SortPolygons(const MT_Transform &transform) { + // Limitations: sorting is quite simple, and handles many + // cases wrong, partially due to polygons being sorted per + // bucket. + // + // a) mixed triangles/quads are sorted wrong + // b) mixed materials are sorted wrong + // c) more than 65k faces are sorted wrong + // d) intersecting objects are sorted wrong + // e) intersecting polygons are sorted wrong + // + // a) can be solved by making all faces either triangles or quads + // if they need to be z-sorted. c) could be solved by allowing + // larger buckets, b) and d) cannot be solved easily if we want + // to avoid excessive state changes while drawing. e) would + // require splitting polygons. + if (!m_zsort) return; - + // Extract camera Z plane... const MT_Vector3 pnorm(transform.getBasis()[2]); - const MT_Scalar pval = transform.getOrigin()[2]; - - unsigned int numpolys = m_Polygons.size(); - std::multiset<polygonSlot, backtofront> alphapolyset; - std::multiset<polygonSlot, fronttoback> solidpolyset; - - for (unsigned int p = 0; p < numpolys; p++) - { - RAS_Polygon* poly = m_Polygons[p]; - if (poly->IsVisible()) - { - if (poly->GetMaterial()->GetPolyMaterial()->IsTransparant()) - { - alphapolyset.insert(polygonSlot(pnorm, pval, this, poly)); - } else { - solidpolyset.insert(polygonSlot(pnorm, pval, this, poly)); - } - } - } - - // Clear current array data. + // unneeded: const MT_Scalar pval = transform.getOrigin()[2]; + for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) { - vector<KX_IndexArray*> *indexcache = &GetArrayOptimizer((*it)->GetPolyMaterial())->m_IndexArrayCache1; - for (vector<KX_IndexArray*>::iterator iit = indexcache->begin(); iit != indexcache->end(); ++iit) - (*iit)->clear(); - } + if(!(*it)->IsZSort()) + continue; - std::multiset<polygonSlot, fronttoback>::iterator sit = solidpolyset.begin(); - for (; sit != solidpolyset.end(); ++sit) - SchedulePoly((*sit).m_poly->GetVertexIndexBase(), (*sit).m_poly->VertexCount(), (*sit).m_poly->GetMaterial()->GetPolyMaterial()); - - std::multiset<polygonSlot, backtofront>::iterator ait = alphapolyset.begin(); - for (; ait != alphapolyset.end(); ++ait) - SchedulePoly((*ait).m_poly->GetVertexIndexBase(), (*ait).m_poly->VertexCount(), (*ait).m_poly->GetMaterial()->GetPolyMaterial()); + RAS_IPolyMaterial *mat = (*it)->GetPolyMaterial(); + KX_ArrayOptimizer* ao = GetArrayOptimizer(mat); + + vecIndexArrays& indexarrays = ao->m_IndexArrayCache1; + vecVertexArray& vertexarrays = ao->m_VertexArrayCache1; + unsigned int i, j, nvert = (mat->UsesTriangles())? 3: 4; + + for(i=0; i<indexarrays.size(); i++) { + KX_IndexArray& indexarray = *indexarrays[i]; + KX_VertexArray& vertexarray = *vertexarrays[i]; + + unsigned int totpoly = indexarray.size()/nvert; + vector<polygonSlot> slots(totpoly); + + /* get indices and z into temporary array */ + for(j=0; j<totpoly; j++) + slots[j].get(vertexarray, indexarray, j*nvert, nvert, pnorm); + + /* sort (stable_sort might be better, if flickering happens?) */ + std::sort(slots.begin(), slots.end(), backtofront()); + + /* get indices from temporary array again */ + for(j=0; j<totpoly; j++) + slots[j].set(indexarray, j*nvert, nvert); + } + } } -void RAS_MeshObject::SchedulePolygons(const MT_Transform &transform, int drawingmode) +void RAS_MeshObject::SchedulePolygons(int drawingmode) { -// int nummaterials = m_materials.size(); - int i; - if (m_bModified) { - for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) - { - RAS_MaterialBucket* bucket = *it; + int i, numpolys = m_Polygons.size(); - bucket->SchedulePolygons(drawingmode); - if (bucket->GetPolyMaterial()->IsZSort()) + for (RAS_MaterialBucket::Set::iterator it = m_materials.begin();it!=m_materials.end();++it) + if ((*it)->IsZSort()) m_zsort = true; - } - - int numpolys = m_Polygons.size(); - if ((drawingmode > RAS_IRasterizer::KX_BOUNDINGBOX) && - (drawingmode < RAS_IRasterizer::KX_SOLID)) + if (drawingmode == RAS_IRasterizer::KX_WIREFRAME) { for (i=0;i<numpolys;i++) { RAS_Polygon* poly = m_Polygons[i]; if (poly->IsVisible()) - ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode() - ,poly->GetMaterial()->GetPolyMaterial()); + ScheduleWireframePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetEdgeCode(), + poly->GetMaterial()->GetPolyMaterial()); } m_zsort = false; } else { - if (!m_zsort) + for (i=0;i<numpolys;i++) { - for (i=0;i<numpolys;i++) - { - RAS_Polygon* poly = m_Polygons[i]; - if (poly->IsVisible()) - { - SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(),poly->GetMaterial()->GetPolyMaterial()); - } - } + RAS_Polygon* poly = m_Polygons[i]; + if (poly->IsVisible()) + SchedulePoly(poly->GetVertexIndexBase(),poly->VertexCount(), + poly->GetMaterial()->GetPolyMaterial()); } } m_bModified = false; - m_MeshMod = true; } } + diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index 0d06748f91f..99806666fa6 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -137,6 +137,18 @@ class RAS_MeshObject struct backtofront; struct fronttoback; + void SchedulePoly( + const KX_VertexIndex& idx, + int numverts, + RAS_IPolyMaterial* mat + ); + + void ScheduleWireframePoly( + const KX_VertexIndex& idx, + int numverts, + int edgecode, + RAS_IPolyMaterial* mat + ); protected: enum { BUCKET_MAX_INDICES = 65535 };//2048};//8192}; @@ -189,16 +201,14 @@ public: ); void DebugColor(unsigned int abgr); + void SetVertexColor(RAS_IPolyMaterial* mat,MT_Vector4 rgba); /** * Sorts the polygons by their transformed z values. */ void SortPolygons(const MT_Transform &transform); - void SchedulePolygons( - const MT_Transform &transform, - int drawingmode - ); + void SchedulePolygons(int drawingmode); void ClearArrayData(); @@ -215,19 +225,7 @@ public: int numverts, RAS_IPolyMaterial* polymat ); - - void SchedulePoly( - const KX_VertexIndex& idx, - int numverts, - RAS_IPolyMaterial* mat - ); - void ScheduleWireframePoly( - const KX_VertexIndex& idx, - int numverts, - int edgecode, - RAS_IPolyMaterial* mat - ); // find (and share) or add vertices // for some speedup, only the last 20 added vertices are searched for equality diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index dcc36bf5a39..1dcc6e70934 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -67,6 +67,7 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_motionblurvalue(-1.0), m_texco_num(0), m_attrib_num(0), + m_last_blendmode(0), m_materialCachingInfo(0) { m_viewmatrix.Identity(); @@ -171,6 +172,8 @@ bool RAS_OpenGLRasterizer::Init() m_ambg = 0.0f; m_ambb = 0.0f; + SetBlendingMode(0); + glClearColor(m_redback,m_greenback,m_blueback,m_alphaback); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -189,18 +192,6 @@ void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue) } -void RAS_OpenGLRasterizer::SetAlphaTest(bool enable) -{ - if (enable) - { - glEnable(GL_ALPHA_TEST); - glAlphaFunc(GL_GREATER, 0.6f); - } - else glDisable(GL_ALPHA_TEST); -} - - - void RAS_OpenGLRasterizer::SetAmbient(float factor) { float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f }; @@ -353,6 +344,8 @@ bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) glEnable (GL_CULL_FACE); } + SetBlendingMode(0); + glShadeModel(GL_SMOOTH); m_2DCanvas->BeginFrame(); @@ -1389,3 +1382,34 @@ void RAS_OpenGLRasterizer::DisableMotionBlur() m_motionblur = 0; m_motionblurvalue = -1.0; } + +void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) +{ + if(blendmode == m_last_blendmode) + return; + + if(blendmode == 0) { + glDisable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + else if(blendmode == 1) { + glBlendFunc(GL_ONE, GL_ONE); + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + } + else if(blendmode == 2) { + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.0f); + } + else if(blendmode == 4) { + glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.5f); + } + + m_last_blendmode = blendmode; +} + diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 0d54552db05..02056cce446 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -99,6 +99,7 @@ protected: TexCoGen m_attrib[RAS_MAX_ATTRIB]; int m_texco_num; int m_attrib_num; + int m_last_blendmode; /** Stores the caching information for the last material activated. */ RAS_IPolyMaterial::TCachingInfo m_materialCachingInfo; @@ -142,8 +143,6 @@ public: virtual void SetFocalLength(const float focallength); virtual float GetFocalLength(); - virtual void SetAlphaTest(bool enable); - virtual void SwapBuffers(); virtual void IndexPrimitives( const vecVertexArray& vertexarrays, @@ -282,8 +281,8 @@ public: virtual void EnableMotionBlur(float motionblurvalue); virtual void DisableMotionBlur(); virtual float GetMotionBlurValue(){return m_motionblurvalue;}; - virtual int GetMotionBlurState(){return m_motionblur;}; - virtual void SetMotionBlurState(int newstate) + virtual int GetMotionBlurState(){return m_motionblur;}; + virtual void SetMotionBlurState(int newstate) { if(newstate<0) m_motionblur = 0; @@ -292,6 +291,8 @@ public: else m_motionblur = newstate; }; + + virtual void SetBlendingMode(int blendmode); }; #endif //__RAS_OPENGLRASTERIZER diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp index 852c94def3f..b74cb9cfcac 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.cpp +++ b/source/gameengine/Rasterizer/RAS_Polygon.cpp @@ -37,24 +37,6 @@ #include "RAS_Polygon.h" -/* -RAS_TexVert* RAS_Polygon::GetVertex(int index) -{ - if (m_bucket) - return m_bucket->GetVertex(m_vertexindexbase.m_vtxarray, m_vertexindexbase.m_indexarray[index]); - else - return NULL; -} -*/ - -/*void RAS_Polygon::Bucketize(double* oglmatrix) -{ - //Transform(trans); - if (m_bucket) - m_bucket->AddPolygon(this,oglmatrix); -} -*/ - RAS_Polygon::RAS_Polygon(RAS_MaterialBucket* bucket, bool visible, int numverts, diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp index c347bbc6d9a..d0bdac5c8f0 100644 --- a/source/gameengine/SceneGraph/SG_IObject.cpp +++ b/source/gameengine/SceneGraph/SG_IObject.cpp @@ -104,7 +104,7 @@ SetSGClientObject( } - void + bool SG_IObject:: ActivateReplicationCallback( SG_IObject *replica @@ -112,8 +112,10 @@ ActivateReplicationCallback( if (m_callbacks.m_replicafunc) { // Call client provided replication func - m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo); + if (m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo) == NULL) + return false; } + return true; }; void diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h index 438ab48c556..7f6bdfbbb1c 100644 --- a/source/gameengine/SceneGraph/SG_IObject.h +++ b/source/gameengine/SceneGraph/SG_IObject.h @@ -202,7 +202,7 @@ public: protected : - void + bool ActivateReplicationCallback( SG_IObject *replica ); diff --git a/source/gameengine/SceneGraph/SG_Node.cpp b/source/gameengine/SceneGraph/SG_Node.cpp index 4e90d7c4653..8de7ac83477 100644 --- a/source/gameengine/SceneGraph/SG_Node.cpp +++ b/source/gameengine/SceneGraph/SG_Node.cpp @@ -68,7 +68,7 @@ SG_Node* SG_Node::GetSGReplica() SG_Node* replica = new SG_Node(*this); if (replica == NULL) return NULL; - ProcessSGReplica(replica); + ProcessSGReplica(&replica); return replica; } @@ -76,25 +76,42 @@ SG_Node* SG_Node::GetSGReplica() void SG_Node:: ProcessSGReplica( - SG_Node* replica + SG_Node** replica ){ // Apply the replication call back function. - ActivateReplicationCallback(replica); + if (!ActivateReplicationCallback(*replica)) + { + delete (*replica); + *replica = NULL; + return; + } // clear the replica node of it's parent. - static_cast<SG_Node*>(replica)->m_SGparent = NULL; + static_cast<SG_Node*>(*replica)->m_SGparent = NULL; if (m_children.begin() != m_children.end()) { // if this node has children, the replica has too, so clear and clone children - replica->ClearSGChildren(); + (*replica)->ClearSGChildren(); NodeList::iterator childit; for (childit = m_children.begin();childit!=m_children.end();++childit) { - replica->AddChild((*childit)->GetSGReplica()); + SG_Node* childnode = (*childit)->GetSGReplica(); + if (childnode) + (*replica)->AddChild(childnode); } } + // Nodes without children and without client object are + // not worth to keep, they will just take up CPU + // This can happen in partial replication of hierarchy + // during group duplication. + if ((*replica)->m_children.empty() && + (*replica)->GetSGClientObject() == NULL) + { + delete (*replica); + *replica = NULL; + } } diff --git a/source/gameengine/SceneGraph/SG_Node.h b/source/gameengine/SceneGraph/SG_Node.h index f86e3046d93..ffaaad861e2 100644 --- a/source/gameengine/SceneGraph/SG_Node.h +++ b/source/gameengine/SceneGraph/SG_Node.h @@ -205,7 +205,7 @@ private: void ProcessSGReplica( - SG_Node* replica + SG_Node** replica ); /** |