diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-06-09 00:08:19 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2009-06-09 00:08:19 +0400 |
commit | c8b4cf92067ffeb625aa39003baf5d8f7c3f0025 (patch) | |
tree | c6c50dbc3d90a65fca6c1ca56a93e4a57cf7e154 /source/gameengine | |
parent | e93db433a086a3e739c0f4026cd500f0b595b0f1 (diff) | |
parent | d76a6f5231c015c35123d22e1f5c3ffcdfbf9bbd (diff) |
2.50:
svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r19820:HEAD
Notes:
* Game and sequencer RNA, and sequencer header are now out of date
a bit after changes in trunk.
* I didn't know how to port these bugfixes, most likely they are
not needed anymore.
* Fix "duplicate strip" always increase the user count for ipo.
* IPO pinning on sequencer strips was lost during Undo.
Diffstat (limited to 'source/gameengine')
385 files changed, 15994 insertions, 10691 deletions
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index d8de24c610c..4ac28e36c48 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -129,6 +129,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, BLI_strncpy(pathname, blenderdata->name, sizeof(pathname)); BLI_strncpy(oldsce, G.sce, sizeof(oldsce)); + resetGamePythonPath(); // need this so running a second time wont use an old blendfiles path setGamePythonPath(G.sce); // Acquire Python's GIL (global interpreter lock) @@ -153,7 +154,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, bool game2ipo = (SYS_GetCommandLineInt(syshandle, "game2ipo", 0) != 0); bool displaylists = (SYS_GetCommandLineInt(syshandle, "displaylists", 0) != 0); bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0); - + bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0); // create the canvas, rasterizer and rendertools RAS_ICanvas* canvas = new KX_BlenderCanvas(area); canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); @@ -161,12 +162,12 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, RAS_IRasterizer* rasterizer = NULL; if(displaylists) { - if (GLEW_VERSION_1_1) + if (GLEW_VERSION_1_1 && !novertexarrays) rasterizer = new RAS_ListRasterizer(canvas, true, true); else rasterizer = new RAS_ListRasterizer(canvas); } - else if (GLEW_VERSION_1_1) + else if (GLEW_VERSION_1_1 && !novertexarrays) rasterizer = new RAS_VAOpenGLRasterizer(canvas, false); else rasterizer = new RAS_OpenGLRasterizer(canvas); @@ -292,6 +293,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, if(blenderdata) { BLI_strncpy(G.sce, blenderdata->name, sizeof(G.sce)); BLI_strncpy(pathname, blenderdata->name, sizeof(pathname)); + setGamePythonPath(G.sce); } } // else forget it, we can't find it @@ -321,12 +323,11 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, { int startFrame = blscene->r.cfra; ketsjiengine->SetGame2IpoMode(game2ipo,startFrame); + + // Quad buffered needs a special window. + if (blscene->r.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) + rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) blscene->r.stereomode); } - - - // Quad buffered needs a special window. - if (blscene->r.stereomode != RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) - rasterizer->SetStereoMode((RAS_IRasterizer::StereoMode) blscene->r.stereomode); if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME) { @@ -380,6 +381,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, initGameKeys(); initPythonConstraintBinding(); initMathutils(); + initGeometry(); initBGL(); #ifdef WITH_FFMPEG initVideoTexture(); @@ -387,7 +389,7 @@ extern "C" void StartKetsjiShell(struct ScrArea *area, //initialize Dome Settings if(blscene->r.stereomode == RAS_IRasterizer::RAS_STEREO_DOME) - ketsjiengine->InitDome(blscene->r.domesize, blscene->r.domeres, blscene->r.domemode, blscene->r.domeangle, blscene->r.domeresbuf, blscene->r.dometext); + ketsjiengine->InitDome(blscene->r.domeres, blscene->r.domemode, blscene->r.domeangle, blscene->r.domeresbuf, blscene->r.dometilt, blscene->r.dometext); if (sceneconverter) { @@ -684,6 +686,7 @@ extern "C" void StartKetsjiShellSimulation(struct ScrArea *area, initGameKeys(); initPythonConstraintBinding(); initMathutils(); + initGeometry(); initBGL(); #ifdef WITH_FFMPEG initVideoTexture(); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp index 9dbda3f195b..17d1bf65ca4 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderRenderTools.cpp @@ -68,8 +68,8 @@ void KX_BlenderRenderTools::BeginFrame(RAS_IRasterizer* rasty) { m_clientobject = NULL; m_lastlightlayer = -1; - m_lastlighting = false; m_lastauxinfo = NULL; + m_lastlighting = true; /* force disable in DisableOpenGLLights() */ DisableOpenGLLights(); } @@ -295,7 +295,7 @@ void KX_BlenderRenderTools::RenderText( RAS_IPolyMaterial* polymat, float v1[3], float v2[3], float v3[3], float v4[3], int glattrib) { - STR_String mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); + const STR_String& mytext = ((CValue*)m_clientobject)->GetPropertyText("Text"); const unsigned int flag = polymat->GetFlag(); struct MTFace* tface = 0; diff --git a/source/gameengine/CMakeLists.txt b/source/gameengine/CMakeLists.txt index 3ea788791e2..fd05858710d 100644 --- a/source/gameengine/CMakeLists.txt +++ b/source/gameengine/CMakeLists.txt @@ -24,25 +24,23 @@ # # ***** END GPL LICENSE BLOCK ***** -SUBDIRS( - BlenderRoutines - Converter - Expressions - GameLogic - Ketsji - Ketsji/KXNetwork - Network - Network/LoopBackNetwork - Physics/common - Physics/Dummy - Rasterizer - Rasterizer/RAS_OpenGLRasterizer - SceneGraph - Physics/Bullet - Physics/Sumo - VideoTexture -) +ADD_SUBDIRECTORY(BlenderRoutines) +ADD_SUBDIRECTORY(Converter) +ADD_SUBDIRECTORY(Expressions) +ADD_SUBDIRECTORY(GameLogic) +ADD_SUBDIRECTORY(Ketsji) +ADD_SUBDIRECTORY(Ketsji/KXNetwork) +ADD_SUBDIRECTORY(Network) +ADD_SUBDIRECTORY(Network/LoopBackNetwork) +ADD_SUBDIRECTORY(Physics/common) +ADD_SUBDIRECTORY(Physics/Dummy) +ADD_SUBDIRECTORY(Rasterizer) +ADD_SUBDIRECTORY(Rasterizer/RAS_OpenGLRasterizer) +ADD_SUBDIRECTORY(SceneGraph) +ADD_SUBDIRECTORY(Physics/Bullet) +ADD_SUBDIRECTORY(Physics/Sumo) +ADD_SUBDIRECTORY(VideoTexture) IF(WITH_PLAYER) - SUBDIRS(GamePlayer) + ADD_SUBDIRECTORY(GamePlayer) ENDIF(WITH_PLAYER) diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 662d6b7a63e..e4dd588f06a 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -66,9 +66,9 @@ BL_ActionActuator::~BL_ActionActuator() game_free_pose(m_blendpose); } -void BL_ActionActuator::ProcessReplica(){ -// bPose *oldpose = m_pose; -// bPose *oldbpose = m_blendpose; +void BL_ActionActuator::ProcessReplica() +{ + SCA_IActuator::ProcessReplica(); m_pose = NULL; m_blendpose = NULL; @@ -84,9 +84,6 @@ void BL_ActionActuator::SetBlendTime (float newtime){ CValue* BL_ActionActuator::GetReplica() { BL_ActionActuator* replica = new BL_ActionActuator(*this);//m_float,GetName()); replica->ProcessReplica(); - - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; } @@ -159,16 +156,9 @@ bool BL_ActionActuator::Update(double curtime, bool frame) // maybe there are events for us in the queue ! if (frame) { - for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++) - { - if ((*i)->GetNumber() == 0.0f) - bNegativeEvent = true; - else - bPositiveEvent= true; - (*i)->Release(); - - } - m_events.clear(); + bNegativeEvent = m_negevent; + bPositiveEvent = m_posevent; + RemoveAllEvents(); if (bPositiveEvent) m_flag |= ACT_FLAG_ACTIVE; @@ -945,8 +935,13 @@ KX_PYMETHODDEF_DOC(BL_ActionActuator, setChannel, /* ------------------------------------------------------------------------- */ PyTypeObject BL_ActionActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "BL_ActionActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -1002,17 +997,17 @@ PyMethodDef BL_ActionActuator::Methods[] = { }; PyAttributeDef BL_ActionActuator::Attributes[] = { - KX_PYATTRIBUTE_FLOAT_RW("start", 0, MAXFRAMEF, BL_ActionActuator, m_startframe), - KX_PYATTRIBUTE_FLOAT_RW("end", 0, MAXFRAMEF, BL_ActionActuator, m_endframe), - KX_PYATTRIBUTE_FLOAT_RW("blendin", 0, MAXFRAMEF, BL_ActionActuator, m_blendin), + KX_PYATTRIBUTE_FLOAT_RW("frameStart", 0, MAXFRAMEF, BL_ActionActuator, m_startframe), + KX_PYATTRIBUTE_FLOAT_RW("frameEnd", 0, MAXFRAMEF, BL_ActionActuator, m_endframe), + KX_PYATTRIBUTE_FLOAT_RW("blendIn", 0, MAXFRAMEF, BL_ActionActuator, m_blendin), KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ActionActuator, pyattr_get_action, pyattr_set_action), KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ActionActuator, m_priority), KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ActionActuator, m_localtime, CheckFrame), - KX_PYATTRIBUTE_STRING_RW("property", 0, 31, false, BL_ActionActuator, m_propname), - KX_PYATTRIBUTE_STRING_RW("frameProperty", 0, 31, false, BL_ActionActuator, m_framepropname), - KX_PYATTRIBUTE_BOOL_RW("continue", BL_ActionActuator, m_end_reset), + KX_PYATTRIBUTE_STRING_RW("propName", 0, 31, false, BL_ActionActuator, m_propname), + KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 31, false, BL_ActionActuator, m_framepropname), + KX_PYATTRIBUTE_BOOL_RW("useContinue", BL_ActionActuator, m_end_reset), KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ActionActuator, m_blendframe, CheckBlendTime), - KX_PYATTRIBUTE_SHORT_RW_CHECK("type",0,100,false,BL_ActionActuator,m_playtype,CheckType), + KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",0,100,false,BL_ActionActuator,m_playtype,CheckType), { NULL } //Sentinel }; @@ -1020,6 +1015,10 @@ PyObject* BL_ActionActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); } +PyObject* BL_ActionActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int BL_ActionActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); } @@ -1038,7 +1037,7 @@ int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF if (!PyString_Check(value)) { PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, expected the string name of the action"); - return -1; + return PY_SET_ATTR_FAIL; } bAction *action= NULL; @@ -1050,11 +1049,11 @@ int BL_ActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE_DEF if (!action) { PyErr_SetString(PyExc_ValueError, "actuator.action = val: Action Actuator, action not found!"); - return 1; + return PY_SET_ATTR_FAIL; } } self->SetAction(action); - return 0; + return PY_SET_ATTR_SUCCESS; } diff --git a/source/gameengine/Converter/BL_ActionActuator.h b/source/gameengine/Converter/BL_ActionActuator.h index 6ae7f716b4b..b3c15c08f50 100644 --- a/source/gameengine/Converter/BL_ActionActuator.h +++ b/source/gameengine/Converter/BL_ActionActuator.h @@ -114,6 +114,7 @@ public: KX_PYMETHOD_DOC(BL_ActionActuator,setChannel); virtual PyObject* py_getattro(PyObject* attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject* attr, PyObject* value); static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index 071cd50c506..6fc5c40d570 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -70,20 +70,17 @@ BL_ArmatureObject::BL_ArmatureObject( CValue* BL_ArmatureObject::GetReplica() { BL_ArmatureObject* replica = new BL_ArmatureObject(*this); - - // this will copy properties and so on... - CValue::AddDataToReplica(replica); - - ProcessReplica(replica); + replica->ProcessReplica(); return replica; } -void BL_ArmatureObject::ProcessReplica(BL_ArmatureObject *replica) +void BL_ArmatureObject::ProcessReplica() { - KX_GameObject::ProcessReplica(replica); + bPose *pose= m_pose; + KX_GameObject::ProcessReplica(); - replica->m_pose = NULL; - game_copy_pose(&replica->m_pose, m_pose); + m_pose = NULL; + game_copy_pose(&m_pose, pose); } BL_ArmatureObject::~BL_ArmatureObject() diff --git a/source/gameengine/Converter/BL_ArmatureObject.h b/source/gameengine/Converter/BL_ArmatureObject.h index d68e37d9e37..d5402cfd126 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.h +++ b/source/gameengine/Converter/BL_ArmatureObject.h @@ -45,7 +45,7 @@ class BL_ArmatureObject : public KX_GameObject public: double GetLastFrame (); short GetActivePriority(); - virtual void ProcessReplica(BL_ArmatureObject *replica); + virtual void ProcessReplica(); class BL_ActionActuator * GetActiveAction(); BL_ArmatureObject( diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 5220361d10d..c25bdbe71f7 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -90,6 +90,7 @@ #include "BKE_object.h" #include "BKE_scene.h" #include "BL_SkinMeshObject.h" +#include "BL_ModifierDeformer.h" #include "BL_ShapeDeformer.h" #include "BL_SkinDeformer.h" #include "BL_MeshDeformer.h" @@ -317,7 +318,8 @@ typedef struct MTF_localLayer }MTF_localLayer; // ------------------------------------ -BL_Material* ConvertMaterial( +bool ConvertMaterial( + BL_Material *material, Material *mat, MTFace* tface, const char *tfaceName, @@ -328,9 +330,7 @@ BL_Material* ConvertMaterial( MTF_localLayer *layers, bool glslmat) { - //this needs some type of manager - BL_Material *material = new BL_Material(); - + material->Initialize(); int numchan = -1, texalpha = 0; bool validmat = (mat!=0); bool validface = (tface!=0); @@ -341,6 +341,7 @@ BL_Material* ConvertMaterial( material->IdMode = DEFAULT_BLENDER; material->glslmat = (validmat)? glslmat: false; + material->materialindex = mface->mat_nr; // -------------------------------- if(validmat) { @@ -718,7 +719,7 @@ BL_Material* ConvertMaterial( material->tface = tface; material->material = mat; - return material; + return true; } @@ -728,6 +729,8 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* bool skinMesh = false; int lightlayer = blenderobj->lay; + if ((meshobj = converter->FindGameMesh(mesh/*, ob->lay*/)) != NULL) + return meshobj; // Get DerivedMesh data DerivedMesh *dm = CDDM_from_mesh(mesh, blenderobj); @@ -747,7 +750,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* } // Determine if we need to make a skinned mesh - if (mesh->dvert || mesh->key || ((blenderobj->gameflag & OB_SOFT_BODY) != 0)) + if (mesh->dvert || mesh->key || ((blenderobj->gameflag & OB_SOFT_BODY) != 0) || BL_ModifierDeformer::HasCompatibleDeformer(blenderobj)) { meshobj = new BL_SkinMeshObject(mesh, lightlayer); skinMesh = true; @@ -779,6 +782,13 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* meshobj->SetName(mesh->id.name); meshobj->m_sharedvertex_map.resize(totvert); + RAS_IPolyMaterial* polymat = NULL; + STR_String imastr; + // These pointers will hold persistent material structure during the conversion + // to avoid countless allocation/deallocation of memory. + BL_Material* bl_mat = NULL; + KX_BlenderMaterial* kx_blmat = NULL; + KX_PolygonMaterial* kx_polymat = NULL; for (int f=0;f<totface;f++,mface++) { @@ -841,8 +851,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* { bool visible = true; bool twoside = false; - RAS_IPolyMaterial* polymat = NULL; - BL_Material *bl_mat = NULL; if(converter->GetMaterials()) { /* do Blender Multitexture and Blender GLSL materials */ @@ -850,11 +858,11 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* MT_Point2 uv[4]; /* first is the BL_Material */ - bl_mat = ConvertMaterial(ma, tface, tfaceName, mface, mcol, + if (!bl_mat) + bl_mat = new BL_Material(); + ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, lightlayer, blenderobj, layers, converter->GetGLSLMaterials()); - bl_mat->material_index = (int)mface->mat_nr; - visible = ((bl_mat->ras_mode & POLY_VIS)!=0); collider = ((bl_mat->ras_mode & COLLIDER)!=0); twoside = ((bl_mat->mode & TF_TWOSIDE)!=0); @@ -873,12 +881,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* uv22 = uv[2]; uv23 = uv[3]; /* then the KX_BlenderMaterial */ - polymat = new KX_BlenderMaterial(scene, bl_mat, skinMesh, lightlayer); + if (kx_blmat == NULL) + kx_blmat = new KX_BlenderMaterial(); + + kx_blmat->Initialize(scene, bl_mat, skinMesh, lightlayer); + polymat = static_cast<RAS_IPolyMaterial*>(kx_blmat); } else { /* do Texture Face materials */ Image* bima = (tface)? (Image*)tface->tpage: NULL; - STR_String imastr = (tface)? (bima? (bima)->id.name : "" ) : ""; + imastr = (tface)? (bima? (bima)->id.name : "" ) : ""; char transp=0; short mode=0, tile=0; @@ -956,9 +968,12 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* bool alpha = (transp == TF_ALPHA || transp == TF_ADD); bool zsort = (mode & TF_ALPHASORT)? alpha: 0; - polymat = new KX_PolygonMaterial(imastr, ma, + if (kx_polymat == NULL) + kx_polymat = new KX_PolygonMaterial(); + kx_polymat->Initialize(imastr, ma, (int)mface->mat_nr, tile, tilexrep, tileyrep, mode, transp, alpha, zsort, lightlayer, tface, (unsigned int*)mcol); + polymat = static_cast<RAS_IPolyMaterial*>(kx_polymat); if (ma) { polymat->m_specular = MT_Vector3(ma->specr, ma->specg, ma->specb)*ma->spec; @@ -983,15 +998,17 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* converter->RegisterPolyMaterial(polymat); if(converter->GetMaterials()) { converter->RegisterBlenderMaterial(bl_mat); + // the poly material has been stored in the bucket, next time we must create a new one + bl_mat = NULL; + kx_blmat = NULL; + } else { + // the poly material has been stored in the bucket, next time we must create a new one + kx_polymat = NULL; } } 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(); + // keep the material pointers, they will be reused for next face } int nverts = (mface->v4)? 4: 3; @@ -1028,14 +1045,21 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, RAS_IRenderTools* // pre calculate texture generation for(list<RAS_MeshMaterial>::iterator mit = meshobj->GetFirstMaterial(); mit != meshobj->GetLastMaterial(); ++ mit) { - mit->m_bucket->GetPolyMaterial()->OnConstruction(); + mit->m_bucket->GetPolyMaterial()->OnConstruction(lightlayer); } if (layers) delete []layers; dm->release(dm); - + // cleanup material + if (bl_mat) + delete bl_mat; + if (kx_blmat) + delete kx_blmat; + if (kx_polymat) + delete kx_polymat; + converter->RegisterGameMesh(meshobj, mesh); return meshobj; } @@ -1228,18 +1252,34 @@ static void my_tex_space_mesh(Mesh *me) } -static void my_get_local_bounds(Object *ob, float *center, float *size) +static void my_get_local_bounds(Object *ob, DerivedMesh *dm, float *center, float *size) { BoundBox *bb= NULL; /* uses boundbox, function used by Ketsji */ switch (ob->type) { case OB_MESH: - bb= ( (Mesh *)ob->data )->bb; - if(bb==0) + if (dm) + { + float min_r[3], max_r[3]; + INIT_MINMAX(min_r, max_r); + dm->getMinMax(dm, min_r, max_r); + size[0]= 0.5*fabs(max_r[0] - min_r[0]); + size[1]= 0.5*fabs(max_r[1] - min_r[1]); + size[2]= 0.5*fabs(max_r[2] - min_r[2]); + + center[0]= 0.5*(max_r[0] + min_r[0]); + center[1]= 0.5*(max_r[1] + min_r[1]); + center[2]= 0.5*(max_r[2] + min_r[2]); + return; + } else { - my_tex_space_mesh((struct Mesh *)ob->data); bb= ( (Mesh *)ob->data )->bb; + if(bb==0) + { + my_tex_space_mesh((struct Mesh *)ob->data); + bb= ( (Mesh *)ob->data )->bb; + } } break; case OB_CURVE: @@ -1297,8 +1337,15 @@ void BL_CreateGraphicObjectNew(KX_GameObject* gameobj, gameobj->SetGraphicController(ctrl); ctrl->setNewClientInfo(gameobj->getClientInfo()); ctrl->setLocalAabb(localAabbMin, localAabbMax); - if (isActive) - env->addCcdGraphicController(ctrl); + if (isActive) { + // add first, this will create the proxy handle, only if the object is visible + if (gameobj->GetVisible()) + env->addCcdGraphicController(ctrl); + // update the mesh if there is a deformer, this will also update the bounding box for modifiers + RAS_Deformer* deformer = gameobj->GetDeformer(); + if (deformer) + deformer->UpdateBuckets(); + } } break; #endif @@ -1334,10 +1381,11 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, } bool isCompoundChild = false; + bool hasCompoundChildren = !parent && (blenderobject->gameflag & OB_CHILD); - if (parent && (parent->gameflag & OB_DYNAMIC)) { + if (parent/* && (parent->gameflag & OB_DYNAMIC)*/) { - if ((parent->gameflag & OB_CHILD) != 0) + if ((parent->gameflag & OB_CHILD) != 0 && (blenderobject->gameflag & OB_CHILD)) { isCompoundChild = true; } @@ -1363,14 +1411,26 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_lockZRotaxis = (blenderobject->gameflag2 & OB_LOCK_RIGID_BODY_Z_ROT_AXIS) !=0; objprop.m_isCompoundChild = isCompoundChild; - objprop.m_hasCompoundChildren = (blenderobject->gameflag & OB_CHILD) != 0; + objprop.m_hasCompoundChildren = hasCompoundChildren; objprop.m_margin = blenderobject->margin; + // ACTOR is now a separate feature objprop.m_isactor = (blenderobject->gameflag & OB_ACTOR)!=0; objprop.m_dyna = (blenderobject->gameflag & OB_DYNAMIC) != 0; objprop.m_softbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0; objprop.m_angular_rigidbody = (blenderobject->gameflag & OB_RIGID_BODY) != 0; + ///contact processing threshold is only for rigid bodies and static geometry, not 'dynamic' + if (objprop.m_angular_rigidbody || !objprop.m_dyna ) + { + objprop.m_contactProcessingThreshold = blenderobject->m_contactProcessingThreshold; + } else + { + objprop.m_contactProcessingThreshold = 0.f; + } + + objprop.m_sensor = (blenderobject->gameflag & OB_SENSOR) != 0; + if (objprop.m_softbody) { ///for game soft bodies @@ -1411,7 +1471,9 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_soft_kAHR= blenderobject->bsoft->kAHR; /* Anchors hardness [0,1] */ objprop.m_soft_collisionflags= blenderobject->bsoft->collisionflags; /* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */ objprop.m_soft_numclusteriterations= blenderobject->bsoft->numclusteriterations; /* number of iterations to refine collision clusters*/ - + objprop.m_soft_welding = blenderobject->bsoft->welding; /* welding */ + objprop.m_margin = blenderobject->bsoft->margin; + objprop.m_contactProcessingThreshold = 0.f; } else { objprop.m_gamesoftFlag = OB_BSB_BENDING_CONSTRAINTS | OB_BSB_SHAPE_MATCHING | OB_BSB_AERO_VPOINT; @@ -1450,6 +1512,9 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, objprop.m_soft_kAHR= 0.7f; objprop.m_soft_collisionflags= OB_BSB_COL_SDF_RS + OB_BSB_COL_VF_SS; objprop.m_soft_numclusteriterations= 16; + objprop.m_soft_welding = 0.f; + objprop.m_margin = 0.f; + objprop.m_contactProcessingThreshold = 0.f; } } @@ -1469,7 +1534,10 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, } KX_BoxBounds bb; - my_get_local_bounds(blenderobject,objprop.m_boundobject.box.m_center,bb.m_extends); + DerivedMesh* dm = NULL; + if (gameobj->GetDeformer()) + dm = gameobj->GetDeformer()->GetFinalMesh(); + my_get_local_bounds(blenderobject,dm,objprop.m_boundobject.box.m_center,bb.m_extends); if (blenderobject->gameflag & OB_BOUNDS) { switch (blenderobject->boundtype) @@ -1521,12 +1589,13 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, } - if (parent && (parent->gameflag & OB_DYNAMIC)) { - + if (parent/* && (parent->gameflag & OB_DYNAMIC)*/) { + // parented object cannot be dynamic KX_GameObject *parentgameobject = converter->FindGameObject(parent); objprop.m_dynamic_parent = parentgameobject; //cannot be dynamic: objprop.m_dyna = false; + objprop.m_softbody = false; shapeprops->m_mass = 0.f; } @@ -1537,7 +1606,7 @@ void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, { #ifdef USE_BULLET case UseBullet: - KX_ConvertBulletObject(gameobj, meshobj, kxscene, shapeprops, smmaterial, &objprop); + KX_ConvertBulletObject(gameobj, meshobj, dm, kxscene, shapeprops, smmaterial, &objprop); break; #endif @@ -1612,7 +1681,7 @@ static KX_LightObject *gamelight_from_blamp(Object *ob, Lamp *la, unsigned int l static KX_Camera *gamecamera_from_bcamera(Object *ob, KX_Scene *kxscene, KX_BlenderSceneConverter *converter) { Camera* ca = static_cast<Camera*>(ob->data); - RAS_CameraData camdata(ca->lens, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, dof_camera(ob)); + RAS_CameraData camdata(ca->lens, ca->ortho_scale, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, dof_camera(ob)); KX_Camera *gamecamera; gamecamera= new KX_Camera(kxscene, KX_Scene::m_callbacks, camdata); @@ -1660,14 +1729,9 @@ static KX_GameObject *gameobject_from_blenderobject( case OB_MESH: { Mesh* mesh = static_cast<Mesh*>(ob->data); - RAS_MeshObject* meshobj = converter->FindGameMesh(mesh, ob->lay); float center[3], extents[3]; float radius = my_boundbox_mesh((Mesh*) ob->data, center, extents); - - if (!meshobj) { - meshobj = BL_ConvertMesh(mesh,ob,rendertools,kxscene,converter); - converter->RegisterGameMesh(meshobj, mesh); - } + RAS_MeshObject* meshobj = BL_ConvertMesh(mesh,ob,rendertools,kxscene,converter); // needed for python scripting kxscene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); @@ -1689,8 +1753,15 @@ static KX_GameObject *gameobject_from_blenderobject( bool bHasShapeKey = mesh->key != NULL && mesh->key->type==KEY_RELATIVE; bool bHasDvert = mesh->dvert != NULL && ob->defbase.first; bool bHasArmature = (ob->parent && ob->parent->type == OB_ARMATURE && ob->partype==PARSKEL && bHasDvert); + bool bHasModifier = BL_ModifierDeformer::HasCompatibleDeformer(ob); - if (bHasShapeKey) { + if (bHasModifier) { + BL_ModifierDeformer *dcont = new BL_ModifierDeformer((BL_DeformableGameObject *)gameobj, + blenderscene, ob, (BL_SkinMeshObject *)meshobj); + ((BL_DeformableGameObject*)gameobj)->SetDeformer(dcont); + if (bHasShapeKey && bHasArmature) + dcont->LoadShapeDrivers(ob->parent); + } else if (bHasShapeKey) { // not that we can have shape keys without dvert! BL_ShapeDeformer *dcont = new BL_ShapeDeformer((BL_DeformableGameObject*)gameobj, ob, (BL_SkinMeshObject*)meshobj); @@ -1910,8 +1981,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, int activeLayerBitInfo = blenderscene->lay; - // templist to find Root Parents (object with no parents) - CListValue* templist = new CListValue(); + // list of all object converted, active and inactive CListValue* sumolist = new CListValue(); vector<parentChildLink> vec_parent_child; @@ -2011,14 +2081,12 @@ void BL_ConvertBlenderObjects(struct Main* maggie, 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()); + SG_Callbacks callback(NULL,NULL,NULL,KX_Scene::KX_ScenegraphUpdateFunc,KX_Scene::KX_ScenegraphRescheduleFunc); + SG_Node* parentinversenode = new SG_Node(NULL,kxscene,callback); // define a normal parent relationship for this node. KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New(); @@ -2205,14 +2273,12 @@ void BL_ConvertBlenderObjects(struct Main* maggie, 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()); + SG_Callbacks callback(NULL,NULL,NULL,KX_Scene::KX_ScenegraphUpdateFunc,KX_Scene::KX_ScenegraphRescheduleFunc); + SG_Node* parentinversenode = new SG_Node(NULL,kxscene,callback); // define a normal parent relationship for this node. KX_NormalParentRelation * parent_relation = KX_NormalParentRelation::New(); @@ -2359,8 +2425,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, for ( i=0;i<childrenlist->GetCount();i++) { KX_GameObject* obj = static_cast<KX_GameObject*>(childrenlist->GetValue(i)); - if (templist->RemoveValue(obj)) - obj->Release(); if (sumolist->RemoveValue(obj)) obj->Release(); if (logicbrick_conversionlist->RemoveValue(obj)) @@ -2416,16 +2480,49 @@ void BL_ConvertBlenderObjects(struct Main* maggie, vec_parent_child.clear(); // find 'root' parents (object that has not parents in SceneGraph) - for (i=0;i<templist->GetCount();++i) + for (i=0;i<sumolist->GetCount();++i) { - KX_GameObject* gameobj = (KX_GameObject*) templist->GetValue(i); + KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); if (gameobj->GetSGNode()->GetSGParent() == 0) { parentlist->Add(gameobj->AddRef()); gameobj->NodeUpdateGS(0); } } - + + // create graphic controller for culling + if (kxscene->GetDbvtCulling()) + { + bool occlusion = false; + for (i=0; i<sumolist->GetCount();i++) + { + KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); + if (gameobj->GetMeshCount() > 0) + { + MT_Point3 box[2]; + gameobj->GetSGNode()->BBox().getmm(box, MT_Transform::Identity()); + // box[0] is the min, box[1] is the max + bool isactive = objectlist->SearchValue(gameobj); + BL_CreateGraphicObjectNew(gameobj,box[0],box[1],kxscene,isactive,physics_engine); + if (gameobj->GetOccluder()) + occlusion = true; + } + } + if (occlusion) + kxscene->SetDbvtOcclusionRes(blenderscene->world->occlusionRes); + } + if (blenderscene->world) + kxscene->GetPhysicsEnvironment()->setNumTimeSubSteps(blenderscene->world->physubstep); + + // now that the scenegraph is complete, let's instantiate the deformers. + // We need that to create reusable derived mesh and physic shapes + for (i=0;i<sumolist->GetCount();++i) + { + KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); + if (gameobj->GetDeformer()) + gameobj->GetDeformer()->UpdateBuckets(); + } + bool processCompoundChildren = false; // create physics information @@ -2459,28 +2556,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,physics_engine,converter,processCompoundChildren); } - // create graphic controller for culling - if (kxscene->GetDbvtCulling()) - { - bool occlusion = false; - for (i=0; i<sumolist->GetCount();i++) - { - KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); - if (gameobj->GetMeshCount() > 0) - { - MT_Point3 box[2]; - gameobj->GetSGNode()->BBox().getmm(box, MT_Transform::Identity()); - // box[0] is the min, box[1] is the max - bool isactive = objectlist->SearchValue(gameobj); - BL_CreateGraphicObjectNew(gameobj,box[0],box[1],kxscene,isactive,physics_engine); - if (gameobj->GetOccluder()) - occlusion = true; - } - } - if (occlusion) - kxscene->SetDbvtOcclusionRes(blenderscene->world->occlusionRes); - } - //set ini linearVel and int angularVel //rcruiz if (converter->addInitFromFrame) for (i=0;i<sumolist->GetCount();i++) @@ -2566,11 +2641,8 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } } - templist->Release(); sumolist->Release(); - int executePriority=0; /* incremented by converter routines */ - // convert global sound stuff /* XXX, glob is the very very wrong place for this @@ -2601,7 +2673,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, struct Object* blenderobj = converter->FindBlenderObject(gameobj); 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); + BL_ConvertActuators(maggie->name, blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,layerMask,isInActiveLayer,rendertools,converter); } for ( i=0;i<logicbrick_conversionlist->GetCount();i++) { @@ -2609,7 +2681,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, struct Object* blenderobj = converter->FindBlenderObject(gameobj); 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); + BL_ConvertControllers(blenderobj,gameobj,logicmgr,pythondictionary,layerMask,isInActiveLayer,converter); } for ( i=0;i<logicbrick_conversionlist->GetCount();i++) { @@ -2617,7 +2689,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, struct Object* blenderobj = converter->FindBlenderObject(gameobj); int layerMask = (groupobj.find(blenderobj) == groupobj.end()) ? activeLayerBitInfo : 0; bool isInActiveLayer = (blenderobj->lay & layerMask)!=0; - BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,keydev,executePriority,layerMask,isInActiveLayer,canvas,converter); + BL_ConvertSensors(blenderobj,gameobj,logicmgr,kxscene,ketsjiEngine,keydev,layerMask,isInActiveLayer,canvas,converter); // set the init state to all objects gameobj->SetInitState((blenderobj->init_state)?blenderobj->init_state:blenderobj->state); } diff --git a/source/gameengine/Converter/BL_DeformableGameObject.cpp b/source/gameengine/Converter/BL_DeformableGameObject.cpp index e2610d2b405..cb882f31e80 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.cpp +++ b/source/gameengine/Converter/BL_DeformableGameObject.cpp @@ -30,6 +30,8 @@ #include "BL_DeformableGameObject.h" #include "BL_ShapeDeformer.h" #include "BL_ShapeActionActuator.h" +#include "RAS_MaterialBucket.h" + #ifdef HAVE_CONFIG_H #include <config.h> @@ -41,27 +43,19 @@ BL_DeformableGameObject::~BL_DeformableGameObject() delete m_pDeformer; // __NLA : Temporary until we decide where to put this } -void BL_DeformableGameObject::ProcessReplica(KX_GameObject* replica) +void BL_DeformableGameObject::ProcessReplica() { - BL_MeshDeformer *deformer; - KX_GameObject::ProcessReplica(replica); - - if (m_pDeformer) { - deformer = (BL_MeshDeformer*)m_pDeformer->GetReplica(replica); - ((BL_DeformableGameObject*)replica)->m_pDeformer = deformer; - } + KX_GameObject::ProcessReplica(); + if (m_pDeformer) + m_pDeformer= (BL_MeshDeformer*)m_pDeformer->GetReplica(); } CValue* BL_DeformableGameObject::GetReplica() { BL_DeformableGameObject* replica = new BL_DeformableGameObject(*this);//m_float,GetName()); - - // this will copy properties and so on... - CValue::AddDataToReplica(replica); - - ProcessReplica(replica); + replica->ProcessReplica(); return replica; } @@ -109,3 +103,14 @@ bool BL_DeformableGameObject::GetShape(vector<float> &shape) return !shape.empty(); } +void BL_DeformableGameObject::SetDeformer(class RAS_Deformer* deformer) +{ + m_pDeformer = deformer; + + SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots); + for(mit.begin(); !mit.end(); ++mit) + { + (*mit)->SetDeformer(deformer); + } +} + diff --git a/source/gameengine/Converter/BL_DeformableGameObject.h b/source/gameengine/Converter/BL_DeformableGameObject.h index 126a1fcb1e7..b20b8e81b37 100644 --- a/source/gameengine/Converter/BL_DeformableGameObject.h +++ b/source/gameengine/Converter/BL_DeformableGameObject.h @@ -62,7 +62,7 @@ public: m_pDeformer->Relink (map); KX_GameObject::Relink(map); }; - void ProcessReplica(KX_GameObject* replica); + void ProcessReplica(); BL_DeformableGameObject(Object* blendobj, void* sgReplicationInfo, SG_Callbacks callbacks) : KX_GameObject(sgReplicationInfo,callbacks), @@ -83,10 +83,7 @@ public: return (m_pDeformer) ? ((BL_MeshDeformer*)m_pDeformer)->GetMesh()->key : NULL; } - virtual void SetDeformer(class RAS_Deformer* deformer) - { - m_pDeformer = deformer; - } + virtual void SetDeformer(class RAS_Deformer* deformer); virtual class RAS_Deformer* GetDeformer() { return m_pDeformer; diff --git a/source/gameengine/Converter/BL_MeshDeformer.cpp b/source/gameengine/Converter/BL_MeshDeformer.cpp index 80112346c72..d7012abe316 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.cpp +++ b/source/gameengine/Converter/BL_MeshDeformer.cpp @@ -47,6 +47,7 @@ #include "GEN_Map.h" #include "STR_HashedString.h" +#include "BLI_arithb.h" bool BL_MeshDeformer::Apply(RAS_IPolyMaterial*) { @@ -90,6 +91,15 @@ BL_MeshDeformer::~BL_MeshDeformer() delete [] m_transnors; } +void BL_MeshDeformer::ProcessReplica() +{ + m_transverts = NULL; + m_transnors = NULL; + m_tvtot = 0; + m_bDynamic=false; + m_lastDeformUpdate = -1; +} + void BL_MeshDeformer::Relink(GEN_Map<class GEN_HashedPtr, void*>*map) { void **h_obj = (*map)[m_gameobj]; @@ -133,9 +143,9 @@ void BL_MeshDeformer::RecalcNormals() RAS_TexVert& v3 = it.vertex[it.index[i+2]]; RAS_TexVert *v4 = NULL; - const float *co1 = v1.getXYZ(); - const float *co2 = v2.getXYZ(); - const float *co3 = v3.getXYZ(); + const float *co1 = m_transverts[v1.getOrigIndex()]; + const float *co2 = m_transverts[v2.getOrigIndex()]; + const float *co3 = m_transverts[v3.getOrigIndex()]; const float *co4 = NULL; /* compute face normal */ @@ -143,7 +153,7 @@ void BL_MeshDeformer::RecalcNormals() if(nvert == 4) { v4 = &it.vertex[it.index[i+3]]; - co4 = v4->getXYZ(); + co4 = m_transverts[v4->getOrigIndex()]; n1[0]= co1[0]-co3[0]; n1[1]= co1[1]-co3[1]; @@ -166,6 +176,7 @@ void BL_MeshDeformer::RecalcNormals() fnor[0]= n1[1]*n2[2] - n1[2]*n2[1]; fnor[1]= n1[2]*n2[0] - n1[0]*n2[2]; fnor[2]= n1[0]*n2[1] - n1[1]*n2[0]; + Normalize(fnor); /* add to vertices for smooth normals */ float *vn1 = m_transnors[v1.getOrigIndex()]; diff --git a/source/gameengine/Converter/BL_MeshDeformer.h b/source/gameengine/Converter/BL_MeshDeformer.h index 8de59c1cdf3..99ae5f9dea0 100644 --- a/source/gameengine/Converter/BL_MeshDeformer.h +++ b/source/gameengine/Converter/BL_MeshDeformer.h @@ -64,7 +64,9 @@ public: virtual void SetSimulatedTime(double time){}; virtual bool Apply(class RAS_IPolyMaterial *mat); virtual bool Update(void){ return false; }; - virtual RAS_Deformer* GetReplica(class KX_GameObject* replica){return NULL;}; + virtual bool UpdateBuckets(void){ return false; }; + virtual RAS_Deformer* GetReplica(){return NULL;}; + virtual void ProcessReplica(); struct Mesh* GetMesh() { return m_bmesh; }; // virtual void InitDeform(double time){}; diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp new file mode 100644 index 00000000000..80165548ff2 --- /dev/null +++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp @@ -0,0 +1,183 @@ +/** + * $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 ***** + */ + +#ifdef WIN32 +#pragma warning (disable : 4786) +#endif //WIN32 + +#include "MEM_guardedalloc.h" +#include "BL_ModifierDeformer.h" +#include "GEN_Map.h" +#include "STR_HashedString.h" +#include "RAS_IPolygonMaterial.h" +#include "BL_SkinMeshObject.h" +#include "PHY_IGraphicController.h" + +//#include "BL_ArmatureController.h" +#include "DNA_armature_types.h" +#include "DNA_action_types.h" +#include "DNA_key_types.h" +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_ipo_types.h" +#include "DNA_curve_types.h" +#include "DNA_modifier_types.h" +#include "DNA_scene_types.h" +#include "BKE_armature.h" +#include "BKE_action.h" +#include "BKE_key.h" +#include "BKE_ipo.h" +#include "MT_Point3.h" + +extern "C"{ + #include "BKE_customdata.h" + #include "BKE_DerivedMesh.h" + #include "BKE_lattice.h" + #include "BKE_modifier.h" +} + #include "BKE_utildefines.h" + +#include "BLI_blenlib.h" +#include "BLI_arithb.h" + +#define __NLA_DEFNORMALS +//#undef __NLA_DEFNORMALS + + +BL_ModifierDeformer::~BL_ModifierDeformer() +{ + if (m_dm) { + // deformedOnly is used as a user counter + if (--m_dm->deformedOnly == 0) { + m_dm->needsFree = 1; + m_dm->release(m_dm); + } + } +}; + +RAS_Deformer *BL_ModifierDeformer::GetReplica() +{ + BL_ModifierDeformer *result; + + result = new BL_ModifierDeformer(*this); + result->ProcessReplica(); + return result; +} + +void BL_ModifierDeformer::ProcessReplica() +{ + /* Note! - This is not inherited from PyObjectPlus */ + BL_ShapeDeformer::ProcessReplica(); + if (m_dm) + // by default try to reuse mesh, deformedOnly is used as a user count + m_dm->deformedOnly++; + // this will force an update and if the mesh cannot be reused, a new one will be created + m_lastModifierUpdate = -1; +} + +bool BL_ModifierDeformer::HasCompatibleDeformer(Object *ob) +{ + if (!ob->modifiers.first) + return false; + // soft body cannot use mesh modifiers + if ((ob->gameflag & OB_SOFT_BODY) != 0) + return false; + ModifierData* md; + for (md = (ModifierData*)ob->modifiers.first; md; md = (ModifierData*)md->next) { + if (modifier_dependsOnTime(md)) + continue; + if (!(md->mode & eModifierMode_Realtime)) + continue; + return true; + } + return false; +} + +bool BL_ModifierDeformer::Update(void) +{ + bool bShapeUpdate = BL_ShapeDeformer::Update(); + + if (bShapeUpdate || m_lastModifierUpdate != m_gameobj->GetLastFrame()) { + // static derived mesh are not updated + if (m_dm == NULL || m_bDynamic) { + /* execute the modifiers */ + Object* blendobj = m_gameobj->GetBlendObject(); + /* hack: the modifiers require that the mesh is attached to the object + It may not be the case here because of replace mesh actuator */ + Mesh *oldmesh = (Mesh*)blendobj->data; + blendobj->data = m_bmesh; + /* execute the modifiers */ + DerivedMesh *dm = mesh_create_derived_no_virtual(m_scene, blendobj, m_transverts, CD_MASK_MESH); + /* restore object data */ + blendobj->data = oldmesh; + /* free the current derived mesh and replace, (dm should never be NULL) */ + if (m_dm != NULL) { + // HACK! use deformedOnly as a user counter + if (--m_dm->deformedOnly == 0) { + m_dm->needsFree = 1; + m_dm->release(m_dm); + } + } + m_dm = dm; + // get rid of temporary data + m_dm->needsFree = 0; + m_dm->release(m_dm); + // HACK! use deformedOnly as a user counter + m_dm->deformedOnly = 1; + /* update the graphic controller */ + PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController(); + if (ctrl) { + float min_r[3], max_r[3]; + INIT_MINMAX(min_r, max_r); + m_dm->getMinMax(m_dm, min_r, max_r); + ctrl->setLocalAabb(min_r, max_r); + } + } + m_lastModifierUpdate=m_gameobj->GetLastFrame(); + bShapeUpdate = true; + } + return bShapeUpdate; +} + +bool BL_ModifierDeformer::Apply(RAS_IPolyMaterial *mat) +{ + if (!Update()) + return false; + + // drawing is based on derived mesh, must set it in the mesh slots + int nmat = m_pMeshObject->NumMaterials(); + for (int imat=0; imat<nmat; imat++) { + RAS_MeshMaterial *mmat = m_pMeshObject->GetMeshMaterial(imat); + RAS_MeshSlot **slot = mmat->m_slots[(void*)m_gameobj]; + if(!slot || !*slot) + continue; + (*slot)->m_pDerivedMesh = m_dm; + } + return true; +} diff --git a/source/gameengine/Converter/BL_ModifierDeformer.h b/source/gameengine/Converter/BL_ModifierDeformer.h new file mode 100644 index 00000000000..b09cc2087ca --- /dev/null +++ b/source/gameengine/Converter/BL_ModifierDeformer.h @@ -0,0 +1,107 @@ +/** + * $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 BL_MODIFIERDEFORMER +#define BL_MODIFIERDEFORMER + +#ifdef WIN32 +#pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning +#endif //WIN32 + +#include "BL_ShapeDeformer.h" +#include "BL_DeformableGameObject.h" +#include <vector> + +struct DerivedMesh; +struct Object; + +class BL_ModifierDeformer : public BL_ShapeDeformer +{ +public: + static bool HasCompatibleDeformer(Object *ob); + + + BL_ModifierDeformer(BL_DeformableGameObject *gameobj, + Scene *scene, + Object *bmeshobj, + BL_SkinMeshObject *mesh) + : + BL_ShapeDeformer(gameobj,bmeshobj, mesh), + m_lastModifierUpdate(-1), + m_scene(scene), + m_dm(NULL) + { + m_recalcNormal = false; + }; + + /* this second constructor is needed for making a mesh deformable on the fly. */ + BL_ModifierDeformer(BL_DeformableGameObject *gameobj, + struct Scene *scene, + struct Object *bmeshobj_old, + struct Object *bmeshobj_new, + class BL_SkinMeshObject *mesh, + bool release_object, + BL_ArmatureObject* arma = NULL) + : + BL_ShapeDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, false, arma), + m_lastModifierUpdate(-1), + m_scene(scene), + m_dm(NULL) + { + }; + + virtual void ProcessReplica(); + virtual RAS_Deformer *GetReplica(); + virtual ~BL_ModifierDeformer(); + virtual bool UseVertexArray() + { + return false; + } + + bool Update (void); + bool Apply(RAS_IPolyMaterial *mat); + void ForceUpdate() + { + m_lastModifierUpdate = -1.0; + }; + virtual struct DerivedMesh* GetFinalMesh() + { + return m_dm; + } + + +protected: + double m_lastModifierUpdate; + Scene *m_scene; + DerivedMesh *m_dm; + +}; + +#endif + diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index b0c9e0f5694..7aa8714de3a 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -61,6 +61,7 @@ BL_ShapeActionActuator::~BL_ShapeActionActuator() void BL_ShapeActionActuator::ProcessReplica() { + SCA_IActuator::ProcessReplica(); m_localtime=m_startframe; m_lastUpdate=-1; } @@ -74,9 +75,6 @@ CValue* BL_ShapeActionActuator::GetReplica() { BL_ShapeActionActuator* replica = new BL_ShapeActionActuator(*this);//m_float,GetName()); replica->ProcessReplica(); - - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; } @@ -162,16 +160,9 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame) // maybe there are events for us in the queue ! if (frame) { - for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++) - { - if ((*i)->GetNumber() == 0.0f) - bNegativeEvent = true; - else - bPositiveEvent= true; - (*i)->Release(); - - } - m_events.clear(); + bNegativeEvent = m_negevent; + bPositiveEvent = m_posevent; + RemoveAllEvents(); if (bPositiveEvent) m_flag |= ACT_FLAG_ACTIVE; @@ -420,8 +411,13 @@ bool BL_ShapeActionActuator::Update(double curtime, bool frame) /* Integration hooks ------------------------------------------------------- */ PyTypeObject BL_ShapeActionActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "BL_ShapeActionActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -471,16 +467,16 @@ PyMethodDef BL_ShapeActionActuator::Methods[] = { }; PyAttributeDef BL_ShapeActionActuator::Attributes[] = { - KX_PYATTRIBUTE_FLOAT_RW("start", 0, MAXFRAMEF, BL_ShapeActionActuator, m_startframe), - KX_PYATTRIBUTE_FLOAT_RW("end", 0, MAXFRAMEF, BL_ShapeActionActuator, m_endframe), - KX_PYATTRIBUTE_FLOAT_RW("blendin", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendin), + KX_PYATTRIBUTE_FLOAT_RW("frameStart", 0, MAXFRAMEF, BL_ShapeActionActuator, m_startframe), + KX_PYATTRIBUTE_FLOAT_RW("frameEnd", 0, MAXFRAMEF, BL_ShapeActionActuator, m_endframe), + KX_PYATTRIBUTE_FLOAT_RW("blendIn", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendin), KX_PYATTRIBUTE_RW_FUNCTION("action", BL_ShapeActionActuator, pyattr_get_action, pyattr_set_action), KX_PYATTRIBUTE_SHORT_RW("priority", 0, 100, false, BL_ShapeActionActuator, m_priority), KX_PYATTRIBUTE_FLOAT_RW_CHECK("frame", 0, MAXFRAMEF, BL_ShapeActionActuator, m_localtime, CheckFrame), - KX_PYATTRIBUTE_STRING_RW("property", 0, 31, false, BL_ShapeActionActuator, m_propname), - KX_PYATTRIBUTE_STRING_RW("frameProperty", 0, 31, false, BL_ShapeActionActuator, m_framepropname), + KX_PYATTRIBUTE_STRING_RW("propName", 0, 31, false, BL_ShapeActionActuator, m_propname), + KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 31, false, BL_ShapeActionActuator, m_framepropname), KX_PYATTRIBUTE_FLOAT_RW_CHECK("blendTime", 0, MAXFRAMEF, BL_ShapeActionActuator, m_blendframe, CheckBlendTime), - KX_PYATTRIBUTE_SHORT_RW_CHECK("type",0,100,false,BL_ShapeActionActuator,m_playtype,CheckType), + KX_PYATTRIBUTE_SHORT_RW_CHECK("mode",0,100,false,BL_ShapeActionActuator,m_playtype,CheckType), { NULL } //Sentinel }; @@ -489,6 +485,10 @@ PyObject* BL_ShapeActionActuator::py_getattro(PyObject* attr) { py_getattro_up(SCA_IActuator); } +PyObject* BL_ShapeActionActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int BL_ShapeActionActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); } @@ -870,7 +870,7 @@ int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE if (!PyString_Check(value)) { PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, expected the string name of the action"); - return -1; + return PY_SET_ATTR_FAIL; } bAction *action= NULL; @@ -882,11 +882,11 @@ int BL_ShapeActionActuator::pyattr_set_action(void *self_v, const KX_PYATTRIBUTE if (action==NULL) { PyErr_SetString(PyExc_ValueError, "actuator.action = val: Shape Action Actuator, action not found!"); - return 1; + return PY_SET_ATTR_FAIL; } } self->SetAction(action); - return 0; + return PY_SET_ATTR_SUCCESS; } diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.h b/source/gameengine/Converter/BL_ShapeActionActuator.h index 3bc35ac9495..d268eef6d23 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.h +++ b/source/gameengine/Converter/BL_ShapeActionActuator.h @@ -107,6 +107,7 @@ public: KX_PYMETHOD_DOC_VARARGS(BL_ShapeActionActuator,SetType); virtual PyObject* py_getattro(PyObject* attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject* attr, PyObject* value); static PyObject* pyattr_get_action(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Converter/BL_ShapeDeformer.cpp b/source/gameengine/Converter/BL_ShapeDeformer.cpp index 8be612503bc..d39917b0e5c 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.cpp +++ b/source/gameengine/Converter/BL_ShapeDeformer.cpp @@ -68,7 +68,7 @@ BL_ShapeDeformer::~BL_ShapeDeformer() { }; -RAS_Deformer *BL_ShapeDeformer::GetReplica(class KX_GameObject* replica) +RAS_Deformer *BL_ShapeDeformer::GetReplica() { BL_ShapeDeformer *result; @@ -79,6 +79,8 @@ RAS_Deformer *BL_ShapeDeformer::GetReplica(class KX_GameObject* replica) void BL_ShapeDeformer::ProcessReplica() { + BL_SkinDeformer::ProcessReplica(); + m_lastShapeUpdate = -1; } bool BL_ShapeDeformer::LoadShapeDrivers(Object* arma) @@ -87,7 +89,7 @@ bool BL_ShapeDeformer::LoadShapeDrivers(Object* arma) m_shapeDrivers.clear(); // check if this mesh has armature driven shape keys - if (m_bmesh->key->ipo) { + if (m_bmesh->key && m_bmesh->key->ipo) { for(icu= (IpoCurve*)m_bmesh->key->ipo->curve.first; icu; icu= (IpoCurve*)icu->next) { if(icu->driver && (icu->flag & IPO_MUTE) == 0 && @@ -125,7 +127,7 @@ bool BL_ShapeDeformer::ExecuteShapeDrivers(void) ForceUpdate(); m_armobj->RestorePose(); - + m_bDynamic = true; return true; } return false; @@ -147,7 +149,11 @@ bool BL_ShapeDeformer::Update(void) m_pMeshObject->CheckWeightCache(blendobj); /* we will blend the key directly in mvert array: it is used by armature as the start position */ - do_rel_key(0, m_bmesh->totvert, m_bmesh->totvert, (char *)m_bmesh->mvert->co, m_bmesh->key, 0); + /* m_bmesh->key can be NULL in case of Modifier deformer */ + if (m_bmesh->key) { + do_rel_key(0, m_bmesh->totvert, m_bmesh->totvert, (char *)m_bmesh->mvert->co, m_bmesh->key, 0); + m_bDynamic = true; + } // Don't release the weight array as in Blender, it will most likely be reusable on next frame // The weight array are ultimately deleted when the skin mesh is destroyed @@ -163,7 +169,8 @@ bool BL_ShapeDeformer::Update(void) // check for armature deform bSkinUpdate = BL_SkinDeformer::Update(); - if (!bSkinUpdate && bShapeUpdate) { + // non dynamic deformer = Modifer without armature and shape keys, no need to create storage + if (!bSkinUpdate && bShapeUpdate && m_bDynamic) { // this means that there is no armature, we still need to copy the vertex to m_transverts // and update the normal (was not done after shape key calculation) @@ -174,7 +181,8 @@ bool BL_ShapeDeformer::Update(void) VECCOPY(m_transverts[v], m_bmesh->mvert[v].co); #ifdef __NLA_DEFNORMALS - RecalcNormals(); + if (m_recalcNormal) + RecalcNormals(); #endif bSkinUpdate = true; } diff --git a/source/gameengine/Converter/BL_ShapeDeformer.h b/source/gameengine/Converter/BL_ShapeDeformer.h index 90b9f5caea1..949e5e1e3ad 100644 --- a/source/gameengine/Converter/BL_ShapeDeformer.h +++ b/source/gameengine/Converter/BL_ShapeDeformer.h @@ -58,15 +58,16 @@ public: struct Object *bmeshobj_new, class BL_SkinMeshObject *mesh, bool release_object, + bool recalc_normal, BL_ArmatureObject* arma = NULL) : - BL_SkinDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, arma), + BL_SkinDeformer(gameobj, bmeshobj_old, bmeshobj_new, mesh, release_object, recalc_normal, arma), m_lastShapeUpdate(-1) { }; + virtual RAS_Deformer *GetReplica(); virtual void ProcessReplica(); - virtual RAS_Deformer *GetReplica(class KX_GameObject* replica); virtual ~BL_ShapeDeformer(); bool Update (void); diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index d8563763954..a13f78e1b27 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -65,9 +65,10 @@ BL_SkinDeformer::BL_SkinDeformer(BL_DeformableGameObject *gameobj, BL_MeshDeformer(gameobj, bmeshobj, mesh), m_armobj(arma), m_lastArmaUpdate(-1), - m_defbase(&bmeshobj->defbase), + //m_defbase(&bmeshobj->defbase), m_releaseobject(false), - m_poseApplied(false) + m_poseApplied(false), + m_recalcNormal(true) { Mat4CpyMat4(m_obmat, bmeshobj->obmat); }; @@ -78,12 +79,14 @@ BL_SkinDeformer::BL_SkinDeformer( struct Object *bmeshobj_new, // Blender object that owns the original mesh class BL_SkinMeshObject *mesh, bool release_object, + bool recalc_normal, BL_ArmatureObject* arma) : BL_MeshDeformer(gameobj, bmeshobj_old, mesh), m_armobj(arma), m_lastArmaUpdate(-1), - m_defbase(&bmeshobj_old->defbase), - m_releaseobject(release_object) + //m_defbase(&bmeshobj_old->defbase), + m_releaseobject(release_object), + m_recalcNormal(recalc_normal) { // this is needed to ensure correct deformation of mesh: // the deformation is done with Blender's armature_deform_verts() function @@ -105,7 +108,7 @@ void BL_SkinDeformer::Relink(GEN_Map<class GEN_HashedPtr, void*>*map) void **h_obj = (*map)[m_armobj]; if (h_obj) - SetArmature( (BL_ArmatureObject*)(*h_obj) ); + m_armobj = (BL_ArmatureObject*)(*h_obj); else m_armobj=NULL; } @@ -118,45 +121,53 @@ bool BL_SkinDeformer::Apply(RAS_IPolyMaterial *mat) RAS_MeshSlot::iterator it; RAS_MeshMaterial *mmat; RAS_MeshSlot *slot; - size_t i; + size_t i, nmat, imat; // update the vertex in m_transverts - Update(); - - // 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. - mmat = m_pMeshObject->GetMeshMaterial(mat); - if(!mmat->m_slots[(void*)m_gameobj]) - return true; - - slot = *mmat->m_slots[(void*)m_gameobj]; - - // for each array - for(slot->begin(it); !slot->end(it); slot->next(it)) { - // for each vertex - // copy the untransformed data from the original mvert - for(i=it.startvertex; i<it.endvertex; i++) { - RAS_TexVert& v = it.vertex[i]; - v.SetXYZ(m_transverts[v.getOrigIndex()]); + if (!Update()) + return false; + + if (m_transverts) { + // the vertex cache is unique to this deformer, no need to update it + // if it wasn't updated! We must update all the materials at once + // because we will not get here again for the other material + nmat = m_pMeshObject->NumMaterials(); + for (imat=0; imat<nmat; imat++) { + mmat = m_pMeshObject->GetMeshMaterial(imat); + if(!mmat->m_slots[(void*)m_gameobj]) + continue; + + slot = *mmat->m_slots[(void*)m_gameobj]; + + // for each array + for(slot->begin(it); !slot->end(it); slot->next(it)) { + // for each vertex + // copy the untransformed data from the original mvert + for(i=it.startvertex; i<it.endvertex; i++) { + RAS_TexVert& v = it.vertex[i]; + v.SetXYZ(m_transverts[v.getOrigIndex()]); + } + } } } - return true; } -RAS_Deformer *BL_SkinDeformer::GetReplica(class KX_GameObject* replica) +RAS_Deformer *BL_SkinDeformer::GetReplica() { BL_SkinDeformer *result; result = new BL_SkinDeformer(*this); + /* there is m_armobj that must be fixed but we cannot do it now, it will be done in Relink */ result->ProcessReplica(); return result; } void BL_SkinDeformer::ProcessReplica() { + BL_MeshDeformer::ProcessReplica(); + m_lastArmaUpdate = -1; + m_releaseobject = false; } //void where_is_pose (Object *ob); @@ -191,14 +202,16 @@ bool BL_SkinDeformer::Update(void) Mat4CpyMat4(m_objMesh->obmat, obmat); #ifdef __NLA_DEFNORMALS - RecalcNormals(); + if (m_recalcNormal) + RecalcNormals(); #endif /* Update the current frame */ m_lastArmaUpdate=m_armobj->GetLastFrame(); m_armobj->RestorePose(); - + /* dynamic vertex, cannot use display list */ + m_bDynamic = true; /* 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 f87860021c6..7c43246a9d7 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.h +++ b/source/gameengine/Converter/BL_SkinDeformer.h @@ -64,13 +64,20 @@ public: struct Object *bmeshobj_new, class BL_SkinMeshObject *mesh, bool release_object, + bool recalc_normal, BL_ArmatureObject* arma = NULL); + virtual RAS_Deformer *GetReplica(); virtual void ProcessReplica(); - virtual RAS_Deformer *GetReplica(class KX_GameObject* replica); + virtual ~BL_SkinDeformer(); bool Update (void); bool Apply (class RAS_IPolyMaterial *polymat); + bool UpdateBuckets(void) + { + // update the deformer and all the mesh slots; Apply() does it well, so just call it. + return Apply(NULL); + } bool PoseUpdated(void) { if (m_armobj && m_lastArmaUpdate!=m_armobj->GetLastFrame()) { @@ -83,15 +90,20 @@ public: { m_lastArmaUpdate = -1.0; }; + virtual bool ShareVertexArray() + { + return false; + } protected: BL_ArmatureObject* m_armobj; // Our parent object float m_time; double m_lastArmaUpdate; - ListBase* m_defbase; + //ListBase* m_defbase; float m_obmat[4][4]; // the reference matrix for skeleton deform bool m_releaseobject; bool m_poseApplied; + bool m_recalcNormal; }; diff --git a/source/gameengine/Converter/BL_SkinMeshObject.cpp b/source/gameengine/Converter/BL_SkinMeshObject.cpp index eb3f9d0588d..0a18296f261 100644 --- a/source/gameengine/Converter/BL_SkinMeshObject.cpp +++ b/source/gameengine/Converter/BL_SkinMeshObject.cpp @@ -87,7 +87,7 @@ void BL_SkinMeshObject::UpdateBuckets(void* clientobj,double* oglmatrix,bool use continue; RAS_MeshSlot *slot = *it->m_slots[clientobj]; - slot->m_pDeformer = ((BL_DeformableGameObject*)clientobj)->GetDeformer(); + slot->SetDeformer(((BL_DeformableGameObject*)clientobj)->GetDeformer()); } RAS_MeshObject::UpdateBuckets(clientobj, oglmatrix, useObjectColor, rgbavec, visible, culled); diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 60cf6a4a8ee..b13e3f7cadb 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -87,6 +87,7 @@ extern "C" //XXX #include "BSE_editipo_types.h" #include "DNA_ipo_types.h" #include "BKE_global.h" +#include "BKE_ipo.h" // eval_icu #include "DNA_space_types.h" } @@ -549,12 +550,12 @@ void KX_BlenderSceneConverter::RegisterGameMesh( RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh( - struct Mesh *for_blendermesh, - unsigned int onlayer) + struct Mesh *for_blendermesh/*, + unsigned int onlayer*/) { RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)]; - if (meshp && onlayer==(*meshp)->GetLightLayer()) { + if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) { return *meshp; } else { return NULL; @@ -668,7 +669,9 @@ extern "C" //XXX struct IpoCurve *verify_ipocurve(struct ID *, short, char *, char *, char *, int); //XXX void testhandles_ipocurve(struct IpoCurve *icu); void insert_vert_icu(struct IpoCurve *, float, float, short); - void Mat3ToEul(float tmat[][3], float *eul); + float eval_icu(struct IpoCurve *icu, float ipotime); + //void Mat3ToEul(float tmat[][3], float *eul); + void Mat3ToCompatibleEul(float mat[][3], float *eul, float *oldrot); } IpoCurve* findIpoCurve(IpoCurve* first, const char* searchName) @@ -818,7 +821,6 @@ void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo(){ } } -#define TEST_HANDLES_GAME2IPO 0 ///this generates ipo curves for position, rotation, allowing to use game physics in animation void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) @@ -842,138 +844,83 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); Object* blenderObject = FindBlenderObject(gameObj); - if (blenderObject) + if (blenderObject && blenderObject->ipo) { - + const MT_Point3& position = gameObj->NodeGetWorldPosition(); + //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); + float eulerAngles[3]; + float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f}; float tmat[3][3]; - for (int r=0;r<3;r++) - { - for (int c=0;c<3;c++) - { - tmat[r][c] = orn[c][r]; - } - } - Mat3ToEul(tmat, eulerAngles); - - for(int x = 0; x < 3; x++) { - eulerAngles[x] *= (float) (180 / 3.14159265f); - } - - eulerAngles[0]/=10.f; - eulerAngles[1]/=10.f; - eulerAngles[2]/=10.f; - - - - //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - const MT_Point3& position = gameObj->NodeGetWorldPosition(); + // XXX animato +#if 0 Ipo* ipo = blenderObject->ipo; - if (ipo) - { - //create the curves, if not existing + //create the curves, if not existing, set linear if new - IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X); + IpoCurve *icu_lx = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); + if (!icu_lx) { + icu_lx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1); + if(icu_lx) icu_lx->ipo = IPO_LIN; + } + IpoCurve *icu_ly = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); + if (!icu_ly) { + icu_ly = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1); + if(icu_ly) icu_ly->ipo = IPO_LIN; + } + IpoCurve *icu_lz = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); + if (!icu_lz) { + icu_lz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1); + if(icu_lz) icu_lz->ipo = IPO_LIN; + } + IpoCurve *icu_rx = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); + if (!icu_rx) { + icu_rx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1); + if(icu_rx) icu_rx->ipo = IPO_LIN; + } + IpoCurve *icu_ry = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); + if (!icu_ry) { + icu_ry = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1); + if(icu_ry) icu_ry->ipo = IPO_LIN; + } + IpoCurve *icu_rz = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); + if (!icu_rz) { + icu_rz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1); + if(icu_rz) icu_rz->ipo = IPO_LIN; + } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y); + if(icu_rx) eulerAnglesOld[0]= eval_icu( icu_rx, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); + if(icu_ry) eulerAnglesOld[1]= eval_icu( icu_ry, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); + if(icu_rz) eulerAnglesOld[2]= eval_icu( icu_rz, frameNumber - 1 ) / ((180 / 3.14159265f) / 10); + + // orn.getValue((float *)tmat); // uses the wrong ordering, cant use this + for (int r=0;r<3;r++) + for (int c=0;c<3;c++) + tmat[r][c] = orn[c][r]; + + // Mat3ToEul(tmat, eulerAngles); // better to use Mat3ToCompatibleEul + Mat3ToCompatibleEul(tmat, eulerAngles, eulerAnglesOld); + + //eval_icu + for(int x = 0; x < 3; x++) + eulerAngles[x] *= (float) ((180 / 3.14159265f) / 10.0); - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z); - - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X); - - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y); - - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z); - - - //fill the curves with data - - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); - if (icu1) - { - float curVal = position.x(); - //XXX insert_vert_icu(icu1, frameNumber, curVal, 0); -#ifdef TEST_HANDLES_GAME2IPO - //XXX testhandles_ipocurve(icu1); -#endif - } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); - if (icu1) - { - float curVal = position.y(); - //XXX insert_vert_icu(icu1, frameNumber, curVal, 0); -#ifdef TEST_HANDLES_GAME2IPO - - //XXX testhandles_ipocurve(icu1); -#endif - } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); - if (icu1) - { - float curVal = position.z(); - //XXX insert_vert_icu(icu1, frameNumber, curVal, 0); -#ifdef TEST_HANDLES_GAME2IPO - //XXX testhandles_ipocurve(icu1); -#endif - } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); - if (icu1) - { - float curVal = eulerAngles[0]; - //XXX insert_vert_icu(icu1, frameNumber, curVal, 0); -#ifdef TEST_HANDLES_GAME2IPO - - //XXX testhandles_ipocurve(icu1); -#endif - } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); - if (icu1) - { - float curVal = eulerAngles[1]; - //XXX insert_vert_icu(icu1, frameNumber, curVal, 0); -#ifdef TEST_HANDLES_GAME2IPO - - //XXX testhandles_ipocurve(icu1); -#endif - } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); - if (icu1) - { - float curVal = eulerAngles[2]; - //XXX insert_vert_icu(icu1, frameNumber, curVal, 0); -#ifdef TEST_HANDLES_GAME2IPO - - //XXX testhandles_ipocurve(icu1); + if (icu_lx) insert_vert_icu(icu_lx, frameNumber, position.x(), 1); + if (icu_ly) insert_vert_icu(icu_ly, frameNumber, position.y(), 1); + if (icu_lz) insert_vert_icu(icu_lz, frameNumber, position.z(), 1); + if (icu_rx) insert_vert_icu(icu_rx, frameNumber, eulerAngles[0], 1); + if (icu_ry) insert_vert_icu(icu_ry, frameNumber, eulerAngles[1], 1); + if (icu_rz) insert_vert_icu(icu_rz, frameNumber, eulerAngles[2], 1); + + // Handles are corrected at the end, testhandles_ipocurve isnt needed yet #endif - - } - - } } } - } - - - } - - + } } @@ -998,100 +945,21 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController(); Object* blenderObject = FindBlenderObject(gameObj); - if (blenderObject) + if (blenderObject && blenderObject->ipo) { - - const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); - float eulerAngles[3]; - float tmat[3][3]; - for (int r=0;r<3;r++) - { - for (int c=0;c<3;c++) - { - tmat[r][c] = orn[c][r]; - } - } - Mat3ToEul(tmat, eulerAngles); - - for(int x = 0; x < 3; x++) { - eulerAngles[x] *= (float) (180 / 3.14159265f); - } - - eulerAngles[0]/=10.f; - eulerAngles[1]/=10.f; - eulerAngles[2]/=10.f; - - - - //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - //const MT_Point3& position = gameObj->NodeGetWorldPosition(); - + // XXX animato +#if 0 Ipo* ipo = blenderObject->ipo; - if (ipo) - { - - //create the curves, if not existing - - IpoCurve *icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X); - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y); - - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z); - - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X); - - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y); - - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); - //XXX if (!icu1) - //XXX icu1 = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z); - - - - //fill the curves with data - - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"); - if (icu1) - { - //XXX testhandles_ipocurve(icu1); - } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"); - if (icu1) - { - //XXX testhandles_ipocurve(icu1); - } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"); - if (icu1) - { - //XXX testhandles_ipocurve(icu1); - } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"); - if (icu1) - { - //XXX testhandles_ipocurve(icu1); - } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"); - if (icu1) - { - //XXX testhandles_ipocurve(icu1); - } - icu1 = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"); - if (icu1) - { - //XXX testhandles_ipocurve(icu1); - } - - } + //create the curves, if not existing + //testhandles_ipocurve checks for NULL + testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocX")); + testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocY")); + testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ")); + testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotX")); + testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotY")); + testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ")); +#endif } } diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h index 2317e952a0a..f7c1a506457 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.h +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h @@ -115,7 +115,7 @@ public: struct Object *FindBlenderObject(KX_GameObject *for_gameobject); void RegisterGameMesh(RAS_MeshObject *gamemesh, struct Mesh *for_blendermesh); - RAS_MeshObject *FindGameMesh(struct Mesh *for_blendermesh, unsigned int onlayer); + RAS_MeshObject *FindGameMesh(struct Mesh *for_blendermesh/*, unsigned int onlayer*/); // void RegisterSumoShape(DT_ShapeHandle shape, RAS_MeshObject *for_gamemesh); // DT_ShapeHandle FindSumoShape(RAS_MeshObject *for_gamemesh); diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index eb2d0a1c4b1..ea812a71fdd 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -38,7 +38,7 @@ #include "KX_BlenderSceneConverter.h" #include "KX_ConvertActuators.h" - +#include "SND_Scene.h" // Actuators //SCA logiclibrary native logicbricks #include "SCA_PropertyActuator.h" @@ -105,7 +105,6 @@ void BL_ConvertActuators(char* maggiename, SCA_LogicManager* logicmgr, KX_Scene* scene, KX_KetsjiEngine* ketsjiEngine, - int & executePriority, int activeLayerBitInfo, bool isInActiveLayer, RAS_IRenderTools* rendertools, @@ -114,11 +113,20 @@ void BL_ConvertActuators(char* maggiename, { int uniqueint = 0; + int actcount = 0; + int executePriority = 0; bActuator* bact = (bActuator*) blenderobject->actuators.first; + while (bact) + { + actcount++; + bact = bact->next; + } + gameobj->ReserveActuator(actcount); + bact = (bActuator*) blenderobject->actuators.first; while(bact) { STR_String uniquename = bact->name; - STR_String objectname = gameobj->GetName(); + STR_String& objectname = gameobj->GetName(); SCA_IActuator* baseact = NULL; switch (bact->type) @@ -126,6 +134,7 @@ void BL_ConvertActuators(char* maggiename, case ACT_OBJECT: { bObjectActuator* obact = (bObjectActuator*) bact->data; + KX_GameObject* obref = NULL; MT_Vector3 forcevec(KX_BLENDERTRUNC(obact->forceloc[0]), KX_BLENDERTRUNC(obact->forceloc[1]), KX_BLENDERTRUNC(obact->forceloc[2])); @@ -163,9 +172,13 @@ void BL_ConvertActuators(char* maggiename, bitLocalFlag.AngularVelocity = bool((obact->flag & ACT_ANG_VEL_LOCAL)!=0); bitLocalFlag.ServoControl = bool(obact->type == ACT_OBJECT_SERVO); bitLocalFlag.AddOrSetLinV = bool((obact->flag & ACT_ADD_LIN_VEL)!=0); - + if (obact->reference && bitLocalFlag.ServoControl) + { + obref = converter->FindGameObject(obact->reference); + } KX_ObjectActuator* tmpbaseact = new KX_ObjectActuator(gameobj, + obref, forcevec.getValue(), torquevec.getValue(), dlocvec.getValue(), @@ -941,6 +954,11 @@ void BL_ConvertActuators(char* maggiename, = (bRandomActuator *) bact->data; unsigned long seedArg = randAct->seed; + if (seedArg == 0) + { + seedArg = (int)(ketsjiEngine->GetRealTime()*100000.0); + seedArg ^= (intptr_t)randAct; + } SCA_RandomActuator::KX_RANDOMACT_MODE modeArg = SCA_RandomActuator::KX_RANDOMACT_NODEF; SCA_RandomActuator *tmprandomact; @@ -1097,7 +1115,7 @@ void BL_ConvertActuators(char* maggiename, buf = txt_to_buf(_2dfilter->text); if (buf) { - tmp->SetShaderText(STR_String(buf)); + tmp->SetShaderText(buf); MEM_freeN(buf); } } @@ -1110,6 +1128,8 @@ void BL_ConvertActuators(char* maggiename, { bParentActuator *parAct = (bParentActuator *) bact->data; int mode = KX_ParentActuator::KX_PARENT_NODEF; + bool addToCompound = true; + bool ghost = true; KX_GameObject *tmpgob = NULL; switch(parAct->type) @@ -1117,6 +1137,8 @@ void BL_ConvertActuators(char* maggiename, case ACT_PARENT_SET: mode = KX_ParentActuator::KX_PARENT_SET; tmpgob = converter->FindGameObject(parAct->ob); + addToCompound = !(parAct->flag & ACT_PARENT_COMPOUND); + ghost = !(parAct->flag & ACT_PARENT_GHOST); break; case ACT_PARENT_REMOVE: mode = KX_ParentActuator::KX_PARENT_REMOVE; @@ -1127,6 +1149,8 @@ void BL_ConvertActuators(char* maggiename, KX_ParentActuator *tmpparact = new KX_ParentActuator(gameobj, mode, + addToCompound, + ghost, tmpgob); baseact = tmpparact; break; @@ -1144,7 +1168,7 @@ void BL_ConvertActuators(char* maggiename, CIntValue* uniqueval = new CIntValue(uniqueint); uniquename += uniqueval->GetText(); uniqueval->Release(); - baseact->SetName(STR_String(bact->name)); + baseact->SetName(bact->name); //gameobj->SetProperty(uniquename,baseact); gameobj->AddActuator(baseact); diff --git a/source/gameengine/Converter/KX_ConvertActuators.h b/source/gameengine/Converter/KX_ConvertActuators.h index 03ea0db99b9..e38a9c74efc 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.h +++ b/source/gameengine/Converter/KX_ConvertActuators.h @@ -35,7 +35,6 @@ void BL_ConvertActuators(char* maggiename, class SCA_LogicManager* logicmgr, class KX_Scene* scene, class KX_KetsjiEngine* ketsjiEngine, - int & executePriority, int activeLayerBitInfo, bool isInActiveLayer, class RAS_IRenderTools* rendertools, diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp index fb100b0a68b..85ab8e4f8b8 100644 --- a/source/gameengine/Converter/KX_ConvertControllers.cpp +++ b/source/gameengine/Converter/KX_ConvertControllers.cpp @@ -76,6 +76,7 @@ LinkControllerToActuators( // Iterate through the actuators of the game blender // controller and find the corresponding ketsji actuator. + game_controller->ReserveActuator(bcontr->totlinks); for (int i=0;i<bcontr->totlinks;i++) { bActuator* bact = (bActuator*) bcontr->links[i]; @@ -92,52 +93,54 @@ void BL_ConvertControllers( class KX_GameObject* gameobj, SCA_LogicManager* logicmgr, PyObject* pythondictionary, - int &executePriority, int activeLayerBitInfo, bool isInActiveLayer, KX_BlenderSceneConverter* converter ) { int uniqueint=0; + int count = 0; + int executePriority=0; bController* bcontr = (bController*)blenderobject->controllers.first; while (bcontr) { + bcontr = bcontr->next; + count++; + } + gameobj->ReserveController(count); + bcontr = (bController*)blenderobject->controllers.first; + while (bcontr) + { SCA_IController* gamecontroller = NULL; switch(bcontr->type) { case CONT_LOGIC_AND: { gamecontroller = new SCA_ANDController(gameobj); - LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); break; } case CONT_LOGIC_OR: { gamecontroller = new SCA_ORController(gameobj); - LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); break; } case CONT_LOGIC_NAND: { gamecontroller = new SCA_NANDController(gameobj); - LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); break; } case CONT_LOGIC_NOR: { gamecontroller = new SCA_NORController(gameobj); - LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); break; } case CONT_LOGIC_XOR: { gamecontroller = new SCA_XORController(gameobj); - LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); break; } case CONT_LOGIC_XNOR: { gamecontroller = new SCA_XNORController(gameobj); - LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); break; } case CONT_EXPRESSION: @@ -147,37 +150,43 @@ void BL_ConvertControllers( if (expressiontext.Length() > 0) { gamecontroller = new SCA_ExpressionController(gameobj,expressiontext); - LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); - } break; } case CONT_PYTHON: { - - // we should create a Python controller here - - SCA_PythonController* pyctrl = new SCA_PythonController(gameobj); - gamecontroller = pyctrl; - bPythonCont* pycont = (bPythonCont*) bcontr->data; + SCA_PythonController* pyctrl = new SCA_PythonController(gameobj, pycont->mode); + gamecontroller = pyctrl; + pyctrl->SetDictionary(pythondictionary); - - if (pycont->text) - { - char *buf; - // this is some blender specific code - buf= txt_to_buf(pycont->text); - if (buf) + + if(pycont->mode==SCA_PythonController::SCA_PYEXEC_SCRIPT) { + if (pycont->text) { - pyctrl->SetScriptText(STR_String(buf)); - pyctrl->SetScriptName(pycont->text->id.name+2); - MEM_freeN(buf); + char *buf; + // this is some blender specific code + buf= txt_to_buf(pycont->text); + if (buf) + { + pyctrl->SetScriptText(STR_String(buf)); + pyctrl->SetScriptName(pycont->text->id.name+2); + MEM_freeN(buf); + } + } - } - - LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); + else { + /* let the controller print any warnings here when importing */ + pyctrl->SetScriptText(STR_String(pycont->module)); + pyctrl->SetScriptName(pycont->module); /* will be something like module.func so using it as the name is OK */ + } + + if(pycont->flag & CONT_PY_DEBUG) { + printf("\nDebuging \"%s\", module for object %s\n\texpect worse performance.\n", pycont->module, blenderobject->id.name+2); + pyctrl->SetDebug(true); + } + break; } default: @@ -188,7 +197,9 @@ void BL_ConvertControllers( if (gamecontroller) { + LinkControllerToActuators(gamecontroller,bcontr,logicmgr,converter); gamecontroller->SetExecutePriority(executePriority++); + gamecontroller->SetBookmark((bcontr->flag & CONT_PRIO) != 0); gamecontroller->SetState(bcontr->state_mask); STR_String uniquename = bcontr->name; uniquename += "#CONTR#"; @@ -202,9 +213,18 @@ void BL_ConvertControllers( converter->RegisterGameController(gamecontroller, bcontr); if (bcontr->type==CONT_PYTHON) { + SCA_PythonController *pyctrl= static_cast<SCA_PythonController*>(gamecontroller); /* not strictly needed but gives syntax errors early on and * gives more pradictable performance for larger scripts */ - (static_cast<SCA_PythonController*>(gamecontroller))->Compile(); + if(pyctrl->m_mode==SCA_PythonController::SCA_PYEXEC_SCRIPT) + pyctrl->Compile(); + else { + /* We cant do this because importing runs the script which could end up accessing + * internal BGE functions, this is unstable while we're converting the scene. + * This is a pitty because its useful to see errors at startup but cant help it */ + + // pyctrl->Import(); + } } //done with gamecontroller diff --git a/source/gameengine/Converter/KX_ConvertControllers.h b/source/gameengine/Converter/KX_ConvertControllers.h index 3e8a87fc90b..d340778290c 100644 --- a/source/gameengine/Converter/KX_ConvertControllers.h +++ b/source/gameengine/Converter/KX_ConvertControllers.h @@ -36,7 +36,6 @@ void BL_ConvertControllers( class KX_GameObject* gameobj, class SCA_LogicManager* logicmgr, PyObject* pythondictionary, - int & executePriority, int activeLayerBitInfo, bool isInActiveLayer, class KX_BlenderSceneConverter* converter diff --git a/source/gameengine/Converter/KX_ConvertProperties.cpp b/source/gameengine/Converter/KX_ConvertProperties.cpp index 53769dc30a1..5e8d6f3cbf0 100644 --- a/source/gameengine/Converter/KX_ConvertProperties.cpp +++ b/source/gameengine/Converter/KX_ConvertProperties.cpp @@ -129,6 +129,22 @@ void BL_ConvertProperties(Object* object,KX_GameObject* gameobj,SCA_TimeEventMan // done with propval, release it propval->Release(); } + + + /* Warn if we double up on attributes, this isnt quite right since it wont find inherited attributes however there arnt many */ + for(PyAttributeDef *attrdef = KX_GameObject::Attributes; attrdef->m_name; attrdef++) { + if(strcmp(prop->name, attrdef->m_name)==0) { + printf("Warning! user defined property name \"%s\" is also a python attribute for object \"%s\"\n\tUse ob[\"%s\"] syntax to avoid conflict\n", prop->name, object->id.name+2, prop->name); + break; + } + } + for(PyMethodDef *methdef = KX_GameObject::Methods; methdef->ml_name; methdef++) { + if(strcmp(prop->name, methdef->ml_name)==0) { + printf("Warning! user defined property name \"%s\" is also a python method for object \"%s\"\n\tUse ob[\"%s\"] syntax to avoid conflict\n", prop->name, object->id.name+2, prop->name); + break; + } + } + /* end warning check */ prop = prop->next; } diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 7d43b358502..0b395cfd402 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -95,178 +95,194 @@ void BL_ConvertSensors(struct Object* blenderobject, KX_Scene* kxscene, KX_KetsjiEngine* kxengine, SCA_IInputDevice* keydev, - int & executePriority, int activeLayerBitInfo, bool isInActiveLayer, RAS_ICanvas* canvas, KX_BlenderSceneConverter* converter ) { + static bool reverseTableConverted = false; - - - /* The reverse table. In order to not confuse ourselves, we */ - /* immediately convert all events that come in to KX codes. */ - gReverseKeyTranslateTable[LEFTMOUSE ] = SCA_IInputDevice::KX_LEFTMOUSE; - gReverseKeyTranslateTable[MIDDLEMOUSE ] = SCA_IInputDevice::KX_MIDDLEMOUSE; - gReverseKeyTranslateTable[RIGHTMOUSE ] = SCA_IInputDevice::KX_RIGHTMOUSE; - gReverseKeyTranslateTable[WHEELUPMOUSE ] = SCA_IInputDevice::KX_WHEELUPMOUSE; - gReverseKeyTranslateTable[WHEELDOWNMOUSE ] = SCA_IInputDevice::KX_WHEELDOWNMOUSE; - gReverseKeyTranslateTable[MOUSEX ] = SCA_IInputDevice::KX_MOUSEX; - gReverseKeyTranslateTable[MOUSEY ] = SCA_IInputDevice::KX_MOUSEY; - - // TIMERS - - gReverseKeyTranslateTable[TIMER0 ] = SCA_IInputDevice::KX_TIMER0; - gReverseKeyTranslateTable[TIMER1 ] = SCA_IInputDevice::KX_TIMER1; - gReverseKeyTranslateTable[TIMER2 ] = SCA_IInputDevice::KX_TIMER2; - - // SYSTEM - + if (!reverseTableConverted) + { + reverseTableConverted = true; + + /* The reverse table. In order to not confuse ourselves, we */ + /* immediately convert all events that come in to KX codes. */ + gReverseKeyTranslateTable[LEFTMOUSE ] = SCA_IInputDevice::KX_LEFTMOUSE; + gReverseKeyTranslateTable[MIDDLEMOUSE ] = SCA_IInputDevice::KX_MIDDLEMOUSE; + gReverseKeyTranslateTable[RIGHTMOUSE ] = SCA_IInputDevice::KX_RIGHTMOUSE; + gReverseKeyTranslateTable[WHEELUPMOUSE ] = SCA_IInputDevice::KX_WHEELUPMOUSE; + gReverseKeyTranslateTable[WHEELDOWNMOUSE ] = SCA_IInputDevice::KX_WHEELDOWNMOUSE; + gReverseKeyTranslateTable[MOUSEX ] = SCA_IInputDevice::KX_MOUSEX; + gReverseKeyTranslateTable[MOUSEY ] = SCA_IInputDevice::KX_MOUSEY; + + // TIMERS + + gReverseKeyTranslateTable[TIMER0 ] = SCA_IInputDevice::KX_TIMER0; + gReverseKeyTranslateTable[TIMER1 ] = SCA_IInputDevice::KX_TIMER1; + gReverseKeyTranslateTable[TIMER2 ] = SCA_IInputDevice::KX_TIMER2; + + // SYSTEM + #if 0 - /* **** XXX **** */ - gReverseKeyTranslateTable[KEYBD ] = SCA_IInputDevice::KX_KEYBD; - gReverseKeyTranslateTable[RAWKEYBD ] = SCA_IInputDevice::KX_RAWKEYBD; - gReverseKeyTranslateTable[REDRAW ] = SCA_IInputDevice::KX_REDRAW; - gReverseKeyTranslateTable[INPUTCHANGE ] = SCA_IInputDevice::KX_INPUTCHANGE; - gReverseKeyTranslateTable[QFULL ] = SCA_IInputDevice::KX_QFULL; - gReverseKeyTranslateTable[WINFREEZE ] = SCA_IInputDevice::KX_WINFREEZE; - gReverseKeyTranslateTable[WINTHAW ] = SCA_IInputDevice::KX_WINTHAW; - gReverseKeyTranslateTable[WINCLOSE ] = SCA_IInputDevice::KX_WINCLOSE; - gReverseKeyTranslateTable[WINQUIT ] = SCA_IInputDevice::KX_WINQUIT; - gReverseKeyTranslateTable[Q_FIRSTTIME ] = SCA_IInputDevice::KX_Q_FIRSTTIME; - /* **** XXX **** */ + /* **** XXX **** */ + gReverseKeyTranslateTable[KEYBD ] = SCA_IInputDevice::KX_KEYBD; + gReverseKeyTranslateTable[RAWKEYBD ] = SCA_IInputDevice::KX_RAWKEYBD; + gReverseKeyTranslateTable[REDRAW ] = SCA_IInputDevice::KX_REDRAW; + gReverseKeyTranslateTable[INPUTCHANGE ] = SCA_IInputDevice::KX_INPUTCHANGE; + gReverseKeyTranslateTable[QFULL ] = SCA_IInputDevice::KX_QFULL; + gReverseKeyTranslateTable[WINFREEZE ] = SCA_IInputDevice::KX_WINFREEZE; + gReverseKeyTranslateTable[WINTHAW ] = SCA_IInputDevice::KX_WINTHAW; + gReverseKeyTranslateTable[WINCLOSE ] = SCA_IInputDevice::KX_WINCLOSE; + gReverseKeyTranslateTable[WINQUIT ] = SCA_IInputDevice::KX_WINQUIT; + gReverseKeyTranslateTable[Q_FIRSTTIME ] = SCA_IInputDevice::KX_Q_FIRSTTIME; + /* **** XXX **** */ #endif - // standard keyboard - - gReverseKeyTranslateTable[AKEY ] = SCA_IInputDevice::KX_AKEY; - gReverseKeyTranslateTable[BKEY ] = SCA_IInputDevice::KX_BKEY; - gReverseKeyTranslateTable[CKEY ] = SCA_IInputDevice::KX_CKEY; - gReverseKeyTranslateTable[DKEY ] = SCA_IInputDevice::KX_DKEY; - gReverseKeyTranslateTable[EKEY ] = SCA_IInputDevice::KX_EKEY; - gReverseKeyTranslateTable[FKEY ] = SCA_IInputDevice::KX_FKEY; - gReverseKeyTranslateTable[GKEY ] = SCA_IInputDevice::KX_GKEY; + + // standard keyboard + + gReverseKeyTranslateTable[AKEY ] = SCA_IInputDevice::KX_AKEY; + gReverseKeyTranslateTable[BKEY ] = SCA_IInputDevice::KX_BKEY; + gReverseKeyTranslateTable[CKEY ] = SCA_IInputDevice::KX_CKEY; + gReverseKeyTranslateTable[DKEY ] = SCA_IInputDevice::KX_DKEY; + gReverseKeyTranslateTable[EKEY ] = SCA_IInputDevice::KX_EKEY; + gReverseKeyTranslateTable[FKEY ] = SCA_IInputDevice::KX_FKEY; + gReverseKeyTranslateTable[GKEY ] = SCA_IInputDevice::KX_GKEY; + //XXX clean up #ifdef WIN32 #define HKEY 'h' #endif - gReverseKeyTranslateTable[HKEY ] = SCA_IInputDevice::KX_HKEY; + gReverseKeyTranslateTable[HKEY ] = SCA_IInputDevice::KX_HKEY; //XXX clean up #ifdef WIN32 #undef HKEY #endif - gReverseKeyTranslateTable[IKEY ] = SCA_IInputDevice::KX_IKEY; - gReverseKeyTranslateTable[JKEY ] = SCA_IInputDevice::KX_JKEY; - gReverseKeyTranslateTable[KKEY ] = SCA_IInputDevice::KX_KKEY; - gReverseKeyTranslateTable[LKEY ] = SCA_IInputDevice::KX_LKEY; - gReverseKeyTranslateTable[MKEY ] = SCA_IInputDevice::KX_MKEY; - gReverseKeyTranslateTable[NKEY ] = SCA_IInputDevice::KX_NKEY; - gReverseKeyTranslateTable[OKEY ] = SCA_IInputDevice::KX_OKEY; - gReverseKeyTranslateTable[PKEY ] = SCA_IInputDevice::KX_PKEY; - gReverseKeyTranslateTable[QKEY ] = SCA_IInputDevice::KX_QKEY; - gReverseKeyTranslateTable[RKEY ] = SCA_IInputDevice::KX_RKEY; - gReverseKeyTranslateTable[SKEY ] = SCA_IInputDevice::KX_SKEY; - gReverseKeyTranslateTable[TKEY ] = SCA_IInputDevice::KX_TKEY; - gReverseKeyTranslateTable[UKEY ] = SCA_IInputDevice::KX_UKEY; - gReverseKeyTranslateTable[VKEY ] = SCA_IInputDevice::KX_VKEY; - gReverseKeyTranslateTable[WKEY ] = SCA_IInputDevice::KX_WKEY; - gReverseKeyTranslateTable[XKEY ] = SCA_IInputDevice::KX_XKEY; - gReverseKeyTranslateTable[YKEY ] = SCA_IInputDevice::KX_YKEY; - gReverseKeyTranslateTable[ZKEY ] = SCA_IInputDevice::KX_ZKEY; - - gReverseKeyTranslateTable[ZEROKEY ] = SCA_IInputDevice::KX_ZEROKEY; - gReverseKeyTranslateTable[ONEKEY ] = SCA_IInputDevice::KX_ONEKEY; - gReverseKeyTranslateTable[TWOKEY ] = SCA_IInputDevice::KX_TWOKEY; - gReverseKeyTranslateTable[THREEKEY ] = SCA_IInputDevice::KX_THREEKEY; - gReverseKeyTranslateTable[FOURKEY ] = SCA_IInputDevice::KX_FOURKEY; - gReverseKeyTranslateTable[FIVEKEY ] = SCA_IInputDevice::KX_FIVEKEY; - gReverseKeyTranslateTable[SIXKEY ] = SCA_IInputDevice::KX_SIXKEY; - gReverseKeyTranslateTable[SEVENKEY ] = SCA_IInputDevice::KX_SEVENKEY; - gReverseKeyTranslateTable[EIGHTKEY ] = SCA_IInputDevice::KX_EIGHTKEY; - gReverseKeyTranslateTable[NINEKEY ] = SCA_IInputDevice::KX_NINEKEY; - - gReverseKeyTranslateTable[CAPSLOCKKEY ] = SCA_IInputDevice::KX_CAPSLOCKKEY; - - gReverseKeyTranslateTable[LEFTCTRLKEY ] = SCA_IInputDevice::KX_LEFTCTRLKEY; - gReverseKeyTranslateTable[LEFTALTKEY ] = SCA_IInputDevice::KX_LEFTALTKEY; - gReverseKeyTranslateTable[RIGHTALTKEY ] = SCA_IInputDevice::KX_RIGHTALTKEY; - gReverseKeyTranslateTable[RIGHTCTRLKEY ] = SCA_IInputDevice::KX_RIGHTCTRLKEY; - gReverseKeyTranslateTable[RIGHTSHIFTKEY ] = SCA_IInputDevice::KX_RIGHTSHIFTKEY; - gReverseKeyTranslateTable[LEFTSHIFTKEY ] = SCA_IInputDevice::KX_LEFTSHIFTKEY; - - gReverseKeyTranslateTable[ESCKEY ] = SCA_IInputDevice::KX_ESCKEY; - gReverseKeyTranslateTable[TABKEY ] = SCA_IInputDevice::KX_TABKEY; - gReverseKeyTranslateTable[RETKEY ] = SCA_IInputDevice::KX_RETKEY; - gReverseKeyTranslateTable[SPACEKEY ] = SCA_IInputDevice::KX_SPACEKEY; - gReverseKeyTranslateTable[LINEFEEDKEY ] = SCA_IInputDevice::KX_LINEFEEDKEY; - gReverseKeyTranslateTable[BACKSPACEKEY ] = SCA_IInputDevice::KX_BACKSPACEKEY; - gReverseKeyTranslateTable[DELKEY ] = SCA_IInputDevice::KX_DELKEY; - gReverseKeyTranslateTable[SEMICOLONKEY ] = SCA_IInputDevice::KX_SEMICOLONKEY; - gReverseKeyTranslateTable[PERIODKEY ] = SCA_IInputDevice::KX_PERIODKEY; - gReverseKeyTranslateTable[COMMAKEY ] = SCA_IInputDevice::KX_COMMAKEY; - gReverseKeyTranslateTable[QUOTEKEY ] = SCA_IInputDevice::KX_QUOTEKEY; - gReverseKeyTranslateTable[ACCENTGRAVEKEY ] = SCA_IInputDevice::KX_ACCENTGRAVEKEY; - gReverseKeyTranslateTable[MINUSKEY ] = SCA_IInputDevice::KX_MINUSKEY; - gReverseKeyTranslateTable[SLASHKEY ] = SCA_IInputDevice::KX_SLASHKEY; - gReverseKeyTranslateTable[BACKSLASHKEY ] = SCA_IInputDevice::KX_BACKSLASHKEY; - gReverseKeyTranslateTable[EQUALKEY ] = SCA_IInputDevice::KX_EQUALKEY; - gReverseKeyTranslateTable[LEFTBRACKETKEY ] = SCA_IInputDevice::KX_LEFTBRACKETKEY; - gReverseKeyTranslateTable[RIGHTBRACKETKEY ] = SCA_IInputDevice::KX_RIGHTBRACKETKEY; - - gReverseKeyTranslateTable[LEFTARROWKEY ] = SCA_IInputDevice::KX_LEFTARROWKEY; - gReverseKeyTranslateTable[DOWNARROWKEY ] = SCA_IInputDevice::KX_DOWNARROWKEY; - gReverseKeyTranslateTable[RIGHTARROWKEY ] = SCA_IInputDevice::KX_RIGHTARROWKEY; - gReverseKeyTranslateTable[UPARROWKEY ] = SCA_IInputDevice::KX_UPARROWKEY; - - gReverseKeyTranslateTable[PAD2 ] = SCA_IInputDevice::KX_PAD2; - gReverseKeyTranslateTable[PAD4 ] = SCA_IInputDevice::KX_PAD4; - gReverseKeyTranslateTable[PAD6 ] = SCA_IInputDevice::KX_PAD6; - gReverseKeyTranslateTable[PAD8 ] = SCA_IInputDevice::KX_PAD8; - - gReverseKeyTranslateTable[PAD1 ] = SCA_IInputDevice::KX_PAD1; - gReverseKeyTranslateTable[PAD3 ] = SCA_IInputDevice::KX_PAD3; - gReverseKeyTranslateTable[PAD5 ] = SCA_IInputDevice::KX_PAD5; - gReverseKeyTranslateTable[PAD7 ] = SCA_IInputDevice::KX_PAD7; - gReverseKeyTranslateTable[PAD9 ] = SCA_IInputDevice::KX_PAD9; - - gReverseKeyTranslateTable[PADPERIOD ] = SCA_IInputDevice::KX_PADPERIOD; - gReverseKeyTranslateTable[PADSLASHKEY ] = SCA_IInputDevice::KX_PADSLASHKEY; - gReverseKeyTranslateTable[PADASTERKEY ] = SCA_IInputDevice::KX_PADASTERKEY; - - gReverseKeyTranslateTable[PAD0 ] = SCA_IInputDevice::KX_PAD0; - gReverseKeyTranslateTable[PADMINUS ] = SCA_IInputDevice::KX_PADMINUS; - gReverseKeyTranslateTable[PADENTER ] = SCA_IInputDevice::KX_PADENTER; - gReverseKeyTranslateTable[PADPLUSKEY ] = SCA_IInputDevice::KX_PADPLUSKEY; - - - gReverseKeyTranslateTable[F1KEY ] = SCA_IInputDevice::KX_F1KEY; - gReverseKeyTranslateTable[F2KEY ] = SCA_IInputDevice::KX_F2KEY; - gReverseKeyTranslateTable[F3KEY ] = SCA_IInputDevice::KX_F3KEY; - gReverseKeyTranslateTable[F4KEY ] = SCA_IInputDevice::KX_F4KEY; - gReverseKeyTranslateTable[F5KEY ] = SCA_IInputDevice::KX_F5KEY; - gReverseKeyTranslateTable[F6KEY ] = SCA_IInputDevice::KX_F6KEY; - gReverseKeyTranslateTable[F7KEY ] = SCA_IInputDevice::KX_F7KEY; - gReverseKeyTranslateTable[F8KEY ] = SCA_IInputDevice::KX_F8KEY; - gReverseKeyTranslateTable[F9KEY ] = SCA_IInputDevice::KX_F9KEY; - gReverseKeyTranslateTable[F10KEY ] = SCA_IInputDevice::KX_F10KEY; - gReverseKeyTranslateTable[F11KEY ] = SCA_IInputDevice::KX_F11KEY; - gReverseKeyTranslateTable[F12KEY ] = SCA_IInputDevice::KX_F12KEY; - - gReverseKeyTranslateTable[PAUSEKEY ] = SCA_IInputDevice::KX_PAUSEKEY; - gReverseKeyTranslateTable[INSERTKEY ] = SCA_IInputDevice::KX_INSERTKEY; - gReverseKeyTranslateTable[HOMEKEY ] = SCA_IInputDevice::KX_HOMEKEY; - gReverseKeyTranslateTable[PAGEUPKEY ] = SCA_IInputDevice::KX_PAGEUPKEY; - gReverseKeyTranslateTable[PAGEDOWNKEY ] = SCA_IInputDevice::KX_PAGEDOWNKEY; - gReverseKeyTranslateTable[ENDKEY ] = SCA_IInputDevice::KX_ENDKEY; - + + gReverseKeyTranslateTable[IKEY ] = SCA_IInputDevice::KX_IKEY; + gReverseKeyTranslateTable[JKEY ] = SCA_IInputDevice::KX_JKEY; + gReverseKeyTranslateTable[KKEY ] = SCA_IInputDevice::KX_KKEY; + gReverseKeyTranslateTable[LKEY ] = SCA_IInputDevice::KX_LKEY; + gReverseKeyTranslateTable[MKEY ] = SCA_IInputDevice::KX_MKEY; + gReverseKeyTranslateTable[NKEY ] = SCA_IInputDevice::KX_NKEY; + gReverseKeyTranslateTable[OKEY ] = SCA_IInputDevice::KX_OKEY; + gReverseKeyTranslateTable[PKEY ] = SCA_IInputDevice::KX_PKEY; + gReverseKeyTranslateTable[QKEY ] = SCA_IInputDevice::KX_QKEY; + gReverseKeyTranslateTable[RKEY ] = SCA_IInputDevice::KX_RKEY; + gReverseKeyTranslateTable[SKEY ] = SCA_IInputDevice::KX_SKEY; + gReverseKeyTranslateTable[TKEY ] = SCA_IInputDevice::KX_TKEY; + gReverseKeyTranslateTable[UKEY ] = SCA_IInputDevice::KX_UKEY; + gReverseKeyTranslateTable[VKEY ] = SCA_IInputDevice::KX_VKEY; + gReverseKeyTranslateTable[WKEY ] = SCA_IInputDevice::KX_WKEY; + gReverseKeyTranslateTable[XKEY ] = SCA_IInputDevice::KX_XKEY; + gReverseKeyTranslateTable[YKEY ] = SCA_IInputDevice::KX_YKEY; + gReverseKeyTranslateTable[ZKEY ] = SCA_IInputDevice::KX_ZKEY; + + gReverseKeyTranslateTable[ZEROKEY ] = SCA_IInputDevice::KX_ZEROKEY; + gReverseKeyTranslateTable[ONEKEY ] = SCA_IInputDevice::KX_ONEKEY; + gReverseKeyTranslateTable[TWOKEY ] = SCA_IInputDevice::KX_TWOKEY; + gReverseKeyTranslateTable[THREEKEY ] = SCA_IInputDevice::KX_THREEKEY; + gReverseKeyTranslateTable[FOURKEY ] = SCA_IInputDevice::KX_FOURKEY; + gReverseKeyTranslateTable[FIVEKEY ] = SCA_IInputDevice::KX_FIVEKEY; + gReverseKeyTranslateTable[SIXKEY ] = SCA_IInputDevice::KX_SIXKEY; + gReverseKeyTranslateTable[SEVENKEY ] = SCA_IInputDevice::KX_SEVENKEY; + gReverseKeyTranslateTable[EIGHTKEY ] = SCA_IInputDevice::KX_EIGHTKEY; + gReverseKeyTranslateTable[NINEKEY ] = SCA_IInputDevice::KX_NINEKEY; + + gReverseKeyTranslateTable[CAPSLOCKKEY ] = SCA_IInputDevice::KX_CAPSLOCKKEY; + + gReverseKeyTranslateTable[LEFTCTRLKEY ] = SCA_IInputDevice::KX_LEFTCTRLKEY; + gReverseKeyTranslateTable[LEFTALTKEY ] = SCA_IInputDevice::KX_LEFTALTKEY; + gReverseKeyTranslateTable[RIGHTALTKEY ] = SCA_IInputDevice::KX_RIGHTALTKEY; + gReverseKeyTranslateTable[RIGHTCTRLKEY ] = SCA_IInputDevice::KX_RIGHTCTRLKEY; + gReverseKeyTranslateTable[RIGHTSHIFTKEY ] = SCA_IInputDevice::KX_RIGHTSHIFTKEY; + gReverseKeyTranslateTable[LEFTSHIFTKEY ] = SCA_IInputDevice::KX_LEFTSHIFTKEY; + + gReverseKeyTranslateTable[ESCKEY ] = SCA_IInputDevice::KX_ESCKEY; + gReverseKeyTranslateTable[TABKEY ] = SCA_IInputDevice::KX_TABKEY; + gReverseKeyTranslateTable[RETKEY ] = SCA_IInputDevice::KX_RETKEY; + gReverseKeyTranslateTable[SPACEKEY ] = SCA_IInputDevice::KX_SPACEKEY; + gReverseKeyTranslateTable[LINEFEEDKEY ] = SCA_IInputDevice::KX_LINEFEEDKEY; + gReverseKeyTranslateTable[BACKSPACEKEY ] = SCA_IInputDevice::KX_BACKSPACEKEY; + gReverseKeyTranslateTable[DELKEY ] = SCA_IInputDevice::KX_DELKEY; + gReverseKeyTranslateTable[SEMICOLONKEY ] = SCA_IInputDevice::KX_SEMICOLONKEY; + gReverseKeyTranslateTable[PERIODKEY ] = SCA_IInputDevice::KX_PERIODKEY; + gReverseKeyTranslateTable[COMMAKEY ] = SCA_IInputDevice::KX_COMMAKEY; + gReverseKeyTranslateTable[QUOTEKEY ] = SCA_IInputDevice::KX_QUOTEKEY; + gReverseKeyTranslateTable[ACCENTGRAVEKEY ] = SCA_IInputDevice::KX_ACCENTGRAVEKEY; + gReverseKeyTranslateTable[MINUSKEY ] = SCA_IInputDevice::KX_MINUSKEY; + gReverseKeyTranslateTable[SLASHKEY ] = SCA_IInputDevice::KX_SLASHKEY; + gReverseKeyTranslateTable[BACKSLASHKEY ] = SCA_IInputDevice::KX_BACKSLASHKEY; + gReverseKeyTranslateTable[EQUALKEY ] = SCA_IInputDevice::KX_EQUALKEY; + gReverseKeyTranslateTable[LEFTBRACKETKEY ] = SCA_IInputDevice::KX_LEFTBRACKETKEY; + gReverseKeyTranslateTable[RIGHTBRACKETKEY ] = SCA_IInputDevice::KX_RIGHTBRACKETKEY; + + gReverseKeyTranslateTable[LEFTARROWKEY ] = SCA_IInputDevice::KX_LEFTARROWKEY; + gReverseKeyTranslateTable[DOWNARROWKEY ] = SCA_IInputDevice::KX_DOWNARROWKEY; + gReverseKeyTranslateTable[RIGHTARROWKEY ] = SCA_IInputDevice::KX_RIGHTARROWKEY; + gReverseKeyTranslateTable[UPARROWKEY ] = SCA_IInputDevice::KX_UPARROWKEY; + + gReverseKeyTranslateTable[PAD2 ] = SCA_IInputDevice::KX_PAD2; + gReverseKeyTranslateTable[PAD4 ] = SCA_IInputDevice::KX_PAD4; + gReverseKeyTranslateTable[PAD6 ] = SCA_IInputDevice::KX_PAD6; + gReverseKeyTranslateTable[PAD8 ] = SCA_IInputDevice::KX_PAD8; + + gReverseKeyTranslateTable[PAD1 ] = SCA_IInputDevice::KX_PAD1; + gReverseKeyTranslateTable[PAD3 ] = SCA_IInputDevice::KX_PAD3; + gReverseKeyTranslateTable[PAD5 ] = SCA_IInputDevice::KX_PAD5; + gReverseKeyTranslateTable[PAD7 ] = SCA_IInputDevice::KX_PAD7; + gReverseKeyTranslateTable[PAD9 ] = SCA_IInputDevice::KX_PAD9; + + gReverseKeyTranslateTable[PADPERIOD ] = SCA_IInputDevice::KX_PADPERIOD; + gReverseKeyTranslateTable[PADSLASHKEY ] = SCA_IInputDevice::KX_PADSLASHKEY; + gReverseKeyTranslateTable[PADASTERKEY ] = SCA_IInputDevice::KX_PADASTERKEY; + + gReverseKeyTranslateTable[PAD0 ] = SCA_IInputDevice::KX_PAD0; + gReverseKeyTranslateTable[PADMINUS ] = SCA_IInputDevice::KX_PADMINUS; + gReverseKeyTranslateTable[PADENTER ] = SCA_IInputDevice::KX_PADENTER; + gReverseKeyTranslateTable[PADPLUSKEY ] = SCA_IInputDevice::KX_PADPLUSKEY; + + + gReverseKeyTranslateTable[F1KEY ] = SCA_IInputDevice::KX_F1KEY; + gReverseKeyTranslateTable[F2KEY ] = SCA_IInputDevice::KX_F2KEY; + gReverseKeyTranslateTable[F3KEY ] = SCA_IInputDevice::KX_F3KEY; + gReverseKeyTranslateTable[F4KEY ] = SCA_IInputDevice::KX_F4KEY; + gReverseKeyTranslateTable[F5KEY ] = SCA_IInputDevice::KX_F5KEY; + gReverseKeyTranslateTable[F6KEY ] = SCA_IInputDevice::KX_F6KEY; + gReverseKeyTranslateTable[F7KEY ] = SCA_IInputDevice::KX_F7KEY; + gReverseKeyTranslateTable[F8KEY ] = SCA_IInputDevice::KX_F8KEY; + gReverseKeyTranslateTable[F9KEY ] = SCA_IInputDevice::KX_F9KEY; + gReverseKeyTranslateTable[F10KEY ] = SCA_IInputDevice::KX_F10KEY; + gReverseKeyTranslateTable[F11KEY ] = SCA_IInputDevice::KX_F11KEY; + gReverseKeyTranslateTable[F12KEY ] = SCA_IInputDevice::KX_F12KEY; + + gReverseKeyTranslateTable[PAUSEKEY ] = SCA_IInputDevice::KX_PAUSEKEY; + gReverseKeyTranslateTable[INSERTKEY ] = SCA_IInputDevice::KX_INSERTKEY; + gReverseKeyTranslateTable[HOMEKEY ] = SCA_IInputDevice::KX_HOMEKEY; + gReverseKeyTranslateTable[PAGEUPKEY ] = SCA_IInputDevice::KX_PAGEUPKEY; + gReverseKeyTranslateTable[PAGEDOWNKEY ] = SCA_IInputDevice::KX_PAGEDOWNKEY; + gReverseKeyTranslateTable[ENDKEY ] = SCA_IInputDevice::KX_ENDKEY; + } + + int executePriority = 0; int uniqueint = 0; + int count = 0; bSensor* sens = (bSensor*)blenderobject->sensors.first; bool pos_pulsemode = false; bool neg_pulsemode = false; int frequency = 0; bool invert = false; bool level = false; + bool tap = false; + while (sens) + { + sens = sens->next; + count++; + } + gameobj->ReserveSensor(count); + sens = (bSensor*)blenderobject->sensors.first; while(sens) { SCA_ISensor* gamesensor=NULL; @@ -279,6 +295,7 @@ void BL_ConvertSensors(struct Object* blenderobject, frequency = sens->freq; invert = !(sens->invert == 0); level = !(sens->level == 0); + tap = !(sens->tap == 0); switch (sens->type) { @@ -679,6 +696,11 @@ void BL_ConvertSensors(struct Object* blenderobject, if (eventmgr) { int randomSeed = blenderrndsensor->seed; + if (randomSeed == 0) + { + randomSeed = (int)(kxengine->GetRealTime()*100000.0); + randomSeed ^= (intptr_t)blenderrndsensor; + } gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed); } } @@ -766,7 +788,8 @@ void BL_ConvertSensors(struct Object* blenderobject, frequency); gamesensor->SetInvert(invert); gamesensor->SetLevel(level); - gamesensor->SetName(STR_String(sens->name)); + gamesensor->SetTap(tap); + gamesensor->SetName(sens->name); gameobj->AddSensor(gamesensor); @@ -775,7 +798,7 @@ void BL_ConvertSensors(struct Object* blenderobject, //if (isInActiveLayer) // gamesensor->RegisterToManager(); - + gamesensor->ReserveController(sens->totlinks); for (int i=0;i<sens->totlinks;i++) { bController* linkedcont = (bController*) sens->links[i]; diff --git a/source/gameengine/Converter/KX_ConvertSensors.h b/source/gameengine/Converter/KX_ConvertSensors.h index b18ffc10a2a..9162a866768 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.h +++ b/source/gameengine/Converter/KX_ConvertSensors.h @@ -35,7 +35,6 @@ void BL_ConvertSensors(struct Object* blenderobject, class KX_Scene* kxscene, class KX_KetsjiEngine* kxengine, class SCA_IInputDevice* keydev, - int & executePriority , int activeLayerBitInfo, bool isInActiveLayer, class RAS_ICanvas* canvas, diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/BoolValue.cpp index 13c870b68e5..d90da8b3a92 100644 --- a/source/gameengine/Expressions/BoolValue.cpp +++ b/source/gameengine/Expressions/BoolValue.cpp @@ -26,6 +26,9 @@ // Construction/Destruction ////////////////////////////////////////////////////////////////////// +const STR_String CBoolValue::sTrueString = "TRUE"; +const STR_String CBoolValue::sFalseString = "FALSE"; + CBoolValue::CBoolValue() /* @@ -45,7 +48,7 @@ CBoolValue::CBoolValue(bool inBool) -CBoolValue::CBoolValue(bool innie,STR_String name,AllocationTYPE alloctype) +CBoolValue::CBoolValue(bool innie,const char *name,AllocationTYPE alloctype) { m_bool = innie; SetName(name); @@ -190,9 +193,6 @@ double CBoolValue::GetNumber() const STR_String& CBoolValue::GetText() { - static STR_String sTrueString = STR_String("TRUE"); - static STR_String sFalseString = STR_String("FALSE"); - return m_bool ? sTrueString : sFalseString; } @@ -201,7 +201,7 @@ const STR_String& CBoolValue::GetText() CValue* CBoolValue::GetReplica() { CBoolValue* replica = new CBoolValue(*this); - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } diff --git a/source/gameengine/Expressions/BoolValue.h b/source/gameengine/Expressions/BoolValue.h index 9352b9d4b92..726619e7193 100644 --- a/source/gameengine/Expressions/BoolValue.h +++ b/source/gameengine/Expressions/BoolValue.h @@ -28,9 +28,12 @@ class CBoolValue : public CPropValue //PLUGIN_DECLARE_SERIAL(CBoolValue,CValue) public: + static const STR_String sTrueString; + static const STR_String sFalseString; + CBoolValue(); CBoolValue(bool inBool); - CBoolValue(bool innie, STR_String name, AllocationTYPE alloctype = CValue::HEAPVALUE); + CBoolValue(bool innie, const char *name, AllocationTYPE alloctype = CValue::HEAPVALUE); virtual const STR_String& GetText(); virtual double GetNumber(); diff --git a/source/gameengine/Expressions/CMakeLists.txt b/source/gameengine/Expressions/CMakeLists.txt index 6b2a835d648..e3942b46557 100644 --- a/source/gameengine/Expressions/CMakeLists.txt +++ b/source/gameengine/Expressions/CMakeLists.txt @@ -31,6 +31,7 @@ SET(INC ../../../source/kernel/gen_system ../../../intern/string ../../../intern/moto/include + ../../../source/gameengine/SceneGraph ${PYTHON_INC} ) diff --git a/source/gameengine/Expressions/EmptyValue.cpp b/source/gameengine/Expressions/EmptyValue.cpp index f72ddc47096..5d1273b5301 100644 --- a/source/gameengine/Expressions/EmptyValue.cpp +++ b/source/gameengine/Expressions/EmptyValue.cpp @@ -121,7 +121,7 @@ const STR_String & CEmptyValue::GetText() CValue* CEmptyValue::GetReplica() { CEmptyValue* replica = new CEmptyValue(*this); - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } diff --git a/source/gameengine/Expressions/ErrorValue.cpp b/source/gameengine/Expressions/ErrorValue.cpp index 651a772db19..a44abf8b22e 100644 --- a/source/gameengine/Expressions/ErrorValue.cpp +++ b/source/gameengine/Expressions/ErrorValue.cpp @@ -34,13 +34,15 @@ effect: constructs a new CErrorValue containing errormessage "Error" -CErrorValue::CErrorValue(STR_String errmsg) +CErrorValue::CErrorValue(const char *errmsg) /* pre: effect: constructs a new CErrorValue containing errormessage errmsg */ { - m_strErrorText = "[" + errmsg + "]"; + m_strErrorText = "["; + m_strErrorText += errmsg; + m_strErrorText += "]"; SetError(true); } diff --git a/source/gameengine/Expressions/ErrorValue.h b/source/gameengine/Expressions/ErrorValue.h index 5b5795196ba..b4b758feea7 100644 --- a/source/gameengine/Expressions/ErrorValue.h +++ b/source/gameengine/Expressions/ErrorValue.h @@ -25,7 +25,7 @@ public: virtual const STR_String & GetText(); virtual double GetNumber(); CErrorValue(); - CErrorValue(STR_String errmsg); + CErrorValue(const char *errmsg); virtual ~CErrorValue(); virtual CValue* Calc(VALUE_OPERATOR op, CValue* val); virtual CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); diff --git a/source/gameengine/Expressions/FloatValue.cpp b/source/gameengine/Expressions/FloatValue.cpp index 212a55fe457..4de685a82c1 100644 --- a/source/gameengine/Expressions/FloatValue.cpp +++ b/source/gameengine/Expressions/FloatValue.cpp @@ -50,7 +50,7 @@ effect: constructs a new CFloatValue containing value fl -CFloatValue::CFloatValue(float fl,STR_String name,AllocationTYPE alloctype) +CFloatValue::CFloatValue(float fl,const char *name,AllocationTYPE alloctype) /* pre: effect: constructs a new CFloatValue containing value fl @@ -307,8 +307,8 @@ const STR_String & CFloatValue::GetText() CValue* CFloatValue::GetReplica() { CFloatValue* replica = new CFloatValue(*this); - replica->m_pstrRep = NULL; - CValue::AddDataToReplica(replica); + replica->m_pstrRep = NULL; /* should be in CFloatValue::ProcessReplica() but its not defined, no matter */ + replica->ProcessReplica(); return replica; } diff --git a/source/gameengine/Expressions/FloatValue.h b/source/gameengine/Expressions/FloatValue.h index 41f70b5c54c..fb75b7c702b 100644 --- a/source/gameengine/Expressions/FloatValue.h +++ b/source/gameengine/Expressions/FloatValue.h @@ -23,7 +23,7 @@ class CFloatValue : public CPropValue public: CFloatValue(); CFloatValue(float fl); - CFloatValue(float fl,STR_String name,AllocationTYPE alloctype=CValue::HEAPVALUE); + CFloatValue(float fl,const char *name,AllocationTYPE alloctype=CValue::HEAPVALUE); virtual const STR_String & GetText(); diff --git a/source/gameengine/Expressions/IfExpr.cpp b/source/gameengine/Expressions/IfExpr.cpp index 5d3eb3641ca..fcb37bff52d 100644 --- a/source/gameengine/Expressions/IfExpr.cpp +++ b/source/gameengine/Expressions/IfExpr.cpp @@ -15,6 +15,7 @@ #include "IfExpr.h" #include "EmptyValue.h" #include "ErrorValue.h" +#include "BoolValue.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -72,14 +73,14 @@ ret: a new object containing the value of m_e1 if m_guard is a boolean TRUE { CValue *guardval; guardval = m_guard->Calculate(); - STR_String text = guardval->GetText(); + const STR_String& text = guardval->GetText(); guardval->Release(); - if (text == STR_String("TRUE")) + if (&text == &CBoolValue::sTrueString) { return m_e1->Calculate(); } - else if (text == STR_String("FALSE")) + else if (&text == &CBoolValue::sFalseString) { return m_e2->Calculate(); } diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/InputParser.cpp index 66075dd8d42..b15b206a38a 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/InputParser.cpp @@ -38,7 +38,7 @@ // cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc... #include "IfExpr.h" -#if defined(WIN32) || defined(WIN64) +#if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS) #define strcasecmp _stricmp #ifndef strtoll @@ -66,7 +66,7 @@ CParser::~CParser() -void CParser::ScanError(STR_String str) +void CParser::ScanError(const char *str) { // sets the global variable errmsg to an errormessage with // contents str, appending if it already exists @@ -81,7 +81,7 @@ void CParser::ScanError(STR_String str) -CExpression* CParser::Error(STR_String str) +CExpression* CParser::Error(const char *str) { // makes and returns a new CConstExpr filled with an CErrorValue // with string str @@ -537,7 +537,7 @@ CExpression *CParser::Expr() { } CExpression* CParser::ProcessText -(STR_String intext) { +(const char *intext) { // and parses the string in intext and returns it. @@ -574,7 +574,7 @@ CExpression* CParser::ProcessText -float CParser::GetFloat(STR_String txt) +float CParser::GetFloat(STR_String& txt) { // returns parsed text into a float // empty string returns -1 @@ -599,7 +599,7 @@ float CParser::GetFloat(STR_String txt) return result; } -CValue* CParser::GetValue(STR_String txt, bool bFallbackToText) +CValue* CParser::GetValue(STR_String& txt, bool bFallbackToText) { // returns parsed text into a value, // empty string returns NULL value ! @@ -658,10 +658,41 @@ static PyMethodDef CParserMethods[] = { NULL,NULL} // Sentinel }; + +#if (PY_VERSION_HEX >= 0x03000000) +static struct PyModuleDef Expression_module_def = { + {}, /* m_base */ + "Expression", /* m_name */ + 0, /* m_doc */ + 0, /* m_size */ + CParserMethods, /* m_methods */ + 0, /* m_reload */ + 0, /* m_traverse */ + 0, /* m_clear */ + 0, /* m_free */ +}; +#endif + extern "C" { void initExpressionModule(void) { - Py_InitModule("Expression",CParserMethods); + PyObject *m; + /* Use existing module where possible + * be careful not to init any runtime vars after this */ + m = PyImport_ImportModule( "Expression" ); + if(m) { + Py_DECREF(m); + //return m; + } + else { + PyErr_Clear(); + +#if (PY_VERSION_HEX >= 0x03000000) + PyModule_Create(&Expression_module_def); +#else + Py_InitModule("Expression",CParserMethods); +#endif + } } } diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/InputParser.h index 3d517222639..810bdc244a8 100644 --- a/source/gameengine/Expressions/InputParser.h +++ b/source/gameengine/Expressions/InputParser.h @@ -27,9 +27,9 @@ public: CParser(); virtual ~CParser(); - float GetFloat(STR_String txt); - CValue* GetValue(STR_String txt, bool bFallbackToText=false); - CExpression* ProcessText(STR_String intext); + float GetFloat(STR_String& txt); + CValue* GetValue(STR_String& txt, bool bFallbackToText=false); + CExpression* ProcessText(const char *intext); void SetContext(CValue* context); private: @@ -86,8 +86,8 @@ private: CValue* m_identifierContext;// context in which identifiers are looked up - void ScanError(STR_String str); - CExpression* Error(STR_String str); + void ScanError(const char *str); + CExpression* Error(const char *str); void NextCh(); void TermChar(char c); void DigRep(); diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp index 4e86f7bf789..227518e9439 100644 --- a/source/gameengine/Expressions/IntValue.cpp +++ b/source/gameengine/Expressions/IntValue.cpp @@ -54,7 +54,7 @@ effect: constructs a new CIntValue containing cInt innie -CIntValue::CIntValue(cInt innie,STR_String name,AllocationTYPE alloctype) +CIntValue::CIntValue(cInt innie,const char *name,AllocationTYPE alloctype) { m_int = innie; SetName(name); @@ -311,7 +311,7 @@ const STR_String & CIntValue::GetText() CValue* CIntValue::GetReplica() { CIntValue* replica = new CIntValue(*this); - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->m_pstrRep = NULL; return replica; diff --git a/source/gameengine/Expressions/IntValue.h b/source/gameengine/Expressions/IntValue.h index 0f3a38b274b..06bf1755749 100644 --- a/source/gameengine/Expressions/IntValue.h +++ b/source/gameengine/Expressions/IntValue.h @@ -32,7 +32,7 @@ public: CIntValue(); CIntValue(cInt innie); CIntValue(cInt innie, - STR_String name, + const char *name, AllocationTYPE alloctype=CValue::HEAPVALUE); virtual CValue* Calc(VALUE_OPERATOR op, diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/ListValue.cpp index dd9b296dce1..a0d73c75d60 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/ListValue.cpp @@ -18,6 +18,7 @@ #include "StringValue.h" #include "VoidValue.h" #include <algorithm> +#include "BoolValue.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -39,8 +40,10 @@ Py_ssize_t listvalue_bufferlen(PyObject* self) PyObject* listvalue_buffer_item(PyObject* self, Py_ssize_t index) { CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self)); + CValue *cval; + if (list==NULL) { - PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, "val = CList[i], "BGE_PROXY_ERROR_MSG); return NULL; } @@ -49,43 +52,47 @@ PyObject* listvalue_buffer_item(PyObject* self, Py_ssize_t index) if (index < 0) index = count+index; - if (index >= 0 && index < count) - { - PyObject* pyobj = list->GetValue(index)->ConvertValueToPython(); - if (pyobj) - return pyobj; - else - return list->GetValue(index)->GetProxy(); - + if (index < 0 || index >= count) { + PyErr_SetString(PyExc_IndexError, "CList[i]: Python ListIndex out of range in CValueList"); + return NULL; } - PyErr_SetString(PyExc_IndexError, "list[i]: Python ListIndex out of range in CValueList"); - return NULL; + + cval= list->GetValue(index); + + PyObject* pyobj = cval->ConvertValueToPython(); + if (pyobj) + return pyobj; + else + return cval->GetProxy(); } PyObject* listvalue_mapping_subscript(PyObject* self, PyObject* pyindex) { CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self)); if (list==NULL) { - PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, "value = CList[i], "BGE_PROXY_ERROR_MSG); return NULL; } if (PyString_Check(pyindex)) { - STR_String index(PyString_AsString(pyindex)); - CValue *item = ((CListValue*) list)->FindValue(index); - if (item) - return item->GetProxy(); - + CValue *item = ((CListValue*) list)->FindValue(PyString_AsString(pyindex)); + if (item) { + PyObject* pyobj = item->ConvertValueToPython(); + if(pyobj) + return pyobj; + else + return item->GetProxy(); + } } - if (PyInt_Check(pyindex)) + else if (PyInt_Check(pyindex)) { int index = PyInt_AsLong(pyindex); - return listvalue_buffer_item(self, index); + return listvalue_buffer_item(self, index); /* wont add a ref */ } PyObject *pyindex_str = PyObject_Repr(pyindex); /* new ref */ - PyErr_Format(PyExc_KeyError, "list[key]: '%s' key not in list", PyString_AsString(pyindex_str)); + PyErr_Format(PyExc_KeyError, "CList[key]: '%s' key not in list", PyString_AsString(pyindex_str)); Py_DECREF(pyindex_str); return NULL; } @@ -96,7 +103,7 @@ PyObject* listvalue_buffer_slice(PyObject* self,Py_ssize_t ilow, Py_ssize_t ihig { CListValue *list= static_cast<CListValue *>(BGE_PROXY_REF(self)); if (list==NULL) { - PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, "val = CList[i:j], "BGE_PROXY_ERROR_MSG); return NULL; } @@ -127,73 +134,79 @@ PyObject* listvalue_buffer_slice(PyObject* self,Py_ssize_t ilow, Py_ssize_t ihig } - -static PyObject * -listvalue_buffer_concat(PyObject * self, PyObject * other) +/* clist + list, return a list that python owns */ +static PyObject *listvalue_buffer_concat(PyObject * self, PyObject * other) { CListValue *listval= static_cast<CListValue *>(BGE_PROXY_REF(self)); + int i, numitems, numitems_orig; + if (listval==NULL) { - PyErr_SetString(PyExc_IndexError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, "CList+other, "BGE_PROXY_ERROR_MSG); return NULL; } + numitems_orig= listval->GetCount(); + // for now, we support CListValue concatenated with items // and CListValue concatenated to Python Lists // and CListValue concatenated with another CListValue - listval->AddRef(); - if (other->ob_type == &PyList_Type) + /* Shallow copy, dont use listval->GetReplica(), it will screw up with KX_GameObjects */ + CListValue* listval_new = new CListValue(); + + if (PyList_Check(other)) { + CValue* listitemval; bool error = false; - - int i; - int numitems = PyList_Size(other); + + numitems = PyList_Size(other); + + /* copy the first part of the list */ + listval_new->Resize(numitems_orig + numitems); + for (i=0;i<numitems_orig;i++) + listval_new->SetValue(i, listval->GetValue(i)->AddRef()); + for (i=0;i<numitems;i++) { - PyObject* listitem = PyList_GetItem(other,i); - CValue* listitemval = listval->ConvertPythonToValue(listitem); - if (listitemval) - { - listval->Add(listitemval); - } else - { - error = true; + listitemval = listval->ConvertPythonToValue(PyList_GetItem(other,i), "cList + pyList: CListValue, "); + + if (listitemval) { + listval_new->SetValue(i+numitems_orig, listitemval); + } else { + error= true; + break; } } - + if (error) { - PyErr_SetString(PyExc_SystemError, "list.append(val): couldn't add one or more items to this CValueList"); - return NULL; + listval_new->Resize(numitems_orig+i); /* resize so we dont try release NULL pointers */ + listval_new->Release(); + return NULL; /* ConvertPythonToValue above sets the error */ } - - } else - { - if (other->ob_type == &CListValue::Type) - { - // add items from otherlist to this list - CListValue* otherval = (CListValue*) other; - - - for (int i=0;i<otherval->GetCount();i++) - { - otherval->Add(listval->GetValue(i)->AddRef()); - } - } - else - { - CValue* objval = listval->ConvertPythonToValue(other); - if (objval) - { - listval->Add(objval); - } else - { - PyErr_SetString(PyExc_SystemError, "list.append(i): couldn't add item to this CValueList"); - return NULL; - } + + } + else if (PyObject_TypeCheck(other, &CListValue::Type)) { + // add items from otherlist to this list + CListValue* otherval = static_cast<CListValue *>(BGE_PROXY_REF(other)); + if(otherval==NULL) { + listval_new->Release(); + PyErr_SetString(PyExc_SystemError, "CList+other, "BGE_PROXY_ERROR_MSG); + return NULL; } + + numitems = otherval->GetCount(); + + /* copy the first part of the list */ + listval_new->Resize(numitems_orig + numitems); /* resize so we dont try release NULL pointers */ + for (i=0;i<numitems_orig;i++) + listval_new->SetValue(i, listval->GetValue(i)->AddRef()); + + /* now copy the other part of the list */ + for (i=0;i<numitems;i++) + listval_new->SetValue(i+numitems_orig, otherval->GetValue(i)->AddRef()); + } - - return self; + return listval_new->NewProxy(true); /* python owns this list */ } @@ -203,9 +216,15 @@ static PySequenceMethods listvalue_as_sequence = { listvalue_buffer_concat, /*sq_concat*/ NULL, /*sq_repeat*/ listvalue_buffer_item, /*sq_item*/ +#if (PY_VERSION_HEX >= 0x03000000) // TODO, slicing in py3? + NULL, + NULL, + NULL, +#else listvalue_buffer_slice, /*sq_slice*/ NULL, /*sq_ass_item*/ - NULL /*sq_ass_slice*/ + NULL, /*sq_ass_slice*/ +#endif }; @@ -220,8 +239,13 @@ static PyMappingMethods instance_as_mapping = { PyTypeObject CListValue::Type = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "CListValue", /*tp_name*/ sizeof(PyObjectPlus_Proxy), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -256,10 +280,17 @@ PyParentObject CListValue::Parents[] = { PyMethodDef CListValue::Methods[] = { + /* List style access */ {"append", (PyCFunction)CListValue::sPyappend,METH_O}, {"reverse", (PyCFunction)CListValue::sPyreverse,METH_NOARGS}, {"index", (PyCFunction)CListValue::sPyindex,METH_O}, {"count", (PyCFunction)CListValue::sPycount,METH_O}, + + /* Dict style access */ + {"get", (PyCFunction)CListValue::sPyget,METH_VARARGS}, + {"has_key", (PyCFunction)CListValue::sPyhas_key,METH_O}, + + /* Own cvalue funcs */ {"from_id", (PyCFunction)CListValue::sPyfrom_id,METH_O}, {NULL,NULL} //Sentinel @@ -273,6 +304,10 @@ PyObject* CListValue::py_getattro(PyObject* attr) { py_getattro_up(CValue); } +PyObject* CListValue::py_getattro_dict() { + py_getattro_dict_up(CValue); +} + ////////////////////////////////////////////////////////////////////// // Construction/Destruction @@ -320,7 +355,7 @@ const STR_String & CListValue::GetText() CValue* CListValue::GetReplica() { CListValue* replica = new CListValue(*this); - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->m_bReleaseContents=true; // for copy, complete array is copied for now... // copy all values @@ -370,23 +405,21 @@ void CListValue::ReleaseAndRemoveAll() CValue* CListValue::FindValue(const STR_String & name) { - CValue* resultval = NULL; - int i=0; + for (int i=0; i < GetCount(); i++) + if (GetValue(i)->GetName() == name) + return GetValue(i); - while (!resultval && i < GetCount()) - { - CValue* myval = GetValue(i); - - if (myval->GetName() == name) - resultval = GetValue(i)->AddRef(); // add referencecount - else - i++; - - } - return resultval; + return NULL; } - +CValue* CListValue::FindValue(const char * name) +{ + for (int i=0; i < GetCount(); i++) + if (GetValue(i)->GetName() == name) + return GetValue(i); + + return NULL; +} bool CListValue::SearchValue(CValue *val) { @@ -433,14 +466,24 @@ void CListValue::MergeList(CListValue *otherlist) { SetValue(i+numelements,otherlist->GetValue(i)->AddRef()); } - } - PyObject* CListValue::Pyappend(PyObject* value) { - return listvalue_buffer_concat(m_proxy, value); /* m_proxy is the same as self */ + CValue* objval = ConvertPythonToValue(value, "CList.append(i): CValueList, "); + + if (!objval) /* ConvertPythonToValue sets the error */ + return NULL; + + if (!BGE_PROXY_PYOWNS(m_proxy)) { + PyErr_SetString(PyExc_TypeError, "CList.append(i): this CValueList is used internally for the game engine and can't be modified"); + return NULL; + } + + Add(objval); + + Py_RETURN_NONE; } @@ -461,13 +504,12 @@ bool CListValue::CheckEqual(CValue* first,CValue* second) if (eqval==NULL) return false; - - STR_String txt = eqval->GetText(); - eqval->Release(); - if (txt=="TRUE") + const STR_String& text = eqval->GetText(); + if (&text==&CBoolValue::sTrueString) { result = true; } + eqval->Release(); return result; } @@ -478,7 +520,7 @@ PyObject* CListValue::Pyindex(PyObject *value) { PyObject* result = NULL; - CValue* checkobj = ConvertPythonToValue(value); + CValue* checkobj = ConvertPythonToValue(value, "val = cList[i]: CValueList, "); if (checkobj==NULL) return NULL; /* ConvertPythonToValue sets the error */ @@ -495,7 +537,7 @@ PyObject* CListValue::Pyindex(PyObject *value) checkobj->Release(); if (result==NULL) { - PyErr_SetString(PyExc_ValueError, "list.index(x): x not in CListValue"); + PyErr_SetString(PyExc_ValueError, "CList.index(x): x not in CListValue"); } return result; @@ -507,7 +549,7 @@ PyObject* CListValue::Pycount(PyObject* value) { int numfound = 0; - CValue* checkobj = ConvertPythonToValue(value); + CValue* checkobj = ConvertPythonToValue(value, ""); /* error ignored */ if (checkobj==NULL) { /* in this case just return that there are no items in the list */ PyErr_Clear(); @@ -528,7 +570,35 @@ PyObject* CListValue::Pycount(PyObject* value) return PyInt_FromLong(numfound); } +/* Matches python dict.get(key, [default]) */ +PyObject* CListValue::Pyget(PyObject *args) +{ + char *key; + PyObject* def = Py_None; + + if (!PyArg_ParseTuple(args, "s|O:get", &key, &def)) + return NULL; + + CValue *item = FindValue((const char *)key); + if (item) { + PyObject* pyobj = item->ConvertValueToPython(); + if (pyobj) + return pyobj; + else + return item->GetProxy(); + } + Py_INCREF(def); + return def; +} +/* Matches python dict.has_key() */ +PyObject* CListValue::Pyhas_key(PyObject* value) +{ + if (PyString_Check(value) && FindValue((const char *)PyString_AsString(value))) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; +} PyObject* CListValue::Pyfrom_id(PyObject* value) { @@ -555,18 +625,24 @@ PyObject* CListValue::Pyfrom_id(PyObject* value) CValue* CListValue::Calc(VALUE_OPERATOR op,CValue *val) { //assert(false); // todo: implement me! - fprintf(stderr, "CValueList::Calc not yet implimented\n"); + static int error_printed = 0; + if (error_printed==0) { + fprintf(stderr, "CValueList::Calc not yet implimented\n"); + error_printed = 1; + } return NULL; } - - CValue* CListValue::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue* val) { //assert(false); // todo: implement me! - fprintf(stderr, "CValueList::CalcFinal not yet implimented\n"); + static int error_printed = 0; + if (error_printed==0) { + fprintf(stderr, "CValueList::CalcFinal not yet implimented\n"); + error_printed = 1; + } return NULL; } diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/ListValue.h index 2af5a330c43..68e900e25e0 100644 --- a/source/gameengine/Expressions/ListValue.h +++ b/source/gameengine/Expressions/ListValue.h @@ -46,6 +46,7 @@ public: bool SearchValue(CValue* val); CValue* FindValue(const STR_String & name); + CValue* FindValue(const char *name); void ReleaseAndRemoveAll(); virtual void SetModified(bool bModified); @@ -60,6 +61,7 @@ public: bool CheckEqual(CValue* first,CValue* second); virtual PyObject* py_getattro(PyObject* attr); + virtual PyObject* py_getattro_dict(); virtual PyObject* py_repr(void) { PyObject *py_proxy= this->GetProxy(); PyObject *py_list= PySequence_List(py_proxy); @@ -73,6 +75,8 @@ public: KX_PYMETHOD_NOARGS(CListValue,reverse); KX_PYMETHOD_O(CListValue,index); KX_PYMETHOD_O(CListValue,count); + KX_PYMETHOD_VARARGS(CListValue,get); + KX_PYMETHOD_O(CListValue,has_key); KX_PYMETHOD_O(CListValue,from_id); diff --git a/source/gameengine/Expressions/Makefile b/source/gameengine/Expressions/Makefile index 6736149bbcd..f46c0037200 100644 --- a/source/gameengine/Expressions/Makefile +++ b/source/gameengine/Expressions/Makefile @@ -41,4 +41,5 @@ CPPFLAGS += -I../../blender/makesdna CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I../../kernel/gen_system +CPPFLAGS += -I../../gameengine/SceneGraph diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 6cfa14ddc80..defb6853e67 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -50,14 +50,20 @@ #include "stdlib.h" #include "PyObjectPlus.h" #include "STR_String.h" +#include "MT_Vector3.h" /*------------------------------ * PyObjectPlus Type -- Every class, even the abstract one should have a Type ------------------------------*/ PyTypeObject PyObjectPlus::Type = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "PyObjectPlus", /*tp_name*/ sizeof(PyObjectPlus_Proxy), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -90,6 +96,7 @@ void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper PyObjectPlus *self_plus= BGE_PROXY_REF(self); if(self_plus) { if(BGE_PROXY_PYOWNS(self)) { /* Does python own this?, then delete it */ + self_plus->m_proxy = NULL; /* Need this to stop ~PyObjectPlus from decrefing m_proxy otherwise its decref'd twice and py-debug crashes */ delete self_plus; } @@ -98,7 +105,7 @@ void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper PyObject_DEL( self ); }; -PyObjectPlus::PyObjectPlus(PyTypeObject *T) // constructor +PyObjectPlus::PyObjectPlus(PyTypeObject *T) : SG_QList() // constructor { MT_assert(T != NULL); m_proxy= NULL; @@ -113,13 +120,13 @@ PyMethodDef PyObjectPlus::Methods[] = { }; PyAttributeDef PyObjectPlus::Attributes[] = { - KX_PYATTRIBUTE_RO_FUNCTION("isValid", PyObjectPlus, pyattr_get_is_valid), + KX_PYATTRIBUTE_RO_FUNCTION("invalid", PyObjectPlus, pyattr_get_invalid), {NULL} //Sentinel }; -PyObject* PyObjectPlus::pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject* PyObjectPlus::pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - Py_RETURN_TRUE; + Py_RETURN_FALSE; } /*------------------------------ @@ -137,13 +144,33 @@ PyObject *PyObjectPlus::py_base_getattro(PyObject * self, PyObject *attr) { PyObjectPlus *self_plus= BGE_PROXY_REF(self); if(self_plus==NULL) { - if(!strcmp("isValid", PyString_AsString(attr))) { + if(!strcmp("invalid", PyString_AsString(attr))) { Py_RETURN_TRUE; } - PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); return NULL; } - return self_plus->py_getattro(attr); + + PyObject *ret= self_plus->py_getattro(attr); + + /* Attribute not found, was this a __dict__ lookup?, otherwise set an error if none is set */ + if(ret==NULL) { + char *attr_str= PyString_AsString(attr); + + if (strcmp(attr_str, "__dict__")==0) + { + /* the error string will probably not + * be set but just incase clear it */ + PyErr_Clear(); + ret= self_plus->py_getattro_dict(); + } + else if (!PyErr_Occurred()) { + /* We looked for an attribute but it wasnt found + * since py_getattro didnt set the error, set it here */ + PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", self->ob_type->tp_name, attr_str); + } + } + return ret; } /* This should be the entry in Type since it takes the C++ class from PyObjectPlus_Proxy */ @@ -151,7 +178,7 @@ int PyObjectPlus::py_base_setattro(PyObject *self, PyObject *attr, PyObject *val { PyObjectPlus *self_plus= BGE_PROXY_REF(self); if(self_plus==NULL) { - PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); return -1; } @@ -166,7 +193,7 @@ PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the ent PyObjectPlus *self_plus= BGE_PROXY_REF(self); if(self_plus==NULL) { - PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); return NULL; } @@ -177,11 +204,7 @@ PyObject *PyObjectPlus::py_getattro(PyObject* attr) { PyObject *descr = PyDict_GetItem(Type.tp_dict, attr); \ if (descr == NULL) { - if (strcmp(PyString_AsString(attr), "__dict__")==0) { - return py_getattr_dict(NULL, Type.tp_dict); /* no Attributes yet */ - } - PyErr_Format(PyExc_AttributeError, "attribute \"%s\" not found", PyString_AsString(attr)); - return NULL; + return NULL; /* py_base_getattro sets the error, this way we can avoid setting the error at many levels */ } else { /* Copied from py_getattro_up */ if (PyCObject_Check(descr)) { @@ -189,13 +212,16 @@ PyObject *PyObjectPlus::py_getattro(PyObject* attr) } else if (descr->ob_type->tp_descr_get) { return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); } else { - fprintf(stderr, "Unknown attribute type (PyObjectPlus::py_getattro)"); - return descr; + return NULL; } /* end py_getattro_up copy */ } } +PyObject* PyObjectPlus::py_getattro_dict() { + return py_getattr_dict(NULL, Type.tp_dict); +} + int PyObjectPlus::py_delattro(PyObject* attr) { PyErr_SetString(PyExc_AttributeError, "attribute cant be deleted"); @@ -233,14 +259,14 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef { bool *val = reinterpret_cast<bool*>(ptr); ptr += sizeof(bool); - PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); + PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_SHORT: { short int *val = reinterpret_cast<short int*>(ptr); ptr += sizeof(short int); - PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); + PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_ENUM: @@ -255,14 +281,14 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef { int *val = reinterpret_cast<int*>(ptr); ptr += sizeof(int); - PyList_SetItem(resultlist,i,PyInt_FromLong(*val)); + PyList_SET_ITEM(resultlist,i,PyInt_FromLong(*val)); break; } case KX_PYATTRIBUTE_TYPE_FLOAT: { float *val = reinterpret_cast<float*>(ptr); ptr += sizeof(float); - PyList_SetItem(resultlist,i,PyFloat_FromDouble(*val)); + PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble(*val)); break; } default: @@ -303,6 +329,16 @@ PyObject *PyObjectPlus::py_get_attrdef(void *self, const PyAttributeDef *attrdef float *val = reinterpret_cast<float*>(ptr); return PyFloat_FromDouble(*val); } + case KX_PYATTRIBUTE_TYPE_VECTOR: + { + PyObject* resultlist = PyList_New(3); + MT_Vector3 *val = reinterpret_cast<MT_Vector3*>(ptr); + for (unsigned int i=0; i<3; i++) + { + PyList_SET_ITEM(resultlist,i,PyFloat_FromDouble((*val)[i])); + } + return resultlist; + } case KX_PYATTRIBUTE_TYPE_STRING: { STR_String *val = reinterpret_cast<STR_String*>(ptr); @@ -326,12 +362,12 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb if (!PySequence_Check(value)) { PyErr_Format(PyExc_TypeError, "expected a sequence for attribute \"%s\"", attrdef->m_name); - return 1; + return PY_SET_ATTR_FAIL; } if (PySequence_Size(value) != attrdef->m_length) { PyErr_Format(PyExc_TypeError, "incorrect number of elements in sequence for attribute \"%s\"", attrdef->m_name); - return 1; + return PY_SET_ATTR_FAIL; } switch (attrdef->m_type) { @@ -339,7 +375,7 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb if (attrdef->m_setFunction == NULL) { PyErr_Format(PyExc_AttributeError, "function attribute without function for attribute \"%s\", report to blender.org", attrdef->m_name); - return 1; + return PY_SET_ATTR_FAIL; } return (*attrdef->m_setFunction)(self, attrdef, value); case KX_PYATTRIBUTE_TYPE_BOOL: @@ -358,7 +394,7 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb default: // should not happen PyErr_Format(PyExc_AttributeError, "Unsupported attribute type for attribute \"%s\", report to blender.org", attrdef->m_name); - return 1; + return PY_SET_ATTR_FAIL; } // let's implement a smart undo method bufferSize *= attrdef->m_length; @@ -495,6 +531,10 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb { if ((*attrdef->m_checkFunction)(self, attrdef) != 0) { + // if the checing function didnt set an error then set a generic one here so we dont set an error with no exception + if (PyErr_Occurred()==0) + PyErr_Format(PyExc_AttributeError, "type check error for attribute \"%s\", reasion unknown", attrdef->m_name); + // post check returned an error, restore values UNDO_AND_ERROR: if (undoBuffer) @@ -502,12 +542,12 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb memcpy(sourceBuffer, undoBuffer, bufferSize); free(undoBuffer); } - return 1; + return PY_SET_ATTR_FAIL; } } if (undoBuffer) free(undoBuffer); - return 0; + return PY_SET_ATTR_SUCCESS; } else // simple attribute value { @@ -516,11 +556,11 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb if (attrdef->m_setFunction == NULL) { PyErr_Format(PyExc_AttributeError, "function attribute without function \"%s\", report to blender.org", attrdef->m_name); - return 1; + return PY_SET_ATTR_FAIL; } return (*attrdef->m_setFunction)(self, attrdef, value); } - if (attrdef->m_checkFunction != NULL) + if (attrdef->m_checkFunction != NULL || attrdef->m_type == KX_PYATTRIBUTE_TYPE_VECTOR) { // post check function is provided, prepare undo buffer sourceBuffer = ptr; @@ -544,9 +584,12 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb if (sourceBuffer) bufferSize = strlen(reinterpret_cast<char*>(sourceBuffer))+1; break; + case KX_PYATTRIBUTE_TYPE_VECTOR: + bufferSize = sizeof(MT_Vector3); + break; default: PyErr_Format(PyExc_AttributeError, "unknown type for attribute \"%s\", report to blender.org", attrdef->m_name); - return 1; + return PY_SET_ATTR_FAIL; } if (bufferSize) { @@ -664,6 +707,42 @@ int PyObjectPlus::py_set_attrdef(void *self, const PyAttributeDef *attrdef, PyOb *var = (float)val; break; } + case KX_PYATTRIBUTE_TYPE_VECTOR: + { + if (!PySequence_Check(value) || PySequence_Size(value) != 3) + { + PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } + MT_Vector3 *var = reinterpret_cast<MT_Vector3*>(ptr); + for (int i=0; i<3; i++) + { + PyObject *item = PySequence_GetItem(value, i); /* new ref */ + // we can decrement the reference immediately, the reference count + // is at least 1 because the item is part of an array + Py_DECREF(item); + double val = PyFloat_AsDouble(item); + if (val == -1.0 && PyErr_Occurred()) + { + PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name); + goto RESTORE_AND_ERROR; + } + else if (attrdef->m_clamp) + { + if (val < attrdef->m_fmin) + val = attrdef->m_fmin; + else if (val > attrdef->m_fmax) + val = attrdef->m_fmax; + } + else if (val < attrdef->m_fmin || val > attrdef->m_fmax) + { + PyErr_Format(PyExc_ValueError, "value out of range for attribute \"%s\"", attrdef->m_name); + goto RESTORE_AND_ERROR; + } + (*var)[i] = (MT_Scalar)val; + } + break; + } case KX_PYATTRIBUTE_TYPE_STRING: { STR_String *var = reinterpret_cast<STR_String*>(ptr); @@ -791,6 +870,31 @@ PyObject *PyObjectPlus::PyisA(PyObject *value) // Python wrapper for isA return NULL; } + +void PyObjectPlus::ProcessReplica() +{ + /* Clear the proxy, will be created again if needed with GetProxy() + * otherwise the PyObject will point to the wrong reference */ + m_proxy= NULL; +} + +/* Sometimes we might want to manually invalidate a BGE type even if + * it hasnt been released by the BGE, say for example when an object + * is removed from a scene, accessing it may cause problems. + * + * In this case the current proxy is made invalid, disowned, + * and will raise an error on access. However if python can get access + * to this class again it will make a new proxy and work as expected. + */ +void PyObjectPlus::InvalidateProxy() // check typename of each parent +{ + if(m_proxy) { + BGE_PROXY_REF(m_proxy)=NULL; + Py_DECREF(m_proxy); + m_proxy= NULL; + } +} + /* Utility function called by the macro py_getattro_up() * for getting ob.__dict__() values from our PyObject * this is used by python for doing dir() on an object, so its good @@ -852,5 +956,80 @@ PyObject *PyObjectPlus::NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool return self->m_proxy; } +/////////////////////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////////////// +/* deprecation warning management */ + +bool PyObjectPlus::m_ignore_deprecation_warnings(false); +void PyObjectPlus::SetDeprecationWarnings(bool ignoreDeprecationWarnings) +{ + m_ignore_deprecation_warnings = ignoreDeprecationWarnings; +} + +void PyObjectPlus::ShowDeprecationWarning_func(const char* old_way,const char* new_way) +{ + { + printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way); + + // import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno) + + PyObject *getframe, *frame; + PyObject *f_lineno, *f_code, *co_filename; + + getframe = PySys_GetObject((char *)"_getframe"); // borrowed + if (getframe) { + frame = PyObject_CallObject(getframe, NULL); + if (frame) { + f_lineno= PyObject_GetAttrString(frame, "f_lineno"); + f_code= PyObject_GetAttrString(frame, "f_code"); + if (f_lineno && f_code) { + co_filename= PyObject_GetAttrString(f_code, "co_filename"); + if (co_filename) { + + printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno)); + + Py_DECREF(f_lineno); + Py_DECREF(f_code); + Py_DECREF(co_filename); + Py_DECREF(frame); + return; + } + } + + Py_XDECREF(f_lineno); + Py_XDECREF(f_code); + Py_DECREF(frame); + } + + } + PyErr_Clear(); + printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n"); + } +} + +void PyObjectPlus::ClearDeprecationWarning() +{ + WarnLink *wlink_next; + WarnLink *wlink = GetDeprecationWarningLinkFirst(); + + while(wlink) + { + wlink->warn_done= false; /* no need to NULL the link, its cleared before adding to the list next time round */ + wlink_next= reinterpret_cast<WarnLink *>(wlink->link); + wlink->link= NULL; + wlink= wlink_next; + } + NullDeprecationWarning(); +} + +WarnLink* m_base_wlink_first= NULL; +WarnLink* m_base_wlink_last= NULL; + +WarnLink* PyObjectPlus::GetDeprecationWarningLinkFirst(void) {return m_base_wlink_first;} +WarnLink* PyObjectPlus::GetDeprecationWarningLinkLast(void) {return m_base_wlink_last;} +void PyObjectPlus::SetDeprecationWarningFirst(WarnLink* wlink) {m_base_wlink_first= wlink;} +void PyObjectPlus::SetDeprecationWarningLinkLast(WarnLink* wlink) {m_base_wlink_last= wlink;} +void PyObjectPlus::NullDeprecationWarning() {m_base_wlink_first= m_base_wlink_last= NULL;} + #endif //NO_EXP_PYTHON_EMBEDDING diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/PyObjectPlus.h index 370717a919b..369c00782cc 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/PyObjectPlus.h @@ -38,11 +38,30 @@ #include "KX_Python.h" #include "STR_String.h" +#include "MT_Vector3.h" +#include "SG_QList.h" /*------------------------------ * Python defines ------------------------------*/ + + +#if PY_VERSION_HEX > 0x03000000 +#define PyString_FromString PyUnicode_FromString +#define PyString_FromFormat PyUnicode_FromFormat +#define PyString_Check PyUnicode_Check +#define PyString_Size PyUnicode_GetSize + +#define PyInt_FromLong PyLong_FromSsize_t +#define PyInt_AsLong PyLong_AsSsize_t +#define PyString_AsString _PyUnicode_AsString +#define PyInt_Check PyLong_Check +#define PyInt_AS_LONG PyLong_AsLong // TODO - check this one +#endif + + + /* Py_RETURN_NONE Python 2.4 macro. @@ -81,6 +100,36 @@ static inline void Py_Fatal(const char *M) { exit(-1); }; + +/* Use with ShowDeprecationWarning macro */ +typedef struct { + bool warn_done; + void *link; +} WarnLink; + +#define ShowDeprecationWarning(old_way, new_way) \ +{ \ + static WarnLink wlink = {false, NULL}; \ + if ((m_ignore_deprecation_warnings || wlink.warn_done)==0) \ + { \ + ShowDeprecationWarning_func(old_way, new_way); \ + WarnLink *wlink_last= GetDeprecationWarningLinkLast(); \ + ShowDeprecationWarning_func(old_way, new_way); \ + wlink.warn_done = true; \ + wlink.link = NULL; \ + \ + if(wlink_last) { \ + wlink_last->link= (void *)&(wlink); \ + SetDeprecationWarningLinkLast(&(wlink)); \ + } else { \ + SetDeprecationWarningFirst(&(wlink)); \ + SetDeprecationWarningLinkLast(&(wlink)); \ + } \ + } \ +} \ + + + typedef struct { PyObject_HEAD /* required python macro */ class PyObjectPlus *ref; @@ -92,7 +141,7 @@ typedef struct { #define BGE_PROXY_PYOWNS(_self) (((PyObjectPlus_Proxy *)_self)->py_owns) /* Note, sometimes we dont care what BGE type this is as long as its a proxy */ -#define BGE_PROXY_CHECK_TYPE(_self) ((_self)->ob_type->tp_dealloc == py_base_dealloc) +#define BGE_PROXY_CHECK_TYPE(_self) ((_self)->ob_type->tp_dealloc == PyObjectPlus::py_base_dealloc) // This must be the first line of each @@ -114,6 +163,9 @@ typedef struct { // This defines the py_getattro_up macro // which allows attribute and method calls // to be properly passed up the hierarchy. + // + // Note, PyDict_GetItem() WONT set an exception! + // let the py_base_getattro function do this. #define py_getattro_up(Parent) \ \ @@ -125,21 +177,14 @@ typedef struct { } else if (descr->ob_type->tp_descr_get) { \ return PyCFunction_New(((PyMethodDescrObject *)descr)->d_method, this->m_proxy); \ } else { \ - fprintf(stderr, "unknown attribute type"); \ - return descr; \ + return NULL; \ } \ } else { \ - PyErr_Clear(); \ - PyObject *rvalue= Parent::py_getattro(attr); \ - \ - if (strcmp(PyString_AsString(attr), "__dict__")==0) { \ - return py_getattr_dict(rvalue, Type.tp_dict); \ - } \ - \ - return rvalue; \ - } \ - return NULL; + return Parent::py_getattro(attr); \ + } +#define py_getattro_dict_up(Parent) \ + return py_getattr_dict(Parent::py_getattro_dict(), Type.tp_dict); /* * nonzero values are an error for setattr @@ -182,30 +227,35 @@ typedef struct { #define KX_PYMETHOD(class_name, method_name) \ PyObject* Py##method_name(PyObject* args, PyObject* kwds); \ static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \ + if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args, kwds); \ }; \ #define KX_PYMETHOD_VARARGS(class_name, method_name) \ PyObject* Py##method_name(PyObject* args); \ static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \ + if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args); \ }; \ #define KX_PYMETHOD_NOARGS(class_name, method_name) \ PyObject* Py##method_name(); \ static PyObject* sPy##method_name( PyObject* self) { \ + if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(); \ }; \ #define KX_PYMETHOD_O(class_name, method_name) \ PyObject* Py##method_name(PyObject* value); \ static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \ + if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(value) - " BGE_PROXY_ERROR_MSG); return NULL; } \ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(value); \ }; \ #define KX_PYMETHOD_DOC(class_name, method_name) \ PyObject* Py##method_name(PyObject* args, PyObject* kwds); \ static PyObject* sPy##method_name( PyObject* self, PyObject* args, PyObject* kwds) { \ + if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(...) - " BGE_PROXY_ERROR_MSG); return NULL; } \ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args, kwds); \ }; \ static const char method_name##_doc[]; \ @@ -213,6 +263,7 @@ typedef struct { #define KX_PYMETHOD_DOC_VARARGS(class_name, method_name) \ PyObject* Py##method_name(PyObject* args); \ static PyObject* sPy##method_name( PyObject* self, PyObject* args) { \ + if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(...) - " BGE_PROXY_ERROR_MSG); return NULL; } \ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(args); \ }; \ static const char method_name##_doc[]; \ @@ -220,6 +271,7 @@ typedef struct { #define KX_PYMETHOD_DOC_O(class_name, method_name) \ PyObject* Py##method_name(PyObject* value); \ static PyObject* sPy##method_name( PyObject* self, PyObject* value) { \ + if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "(value) - " BGE_PROXY_ERROR_MSG); return NULL; } \ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(value); \ }; \ static const char method_name##_doc[]; \ @@ -227,6 +279,7 @@ typedef struct { #define KX_PYMETHOD_DOC_NOARGS(class_name, method_name) \ PyObject* Py##method_name(); \ static PyObject* sPy##method_name( PyObject* self) { \ + if(BGE_PROXY_REF(self)==NULL) { PyErr_SetString(PyExc_SystemError, #class_name "." #method_name "() - " BGE_PROXY_ERROR_MSG); return NULL; } \ return ((class_name*)BGE_PROXY_REF(self))->Py##method_name(); \ }; \ static const char method_name##_doc[]; \ @@ -276,6 +329,7 @@ enum KX_PYATTRIBUTE_TYPE { KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_TYPE_FUNCTION, + KX_PYATTRIBUTE_TYPE_VECTOR, }; enum KX_PYATTRIBUTE_ACCESS { @@ -313,97 +367,105 @@ typedef struct KX_PYATTRIBUTE_DEF { int *m_intPtr; float *m_floatPtr; STR_String *m_stringPtr; + MT_Vector3 *m_vectorPtr; } m_typeCheck; } PyAttributeDef; #define KX_PYATTRIBUTE_DUMMY(name) \ - { name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_DUMMY, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_BOOL_RW(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_BOOL_RW_CHECK(name,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RW, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_BOOL_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_BOOL, KX_PYATTRIBUTE_RO, 0, 1, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {&((object *)0)->field, NULL, NULL, NULL, NULL, NULL} } // enum field cannot be mapped to pointer (because we would need a pointer for each enum) // use field size to verify mapping at runtime only, assuming enum size is equal to int size. #define KX_PYATTRIBUTE_ENUM_RW(name,min,max,clamp,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_ENUM_RW_CHECK(name,min,max,clamp,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), sizeof(((object *)0)->field), 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_ENUM_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_ENUM, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), sizeof(((object *)0)->field), 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_RW(name,min,max,clamp,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_RW_CHECK(name,min,max,clamp,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_ARRAY_RW(name,min,max,clamp,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_ARRAY_RO(name,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, ((object *)0)->field, NULL, NULL, NULL, NULL} } // SHORT_LIST #define KX_PYATTRIBUTE_SHORT_LIST_RW(name,min,max,clamp,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_SHORT_LIST_RO(name,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_SHORT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, &((object *)0)->field, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_INT_RW(name,min,max,clamp,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_INT_RW_CHECK(name,min,max,clamp,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_INT_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_INT_ARRAY_RW(name,min,max,clamp,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_INT_ARRAY_RW_CHECK(name,min,max,clamp,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_INT_ARRAY_RO(name,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, ((object *)0)->field, NULL, NULL, NULL} } // INT_LIST #define KX_PYATTRIBUTE_INT_LIST_RW(name,min,max,clamp,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_INT_LIST_RW_CHECK(name,min,max,clamp,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_INT_LIST_RO(name,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_INT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, &((object *)0)->field, NULL, NULL, NULL} } // always clamp for float #define KX_PYATTRIBUTE_FLOAT_RW(name,min,max,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_FLOAT_RW_CHECK(name,min,max,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_FLOAT_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, &((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_FLOAT_ARRAY_RW(name,min,max,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK(name,min,max,object,field,length,function) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, length, &object::function, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_FLOAT_ARRAY_RO(name,object,field,length) \ - { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FLOAT, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, length, NULL, NULL, NULL, {NULL, NULL, NULL, ((object *)0)->field, NULL, NULL} } #define KX_PYATTRIBUTE_STRING_RW(name,min,max,clamp,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_STRING_RW_CHECK(name,min,max,clamp,object,field,function) \ - { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RW, min, max, 0.f, 0.f, clamp, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} } #define KX_PYATTRIBUTE_STRING_RO(name,object,field) \ - { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field} } + { name, KX_PYATTRIBUTE_TYPE_STRING, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, &((object *)0)->field, NULL} } + +#define KX_PYATTRIBUTE_VECTOR_RW(name,min,max,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field} } +#define KX_PYATTRIBUTE_VECTOR_RW_CHECK(name,min,max,clamp,object,field,function) \ + { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RW, 0, 0, min, max, true, offsetof(object,field), 0, 1, &object::function, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field} } +#define KX_PYATTRIBUTE_VECTOR_RO(name,object,field) \ + { name, KX_PYATTRIBUTE_TYPE_VECTOR, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, offsetof(object,field), 0, 1 , NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, &((object *)0)->field} } #define KX_PYATTRIBUTE_RW_FUNCTION(name,object,getfunction,setfunction) \ - { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_RO_FUNCTION(name,object,getfunction) \ - { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0.f, false, 0, 0, 1, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_ARRAY_RW_FUNCTION(name,object,length,getfunction,setfunction) \ - { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0,f, false, 0, 0, length, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RW, 0, 0, 0.f, 0,f, false, 0, 0, length, NULL, &object::setfunction, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL} } #define KX_PYATTRIBUTE_ARRAY_RO_FUNCTION(name,object,length,getfunction) \ - { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0,f, false, 0, 0, length, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL} } + { name, KX_PYATTRIBUTE_TYPE_FUNCTION, KX_PYATTRIBUTE_RO, 0, 0, 0.f, 0,f, false, 0, 0, length, NULL, NULL, &object::getfunction, {NULL, NULL, NULL, NULL, NULL, NULL} } /*------------------------------ @@ -411,7 +473,18 @@ typedef struct KX_PYATTRIBUTE_DEF { ------------------------------*/ typedef PyTypeObject * PyParentObject; // Define the PyParent Object -class PyObjectPlus +// By making SG_QList the ultimate parent for PyObjectPlus objects, it +// allows to put them in 2 different dynamic lists at the same time +// The use of these links is interesting because they free of memory allocation +// but it's very important not to mess up with them. If you decide that +// the SG_QList or SG_DList component is used for something for a certain class, +// they cannot can be used for anything else at a parent level! +// What these lists are and what they are used for must be carefully documented +// at the level where they are used. +// DON'T MAKE ANY USE OF THESE LIST AT THIS LEVEL, they are already used +// at SCA_IActuator, SCA_ISensor, SCA_IController level which rules out the +// possibility to use them at SCA_ILogicBrick, CValue and PyObjectPlus level. +class PyObjectPlus : public SG_QList { // The PyObjectPlus abstract class Py_Header; // Always start with Py_Header @@ -434,6 +507,7 @@ public: /* These are all virtual python methods that are defined in each class * Our own fake subclassing calls these on each class, then calls the parent */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_delattro(PyObject *attr); virtual int py_setattro(PyObject *attr, PyObject *value); virtual PyObject* py_repr(void); @@ -449,12 +523,36 @@ public: KX_PYMETHOD_O(PyObjectPlus,isA); /* Kindof dumb, always returns True, the false case is checked for, before this function gets accessed */ - static PyObject* pyattr_get_is_valid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_invalid(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject *GetProxy_Ext(PyObjectPlus *self, PyTypeObject *tp); static PyObject *NewProxy_Ext(PyObjectPlus *self, PyTypeObject *tp, bool py_owns); + + void InvalidateProxy(); + + /** + * Makes sure any internal data owned by this class is deep copied. + */ + virtual void ProcessReplica(); + + + static bool m_ignore_deprecation_warnings; + + static WarnLink* GetDeprecationWarningLinkFirst(void); + static WarnLink* GetDeprecationWarningLinkLast(void); + static void SetDeprecationWarningFirst(WarnLink* wlink); + static void SetDeprecationWarningLinkLast(WarnLink* wlink); + static void NullDeprecationWarning(); + + /** enable/disable display of deprecation warnings */ + static void SetDeprecationWarnings(bool ignoreDeprecationWarnings); + /** Shows a deprecation warning */ + static void ShowDeprecationWarning_func(const char* method,const char* prop); + static void ClearDeprecationWarning(); + }; + PyObject *py_getattr_dict(PyObject *pydict, PyObject *tp_dict); #endif // _adr_py_lib_h_ diff --git a/source/gameengine/Expressions/SConscript b/source/gameengine/Expressions/SConscript index 25adcf3e895..b5c69eafe6b 100644 --- a/source/gameengine/Expressions/SConscript +++ b/source/gameengine/Expressions/SConscript @@ -3,7 +3,7 @@ Import ('env') sources = env.Glob('*.cpp') -incs ='. #source/kernel/gen_system #intern/string #intern/moto/include' +incs ='. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/SceneGraph' incs += ' ' + env['BF_PYTHON_INC'] cxxflags = [] diff --git a/source/gameengine/Expressions/StringValue.cpp b/source/gameengine/Expressions/StringValue.cpp index 2b3c62c411e..a7033fcf11c 100644 --- a/source/gameengine/Expressions/StringValue.cpp +++ b/source/gameengine/Expressions/StringValue.cpp @@ -34,7 +34,7 @@ effect: constructs a new CStringValue m_strString = "[Illegal String constructor call]"; } -CStringValue::CStringValue(STR_String txt,STR_String name,AllocationTYPE alloctype) +CStringValue::CStringValue(const char *txt,const char *name,AllocationTYPE alloctype) /* pre: effect: constructs a new CStringValue containing text txt @@ -133,7 +133,7 @@ bool CStringValue::IsEqual(const STR_String & other) CValue* CStringValue::GetReplica() { CStringValue* replica = new CStringValue(*this); - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; }; diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/StringValue.h index 16575ed7ffa..52f8a580f4d 100644 --- a/source/gameengine/Expressions/StringValue.h +++ b/source/gameengine/Expressions/StringValue.h @@ -26,7 +26,7 @@ class CStringValue : public CPropValue public: /// Construction / destruction CStringValue(); - CStringValue (STR_String txt, STR_String name , AllocationTYPE alloctype = CValue::HEAPVALUE); + CStringValue (const char *txt, const char *name , AllocationTYPE alloctype = CValue::HEAPVALUE); virtual ~CStringValue() { }; diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/Value.cpp index 7cb97909119..e6ef9733da8 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/Value.cpp @@ -32,13 +32,17 @@ ////////////////////////////////////////////////////////////////////// double CValue::m_sZeroVec[3] = {0.0,0.0,0.0}; -bool CValue::m_ignore_deprecation_warnings(false); #ifndef NO_EXP_PYTHON_EMBEDDING PyTypeObject CValue::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "CValue", sizeof(PyObjectPlus_Proxy), 0, @@ -62,13 +66,14 @@ PyParentObject CValue::Parents[] = { }; PyMethodDef CValue::Methods[] = { -// { "printHello", (PyCFunction) CValue::sPyPrintHello, METH_VARARGS}, { "getName", (PyCFunction) CValue::sPyGetName, METH_NOARGS}, {NULL,NULL} //Sentinel }; PyObject* CValue::PyGetName() { + ShowDeprecationWarning("getName()", "the name property"); + return PyString_FromString(this->GetName()); } @@ -287,13 +292,15 @@ CValue* CValue::GetProperty(const char *inName) // // Get text description of property with name <inName>, returns an empty string if there is no property named <inName> // -STR_String CValue::GetPropertyText(const STR_String & inName,const STR_String& deftext) +const STR_String& CValue::GetPropertyText(const STR_String & inName) { + const static STR_String sEmpty(""); + CValue *property = GetProperty(inName); if (property) return property->GetText(); else - return deftext;//String::sEmpty; + return sEmpty; } float CValue::GetPropertyNumber(const STR_String& inName,float defnumber) @@ -439,27 +446,6 @@ int CValue::GetPropertyCount() } - - - -void CValue::CloneProperties(CValue *replica) -{ - - if (m_pNamedPropertyArray) - { - replica->m_pNamedPropertyArray=NULL; - std::map<STR_String,CValue*>::iterator it; - for (it= m_pNamedPropertyArray->begin(); (it != m_pNamedPropertyArray->end()); it++) - { - CValue *val = (*it).second->GetReplica(); - replica->SetProperty((*it).first,val); - val->Release(); - } - } - - -} - double* CValue::GetVector3(bool bGetTransformedVec) { assertd(false); // don;t get vector from me @@ -470,50 +456,12 @@ double* CValue::GetVector3(bool bGetTransformedVec) /*--------------------------------------------------------------------------------------------------------------------- Reference Counting ---------------------------------------------------------------------------------------------------------------------*/ -// -// Add a reference to this value -// -CValue *CValue::AddRef() -{ - // Increase global reference count, used to see at the end of the program - // if all CValue-derived classes have been dereferenced to 0 - //debug(gRefCountValue++); -#ifdef _DEBUG - //gRefCountValue++; -#endif - m_refcount++; - return this; -} // // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) // -int CValue::Release() -{ - // Decrease global reference count, used to see at the end of the program - // if all CValue-derived classes have been dereferenced to 0 - //debug(gRefCountValue--); -#ifdef _DEBUG - //gRefCountValue--; -#endif - // Decrease local reference count, if it reaches 0 the object should be freed - if (--m_refcount > 0) - { - // Reference count normal, return new reference count - return m_refcount; - } - else - { - // Reference count reached 0, delete ourselves and return 0 -// MT_assert(m_refcount==0, "Reference count reached sub-zero, object released too much"); - - delete this; - return 0; - } - -} @@ -534,23 +482,32 @@ void CValue::DisableRefCount() -void CValue::AddDataToReplica(CValue *replica) +void CValue::ProcessReplica() /* was AddDataToReplica in 2.48 */ { - replica->m_refcount = 1; - + m_refcount = 1; + #ifdef _DEBUG //gRefCountValue++; #endif - replica->m_ValFlags.RefCountDisabled = false; + PyObjectPlus::ProcessReplica(); - replica->ReplicaSetName(GetName()); + m_ValFlags.RefCountDisabled = false; - //copy all props - CloneProperties(replica); + /* copy all props */ + if (m_pNamedPropertyArray) + { + std::map<STR_String,CValue*> *pOldArray = m_pNamedPropertyArray; + m_pNamedPropertyArray=NULL; + std::map<STR_String,CValue*>::iterator it; + for (it= pOldArray->begin(); (it != pOldArray->end()); it++) + { + CValue *val = (*it).second->GetReplica(); + SetProperty((*it).first,val); + val->Release(); + } + } } - - CValue* CValue::FindIdentifier(const STR_String& identifiername) { @@ -592,18 +549,22 @@ static PyMethodDef CValueMethods[] = }; PyAttributeDef CValue::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("name", CValue, pyattr_get_name), { NULL } //Sentinel }; PyObject* CValue::py_getattro(PyObject *attr) -{ +{ char *attr_str= PyString_AsString(attr); CValue* resultattr = GetProperty(attr_str); if (resultattr) { + /* only show the wanting here because python inspects for __class__ and KX_MeshProxy uses CValues name attr */ + ShowDeprecationWarning("val = ob.attr", "val = ob['attr']"); + PyObject* pyconvert = resultattr->ConvertValueToPython(); - + if (pyconvert) return pyconvert; else @@ -612,7 +573,16 @@ PyObject* CValue::py_getattro(PyObject *attr) py_getattro_up(PyObjectPlus); } -CValue* CValue::ConvertPythonToValue(PyObject* pyobj) +PyObject* CValue::py_getattro_dict() { + py_getattro_dict_up(PyObjectPlus); +} + +PyObject * CValue::pyattr_get_name(void * self_v, const KX_PYATTRIBUTE_DEF * attrdef) { + CValue * self = static_cast<CValue *> (self_v); + return PyString_FromString(self->GetName()); +} + +CValue* CValue::ConvertPythonToValue(PyObject* pyobj, const char *error_prefix) { CValue* vallie = NULL; @@ -628,7 +598,7 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) for (i=0;i<numitems;i++) { PyObject* listitem = PyList_GetItem(pyobj,i); /* borrowed ref */ - CValue* listitemval = ConvertPythonToValue(listitem); + CValue* listitemval = ConvertPythonToValue(listitem, error_prefix); if (listitemval) { listval->Add(listitemval); @@ -665,13 +635,22 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) { vallie = new CStringValue(PyString_AsString(pyobj),""); } else - if (pyobj->ob_type==&CValue::Type || pyobj->ob_type==&CListValue::Type) + if (BGE_PROXY_CHECK_TYPE(pyobj)) /* Note, dont let these get assigned to GameObject props, must check elsewhere */ { - vallie = ((CValue*) pyobj)->AddRef(); + if (BGE_PROXY_REF(pyobj) && (BGE_PROXY_REF(pyobj))->isA(&CValue::Type)) + { + vallie = (static_cast<CValue *>(BGE_PROXY_REF(pyobj)))->AddRef(); + } else { + + if(BGE_PROXY_REF(pyobj)) /* this is not a CValue */ + PyErr_Format(PyExc_TypeError, "%sgame engine python type cannot be used as a property", error_prefix); + else /* PyObjectPlus_Proxy has been removed, cant use */ + PyErr_Format(PyExc_SystemError, "%s"BGE_PROXY_ERROR_MSG, error_prefix); + } } else { /* return an error value from the caller */ - PyErr_SetString(PyExc_TypeError, "This python type could not be converted to a to a game engine property"); + PyErr_Format(PyExc_TypeError, "%scould convert python value to a game engine property", error_prefix); } return vallie; @@ -679,21 +658,26 @@ CValue* CValue::ConvertPythonToValue(PyObject* pyobj) int CValue::py_delattro(PyObject *attr) { + ShowDeprecationWarning("del ob.attr", "del ob['attr']"); + char *attr_str= PyString_AsString(attr); - if (RemoveProperty(STR_String(attr_str))) + if (RemoveProperty(attr_str)) return 0; PyErr_Format(PyExc_AttributeError, "attribute \"%s\" dosnt exist", attr_str); - return 1; + return PY_SET_ATTR_MISSING; } int CValue::py_setattro(PyObject *attr, PyObject* pyobj) { - char *attr_str= PyString_AsString(attr); - CValue* oldprop = GetProperty(attr_str); + ShowDeprecationWarning("ob.attr = val", "ob['attr'] = val"); - CValue* vallie = ConvertPythonToValue(pyobj); - if (vallie) + char *attr_str= PyString_AsString(attr); + CValue* oldprop = GetProperty(attr_str); + CValue* vallie; + + /* Dissallow python to assign GameObjects, Scenes etc as values */ + if ((BGE_PROXY_CHECK_TYPE(pyobj)==0) && (vallie = ConvertPythonToValue(pyobj, "cvalue.attr = value: "))) { if (oldprop) oldprop->SetValue(vallie); @@ -750,10 +734,40 @@ PyObject* CValue::PyMake(PyObject* ignored,PyObject* args) } */ +#if (PY_VERSION_HEX >= 0x03000000) +static struct PyModuleDef CValue_module_def = { + {}, /* m_base */ + "CValue", /* m_name */ + 0, /* m_doc */ + 0, /* m_size */ + CValueMethods, /* m_methods */ + 0, /* m_reload */ + 0, /* m_traverse */ + 0, /* m_clear */ + 0, /* m_free */ +}; +#endif + extern "C" { void initCValue(void) { - Py_InitModule("CValue",CValueMethods); + PyObject *m; + /* Use existing module where possible + * be careful not to init any runtime vars after this */ + m = PyImport_ImportModule( "CValue" ); + if(m) { + Py_DECREF(m); + //return m; + } + else { + PyErr_Clear(); + +#if (PY_VERSION_HEX >= 0x03000000) + PyModule_Create(&CValue_module_def); +#else + Py_InitModule("CValue",CValueMethods); +#endif + } } } @@ -779,52 +793,3 @@ void CValue::SetValue(CValue* newval) // no one should get here assertd(newval->GetNumber() == 10121969); } -/////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////// -/* deprecation warning management */ -void CValue::SetDeprecationWarnings(bool ignoreDeprecationWarnings) -{ - m_ignore_deprecation_warnings = ignoreDeprecationWarnings; -} - -void CValue::ShowDeprecationWarning(const char* old_way,const char* new_way) -{ - if (!m_ignore_deprecation_warnings) { - printf("Method %s is deprecated, please use %s instead.\n", old_way, new_way); - - // import sys; print '\t%s:%d' % (sys._getframe(0).f_code.co_filename, sys._getframe(0).f_lineno) - - PyObject *getframe, *frame; - PyObject *f_lineno, *f_code, *co_filename; - - getframe = PySys_GetObject((char *)"_getframe"); // borrowed - if (getframe) { - frame = PyObject_CallObject(getframe, NULL); - if (frame) { - f_lineno= PyObject_GetAttrString(frame, "f_lineno"); - f_code= PyObject_GetAttrString(frame, "f_code"); - if (f_lineno && f_code) { - co_filename= PyObject_GetAttrString(f_code, "co_filename"); - if (co_filename) { - - printf("\t%s:%d\n", PyString_AsString(co_filename), (int)PyInt_AsLong(f_lineno)); - - Py_DECREF(f_lineno); - Py_DECREF(f_code); - Py_DECREF(co_filename); - Py_DECREF(frame); - return; - } - } - - Py_XDECREF(f_lineno); - Py_XDECREF(f_code); - Py_DECREF(frame); - } - - } - PyErr_Clear(); - printf("\tERROR - Could not access sys._getframe(0).f_lineno or sys._getframe().f_code.co_filename\n"); - } -} - diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/Value.h index a687e1a493c..29ef19b46c9 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/Value.h @@ -225,16 +225,19 @@ public: virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual PyObject* ConvertValueToPython() { return NULL; } - virtual CValue* ConvertPythonToValue(PyObject* pyobj); + virtual CValue* ConvertPythonToValue(PyObject* pyobj, const char *error_prefix); virtual int py_delattro(PyObject *attr); virtual int py_setattro(PyObject *attr, PyObject* value); + static PyObject * pyattr_get_name(void * self, const KX_PYATTRIBUTE_DEF * attrdef); + virtual PyObject* ConvertKeysToPython( void ); KX_PYMETHOD_NOARGS(CValue,GetName); @@ -258,17 +261,56 @@ public: }; /// Reference Counting - int GetRefCount() { return m_refcount; } - virtual CValue* AddRef(); // Add a reference to this value - virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) - + int GetRefCount() + { + return m_refcount; + } + + // Add a reference to this value + CValue* AddRef() + { + // Increase global reference count, used to see at the end of the program + // if all CValue-derived classes have been dereferenced to 0 + //debug(gRefCountValue++); + #ifdef _DEBUG + //gRefCountValue++; + #endif + m_refcount++; + return this; + } + + // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) + int Release() + { + // Decrease global reference count, used to see at the end of the program + // if all CValue-derived classes have been dereferenced to 0 + //debug(gRefCountValue--); + #ifdef _DEBUG + //gRefCountValue--; + #endif + // Decrease local reference count, if it reaches 0 the object should be freed + if (--m_refcount > 0) + { + // Reference count normal, return new reference count + return m_refcount; + } + else + { + // Reference count reached 0, delete ourselves and return 0 + // MT_assert(m_refcount==0, "Reference count reached sub-zero, object released too much"); + + delete this; + return 0; + } + } + /// Property Management virtual void SetProperty(const STR_String& name,CValue* ioProperty); // Set property <ioProperty>, overwrites and releases a previous property with the same name if needed virtual void SetProperty(const char* name,CValue* ioProperty); virtual CValue* GetProperty(const char* inName); // Get pointer to a property with name <inName>, returns NULL if there is no property named <inName> virtual CValue* GetProperty(const STR_String & inName); - STR_String GetPropertyText(const STR_String & inName,const STR_String& deftext=""); // Get text description of property with name <inName>, returns an empty string if there is no property named <inName> + const STR_String& GetPropertyText(const STR_String & inName); // Get text description of property with name <inName>, returns an empty string if there is no property named <inName> float GetPropertyNumber(const STR_String& inName,float defnumber); virtual bool RemoveProperty(const char *inName); // Remove the property named <inName>, returns true if the property was succesfully removed, false if property was not found or could not be removed virtual vector<STR_String> GetPropertyNames(); @@ -280,7 +322,6 @@ public: virtual CValue* GetProperty(int inIndex); // Get property number <inIndex> virtual int GetPropertyCount(); // Get the amount of properties assiocated with this value - virtual void CloneProperties(CValue* replica); virtual CValue* FindIdentifier(const STR_String& identifiername); /** Set the wireframe color of this value depending on the CSG * operator type <op> @@ -292,21 +333,17 @@ public: double* ZeroVector() { return m_sZeroVec; }; virtual double* GetVector3(bool bGetTransformedVec = false); - virtual STR_String GetName() = 0; // Retrieve the name of the value - virtual void SetName(STR_String name) = 0; // Set the name of the value - virtual void ReplicaSetName(STR_String name) = 0; + virtual STR_String& GetName() = 0; // Retrieve the name of the value + virtual void SetName(const char *name) = 0; // Set the name of the value /** Sets the value to this cvalue. * @attention this particular function should never be called. Why not abstract? */ virtual void SetValue(CValue* newval); virtual CValue* GetReplica() =0; + virtual void ProcessReplica(); //virtual CValue* Copy() = 0; STR_String op2str(VALUE_OPERATOR op); - /** enable/disable display of deprecation warnings */ - static void SetDeprecationWarnings(bool ignoreDeprecationWarnings); - /** Shows a deprecation warning */ - static void ShowDeprecationWarning(const char* method,const char* prop); // setting / getting flags inline void SetSelected(bool bSelected) { m_ValFlags.Selected = bSelected; } @@ -327,10 +364,10 @@ public: virtual void SetCustomFlag2(bool bCustomFlag) { m_ValFlags.CustomFlag2 = bCustomFlag;}; virtual bool IsCustomFlag2() { return m_ValFlags.CustomFlag2;}; - + protected: virtual void DisableRefCount(); // Disable reference counting for this value - virtual void AddDataToReplica(CValue* replica); + //virtual void AddDataToReplica(CValue* replica); virtual ~CValue(); private: // Member variables @@ -338,7 +375,6 @@ private: ValueFlags m_ValFlags; // Frequently used flags in a bitfield (low memoryusage) int m_refcount; // Reference Counter static double m_sZeroVec[3]; - static bool m_ignore_deprecation_warnings; }; @@ -386,49 +422,28 @@ public: #else CPropValue() : #endif //NO_EXP_PYTHON_EMBEDDING - m_pstrNewName(NULL) + m_strNewName() { } virtual ~CPropValue() { - if (m_pstrNewName) - { - delete m_pstrNewName; - m_pstrNewName = NULL; - } } - virtual void SetName(STR_String name) { - if (m_pstrNewName) - { - delete m_pstrNewName; - m_pstrNewName = NULL; - } - if (name.Length()) - m_pstrNewName = new STR_String(name); - } - virtual void ReplicaSetName(STR_String name) { - m_pstrNewName=NULL; - if (name.Length()) - m_pstrNewName = new STR_String(name); + virtual void SetName(const char *name) { + m_strNewName = name; } - virtual STR_String GetName() { + virtual STR_String& GetName() { //STR_String namefromprop = GetPropertyText("Name"); //if (namefromprop.Length() > 0) // return namefromprop; - - if (m_pstrNewName) - { - return *m_pstrNewName; - } - return STR_String(""); + return m_strNewName; }; // name of Value protected: - STR_String* m_pstrNewName; // Identification + STR_String m_strNewName; // Identification }; #endif // !defined _VALUEBASECLASS_H diff --git a/source/gameengine/Expressions/VectorValue.cpp b/source/gameengine/Expressions/VectorValue.cpp index 497a50b90e7..c58c78e6ebe 100644 --- a/source/gameengine/Expressions/VectorValue.cpp +++ b/source/gameengine/Expressions/VectorValue.cpp @@ -48,7 +48,7 @@ CVectorValue::CVectorValue(float x,float y,float z, AllocationTYPE alloctype) m_vec[KX_Z] = m_transformedvec[KX_Z] = z; } -CVectorValue::CVectorValue(double vec[],STR_String name,AllocationTYPE alloctype) { +CVectorValue::CVectorValue(double vec[],const char *name,AllocationTYPE alloctype) { SetCustomFlag1(false);//FancyOutput=false; @@ -204,7 +204,7 @@ const STR_String & CVectorValue::GetText() CValue* CVectorValue::GetReplica() { CVectorValue* replica = new CVectorValue(*this); - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; }; diff --git a/source/gameengine/Expressions/VectorValue.h b/source/gameengine/Expressions/VectorValue.h index 99bf0abb11b..19c7dd30076 100644 --- a/source/gameengine/Expressions/VectorValue.h +++ b/source/gameengine/Expressions/VectorValue.h @@ -41,7 +41,7 @@ public: CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); - CVectorValue(double vec[],STR_String name,AllocationTYPE alloctype=CValue::HEAPVALUE); + CVectorValue(double vec[],const char *name,AllocationTYPE alloctype=CValue::HEAPVALUE); CVectorValue() {}; CVectorValue(double vec[],AllocationTYPE alloctype=CValue::HEAPVALUE); diff --git a/source/gameengine/GameLogic/CMakeLists.txt b/source/gameengine/GameLogic/CMakeLists.txt index a7519196d50..7e2bc85bd1f 100644 --- a/source/gameengine/GameLogic/CMakeLists.txt +++ b/source/gameengine/GameLogic/CMakeLists.txt @@ -31,6 +31,7 @@ SET(INC ../../../source/kernel/gen_system ../../../intern/string ../../../source/gameengine/Expressions + ../../../source/gameengine/SceneGraph ../../../intern/moto/include ../../../source/gameengine/Rasterizer ${PYTHON_INC} diff --git a/source/gameengine/GameLogic/Joystick/Makefile b/source/gameengine/GameLogic/Joystick/Makefile index 7016f1ed16f..02def1cec62 100644 --- a/source/gameengine/GameLogic/Joystick/Makefile +++ b/source/gameengine/GameLogic/Joystick/Makefile @@ -40,5 +40,5 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) CPPFLAGS += $(NAN_SDLCFLAGS) - +CPPFLAGS += -I../../SceneGraph CPPFLAGS += -I../../../kernel/gen_system diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp index c300baa9bd4..d83179d4f80 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp @@ -38,11 +38,9 @@ SCA_Joystick::SCA_Joystick(short int index) : m_joyindex(index), m_prec(3200), - m_buttonnum(-2), m_axismax(-1), m_buttonmax(-1), m_hatmax(-1), - m_hatdir(-2), m_isinit(0), m_istrig_axis(0), m_istrig_button(0), @@ -50,6 +48,10 @@ SCA_Joystick::SCA_Joystick(short int index) { for(int i=0; i<JOYAXIS_MAX; i++) m_axis_array[i]= 0; + + for(int i=0; i<JOYHAT_MAX; i++) + m_hat_array[i]= 0; + #ifndef DISABLE_SDL m_private = new PrivateData(); #endif @@ -65,6 +67,7 @@ SCA_Joystick::~SCA_Joystick() } SCA_Joystick *SCA_Joystick::m_instance[JOYINDEX_MAX]; +int SCA_Joystick::m_joynum = 0; int SCA_Joystick::m_refCount = 0; SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) @@ -85,6 +88,9 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) echo("Error-Initializing-SDL: " << SDL_GetError()); return NULL; } + + m_joynum = SDL_NumJoysticks(); + for (i=0; i<JOYINDEX_MAX; i++) { m_instance[i] = new SCA_Joystick(i); m_instance[i]->CreateJoystickDevice(); @@ -152,12 +158,13 @@ bool SCA_Joystick::aAxisIsPositive(int axis_single) bool SCA_Joystick::aAnyButtonPressIsPositive(void) { - return (m_buttonnum==-2) ? false : true; -} - -bool SCA_Joystick::aAnyButtonReleaseIsPositive(void) -{ - return (m_buttonnum==-2) ? true : false; + /* this is needed for the "all events" option + * so we know if there are no buttons pressed */ + for (int i=0; i<m_buttonmax; i++) + if (SDL_JoystickGetButton(m_private->m_joystick, i)) + return true; + + return false; } bool SCA_Joystick::aButtonPressIsPositive(int button) @@ -184,20 +191,9 @@ bool SCA_Joystick::aButtonReleaseIsPositive(int button) } -bool SCA_Joystick::aHatIsPositive(int dir) +bool SCA_Joystick::aHatIsPositive(int hatnum, int dir) { - bool result; - int res = pGetHat(dir); - res == dir? result = true : result = false; - return result; -} - -int SCA_Joystick::pGetHat(int direction) -{ - if(direction == m_hatdir){ - return m_hatdir; - } - return 0; + return (GetHat(hatnum)==dir) ? true : false; } int SCA_Joystick::GetNumberOfAxes() @@ -220,12 +216,17 @@ int SCA_Joystick::GetNumberOfHats() bool SCA_Joystick::CreateJoystickDevice(void) { #ifdef DISABLE_SDL + m_isinit = true; + m_axismax = m_buttonmax = m_hatmax = 0; return false; #else if(m_isinit == false){ - if (m_joyindex>=SDL_NumJoysticks()) { + if (m_joyindex>=m_joynum) { // don't print a message, because this is done anyway //echo("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); + + // Need this so python args can return empty lists + m_axismax = m_buttonmax = m_hatmax = 0; return false; } @@ -237,11 +238,16 @@ bool SCA_Joystick::CreateJoystickDevice(void) /* must run after being initialized */ m_axismax = SDL_JoystickNumAxes(m_private->m_joystick); - if (m_axismax > JOYAXIS_MAX) m_axismax= JOYAXIS_MAX; /* very unlikely */ - m_buttonmax = SDL_JoystickNumButtons(m_private->m_joystick); m_hatmax = SDL_JoystickNumHats(m_private->m_joystick); + if (m_axismax > JOYAXIS_MAX) m_axismax= JOYAXIS_MAX; /* very unlikely */ + else if (m_axismax < 0) m_axismax = 0; + + if (m_hatmax > JOYHAT_MAX) m_hatmax= JOYHAT_MAX; /* very unlikely */ + else if(m_hatmax<0) m_hatmax= 0; + + if(m_buttonmax<0) m_buttonmax= 0; } return true; @@ -271,15 +277,6 @@ int SCA_Joystick::Connected(void) return 0; } -void SCA_Joystick::pFillAxes() -{ -#ifndef DISABLE_SDL - for(int i=0; i<m_axismax; i++) - m_axis_array[i]= SDL_JoystickGetAxis(m_private->m_joystick, i); -#endif -} - - int SCA_Joystick::pGetAxis(int axisnum, int udlr) { #ifndef DISABLE_SDL diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h index 53cd65cd495..6324b898247 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.h +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.h @@ -44,6 +44,7 @@ class SCA_Joystick { static SCA_Joystick *m_instance[JOYINDEX_MAX]; + static int m_joynum; static int m_refCount; class PrivateData; @@ -53,9 +54,14 @@ class SCA_Joystick int m_joyindex; /* - *support for 2 axes + *support for JOYAXIS_MAX axes (in pairs) */ int m_axis_array[JOYAXIS_MAX]; + + /* + *support for JOYHAT_MAX hats (each is a direction) + */ + int m_hat_array[JOYHAT_MAX]; /* * Precision or range of the axes @@ -63,24 +69,6 @@ class SCA_Joystick int m_prec; /* - * multiple axis values stored here - */ - int m_axisnum; - int m_axisvalue; - - /* - * max # of axes avail - */ - /*disabled - int m_axismax; - */ - - /* - * button values stored here - */ - int m_buttonnum; - - /* * max # of buttons avail */ @@ -88,18 +76,6 @@ class SCA_Joystick int m_buttonmax; int m_hatmax; - /* - * hat values stored here - */ - int m_hatnum; - int m_hatdir; - - /* - - * max # of hats avail - disabled - int m_hatmax; - */ /* is the joystick initialized ?*/ bool m_isinit; @@ -136,7 +112,6 @@ class SCA_Joystick /* * fills the axis mnember values */ - void pFillAxes(void); void pFillButtons(void); /* @@ -149,11 +124,6 @@ class SCA_Joystick */ int pGetAxis(int axisnum, int udlr); - /* - * gets the current hat direction - */ - int pGetHat(int direction); - SCA_Joystick(short int index); ~SCA_Joystick(); @@ -172,10 +142,9 @@ public: bool aAxisIsPositive(int axis_single); /* check a single axis only */ bool aAnyButtonPressIsPositive(void); - bool aAnyButtonReleaseIsPositive(void); bool aButtonPressIsPositive(int button); bool aButtonReleaseIsPositive(int button); - bool aHatIsPositive(int dir); + bool aHatIsPositive(int hatnum, int dir); /* * precision is default '3200' which is overridden by input @@ -186,13 +155,9 @@ public: int GetAxisPosition(int index){ return m_axis_array[index]; } - - int GetButton(void){ - return m_buttonnum; - } - int GetHat(void){ - return m_hatdir; + int GetHat(int index){ + return m_hat_array[index]; } int GetThreshold(void){ diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h index 636c4dd5a42..70619ff337a 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickDefines.h @@ -40,6 +40,8 @@ #define JOYINDEX_MAX 8 #define JOYAXIS_MAX 16 +#define JOYBUT_MAX 18 +#define JOYHAT_MAX 4 #define JOYAXIS_RIGHT 0 #define JOYAXIS_UP 1 diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp index 8e190060e95..53d3be35f92 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp @@ -35,44 +35,37 @@ #ifndef DISABLE_SDL void SCA_Joystick::OnAxisMotion(SDL_Event* sdl_event) { - pFillAxes(); - m_axisnum = sdl_event->jaxis.axis; - m_axisvalue = sdl_event->jaxis.value; + if(sdl_event->jaxis.axis >= JOYAXIS_MAX) + return; + + m_axis_array[sdl_event->jaxis.axis]= sdl_event->jaxis.value; m_istrig_axis = 1; } - +/* See notes below in the event loop */ void SCA_Joystick::OnHatMotion(SDL_Event* sdl_event) { - m_hatdir = sdl_event->jhat.value; - m_hatnum = sdl_event->jhat.hat; + if(sdl_event->jhat.hat >= JOYHAT_MAX) + return; + + m_hat_array[sdl_event->jhat.hat]= sdl_event->jhat.value; m_istrig_hat = 1; } +/* See notes below in the event loop */ void SCA_Joystick::OnButtonUp(SDL_Event* sdl_event) { m_istrig_button = 1; - - /* this is needed for the "all events" option - * so we know if there are no buttons pressed */ - int i; - for (i=0; i<m_buttonmax; i++) { - if (SDL_JoystickGetButton(m_private->m_joystick, i)) { - m_buttonnum = i; - return; - } - } - m_buttonnum = -2; } void SCA_Joystick::OnButtonDown(SDL_Event* sdl_event) { - if(sdl_event->jbutton.button <= m_buttonmax) /* unsigned int so always above 0 */ - { - m_istrig_button = 1; - m_buttonnum = sdl_event->jbutton.button; - } + //if(sdl_event->jbutton.button > m_buttonmax) /* unsigned int so always above 0 */ + // return; + // sdl_event->jbutton.button; + + m_istrig_button = 1; } @@ -81,22 +74,27 @@ void SCA_Joystick::OnNothing(SDL_Event* sdl_event) m_istrig_axis = m_istrig_button = m_istrig_hat = 0; } -/* only handle events for 1 joystick */ - void SCA_Joystick::HandleEvents(void) { SDL_Event sdl_event; int i; - for (i=0; i<JOYINDEX_MAX; i++) { + for (i=0; i<m_joynum; i++) { /* could use JOYINDEX_MAX but no reason to */ if(SCA_Joystick::m_instance[i]) SCA_Joystick::m_instance[i]->OnNothing(&sdl_event); } - if(SDL_PollEvent(&sdl_event)) + while(SDL_PollEvent(&sdl_event)) { /* Note! m_instance[sdl_event.jaxis.which] * will segfault if over JOYINDEX_MAX, not too nice but what are the chances? */ + + /* Note!, with buttons, this wont care which button is pressed, + * only to set 'm_istrig_button', actual pressed buttons are detected by SDL_JoystickGetButton */ + + /* Note!, if you manage to press and release a button within 1 logic tick + * it wont work as it should */ + switch(sdl_event.type) { case SDL_JOYAXISMOTION: diff --git a/source/gameengine/GameLogic/Makefile b/source/gameengine/GameLogic/Makefile index 355ece6e8bd..a1794a60452 100644 --- a/source/gameengine/GameLogic/Makefile +++ b/source/gameengine/GameLogic/Makefile @@ -39,6 +39,7 @@ include nan_compile.mk CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I../Expressions +CPPFLAGS += -I../SceneGraph CPPFLAGS += -I../Rasterizer CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp index 251a586308e..caed85b9938 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.cpp @@ -64,8 +64,6 @@ CValue* SCA_2DFilterActuator::GetReplica() { SCA_2DFilterActuator* replica = new SCA_2DFilterActuator(*this); replica->ProcessReplica(); - CValue::AddDataToReplica(replica); - return replica; } @@ -97,7 +95,7 @@ bool SCA_2DFilterActuator::Update() } -void SCA_2DFilterActuator::SetShaderText(STR_String text) +void SCA_2DFilterActuator::SetShaderText(const char *text) { m_shaderText = text; } @@ -110,8 +108,13 @@ void SCA_2DFilterActuator::SetShaderText(STR_String text) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_2DFilterActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_2DFilterActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -146,8 +149,8 @@ PyMethodDef SCA_2DFilterActuator::Methods[] = { PyAttributeDef SCA_2DFilterActuator::Attributes[] = { KX_PYATTRIBUTE_STRING_RW("shaderText", 0, 64000, false, SCA_2DFilterActuator, m_shaderText), KX_PYATTRIBUTE_SHORT_RW("disableMotionBlur", 0, 1, true, SCA_2DFilterActuator, m_disableMotionBlur), - KX_PYATTRIBUTE_ENUM_RW("type",RAS_2DFilterManager::RAS_2DFILTER_ENABLED,RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS,false,SCA_2DFilterActuator,m_type), - KX_PYATTRIBUTE_INT_RW("passNb", 0, 100, true, SCA_2DFilterActuator, m_int_arg), + KX_PYATTRIBUTE_ENUM_RW("mode",RAS_2DFilterManager::RAS_2DFILTER_ENABLED,RAS_2DFilterManager::RAS_2DFILTER_NUMBER_OF_FILTERS,false,SCA_2DFilterActuator,m_type), + KX_PYATTRIBUTE_INT_RW("passNumber", 0, 100, true, SCA_2DFilterActuator, m_int_arg), KX_PYATTRIBUTE_FLOAT_RW("value", 0.0, 100.0, SCA_2DFilterActuator, m_float_arg), { NULL } //Sentinel }; @@ -157,6 +160,10 @@ PyObject* SCA_2DFilterActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* SCA_2DFilterActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int SCA_2DFilterActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); diff --git a/source/gameengine/GameLogic/SCA_2DFilterActuator.h b/source/gameengine/GameLogic/SCA_2DFilterActuator.h index de0201a4b19..13b9997a010 100644 --- a/source/gameengine/GameLogic/SCA_2DFilterActuator.h +++ b/source/gameengine/GameLogic/SCA_2DFilterActuator.h @@ -60,7 +60,7 @@ public: PyTypeObject* T=&Type ); - void SetShaderText(STR_String text); + void SetShaderText(const char *text); virtual ~SCA_2DFilterActuator(); virtual bool Update(); @@ -71,6 +71,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); }; diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp index 1cb03f375cb..87f7c612e7c 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.cpp +++ b/source/gameengine/GameLogic/SCA_ANDController.cpp @@ -66,26 +66,19 @@ void SCA_ANDController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (!sensor->IsPositiveTrigger()) + if (!sensor->GetState()) { sensorresult = false; break; } } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); - } @@ -94,7 +87,7 @@ CValue* SCA_ANDController::GetReplica() { CValue* replica = new SCA_ANDController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -107,8 +100,13 @@ CValue* SCA_ANDController::GetReplica() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_ANDController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_ANDController", sizeof(PyObjectPlus_Proxy), 0, @@ -145,4 +143,8 @@ PyObject* SCA_ANDController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_ANDController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ANDController.h b/source/gameengine/GameLogic/SCA_ANDController.h index fdb93d0fc42..9a359d57cb4 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.h +++ b/source/gameengine/GameLogic/SCA_ANDController.h @@ -49,6 +49,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp b/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp index 768a3a45937..a80b2af55c8 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorEventManager.cpp @@ -51,17 +51,19 @@ SCA_ActuatorEventManager::~SCA_ActuatorEventManager() void SCA_ActuatorEventManager::NextFrame() { // check for changed actuator - for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*it)->Activate(m_logicmgr,NULL); + (*it)->Activate(m_logicmgr); } } void SCA_ActuatorEventManager::UpdateFrame() { // update the state of actuator before executing them - for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + SG_DList::iterator<SCA_ActuatorSensor> it(m_sensors); + for (it.begin();!it.end();++it) { - ((SCA_ActuatorSensor*)(*it))->Update(); + (*it)->Update(); } }
\ No newline at end of file diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp index acd906ef9dd..4dad65c5a25 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.cpp @@ -60,7 +60,7 @@ CValue* SCA_ActuatorSensor::GetReplica() { SCA_ActuatorSensor* replica = new SCA_ActuatorSensor(*this); // m_range_expr must be recalculated on replica! - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); return replica; @@ -89,7 +89,7 @@ SCA_ActuatorSensor::~SCA_ActuatorSensor() -bool SCA_ActuatorSensor::Evaluate(CValue* event) +bool SCA_ActuatorSensor::Evaluate() { if (m_actuator) { @@ -122,8 +122,13 @@ void SCA_ActuatorSensor::Update() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_ActuatorSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_ActuatorSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -165,6 +170,10 @@ PyObject* SCA_ActuatorSensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_ActuatorSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_ActuatorSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); } diff --git a/source/gameengine/GameLogic/SCA_ActuatorSensor.h b/source/gameengine/GameLogic/SCA_ActuatorSensor.h index 21960993497..6655e08dc70 100644 --- a/source/gameengine/GameLogic/SCA_ActuatorSensor.h +++ b/source/gameengine/GameLogic/SCA_ActuatorSensor.h @@ -52,7 +52,7 @@ public: virtual ~SCA_ActuatorSensor(); virtual CValue* GetReplica(); virtual void Init(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void ReParent(SCA_IObject* parent); void Update(); @@ -62,6 +62,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* 3. setProperty */ diff --git a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp index 4cd2dfba994..dd3b55abcc9 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysEventManager.cpp @@ -51,9 +51,10 @@ SCA_AlwaysEventManager::SCA_AlwaysEventManager(class SCA_LogicManager* logicmgr) void SCA_AlwaysEventManager::NextFrame() { - for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*i)->Activate(m_logicmgr, NULL); + (*it)->Activate(m_logicmgr); } } diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp index b7ecb0233a1..ff02680f191 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.cpp @@ -72,7 +72,7 @@ CValue* SCA_AlwaysSensor::GetReplica() { CValue* replica = new SCA_AlwaysSensor(*this);//m_float,GetName()); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -86,7 +86,7 @@ bool SCA_AlwaysSensor::IsPositiveTrigger() -bool SCA_AlwaysSensor::Evaluate(CValue* event) +bool SCA_AlwaysSensor::Evaluate() { /* Nice! :) */ //return true; @@ -105,8 +105,13 @@ bool SCA_AlwaysSensor::Evaluate(CValue* event) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_AlwaysSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_AlwaysSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -143,4 +148,8 @@ PyObject* SCA_AlwaysSensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_AlwaysSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_AlwaysSensor.h b/source/gameengine/GameLogic/SCA_AlwaysSensor.h index 87949babf59..0f85a641ef1 100644 --- a/source/gameengine/GameLogic/SCA_AlwaysSensor.h +++ b/source/gameengine/GameLogic/SCA_AlwaysSensor.h @@ -43,7 +43,7 @@ public: PyTypeObject* T =&Type); virtual ~SCA_AlwaysSensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); @@ -53,7 +53,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); - + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.cpp b/source/gameengine/GameLogic/SCA_DelaySensor.cpp index 44a0175d916..dcdae0b4e75 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.cpp +++ b/source/gameengine/GameLogic/SCA_DelaySensor.cpp @@ -77,7 +77,7 @@ CValue* SCA_DelaySensor::GetReplica() { CValue* replica = new SCA_DelaySensor(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -89,7 +89,7 @@ bool SCA_DelaySensor::IsPositiveTrigger() return (m_invert ? !m_lastResult : m_lastResult); } -bool SCA_DelaySensor::Evaluate(CValue* event) +bool SCA_DelaySensor::Evaluate() { bool trigger = false; bool result; @@ -131,8 +131,13 @@ bool SCA_DelaySensor::Evaluate(CValue* event) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_DelaySensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_DelaySensor", sizeof(PyObjectPlus_Proxy), 0, @@ -182,6 +187,10 @@ PyObject* SCA_DelaySensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_DelaySensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_DelaySensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); } diff --git a/source/gameengine/GameLogic/SCA_DelaySensor.h b/source/gameengine/GameLogic/SCA_DelaySensor.h index 8da76ff7189..5ccb33f8a16 100644 --- a/source/gameengine/GameLogic/SCA_DelaySensor.h +++ b/source/gameengine/GameLogic/SCA_DelaySensor.h @@ -51,7 +51,7 @@ public: PyTypeObject* T =&Type); virtual ~SCA_DelaySensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); @@ -61,6 +61,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* setProperty */ diff --git a/source/gameengine/GameLogic/SCA_EventManager.cpp b/source/gameengine/GameLogic/SCA_EventManager.cpp index e4fd0379597..d1301541a0a 100644 --- a/source/gameengine/GameLogic/SCA_EventManager.cpp +++ b/source/gameengine/GameLogic/SCA_EventManager.cpp @@ -28,6 +28,7 @@ #include <assert.h> #include "SCA_EventManager.h" +#include "SCA_ISensor.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -43,16 +44,18 @@ SCA_EventManager::SCA_EventManager(EVENT_MANAGER_TYPE mgrtype) SCA_EventManager::~SCA_EventManager() { + // all sensors should be removed + assert(m_sensors.Empty()); } void SCA_EventManager::RegisterSensor(class SCA_ISensor* sensor) { - m_sensors.insert(sensor); + m_sensors.AddBack(sensor); } void SCA_EventManager::RemoveSensor(class SCA_ISensor* sensor) { - m_sensors.erase(sensor); + sensor->Delink(); } 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 9dbb5a6d24f..5ff55849bfe 100644 --- a/source/gameengine/GameLogic/SCA_EventManager.h +++ b/source/gameengine/GameLogic/SCA_EventManager.h @@ -33,11 +33,14 @@ #include <set> #include <algorithm> +#include "SG_DList.h" + class SCA_EventManager { protected: // use a set to speed-up insertion/removal - std::set <class SCA_ISensor*> m_sensors; + //std::set <class SCA_ISensor*> m_sensors; + SG_DList m_sensors; public: enum EVENT_MANAGER_TYPE { diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp index 352a39a6fea..8e044b89c71 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.cpp +++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp @@ -70,7 +70,7 @@ CValue* SCA_ExpressionController::GetReplica() replica->m_exprText = m_exprText; replica->m_exprCache = NULL; // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -115,37 +115,14 @@ void SCA_ExpressionController::Trigger(SCA_LogicManager* logicmgr) value->Release(); } - //m_exprCache->Release(); - //m_exprCache = NULL; } - /* - - for (vector<SCA_ISensor*>::const_iterator is=m_linkedsensors.begin(); - !(is==m_linkedsensors.end());is++) - { - SCA_ISensor* sensor = *is; - if (!sensor->IsPositiveTrigger()) - { - sensorresult = false; - break; - } - } - - */ - - CValue* newevent = new CBoolValue(expressionresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { SCA_IActuator* actua = *i; - logicmgr->AddActiveActuator(actua,newevent); + logicmgr->AddActiveActuator(actua,expressionresult); } - //printf("expr %d.",expressionresult); - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); } @@ -161,7 +138,7 @@ CValue* SCA_ExpressionController::FindIdentifier(const STR_String& identifiernam SCA_ISensor* sensor = *is; if (sensor->GetName() == identifiername) { - identifierval = new CBoolValue(sensor->IsPositiveTrigger()); + identifierval = new CBoolValue(sensor->GetState()); //identifierval = sensor->AddRef(); } diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.h b/source/gameengine/GameLogic/SCA_ExpressionController.h index 2936742be19..6a34d7b2dff 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.h +++ b/source/gameengine/GameLogic/SCA_ExpressionController.h @@ -60,6 +60,7 @@ public: /* --------------------------------------------------------------------- */ // virtual PyObject* py_getattro(PyObject *attr); +// virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_IActuator.cpp b/source/gameengine/GameLogic/SCA_IActuator.cpp index 309f3108418..be7c2651686 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.cpp +++ b/source/gameengine/GameLogic/SCA_IActuator.cpp @@ -37,53 +37,13 @@ using namespace std; SCA_IActuator::SCA_IActuator(SCA_IObject* gameobj, PyTypeObject* T) : SCA_ILogicBrick(gameobj,T), - m_links(0) + m_links(0), + m_posevent(false), + m_negevent(false) { // nothing to do } - - -void SCA_IActuator::AddEvent(CValue* event) -{ - m_events.push_back(event); -} - - - -void SCA_IActuator::RemoveAllEvents() -{ // remove event queue! - for (vector<CValue*>::iterator i=m_events.begin(); !(i==m_events.end());i++) - { - (*i)->Release(); - } - m_events.clear(); -} - - - - - -bool SCA_IActuator::IsNegativeEvent() const -{ - bool bPositiveEvent(false); - bool bNegativeEvent(false); - - for (vector<CValue*>::const_iterator i=m_events.begin(); i!=m_events.end();++i) - { - if ((*i)->GetNumber() == 0.0f) - { - bNegativeEvent = true; - } else { - bPositiveEvent = true; - } - } - - // if at least 1 positive event, return false - - return !bPositiveEvent && bNegativeEvent; -} - bool SCA_IActuator::Update(double curtime, bool frame) { if (frame) @@ -98,9 +58,34 @@ bool SCA_IActuator::Update() return false; } +void SCA_IActuator::Activate(SG_DList& head) +{ + if (QEmpty()) + { + InsertActiveQList(m_gameobj->m_activeActuators); + head.AddBack(&m_gameobj->m_activeActuators); + } +} + +// this function is only used to deactivate actuators outside the logic loop +// e.g. when an object is deleted. +void SCA_IActuator::Deactivate() +{ + if (QDelink()) + { + // the actuator was in the active list + if (m_gameobj->m_activeActuators.QEmpty()) + // the owner object has no more active actuators, remove it from the global list + m_gameobj->m_activeActuators.Delink(); + } +} + + void SCA_IActuator::ProcessReplica() { - m_events.clear(); + SCA_ILogicBrick::ProcessReplica(); + RemoveAllEvents(); + m_linkedcontrollers.clear(); } @@ -119,3 +104,36 @@ void SCA_IActuator::DecLink() m_links = 0; } } + +void SCA_IActuator::LinkToController(SCA_IController* controller) +{ + m_linkedcontrollers.push_back(controller); +} + +void SCA_IActuator::UnlinkController(SCA_IController* controller) +{ + std::vector<class SCA_IController*>::iterator contit; + for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit) + { + if ((*contit) == controller) + { + *contit = m_linkedcontrollers.back(); + m_linkedcontrollers.pop_back(); + return; + } + } + printf("Missing link from actuator %s:%s to controller %s:%s\n", + m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), + controller->GetParent()->GetName().ReadPtr(), controller->GetName().ReadPtr()); +} + +void SCA_IActuator::UnlinkAllControllers() +{ + std::vector<class SCA_IController*>::iterator contit; + for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit) + { + (*contit)->UnlinkActuator(this); + } + m_linkedcontrollers.clear(); +} + diff --git a/source/gameengine/GameLogic/SCA_IActuator.h b/source/gameengine/GameLogic/SCA_IActuator.h index 51bd6454d92..27afcbc386b 100644 --- a/source/gameengine/GameLogic/SCA_IActuator.h +++ b/source/gameengine/GameLogic/SCA_IActuator.h @@ -29,17 +29,32 @@ #ifndef __KX_IACTUATOR #define __KX_IACTUATOR -#include "SCA_ILogicBrick.h" +#include "SCA_IController.h" #include <vector> +/* + * Use of SG_DList : None + * Use of SG_QList : element of activated actuator list of their owner + * Head: SCA_IObject::m_activeActuators + */ class SCA_IActuator : public SCA_ILogicBrick { friend class SCA_LogicManager; protected: int m_links; // number of active links to controllers // when 0, the actuator is automatically stopped - std::vector<CValue*> m_events; - void RemoveAllEvents(); + //std::vector<CValue*> m_events; + bool m_posevent; + bool m_negevent; + + std::vector<class SCA_IController*> m_linkedcontrollers; + + void RemoveAllEvents() + { + m_posevent = false; + m_negevent = false; + } + public: /** @@ -75,7 +90,15 @@ public: /** * Add an event to an actuator. */ - void AddEvent(CValue* event); + //void AddEvent(CValue* event) + void AddEvent(bool event) + { + if (event) + m_posevent = true; + else + m_negevent = true; + } + virtual void ProcessReplica(); /** @@ -84,9 +107,23 @@ public: * not immediately clear. But usually refers to key-up events * or events where no action is required. */ - bool IsNegativeEvent() const; + bool IsNegativeEvent() const + { + return !m_posevent && m_negevent; + } + virtual ~SCA_IActuator(); + /** + * remove this actuator from the list of active actuators + */ + virtual void Deactivate(); + virtual void Activate(SG_DList& head); + + void LinkToController(SCA_IController* controller); + void UnlinkController(class SCA_IController* cont); + void UnlinkAllControllers(); + void ClrLink() { m_links=0; } void IncLink() { m_links++; } void DecLink(); diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index f9c192cae5c..f2c3c83a2d9 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -30,6 +30,8 @@ #include "SCA_LogicManager.h" #include "SCA_IActuator.h" #include "SCA_ISensor.h" +#include "PyObjectPlus.h" +#include "../Ketsji/KX_PythonSeq.h" /* not nice, only need for KX_PythonSeq_CreatePyObject */ #ifdef HAVE_CONFIG_H #include <config.h> @@ -39,7 +41,8 @@ SCA_IController::SCA_IController(SCA_IObject* gameobj, PyTypeObject* T) : SCA_ILogicBrick(gameobj,T), - m_statemask(0) + m_statemask(0), + m_justActivated(false) { } @@ -47,19 +50,19 @@ SCA_IController::SCA_IController(SCA_IObject* gameobj, SCA_IController::~SCA_IController() { - UnlinkAllActuators(); + //UnlinkAllActuators(); } -const std::vector<class SCA_ISensor*>& SCA_IController::GetLinkedSensors() +std::vector<class SCA_ISensor*>& SCA_IController::GetLinkedSensors() { return m_linkedsensors; } -const std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators() +std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators() { return m_linkedactuators; } @@ -68,13 +71,14 @@ const std::vector<class SCA_IActuator*>& SCA_IController::GetLinkedActuators() void SCA_IController::UnlinkAllSensors() { - if (IsActive()) + std::vector<class SCA_ISensor*>::iterator sensit; + for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) { - std::vector<class SCA_ISensor*>::iterator sensit; - for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) + if (IsActive()) { (*sensit)->DecLink(); } + (*sensit)->UnlinkController(this); } m_linkedsensors.clear(); } @@ -83,34 +87,18 @@ void SCA_IController::UnlinkAllSensors() void SCA_IController::UnlinkAllActuators() { - if (IsActive()) + std::vector<class SCA_IActuator*>::iterator actit; + for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit) { - std::vector<class SCA_IActuator*>::iterator actit; - for (actit = m_linkedactuators.begin();!(actit==m_linkedactuators.end());++actit) + if (IsActive()) { (*actit)->DecLink(); } + (*actit)->UnlinkController(this); } m_linkedactuators.clear(); } - - -/* -void SCA_IController::Trigger(SCA_LogicManager* logicmgr) -{ - //for (int i=0;i<m_linkedactuators.size();i++) - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); - !(i==m_linkedactuators.end());i++) - { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - - logicmgr->AddActiveActuator(actua); - } - -} -*/ - void SCA_IController::LinkToActuator(SCA_IActuator* actua) { m_linkedactuators.push_back(actua); @@ -127,18 +115,18 @@ void SCA_IController::UnlinkActuator(class SCA_IActuator* actua) { if ((*actit) == actua) { - break; - } - - } - if (!(actit==m_linkedactuators.end())) - { - if (IsActive()) - { - (*actit)->DecLink(); + if (IsActive()) + { + (*actit)->DecLink(); + } + *actit = m_linkedactuators.back(); + m_linkedactuators.pop_back(); + return; } - m_linkedactuators.erase(actit); } + printf("Missing link from controller %s:%s to actuator %s:%s\n", + m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), + actua->GetParent()->GetName().ReadPtr(), actua->GetName().ReadPtr()); } void SCA_IController::LinkToSensor(SCA_ISensor* sensor) @@ -157,20 +145,21 @@ void SCA_IController::UnlinkSensor(class SCA_ISensor* sensor) { if ((*sensit) == sensor) { - break; - } - - } - if (!(sensit==m_linkedsensors.end())) - { - if (IsActive()) - { - (*sensit)->DecLink(); + if (IsActive()) + { + sensor->DecLink(); + } + *sensit = m_linkedsensors.back(); + m_linkedsensors.pop_back(); + return; } - m_linkedsensors.erase(sensit); } + printf("Missing link from controller %s:%s to sensor %s:%s\n", + m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), + sensor->GetParent()->GetName().ReadPtr(), sensor->GetName().ReadPtr()); } + void SCA_IController::ApplyState(unsigned int state) { std::vector<class SCA_IActuator*>::iterator actit; @@ -185,13 +174,13 @@ void SCA_IController::ApplyState(unsigned int state) { (*actit)->IncLink(); } + for (sensit = m_linkedsensors.begin();!(sensit==m_linkedsensors.end());++sensit) { (*sensit)->IncLink(); - // remember that this controller just activated that sensor - (*sensit)->AddNewController(this); } SetActive(true); + m_justActivated = true; } } else if (IsActive()) { @@ -204,6 +193,168 @@ void SCA_IController::ApplyState(unsigned int state) (*sensit)->DecLink(); } SetActive(false); + m_justActivated = false; } } +/* Python api */ + +PyTypeObject SCA_IController::Type = { +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif + "SCA_IController", + sizeof(PyObjectPlus_Proxy), + 0, + py_base_dealloc, + 0, + 0, + 0, + 0, + py_base_repr, + 0,0,0,0,0,0, + py_base_getattro, + py_base_setattro, + 0,0,0,0,0,0,0,0,0, + Methods +}; + +PyParentObject SCA_IController::Parents[] = { + &SCA_IController::Type, + &CValue::Type, + NULL +}; + +PyMethodDef SCA_IController::Methods[] = { + //Deprecated functions ------> + {"getSensor", (PyCFunction) SCA_IController::sPyGetSensor, METH_O}, + {"getActuator", (PyCFunction) SCA_IController::sPyGetActuator, METH_O}, + {"getSensors", (PyCFunction) SCA_IController::sPyGetSensors, METH_NOARGS}, + {"getActuators", (PyCFunction) SCA_IController::sPyGetActuators, METH_NOARGS}, + {"getState", (PyCFunction) SCA_IController::sPyGetState, METH_NOARGS}, + //<----- Deprecated + {NULL,NULL} //Sentinel +}; + +PyAttributeDef SCA_IController::Attributes[] = { + KX_PYATTRIBUTE_RO_FUNCTION("state", SCA_IController, pyattr_get_state), + KX_PYATTRIBUTE_RO_FUNCTION("sensors", SCA_IController, pyattr_get_sensors), + KX_PYATTRIBUTE_RO_FUNCTION("actuators", SCA_IController, pyattr_get_actuators), + KX_PYATTRIBUTE_BOOL_RW("useHighPriority",SCA_IController,m_bookmark), + { NULL } //Sentinel +}; + +PyObject* SCA_IController::py_getattro(PyObject *attr) +{ + py_getattro_up(SCA_ILogicBrick); +} + +PyObject* SCA_IController::py_getattro_dict() { + py_getattro_dict_up(SCA_ILogicBrick); +} + +int SCA_IController::py_setattro(PyObject *attr, PyObject *value) +{ + py_setattro_up(SCA_ILogicBrick); +} + + + +PyObject* SCA_IController::PyGetActuators() +{ + ShowDeprecationWarning("getActuators()", "the actuators property"); + + PyObject* resultlist = PyList_New(m_linkedactuators.size()); + for (unsigned int index=0;index<m_linkedactuators.size();index++) + { + PyList_SET_ITEM(resultlist,index, m_linkedactuators[index]->GetProxy()); + } + + return resultlist; +} + +PyObject* SCA_IController::PyGetSensor(PyObject* value) +{ + ShowDeprecationWarning("getSensor(string)", "the sensors[string] property"); + + char *scriptArg = PyString_AsString(value); + if (scriptArg==NULL) { + PyErr_SetString(PyExc_TypeError, "controller.getSensor(string): Python Controller, expected a string (sensor name)"); + return NULL; + } + + for (unsigned int index=0;index<m_linkedsensors.size();index++) + { + SCA_ISensor* sensor = m_linkedsensors[index]; + STR_String& realname = sensor->GetName(); + if (realname == scriptArg) + { + return sensor->GetProxy(); + } + } + + PyErr_Format(PyExc_AttributeError, "controller.getSensor(string): Python Controller, unable to find requested sensor \"%s\"", scriptArg); + return NULL; +} + +PyObject* SCA_IController::PyGetActuator(PyObject* value) +{ + ShowDeprecationWarning("getActuator(string)", "the actuators[string] property"); + + char *scriptArg = PyString_AsString(value); + if (scriptArg==NULL) { + PyErr_SetString(PyExc_TypeError, "controller.getActuator(string): Python Controller, expected a string (actuator name)"); + return NULL; + } + + for (unsigned int index=0;index<m_linkedactuators.size();index++) + { + SCA_IActuator* actua = m_linkedactuators[index]; + if (actua->GetName() == scriptArg) + { + return actua->GetProxy(); + } + } + + PyErr_Format(PyExc_AttributeError, "controller.getActuator(string): Python Controller, unable to find requested actuator \"%s\"", scriptArg); + return NULL; +} + +PyObject* SCA_IController::PyGetSensors() +{ + ShowDeprecationWarning("getSensors()", "the sensors property"); + + PyObject* resultlist = PyList_New(m_linkedsensors.size()); + for (unsigned int index=0;index<m_linkedsensors.size();index++) + { + PyList_SET_ITEM(resultlist,index, m_linkedsensors[index]->GetProxy()); + } + + return resultlist; +} + +PyObject* SCA_IController::PyGetState() +{ + ShowDeprecationWarning("getState()", "the state property"); + return PyInt_FromLong(m_statemask); +} + +PyObject* SCA_IController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_IController* self= static_cast<SCA_IController*>(self_v); + return PyInt_FromLong(self->m_statemask); +} + +PyObject* SCA_IController::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_SENSORS); +} + +PyObject* SCA_IController::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + return KX_PythonSeq_CreatePyObject((static_cast<SCA_IController*>(self_v))->m_proxy, KX_PYGENSEQ_CONT_TYPE_ACTUATORS); +} diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h index f67c0942eb4..a52c57ab3ed 100644 --- a/source/gameengine/GameLogic/SCA_IController.h +++ b/source/gameengine/GameLogic/SCA_IController.h @@ -30,28 +30,87 @@ #define __KX_ICONTROLLER #include "SCA_ILogicBrick.h" +#include "PyObjectPlus.h" +/* + * Use of SG_DList element: none + * Use of SG_QList element: build ordered list of activated controller on the owner object + * Head: SCA_IObject::m_activeControllers + */ class SCA_IController : public SCA_ILogicBrick { + Py_Header; protected: std::vector<class SCA_ISensor*> m_linkedsensors; std::vector<class SCA_IActuator*> m_linkedactuators; unsigned int m_statemask; + bool m_justActivated; + bool m_bookmark; public: SCA_IController(SCA_IObject* gameobj,PyTypeObject* T); virtual ~SCA_IController(); virtual void Trigger(class SCA_LogicManager* logicmgr)=0; void LinkToSensor(SCA_ISensor* sensor); void LinkToActuator(SCA_IActuator*); - const std::vector<class SCA_ISensor*>& GetLinkedSensors(); - const std::vector<class SCA_IActuator*>& GetLinkedActuators(); + std::vector<class SCA_ISensor*>& GetLinkedSensors(); + std::vector<class SCA_IActuator*>& GetLinkedActuators(); + void ReserveActuator(int num) + { + m_linkedactuators.reserve(num); + } void UnlinkAllSensors(); void UnlinkAllActuators(); void UnlinkActuator(class SCA_IActuator* actua); void UnlinkSensor(class SCA_ISensor* sensor); void SetState(unsigned int state) { m_statemask = state; } void ApplyState(unsigned int state); + void Deactivate() + { + // the controller can only be part of a sensor m_newControllers list + Delink(); + } + bool IsJustActivated() + { + return m_justActivated; + } + void ClrJustActivated() + { + m_justActivated = false; + } + void SetBookmark(bool bookmark) + { + m_bookmark = bookmark; + } + void Activate(SG_DList& head) + { + if (QEmpty()) + { + if (m_bookmark) + { + m_gameobj->m_activeBookmarkedControllers.QAddBack(this); + head.AddFront(&m_gameobj->m_activeBookmarkedControllers); + } + else + { + InsertActiveQList(m_gameobj->m_activeControllers); + head.AddBack(&m_gameobj->m_activeControllers); + } + } + } + virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); + virtual int py_setattro(PyObject *attr, PyObject *value); + + KX_PYMETHOD_NOARGS(SCA_IController,GetSensors); + KX_PYMETHOD_NOARGS(SCA_IController,GetActuators); + KX_PYMETHOD_O(SCA_IController,GetSensor); + KX_PYMETHOD_O(SCA_IController,GetActuator); + KX_PYMETHOD_NOARGS(SCA_IController,GetState); + + static PyObject* pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); }; diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 3cd750ff63b..2dc80f54568 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -71,13 +71,6 @@ void SCA_ILogicBrick::SetUeberExecutePriority(int execute_Priority) -SCA_IObject* SCA_ILogicBrick::GetParent() -{ - return m_gameobj; -} - - - void SCA_ILogicBrick::ReParent(SCA_IObject* parent) { m_gameobj = parent; @@ -130,33 +123,17 @@ double SCA_ILogicBrick::GetNumber() -STR_String SCA_ILogicBrick::GetName() +STR_String& SCA_ILogicBrick::GetName() { return m_name; } -void SCA_ILogicBrick::SetName(STR_String name) -{ - m_name = name; -} - - - -void SCA_ILogicBrick::ReplicaSetName(STR_String name) +void SCA_ILogicBrick::SetName(const char *name) { m_name = name; } - - - -bool SCA_ILogicBrick::IsActive() -{ - return m_bActive; -} - - bool SCA_ILogicBrick::LessComparedTo(SCA_ILogicBrick* other) { @@ -165,22 +142,6 @@ bool SCA_ILogicBrick::LessComparedTo(SCA_ILogicBrick* other) (this->m_Execute_Priority < other->m_Execute_Priority)); } - - -void SCA_ILogicBrick::SetActive(bool active) -{ - m_bActive=active; - if (active) - { - //m_gameobj->SetDebugColor(GetDrawColor()); - } else - { - //m_gameobj->ResetDebugColor(); - } -} - - - void SCA_ILogicBrick::RegisterEvent(CValue* eventval) { if (m_eventval) @@ -217,8 +178,13 @@ CValue* SCA_ILogicBrick::GetEvent() /* python stuff */ PyTypeObject SCA_ILogicBrick::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_ILogicBrick", sizeof(PyObjectPlus_Proxy), 0, @@ -256,7 +222,8 @@ PyMethodDef SCA_ILogicBrick::Methods[] = { PyAttributeDef SCA_ILogicBrick::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("owner", SCA_ILogicBrick, pyattr_get_owner), - KX_PYATTRIBUTE_INT_RW("executePriority",0,100000,false,SCA_ILogicBrick,m_Execute_Ueber_Priority), + KX_PYATTRIBUTE_INT_RW("executePriority",0,100000,false,SCA_ILogicBrick,m_Execute_Priority), + KX_PYATTRIBUTE_STRING_RO("name", SCA_ILogicBrick, m_name), {NULL} //Sentinel }; @@ -278,12 +245,15 @@ int SCA_ILogicBrick::CheckProperty(void *self, const PyAttributeDef *attrdef) return 0; } -PyObject* -SCA_ILogicBrick::py_getattro(PyObject *attr) +PyObject* SCA_ILogicBrick::py_getattro(PyObject *attr) { py_getattro_up(CValue); } +PyObject* SCA_ILogicBrick::py_getattro_dict() { + py_getattro_dict_up(CValue); +} + int SCA_ILogicBrick::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(CValue); @@ -316,7 +286,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* args) return NULL; } - m_Execute_Ueber_Priority = priority; + m_Execute_Priority = priority; Py_RETURN_NONE; } @@ -326,7 +296,7 @@ PyObject* SCA_ILogicBrick::PySetExecutePriority(PyObject* args) PyObject* SCA_ILogicBrick::PyGetExecutePriority() { ShowDeprecationWarning("getExecutePriority()", "the executePriority property"); - return PyInt_FromLong(m_Execute_Ueber_Priority); + return PyInt_FromLong(m_Execute_Priority); } diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index e59d05ea051..779e5397a6a 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -59,7 +59,8 @@ public: void SetExecutePriority(int execute_Priority); void SetUeberExecutePriority(int execute_Priority); - SCA_IObject* GetParent(); + SCA_IObject* GetParent() { return m_gameobj; } + virtual void ReParent(SCA_IObject* parent); virtual void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); virtual void Delete() { Release(); } @@ -70,16 +71,59 @@ public: virtual const STR_String & GetText(); virtual double GetNumber(); - virtual STR_String GetName(); - virtual void SetName(STR_String name); - virtual void ReplicaSetName(STR_String name); + virtual STR_String& GetName(); + virtual void SetName(const char *); - bool IsActive(); - void SetActive(bool active) ; + bool IsActive() + { + return m_bActive; + } + + void SetActive(bool active) + { + m_bActive=active; + } + + // insert in a QList at position corresponding to m_Execute_Priority + void InsertActiveQList(SG_QList& head) + { + SG_QList::iterator<SCA_ILogicBrick> it(head); + for(it.begin(); !it.end() && m_Execute_Priority > (*it)->m_Execute_Priority; ++it); + it.add_back(this); + } + + // insert in a QList at position corresponding to m_Execute_Priority + // inside a longer list that contains elements of other objects. + // Sorting is done only between the elements of the same object. + // head is the head of the combined list + // current points to the first element of the object in the list, NULL if none yet + void InsertSelfActiveQList(SG_QList& head, SG_QList** current) + { + if (!*current) + { + // first element can be put anywhere + head.QAddBack(this); + *current = this; + return; + } + // note: we assume current points actually to one o our element, skip the tests + SG_QList::iterator<SCA_ILogicBrick> it(head,*current); + if (m_Execute_Priority <= (*it)->m_Execute_Priority) + { + // this element comes before the first + *current = this; + } + else + { + for(++it; !it.end() && (*it)->m_gameobj == m_gameobj && m_Execute_Priority > (*it)->m_Execute_Priority; ++it); + } + it.add_back(this); + } virtual bool LessComparedTo(SCA_ILogicBrick* other); virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); static class SCA_LogicManager* m_sCurrentLogicManager; diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index 75804525e7a..9876f2512c0 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -39,13 +39,13 @@ #endif MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0); +SG_QList SCA_IObject::m_activeBookmarkedControllers; + +SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T), m_initState(0), m_state(0), m_firstState(NULL) -SCA_IObject::SCA_IObject(PyTypeObject* T): CValue(T), m_initState(0), m_state(0) { m_suspended = false; } - - SCA_IObject::~SCA_IObject() { @@ -70,7 +70,7 @@ SCA_IObject::~SCA_IObject() } for (ita = m_actuators.begin(); !(ita==m_actuators.end()); ++ita) { - ((CValue*)(*ita))->Release(); + (*ita)->Delete(); } //T_InterpolatorList::iterator i; @@ -79,29 +79,6 @@ SCA_IObject::~SCA_IObject() //} } - - -SCA_ControllerList& SCA_IObject::GetControllers() -{ - return m_controllers; -} - - - -SCA_SensorList& SCA_IObject::GetSensors() -{ - return m_sensors; -} - - - -SCA_ActuatorList& SCA_IObject::GetActuators() -{ - return m_actuators; -} - - - void SCA_IObject::AddSensor(SCA_ISensor* act) { act->AddRef(); @@ -133,7 +110,7 @@ void SCA_IObject::RegisterActuator(SCA_IActuator* act) void SCA_IObject::UnregisterActuator(SCA_IActuator* act) { SCA_ActuatorList::iterator ita; - for (ita = m_registeredActuators.begin(); ita != m_registeredActuators.end(); ita++) + for (ita = m_registeredActuators.begin(); ita != m_registeredActuators.end(); ++ita) { if ((*ita) == act) { (*ita) = m_registeredActuators.back(); @@ -143,20 +120,6 @@ void SCA_IObject::UnregisterActuator(SCA_IActuator* act) } } -void SCA_IObject::SetIgnoreActivityCulling(bool b) -{ - m_ignore_activity_culling = b; -} - - - -bool SCA_IObject::GetIgnoreActivityCulling() -{ - return m_ignore_activity_culling; -} - - - void SCA_IObject::ReParentLogic() { SCA_ActuatorList& oldactuators = GetActuators(); @@ -208,7 +171,7 @@ SCA_ISensor* SCA_IObject::FindSensor(const STR_String& sensorname) { SCA_ISensor* foundsensor = NULL; - for (SCA_SensorList::iterator its = m_sensors.begin();!(its==m_sensors.end());its++) + for (SCA_SensorList::iterator its = m_sensors.begin();!(its==m_sensors.end());++its) { if ((*its)->GetName() == sensorname) { @@ -225,7 +188,7 @@ SCA_IController* SCA_IObject::FindController(const STR_String& controllername) { SCA_IController* foundcontroller = NULL; - for (SCA_ControllerList::iterator itc = m_controllers.begin();!(itc==m_controllers.end());itc++) + for (SCA_ControllerList::iterator itc = m_controllers.begin();!(itc==m_controllers.end());++itc) { if ((*itc)->GetName() == controllername) { @@ -242,7 +205,7 @@ SCA_IActuator* SCA_IObject::FindActuator(const STR_String& actuatorname) { SCA_IActuator* foundactuator = NULL; - for (SCA_ActuatorList::iterator ita = m_actuators.begin();!(ita==m_actuators.end());ita++) + for (SCA_ActuatorList::iterator ita = m_actuators.begin();!(ita==m_actuators.end());++ita) { if ((*ita)->GetName() == actuatorname) { @@ -256,14 +219,6 @@ SCA_IActuator* SCA_IObject::FindActuator(const STR_String& actuatorname) -void SCA_IObject::SetCurrentTime(float currentTime) { - //T_InterpolatorList::iterator i; - //for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { - // (*i)->Execute(currentTime); - //} -} - - #if 0 const MT_Point3& SCA_IObject::ConvertPythonPylist(PyObject* pylist) { @@ -317,7 +272,7 @@ void SCA_IObject::Suspend() SCA_SensorList::iterator i = m_sensors.begin(); while (i != m_sensors.end()) { (*i)->Suspend(); - i++; + ++i; } } } @@ -332,7 +287,7 @@ void SCA_IObject::Resume(void) SCA_SensorList::iterator i = m_sensors.begin(); while (i != m_sensors.end()) { (*i)->Resume(); - i++; + ++i; } } } @@ -352,7 +307,7 @@ void SCA_IObject::SetState(unsigned int state) if (tmpstate != m_state) { // update the status of the controllers - for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + for (contit = m_controllers.begin(); contit != m_controllers.end(); ++contit) { (*contit)->ApplyState(tmpstate); } @@ -360,7 +315,7 @@ void SCA_IObject::SetState(unsigned int state) m_state = state; if (m_state != tmpstate) { - for (contit = m_controllers.begin(); contit != m_controllers.end(); contit++) + for (contit = m_controllers.begin(); contit != m_controllers.end(); ++contit) { (*contit)->ApplyState(m_state); } @@ -375,8 +330,13 @@ void SCA_IObject::SetState(unsigned int state) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_IObject::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_IObject", sizeof(PyObjectPlus_Proxy), 0, @@ -418,3 +378,6 @@ PyObject* SCA_IObject::py_getattro(PyObject *attr) { py_getattro_up(CValue); } +PyObject* SCA_IObject::py_getattro_dict() { + py_getattro_dict_up(CValue); +} diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index 44ed3c8f3fe..eae427741ca 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -52,10 +52,30 @@ class SCA_IObject : public CValue Py_Header; protected: + friend class KX_StateActuator; + friend class SCA_IActuator; + friend class SCA_IController; SCA_SensorList m_sensors; SCA_ControllerList m_controllers; SCA_ActuatorList m_actuators; SCA_ActuatorList m_registeredActuators; // actuators that use a pointer to this object + + // SG_Dlist: element of objects with active actuators + // Head: SCA_LogicManager::m_activeActuators + // SG_QList: Head of active actuators list on this object + // Elements: SCA_IActuator + SG_QList m_activeActuators; + // SG_Dlist: element of list os lists with active controllers + // Head: SCA_LogicManager::m_activeControllers + // SG_QList: Head of active controller list on this object + // Elements: SCA_IController + SG_QList m_activeControllers; + // SG_Dlist: element of list of lists of active controllers + // Head: SCA_LogicManager::m_activeControllers + // SG_QList: Head of active bookmarked controller list globally + // Elements: SCA_IController with bookmark option + static SG_QList m_activeBookmarkedControllers; + static class MT_Point3 m_sDummy; /** @@ -78,18 +98,48 @@ protected: */ unsigned int m_state; + /** + * pointer inside state actuator list for sorting + */ + SG_QList* m_firstState; + public: SCA_IObject(PyTypeObject* T=&Type); virtual ~SCA_IObject(); - SCA_ControllerList& GetControllers(); - SCA_SensorList& GetSensors(); - SCA_ActuatorList& GetActuators(); + SCA_ControllerList& GetControllers() + { + return m_controllers; + } + SCA_SensorList& GetSensors() + { + return m_sensors; + } + SCA_ActuatorList& GetActuators() + { + return m_actuators; + } + SG_QList& GetActiveActuators() + { + return m_activeActuators; + } void AddSensor(SCA_ISensor* act); + void ReserveSensor(int num) + { + m_sensors.reserve(num); + } void AddController(SCA_IController* act); + void ReserveController(int num) + { + m_controllers.reserve(num); + } void AddActuator(SCA_IActuator* act); + void ReserveActuator(int num) + { + m_actuators.reserve(num); + } void RegisterActuator(SCA_IActuator* act); void UnregisterActuator(SCA_IActuator* act); @@ -97,20 +147,26 @@ public: SCA_IActuator* FindActuator(const STR_String& actuatorname); SCA_IController* FindController(const STR_String& controllername); - void SetCurrentTime(float currentTime); + void SetCurrentTime(float currentTime) {} void ReParentLogic(); /** * Set whether or not to ignore activity culling requests */ - void SetIgnoreActivityCulling(bool b); + void SetIgnoreActivityCulling(bool b) + { + m_ignore_activity_culling = b; + } /** * Set whether or not this object wants to ignore activity culling * requests */ - bool GetIgnoreActivityCulling(); + bool GetIgnoreActivityCulling() + { + return m_ignore_activity_culling; + } /** * Suspend all progress. @@ -146,6 +202,7 @@ public: // here come the python forwarded methods virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int GetGameObjectType() {return -1;} diff --git a/source/gameengine/GameLogic/SCA_IScene.cpp b/source/gameengine/GameLogic/SCA_IScene.cpp index 9fbeb706910..86b176a38b0 100644 --- a/source/gameengine/GameLogic/SCA_IScene.cpp +++ b/source/gameengine/GameLogic/SCA_IScene.cpp @@ -50,7 +50,7 @@ SCA_IScene::SCA_IScene() void SCA_IScene::RemoveAllDebugProperties() { for (std::vector<SCA_DebugProp*>::iterator it = m_debugList.begin(); - !(it==m_debugList.end());it++) + !(it==m_debugList.end());++it) { delete (*it); } diff --git a/source/gameengine/GameLogic/SCA_IScene.h b/source/gameengine/GameLogic/SCA_IScene.h index d18778a37c2..b641efc6ee1 100644 --- a/source/gameengine/GameLogic/SCA_IScene.h +++ b/source/gameengine/GameLogic/SCA_IScene.h @@ -52,7 +52,7 @@ public: int lifespan=0)=0; virtual void RemoveObject(class CValue* gameobj)=0; virtual void DelayedRemoveObject(class CValue* gameobj)=0; - virtual void DelayedReleaseObject(class CValue* gameobj)=0; + //virtual void DelayedReleaseObject(class CValue* gameobj)=0; virtual void ReplaceMesh(class CValue* gameobj, void* meshobj)=0; diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 68f5653d53a..2783bf14600 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -45,26 +45,28 @@ void SCA_ISensor::ReParent(SCA_IObject* parent) SCA_ILogicBrick::ReParent(parent); // will be done when the sensor is activated //m_eventmgr->RegisterSensor(this); - this->SetActive(false); + //this->SetActive(false); } SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj, class SCA_EventManager* eventmgr, PyTypeObject* T ) : - SCA_ILogicBrick(gameobj,T), - m_triggered(false) + SCA_ILogicBrick(gameobj,T) { m_links = 0; m_suspended = false; m_invert = false; m_level = false; + m_tap = false; m_reset = false; m_pos_ticks = 0; m_neg_ticks = 0; m_pos_pulsemode = false; m_neg_pulsemode = false; m_pulse_frequency = 0; + m_state = false; + m_prev_state = false; m_eventmgr = eventmgr; } @@ -75,6 +77,12 @@ SCA_ISensor::~SCA_ISensor() // intentionally empty } +void SCA_ISensor::ProcessReplica() +{ + SCA_ILogicBrick::ProcessReplica(); + m_linkedcontrollers.clear(); +} + bool SCA_ISensor::IsPositiveTrigger() { bool result = false; @@ -104,9 +112,13 @@ void SCA_ISensor::SetLevel(bool lvl) { m_level = lvl; } +void SCA_ISensor::SetTap(bool tap) { + m_tap = tap; +} + double SCA_ISensor::GetNumber() { - return IsPositiveTrigger(); + return GetState(); } void SCA_ISensor::Suspend() { @@ -143,27 +155,80 @@ void SCA_ISensor::RegisterToManager() { // sensor is just activated, initialize it Init(); - m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); + m_state = false; m_eventmgr->RegisterSensor(this); } +void SCA_ISensor::LinkToController(SCA_IController* controller) +{ + m_linkedcontrollers.push_back(controller); +} + +void SCA_ISensor::UnlinkController(SCA_IController* controller) +{ + std::vector<class SCA_IController*>::iterator contit; + for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit) + { + if ((*contit) == controller) + { + *contit = m_linkedcontrollers.back(); + m_linkedcontrollers.pop_back(); + return; + } + } + printf("Missing link from sensor %s:%s to controller %s:%s\n", + m_gameobj->GetName().ReadPtr(), GetName().ReadPtr(), + controller->GetParent()->GetName().ReadPtr(), controller->GetName().ReadPtr()); +} + +void SCA_ISensor::UnlinkAllControllers() +{ + std::vector<class SCA_IController*>::iterator contit; + for (contit = m_linkedcontrollers.begin();!(contit==m_linkedcontrollers.end());++contit) + { + (*contit)->UnlinkSensor(this); + } + m_linkedcontrollers.clear(); +} + void SCA_ISensor::UnregisterToManager() { m_eventmgr->RemoveSensor(this); + m_links = 0; +} + +void SCA_ISensor::ActivateControllers(class SCA_LogicManager* logicmgr) +{ + for(vector<SCA_IController*>::const_iterator c= m_linkedcontrollers.begin(); + c!=m_linkedcontrollers.end();++c) + { + SCA_IController* contr = *c; + if (contr->IsActive()) + logicmgr->AddTriggeredController(contr, this); + } } -void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) +void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr) { // calculate if a __triggering__ is wanted // don't evaluate a sensor that is not connected to any controller if (m_links && !m_suspended) { - bool result = this->Evaluate(event); + bool result = this->Evaluate(); + // store the state for the rest of the logic system + m_prev_state = m_state; + m_state = this->IsPositiveTrigger(); if (result) { - logicmgr->AddActivatedSensor(this); - // reset these counters so that pulse are synchronized with transition - m_pos_ticks = 0; - m_neg_ticks = 0; + // the sensor triggered this frame + if (m_state || !m_tap) { + ActivateControllers(logicmgr); + // reset these counters so that pulse are synchronized with transition + m_pos_ticks = 0; + m_neg_ticks = 0; + } else + { + result = false; + } } else { /* First, the pulsing behaviour, if pulse mode is @@ -172,41 +237,55 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr, CValue* event) if (m_pos_pulsemode) { m_pos_ticks++; if (m_pos_ticks > m_pulse_frequency) { - if ( this->IsPositiveTrigger() ) + if ( m_state ) { - logicmgr->AddActivatedSensor(this); + ActivateControllers(logicmgr); + result = true; } m_pos_ticks = 0; } } - - if (m_neg_pulsemode) + // negative pulse doesn't make sense in tap mode, skip + if (m_neg_pulsemode && !m_tap) { m_neg_ticks++; if (m_neg_ticks > m_pulse_frequency) { - if (!this->IsPositiveTrigger() ) + if (!m_state ) { - logicmgr->AddActivatedSensor(this); + ActivateControllers(logicmgr); + result = true; } m_neg_ticks = 0; } } } - if (!m_newControllers.empty()) + if (m_tap) { - if (!IsActive() && m_level) + // in tap mode: we send always a negative pulse immediately after a positive pulse + if (!result) { - // This level sensor is connected to at least one controller that was just made - // active but it did not generate an event yet, do it now to those controllers only - for (std::vector<SCA_IController*>::iterator ci=m_newControllers.begin(); - ci != m_newControllers.end(); ci++) + // the sensor did not trigger on this frame + if (m_prev_state) { - logicmgr->AddTriggeredController(*ci, this); + // but it triggered on previous frame => send a negative pulse + ActivateControllers(logicmgr); + result = true; } + // in any case, absence of trigger means sensor off + m_state = false; + } + } + if (!result && m_level) + { + // This level sensor is connected to at least one controller that was just made + // active but it did not generate an event yet, do it now to those controllers only + for(vector<SCA_IController*>::const_iterator c= m_linkedcontrollers.begin(); + c!=m_linkedcontrollers.end();++c) + { + SCA_IController* contr = *c; + if (contr->IsJustActivated()) + logicmgr->AddTriggeredController(contr, this); } - // clear the list. Instead of using clear, which also release the memory, - // use erase, which keeps the memory available for next time. - m_newControllers.erase(m_newControllers.begin(), m_newControllers.end()); } } } @@ -221,7 +300,7 @@ const char SCA_ISensor::IsPositive_doc[] = PyObject* SCA_ISensor::PyIsPositive() { ShowDeprecationWarning("isPositive()", "the read-only positive property"); - int retval = IsPositiveTrigger(); + int retval = GetState(); return PyInt_FromLong(retval); } @@ -385,6 +464,7 @@ KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset, "\tThe sensor is put in its initial state as if it was just activated.\n") { Init(); + m_prev_state = false; Py_RETURN_NONE; } @@ -393,8 +473,13 @@ KX_PYMETHODDEF_DOC_NOARGS(SCA_ISensor, reset, /* ----------------------------------------------- */ PyTypeObject SCA_ISensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_ISensor", sizeof(PyObjectPlus_Proxy), 0, @@ -453,18 +538,25 @@ PyAttributeDef SCA_ISensor::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode), KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency), KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert), - KX_PYATTRIBUTE_BOOL_RW("level",SCA_ISensor,m_level), + KX_PYATTRIBUTE_BOOL_RW_CHECK("level",SCA_ISensor,m_level,pyattr_check_level), + KX_PYATTRIBUTE_BOOL_RW_CHECK("tap",SCA_ISensor,m_tap,pyattr_check_tap), KX_PYATTRIBUTE_RO_FUNCTION("triggered", SCA_ISensor, pyattr_get_triggered), KX_PYATTRIBUTE_RO_FUNCTION("positive", SCA_ISensor, pyattr_get_positive), + //KX_PYATTRIBUTE_TODO("links"), + //KX_PYATTRIBUTE_TODO("posTicks"), + //KX_PYATTRIBUTE_TODO("negTicks"), { NULL } //Sentinel }; -PyObject* -SCA_ISensor::py_getattro(PyObject *attr) +PyObject* SCA_ISensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ILogicBrick); } +PyObject* SCA_ISensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ILogicBrick); +} + int SCA_ISensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ILogicBrick); @@ -482,7 +574,23 @@ PyObject* SCA_ISensor::pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_D PyObject* SCA_ISensor::pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); - return PyInt_FromLong(self->IsPositiveTrigger()); + return PyInt_FromLong(self->GetState()); +} + +int SCA_ISensor::pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); + if (self->m_level) + self->m_tap = false; + return 0; +} + +int SCA_ISensor::pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_ISensor* self= static_cast<SCA_ISensor*>(self_v); + if (self->m_tap) + self->m_level = false; + return 0; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 6b1c8cca104..9bbd6ed41e4 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -32,18 +32,22 @@ #ifndef __SCA_ISENSOR #define __SCA_ISENSOR -#include "SCA_ILogicBrick.h" +#include "SCA_IController.h" #include <vector> /** * Interface Class for all logic Sensors. Implements - * pulsemode,pulsefrequency */ + * pulsemode,pulsefrequency + * Use of SG_DList element: link sensors to their respective event manager + * Head: SCA_EventManager::m_sensors + * Use of SG_QList element: not used + */ class SCA_ISensor : public SCA_ILogicBrick { Py_Header; +protected: class SCA_EventManager* m_eventmgr; - bool m_triggered; /** Pulse positive pulses? */ bool m_pos_pulsemode; @@ -66,6 +70,9 @@ class SCA_ISensor : public SCA_ILogicBrick /** detect level instead of edge*/ bool m_level; + /** tap mode */ + bool m_tap; + /** sensor has been reset */ bool m_reset; @@ -75,10 +82,24 @@ class SCA_ISensor : public SCA_ILogicBrick /** number of connections to controller */ int m_links; - /** list of controllers that have just activated this sensor because of a state change */ - std::vector<class SCA_IController*> m_newControllers; + /** current sensor state */ + bool m_state; + + /** previous state (for tap option) */ + bool m_prev_state; + + std::vector<class SCA_IController*> m_linkedcontrollers; public: + + enum sensortype { + ST_NONE = 0, + ST_TOUCH, + ST_NEAR, + ST_RADAR, + // to be updated as needed + }; + SCA_ISensor(SCA_IObject* gameobj, class SCA_EventManager* eventmgr, PyTypeObject* T );; @@ -89,8 +110,8 @@ public: /* an implementation on this level. It requires an evaluate on the lower */ /* level of individual sensors. Mapping the old activate()s is easy. */ /* The IsPosTrig() also has to change, to keep things consistent. */ - void Activate(class SCA_LogicManager* logicmgr,CValue* event); - virtual bool Evaluate(CValue* event) = 0; + void Activate(class SCA_LogicManager* logicmgr); + virtual bool Evaluate() = 0; virtual bool IsPositiveTrigger(); virtual void Init(); @@ -109,23 +130,40 @@ public: void SetInvert(bool inv); /** set the level detection on or off */ void SetLevel(bool lvl); + void SetTap(bool tap); virtual void RegisterToManager(); virtual void UnregisterToManager(); + void ReserveController(int num) + { + m_linkedcontrollers.reserve(num); + } + void LinkToController(SCA_IController* controller); + void UnlinkController(SCA_IController* controller); + void UnlinkAllControllers(); + void ActivateControllers(class SCA_LogicManager* logicmgr); + + virtual void ProcessReplica(); virtual double GetNumber(); + virtual sensortype GetSensorType() { return ST_NONE; } + /** Stop sensing for a while. */ void Suspend(); /** Is this sensor switched off? */ bool IsSuspended(); + /** get the state of the sensor: positive or negative */ + bool GetState() + { + return m_state; + } + /** Resume sensing. */ void Resume(); - void AddNewController(class SCA_IController* controller) - { m_newControllers.push_back(controller); } void ClrLink() { m_links = 0; } void IncLink() @@ -137,6 +175,7 @@ public: /* Python functions: */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated functions -----> @@ -157,6 +196,8 @@ public: static PyObject* pyattr_get_triggered(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_positive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); }; #endif //__SCA_ISENSOR diff --git a/source/gameengine/GameLogic/SCA_JoystickManager.cpp b/source/gameengine/GameLogic/SCA_JoystickManager.cpp index f3ce549a637..ff8f3b1c81f 100644 --- a/source/gameengine/GameLogic/SCA_JoystickManager.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickManager.cpp @@ -59,20 +59,21 @@ SCA_JoystickManager::~SCA_JoystickManager() void SCA_JoystickManager::NextFrame(double curtime,double deltatime) { - if (m_sensors.size()==0) { + if (m_sensors.Empty()) { return; } else { - set<SCA_ISensor*>::iterator it; + ; #ifndef DISABLE_SDL SCA_Joystick::HandleEvents(); /* Handle all SDL Joystick events */ #endif - for (it = m_sensors.begin(); it != m_sensors.end(); it++) + SG_DList::iterator<SCA_JoystickSensor> it(m_sensors); + for (it.begin();!it.end();++it) { - SCA_JoystickSensor* joysensor = (SCA_JoystickSensor*)(*it); + SCA_JoystickSensor* joysensor = *it; if(!joysensor->IsSuspended()) { - joysensor->Activate(m_logicmgr, NULL); + joysensor->Activate(m_logicmgr); } } } diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 1c601eded81..336529667d7 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -87,7 +87,7 @@ CValue* SCA_JoystickSensor::GetReplica() { SCA_JoystickSensor* replica = new SCA_JoystickSensor(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); return replica; } @@ -102,7 +102,7 @@ bool SCA_JoystickSensor::IsPositiveTrigger() } -bool SCA_JoystickSensor::Evaluate(CValue* event) +bool SCA_JoystickSensor::Evaluate() { SCA_Joystick *js = m_pJoystickMgr->GetJoystickDevice(m_joyindex); bool result = false; @@ -198,33 +198,20 @@ bool SCA_JoystickSensor::Evaluate(CValue* event) case KX_JOYSENSORMODE_HAT: { /* what is what! - numberof = m_hat -- max 2 + numberof = m_hat -- max 4 direction= m_hatf -- max 12 */ if (!js->IsTrigHat() && !reset) /* No events from SDL? - dont bother */ return false; - if(m_hat == 1){ - if(js->aHatIsPositive(m_hatf)){ - m_istrig = 1; - result = true; - }else{ - if(m_istrig){ - m_istrig = 0; - result = true; - } - } - } - if(m_hat == 2){ - if(js->aHatIsPositive(m_hatf)){ - m_istrig = 1; + if((m_bAllEvents && js->GetHat(m_hat-1)) || js->aHatIsPositive(m_hat-1, m_hatf)) { + m_istrig = 1; + result = true; + }else{ + if(m_istrig){ + m_istrig = 0; result = true; - }else{ - if(m_istrig){ - m_istrig = 0; - result = true; - } } } break; @@ -266,8 +253,13 @@ bool SCA_JoystickSensor::isValid(SCA_JoystickSensor::KX_JOYSENSORMODE m) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_JoystickSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_JoystickSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -326,11 +318,13 @@ PyAttributeDef SCA_JoystickSensor::Attributes[] = { KX_PYATTRIBUTE_INT_LIST_RW_CHECK("hat",0,12,true,SCA_JoystickSensor,m_hat,2,CheckHat), KX_PYATTRIBUTE_RO_FUNCTION("axisValues", SCA_JoystickSensor, pyattr_get_axis_values), KX_PYATTRIBUTE_RO_FUNCTION("axisSingle", SCA_JoystickSensor, pyattr_get_axis_single), + KX_PYATTRIBUTE_RO_FUNCTION("hatValues", SCA_JoystickSensor, pyattr_get_hat_values), + KX_PYATTRIBUTE_RO_FUNCTION("hatSingle", SCA_JoystickSensor, pyattr_get_hat_single), KX_PYATTRIBUTE_RO_FUNCTION("numAxis", SCA_JoystickSensor, pyattr_get_num_axis), KX_PYATTRIBUTE_RO_FUNCTION("numButtons", SCA_JoystickSensor, pyattr_get_num_buttons), KX_PYATTRIBUTE_RO_FUNCTION("numHats", SCA_JoystickSensor, pyattr_get_num_hats), KX_PYATTRIBUTE_RO_FUNCTION("connected", SCA_JoystickSensor, pyattr_get_connected), - + //KX_PYATTRIBUTE_TODO("events"), { NULL } //Sentinel }; @@ -339,6 +333,10 @@ PyObject* SCA_JoystickSensor::py_getattro(PyObject *attr) py_getattro_up(SCA_ISensor); } +PyObject* SCA_JoystickSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_JoystickSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); @@ -394,6 +392,8 @@ PyObject* SCA_JoystickSensor::PySetAxis( PyObject* args ) { } m_axis = axis; m_axisf = axisflag; + + CheckAxis((void *)this, NULL); /* clamp values */ Py_RETURN_NONE; } @@ -535,6 +535,8 @@ PyObject* SCA_JoystickSensor::PySetHat( PyObject* args ) { } m_hat = hat; m_hatf = hatflag; + + CheckHat((void *)this, NULL); /* clamp values */ Py_RETURN_NONE; } @@ -608,6 +610,29 @@ PyObject* SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT return PyInt_FromLong(joy->GetAxisPosition(self->m_axis-1)); } +PyObject* SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v); + SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); + + int hat_index= joy->GetNumberOfHats(); + PyObject *list= PyList_New(hat_index); + + while(hat_index--) { + PyList_SET_ITEM(list, hat_index, PyInt_FromLong(joy->GetHat(hat_index))); + } + + return list; +} + +PyObject* SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v); + SCA_Joystick *joy = self->m_pJoystickMgr->GetJoystickDevice(self->m_joyindex); + + return PyInt_FromLong(joy->GetHat(self->m_hat-1)); +} + PyObject* SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_JoystickSensor* self= static_cast<SCA_JoystickSensor*>(self_v); diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.h b/source/gameengine/GameLogic/SCA_JoystickSensor.h index cf3e7e74414..e6a1d2eef32 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.h +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.h @@ -30,6 +30,7 @@ #define __JOYSENSOR_H #include "SCA_ISensor.h" +#include "./Joystick/SCA_JoystickDefines.h" class SCA_JoystickSensor :public SCA_ISensor { @@ -37,7 +38,7 @@ class SCA_JoystickSensor :public SCA_ISensor class SCA_JoystickManager* m_pJoystickMgr; /** - * Axis 1-or-2, MUST be followed by m_axisf + * Axis 1-JOYAXIS_MAX, MUST be followed by m_axisf */ int m_axis; /** @@ -53,11 +54,11 @@ class SCA_JoystickSensor :public SCA_ISensor */ int m_buttonf; /** - * The actual hat. MUST be followed by m_hatf + * The actual hat 1-JOYHAT_MAX. MUST be followed by m_hatf */ int m_hat; /** - * Flag to find direction 0-11, MUST be an int + * Flag to find direction 1-12, MUST be an int */ int m_hatf; /** @@ -110,7 +111,7 @@ public: virtual ~SCA_JoystickSensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); @@ -123,6 +124,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* Joystick Index */ @@ -151,6 +153,8 @@ public: static PyObject* pyattr_get_axis_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_axis_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_hat_single(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_num_buttons(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_num_hats(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); @@ -163,8 +167,8 @@ public: SCA_JoystickSensor* sensor = reinterpret_cast<SCA_JoystickSensor*>(self); if (sensor->m_axis < 1) sensor->m_axis = 1; - else if (sensor->m_axis > 2) - sensor->m_axis = 2; + else if (sensor->m_axis > JOYAXIS_MAX) + sensor->m_axis = JOYAXIS_MAX; return 0; } static int CheckHat(void *self, const PyAttributeDef*) @@ -172,8 +176,8 @@ public: SCA_JoystickSensor* sensor = reinterpret_cast<SCA_JoystickSensor*>(self); if (sensor->m_hat < 1) sensor->m_hat = 1; - else if (sensor->m_hat > 2) - sensor->m_hat = 2; + else if (sensor->m_hat > JOYHAT_MAX) + sensor->m_hat = JOYHAT_MAX; return 0; } diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp index 6a96442b124..279adab94d8 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp @@ -62,12 +62,11 @@ void SCA_KeyboardManager::NextFrame() { //const SCA_InputEvent& event = GetEventValue(SCA_IInputDevice::KX_EnumInputs inputcode)=0; // cerr << "SCA_KeyboardManager::NextFrame"<< endl; - set<SCA_ISensor*>::iterator it; - for (it=m_sensors.begin(); it != m_sensors.end(); it++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*it)->Activate(m_logicmanager,NULL); + (*it)->Activate(m_logicmanager); } - } bool SCA_KeyboardManager::IsPressed(SCA_IInputDevice::KX_EnumInputs inputcode) diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index c946156283f..f8ee8ed8b41 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -85,7 +85,7 @@ CValue* SCA_KeyboardSensor::GetReplica() { SCA_KeyboardSensor* replica = new SCA_KeyboardSensor(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); return replica; } @@ -118,7 +118,7 @@ bool SCA_KeyboardSensor::TriggerOnAllKeys() -bool SCA_KeyboardSensor::Evaluate(CValue* eventval) +bool SCA_KeyboardSensor::Evaluate() { bool result = false; bool reset = m_reset && m_level; @@ -195,6 +195,9 @@ bool SCA_KeyboardSensor::Evaluate(CValue* eventval) } } } + if (m_tap) + // special case for tap mode: only generate event for new activation + result = false; } @@ -612,8 +615,13 @@ KX_PYMETHODDEF_DOC_O(SCA_KeyboardSensor, getKeyStatus, /* ------------------------------------------------------------------------- */ PyTypeObject SCA_KeyboardSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_KeyboardSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -664,12 +672,15 @@ PyAttributeDef SCA_KeyboardSensor::Attributes[] = { { NULL } //Sentinel }; -PyObject* -SCA_KeyboardSensor::py_getattro(PyObject *attr) +PyObject* SCA_KeyboardSensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_KeyboardSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_KeyboardSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); @@ -691,7 +702,7 @@ PyObject* SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBU { PyObject* keypair = PyList_New(2); PyList_SET_ITEM(keypair,0,PyInt_FromLong(i)); - PyList_SetItem(keypair,1,PyInt_FromLong(inevent.m_status)); + PyList_SET_ITEM(keypair,1,PyInt_FromLong(inevent.m_status)); PyList_Append(resultlist,keypair); } } diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index 073b3e6dbe0..033225cd9be 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -102,7 +102,7 @@ public: short int GetHotkey(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); bool TriggerOnAllKeys(); @@ -111,6 +111,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated functions -----> diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index b584b37180f..83271288154 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -49,37 +49,14 @@ SCA_LogicManager::SCA_LogicManager() SCA_LogicManager::~SCA_LogicManager() { - /* AddRef() is not used when the objects are added to m_mapStringToGameObjects - so Release() should not be used either. The memory leak big is fixed - in BL_ConvertBlenderObjects() - - int numgameobj = m_mapStringToGameObjects.size(); - for (int i = 0; i < numgameobj; i++) - { - CValue** gameobjptr = m_mapStringToGameObjects.at(i); - assert(gameobjptr); - if (gameobjptr) - (*gameobjptr)->Release(); - - } - */ - /*for (int i=0;i<m_sensorcontrollermap.size();i++) - { - vector<SCA_IController*>* controllerarray = *(m_sensorcontrollermap[i]); - delete controllerarray; - } - */ - for (vector<SCA_EventManager*>::iterator it = m_eventmanagers.begin();!(it==m_eventmanagers.end());it++) + for (vector<SCA_EventManager*>::iterator it = m_eventmanagers.begin();!(it==m_eventmanagers.end());++it) { delete (*it); } m_eventmanagers.clear(); - m_sensorcontrollermapje.clear(); - m_removedActuators.clear(); - m_activeActuators.clear(); + assert(m_activeActuators.Empty()); } - /* // this kind of fixes bug 398 but breakes games, so better leave it out for now. // a removed object's gameobject (and logicbricks and stuff) didn't get released @@ -171,12 +148,7 @@ void* SCA_LogicManager::FindBlendObjByGameMeshName(const STR_String& gamemeshnam void SCA_LogicManager::RemoveSensor(SCA_ISensor* sensor) { - controllerlist contlist = m_sensorcontrollermapje[sensor]; - for (controllerlist::const_iterator c= contlist.begin();!(c==contlist.end());c++) - { - (*c)->UnlinkSensor(sensor); - } - m_sensorcontrollermapje.erase(sensor); + sensor->UnlinkAllControllers(); sensor->UnregisterToManager(); } @@ -184,35 +156,22 @@ void SCA_LogicManager::RemoveController(SCA_IController* controller) { controller->UnlinkAllSensors(); controller->UnlinkAllActuators(); - std::map<SCA_ISensor*,controllerlist>::iterator sit; - for (sit = m_sensorcontrollermapje.begin();!(sit==m_sensorcontrollermapje.end());++sit) - { - (*sit).second.remove(controller); - } + controller->Deactivate(); } -void SCA_LogicManager::RemoveDestroyedActuator(SCA_IActuator* actuator) +void SCA_LogicManager::RemoveActuator(SCA_IActuator* actuator) { - m_removedActuators.push_back(SmartActuatorPtr(actuator,0)); - // take care that no controller can use this actuator again ! - - std::map<SCA_ISensor*,controllerlist>::const_iterator sit; - for (sit = m_sensorcontrollermapje.begin();!(sit==m_sensorcontrollermapje.end());++sit) - { - controllerlist contlist = (*sit).second; - for (list<SCA_IController*>::const_iterator c= contlist.begin();!(c==contlist.end());c++) - { - (*c)->UnlinkActuator(actuator); - } - } + actuator->UnlinkAllControllers(); + actuator->Deactivate(); + actuator->SetActive(false); } void SCA_LogicManager::RegisterToSensor(SCA_IController* controller,SCA_ISensor* sensor) { - m_sensorcontrollermapje[sensor].push_back(controller); + sensor->LinkToController(controller); controller->LinkToSensor(sensor); } @@ -220,6 +179,7 @@ void SCA_LogicManager::RegisterToSensor(SCA_IController* controller,SCA_ISensor* void SCA_LogicManager::RegisterToActuator(SCA_IController* controller,SCA_IActuator* actua) { + actua->LinkToController(controller); controller->LinkToActuator(actua); } @@ -230,88 +190,62 @@ void SCA_LogicManager::BeginFrame(double curtime, double fixedtime) for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin(); !(ie==m_eventmanagers.end()); ie++) (*ie)->NextFrame(curtime, fixedtime); - // for this frame, look up for activated sensors, and build the collection of triggered controllers - // int numsensors = this->m_activatedsensors.size(); /*unused*/ - - for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin(); - !(is==m_activatedsensors.end());is++) + for(SG_QList* obj = (SG_QList*)m_triggeredControllerSet.Remove(); + obj != NULL; + obj = (SG_QList*)m_triggeredControllerSet.Remove()) { - SCA_ISensor* sensor = *is; - controllerlist contlist = m_sensorcontrollermapje[sensor]; - for (list<SCA_IController*>::const_iterator c= contlist.begin(); - !(c==contlist.end());c++) + for(SCA_IController* contr = (SCA_IController*)obj->QRemove(); + contr != NULL; + contr = (SCA_IController*)obj->QRemove()) { - SCA_IController* contr = *c;//controllerarray->at(c); - if (contr->IsActive()) - { - m_triggeredControllerSet.insert(SmartControllerPtr(contr,0)); - // So that the controller knows which sensor has activited it. - // Only needed for the python controller though. - if (contr->GetType() == &SCA_PythonController::Type) - { - SCA_PythonController* pythonController = (SCA_PythonController*)contr; - pythonController->AddTriggeredSensor(sensor); - } - } + contr->Trigger(this); + contr->ClrJustActivated(); } - //sensor->SetActive(false); } - - - // int numtriggered = triggeredControllerSet.size(); /*unused*/ - for (set<SmartControllerPtr>::iterator tit=m_triggeredControllerSet.begin(); - !(tit==m_triggeredControllerSet.end());tit++) - { - (*tit)->Trigger(this); - } - m_triggeredControllerSet.clear(); } void SCA_LogicManager::UpdateFrame(double curtime, bool frame) { - vector<SmartActuatorPtr>::iterator ra; - for (ra = m_removedActuators.begin(); !(ra == m_removedActuators.end()); ra++) - { - m_activeActuators.erase(*ra); - (*ra)->SetActive(false); - } - m_removedActuators.clear(); - - // About to run actuators, but before update the sensors for those which depends on actuators for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin(); !(ie==m_eventmanagers.end()); ie++) (*ie)->UpdateFrame(); - for (set<SmartActuatorPtr>::iterator ia = m_activeActuators.begin();!(ia==m_activeActuators.end());ia++) + SG_DList::iterator<SG_QList> io(m_activeActuators); + for (io.begin(); !io.end(); ) { - //SCA_IActuator* actua = *ia; - if (!(*ia)->Update(curtime, frame)) + SG_QList* ahead = *io; + // increment now so that we can remove the current element + ++io; + SG_QList::iterator<SCA_IActuator> ia(*ahead); + for (ia.begin(); !ia.end(); ) { - //*ia = m_activeactuators.back(); - m_removedActuators.push_back(*ia); - - (*ia)->SetActive(false); - //m_activeactuators.pop_back(); - } else if ((*ia)->IsNoLink()) + SCA_IActuator* actua = *ia; + // increment first to allow removal of inactive actuators. + ++ia; + if (!actua->Update(curtime, frame)) + { + // this actuator is not active anymore, remove + actua->QDelink(); + actua->SetActive(false); + } else if (actua->IsNoLink()) + { + // This actuator has no more links but it still active + // make sure it will get a negative event on next frame to stop it + // Do this check after Update() rather than before to make sure + // that all the actuators that are activated at same time than a state + // actuator have a chance to execute. + bool event = false; + actua->RemoveAllEvents(); + actua->AddEvent(event); + } + } + if (ahead->QEmpty()) { - // This actuator has no more links but it still active - // make sure it will get a negative event on next frame to stop it - // Do this check after Update() rather than before to make sure - // that all the actuators that are activated at same time than a state - // actuator have a chance to execute. - CValue* event = new CBoolValue(false); - (*ia)->RemoveAllEvents(); - (*ia)->AddEvent(event); + // no more active controller, remove from main list + ahead->Delink(); } } - - for ( ra = m_removedActuators.begin(); !(ra == m_removedActuators.end()); ra++) - { - m_activeActuators.erase(*ra); - (*ra)->SetActive(false); - } - m_removedActuators.clear(); } @@ -360,39 +294,17 @@ void SCA_LogicManager::RegisterActionName(const STR_String& actname,void* action void SCA_LogicManager::EndFrame() { - for (vector<SCA_ISensor*>::const_iterator is=m_activatedsensors.begin(); - !(is==m_activatedsensors.end());is++) - { - SCA_ISensor* sensor = *is; - sensor->SetActive(false); - } - m_activatedsensors.clear(); - for (vector<SCA_EventManager*>::const_iterator ie=m_eventmanagers.begin(); !(ie==m_eventmanagers.end());ie++) { (*ie)->EndFrame(); } - - } - -void SCA_LogicManager::AddActivatedSensor(SCA_ISensor* sensor) -{ - // each frame, only add sensor once, and to avoid a seek, or bloated container - // hold a flag in each sensor, with the 'framenr' - if (!sensor->IsActive()) - { - sensor->SetActive(true); - m_activatedsensors.push_back(sensor); - } -} - void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor) { - m_triggeredControllerSet.insert(SmartControllerPtr(controller,0)); + controller->Activate(m_triggeredControllerSet); // so that the controller knows which sensor has activited it // only needed for python controller if (controller->GetType() == &SCA_PythonController::Type) @@ -402,19 +314,6 @@ void SCA_LogicManager::AddTriggeredController(SCA_IController* controller, SCA_I } } - -void SCA_LogicManager::AddActiveActuator(SCA_IActuator* actua,CValue* event) -{ - if (!actua->IsActive()) - { - actua->SetActive(true); - m_activeActuators.insert(SmartActuatorPtr(actua,0)); - } - actua->AddEvent(event->AddRef()); -} - - - SCA_EventManager* SCA_LogicManager::FindEventManager(int eventmgrtype) { // find an eventmanager of a certain type @@ -432,109 +331,3 @@ SCA_EventManager* SCA_LogicManager::FindEventManager(int eventmgrtype) } return eventmgr; } - - - -SmartActuatorPtr::SmartActuatorPtr(const SmartActuatorPtr& other) -{ - this->m_actuator = other.m_actuator; - this->m_actuator->AddRef(); -} - - - -SmartActuatorPtr::SmartActuatorPtr(SCA_IActuator* actua,int dummy) -: m_actuator(actua) -{ - actua->AddRef(); -} - - - -SmartActuatorPtr::~SmartActuatorPtr() -{ - m_actuator->Release(); -} - - - -bool SmartActuatorPtr::operator <(const SmartActuatorPtr& other) const -{ - - return m_actuator->LessComparedTo(*other); -} - - - -bool SmartActuatorPtr::operator ==(const SmartActuatorPtr& other) const -{ - bool result2 = other->LessComparedTo(m_actuator); - return (m_actuator->LessComparedTo(*other) && result2); -} - - - -SCA_IActuator* SmartActuatorPtr::operator->() const -{ - return m_actuator; -} - - - -SCA_IActuator* SmartActuatorPtr::operator*() const -{ - return m_actuator; -} - - - -SmartControllerPtr::SmartControllerPtr(const SmartControllerPtr& copy) -{ - this->m_controller = copy.m_controller; - this->m_controller->AddRef(); -} - - - -SmartControllerPtr::SmartControllerPtr(SCA_IController* contr,int dummy) -: m_controller(contr) -{ - m_controller->AddRef(); -} - - - -SmartControllerPtr::~SmartControllerPtr() -{ - m_controller->Release(); -} - - - -bool SmartControllerPtr::operator <(const SmartControllerPtr& other) const -{ - return m_controller->LessComparedTo(*other); -} - - - -bool SmartControllerPtr::operator ==(const SmartControllerPtr& other) const -{ - return (m_controller->LessComparedTo(*other) && other->LessComparedTo(m_controller)); -} - - - -SCA_IController* SmartControllerPtr::operator->() const -{ - return m_controller; -} - - - -SCA_IController* SmartControllerPtr::operator*() const -{ - return m_controller; -} - - diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h index 50383879d8f..53e75e1eaee 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.h +++ b/source/gameengine/GameLogic/SCA_LogicManager.h @@ -43,11 +43,13 @@ #include "GEN_Map.h" #include "STR_HashedString.h" #include "Value.h" +#include "SG_QList.h" #include "KX_HashedPtr.h" using namespace std; -typedef list<class SCA_IController*> controllerlist; +typedef std::list<class SCA_IController*> controllerlist; +typedef std::map<class SCA_ISensor*,controllerlist > sensormap_t; /** * This manager handles sensor, controllers and actuators. @@ -63,45 +65,19 @@ typedef list<class SCA_IController*> controllerlist; */ #include "SCA_ILogicBrick.h" +#include "SCA_IActuator.h" -// todo: make this into a template, but first I want to think about what exactly to put in -class SmartActuatorPtr -{ - SCA_IActuator* m_actuator; -public: - SmartActuatorPtr(SCA_IActuator* actua,int dummy); - SmartActuatorPtr(const SmartActuatorPtr& other); - virtual ~SmartActuatorPtr(); - bool operator <(const SmartActuatorPtr& other) const; - bool operator ==(const SmartActuatorPtr& other) const; - SCA_IActuator* operator->() const; - SCA_IActuator* operator*() const; - -}; - -class SmartControllerPtr -{ - SCA_IController* m_controller; -public: - SmartControllerPtr(const SmartControllerPtr& copy); - SmartControllerPtr(SCA_IController* contr,int dummy); - virtual ~SmartControllerPtr(); - bool operator <(const SmartControllerPtr& other) const; - bool operator ==(const SmartControllerPtr& other) const; - SCA_IController* operator->() const; - SCA_IController* operator*() const; - -}; class SCA_LogicManager { vector<class SCA_EventManager*> m_eventmanagers; - vector<class SCA_ISensor*> m_activatedsensors; - set<class SmartActuatorPtr> m_activeActuators; - set<class SmartControllerPtr> m_triggeredControllerSet; - - map<SCA_ISensor*,controllerlist > m_sensorcontrollermapje; + // SG_DList: Head of objects having activated actuators + // element: SCA_IObject::m_activeActuators + SG_DList m_activeActuators; + // SG_DList: Head of objects having activated controllers + // element: SCA_IObject::m_activeControllers + SG_DList m_triggeredControllerSet; // need to find better way for this // also known as FactoryManager... @@ -111,11 +87,10 @@ class SCA_LogicManager GEN_Map<STR_HashedString,void*> m_map_gamemeshname_to_blendobj; GEN_Map<CHashedPtr,void*> m_map_blendobj_to_gameobj; - - vector<SmartActuatorPtr> m_removedActuators; public: SCA_LogicManager(); virtual ~SCA_LogicManager(); + //void SetKeyboardManager(SCA_KeyboardManager* keyboardmgr) { m_keyboardmgr=keyboardmgr;} void RegisterEventManager(SCA_EventManager* eventmgr); void RegisterToSensor(SCA_IController* controller, @@ -126,8 +101,13 @@ public: void BeginFrame(double curtime, double fixedtime); void UpdateFrame(double curtime, bool frame); void EndFrame(); - void AddActivatedSensor(SCA_ISensor* sensor); - void AddActiveActuator(SCA_IActuator* sensor,class CValue* event); + void AddActiveActuator(SCA_IActuator* actua,bool event) + { + actua->SetActive(true); + actua->Activate(m_activeActuators); + actua->AddEvent(event); + } + void AddTriggeredController(SCA_IController* controller, SCA_ISensor* sensor); SCA_EventManager* FindEventManager(int eventmgrtype); @@ -138,7 +118,7 @@ public: */ void RemoveSensor(SCA_ISensor* sensor); void RemoveController(SCA_IController* controller); - void RemoveDestroyedActuator(SCA_IActuator* actuator); + void RemoveActuator(SCA_IActuator* actuator); // for the scripting... needs a FactoryManager later (if we would have time... ;) diff --git a/source/gameengine/GameLogic/SCA_MouseManager.cpp b/source/gameengine/GameLogic/SCA_MouseManager.cpp index ca875dad07c..d407647cec3 100644 --- a/source/gameengine/GameLogic/SCA_MouseManager.cpp +++ b/source/gameengine/GameLogic/SCA_MouseManager.cpp @@ -75,8 +75,8 @@ void SCA_MouseManager::NextFrame() { if (m_mousedevice) { - set<SCA_ISensor*>::iterator it; - for (it=m_sensors.begin(); it!=m_sensors.end(); it++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { SCA_MouseSensor* mousesensor = (SCA_MouseSensor*)(*it); // (0,0) is the Upper Left corner in our local window @@ -93,7 +93,7 @@ void SCA_MouseManager::NextFrame() mousesensor->setX(mx); mousesensor->setY(my); - mousesensor->Activate(m_logicmanager,NULL); + mousesensor->Activate(m_logicmanager); } } } diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index 4dbeb156e63..c5e1c3c0441 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -111,7 +111,7 @@ CValue* SCA_MouseSensor::GetReplica() { SCA_MouseSensor* replica = new SCA_MouseSensor(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); return replica; @@ -144,7 +144,7 @@ SCA_IInputDevice::KX_EnumInputs SCA_MouseSensor::GetHotKey() -bool SCA_MouseSensor::Evaluate(CValue* event) +bool SCA_MouseSensor::Evaluate() { bool result = false; bool reset = m_reset && m_level; @@ -296,8 +296,13 @@ KX_PYMETHODDEF_DOC_O(SCA_MouseSensor, getButtonStatus, /* ------------------------------------------------------------------------- */ PyTypeObject SCA_MouseSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_MouseSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -342,6 +347,10 @@ PyObject* SCA_MouseSensor::py_getattro(PyObject *attr) py_getattro_up(SCA_ISensor); } +PyObject* SCA_MouseSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_MouseSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 2d1c496029d..6d6302b514a 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -97,7 +97,7 @@ class SCA_MouseSensor : public SCA_ISensor virtual ~SCA_MouseSensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual void Init(); virtual bool IsPositiveTrigger(); short int GetModeKey(); @@ -110,6 +110,7 @@ class SCA_MouseSensor : public SCA_ISensor /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated functions -----> diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp index 703c9c1bbaf..d27aea5e6f7 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.cpp +++ b/source/gameengine/GameLogic/SCA_NANDController.cpp @@ -66,26 +66,19 @@ void SCA_NANDController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (!sensor->IsPositiveTrigger()) + if (!sensor->GetState()) { sensorresult = true; break; } } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); - } @@ -94,7 +87,7 @@ CValue* SCA_NANDController::GetReplica() { CValue* replica = new SCA_NANDController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -107,8 +100,13 @@ CValue* SCA_NANDController::GetReplica() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_NANDController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_NANDController", sizeof(PyObjectPlus_Proxy), 0, @@ -145,4 +143,8 @@ PyObject* SCA_NANDController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_NANDController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_NANDController.h b/source/gameengine/GameLogic/SCA_NANDController.h index 11600914a1a..0ae0ff19745 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.h +++ b/source/gameengine/GameLogic/SCA_NANDController.h @@ -49,6 +49,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp index 06acae5a81a..6c9141636b2 100644 --- a/source/gameengine/GameLogic/SCA_NORController.cpp +++ b/source/gameengine/GameLogic/SCA_NORController.cpp @@ -66,26 +66,19 @@ void SCA_NORController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (sensor->IsPositiveTrigger()) + if (sensor->GetState()) { sensorresult = false; break; } } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); - } @@ -94,7 +87,7 @@ CValue* SCA_NORController::GetReplica() { CValue* replica = new SCA_NORController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -107,8 +100,13 @@ CValue* SCA_NORController::GetReplica() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_NORController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_NORController", sizeof(PyObjectPlus_Proxy), 0, @@ -145,4 +143,8 @@ PyObject* SCA_NORController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_NORController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_NORController.h b/source/gameengine/GameLogic/SCA_NORController.h index fc814e28d37..06cbb70a489 100644 --- a/source/gameengine/GameLogic/SCA_NORController.h +++ b/source/gameengine/GameLogic/SCA_NORController.h @@ -49,6 +49,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp index 319ff04f776..42c0a67d657 100644 --- a/source/gameengine/GameLogic/SCA_ORController.cpp +++ b/source/gameengine/GameLogic/SCA_ORController.cpp @@ -60,7 +60,7 @@ CValue* SCA_ORController::GetReplica() { CValue* replica = new SCA_ORController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -76,21 +76,16 @@ void SCA_ORController::Trigger(SCA_LogicManager* logicmgr) while ( (!sensorresult) && (!(is==m_linkedsensors.end())) ) { sensor = *is; - if (sensor->IsPositiveTrigger()) sensorresult = true; + if (sensor->GetState()) sensorresult = true; is++; } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - - newevent->Release(); } /* ------------------------------------------------------------------------- */ @@ -99,8 +94,13 @@ void SCA_ORController::Trigger(SCA_LogicManager* logicmgr) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_ORController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_ORController", sizeof(PyObjectPlus_Proxy), 0, @@ -138,4 +138,8 @@ PyObject* SCA_ORController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_ORController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ORController.h b/source/gameengine/GameLogic/SCA_ORController.h index fdc81486e74..66f772c739e 100644 --- a/source/gameengine/GameLogic/SCA_ORController.h +++ b/source/gameengine/GameLogic/SCA_ORController.h @@ -50,6 +50,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; #endif //__KX_ORCONTROLLER diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index c4db723ee89..4faa4b55d4a 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -186,11 +186,6 @@ GetReplica() { SCA_PropertyActuator* replica = new SCA_PropertyActuator(*this); replica->ProcessReplica(); - - // this will copy properties and so on... - - CValue::AddDataToReplica(replica); - return replica; }; @@ -233,8 +228,13 @@ void SCA_PropertyActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_PropertyActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_PropertyActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -270,8 +270,9 @@ PyMethodDef SCA_PropertyActuator::Methods[] = { }; PyAttributeDef SCA_PropertyActuator::Attributes[] = { - KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_PropertyActuator,m_propname,CheckProperty), + KX_PYATTRIBUTE_STRING_RW_CHECK("propName",0,100,false,SCA_PropertyActuator,m_propname,CheckProperty), KX_PYATTRIBUTE_STRING_RW("value",0,100,false,SCA_PropertyActuator,m_exprtxt), + KX_PYATTRIBUTE_INT_RW("mode", KX_ACT_PROP_NODEF+1, KX_ACT_PROP_MAX-1, false, SCA_PropertyActuator, m_type), /* ATTR_TODO add constents to game logic dict */ { NULL } //Sentinel }; @@ -279,6 +280,10 @@ PyObject* SCA_PropertyActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); } +PyObject* SCA_PropertyActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int SCA_PropertyActuator::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IActuator); } @@ -291,7 +296,7 @@ const char SCA_PropertyActuator::SetProperty_doc[] = "\tof this name, the call is ignored.\n"; PyObject* SCA_PropertyActuator::PySetProperty(PyObject* args, PyObject* kwds) { - ShowDeprecationWarning("setProperty()", "the 'property' property"); + ShowDeprecationWarning("setProperty()", "the 'propName' property"); /* Check whether the name exists first ! */ char *nameArg; if (!PyArg_ParseTuple(args, "s:setProperty", &nameArg)) { @@ -316,7 +321,7 @@ const char SCA_PropertyActuator::GetProperty_doc[] = "\tReturn the property on which the actuator operates.\n"; PyObject* SCA_PropertyActuator::PyGetProperty(PyObject* args, PyObject* kwds) { - ShowDeprecationWarning("getProperty()", "the 'property' property"); + ShowDeprecationWarning("getProperty()", "the 'propName' property"); return PyString_FromString(m_propname); } diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.h b/source/gameengine/GameLogic/SCA_PropertyActuator.h index bb841cf88ad..a8df08dfc6e 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.h +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.h @@ -87,6 +87,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); // python wrapped methods diff --git a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp index e5e3f9cced5..764465309df 100644 --- a/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyEventManager.cpp @@ -50,8 +50,9 @@ SCA_PropertyEventManager::~SCA_PropertyEventManager() void SCA_PropertyEventManager::NextFrame() { // check for changed properties - for (set<SCA_ISensor*>::const_iterator it = m_sensors.begin();!(it==m_sensors.end());it++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*it)->Activate(m_logicmgr,NULL); + (*it)->Activate(m_logicmgr); } } diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index de8a9fcf03e..3b343af3cba 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -37,6 +37,7 @@ #include "StringValue.h" #include "SCA_EventManager.h" #include "SCA_LogicManager.h" +#include "BoolValue.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -111,7 +112,7 @@ CValue* SCA_PropertySensor::GetReplica() { SCA_PropertySensor* replica = new SCA_PropertySensor(*this); // m_range_expr must be recalculated on replica! - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); replica->m_range_expr = NULL; @@ -152,7 +153,7 @@ SCA_PropertySensor::~SCA_PropertySensor() -bool SCA_PropertySensor::Evaluate(CValue* event) +bool SCA_PropertySensor::Evaluate() { bool result = CheckPropertyCondition(); bool reset = m_reset && m_level; @@ -182,17 +183,14 @@ bool SCA_PropertySensor::CheckPropertyCondition() CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { - STR_String testprop = orgprop->GetText(); + const STR_String& testprop = orgprop->GetText(); // Force strings to upper case, to avoid confusion in // bool tests. It's stupid the prop's identity is lost // on the way here... - if ((testprop == "TRUE") || (testprop == "FALSE")) { - STR_String checkprop = m_checkpropval; - checkprop.Upper(); - result = (testprop == checkprop); - } else { - result = (orgprop->GetText() == m_checkpropval); + if ((&testprop == &CBoolValue::sTrueString) || (&testprop == &CBoolValue::sFalseString)) { + m_checkpropval.Upper(); } + result = (testprop == m_checkpropval); } orgprop->Release(); @@ -232,8 +230,8 @@ bool SCA_PropertySensor::CheckPropertyCondition() CValue* vallie = m_range_expr->Calculate(); if (vallie) { - STR_String errtext = vallie->GetText(); - if (errtext == "TRUE") + const STR_String& errtext = vallie->GetText(); + if (&errtext == &CBoolValue::sTrueString) { result = true; } else @@ -295,9 +293,8 @@ CValue* SCA_PropertySensor::FindIdentifier(const STR_String& identifiername) int SCA_PropertySensor::validValueForProperty(void *self, const PyAttributeDef*) { - bool result = true; /* There is no type checking at this moment, unfortunately... */ - return result; + return 0; } /* ------------------------------------------------------------------------- */ @@ -306,8 +303,13 @@ int SCA_PropertySensor::validValueForProperty(void *self, const PyAttributeDef*) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_PropertySensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_PropertySensor", sizeof(PyObjectPlus_Proxy), 0, @@ -345,8 +347,8 @@ PyMethodDef SCA_PropertySensor::Methods[] = { }; PyAttributeDef SCA_PropertySensor::Attributes[] = { - KX_PYATTRIBUTE_INT_RW("type",KX_PROPSENSOR_NODEF,KX_PROPSENSOR_MAX-1,false,SCA_PropertySensor,m_checktype), - KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_PropertySensor,m_checkpropname,CheckProperty), + KX_PYATTRIBUTE_INT_RW("mode",KX_PROPSENSOR_NODEF,KX_PROPSENSOR_MAX-1,false,SCA_PropertySensor,m_checktype), + KX_PYATTRIBUTE_STRING_RW_CHECK("propName",0,100,false,SCA_PropertySensor,m_checkpropname,CheckProperty), KX_PYATTRIBUTE_STRING_RW_CHECK("value",0,100,false,SCA_PropertySensor,m_checkpropval,validValueForProperty), { NULL } //Sentinel }; @@ -356,6 +358,10 @@ PyObject* SCA_PropertySensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_PropertySensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_PropertySensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); } @@ -366,7 +372,7 @@ const char SCA_PropertySensor::GetType_doc[] = "\tReturns the type of check this sensor performs.\n"; PyObject* SCA_PropertySensor::PyGetType() { - ShowDeprecationWarning("getType()", "the type property"); + ShowDeprecationWarning("getType()", "the mode property"); return PyInt_FromLong(m_checktype); } @@ -379,7 +385,7 @@ const char SCA_PropertySensor::SetType_doc[] = "\tSet the type of check to perform.\n"; PyObject* SCA_PropertySensor::PySetType(PyObject* args) { - ShowDeprecationWarning("setType()", "the type property"); + ShowDeprecationWarning("setType()", "the mode property"); int typeArg; if (!PyArg_ParseTuple(args, "i:setType", &typeArg)) { @@ -400,7 +406,7 @@ const char SCA_PropertySensor::GetProperty_doc[] = "\tReturn the property with which the sensor operates.\n"; PyObject* SCA_PropertySensor::PyGetProperty() { - ShowDeprecationWarning("getProperty()", "the 'property' property"); + ShowDeprecationWarning("getProperty()", "the 'propName' property"); return PyString_FromString(m_checkpropname); } @@ -412,7 +418,7 @@ const char SCA_PropertySensor::SetProperty_doc[] = "\tof this name, the call is ignored.\n"; PyObject* SCA_PropertySensor::PySetProperty(PyObject* args) { - ShowDeprecationWarning("setProperty()", "the 'property' property"); + ShowDeprecationWarning("setProperty()", "the 'propName' property"); /* We should query whether the name exists. Or should we create a prop */ /* on the fly? */ char *propNameArg = NULL; diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.h b/source/gameengine/GameLogic/SCA_PropertySensor.h index e1e378a973c..538ecd65949 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.h +++ b/source/gameengine/GameLogic/SCA_PropertySensor.h @@ -81,7 +81,7 @@ public: void PrecalculateRangeExpression(); bool CheckPropertyCondition(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual CValue* FindIdentifier(const STR_String& identifiername); @@ -90,6 +90,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* 1. getType */ diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index b8052555528..80e4f54c9c5 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -48,12 +48,18 @@ SCA_PythonController* SCA_PythonController::m_sCurrentController = NULL; SCA_PythonController::SCA_PythonController(SCA_IObject* gameobj, + int mode, PyTypeObject* T) : SCA_IController(gameobj, T), m_bytecode(NULL), + m_function(NULL), + m_function_argc(0), m_bModified(true), + m_debug(false), + m_mode(mode), m_pythondictionary(NULL) { + } /* @@ -74,15 +80,12 @@ int SCA_PythonController::Release() SCA_PythonController::~SCA_PythonController() { - if (m_bytecode) - { - // - //printf("released python byte script\n"); - Py_DECREF(m_bytecode); - } + //printf("released python byte script\n"); - if (m_pythondictionary) - { + Py_XDECREF(m_bytecode); + Py_XDECREF(m_function); + + if (m_pythondictionary) { // break any circular references in the dictionary PyDict_Clear(m_pythondictionary); Py_DECREF(m_pythondictionary); @@ -94,8 +97,12 @@ SCA_PythonController::~SCA_PythonController() CValue* SCA_PythonController::GetReplica() { SCA_PythonController* replica = new SCA_PythonController(*this); - // Copy the compiled bytecode if possible. + + /* why is this needed at all??? - m_bytecode is NULL'd below so this doesnt make sense + * but removing it crashes blender (with YoFrankie). so leave in for now - Campbell */ Py_XINCREF(replica->m_bytecode); + + Py_XINCREF(replica->m_function); // this is ok since its not set to NULL replica->m_bModified = replica->m_bytecode == NULL; // The replica->m_pythondictionary is stolen - replace with a copy. @@ -110,7 +117,7 @@ CValue* SCA_PythonController::GetReplica() */ // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -140,6 +147,11 @@ void SCA_PythonController::SetDictionary(PyObject* pythondictionary) Py_DECREF(m_pythondictionary); } m_pythondictionary = PyDict_Copy(pythondictionary); /* new reference */ + + /* Without __file__ set the sys.argv[0] is used for the filename + * which ends up with lines from the blender binary being printed in the console */ + PyDict_SetItemString(m_pythondictionary, "__file__", PyString_FromString(m_scriptName.Ptr())); + } int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) @@ -150,13 +162,14 @@ int SCA_PythonController::IsTriggered(class SCA_ISensor* sensor) return 0; } -#if 0 -static const char* sPyGetCurrentController__doc__; -#endif - /* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */ PyObject* SCA_PythonController::sPyGetCurrentController(PyObject *self) { + if(m_sCurrentController==NULL) + { + PyErr_SetString(PyExc_SystemError, "GameLogic.getCurrentController(), this function is being run outside the python controllers context, or blenders internal state is corrupt."); + return NULL; + } return m_sCurrentController->GetProxy(); } @@ -170,15 +183,15 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) if (PyString_Check(value)) { /* get the actuator from the name */ char *name= PyString_AsString(value); - for(it = lacts.begin(); it!= lacts.end(); it++) { + for(it = lacts.begin(); it!= lacts.end(); ++it) { if( name == (*it)->GetName() ) { return *it; } } } else if (BGE_PROXY_CHECK_TYPE(value)) { - PyObjectPlus *value_plus= BGE_PROXY_REF(value); /* Expecting an actuator type */ // XXX TODO - CHECK TYPE - for(it = lacts.begin(); it!= lacts.end(); it++) { + PyObjectPlus *value_plus= BGE_PROXY_REF(value); + for(it = lacts.begin(); it!= lacts.end(); ++it) { if( static_cast<SCA_IActuator*>(value_plus) == (*it) ) { return *it; } @@ -193,13 +206,11 @@ SCA_IActuator* SCA_PythonController::LinkedActuatorFromPy(PyObject *value) return false; } -#if 0 -static const char* sPyAddActiveActuator__doc__; -#endif - /* warning, self is not the SCA_PythonController, its a PyObjectPlus_Proxy */ PyObject* SCA_PythonController::sPyAddActiveActuator(PyObject* self, PyObject* args) { + ShowDeprecationWarning("GameLogic.addActiveActuator(act, bool)", "controller.activate(act) or controller.deactivate(act)"); + PyObject* ob1; int activate; if (!PyArg_ParseTuple(args, "Oi:addActiveActuator", &ob1,&activate)) @@ -209,20 +220,22 @@ PyObject* SCA_PythonController::sPyAddActiveActuator(PyObject* self, PyObject* a if(actu==NULL) return NULL; - CValue* boolval = new CBoolValue(activate!=0); + bool boolval = (activate!=0); m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu,boolval); - boolval->Release(); Py_RETURN_NONE; } - const char* SCA_PythonController::sPyGetCurrentController__doc__ = "getCurrentController()"; const char* SCA_PythonController::sPyAddActiveActuator__doc__= "addActiveActuator(actuator,bool)"; -const char SCA_PythonController::GetActuators_doc[] = "getActuator"; PyTypeObject SCA_PythonController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_PythonController", sizeof(PyObjectPlus_Proxy), 0, @@ -249,59 +262,137 @@ PyMethodDef SCA_PythonController::Methods[] = { {"activate", (PyCFunction) SCA_PythonController::sPyActivate, METH_O}, {"deactivate", (PyCFunction) SCA_PythonController::sPyDeActivate, METH_O}, - {"getActuators", (PyCFunction) SCA_PythonController::sPyGetActuators, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetActuators_doc}, - {"getActuator", (PyCFunction) SCA_PythonController::sPyGetActuator, METH_O, (PY_METHODCHAR)SCA_PythonController::GetActuator_doc}, - {"getSensors", (PyCFunction) SCA_PythonController::sPyGetSensors, METH_NOARGS, (PY_METHODCHAR)SCA_PythonController::GetSensors_doc}, - {"getSensor", (PyCFunction) SCA_PythonController::sPyGetSensor, METH_O, (PY_METHODCHAR)SCA_PythonController::GetSensor_doc}, //Deprecated functions ------> {"setScript", (PyCFunction) SCA_PythonController::sPySetScript, METH_O}, {"getScript", (PyCFunction) SCA_PythonController::sPyGetScript, METH_NOARGS}, - {"getState", (PyCFunction) SCA_PythonController::sPyGetState, METH_NOARGS}, //<----- Deprecated {NULL,NULL} //Sentinel }; PyAttributeDef SCA_PythonController::Attributes[] = { - KX_PYATTRIBUTE_RO_FUNCTION("state", SCA_PythonController, pyattr_get_state), KX_PYATTRIBUTE_RW_FUNCTION("script", SCA_PythonController, pyattr_get_script, pyattr_set_script), + KX_PYATTRIBUTE_INT_RO("mode", SCA_PythonController, m_mode), { NULL } //Sentinel }; -bool SCA_PythonController::Compile() +void SCA_PythonController::ErrorPrint(const char *error_msg) { + // didn't compile, so instead of compile, complain + // something is wrong, tell the user what went wrong + printf("%s - controller \"%s\":\n", error_msg, GetName().Ptr()); + //PyRun_SimpleString(m_scriptText.Ptr()); + PyErr_Print(); + + /* Added in 2.48a, the last_traceback can reference Objects for example, increasing + * their user count. Not to mention holding references to wrapped data. + * This is especially bad when the PyObject for the wrapped data is free'd, after blender + * has alredy dealocated the pointer */ + PySys_SetObject( (char *)"last_traceback", NULL); + PyErr_Clear(); /* just to be sure */ +} + +bool SCA_PythonController::Compile() +{ //printf("py script modified '%s'\n", m_scriptName.Ptr()); + m_bModified= false; // if a script already exists, decref it before replace the pointer to a new script - if (m_bytecode) - { + if (m_bytecode) { Py_DECREF(m_bytecode); m_bytecode=NULL; } + // recompile the scripttext into bytecode m_bytecode = Py_CompileString(m_scriptText.Ptr(), m_scriptName.Ptr(), Py_file_input); - m_bModified=false; - if (m_bytecode) - { - + if (m_bytecode) { return true; + } else { + ErrorPrint("Python error compiling script"); + return false; } - else { - // didn't compile, so instead of compile, complain - // something is wrong, tell the user what went wrong - printf("Python compile error from controller \"%s\": \n", GetName().Ptr()); - //PyRun_SimpleString(m_scriptText.Ptr()); - PyErr_Print(); +} + +bool SCA_PythonController::Import() +{ + //printf("py module modified '%s'\n", m_scriptName.Ptr()); + m_bModified= false; + + /* incase we re-import */ + Py_XDECREF(m_function); + m_function= NULL; + + vector<STR_String> py_function_path = m_scriptText.Explode('.'); + + if(py_function_path.size() < 2) { + printf("Python module name formatting error \"%s\":\n\texpected \"SomeModule.Func\", got \"%s\"\n", GetName().Ptr(), m_scriptText.Ptr()); + return false; + } + + PyObject *mod = PyImport_ImportModule((char *)py_function_path[0].Ptr()); + /* Dont reload yet, do this within the loop so packages reload too */ + + if(mod==NULL) { + ErrorPrint("Python module not found"); + return false; + } + /* 'mod' will be DECREF'd as 'base' + * 'm_function' will be left holding a reference that the controller owns */ + + PyObject *base= mod; + + for(unsigned int i=1; i < py_function_path.size(); i++) { + if(m_debug && PyModule_Check(base)) { /* base could be a class */ + Py_DECREF(base); /* getting a new one so dont hold a ref to the old one */ + base= PyImport_ReloadModule(base); + if (base==NULL) { + m_function= NULL; + break; + } + } - /* Added in 2.48a, the last_traceback can reference Objects for example, increasing - * their user count. Not to mention holding references to wrapped data. - * This is especially bad when the PyObject for the wrapped data is free'd, after blender - * has alredy dealocated the pointer */ - PySys_SetObject( (char *)"last_traceback", NULL); - PyErr_Clear(); /* just to be sure */ + m_function = PyObject_GetAttrString(base, py_function_path[i].Ptr()); + Py_DECREF(base); + base = m_function; /* for the next loop if there is on */ + if(m_function==NULL) { + break; + } + } + + if(m_function==NULL) { + if(PyErr_Occurred()) + ErrorPrint("Python controller found the module but could not access the function"); + else + printf("Python module error \"%s\":\n \"%s\" module found but function missing\n", GetName().Ptr(), m_scriptText.Ptr()); + return false; + } + + if(!PyCallable_Check(m_function)) { + Py_DECREF(m_function); + printf("Python module function error \"%s\":\n \"%s\" not callable\n", GetName().Ptr(), m_scriptText.Ptr()); + return false; + } + + m_function_argc = 0; /* rare cases this could be a function that isnt defined in python, assume zero args */ + if (PyFunction_Check(m_function)) { + PyObject *py_arg_count = PyObject_GetAttrString(PyFunction_GET_CODE(m_function), "co_argcount"); + if(py_arg_count) { + m_function_argc = PyLong_AsLong(py_arg_count); + Py_DECREF(py_arg_count); + } + else { + PyErr_Clear(); /* unlikely to fail but just incase */ + } + } + + if(m_function_argc > 1) { + Py_DECREF(m_function); + printf("Python module function has \"%s\":\n \"%s\" takes %d args, should be zero or 1 controller arg\n", GetName().Ptr(), m_scriptText.Ptr(), m_function_argc); return false; } + + return true; } void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) @@ -309,16 +400,18 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) m_sCurrentController = this; m_sCurrentLogicManager = logicmgr; - if (m_bModified) + PyObject *excdict= NULL; + PyObject* resultobj= NULL; + + switch(m_mode) { + case SCA_PYEXEC_SCRIPT: { - if (Compile()==false) // sets m_bModified to false + if (m_bModified) + if (Compile()==false) // sets m_bModified to false + return; + if (!m_bytecode) return; - } - if (!m_bytecode) { - return; - } - /* * This part here with excdict is a temporary patch * to avoid python/gameengine crashes when python @@ -337,10 +430,36 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) * should always ensure excdict is cleared). */ - PyObject *excdict= PyDict_Copy(m_pythondictionary); - PyObject* resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode, - excdict, excdict); - + excdict= PyDict_Copy(m_pythondictionary); + resultobj = PyEval_EvalCode((PyCodeObject*)m_bytecode, excdict, excdict); + /* PyRun_SimpleString(m_scriptText.Ptr()); */ + break; + } + case SCA_PYEXEC_MODULE: + { + if (m_bModified || m_debug) + if (Import()==false) // sets m_bModified to false + return; + if (!m_function) + return; + + PyObject *args= NULL; + + if(m_function_argc==1) { + args = PyTuple_New(1); + PyTuple_SET_ITEM(args, 0, GetProxy()); + } + + resultobj = PyObject_CallObject(m_function, args); + Py_XDECREF(args); + break; + } + + } /* end switch */ + + + + /* Free the return value and print the error */ if (resultobj) { Py_DECREF(resultobj); @@ -348,7 +467,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) else { // something is wrong, tell the user what went wrong - printf("Python script error from controller \"%s\": \n", GetName().Ptr()); + printf("Python script error from controller \"%s\":\n", GetName().Ptr()); PyErr_Print(); /* Added in 2.48a, the last_traceback can reference Objects for example, increasing @@ -357,15 +476,17 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) * has alredy dealocated the pointer */ PySys_SetObject( (char *)"last_traceback", NULL); PyErr_Clear(); /* just to be sure */ - - //PyRun_SimpleString(m_scriptText.Ptr()); } - - // clear after PyErrPrint - seems it can be using - // something in this dictionary and crash? - PyDict_Clear(excdict); - Py_DECREF(excdict); - m_triggeredSensors.erase(m_triggeredSensors.begin(), m_triggeredSensors.end()); + + if(excdict) /* Only for SCA_PYEXEC_SCRIPT types */ + { + /* clear after PyErrPrint - seems it can be using + * something in this dictionary and crash? */ + PyDict_Clear(excdict); + Py_DECREF(excdict); + } + + m_triggeredSensors.clear(); m_sCurrentController = NULL; } @@ -376,6 +497,10 @@ PyObject* SCA_PythonController::py_getattro(PyObject *attr) py_getattro_up(SCA_IController); } +PyObject* SCA_PythonController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + int SCA_PythonController::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IController); @@ -383,104 +508,32 @@ int SCA_PythonController::py_setattro(PyObject *attr, PyObject *value) PyObject* SCA_PythonController::PyActivate(PyObject *value) { - SCA_IActuator* actu = LinkedActuatorFromPy(value); - if(actu==NULL) + if(m_sCurrentController != this) { + PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller"); return NULL; + } - CValue* boolval = new CBoolValue(true); - m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, boolval); - boolval->Release(); - Py_RETURN_NONE; -} - -PyObject* SCA_PythonController::PyDeActivate(PyObject *value) -{ SCA_IActuator* actu = LinkedActuatorFromPy(value); if(actu==NULL) return NULL; - CValue* boolval = new CBoolValue(false); - m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, boolval); - boolval->Release(); + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, true); Py_RETURN_NONE; } -PyObject* SCA_PythonController::PyGetActuators() -{ - PyObject* resultlist = PyList_New(m_linkedactuators.size()); - for (unsigned int index=0;index<m_linkedactuators.size();index++) - { - PyList_SET_ITEM(resultlist,index, m_linkedactuators[index]->GetProxy()); - } - - return resultlist; -} - -const char SCA_PythonController::GetSensor_doc[] = -"getSensor (char sensorname) return linked sensor that is named [sensorname]\n"; -PyObject* -SCA_PythonController::PyGetSensor(PyObject* value) +PyObject* SCA_PythonController::PyDeActivate(PyObject *value) { - - char *scriptArg = PyString_AsString(value); - if (scriptArg==NULL) { - PyErr_SetString(PyExc_TypeError, "controller.getSensor(string): Python Controller, expected a string (sensor name)"); + if(m_sCurrentController != this) { + PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller"); return NULL; } - for (unsigned int index=0;index<m_linkedsensors.size();index++) - { - SCA_ISensor* sensor = m_linkedsensors[index]; - STR_String realname = sensor->GetName(); - if (realname == scriptArg) - { - return sensor->GetProxy(); - } - } - - PyErr_Format(PyExc_AttributeError, "controller.getSensor(string): Python Controller, unable to find requested sensor \"%s\"", scriptArg); - return NULL; -} - - - -const char SCA_PythonController::GetActuator_doc[] = -"getActuator (char sensorname) return linked actuator that is named [actuatorname]\n"; -PyObject* -SCA_PythonController::PyGetActuator(PyObject* value) -{ - - char *scriptArg = PyString_AsString(value); - if (scriptArg==NULL) { - PyErr_SetString(PyExc_TypeError, "controller.getActuator(string): Python Controller, expected a string (actuator name)"); + SCA_IActuator* actu = LinkedActuatorFromPy(value); + if(actu==NULL) return NULL; - } - for (unsigned int index=0;index<m_linkedactuators.size();index++) - { - SCA_IActuator* actua = m_linkedactuators[index]; - if (actua->GetName() == scriptArg) - { - return actua->GetProxy(); - } - } - - PyErr_Format(PyExc_AttributeError, "controller.getActuator(string): Python Controller, unable to find requested actuator \"%s\"", scriptArg); - return NULL; -} - - -const char SCA_PythonController::GetSensors_doc[] = "getSensors returns a list of all attached sensors"; -PyObject* -SCA_PythonController::PyGetSensors() -{ - PyObject* resultlist = PyList_New(m_linkedsensors.size()); - for (unsigned int index=0;index<m_linkedsensors.size();index++) - { - PyList_SET_ITEM(resultlist,index, m_linkedsensors[index]->GetProxy()); - } - - return resultlist; + m_sCurrentLogicManager->AddActiveActuator((SCA_IActuator*)actu, false); + Py_RETURN_NONE; } /* 1. getScript */ @@ -510,19 +563,6 @@ PyObject* SCA_PythonController::PySetScript(PyObject* value) Py_RETURN_NONE; } -/* 1. getScript */ -PyObject* SCA_PythonController::PyGetState() -{ - ShowDeprecationWarning("getState()", "the state property"); - return PyInt_FromLong(m_statemask); -} - -PyObject* SCA_PythonController::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) -{ - SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v); - return PyInt_FromLong(self->m_statemask); -} - PyObject* SCA_PythonController::pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { SCA_PythonController* self= static_cast<SCA_PythonController*>(self_v); @@ -537,14 +577,14 @@ int SCA_PythonController::pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_D if (scriptArg==NULL) { PyErr_SetString(PyExc_TypeError, "controller.script = string: Python Controller, expected a string script text"); - return -1; + return PY_SET_ATTR_FAIL; } /* set scripttext sets m_bModified to true, so next time the script is needed, a reparse into byte code is done */ self->SetScriptText(scriptArg); - return 0; + return PY_SET_ATTR_SUCCESS; } diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index f10c4e47ebb..0c2af79c3a3 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -42,23 +42,37 @@ class SCA_IObject; class SCA_PythonController : public SCA_IController { Py_Header; - struct _object * m_bytecode; + struct _object * m_bytecode; /* SCA_PYEXEC_SCRIPT only */ + PyObject* m_function; /* SCA_PYEXEC_MODULE only */ + int m_function_argc; bool m_bModified; + bool m_debug; /* use with SCA_PYEXEC_MODULE for reloading every logic run */ + int m_mode; + protected: STR_String m_scriptText; STR_String m_scriptName; - PyObject* m_pythondictionary; + PyObject* m_pythondictionary; /* for SCA_PYEXEC_SCRIPT only */ + PyObject* m_pythonfunction; /* for SCA_PYEXEC_MODULE only */ + std::vector<class SCA_ISensor*> m_triggeredSensors; + + public: + enum SCA_PyExecMode + { + SCA_PYEXEC_SCRIPT = 0, + SCA_PYEXEC_MODULE, + SCA_PYEXEC_MAX + }; - public: static SCA_PythonController* m_sCurrentController; // protected !!! //for debugging //virtual CValue* AddRef(); //virtual int Release(); // Release a reference to this value (when reference count reaches 0, the value is removed from the heap) - SCA_PythonController(SCA_IObject* gameobj,PyTypeObject* T = &Type); + SCA_PythonController(SCA_IObject* gameobj, int mode, PyTypeObject* T = &Type); virtual ~SCA_PythonController(); virtual CValue* GetReplica(); @@ -67,10 +81,14 @@ class SCA_PythonController : public SCA_IController void SetScriptText(const STR_String& text); void SetScriptName(const STR_String& name); void SetDictionary(PyObject* pythondictionary); + void SetDebug(bool debug) { m_debug = debug; } void AddTriggeredSensor(class SCA_ISensor* sensor) { m_triggeredSensors.push_back(sensor); } int IsTriggered(class SCA_ISensor* sensor); bool Compile(); + bool Import(); + void ErrorPrint(const char *error_msg); + static const char* sPyGetCurrentController__doc__; static PyObject* sPyGetCurrentController(PyObject* self); @@ -78,21 +96,18 @@ class SCA_PythonController : public SCA_IController static PyObject* sPyAddActiveActuator(PyObject* self, PyObject* args); static SCA_IActuator* LinkedActuatorFromPy(PyObject *value); + virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); KX_PYMETHOD_O(SCA_PythonController,Activate); KX_PYMETHOD_O(SCA_PythonController,DeActivate); - KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetSensors); - KX_PYMETHOD_DOC_NOARGS(SCA_PythonController,GetActuators); - KX_PYMETHOD_DOC_O(SCA_PythonController,GetSensor); - KX_PYMETHOD_DOC_O(SCA_PythonController,GetActuator); KX_PYMETHOD_O(SCA_PythonController,SetScript); KX_PYMETHOD_NOARGS(SCA_PythonController,GetScript); - KX_PYMETHOD_NOARGS(SCA_PythonController,GetState); + - static PyObject* pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_script(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 3a72d9b7652..a722590dd10 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -58,7 +58,6 @@ SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj, m_parameter2(para2), m_distribution(mode) { - // m_base is never deleted, probably a memory leak! m_base = new SCA_RandomNumberGenerator(seed); m_counter = 0; enforceConstraints(); @@ -68,7 +67,7 @@ SCA_RandomActuator::SCA_RandomActuator(SCA_IObject *gameobj, SCA_RandomActuator::~SCA_RandomActuator() { - /* intentionally empty */ + m_base->Release(); } @@ -78,11 +77,16 @@ CValue* SCA_RandomActuator::GetReplica() SCA_RandomActuator* replica = new SCA_RandomActuator(*this); // replication just copy the m_base pointer => common random generator replica->ProcessReplica(); - CValue::AddDataToReplica(replica); - return replica; } +void SCA_RandomActuator::ProcessReplica() +{ + SCA_IActuator::ProcessReplica(); + // increment reference count so that we can release the generator at the end + m_base->AddRef(); +} + bool SCA_RandomActuator::Update() @@ -312,8 +316,13 @@ void SCA_RandomActuator::enforceConstraints() { /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_RandomActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_RandomActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -367,7 +376,7 @@ PyAttributeDef SCA_RandomActuator::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RO("para1",SCA_RandomActuator,m_parameter1), KX_PYATTRIBUTE_FLOAT_RO("para2",SCA_RandomActuator,m_parameter2), KX_PYATTRIBUTE_ENUM_RO("distribution",SCA_RandomActuator,m_distribution), - KX_PYATTRIBUTE_STRING_RW_CHECK("property",0,100,false,SCA_RandomActuator,m_propname,CheckProperty), + KX_PYATTRIBUTE_STRING_RW_CHECK("propName",0,100,false,SCA_RandomActuator,m_propname,CheckProperty), KX_PYATTRIBUTE_RW_FUNCTION("seed",SCA_RandomActuator,pyattr_get_seed,pyattr_set_seed), { NULL } //Sentinel }; @@ -384,10 +393,10 @@ int SCA_RandomActuator::pyattr_set_seed(void *self, const struct KX_PYATTRIBUTE_ if (PyInt_Check(value)) { int ival = PyInt_AsLong(value); act->m_base->SetSeed(ival); - return 0; + return PY_SET_ATTR_SUCCESS; } else { PyErr_SetString(PyExc_TypeError, "actuator.seed = int: Random Actuator, expected an integer"); - return 1; + return PY_SET_ATTR_FAIL; } } @@ -395,6 +404,10 @@ PyObject* SCA_RandomActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); } +PyObject* SCA_RandomActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int SCA_RandomActuator::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IActuator); @@ -470,7 +483,7 @@ const char SCA_RandomActuator::SetProperty_doc[] = "\tSet the property to which the random value is assigned. If the \n" "\tgenerator and property types do not match, the assignment is ignored.\n"; PyObject* SCA_RandomActuator::PySetProperty(PyObject* args) { - ShowDeprecationWarning("setProperty()", "the 'property' property"); + ShowDeprecationWarning("setProperty()", "the 'propName' property"); char *nameArg; if (!PyArg_ParseTuple(args, "s:setProperty", &nameArg)) { return NULL; @@ -494,7 +507,7 @@ const char SCA_RandomActuator::GetProperty_doc[] = "\tgenerator and property types do not match, the assignment is ignored.\n"; PyObject* SCA_RandomActuator::PyGetProperty() { - ShowDeprecationWarning("getProperty()", "the 'property' property"); + ShowDeprecationWarning("getProperty()", "the 'propName' property"); return PyString_FromString(m_propname); } diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.h b/source/gameengine/GameLogic/SCA_RandomActuator.h index 8f58ed0dcec..59863589b60 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.h +++ b/source/gameengine/GameLogic/SCA_RandomActuator.h @@ -91,12 +91,14 @@ class SCA_RandomActuator : public SCA_IActuator virtual bool Update(); virtual CValue* GetReplica(); + virtual void ProcessReplica(); /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); static PyObject* pyattr_get_seed(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp index 156478d866d..976597aa812 100644 --- a/source/gameengine/GameLogic/SCA_RandomEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_RandomEventManager.cpp @@ -50,9 +50,10 @@ SCA_RandomEventManager::SCA_RandomEventManager(class SCA_LogicManager* logicmgr) void SCA_RandomEventManager::NextFrame() { - for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*i)->Activate(m_logicmgr, NULL); + (*it)->Activate(m_logicmgr); } } diff --git a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp index 06b5cca6ce9..0267cc8ebbf 100644 --- a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.cpp @@ -59,6 +59,7 @@ SCA_RandomNumberGenerator::SCA_RandomNumberGenerator(long seed) { // int mti = N + 1; /*unused*/ m_seed = seed; + m_refcount = 1; SetStartVector(); } diff --git a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h index b9311d31af6..842a0331752 100644 --- a/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h +++ b/source/gameengine/GameLogic/SCA_RandomNumberGenerator.h @@ -36,6 +36,9 @@ class SCA_RandomNumberGenerator { + /* reference counted for memleak */ + int m_refcount; + /** base seed */ long m_seed; @@ -56,6 +59,16 @@ class SCA_RandomNumberGenerator { float DrawFloat(); long GetSeed(); void SetSeed(long newseed); + SCA_RandomNumberGenerator* AddRef() + { + ++m_refcount; + return this; + } + void Release() + { + if (--m_refcount == 0) + delete this; + } }; #endif /* __KX_RANDOMNUMBERGENERATOR */ diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 5ead82db428..d5cbeef01ae 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -50,7 +50,6 @@ SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr, PyTypeObject* T) : SCA_ISensor(gameobj,eventmgr, T) { - // m_basegenerator is never deleted => memory leak m_basegenerator = new SCA_RandomNumberGenerator(startseed); Init(); } @@ -59,7 +58,7 @@ SCA_RandomSensor::SCA_RandomSensor(SCA_EventManager* eventmgr, SCA_RandomSensor::~SCA_RandomSensor() { - /* Nothing to be done here. */ + m_basegenerator->Release(); } void SCA_RandomSensor::Init() @@ -74,13 +73,18 @@ void SCA_RandomSensor::Init() CValue* SCA_RandomSensor::GetReplica() { CValue* replica = new SCA_RandomSensor(*this); - // replication copies m_basegenerator pointer => share same generator // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } +void SCA_RandomSensor::ProcessReplica() +{ + SCA_ISensor::ProcessReplica(); + // increment reference count so that we can release the generator at this end + m_basegenerator->AddRef(); +} bool SCA_RandomSensor::IsPositiveTrigger() @@ -89,7 +93,7 @@ bool SCA_RandomSensor::IsPositiveTrigger() } -bool SCA_RandomSensor::Evaluate(CValue* event) +bool SCA_RandomSensor::Evaluate() { /* Random generator is the generator from Line 25 of Table 1 in */ /* [KNUTH 1981, The Art of Computer Programming Vol. 2 */ @@ -127,8 +131,13 @@ bool SCA_RandomSensor::Evaluate(CValue* event) /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_RandomSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_RandomSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -154,9 +163,11 @@ PyParentObject SCA_RandomSensor::Parents[] = { }; PyMethodDef SCA_RandomSensor::Methods[] = { + //Deprecated functions -----> {"setSeed", (PyCFunction) SCA_RandomSensor::sPySetSeed, METH_VARARGS, (PY_METHODCHAR)SetSeed_doc}, {"getSeed", (PyCFunction) SCA_RandomSensor::sPyGetSeed, METH_NOARGS, (PY_METHODCHAR)GetSeed_doc}, {"getLastDraw", (PyCFunction) SCA_RandomSensor::sPyGetLastDraw, METH_NOARGS, (PY_METHODCHAR)GetLastDraw_doc}, + //<----- Deprecated {NULL,NULL} //Sentinel }; @@ -170,6 +181,10 @@ PyObject* SCA_RandomSensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* SCA_RandomSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int SCA_RandomSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); @@ -225,10 +240,10 @@ int SCA_RandomSensor::pyattr_set_seed(void *self_v, const KX_PYATTRIBUTE_DEF *at SCA_RandomSensor* self= static_cast<SCA_RandomSensor*>(self_v); if (!PyInt_Check(value)) { PyErr_SetString(PyExc_TypeError, "sensor.seed = int: Random Sensor, expected an integer"); - return -1; + return PY_SET_ATTR_FAIL; } self->m_basegenerator->SetSeed(PyInt_AsLong(value)); - return 0; + return PY_SET_ATTR_SUCCESS; } /* eof */ diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h index 764692600c3..b2bf2440966 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.h +++ b/source/gameengine/GameLogic/SCA_RandomSensor.h @@ -52,7 +52,8 @@ public: PyTypeObject* T=&Type); virtual ~SCA_RandomSensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual void ProcessReplica(); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); @@ -61,6 +62,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* 1. setSeed */ diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp index b7fadd3d62c..911ea772bef 100644 --- a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp @@ -52,7 +52,7 @@ SCA_TimeEventManager::SCA_TimeEventManager(SCA_LogicManager* logicmgr) SCA_TimeEventManager::~SCA_TimeEventManager() { for (vector<CValue*>::iterator it = m_timevalues.begin(); - !(it == m_timevalues.end()); it++) + !(it == m_timevalues.end()); ++it) { (*it)->Release(); } @@ -80,7 +80,7 @@ void SCA_TimeEventManager::NextFrame(double curtime, double fixedtime) // update sensors, but ... need deltatime ! for (vector<CValue*>::iterator it = m_timevalues.begin(); - !(it == m_timevalues.end()); it++) + !(it == m_timevalues.end()); ++it) { float newtime = (*it)->GetNumber() + fixedtime; floatval->SetFloat(newtime); @@ -104,7 +104,7 @@ void SCA_TimeEventManager::AddTimeProperty(CValue* timeval) void SCA_TimeEventManager::RemoveTimeProperty(CValue* timeval) { for (vector<CValue*>::iterator it = m_timevalues.begin(); - !(it == m_timevalues.end()); it++) + !(it == m_timevalues.end()); ++it) { if ((*it) == timeval) { diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp index e9bb37ee958..aee8e26c21a 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.cpp +++ b/source/gameengine/GameLogic/SCA_XNORController.cpp @@ -66,7 +66,7 @@ void SCA_XNORController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (sensor->IsPositiveTrigger()) + if (sensor->GetState()) { if (sensorresult == false) { @@ -77,19 +77,12 @@ void SCA_XNORController::Trigger(SCA_LogicManager* logicmgr) } } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); - } @@ -98,7 +91,7 @@ CValue* SCA_XNORController::GetReplica() { CValue* replica = new SCA_XNORController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -111,8 +104,13 @@ CValue* SCA_XNORController::GetReplica() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_XNORController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_XNORController", sizeof(PyObjectPlus_Proxy), 0, @@ -149,4 +147,8 @@ PyObject* SCA_XNORController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_XNORController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_XNORController.h b/source/gameengine/GameLogic/SCA_XNORController.h index c992d5f1834..4aad5763cb0 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.h +++ b/source/gameengine/GameLogic/SCA_XNORController.h @@ -49,6 +49,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp index 791a139975f..5afb3a750f5 100644 --- a/source/gameengine/GameLogic/SCA_XORController.cpp +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -66,7 +66,7 @@ void SCA_XORController::Trigger(SCA_LogicManager* logicmgr) !(is==m_linkedsensors.end());is++) { SCA_ISensor* sensor = *is; - if (sensor->IsPositiveTrigger()) + if (sensor->GetState()) { if (sensorresult == true) { @@ -77,19 +77,12 @@ void SCA_XORController::Trigger(SCA_LogicManager* logicmgr) } } - CValue* newevent = new CBoolValue(sensorresult); - for (vector<SCA_IActuator*>::const_iterator i=m_linkedactuators.begin(); !(i==m_linkedactuators.end());i++) { - SCA_IActuator* actua = *i;//m_linkedactuators.at(i); - logicmgr->AddActiveActuator(actua,newevent); + SCA_IActuator* actua = *i; + logicmgr->AddActiveActuator(actua,sensorresult); } - - // every actuator that needs the event, has a it's own reference to it now so - // release it (so to be clear: if there is no actuator, it's deleted right now) - newevent->Release(); - } @@ -98,7 +91,7 @@ CValue* SCA_XORController::GetReplica() { CValue* replica = new SCA_XORController(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } @@ -111,8 +104,13 @@ CValue* SCA_XORController::GetReplica() /* Integration hooks ------------------------------------------------------- */ PyTypeObject SCA_XORController::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "SCA_XORController", sizeof(PyObjectPlus_Proxy), 0, @@ -149,4 +147,8 @@ PyObject* SCA_XORController::py_getattro(PyObject *attr) { py_getattro_up(SCA_IController); } +PyObject* SCA_XORController::py_getattro_dict() { + py_getattro_dict_up(SCA_IController); +} + /* eof */ diff --git a/source/gameengine/GameLogic/SCA_XORController.h b/source/gameengine/GameLogic/SCA_XORController.h index 065b31fd901..feb9f2ed07c 100644 --- a/source/gameengine/GameLogic/SCA_XORController.h +++ b/source/gameengine/GameLogic/SCA_XORController.h @@ -49,6 +49,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; diff --git a/source/gameengine/GameLogic/SConscript b/source/gameengine/GameLogic/SConscript index 88e5f7e87cc..91843eef586 100644 --- a/source/gameengine/GameLogic/SConscript +++ b/source/gameengine/GameLogic/SConscript @@ -5,7 +5,7 @@ sources = env.Glob('*.cpp') + env.Glob('Joystick/*.cpp') incs = '. #/source/kernel/gen_system #/intern/string' incs += ' #/source/gameengine/Expressions #/intern/moto/include' -incs += ' #/source/gameengine/Rasterizer' +incs += ' #/source/gameengine/Rasterizer #/source/gameengine/SceneGraph' incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/gameengine/GamePlayer/CMakeLists.txt b/source/gameengine/GamePlayer/CMakeLists.txt index fc5912155cf..134f8fce3b2 100644 --- a/source/gameengine/GamePlayer/CMakeLists.txt +++ b/source/gameengine/GamePlayer/CMakeLists.txt @@ -24,8 +24,9 @@ # # ***** END GPL LICENSE BLOCK ***** -SUBDIRS(common ghost) +ADD_SUBDIRECTORY(common) +ADD_SUBDIRECTORY(ghost) IF(WITH_WEBPLUGIN) - SUBDIRS(xembed) + ADD_SUBDIRECTORY(xembed) ENDIF(WITH_WEBPLUGIN) diff --git a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp index de30bbfcf3a..c5c9dcc6c0f 100644 --- a/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp +++ b/source/gameengine/GamePlayer/common/GPC_RenderTools.cpp @@ -74,8 +74,8 @@ void GPC_RenderTools::BeginFrame(RAS_IRasterizer* rasty) { m_clientobject = NULL; m_lastlightlayer = -1; - m_lastlighting = false; m_lastauxinfo = NULL; + m_lastlighting = true; /* force disable in DisableOpenGLLights() */ DisableOpenGLLights(); } @@ -286,10 +286,7 @@ void GPC_RenderTools::RenderText2D(RAS_TEXT_RENDER_MODE mode, int height) { STR_String tmpstr(text); - int lines; char* s = tmpstr.Ptr(); - char* p; - // Save and change OpenGL settings int texture2D; diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index 109ed3790ff..bdee8a78cfe 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -693,6 +693,7 @@ bool GPG_Application::startEngine(void) initGameKeys(); initPythonConstraintBinding(); initMathutils(); + initGeometry(); initBGL(); #ifdef WITH_FFMPEG initVideoTexture(); @@ -700,7 +701,7 @@ bool GPG_Application::startEngine(void) //initialize Dome Settings if(m_startScene->r.stereomode == RAS_IRasterizer::RAS_STEREO_DOME) - m_ketsjiengine->InitDome(m_startScene->r.domesize, m_startScene->r.domeres, m_startScene->r.domemode, m_startScene->r.domeangle, m_startScene->r.domeresbuf, m_startScene->r.dometext); + m_ketsjiengine->InitDome(m_startScene->r.domeres, m_startScene->r.domemode, m_startScene->r.domeangle, m_startScene->r.domeresbuf, m_startScene->r.dometilt, m_startScene->r.dometext); // Set the GameLogic.globalDict from marshal'd data, so we can // load new blend files and keep data in GameLogic.globalDict diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 97b21d13e90..b69188e5476 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -703,10 +703,10 @@ int main(int argc, char** argv) BLI_strncpy(pathname, maggie->name, sizeof(pathname)); BLI_strncpy(G.sce, maggie->name, sizeof(G.sce)); + setGamePythonPath(G.sce); if (firstTimeRunning) { - setGamePythonPath(G.sce); firstTimeRunning = false; if (fullScreen) diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index 3df483b0598..a0a61d01bb2 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -20,41 +20,33 @@ BL_BlenderShader::BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lig : mScene(scene), mMat(ma), - mLightLayer(lightlayer) + mLightLayer(lightlayer), + mGPUMat(NULL) { mBlenderScene = scene->GetBlenderScene(); mBlendMode = GPU_BLEND_SOLID; - if(mMat) - GPU_material_from_blender(mBlenderScene, mMat); + ReloadMaterial(); } BL_BlenderShader::~BL_BlenderShader() { - if(mMat && GPU_material_from_blender(mBlenderScene, mMat)) - GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat)); + if(mGPUMat) + GPU_material_unbind(mGPUMat); } -bool BL_BlenderShader::Ok() +void BL_BlenderShader::ReloadMaterial() { - return VerifyShader(); -} - -bool BL_BlenderShader::VerifyShader() -{ - if(mMat) - return (GPU_material_from_blender(mBlenderScene, mMat) != 0); - else - return false; + mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat) : NULL; } void BL_BlenderShader::SetProg(bool enable, double time) { if(VerifyShader()) { if(enable) - GPU_material_bind(GPU_material_from_blender(mBlenderScene, mMat), mLightLayer, mBlenderScene->lay, time); + GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time); else - GPU_material_unbind(GPU_material_from_blender(mBlenderScene, mMat)); + GPU_material_unbind(mGPUMat); } } @@ -66,7 +58,7 @@ int BL_BlenderShader::GetAttribNum() if(!VerifyShader()) return enabled; - GPU_material_vertex_attributes(GPU_material_from_blender(mBlenderScene, mMat), &attribs); + GPU_material_vertex_attributes(mGPUMat, &attribs); for(i = 0; i < attribs.totlayer; i++) if(attribs.layer[i].glindex+1 > enabled) @@ -89,7 +81,7 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) if(!VerifyShader()) return; - gpumat = GPU_material_from_blender(mBlenderScene, mMat); + gpumat = mGPUMat; if(ras->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) { GPU_material_vertex_attributes(gpumat, &attribs); @@ -131,7 +123,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4]; GPUMaterial *gpumat; - gpumat = GPU_material_from_blender(mBlenderScene, mMat); + gpumat = mGPUMat; if(!gpumat || !GPU_material_bound(gpumat)) return; diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index 5c1f59f94ad..9af53bfc863 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -32,19 +32,28 @@ private: struct Material *mMat; int mLightLayer; int mBlendMode; + GPUMaterial *mGPUMat; - bool VerifyShader(); + bool VerifyShader() + { + return (NULL != mGPUMat); + } public: BL_BlenderShader(KX_Scene *scene, struct Material *ma, int lightlayer); virtual ~BL_BlenderShader(); - bool Ok(); + bool Ok() + { + // same as VerifyShared + return (NULL != mGPUMat); + } void SetProg(bool enable, double time=0.0); int GetAttribNum(); void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); void Update(const class RAS_MeshSlot & ms, class RAS_IRasterizer* rasty); + void ReloadMaterial(); int GetBlendMode(); bool Equals(BL_BlenderShader *blshader); diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp index 7e3d6984f19..c63b9d55306 100644 --- a/source/gameengine/Ketsji/BL_Material.cpp +++ b/source/gameengine/Ketsji/BL_Material.cpp @@ -28,6 +28,11 @@ int getNumTexChannels( Material *mat ) BL_Material::BL_Material() { + Initialize(); +} + +void BL_Material::Initialize() +{ rgb[0] = 0; rgb[1] = 0; rgb[2] = 0; @@ -52,7 +57,7 @@ BL_Material::BL_Material() mode = 0; material = 0; tface = 0; - material_index = 0; + materialindex = 0; amb=0.5f; num_enabled = 0; num_users = 1; diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index 0eaa234566c..4f572f95891 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -44,6 +44,7 @@ private: public: // ----------------------------------- BL_Material(); + void Initialize(); int IdMode; unsigned int ras_mode; @@ -54,6 +55,7 @@ public: int tile,tilexrep[MAXTEX],tileyrep[MAXTEX]; STR_String matname; STR_String mtexname[MAXTEX]; + int materialindex; float matcolor[4]; float speccolor[3]; @@ -68,8 +70,6 @@ public: int mode; int num_enabled; - int material_index; - BL_Mapping mapping[MAXTEX]; STR_String imageId[MAXTEX]; diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 88d920043e0..c5c517c8a65 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -734,6 +734,10 @@ PyObject* BL_Shader::py_getattro(PyObject *attr) py_getattro_up(PyObjectPlus); } +PyObject* BL_Shader::py_getattro_dict() { + py_getattro_dict_up(PyObjectPlus); +} + PyMethodDef BL_Shader::Methods[] = { @@ -772,8 +776,13 @@ PyAttributeDef BL_Shader::Attributes[] = { }; PyTypeObject BL_Shader::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "BL_Shader", sizeof(PyObjectPlus_Proxy), 0, diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index 08cad5071fd..7db40e778ae 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -203,6 +203,7 @@ public: // Python interface virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual PyObject* py_repr(void) { return PyString_FromFormat("BL_Shader\n\tvertex shader:%s\n\n\tfragment shader%s\n\n", vertProg, fragProg); } // ----------------------------------- diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index ca9ce4dc50c..4aaa49a8493 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -30,11 +30,10 @@ FILE(GLOB SRC *.cpp) #SET(SRC # ${SRC} # ../../../source/blender/python/api2_2x/Mathutils.c +# ../../../source/blender/python/api2_2x/Geometry.c # ../../../source/blender/python/api2_2x/constant.c # ../../../source/blender/python/api2_2x/euler.c -# ../../../source/blender/python/api2_2x/gen_utils.c # ../../../source/blender/python/api2_2x/matrix.c -# ../../../source/blender/python/api2_2x/point.c # ../../../source/blender/python/api2_2x/quat.c # ../../../source/blender/python/api2_2x/vector.c # ../../../source/blender/python/api2_2x/bpy_internal_import.c diff --git a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt index fa0ca378c6b..d9a9fc54f4b 100644 --- a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt +++ b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt @@ -30,9 +30,11 @@ SET(INC . ../../../../source/kernel/gen_system ../../../../intern/string + ../../../../intern/moto/include ../../../../source/gameengine/Ketsji ../../../../source/gameengine/GameLogic ../../../../source/gameengine/Expressions + ../../../../source/gameengine/SceneGraph ../../../../source/gameengine/Network ${PYTHON_INC} ) diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp index eee8e9f6827..738f64713b0 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkEventManager.cpp @@ -61,12 +61,12 @@ void KX_NetworkEventManager::NextFrame() // each frame, the logicmanager will call the network // eventmanager to look for network events, and process it's // 'network' sensors - set<class SCA_ISensor*>::iterator it; - - for (it = m_sensors.begin(); !(it==m_sensors.end()); it++) { + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) + { // printf("KX_NetworkEventManager::proceed sensor %.2f\n", curtime); // process queue - (*it)->Activate(m_logicmgr, NULL); + (*it)->Activate(m_logicmgr); } // now a list of triggerer sensors has been built diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp index 2483a6bfb39..63773352d96 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.cpp @@ -75,7 +75,7 @@ bool KX_NetworkMessageActuator::Update() m_toPropName, GetParent()->GetName(), m_subject, - GetParent()->GetPropertyText(m_body,"")); + GetParent()->GetPropertyText(m_body)); } else { m_networkscene->SendMessage( @@ -93,9 +93,6 @@ CValue* KX_NetworkMessageActuator::GetReplica() new KX_NetworkMessageActuator(*this); replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); - return replica; } @@ -105,8 +102,13 @@ CValue* KX_NetworkMessageActuator::GetReplica() /* Integration hooks -------------------------------------------------- */ PyTypeObject KX_NetworkMessageActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_NetworkMessageActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -157,6 +159,10 @@ PyObject* KX_NetworkMessageActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); } +PyObject* KX_NetworkMessageActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_NetworkMessageActuator::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IActuator); } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h index 850f825b8f3..cf92fd46fe0 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageActuator.h @@ -62,6 +62,7 @@ public: /* ------------------------------------------------------------ */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); // Deprecated -----> diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 7782567943e..8ddcd87b66f 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -79,15 +79,13 @@ CValue* KX_NetworkMessageSensor::GetReplica() { CValue* replica = new KX_NetworkMessageSensor(*this); if (replica == NULL) return NULL; - - // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } // Return true only for flank (UP and DOWN) -bool KX_NetworkMessageSensor::Evaluate(CValue* event) +bool KX_NetworkMessageSensor::Evaluate() { bool result = false; bool WasUp = m_IsUp; @@ -104,8 +102,8 @@ bool KX_NetworkMessageSensor::Evaluate(CValue* event) m_SubjectList = NULL; } - STR_String toname=GetParent()->GetName(); - STR_String subject = this->m_subject; + STR_String& toname=GetParent()->GetName(); + STR_String& subject = this->m_subject; vector<NG_NetworkMessage*> messages = m_NetworkScene->FindMessages(toname,"",subject,true); @@ -125,9 +123,9 @@ bool KX_NetworkMessageSensor::Evaluate(CValue* event) for (mesit=messages.begin();mesit!=messages.end();mesit++) { // save the body - STR_String body = (*mesit)->GetMessageText(); + const STR_String& body = (*mesit)->GetMessageText(); // save the subject - STR_String messub = (*mesit)->GetSubject(); + const STR_String& messub = (*mesit)->GetSubject(); #ifdef NAN_NET_DEBUG if (body) { cout << "body [" << body << "]\n"; @@ -168,8 +166,13 @@ bool KX_NetworkMessageSensor::IsPositiveTrigger() /* Integration hooks --------------------------------------------------- */ PyTypeObject KX_NetworkMessageSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_NetworkMessageSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -227,6 +230,10 @@ PyObject* KX_NetworkMessageSensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* KX_NetworkMessageSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int KX_NetworkMessageSensor::py_setattro(PyObject *attr, PyObject *value) { return SCA_ISensor::py_setattro(attr, value); } diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h index ac0e880d25c..53183f33826 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.h @@ -63,7 +63,7 @@ public: virtual ~KX_NetworkMessageSensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); void EndFrame(); @@ -73,6 +73,7 @@ public: /* ------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); // Deprecated -----> diff --git a/source/gameengine/Ketsji/KXNetwork/Makefile b/source/gameengine/Ketsji/KXNetwork/Makefile index ddcb03600d5..365ed8fc9c3 100644 --- a/source/gameengine/Ketsji/KXNetwork/Makefile +++ b/source/gameengine/Ketsji/KXNetwork/Makefile @@ -38,8 +38,10 @@ CCFLAGS += $(LEVEL_1_CPP_WARNINGS) CPPFLAGS += -I$(NAN_PYTHON)/include/python$(NAN_PYTHON_VERSION) CPPFLAGS += -I$(NAN_STRING)/include +CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I../../Expressions CPPFLAGS += -I../../GameLogic +CPPFLAGS += -I../../SceneGraph CPPFLAGS += -I../../Network CPPFLAGS += -I../../../kernel/gen_system CPPFLAGS += -I.. diff --git a/source/gameengine/Ketsji/KXNetwork/SConscript b/source/gameengine/Ketsji/KXNetwork/SConscript index b417edf6413..f350b2ce25a 100644 --- a/source/gameengine/Ketsji/KXNetwork/SConscript +++ b/source/gameengine/Ketsji/KXNetwork/SConscript @@ -3,9 +3,9 @@ Import ('env') sources = env.Glob('*.cpp') -incs = '. #source/kernel/gen_system #intern/string #source/gameengine/Ketsji' +incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Ketsji' incs += ' #source/gameengine/GameLogic #source/gameengine/Expressions' -incs += ' #source/gameengine/Network' +incs += ' #source/gameengine/Network #source/gameengine/SceneGraph' incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 849332008ce..30057fc039d 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -43,35 +43,48 @@ BL_BlenderShader *KX_BlenderMaterial::mLastBlenderShader = NULL; //static PyObject *gTextureDict = 0; KX_BlenderMaterial::KX_BlenderMaterial( - KX_Scene *scene, - BL_Material *data, - bool skin, - int lightlayer, PyTypeObject *T ) : PyObjectPlus(T), - RAS_IPolyMaterial( - STR_String( data->texname[0] ), - STR_String( data->matname ), // needed for physics! - data->tile, - data->tilexrep[0], - data->tileyrep[0], - data->mode, - data->transp, - ((data->ras_mode &ALPHA)!=0), - ((data->ras_mode &ZSORT)!=0), - lightlayer - ), - mMaterial(data), + RAS_IPolyMaterial(), + mMaterial(NULL), mShader(0), mBlenderShader(0), - mScene(scene), + mScene(NULL), mUserDefBlend(0), mModified(0), mConstructed(false), mPass(0) +{ +} +void KX_BlenderMaterial::Initialize( + KX_Scene *scene, + BL_Material *data, + bool skin, + int lightlayer) { + RAS_IPolyMaterial::Initialize( + data->texname[0], + data->matname, + data->materialindex, + data->tile, + data->tilexrep[0], + data->tileyrep[0], + data->mode, + data->transp, + ((data->ras_mode &ALPHA)!=0), + ((data->ras_mode &ZSORT)!=0), + lightlayer + ); + mMaterial = data; + mShader = 0; + mBlenderShader = 0; + mScene = scene; + mUserDefBlend = 0; + mModified = 0; + mConstructed = false; + mPass = 0; // -------------------------------- // RAS_IPolyMaterial variables... m_flag |= RAS_BLENDERMAT; @@ -95,7 +108,6 @@ KX_BlenderMaterial::KX_BlenderMaterial( ); } m_multimode += mMaterial->IdMode+ (mMaterial->ras_mode & ~(COLLIDER|USE_LIGHT)); - } KX_BlenderMaterial::~KX_BlenderMaterial() @@ -106,7 +118,6 @@ KX_BlenderMaterial::~KX_BlenderMaterial() OnExit(); } - MTFace* KX_BlenderMaterial::GetMTFace(void) const { // fonts on polys @@ -120,14 +131,41 @@ unsigned int* KX_BlenderMaterial::GetMCol(void) const return mMaterial->rgb; } -void KX_BlenderMaterial::OnConstruction() +void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const +{ + if (mMaterial) { + *rgba++ = (unsigned char) (mMaterial->matcolor[0]*255.0); + *rgba++ = (unsigned char) (mMaterial->matcolor[1]*255.0); + *rgba++ = (unsigned char) (mMaterial->matcolor[2]*255.0); + *rgba++ = (unsigned char) (mMaterial->matcolor[3]*255.0); + } else + RAS_IPolyMaterial::GetMaterialRGBAColor(rgba); +} + +Material *KX_BlenderMaterial::GetBlenderMaterial() const +{ + return mMaterial->material; +} + +Scene* KX_BlenderMaterial::GetBlenderScene() const +{ + return mScene->GetBlenderScene(); +} + +void KX_BlenderMaterial::ReleaseMaterial() +{ + if (mBlenderShader) + mBlenderShader->ReloadMaterial(); +} + +void KX_BlenderMaterial::OnConstruction(int layer) { if (mConstructed) // when material are reused between objects return; if(mMaterial->glslmat) - SetBlenderGLSLShader(); + SetBlenderGLSLShader(layer); // for each unique material... int i; @@ -377,10 +415,12 @@ KX_BlenderMaterial::ActivatShaders( } else rasty->SetLines(false); + ActivatGLMaterials(rasty); + ActivateTexGen(rasty); } - ActivatGLMaterials(rasty); - ActivateTexGen(rasty); + //ActivatGLMaterials(rasty); + //ActivateTexGen(rasty); } void @@ -469,10 +509,12 @@ KX_BlenderMaterial::ActivateMat( } else rasty->SetLines(false); + ActivatGLMaterials(rasty); + ActivateTexGen(rasty); } - ActivatGLMaterials(rasty); - ActivateTexGen(rasty); + //ActivatGLMaterials(rasty); + //ActivateTexGen(rasty); } bool @@ -601,8 +643,7 @@ void KX_BlenderMaterial::ActivateTexGen(RAS_IRasterizer *ras) const if (mode &USECUSTOMUV) { - STR_String str = mMaterial->mapping[i].uvCoName; - if (!str.IsEmpty()) + if (!mMaterial->mapping[i].uvCoName.IsEmpty()) ras->SetTexCoord(RAS_IRasterizer::RAS_TEXCO_UV2, i); continue; } @@ -749,12 +790,20 @@ PyMethodDef KX_BlenderMaterial::Methods[] = }; PyAttributeDef KX_BlenderMaterial::Attributes[] = { + //KX_PYATTRIBUTE_TODO("shader"), + //KX_PYATTRIBUTE_TODO("materialIndex"), + //KX_PYATTRIBUTE_TODO("blending"), { NULL } //Sentinel }; PyTypeObject KX_BlenderMaterial::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_BlenderMaterial", sizeof(PyObjectPlus_Proxy), 0, @@ -784,6 +833,10 @@ PyObject* KX_BlenderMaterial::py_getattro(PyObject *attr) py_getattro_up(PyObjectPlus); } +PyObject* KX_BlenderMaterial::py_getattro_dict() { + py_getattro_dict_up(PyObjectPlus); +} + int KX_BlenderMaterial::py_setattro(PyObject *attr, PyObject *pyvalue) { return PyObjectPlus::py_setattro(attr, pyvalue); @@ -846,10 +899,10 @@ KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getShader , "getShader()") } -void KX_BlenderMaterial::SetBlenderGLSLShader(void) +void KX_BlenderMaterial::SetBlenderGLSLShader(int layer) { if(!mBlenderShader) - mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, m_lightlayer); + mBlenderShader = new BL_BlenderShader(mScene, mMaterial->material, layer); if(!mBlenderShader->Ok()) { delete mBlenderShader; @@ -859,7 +912,7 @@ void KX_BlenderMaterial::SetBlenderGLSLShader(void) KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getMaterialIndex, "getMaterialIndex()") { - return PyInt_FromLong( mMaterial->material_index ); + return PyInt_FromLong( GetMaterialIndex() ); } KX_PYMETHODDEF_DOC( KX_BlenderMaterial, getTexture, "getTexture( index )" ) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 48d4730ab07..b29f2df98db 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -24,11 +24,13 @@ class KX_BlenderMaterial : public PyObjectPlus, public RAS_IPolyMaterial public: // -------------------------------- KX_BlenderMaterial( + PyTypeObject* T=&Type + ); + void Initialize( class KX_Scene* scene, BL_Material* mat, bool skin, - int lightlayer, - PyTypeObject* T=&Type + int lightlayer ); virtual ~KX_BlenderMaterial(); @@ -73,7 +75,6 @@ public: Image * getImage (unsigned int idx) { return (idx < MAXTEX && mMaterial) ? mMaterial->img[idx] : NULL; } - // for ipos void UpdateIPO( MT_Vector4 rgba, MT_Vector3 specrgb, @@ -83,6 +84,7 @@ public: // -------------------------------- virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *pyvalue); virtual PyObject* py_repr(void) { return PyString_FromString(mMaterial->matname.ReadPtr()); } @@ -95,7 +97,7 @@ public: // -------------------------------- // pre calculate to avoid pops/lag at startup - virtual void OnConstruction( ); + virtual void OnConstruction(int layer); static void EndFrame(); @@ -110,12 +112,16 @@ private: bool mModified; bool mConstructed; // if false, don't clean on exit - void SetBlenderGLSLShader(); + void SetBlenderGLSLShader(int layer); void ActivatGLMaterials( RAS_IRasterizer* rasty )const; void ActivateTexGen( RAS_IRasterizer *ras ) const; bool UsesLighting(RAS_IRasterizer *rasty) const; + void GetMaterialRGBAColor(unsigned char *rgba) const; + Material* GetBlenderMaterial() const; + Scene* GetBlenderScene() const; + void ReleaseMaterial(); // message centers void setTexData( bool enable,RAS_IRasterizer *ras); diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp index 831f9241fec..748b0667061 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.cpp @@ -17,13 +17,17 @@ #include "BulletSoftBody/btSoftBody.h" -KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool compound) -: KX_IPhysicsController(dyna,compound,(PHY_IPhysicsController*)this), +KX_BulletPhysicsController::KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool sensor, bool compound) +: KX_IPhysicsController(dyna,sensor,compound,(PHY_IPhysicsController*)this), CcdPhysicsController(ci), m_savedCollisionFlags(0), +m_savedCollisionFilterGroup(0), +m_savedCollisionFilterMask(0), +m_savedMass(0.0), +m_savedDyna(false), +m_suspended(false), m_bulletChildShape(NULL) { - } KX_BulletPhysicsController::~KX_BulletPhysicsController () @@ -88,7 +92,13 @@ void KX_BulletPhysicsController::SetObject (SG_IObject* object) gameobj->SetPhysicsController(this,gameobj->IsDynamic()); CcdPhysicsController::setNewClientInfo(gameobj->getClientInfo()); - + if (m_bSensor) + { + // use a different callback function for sensor object, + // bullet will not synchronize, we must do it explicitely + SG_Callbacks& callbacks = gameobj->GetSGNode()->GetCallBackFunctions(); + callbacks.m_updatefunc = KX_GameObject::SynchronizeTransformFunc; + } } MT_Scalar KX_BulletPhysicsController::GetRadius() @@ -170,6 +180,20 @@ void KX_BulletPhysicsController::setScaling(const MT_Vector3& scaling) { CcdPhysicsController::setScaling(scaling.x(),scaling.y(),scaling.z()); } +void KX_BulletPhysicsController::SetTransform() +{ + btVector3 pos; + btVector3 scale; + float ori[12]; + m_MotionState->getWorldPosition(pos.m_floats[0],pos.m_floats[1],pos.m_floats[2]); + m_MotionState->getWorldScaling(scale.m_floats[0],scale.m_floats[1],scale.m_floats[2]); + m_MotionState->getWorldOrientation(ori); + btMatrix3x3 rot(ori[0], ori[4], ori[8], + ori[1], ori[5], ori[9], + ori[2], ori[6], ori[10]); + CcdPhysicsController::forceWorldTransform(rot, pos); +} + MT_Scalar KX_BulletPhysicsController::GetMass() { if (GetSoftBody()) @@ -258,7 +282,7 @@ void KX_BulletPhysicsController::AddCompoundChild(KX_IPhysicsController* chil // add to parent compound shapeinfo GetShapeInfo()->AddShape(proxyShapeInfo); // create new bullet collision shape from the object shapeinfo and set scaling - btCollisionShape* newChildShape = proxyShapeInfo->CreateBulletShape(); + btCollisionShape* newChildShape = proxyShapeInfo->CreateBulletShape(childCtrl->GetMargin()); newChildShape->setLocalScaling(relativeScale); // add bullet collision shape to parent compound collision shape compoundShape->addChildShape(proxyShapeInfo->m_childTrans,newChildShape); @@ -337,8 +361,7 @@ void KX_BulletPhysicsController::RemoveCompoundChild(KX_IPhysicsController* c void KX_BulletPhysicsController::SetMass(MT_Scalar newmass) { btRigidBody *body = GetRigidBody(); - if (body && body->getActivationState() != DISABLE_SIMULATION && - newmass>MT_EPSILON && GetMass()>MT_EPSILON) + if (body && !m_suspended && newmass>MT_EPSILON && GetMass()>MT_EPSILON) { btVector3 grav = body->getGravity(); btVector3 accel = grav / GetMass(); @@ -356,34 +379,37 @@ void KX_BulletPhysicsController::SetMass(MT_Scalar newmass) void KX_BulletPhysicsController::SuspendDynamics(bool ghost) { btRigidBody *body = GetRigidBody(); - if (body && body->getActivationState() != DISABLE_SIMULATION) + if (body && !m_suspended && !IsSensor()) { btBroadphaseProxy* handle = body->getBroadphaseHandle(); m_savedCollisionFlags = body->getCollisionFlags(); m_savedMass = GetMass(); + m_savedDyna = m_bDyna; m_savedCollisionFilterGroup = handle->m_collisionFilterGroup; m_savedCollisionFilterMask = handle->m_collisionFilterMask; - m_savedActivationState = body->getActivationState(); - body->forceActivationState(DISABLE_SIMULATION); + m_suspended = true; 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); + m_bDyna = false; } } void KX_BulletPhysicsController::RestoreDynamics() { btRigidBody *body = GetRigidBody(); - if (body && body->getActivationState() == DISABLE_SIMULATION) + if (body && m_suspended) { GetPhysicsEnvironment()->updateCcdPhysicsController(this, m_savedMass, m_savedCollisionFlags, m_savedCollisionFilterGroup, m_savedCollisionFilterMask); - body->forceActivationState(m_savedActivationState); + body->activate(); + m_bDyna = m_savedDyna; + m_suspended = false; } } @@ -438,12 +464,12 @@ SG_Controller* KX_BulletPhysicsController::GetReplica(class SG_Node* destnode) void KX_BulletPhysicsController::SetSumoTransform(bool nondynaonly) { - if (GetRigidBody()) - GetRigidBody()->activate(true); - if (!m_bDyna) + if (!m_bDyna && !m_bSensor) { - GetCollisionObject()->setCollisionFlags(GetRigidBody()->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + btCollisionObject* object = GetRigidBody(); + object->setActivationState(ACTIVE_TAG); + object->setCollisionFlags(object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } else { if (!nondynaonly) diff --git a/source/gameengine/Ketsji/KX_BulletPhysicsController.h b/source/gameengine/Ketsji/KX_BulletPhysicsController.h index b39098206f7..755b1cbd780 100644 --- a/source/gameengine/Ketsji/KX_BulletPhysicsController.h +++ b/source/gameengine/Ketsji/KX_BulletPhysicsController.h @@ -13,11 +13,13 @@ private: short int m_savedCollisionFilterGroup; short int m_savedCollisionFilterMask; MT_Scalar m_savedMass; + bool m_savedDyna; + bool m_suspended; btCollisionShape* m_bulletChildShape; public: - KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool compound); + KX_BulletPhysicsController (const CcdConstructionInfo& ci, bool dyna, bool sensor, bool compound); virtual ~KX_BulletPhysicsController (); /////////////////////////////////// @@ -40,6 +42,7 @@ public: virtual void setOrientation(const MT_Matrix3x3& orn); virtual void setPosition(const MT_Point3& pos); virtual void setScaling(const MT_Vector3& scaling); + virtual void SetTransform(); virtual MT_Scalar GetMass(); virtual void SetMass(MT_Scalar newmass); virtual MT_Vector3 GetLocalInertia(); diff --git a/source/gameengine/Ketsji/KX_CDActuator.cpp b/source/gameengine/Ketsji/KX_CDActuator.cpp index 121d4512265..8511526fd5f 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.cpp +++ b/source/gameengine/Ketsji/KX_CDActuator.cpp @@ -74,9 +74,6 @@ CValue* KX_CDActuator::GetReplica() { KX_CDActuator* replica = new KX_CDActuator(*this); replica->ProcessReplica(); - - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; }; @@ -158,8 +155,13 @@ bool KX_CDActuator::Update() /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_CDActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_SoundActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -212,7 +214,7 @@ int KX_CDActuator::pyattr_setGain(void *self, const struct KX_PYATTRIBUTE_DEF *a { KX_CDActuator* act = static_cast<KX_CDActuator*>(self); SND_CDObject::Instance()->SetGain(act->m_gain); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_CDActuator::py_getattro(PyObject *attr) @@ -220,6 +222,10 @@ PyObject* KX_CDActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* KX_CDActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_CDActuator::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IActuator); diff --git a/source/gameengine/Ketsji/KX_CDActuator.h b/source/gameengine/Ketsji/KX_CDActuator.h index b674755e59f..2fd05ab72e5 100644 --- a/source/gameengine/Ketsji/KX_CDActuator.h +++ b/source/gameengine/Ketsji/KX_CDActuator.h @@ -82,6 +82,7 @@ public: /* -------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); // Deprecated -----> diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index c8575424751..ba4d6e22872 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -28,6 +28,7 @@ * Camera in the gameengine. Cameras are also used for views. */ +#include "GL/glew.h" #include "KX_Camera.h" #include "KX_Scene.h" #include "KX_PythonInit.h" @@ -41,15 +42,17 @@ KX_Camera::KX_Camera(void* sgReplicationInfo, SG_Callbacks callbacks, const RAS_CameraData& camdata, bool frustum_culling, + bool delete_node, PyTypeObject *T) : KX_GameObject(sgReplicationInfo,callbacks,T), m_camdata(camdata), m_dirty(true), m_normalized(false), - m_frustum_culling(frustum_culling && camdata.m_perspective), + m_frustum_culling(frustum_culling), m_set_projection_matrix(false), - m_set_frustum_center(false) + m_set_frustum_center(false), + m_delete_node(delete_node) { // setting a name would be nice... m_name = "cam"; @@ -63,6 +66,12 @@ KX_Camera::KX_Camera(void* sgReplicationInfo, KX_Camera::~KX_Camera() { + if (m_delete_node && m_pSGNode) + { + // for shadow camera, avoids memleak + delete m_pSGNode; + m_pSGNode = NULL; + } } @@ -71,15 +80,16 @@ CValue* KX_Camera::GetReplica() KX_Camera* replica = new KX_Camera(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); - ProcessReplica(replica); + replica->ProcessReplica(); return replica; } - -void KX_Camera::ProcessReplica(KX_Camera* replica) + +void KX_Camera::ProcessReplica() { - KX_GameObject::ProcessReplica(replica); + KX_GameObject::ProcessReplica(); + // replicated camera are always registered in the scene + m_delete_node = false; } MT_Transform KX_Camera::GetWorldToCamera() const @@ -190,6 +200,11 @@ float KX_Camera::GetLens() const return m_camdata.m_lens; } +float KX_Camera::GetScale() const +{ + return m_camdata.m_scale; +} + float KX_Camera::GetCameraNear() const @@ -270,80 +285,83 @@ void KX_Camera::ExtractFrustumSphere() MT_Matrix4x4 clip_camcs_matrix = m_projection_matrix; clip_camcs_matrix.invert(); - // detect which of the corner of the far clipping plane is the farthest to the origin - MT_Vector4 nfar; // far point in device normalized coordinate - MT_Point3 farpoint; // most extreme far point in camera coordinate - MT_Point3 nearpoint;// most extreme near point in camera coordinate - MT_Point3 farcenter(0.,0.,0.);// center of far cliping plane in camera coordinate - MT_Scalar F=1.0, N; // square distance of far and near point to origin - MT_Scalar f, n; // distance of far and near point to z axis. f is always > 0 but n can be < 0 - MT_Scalar e, s; // far and near clipping distance (<0) - MT_Scalar c; // slope of center line = distance of far clipping center to z axis / far clipping distance - MT_Scalar z; // projection of sphere center on z axis (<0) - // tmp value - MT_Vector4 npoint(1., 1., 1., 1.); - MT_Vector4 hpoint; - MT_Point3 point; - MT_Scalar len; - for (int i=0; i<4; i++) - { - hpoint = clip_camcs_matrix*npoint; - point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]); - len = point.dot(point); - if (len > F) - { - nfar = npoint; - farpoint = point; - F = len; - } - // rotate by 90 degree along the z axis to walk through the 4 extreme points of the far clipping plane - len = npoint[0]; - npoint[0] = -npoint[1]; - npoint[1] = len; - farcenter += point; - } - // the far center is the average of the far clipping points - farcenter *= 0.25; - // the extreme near point is the opposite point on the near clipping plane - nfar.setValue(-nfar[0], -nfar[1], -1., 1.); - nfar = clip_camcs_matrix*nfar; - nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]); - N = nearpoint.dot(nearpoint); - e = farpoint[2]; - s = nearpoint[2]; - // projection on XY plane for distance to axis computation - MT_Point2 farxy(farpoint[0], farpoint[1]); - // f is forced positive by construction - f = farxy.length(); - // get corresponding point on the near plane - farxy *= s/e; - // this formula preserve the sign of n - n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length(); - c = MT_Point2(farcenter[0], farcenter[1]).length()/e; - // the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case - z = (F-N)/(2.0*(e-s+c*(f-n))); - m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z); - m_frustum_radius = m_frustum_center.distance(farpoint); - -#if 0 - // The most extreme points on the near and far plane. (normalized device coords) - MT_Vector4 hnear(1., 1., 0., 1.), hfar(1., 1., 1., 1.); - - // Transform to hom camera local space - hnear = clip_camcs_matrix*hnear; - hfar = clip_camcs_matrix*hfar; - - // Tranform to 3d camera local space. - MT_Point3 nearpoint(hnear[0]/hnear[3], hnear[1]/hnear[3], hnear[2]/hnear[3]); - MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]); - - // Compute center - // don't use camera data in case the user specifies the matrix directly - m_frustum_center = MT_Point3(0., 0., - (nearpoint.dot(nearpoint) - farpoint.dot(farpoint))/(2.0*(nearpoint[2]-farpoint[2] /*m_camdata.m_clipend - m_camdata.m_clipstart*/))); - m_frustum_radius = m_frustum_center.distance(farpoint); -#endif - + if (m_projection_matrix[3][3] == MT_Scalar(0.0)) + { + // frustrum projection + // detect which of the corner of the far clipping plane is the farthest to the origin + MT_Vector4 nfar; // far point in device normalized coordinate + MT_Point3 farpoint; // most extreme far point in camera coordinate + MT_Point3 nearpoint;// most extreme near point in camera coordinate + MT_Point3 farcenter(0.,0.,0.);// center of far cliping plane in camera coordinate + MT_Scalar F=-1.0, N; // square distance of far and near point to origin + MT_Scalar f, n; // distance of far and near point to z axis. f is always > 0 but n can be < 0 + MT_Scalar e, s; // far and near clipping distance (<0) + MT_Scalar c; // slope of center line = distance of far clipping center to z axis / far clipping distance + MT_Scalar z; // projection of sphere center on z axis (<0) + // tmp value + MT_Vector4 npoint(1., 1., 1., 1.); + MT_Vector4 hpoint; + MT_Point3 point; + MT_Scalar len; + for (int i=0; i<4; i++) + { + hpoint = clip_camcs_matrix*npoint; + point.setValue(hpoint[0]/hpoint[3], hpoint[1]/hpoint[3], hpoint[2]/hpoint[3]); + len = point.dot(point); + if (len > F) + { + nfar = npoint; + farpoint = point; + F = len; + } + // rotate by 90 degree along the z axis to walk through the 4 extreme points of the far clipping plane + len = npoint[0]; + npoint[0] = -npoint[1]; + npoint[1] = len; + farcenter += point; + } + // the far center is the average of the far clipping points + farcenter *= 0.25; + // the extreme near point is the opposite point on the near clipping plane + nfar.setValue(-nfar[0], -nfar[1], -1., 1.); + nfar = clip_camcs_matrix*nfar; + nearpoint.setValue(nfar[0]/nfar[3], nfar[1]/nfar[3], nfar[2]/nfar[3]); + // this is a frustrum projection + N = nearpoint.dot(nearpoint); + e = farpoint[2]; + s = nearpoint[2]; + // projection on XY plane for distance to axis computation + MT_Point2 farxy(farpoint[0], farpoint[1]); + // f is forced positive by construction + f = farxy.length(); + // get corresponding point on the near plane + farxy *= s/e; + // this formula preserve the sign of n + n = f*s/e - MT_Point2(nearpoint[0]-farxy[0], nearpoint[1]-farxy[1]).length(); + c = MT_Point2(farcenter[0], farcenter[1]).length()/e; + // the big formula, it simplifies to (F-N)/(2(e-s)) for the symmetric case + z = (F-N)/(2.0*(e-s+c*(f-n))); + m_frustum_center = MT_Point3(farcenter[0]*z/e, farcenter[1]*z/e, z); + m_frustum_radius = m_frustum_center.distance(farpoint); + } + else + { + // orthographic projection + // The most extreme points on the near and far plane. (normalized device coords) + MT_Vector4 hnear(1., 1., 1., 1.), hfar(-1., -1., -1., 1.); + + // Transform to hom camera local space + hnear = clip_camcs_matrix*hnear; + hfar = clip_camcs_matrix*hfar; + + // Tranform to 3d camera local space. + MT_Point3 nearpoint(hnear[0]/hnear[3], hnear[1]/hnear[3], hnear[2]/hnear[3]); + MT_Point3 farpoint(hfar[0]/hfar[3], hfar[1]/hfar[3], hfar[2]/hfar[3]); + + // just use mediant point + m_frustum_center = (farpoint + nearpoint)*0.5; + m_frustum_radius = m_frustum_center.distance(farpoint); + } // Transform to world space. m_frustum_center = GetCameraToWorld()(m_frustum_center); m_frustum_radius /= fabs(NodeGetWorldScaling()[NodeGetWorldScaling().closestAxis()]); @@ -474,11 +492,16 @@ PyMethodDef KX_Camera::Methods[] = { KX_PYMETHODTABLE_O(KX_Camera, pointInsideFrustum), KX_PYMETHODTABLE_NOARGS(KX_Camera, getCameraToWorld), KX_PYMETHODTABLE_NOARGS(KX_Camera, getWorldToCamera), - KX_PYMETHODTABLE_NOARGS(KX_Camera, getProjectionMatrix), - KX_PYMETHODTABLE_O(KX_Camera, setProjectionMatrix), - KX_PYMETHODTABLE_O(KX_Camera, enableViewport), KX_PYMETHODTABLE(KX_Camera, setViewport), KX_PYMETHODTABLE_NOARGS(KX_Camera, setOnTop), + KX_PYMETHODTABLE_O(KX_Camera, getScreenPosition), + KX_PYMETHODTABLE(KX_Camera, getScreenVect), + KX_PYMETHODTABLE(KX_Camera, getScreenRay), + + // DEPRECATED + KX_PYMETHODTABLE_O(KX_Camera, enableViewport), + KX_PYMETHODTABLE_NOARGS(KX_Camera, getProjectionMatrix), + KX_PYMETHODTABLE_O(KX_Camera, setProjectionMatrix), {NULL,NULL} //Sentinel }; @@ -492,7 +515,9 @@ PyAttributeDef KX_Camera::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("near", KX_Camera, pyattr_get_near, pyattr_set_near), KX_PYATTRIBUTE_RW_FUNCTION("far", KX_Camera, pyattr_get_far, pyattr_set_far), - KX_PYATTRIBUTE_RO_FUNCTION("projection_matrix", KX_Camera, pyattr_get_projection_matrix), + KX_PYATTRIBUTE_RW_FUNCTION("useViewport", KX_Camera, pyattr_get_use_viewport, pyattr_set_use_viewport), + + KX_PYATTRIBUTE_RW_FUNCTION("projection_matrix", KX_Camera, pyattr_get_projection_matrix, pyattr_set_projection_matrix), KX_PYATTRIBUTE_RO_FUNCTION("modelview_matrix", KX_Camera, pyattr_get_modelview_matrix), KX_PYATTRIBUTE_RO_FUNCTION("camera_to_world", KX_Camera, pyattr_get_camera_to_world), KX_PYATTRIBUTE_RO_FUNCTION("world_to_camera", KX_Camera, pyattr_get_world_to_camera), @@ -506,8 +531,13 @@ PyAttributeDef KX_Camera::Attributes[] = { }; PyTypeObject KX_Camera::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_Camera", sizeof(PyObjectPlus_Proxy), 0, @@ -544,6 +574,10 @@ PyObject* KX_Camera::py_getattro(PyObject *attr) py_getattro_up(KX_GameObject); } +PyObject* KX_Camera::py_getattro_dict() { + py_getattro_dict_up(KX_GameObject); +} + int KX_Camera::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(KX_GameObject); @@ -678,6 +712,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, getProjectionMatrix, "\tie: [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0], [0.0, 0.0, 0.0, 1.0]])\n" ) { + ShowDeprecationWarning("getProjectionMatrix()", "the projection_matrix property"); return PyObjectFrom(GetProjectionMatrix()); /* new ref */ } @@ -723,6 +758,8 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, setProjectionMatrix, "\tcam = co.getOwner()\n" "\tcam.setProjectionMatrix(Perspective(-1.0, 1.0, -1.0, 1.0, 0.1, 1))\n") { + ShowDeprecationWarning("setProjectionMatrix(mat)", "the projection_matrix property"); + MT_Matrix4x4 mat; if (!PyMatTo(value, mat)) { @@ -739,8 +776,9 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, enableViewport, "Sets this camera's viewport status\n" ) { - int viewport = PyObject_IsTrue(value); + ShowDeprecationWarning("enableViewport(bool)", "the useViewport property"); + int viewport = PyObject_IsTrue(value); if (viewport == -1) { PyErr_SetString(PyExc_ValueError, "camera.enableViewport(bool): KX_Camera, expected True/False or 0/1"); return NULL; @@ -770,10 +808,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Camera, setOnTop, "setOnTop()\n" "Sets this camera's viewport on top\n") { - class KX_Scene* scene; - - scene = KX_GetActiveScene(); - MT_assert(scene); + class KX_Scene* scene = KX_GetActiveScene(); scene->SetCameraOnTop(this); Py_RETURN_NONE; } @@ -790,11 +825,11 @@ int KX_Camera::pyattr_set_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *at int param = PyObject_IsTrue( value ); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "camera.perspective = bool: KX_Camera, expected True/False or 0/1"); - return -1; + return PY_SET_ATTR_FAIL; } self->m_camdata.m_perspective= param; - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_Camera::pyattr_get_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -809,12 +844,12 @@ int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, float param = PyFloat_AsDouble(value); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater then zero"); - return -1; + return PY_SET_ATTR_FAIL; } self->m_camdata.m_lens= param; self->m_set_projection_matrix = false; - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_Camera::pyattr_get_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -829,12 +864,12 @@ int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, float param = PyFloat_AsDouble(value); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater then zero"); - return -1; + return PY_SET_ATTR_FAIL; } self->m_camdata.m_clipstart= param; self->m_set_projection_matrix = false; - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_Camera::pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -849,14 +884,34 @@ int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P float param = PyFloat_AsDouble(value); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater then zero"); - return -1; + return PY_SET_ATTR_FAIL; } self->m_camdata.m_clipend= param; self->m_set_projection_matrix = false; - return 0; + return PY_SET_ATTR_SUCCESS; +} + + +PyObject* KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + return PyBool_FromLong(self->GetViewport()); +} + +int KX_Camera::pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Camera* self= static_cast<KX_Camera*>(self_v); + int param = PyObject_IsTrue( value ); + if (param == -1) { + PyErr_SetString(PyExc_AttributeError, "camera.useViewport = bool: KX_Camera, expected True or False"); + return PY_SET_ATTR_FAIL; + } + self->EnableViewport((bool)param); + return PY_SET_ATTR_SUCCESS; } + PyObject* KX_Camera::pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Camera* self= static_cast<KX_Camera*>(self_v); @@ -868,10 +923,10 @@ int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_D KX_Camera* self= static_cast<KX_Camera*>(self_v); MT_Matrix4x4 mat; if (!PyMatTo(value, mat)) - return -1; + return PY_SET_ATTR_FAIL; self->SetProjectionMatrix(mat); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -900,3 +955,197 @@ PyObject* KX_Camera::pyattr_get_OUTSIDE(void *self_v, const KX_PYATTRIBUTE_DEF * PyObject* KX_Camera::pyattr_get_INTERSECT(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { return PyInt_FromLong(INTERSECT); } + +bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix) +{ + if (value==NULL) { + PyErr_Format(PyExc_TypeError, "%s, python pointer NULL, should never happen", error_prefix); + *object = NULL; + return false; + } + + if (value==Py_None) { + *object = NULL; + + if (py_none_ok) { + return true; + } else { + PyErr_Format(PyExc_TypeError, "%s, expected KX_Camera or a KX_Camera name, None is invalid", error_prefix); + return false; + } + } + + if (PyString_Check(value)) { + STR_String value_str = PyString_AsString(value); + *object = KX_GetActiveScene()->FindCamera(value_str); + + if (*object) { + return true; + } else { + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any KX_Camera in this scene", error_prefix, PyString_AsString(value)); + return false; + } + } + + if (PyObject_TypeCheck(value, &KX_Camera::Type)) { + *object = static_cast<KX_Camera*>BGE_PROXY_REF(value); + + /* sets the error */ + if (*object==NULL) { + PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); + return false; + } + + return true; + } + + *object = NULL; + + if (py_none_ok) { + PyErr_Format(PyExc_TypeError, "%s, expect a KX_Camera, a string or None", error_prefix); + } else { + PyErr_Format(PyExc_TypeError, "%s, expect a KX_Camera or a string", error_prefix); + } + + return false; +} + +KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, +"getScreenPosition()\n" +) + +{ + MT_Vector3 vect; + KX_GameObject *obj = NULL; + + if (!PyVecTo(value, vect)) + { + if(ConvertPythonToGameObject(value, &obj, true, "")) + { + PyErr_Clear(); + vect = MT_Vector3(obj->NodeGetWorldPosition()); + } + else + { + PyErr_SetString(PyExc_TypeError, "Error in getScreenPosition. Expected a Vector3 or a KX_GameObject or a string for a name of a KX_GameObject"); + return NULL; + } + } + + GLint viewport[4]; + GLdouble win[3]; + GLdouble modelmatrix[16]; + GLdouble projmatrix[16]; + + MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); + + m_modelmatrix.getValue(modelmatrix); + m_projmatrix.getValue(projmatrix); + + glGetIntegerv(GL_VIEWPORT, viewport); + + gluProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]); + + vect[0] = (win[0] - viewport[0]) / viewport[2]; + vect[1] = (win[1] - viewport[1]) / viewport[3]; + + vect[1] = 1.0 - vect[1]; //to follow Blender window coordinate system (Top-Down) + + PyObject* ret = PyTuple_New(2); + if(ret){ + PyTuple_SET_ITEM(ret, 0, PyFloat_FromDouble(vect[0])); + PyTuple_SET_ITEM(ret, 1, PyFloat_FromDouble(vect[1])); + return ret; + } + + return NULL; +} + +KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect, +"getScreenVect()\n" +) +{ + double x,y; + if (!PyArg_ParseTuple(args,"dd:getScreenVect",&x,&y)) + return NULL; + + y = 1.0 - y; //to follow Blender window coordinate system (Top-Down) + + MT_Vector3 vect; + MT_Point3 campos, screenpos; + + GLint viewport[4]; + GLdouble win[3]; + GLdouble modelmatrix[16]; + GLdouble projmatrix[16]; + + MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); + + m_modelmatrix.getValue(modelmatrix); + m_projmatrix.getValue(projmatrix); + + glGetIntegerv(GL_VIEWPORT, viewport); + + vect[0] = x * viewport[2]; + vect[1] = y * viewport[3]; + + vect[0] += viewport[0]; + vect[1] += viewport[1]; + + glReadPixels(x, y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &vect[2]); + gluUnProject(vect[0], vect[1], vect[2], modelmatrix, projmatrix, viewport, &win[0], &win[1], &win[2]); + + campos = this->GetCameraLocation(); + screenpos = MT_Point3(win[0], win[1], win[2]); + vect = campos-screenpos; + + vect.normalize(); + return PyObjectFrom(vect); +} + +KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenRay, +"getScreenRay()\n" +) +{ + MT_Vector3 vect; + double x,y,dist; + char *propName = NULL; + + if (!PyArg_ParseTuple(args,"ddd|s:getScreenRay",&x,&y,&dist,&propName)) + return NULL; + + PyObject* argValue = PyTuple_New(2); + if (argValue) { + PyTuple_SET_ITEM(argValue, 0, PyFloat_FromDouble(x)); + PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(y)); + } + + if(!PyVecTo(PygetScreenVect(argValue), vect)) + { + Py_DECREF(argValue); + PyErr_SetString(PyExc_TypeError, + "Error in getScreenRay. Invalid 2D coordinate. Expected a normalized 2D screen coordinate, a distance and an optional property argument"); + return NULL; + } + Py_DECREF(argValue); + + dist = -dist; + vect += this->GetCameraLocation(); + + argValue = (propName?PyTuple_New(3):PyTuple_New(2)); + if (argValue) { + PyTuple_SET_ITEM(argValue, 0, PyObjectFrom(vect)); + PyTuple_SET_ITEM(argValue, 1, PyFloat_FromDouble(dist)); + if (propName) + PyTuple_SET_ITEM(argValue, 2, PyString_FromString(propName)); + + PyObject* ret= this->PyrayCastTo(argValue,NULL); + Py_DECREF(argValue); + return ret; + } + + return NULL; +} + diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 4accd4bc2f1..aef21cd91e4 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -41,6 +41,9 @@ #include "IntValue.h" #include "RAS_CameraData.h" +/* utility conversion function */ +bool ConvertPythonToCamera(PyObject * value, KX_Camera **object, bool py_none_ok, const char *error_prefix); + class KX_Camera : public KX_GameObject { Py_Header; @@ -110,6 +113,11 @@ protected: bool m_set_frustum_center; /** + * whether the camera should delete the node itself (only for shadow camera) + */ + bool m_delete_node; + + /** * Extracts the camera clip frames from the projection and world-to-camera matrices. */ void ExtractClipPlanes(); @@ -135,7 +143,7 @@ public: enum { INSIDE, INTERSECT, OUTSIDE } ; - KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, PyTypeObject *T = &Type); + KX_Camera(void* sgReplicationInfo,SG_Callbacks callbacks,const RAS_CameraData& camdata, bool frustum_culling = true, bool delete_node = false, PyTypeObject *T = &Type); virtual ~KX_Camera(); /** @@ -146,15 +154,7 @@ public: virtual CValue* GetReplica( ); - - /** - * Inherited from CValue -- Makes sure any internal - * data owned by this class is deep copied. Called internally - */ - virtual void - ProcessReplica( - KX_Camera* replica - ); + virtual void ProcessReplica(); MT_Transform GetWorldToCamera() const; MT_Transform GetCameraToWorld() const; @@ -193,6 +193,8 @@ public: /** Gets the aperture. */ float GetLens() const; + /** Gets the ortho scale. */ + float GetScale() const; /** Gets the near clip distance. */ float GetCameraNear() const; /** Gets the far clip distance. */ @@ -277,7 +279,12 @@ public: KX_PYMETHOD_DOC_VARARGS(KX_Camera, setViewport); KX_PYMETHOD_DOC_NOARGS(KX_Camera, setOnTop); + KX_PYMETHOD_DOC_O(KX_Camera, getScreenPosition); + KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenVect); + KX_PYMETHOD_DOC_VARARGS(KX_Camera, getScreenRay); + virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */ + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *pyvalue); static PyObject* pyattr_get_perspective(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); @@ -290,6 +297,9 @@ public: static PyObject* pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index 8ef9f318142..f8557dac2c4 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -82,8 +82,6 @@ GetReplica( ) { KX_CameraActuator* replica = new KX_CameraActuator(*this); replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; }; @@ -371,8 +369,13 @@ bool KX_CameraActuator::string2axischoice(const char *axisString) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_CameraActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_CameraActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -416,7 +419,7 @@ PyAttributeDef KX_CameraActuator::Attributes[] = { KX_PYATTRIBUTE_FLOAT_RW("min",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_minHeight), KX_PYATTRIBUTE_FLOAT_RW("max",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_maxHeight), KX_PYATTRIBUTE_FLOAT_RW("height",-FLT_MAX,FLT_MAX,KX_CameraActuator,m_height), - KX_PYATTRIBUTE_BOOL_RW("xy",KX_CameraActuator,m_x), + KX_PYATTRIBUTE_BOOL_RW("useXY",KX_CameraActuator,m_x), KX_PYATTRIBUTE_RW_FUNCTION("object", KX_CameraActuator, pyattr_get_object, pyattr_set_object), {NULL} }; @@ -425,6 +428,10 @@ PyObject* KX_CameraActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); } +PyObject* KX_CameraActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_CameraActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); } @@ -447,7 +454,7 @@ PyObject* KX_CameraActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_ob->GetName()); + return PyString_FromString(m_ob->GetName().ReadPtr()); else return m_ob->GetProxy(); } @@ -554,7 +561,7 @@ const char KX_CameraActuator::SetXY_doc[] = "\t1=x, 0=y\n"; PyObject* KX_CameraActuator::PySetXY(PyObject* args) { - ShowDeprecationWarning("setXY()", "the xy property"); + ShowDeprecationWarning("setXY()", "the useXY property"); int value; if(PyArg_ParseTuple(args,"i:setXY", &value)) { @@ -590,7 +597,7 @@ int KX_CameraActuator::pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF KX_GameObject *gameobj; if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_CameraActuator")) - return 1; // ConvertPythonToGameObject sets the error + return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error if (self->m_ob) self->m_ob->UnregisterActuator(self); @@ -598,7 +605,7 @@ int KX_CameraActuator::pyattr_set_object(void *self_v, const KX_PYATTRIBUTE_DEF if ((self->m_ob = (SCA_IObject*)gameobj)) self->m_ob->RegisterActuator(self); - return 0; + return PY_SET_ATTR_SUCCESS; } /* eof */ diff --git a/source/gameengine/Ketsji/KX_CameraActuator.h b/source/gameengine/Ketsji/KX_CameraActuator.h index 9298e1e868d..efa4e2f38d7 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.h +++ b/source/gameengine/Ketsji/KX_CameraActuator.h @@ -121,6 +121,7 @@ private : /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); /* set object to look at */ diff --git a/source/gameengine/Ketsji/KX_ClientObjectInfo.h b/source/gameengine/Ketsji/KX_ClientObjectInfo.h index 7345edb054b..077ac96f0ac 100644 --- a/source/gameengine/Ketsji/KX_ClientObjectInfo.h +++ b/source/gameengine/Ketsji/KX_ClientObjectInfo.h @@ -50,8 +50,9 @@ struct KX_ClientObjectInfo STATIC, ACTOR, RESERVED1, - RADAR, - NEAR + SENSOR, + OBSENSOR, + OBACTORSENSOR } m_type; KX_GameObject* m_gameobject; void* m_auxilary_info; @@ -84,6 +85,7 @@ public: } bool isActor() { return m_type <= ACTOR; } + bool isSensor() { return m_type >= SENSOR && m_type <= OBACTORSENSOR; } }; #endif //__KX_CLIENTOBJECT_INFO_H diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index c2b4db2de8e..bd03dea486b 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -565,8 +565,13 @@ bool KX_ConstraintActuator::IsValidMode(KX_ConstraintActuator::KX_CONSTRAINTTYPE /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_ConstraintActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_ConstraintActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -625,7 +630,7 @@ PyAttributeDef KX_ConstraintActuator::Attributes[] = { KX_PYATTRIBUTE_FLOAT_ARRAY_RW_CHECK("direction",-FLT_MAX,FLT_MAX,KX_ConstraintActuator,m_refDirection,3,pyattr_check_direction), KX_PYATTRIBUTE_INT_RW("option",0,0xFFFF,false,KX_ConstraintActuator,m_option), KX_PYATTRIBUTE_INT_RW("time",0,1000,true,KX_ConstraintActuator,m_activeTime), - KX_PYATTRIBUTE_STRING_RW("property",0,32,true,KX_ConstraintActuator,m_property), + KX_PYATTRIBUTE_STRING_RW("propName",0,32,true,KX_ConstraintActuator,m_property), KX_PYATTRIBUTE_FLOAT_RW("min",-FLT_MAX,FLT_MAX,KX_ConstraintActuator,m_minimumBound), KX_PYATTRIBUTE_FLOAT_RW("distance",-FLT_MAX,FLT_MAX,KX_ConstraintActuator,m_minimumBound), KX_PYATTRIBUTE_FLOAT_RW("max",-FLT_MAX,FLT_MAX,KX_ConstraintActuator,m_maximumBound), @@ -639,6 +644,10 @@ PyObject* KX_ConstraintActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* KX_ConstraintActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_ConstraintActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); @@ -749,9 +758,9 @@ PyObject* KX_ConstraintActuator::PyGetDirection(){ ShowDeprecationWarning("getDirection()", "the direction property"); PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_refDirection[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_refDirection[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_refDirection[2])); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_refDirection[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_refDirection[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_refDirection[2])); return retVal; } diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.h b/source/gameengine/Ketsji/KX_ConstraintActuator.h index 98f6fcd7906..40607b44947 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.h +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.h @@ -132,8 +132,6 @@ protected: virtual CValue* GetReplica() { KX_ConstraintActuator* replica = new KX_ConstraintActuator(*this); replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; }; @@ -144,6 +142,7 @@ protected: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); static int pyattr_check_direction(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index 7c3abb49159..c5cf67af67d 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -48,24 +48,48 @@ KX_ConstraintWrapper::KX_ConstraintWrapper( KX_ConstraintWrapper::~KX_ConstraintWrapper() { } -//python integration methods -PyObject* KX_ConstraintWrapper::PyTestMethod(PyObject* args, PyObject* kwds) -{ - Py_RETURN_NONE; -} -PyObject* KX_ConstraintWrapper::PyGetConstraintId(PyObject* args, PyObject* kwds) +PyObject* KX_ConstraintWrapper::PyGetConstraintId() { return PyInt_FromLong(m_constraintId); } +PyObject* KX_ConstraintWrapper::PyGetParam(PyObject* args, PyObject* kwds) +{ + int dof; + float value; + + if (!PyArg_ParseTuple(args,"i:getParam",&dof)) + return NULL; + + value = m_physenv->getConstraintParam(m_constraintId,dof); + return PyFloat_FromDouble(value); + +} + +PyObject* KX_ConstraintWrapper::PySetParam(PyObject* args, PyObject* kwds) +{ + int dof; + float minLimit,maxLimit; + + if (!PyArg_ParseTuple(args,"iff:setParam",&dof,&minLimit,&maxLimit)) + return NULL; + + m_physenv->setConstraintParam(m_constraintId,dof,minLimit,maxLimit); + Py_RETURN_NONE; +} //python specific stuff PyTypeObject KX_ConstraintWrapper::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_ConstraintWrapper", sizeof(PyObjectPlus_Proxy), 0, @@ -87,45 +111,33 @@ PyParentObject KX_ConstraintWrapper::Parents[] = { NULL }; -PyObject* KX_ConstraintWrapper::py_getattro(PyObject *attr) +//here you can search for existing data members (like mass,friction etc.) +PyObject* KX_ConstraintWrapper::py_getattro(PyObject *attr) { - //here you can search for existing data members (like mass,friction etc.) py_getattro_up(PyObjectPlus); } -int KX_ConstraintWrapper::py_setattro(PyObject *attr,PyObject* pyobj) +PyObject* KX_ConstraintWrapper::py_getattro_dict() { + py_getattro_dict_up(PyObjectPlus); +} + +int KX_ConstraintWrapper::py_setattro(PyObject *attr,PyObject* value) { - int result = 1; - /* what the heck is this supposed to do?, needs attention */ - if (PyList_Check(pyobj)) - { - result = 0; - } - if (PyFloat_Check(pyobj)) - { - result = 0; - - } - if (PyInt_Check(pyobj)) - { - result = 0; - } - if (PyString_Check(pyobj)) - { - result = 0; - } - if (result) - result = PyObjectPlus::py_setattro(attr,pyobj); - return result; + py_setattro_up(PyObjectPlus); }; + + + PyMethodDef KX_ConstraintWrapper::Methods[] = { - {"testMethod",(PyCFunction) KX_ConstraintWrapper::sPyTestMethod, METH_VARARGS}, - {"getConstraintId",(PyCFunction) KX_ConstraintWrapper::sPyGetConstraintId, METH_VARARGS}, + {"getConstraintId",(PyCFunction) KX_ConstraintWrapper::sPyGetConstraintId, METH_NOARGS}, + {"setParam",(PyCFunction) KX_ConstraintWrapper::sPySetParam, METH_VARARGS}, + {"getParam",(PyCFunction) KX_ConstraintWrapper::sPyGetParam, METH_VARARGS}, {NULL,NULL} //Sentinel }; PyAttributeDef KX_ConstraintWrapper::Attributes[] = { + //KX_PYATTRIBUTE_TODO("constraintId"), { NULL } //Sentinel }; diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h index 6e67d842cb6..03813e0f167 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h @@ -36,14 +36,16 @@ class KX_ConstraintWrapper : public PyObjectPlus { Py_Header; virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); public: KX_ConstraintWrapper(PHY_ConstraintType ctype,int constraintId,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); virtual ~KX_ConstraintWrapper (); int getConstraintId() { return m_constraintId;}; - KX_PYMETHOD(KX_ConstraintWrapper,TestMethod); - KX_PYMETHOD(KX_ConstraintWrapper,GetConstraintId); + KX_PYMETHOD_NOARGS(KX_ConstraintWrapper,GetConstraintId); + KX_PYMETHOD(KX_ConstraintWrapper,SetParam); + KX_PYMETHOD(KX_ConstraintWrapper,GetParam); private: int m_constraintId; diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h index 3534500e619..74042366bae 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObject.h @@ -47,6 +47,7 @@ class RAS_MeshObject; class KX_Scene; +struct DerivedMesh; typedef enum { KX_BOUNDBOX, @@ -82,6 +83,7 @@ struct KX_ObjectProperties bool m_ghost; class KX_GameObject* m_dynamic_parent; bool m_isactor; + bool m_sensor; bool m_concave; bool m_isdeformable; bool m_disableSleeping; @@ -124,6 +126,7 @@ struct KX_ObjectProperties float m_soft_kAHR; /* Anchors hardness [0,1] */ int m_soft_collisionflags; /* Vertex/Face or Signed Distance Field(SDF) or Clusters, Soft versus Soft or Rigid */ int m_soft_numclusteriterations; /* number of iterations to refine collision clusters*/ + float m_soft_welding; /* threshold to remove duplicate/nearby vertices */ ///////////////////////// @@ -136,6 +139,8 @@ struct KX_ObjectProperties ///////////////////////// double m_margin; + float m_contactProcessingThreshold; + KX_BoundBoxClass m_boundclass; union { KX_BoxBounds box; @@ -182,6 +187,7 @@ bool KX_ReInstanceShapeFromMesh(RAS_MeshObject* meshobj); void KX_ConvertBulletObject( class KX_GameObject* gameobj, class RAS_MeshObject* meshobj, + struct DerivedMesh* dm, class KX_Scene* kxscene, struct PHY_ShapeProps* shapeprops, struct PHY_MaterialProps* smmaterial, diff --git a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp index 08e2ea30414..51c41c0686d 100644 --- a/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp +++ b/source/gameengine/Ketsji/KX_ConvertPhysicsObjects.cpp @@ -34,7 +34,7 @@ // defines USE_ODE to choose physics engine #include "KX_ConvertPhysicsObject.h" -#include "KX_GameObject.h" +#include "BL_DeformableGameObject.h" #include "RAS_MeshObject.h" #include "KX_Scene.h" #include "SYS_System.h" @@ -52,6 +52,10 @@ #include "KX_MotionState.h" // bridge between motionstate and scenegraph node +extern "C"{ + #include "BKE_DerivedMesh.h" +} + #ifdef USE_ODE #include "KX_OdePhysicsController.h" @@ -670,11 +674,11 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, class KX_SoftBodyDeformer : public RAS_Deformer { - class RAS_MeshObject* m_pMeshObject; - class KX_GameObject* m_gameobj; + class RAS_MeshObject* m_pMeshObject; + class BL_DeformableGameObject* m_gameobj; public: - KX_SoftBodyDeformer(RAS_MeshObject* pMeshObject,KX_GameObject* gameobj) + KX_SoftBodyDeformer(RAS_MeshObject* pMeshObject,BL_DeformableGameObject* gameobj) :m_pMeshObject(pMeshObject), m_gameobj(gameobj) { @@ -687,7 +691,15 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, }; virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map) { - //printf("relink\n"); + void **h_obj = (*map)[m_gameobj]; + + if (h_obj) { + m_gameobj = (BL_DeformableGameObject*)(*h_obj); + m_pMeshObject = m_gameobj->GetMesh(0); + } else { + m_gameobj = NULL; + m_pMeshObject = NULL; + } } virtual bool Apply(class RAS_IPolyMaterial *polymat) { @@ -749,14 +761,27 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, virtual bool Update(void) { //printf("update\n"); + m_bDynamic = true; return true;//?? } - virtual RAS_Deformer *GetReplica(class KX_GameObject* replica) + virtual bool UpdateBuckets(void) { - KX_SoftBodyDeformer* deformer = new KX_SoftBodyDeformer(replica->GetMesh(0),replica); - return deformer; + // this is to update the mesh slots outside the rasterizer, + // no need to do it for this deformer, it's done in any case in Apply() + return false; } + virtual RAS_Deformer *GetReplica() + { + KX_SoftBodyDeformer* deformer = new KX_SoftBodyDeformer(*this); + deformer->ProcessReplica(); + return deformer; + } + virtual void ProcessReplica() + { + // we have two pointers to deal with but we cannot do it now, will be done in Relink + m_bDynamic = false; + } virtual bool SkipVertexTransform() { return true; @@ -771,6 +796,7 @@ void KX_ConvertODEEngineObject(KX_GameObject* gameobj, void KX_ConvertBulletObject( class KX_GameObject* gameobj, class RAS_MeshObject* meshobj, + struct DerivedMesh* dm, class KX_Scene* kxscene, struct PHY_ShapeProps* shapeprops, struct PHY_MaterialProps* smmaterial, @@ -782,12 +808,12 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, bool isbulletdyna = false; + bool isbulletsensor = false; CcdConstructionInfo ci; class PHY_IMotionState* motionstate = new KX_MotionState(gameobj->GetSGNode()); class CcdShapeConstructionInfo *shapeInfo = new CcdShapeConstructionInfo(); - if (!objprop->m_dyna) { ci.m_collisionFlags |= btCollisionObject::CF_STATIC_OBJECT; @@ -806,6 +832,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_margin = objprop->m_margin; shapeInfo->m_radius = objprop->m_radius; isbulletdyna = objprop->m_dyna; + isbulletsensor = objprop->m_sensor; ci.m_localInertiaTensor = btVector3(ci.m_mass/3.f,ci.m_mass/3.f,ci.m_mass/3.f); @@ -825,7 +852,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, //bm = new MultiSphereShape(inertiaHalfExtents,,&trans.getOrigin(),&radius,1); shapeInfo->m_shapeType = PHY_SHAPE_SPHERE; - bm = shapeInfo->CreateBulletShape(); + bm = shapeInfo->CreateBulletShape(ci.m_margin); break; }; case KX_BOUNDBOX: @@ -838,7 +865,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, shapeInfo->m_halfExtend /= 2.0; shapeInfo->m_halfExtend = shapeInfo->m_halfExtend.absolute(); shapeInfo->m_shapeType = PHY_SHAPE_BOX; - bm = shapeInfo->CreateBulletShape(); + bm = shapeInfo->CreateBulletShape(ci.m_margin); break; }; case KX_BOUNDCYLINDER: @@ -849,7 +876,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, objprop->m_boundobject.c.m_height * 0.5f ); shapeInfo->m_shapeType = PHY_SHAPE_CYLINDER; - bm = shapeInfo->CreateBulletShape(); + bm = shapeInfo->CreateBulletShape(ci.m_margin); break; } @@ -858,45 +885,41 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, shapeInfo->m_radius = objprop->m_boundobject.c.m_radius; shapeInfo->m_height = objprop->m_boundobject.c.m_height; shapeInfo->m_shapeType = PHY_SHAPE_CONE; - bm = shapeInfo->CreateBulletShape(); + bm = shapeInfo->CreateBulletShape(ci.m_margin); break; } case KX_BOUNDPOLYTOPE: { - shapeInfo->SetMesh(meshobj, true,false); - bm = shapeInfo->CreateBulletShape(); + shapeInfo->SetMesh(meshobj, dm,true,false); + bm = shapeInfo->CreateBulletShape(ci.m_margin); break; } case KX_BOUNDMESH: { - - if (!ci.m_mass ||objprop->m_softbody) - { - // mesh shapes can be shared, check first if we already have a shape on that mesh - class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, false); - if (sharedShapeInfo != NULL) - { - delete shapeInfo; - shapeInfo = sharedShapeInfo; - shapeInfo->AddRef(); - } else - { - shapeInfo->SetMesh(meshobj, false,false); - } - - // Soft bodies require welding. Only avoid remove doubles for non-soft bodies! - if (objprop->m_softbody) - shapeInfo->setVertexWeldingThreshold1(0.01f); //todo: expose this to the UI + bool useGimpact = ((ci.m_mass || isbulletsensor) && !objprop->m_softbody); - bm = shapeInfo->CreateBulletShape(); - //no moving concave meshes, so don't bother calculating inertia - //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor); + // mesh shapes can be shared, check first if we already have a shape on that mesh + class CcdShapeConstructionInfo *sharedShapeInfo = CcdShapeConstructionInfo::FindMesh(meshobj, dm, false,useGimpact); + if (sharedShapeInfo != NULL) + { + delete shapeInfo; + shapeInfo = sharedShapeInfo; + shapeInfo->AddRef(); } else { - shapeInfo->SetMesh(meshobj, false,true); - bm = shapeInfo->CreateBulletShape(); + shapeInfo->SetMesh(meshobj, dm, false,useGimpact); + } + + // Soft bodies require welding. Only avoid remove doubles for non-soft bodies! + if (objprop->m_softbody) + { + shapeInfo->setVertexWeldingThreshold1(objprop->m_soft_welding); //todo: expose this to the UI } + bm = shapeInfo->CreateBulletShape(ci.m_margin); + //should we compute inertia for dynamic shape? + //bm->calculateLocalInertia(ci.m_mass,ci.m_localInertiaTensor); + break; } } @@ -911,7 +934,7 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, return; } - bm->setMargin(ci.m_margin); + //bm->setMargin(ci.m_margin); if (objprop->m_isCompoundChild) @@ -926,39 +949,27 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, assert(colShape->isCompound()); btCompoundShape* compoundShape = (btCompoundShape*)colShape; - // compute the local transform from parent, this may include a parent inverse node + // compute the local transform from parent, this may include several node in the chain SG_Node* gameNode = gameobj->GetSGNode(); - SG_Node* parentInverseNode = gameNode->GetSGParent(); - if (parentInverseNode && parentInverseNode->GetSGClientObject() != NULL) - // this is not a parent inverse node, cancel it - parentInverseNode = NULL; - // now combine the parent inverse node and the game node - MT_Point3 childPos = gameNode->GetLocalPosition(); - MT_Matrix3x3 childRot = gameNode->GetLocalOrientation(); - MT_Vector3 childScale = gameNode->GetLocalScale(); - if (parentInverseNode) - { - const MT_Point3& parentInversePos = parentInverseNode->GetLocalPosition(); - const MT_Matrix3x3& parentInverseRot = parentInverseNode->GetLocalOrientation(); - const MT_Vector3& parentInverseScale = parentInverseNode->GetLocalScale(); - childRot = parentInverseRot * childRot; - childScale = parentInverseScale * childScale; - childPos = parentInversePos+parentInverseScale*(parentInverseRot*childPos); - } - - shapeInfo->m_childScale.setValue(childScale.x(),childScale.y(),childScale.z()); + SG_Node* parentNode = objprop->m_dynamic_parent->GetSGNode(); + // relative transform + MT_Vector3 parentScale = parentNode->GetWorldScaling(); + parentScale[0] = MT_Scalar(1.0)/parentScale[0]; + parentScale[1] = MT_Scalar(1.0)/parentScale[1]; + parentScale[2] = MT_Scalar(1.0)/parentScale[2]; + MT_Vector3 relativeScale = gameNode->GetWorldScaling() * parentScale; + MT_Matrix3x3 parentInvRot = parentNode->GetWorldOrientation().transposed(); + MT_Vector3 relativePos = parentInvRot*((gameNode->GetWorldPosition()-parentNode->GetWorldPosition())*parentScale); + MT_Matrix3x3 relativeRot = parentInvRot*gameNode->GetWorldOrientation(); + + shapeInfo->m_childScale.setValue(relativeScale[0],relativeScale[1],relativeScale[2]); bm->setLocalScaling(shapeInfo->m_childScale); - - shapeInfo->m_childTrans.setOrigin(btVector3(childPos.x(),childPos.y(),childPos.z())); - float rotval[12]; - childRot.getValue(rotval); - btMatrix3x3 newRot; - newRot.setValue(rotval[0],rotval[1],rotval[2],rotval[4],rotval[5],rotval[6],rotval[8],rotval[9],rotval[10]); - newRot = newRot.transpose(); - - shapeInfo->m_childTrans.setBasis(newRot); + shapeInfo->m_childTrans.getOrigin().setValue(relativePos[0],relativePos[1],relativePos[2]); + float rot[12]; + relativeRot.getValue(rot); + shapeInfo->m_childTrans.getBasis().setFromOpenGLSubMatrix(rot); + parentShapeInfo->AddShape(shapeInfo); - compoundShape->addChildShape(shapeInfo->m_childTrans,bm); //do some recalc? //recalc inertia for rigidbody @@ -969,6 +980,8 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, compoundShape->calculateLocalInertia(mass,localInertia); rigidbody->setMassProps(mass,localInertia); } + // delete motionstate as it's not used + delete motionstate; return; } @@ -1081,26 +1094,32 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, ci.m_soft_numclusteriterations= objprop->m_soft_numclusteriterations; /* number of iterations to refine collision clusters*/ //////////////////// - - ci.m_collisionFilterGroup = (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) : short(CcdConstructionInfo::StaticFilter); - ci.m_collisionFilterMask = (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter); + ci.m_collisionFilterGroup = + (isbulletsensor) ? short(CcdConstructionInfo::SensorFilter) : + (isbulletdyna) ? short(CcdConstructionInfo::DefaultFilter) : + short(CcdConstructionInfo::StaticFilter); + ci.m_collisionFilterMask = + (isbulletsensor) ? short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter) : + (isbulletdyna) ? short(CcdConstructionInfo::AllFilter) : + short(CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::StaticFilter); ci.m_bRigid = objprop->m_dyna && objprop->m_angular_rigidbody; + + ci.m_contactProcessingThreshold = objprop->m_contactProcessingThreshold;//todo: expose this in advanced settings, just like margin, default to 10000 or so ci.m_bSoft = objprop->m_softbody; + ci.m_bSensor = isbulletsensor; MT_Vector3 scaling = gameobj->NodeGetWorldScaling(); ci.m_scaling.setValue(scaling[0], scaling[1], scaling[2]); - KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna,objprop->m_hasCompoundChildren); + KX_BulletPhysicsController* physicscontroller = new KX_BulletPhysicsController(ci,isbulletdyna,isbulletsensor,objprop->m_hasCompoundChildren); // shapeInfo is reference counted, decrement now as we don't use it anymore if (shapeInfo) shapeInfo->Release(); - if (objprop->m_in_active_layer) + gameobj->SetPhysicsController(physicscontroller,isbulletdyna); + // don't add automatically sensor object, they are added when a collision sensor is registered + if (!isbulletsensor && objprop->m_in_active_layer) { env->addCcdPhysicsController( physicscontroller); } - - - - gameobj->SetPhysicsController(physicscontroller,isbulletdyna); physicscontroller->setNewClientInfo(gameobj->getClientInfo()); { btRigidBody* rbody = physicscontroller->GetRigidBody(); @@ -1159,7 +1178,9 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, } bool isActor = objprop->m_isactor; - gameobj->getClientInfo()->m_type = (isActor ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC); + gameobj->getClientInfo()->m_type = + (isbulletsensor) ? ((isActor) ? KX_ClientObjectInfo::OBACTORSENSOR : KX_ClientObjectInfo::OBSENSOR) : + (isActor) ? KX_ClientObjectInfo::ACTOR : KX_ClientObjectInfo::STATIC; // store materialname in auxinfo, needed for touchsensors if (meshobj) { @@ -1187,9 +1208,8 @@ void KX_ConvertBulletObject( class KX_GameObject* gameobj, if (softBody && gameobj->GetMesh(0))//only the first mesh, if any { //should be a mesh then, so add a soft body deformer - KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer( gameobj->GetMesh(0),gameobj); + KX_SoftBodyDeformer* softbodyDeformer = new KX_SoftBodyDeformer( gameobj->GetMesh(0),(BL_DeformableGameObject*)gameobj); gameobj->SetDeformer(softbodyDeformer); - } } diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp index 321370f9f3f..daa31379985 100644 --- a/source/gameengine/Ketsji/KX_Dome.cpp +++ b/source/gameengine/Ketsji/KX_Dome.cpp @@ -43,29 +43,30 @@ KX_Dome::KX_Dome ( RAS_IRenderTools* rendertools, /// engine KX_KetsjiEngine* engine, - - float size, //size for adjustments + short res, //resolution of the mesh short mode, //mode - fisheye, truncated, warped, panoramic, ... short angle, float resbuf, //size adjustment of the buffer + short tilt, struct Text* warptext ): - m_canvas(canvas), - m_rasterizer(rasterizer), - m_rendertools(rendertools), - m_engine(engine), + dlistSupported(false), + canvaswidth(-1), canvasheight(-1), m_drawingmode(engine->GetDrawType()), - m_size(size), m_resolution(res), m_mode(mode), m_angle(angle), m_resbuffer(resbuf), - canvaswidth(-1), canvasheight(-1), - dlistSupported(false) + m_tilt(tilt), + m_canvas(canvas), + m_rasterizer(rasterizer), + m_rendertools(rendertools), + m_engine(engine) { warp.usemesh = false; + fboSupported = false; if (mode >= DOME_NUM_MODES) m_mode = DOME_FISHEYE; @@ -107,15 +108,9 @@ KX_Dome::KX_Dome ( CreateMeshDome250(); m_numfaces = 5; } break; - case DOME_TRUNCATED: - cubetop.resize(1); - cubebottom.resize(1); - cubeleft.resize(2); - cuberight.resize(2); - - m_angle = 180; - CreateMeshDome180(); - m_numfaces = 4; + case DOME_ENVMAP: + m_angle = 360; + m_numfaces = 6; break; case DOME_PANORAM_SPH: cubeleft.resize(2); @@ -129,6 +124,25 @@ KX_Dome::KX_Dome ( CreateMeshPanorama(); m_numfaces = 6; break; + default: //DOME_TRUNCATED_FRONT and DOME_TRUNCATED_REAR + if (m_angle <= 180){ + cubetop.resize(1); + cubebottom.resize(1); + cubeleft.resize(2); + cuberight.resize(2); + + CreateMeshDome180(); + m_numfaces = 4; + }else if (m_angle > 180){ + cubetop.resize(2); + cubebottom.resize(2); + cubeleft.resize(2); + cubefront.resize(2); + cuberight.resize(2); + + CreateMeshDome250(); + m_numfaces = 5; + } break; } m_numimages =(warp.usemesh?m_numfaces+1:m_numfaces); @@ -137,23 +151,27 @@ KX_Dome::KX_Dome ( CreateGLImages(); + if(warp.usemesh) + fboSupported = CreateFBO(); + dlistSupported = CreateDL(); } // destructor KX_Dome::~KX_Dome (void) { - GLuint m_numimages = m_numfaces; - ClearGLImages(); + if(fboSupported) + glDeleteFramebuffersEXT(1, &warp.fboId); + if(dlistSupported) glDeleteLists(dlistId, (GLsizei) m_numimages); } void KX_Dome::SetViewPort(GLuint viewport[4]) { - if(canvaswidth != m_canvas->GetWidth() || canvasheight != m_canvas->GetHeight()) + if(canvaswidth != m_viewport.GetWidth() || canvasheight != m_viewport.GetHeight()) { m_viewport.SetLeft(viewport[0]); m_viewport.SetBottom(viewport[1]); @@ -180,9 +198,9 @@ void KX_Dome::CreateGLImages(void) } if(warp.usemesh){ glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagewidth, warp.imageheight, 0, GL_RGB8, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagesize, warp.imagesize, 0, GL_RGB8, GL_UNSIGNED_BYTE, 0); - glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, warp.imagewidth, warp.imageheight, 0); + glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, warp.imagesize, warp.imagesize, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -207,12 +225,25 @@ void KX_Dome::CalculateImageSize(void) - reduce the buffer for better performace - create a power of 2 texture bigger than the buffer */ +/* +Blender handles Canvas size differently when in fullscreen mode. +We are manually checking for that. Although it's a hack, it works. + +Bug reported here: #18655 - Inconsistency of pixels in canvas dimensions when in maximized mode (affecting BGE Dome) +http://projects.blender.org/tracker/?func=detail&aid=18655&group_id=9&atid=125 +*/ canvaswidth = m_canvas->GetWidth(); canvasheight = m_canvas->GetHeight(); + bool fullscreen(false); //XXX HACK + fullscreen = (canvaswidth != m_viewport.GetWidth()); + m_buffersize = (canvaswidth > canvasheight?canvasheight:canvaswidth); - m_buffersize *= m_resbuffer; //reduce buffer size for better performance + m_buffersize = (int)(m_buffersize*m_resbuffer); //reduce buffer size for better performance + + if (fullscreen) //XXX HACK + m_buffersize --; int i = 0; while ((1 << i) <= m_buffersize) @@ -220,27 +251,25 @@ void KX_Dome::CalculateImageSize(void) m_imagesize = (1 << i); if (warp.usemesh){ - warp.bufferwidth = canvaswidth; - warp.bufferheight = canvasheight; - - i = 0; - while ((1 << i) <= warp.bufferwidth) - i++; - warp.imagewidth = (1 << i); + // warp FBO needs to be up to twice as big as m_buffersize to get more resolution + warp.imagesize = m_imagesize; + if (m_buffersize == m_imagesize) + warp.imagesize *= 2; - i = 0; - while ((1 << i) <= warp.bufferheight) - i++; - warp.imageheight = (1 << i); + //if FBO is not working/supported, we use the canvas dimension as buffer + warp.bufferwidth = canvaswidth; + warp.bufferheight = canvasheight; } + + //XXX HACK + canvaswidth = m_viewport.GetWidth(); + canvasheight = m_viewport.GetHeight(); } bool KX_Dome::CreateDL(){ - int i,j; - dlistId = glGenLists((GLsizei) m_numimages); if (dlistId != 0) { - if(m_mode == DOME_FISHEYE || m_mode == DOME_TRUNCATED){ + if(m_mode == DOME_FISHEYE || m_mode == DOME_TRUNCATED_FRONT || m_mode == DOME_TRUNCATED_REAR){ glNewList(dlistId, GL_COMPILE); GLDrawTriangles(cubetop, nfacestop); glEndList(); @@ -312,6 +341,46 @@ bool KX_Dome::CreateDL(){ return true; } +bool KX_Dome::CreateFBO(void) +{ + if (!GLEW_EXT_framebuffer_object) + { + printf("Dome Error: FrameBuffer unsupported. Using low resolution warp image."); + return false; + } + + glGenFramebuffersEXT(1, &warp.fboId); + if(warp.fboId==0) + { + printf("Dome Error: Invalid frame buffer object. Using low resolution warp image."); + return false; + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId); + + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_2D, domefacesId[m_numfaces], 0); + + GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); + + if(status == GL_FRAMEBUFFER_UNSUPPORTED_EXT) + { + printf("Dome Error: FrameBuffer settings unsupported. Using low resolution warp image."); + return false; + } + else if(status != GL_FRAMEBUFFER_COMPLETE_EXT) + { + glDeleteFramebuffersEXT(1, &warp.fboId); + return false; + } + + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + //nothing failed: we can use the whole FBO as buffersize + warp.bufferwidth = warp.bufferheight = warp.imagesize; + return true; +} + void KX_Dome::GLDrawTriangles(vector <DomeFace>& face, int nfaces) { int i,j; @@ -328,8 +397,9 @@ void KX_Dome::GLDrawTriangles(vector <DomeFace>& face, int nfaces) void KX_Dome::GLDrawWarpQuads(void) { int i, j, i2; - float uv_width = (float)(warp.bufferwidth-1) / warp.imagewidth; - float uv_height = (float)(warp.bufferheight-1) / warp.imageheight; + + float uv_width = (float)(warp.bufferwidth) / warp.imagesize; + float uv_height = (float)(warp.bufferheight) / warp.imagesize; if(warp.mode ==2 ){ glBegin(GL_QUADS); @@ -386,7 +456,7 @@ void KX_Dome::GLDrawWarpQuads(void) } glEnd(); } else{ - printf("Error: Warp Mode unsupported. Try 1 for Polar Mesh or 2 for Fisheye.\n"); + printf("Dome Error: Warp Mode %d unsupported. Try 1 for Polar Mesh or 2 for Fisheye.\n", warp.mode); } } @@ -415,20 +485,22 @@ y varies from -1 to 1 u and v vary from 0 to 1 i ranges from 0 to 1, if negative don't draw that mesh node */ - int i,j,k; + int i; int nodeX=0, nodeY=0; vector<STR_String> columns, lines; lines = text.Explode('\n'); if(lines.size() < 6){ - printf("Error: Warp Mesh File with insufficient data!\n"); + printf("Dome Error: Warp Mesh File with insufficient data!\n"); return false; } columns = lines[1].Explode(' '); + if(columns.size() == 1) + columns = lines[1].Explode('\t'); if(columns.size() !=2){ - printf("Error: Warp Mesh File incorrect. The second line should contain: width height.\n"); + printf("Dome Error: Warp Mesh File incorrect. The second line should contain: width height.\n"); return false; } @@ -437,14 +509,16 @@ i ranges from 0 to 1, if negative don't draw that mesh node warp.n_width = atoi(columns[0]); warp.n_height = atoi(columns[1]); - if (lines.size() < 2 + (warp.n_width * warp.n_height)){ - printf("Error: Warp Mesh File with insufficient data!\n"); + if ((int)lines.size() < 2 + (warp.n_width * warp.n_height)){ + printf("Dome Error: Warp Mesh File with insufficient data!\n"); return false; }else{ warp.nodes = vector<vector<WarpMeshNode> > (warp.n_height, vector<WarpMeshNode>(warp.n_width)); for(i=2; i-2 < (warp.n_width*warp.n_height); i++){ columns = lines[i].Explode(' '); + if(columns.size() == 1) + columns = lines[i].Explode('\t'); if (columns.size() == 5){ nodeX = (i-2)%warp.n_width; @@ -458,7 +532,7 @@ i ranges from 0 to 1, if negative don't draw that mesh node } else{ warp.nodes.clear(); - printf("Error: Warp Mesh File with wrong number of fields. You should use 5: x y u v i.\n"); + printf("Dome Error: Warp Mesh File with wrong number of fields. You should use 5: x y u v i.\n"); return false; } } @@ -1373,7 +1447,7 @@ void KX_Dome::CalculateFrustum(KX_Camera * cam) /* // manually creating a 90º Field of View Frustum - the original formula: + the original formula: top = tan(fov*3.14159/360.0) * near [for fov in degrees] fov*0.5 = arctan ((top-bottom)*0.5 / near) [for fov in radians] bottom = -top @@ -1411,11 +1485,14 @@ Uses 4 cameras for angles up to 180º Uses 5 cameras for angles up to 250º Uses 6 cameras for angles up to 360º */ + int i; float deg45 = MT_PI / 4; MT_Scalar c = cos(deg45); MT_Scalar s = sin(deg45); - if ((m_mode == DOME_FISHEYE && m_angle <= 180)|| m_mode == DOME_TRUNCATED){ + if (m_angle <= 180 && (m_mode == DOME_FISHEYE + || m_mode == DOME_TRUNCATED_FRONT + || m_mode == DOME_TRUNCATED_REAR)){ m_locRot[0] = MT_Matrix3x3( // 90º - Top c, -s, 0.0, @@ -1437,7 +1514,9 @@ Uses 6 cameras for angles up to 360º 0.0, 1.0, 0.0, s, 0.0, c); - } else if ((m_mode == DOME_FISHEYE && m_angle > 180)){ + } else if (m_mode == DOME_ENVMAP || (m_angle > 180 && (m_mode == DOME_FISHEYE + || m_mode == DOME_TRUNCATED_FRONT + || m_mode == DOME_TRUNCATED_REAR))){ m_locRot[0] = MT_Matrix3x3( // 90º - Top 1.0, 0.0, 0.0, @@ -1464,7 +1543,7 @@ Uses 6 cameras for angles up to 360º 0.0, 1.0, 0.0, 0.0, 0.0, 1.0); - m_locRot[5] = MT_Matrix3x3( // 180º - Back - NOT USING + m_locRot[5] = MT_Matrix3x3( // 180º - Back - USED for ENVMAP only -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0,-1.0); @@ -1501,6 +1580,23 @@ Uses 6 cameras for angles up to 360º 0.0, 1.0, 0.0, s, 0.0, c); } + + // rotating the camera in horizontal axis + if (m_tilt) + { + float tiltdeg = ((m_tilt % 360) * 2 * MT_PI) / 360; + c = cos(tiltdeg); + s = sin(tiltdeg); + + MT_Matrix3x3 tilt_mat = MT_Matrix3x3( + 1.0, 0.0, 0.0, + 0.0, c, -s, + 0.0, s, c + ); + + for (i =0;i<6;i++) + m_locRot[i] = tilt_mat * m_locRot[i]; + } } void KX_Dome::RotateCamera(KX_Camera* cam, int i) @@ -1515,8 +1611,7 @@ void KX_Dome::RotateCamera(KX_Camera* cam, int i) MT_Transform camtrans(cam->GetWorldToCamera()); MT_Matrix4x4 viewmat(camtrans); - m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(), - cam->GetCameraLocation(), cam->GetCameraOrientation()); + m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective); cam->SetModelviewMatrix(viewmat); // restore the original orientation @@ -1527,30 +1622,49 @@ void KX_Dome::RotateCamera(KX_Camera* cam, int i) void KX_Dome::Draw(void) { + if (fboSupported){ + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId); + + glViewport(0,0,warp.imagesize, warp.imagesize); + glScissor(0,0,warp.imagesize, warp.imagesize); + } + switch(m_mode){ case DOME_FISHEYE: DrawDomeFisheye(); break; - case DOME_TRUNCATED: - DrawDomeFisheye(); + case DOME_ENVMAP: + DrawEnvMap(); break; case DOME_PANORAM_SPH: DrawPanorama(); break; + case DOME_TRUNCATED_FRONT: + DrawDomeFisheye(); + break; + case DOME_TRUNCATED_REAR: + DrawDomeFisheye(); + break; } if(warp.usemesh) { - glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth, warp.bufferheight); + if(fboSupported) + { + m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight()); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + } + else + { + glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth, warp.bufferheight); + } DrawDomeWarped(); } } -void KX_Dome::DrawDomeFisheye(void) +void KX_Dome::DrawEnvMap(void) { - int i,j; - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -1563,28 +1677,17 @@ void KX_Dome::DrawDomeFisheye(void) float ortho_width, ortho_height; if (warp.usemesh) - glOrtho((-1.0), 1.0, (-1.0), 1.0, -20.0, 10.0); //stretch the image to reduce resolution lost + glOrtho((-1.0), 1.0, (-0.66), 0.66, -20.0, 10.0); //stretch the image to reduce resolution lost - else if(m_mode == DOME_TRUNCATED){ - ortho_width = 1.0; - ortho_height = 2 * ((float)can_height/can_width) - 1.0 ; - - ortho_width /= m_size; - ortho_height /= m_size; - - glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0); - } else { - if (can_width < can_height){ + else { + if (can_width/3 <= can_height/2){ ortho_width = 1.0; ortho_height = (float)can_height/can_width; }else{ - ortho_width = (float)can_width/can_height; - ortho_height = 1.0; + ortho_height = 2.0f / 3; + ortho_width = (float)can_width/can_height * ortho_height; } - ortho_width /= m_size; - ortho_height /= m_size; - glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0); } @@ -1592,6 +1695,150 @@ void KX_Dome::DrawDomeFisheye(void) glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); + gluLookAt(0.0,0.0,1.0, 0.0,0.0,0.0, 0.0,1.0,0.0); + + glPolygonMode(GL_FRONT, GL_FILL); + glShadeModel(GL_SMOOTH); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glEnable(GL_TEXTURE_2D); + glColor3f(1.0,1.0,1.0); + + float uv_ratio = (float)(m_buffersize-1) / m_imagesize; + double onebythree = 1.0f / 3; + + // domefacesId[0] => (top) + glBindTexture(GL_TEXTURE_2D, domefacesId[0]); + glBegin(GL_QUADS); + glTexCoord2f(uv_ratio,uv_ratio); + glVertex3f( onebythree, 0.0f, 3.0f); + glTexCoord2f(0.0,uv_ratio); + glVertex3f(-onebythree, 0.0f, 3.0f); + glTexCoord2f(0.0,0.0); + glVertex3f(-onebythree,-2 * onebythree, 3.0f); + glTexCoord2f(uv_ratio,0.0); + glVertex3f(onebythree,-2 * onebythree, 3.0f); + glEnd(); + + // domefacesId[1] => (bottom) + glBindTexture(GL_TEXTURE_2D, domefacesId[1]); + glBegin(GL_QUADS); + glTexCoord2f(uv_ratio,uv_ratio); + glVertex3f(-onebythree, 0.0f, 3.0f); + glTexCoord2f(0.0,uv_ratio); + glVertex3f(-1.0f, 0.0f, 3.0f); + glTexCoord2f(0.0,0.0); + glVertex3f(-1.0f,-2 * onebythree, 3.0f); + glTexCoord2f(uv_ratio,0.0); + glVertex3f(-onebythree,-2 * onebythree, 3.0f); + glEnd(); + + // domefacesId[2] => -90º (left) + glBindTexture(GL_TEXTURE_2D, domefacesId[2]); + glBegin(GL_QUADS); + glTexCoord2f(uv_ratio,uv_ratio); + glVertex3f(-onebythree, 2 * onebythree, 3.0f); + glTexCoord2f(0.0,uv_ratio); + glVertex3f(-1.0f, 2 * onebythree, 3.0f); + glTexCoord2f(0.0,0.0); + glVertex3f(-1.0f, 0.0f, 3.0f); + glTexCoord2f(uv_ratio,0.0); + glVertex3f(-onebythree, 0.0f, 3.0f); + glEnd(); + + // domefacesId[3] => 90º (right) + glBindTexture(GL_TEXTURE_2D, domefacesId[3]); + glBegin(GL_QUADS); + glTexCoord2f(uv_ratio,uv_ratio); + glVertex3f( 1.0f, 2 * onebythree, 3.0f); + glTexCoord2f(0.0,uv_ratio); + glVertex3f( onebythree, 2 * onebythree, 3.0f); + glTexCoord2f(0.0,0.0); + glVertex3f( onebythree, 0.0f, 3.0f); + glTexCoord2f(uv_ratio,0.0); + glVertex3f(1.0f, 0.0f, 3.0f); + glEnd(); + + // domefacesId[4] => 0º (front) + glBindTexture(GL_TEXTURE_2D, domefacesId[4]); + glBegin(GL_QUADS); + glTexCoord2f(uv_ratio,uv_ratio); + glVertex3f( 1.0f, 0.0f, 3.0f); + glTexCoord2f(0.0,uv_ratio); + glVertex3f( onebythree, 0.0f, 3.0f); + glTexCoord2f(0.0,0.0); + glVertex3f( onebythree,-2 * onebythree, 3.0f); + glTexCoord2f(uv_ratio,0.0); + glVertex3f(1.0f, -2 * onebythree, 3.0f); + glEnd(); + + // domefacesId[5] => 180º (back) + glBindTexture(GL_TEXTURE_2D, domefacesId[5]); + glBegin(GL_QUADS); + glTexCoord2f(uv_ratio,uv_ratio); + glVertex3f( onebythree, 2 * onebythree, 3.0f); + glTexCoord2f(0.0,uv_ratio); + glVertex3f(-onebythree, 2 * onebythree, 3.0f); + glTexCoord2f(0.0,0.0); + glVertex3f(-onebythree, 0.0f, 3.0f); + glTexCoord2f(uv_ratio,0.0); + glVertex3f(onebythree, 0.0f, 3.0f); + glEnd(); + + glDisable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); +} + +void KX_Dome::DrawDomeFisheye(void) +{ + int i; + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // Making the viewport always square + + int can_width = m_viewport.GetRight(); + int can_height = m_viewport.GetTop(); + + float ortho_width, ortho_height; + + if(m_mode == DOME_FISHEYE) { + if (warp.usemesh) + glOrtho((-1.0), 1.0, (-1.0), 1.0, -20.0, 10.0); //stretch the image to reduce resolution lost + + else { + if (can_width < can_height){ + ortho_width = 1.0; + ortho_height = (float)can_height/can_width; + }else{ + ortho_width = (float)can_width/can_height; + ortho_height = 1.0; + } + + glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0); + } + } + else if(m_mode == DOME_TRUNCATED_FRONT) + { + ortho_width = 1.0; + ortho_height = 2 * ((float)can_height/can_width) - 1.0 ; + + glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_width, -20.0, 10.0); + } + else { //m_mode == DOME_TRUNCATED_REAR + ortho_width = 1.0; + ortho_height = 2 * ((float)can_height/can_width) - 1.0 ; + + glOrtho((-ortho_width), ortho_width, (-ortho_width), ortho_height, -20.0, 10.0); + } + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); gluLookAt(0.0,-1.0,0.0, 0.0,0.0,0.0, 0.0,0.0,1.0); if(m_drawingmode == RAS_IRasterizer::KX_WIREFRAME) @@ -1641,7 +1888,7 @@ void KX_Dome::DrawDomeFisheye(void) void KX_Dome::DrawPanorama(void) { - int i,j; + int i; glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -1666,9 +1913,6 @@ void KX_Dome::DrawPanorama(void) ortho_width = (float)can_width/can_height * 0.5; ortho_height = 0.5; } - - ortho_width /= m_size; - ortho_height /= m_size; glOrtho((-ortho_width), ortho_width, (-ortho_height), ortho_height, -20.0, 10.0); } @@ -1728,8 +1972,6 @@ void KX_Dome::DrawPanorama(void) void KX_Dome::DrawDomeWarped(void) { - int i,j; - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); @@ -1739,7 +1981,6 @@ void KX_Dome::DrawDomeWarped(void) int can_height = m_viewport.GetTop(); double screen_ratio = can_width/ (double) can_height; - screen_ratio /= m_size; glOrtho(-screen_ratio,screen_ratio,-1.0,1.0,-20.0,10.0); @@ -1762,10 +2003,6 @@ void KX_Dome::DrawDomeWarped(void) glEnable(GL_TEXTURE_2D); glColor3f(1.0,1.0,1.0); - - float uv_width = (float)(warp.bufferwidth-1) / warp.imagewidth; - float uv_height = (float)(warp.bufferheight-1) / warp.imageheight; - if (dlistSupported){ glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]); glCallList(dlistId + m_numfaces); @@ -1806,8 +2043,7 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i) MT_Transform camtrans(cam->GetWorldToCamera()); MT_Matrix4x4 viewmat(camtrans); - m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(), - cam->GetCameraLocation(), cam->GetCameraOrientation()); + m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), 1.0); cam->SetModelviewMatrix(viewmat); scene->CalculateVisibleMeshes(m_rasterizer,cam); @@ -1816,4 +2052,5 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i) // restore the original orientation cam->NodeSetLocalOrientation(camori); cam->NodeUpdateGS(0.f); -}
\ No newline at end of file +} + diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h index 786e04b4385..20b60ef0173 100644 --- a/source/gameengine/Ketsji/KX_Dome.h +++ b/source/gameengine/Ketsji/KX_Dome.h @@ -38,13 +38,14 @@ Developed as part of a Research and Development project for SAT - La Société des #include "MEM_guardedalloc.h" #include "BKE_text.h" -//#include "BLI_blenlib.h" //Dome modes: limit hardcoded in buttons_scene.c -#define DOME_FISHEYE 1 -#define DOME_TRUNCATED 2 -#define DOME_PANORAM_SPH 3 -#define DOME_NUM_MODES 4 +#define DOME_FISHEYE 1 +#define DOME_TRUNCATED_FRONT 2 +#define DOME_TRUNCATED_REAR 3 +#define DOME_ENVMAP 4 +#define DOME_PANORAM_SPH 5 +#define DOME_NUM_MODES 6 /// class for render 3d scene @@ -60,12 +61,12 @@ public: RAS_IRenderTools* m_rendertools, /// engine KX_KetsjiEngine* m_engine, - - float size, + short res, short mode, short angle, float resbuf, + short tilt, struct Text* warptext ); @@ -74,6 +75,7 @@ public: //openGL checks: bool dlistSupported; + bool fboSupported; //openGL names: GLuint domefacesId[7]; // ID of the images -- room for 7 images, using only 4 for 180º x 360º dome, 6 for panoramic and +1 for warp mesh @@ -93,8 +95,9 @@ public: bool usemesh; int mode; int n_width, n_height; //nodes width and height - int imagewidth, imageheight; + int imagesize; int bufferwidth, bufferheight; + GLuint fboId; vector <vector <WarpMeshNode> > nodes; } warp; @@ -116,7 +119,7 @@ public: void CalculateFrustum(KX_Camera* cam); void RotateCamera(KX_Camera* cam, int i); - //Mesh Creating Functions + //Mesh creation Functions void CreateMeshDome180(void); void CreateMeshDome250(void); void CreateMeshPanorama(void); @@ -131,6 +134,7 @@ public: void GLDrawWarpQuads(void); void Draw(void); void DrawDomeFisheye(void); + void DrawEnvMap(void); void DrawPanorama(void); void DrawDomeWarped(void); @@ -139,6 +143,8 @@ public: void ClearGLImages(void);//called on resize bool CreateDL(void); //create Display Lists void ClearDL(void); //remove Display Lists + bool CreateFBO(void);//create FBO (for warp mesh) + void ClearFBO(void); //remove FBO void CalculateCameraOrientation(); void CalculateImageSize(); //set m_imagesize @@ -153,13 +159,13 @@ protected: int m_buffersize; // canvas small dimension int m_numfaces; // 4 to 6 depending on the kind of dome image int m_numimages; //numfaces +1 if we have warp mesh - - float m_size; // size to adjust + short m_resolution; //resolution to tesselate the mesh short m_mode; // the mode (truncated, warped, panoramic,...) short m_angle; //the angle of the fisheye float m_radangle; //the angle of the fisheye in radians float m_resbuffer; //the resolution of the buffer + short m_tilt; //the dome tilt (camera rotation on horizontal axis) RAS_Rect m_viewport; @@ -181,3 +187,4 @@ protected: }; #endif + diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index 8b587c6f7de..28bf12f5e87 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -73,8 +73,6 @@ CValue* KX_GameActuator::GetReplica() { KX_GameActuator* replica = new KX_GameActuator(*this); replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; } @@ -151,6 +149,8 @@ bool KX_GameActuator::Update() } else { printf("Warning: could not create marshal buffer\n"); } + if (marshal_buffer) + delete [] marshal_buffer; } break; } @@ -208,8 +208,13 @@ bool KX_GameActuator::Update() /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_GameActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_GameActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -249,16 +254,20 @@ PyMethodDef KX_GameActuator::Methods[] = }; PyAttributeDef KX_GameActuator::Attributes[] = { - KX_PYATTRIBUTE_STRING_RW("file",0,100,false,KX_GameActuator,m_filename), + KX_PYATTRIBUTE_STRING_RW("fileName",0,100,false,KX_GameActuator,m_filename), + KX_PYATTRIBUTE_INT_RW("mode", KX_GAME_NODEF+1, KX_GAME_MAX-1, true, KX_GameActuator, m_mode), { NULL } //Sentinel }; -PyObject* -KX_GameActuator::py_getattro(PyObject *attr) +PyObject* KX_GameActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); } +PyObject* KX_GameActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_GameActuator::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IActuator); @@ -272,7 +281,7 @@ const char KX_GameActuator::GetFile_doc[] = "get the name of the file to start.\n"; PyObject* KX_GameActuator::PyGetFile(PyObject* args, PyObject* kwds) { - ShowDeprecationWarning("getFile()", "the file property"); + ShowDeprecationWarning("getFile()", "the fileName property"); return PyString_FromString(m_filename); } @@ -284,7 +293,7 @@ PyObject* KX_GameActuator::PySetFile(PyObject* args, PyObject* kwds) { char* new_file; - ShowDeprecationWarning("setFile()", "the file property"); + ShowDeprecationWarning("setFile()", "the fileName property"); if (!PyArg_ParseTuple(args, "s:setFile", &new_file)) { diff --git a/source/gameengine/Ketsji/KX_GameActuator.h b/source/gameengine/Ketsji/KX_GameActuator.h index 570cb2e68ef..b2b1d6ec2b9 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.h +++ b/source/gameengine/Ketsji/KX_GameActuator.h @@ -78,6 +78,7 @@ protected: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); // Deprecated functions -----> diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index bea0fcff2af..7f417b325c8 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -49,6 +49,8 @@ typedef unsigned long uint_ptr; #include "RAS_IPolygonMaterial.h" #include "KX_BlenderMaterial.h" #include "KX_GameObject.h" +#include "KX_Camera.h" // only for their ::Type +#include "KX_Light.h" // only for their ::Type #include "RAS_MeshObject.h" #include "KX_MeshProxy.h" #include "KX_PolyProxy.h" @@ -63,6 +65,7 @@ typedef unsigned long uint_ptr; #include "KX_RayCast.h" #include "KX_PythonInit.h" #include "KX_PyMath.h" +#include "KX_PythonSeq.h" #include "SCA_IActuator.h" #include "SCA_ISensor.h" #include "SCA_IController.h" @@ -187,38 +190,23 @@ double KX_GameObject::GetNumber() -STR_String KX_GameObject::GetName() +STR_String& KX_GameObject::GetName() { return m_name; } -void KX_GameObject::SetName(STR_String name) +void KX_GameObject::SetName(const char *name) { m_name = name; }; // Set the name of the value - - -void KX_GameObject::ReplicaSetName(STR_String name) -{ -} - - - - - - KX_IPhysicsController* KX_GameObject::GetPhysicsController() { return m_pPhysicsController1; } - - - - KX_GameObject* KX_GameObject::GetParent() { KX_GameObject* result = NULL; @@ -238,7 +226,7 @@ KX_GameObject* KX_GameObject::GetParent() } -void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) +void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj, bool addToCompound, bool ghost) { // check on valid node in case a python controller holds a reference to a deleted object if (obj && GetSGNode() && obj->GetSGNode() && GetSGNode()->GetSGParent() != obj->GetSGNode()) @@ -259,7 +247,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) if (m_pPhysicsController1) { - m_pPhysicsController1->SuspendDynamics(true); + m_pPhysicsController1->SuspendDynamics(ghost); } // Set us to our new scale, position, and orientation scale2[0] = 1.0/scale2[0]; @@ -280,7 +268,7 @@ void KX_GameObject::SetParent(KX_Scene *scene, KX_GameObject* obj) Release(); // if the new parent is a compound object, add this object shape to the compound shape. // step 0: verify this object has physical controller - if (m_pPhysicsController1) + if (m_pPhysicsController1 && addToCompound) { // step 1: find the top parent (not necessarily obj) KX_GameObject* rootobj = (KX_GameObject*)obj->GetSGNode()->GetRootSGParent()->GetSGClientObject(); @@ -326,33 +314,75 @@ void KX_GameObject::RemoveParent(KX_Scene *scene) rootobj->m_pPhysicsController1->RemoveCompoundChild(m_pPhysicsController1); } m_pPhysicsController1->RestoreDynamics(); + if (m_pPhysicsController1->IsDyna() && rootobj->m_pPhysicsController1) + { + // dynamic object should remember the velocity they had while being parented + MT_Point3 childPoint = GetSGNode()->GetWorldPosition(); + MT_Point3 rootPoint = rootobj->GetSGNode()->GetWorldPosition(); + MT_Point3 relPoint; + relPoint = (childPoint-rootPoint); + MT_Vector3 linVel = rootobj->m_pPhysicsController1->GetVelocity(relPoint); + MT_Vector3 angVel = rootobj->m_pPhysicsController1->GetAngularVelocity(); + m_pPhysicsController1->SetLinearVelocity(linVel, false); + m_pPhysicsController1->SetAngularVelocity(angVel, false); + } } // graphically, the object hasn't change place, no need to update m_pGraphicController } } -void KX_GameObject::ProcessReplica(KX_GameObject* replica) +void KX_GameObject::ProcessReplica() { - replica->m_pPhysicsController1 = NULL; - replica->m_pGraphicController = NULL; - 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; + SCA_IObject::ProcessReplica(); + + m_pPhysicsController1 = NULL; + m_pGraphicController = NULL; + m_pSGNode = NULL; + m_pClient_info = new KX_ClientObjectInfo(*m_pClient_info); + m_pClient_info->m_gameobject = this; + m_state = 0; if(m_attr_dict) - replica->m_attr_dict= PyDict_Copy(m_attr_dict); + m_attr_dict= PyDict_Copy(m_attr_dict); + +} + +static void setGraphicController_recursive(SG_Node* node) +{ + NodeList& children = node->GetSGChildren(); + + for (NodeList::iterator childit = children.begin();!(childit==children.end());++childit) + { + SG_Node* childnode = (*childit); + KX_GameObject *clientgameobj = static_cast<KX_GameObject*>( (*childit)->GetSGClientObject()); + if (clientgameobj != NULL) // This is a GameObject + clientgameobj->ActivateGraphicController(false); + // if the childobj is NULL then this may be an inverse parent link + // so a non recursive search should still look down this node. + setGraphicController_recursive(childnode); + } } +void KX_GameObject::ActivateGraphicController(bool recurse) +{ + if (m_pGraphicController) + { + m_pGraphicController->Activate(m_bVisible); + } + if (recurse) + { + setGraphicController_recursive(GetSGNode()); + } +} + CValue* KX_GameObject::GetReplica() { KX_GameObject* replica = new KX_GameObject(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); - ProcessReplica(replica); + replica->ProcessReplica(); return replica; } @@ -421,6 +451,7 @@ double* KX_GameObject::GetOpenGLMatrix() m_bIsNegativeScaling = ((scaling[0] < 0.0) ^ (scaling[1] < 0.0) ^ (scaling[2] < 0.0)) ? true : false; trans.scale(scaling[0], scaling[1], scaling[2]); trans.getValue(fl); + GetSGNode()->ClearDirty(); } return fl; } @@ -428,8 +459,18 @@ double* KX_GameObject::GetOpenGLMatrix() void KX_GameObject::AddMeshUser() { for (size_t i=0;i<m_meshes.size();i++) - m_meshes[i]->AddMeshUser(this); - + { + m_meshes[i]->AddMeshUser(this, &m_meshSlots, GetDeformer()); + } + // set the part of the mesh slot that never change + double* fl = GetOpenGLMatrixPtr()->getPointer(); + + SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots); + RAS_MeshSlot* ms; + for(mit.begin(); !mit.end(); ++mit) + { + (*mit)->m_OpenGLMatrix = fl; + } UpdateBuckets(false); } @@ -453,10 +494,27 @@ static void UpdateBuckets_recursive(SG_Node* node) void KX_GameObject::UpdateBuckets( bool recursive ) { if (GetSGNode()) { - double* fl = GetOpenGLMatrixPtr()->getPointer(); + RAS_MeshSlot *ms; + + if (GetSGNode()->IsDirty()) + GetOpenGLMatrix(); - for (size_t i=0;i<m_meshes.size();i++) - m_meshes[i]->UpdateBuckets(this, fl, m_bUseObjectColor, m_objectColor, m_bVisible, m_bCulled); + SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots); + for(mit.begin(); !mit.end(); ++mit) + { + ms = *mit; + ms->m_bObjectColor = m_bUseObjectColor; + ms->m_RGBAcolor = m_objectColor; + ms->m_bVisible = m_bVisible; + ms->m_bCulled = m_bCulled || !m_bVisible; + if (!ms->m_bCulled) + ms->m_bucket->ActivateMesh(ms); + + /* split if necessary */ +#ifdef USE_SPLIT + ms->Split(); +#endif + } if (recursive) { UpdateBuckets_recursive(GetSGNode()); @@ -476,11 +534,11 @@ void KX_GameObject::RemoveMeshes() void KX_GameObject::UpdateTransform() { - if (m_pPhysicsController1) - // only update the transform of static object, dynamic object are handled differently - // note that for bullet, this does not even update the transform of static object + // HACK: saves function call for dynamic object, they are handled differently + if (m_pPhysicsController1 && !m_pPhysicsController1->IsDyna()) + // Note that for Bullet, this does not even update the transform of static object // but merely sets there collision flag to "kinematic" because the synchronization is - // done differently during physics simulation + // done during physics simulation m_pPhysicsController1->SetSumoTransform(true); if (m_pGraphicController) // update the culling tree @@ -493,6 +551,20 @@ void KX_GameObject::UpdateTransformFunc(SG_IObject* node, void* gameobj, void* s ((KX_GameObject*)gameobj)->UpdateTransform(); } +void KX_GameObject::SynchronizeTransform() +{ + // only used for sensor object, do full synchronization as bullet doesn't do it + if (m_pPhysicsController1) + m_pPhysicsController1->SetTransform(); + if (m_pGraphicController) + m_pGraphicController->SetGraphicTransform(); +} + +void KX_GameObject::SynchronizeTransformFunc(SG_IObject* node, void* gameobj, void* scene) +{ + ((KX_GameObject*)gameobj)->SynchronizeTransform(); +} + void KX_GameObject::SetDebugColor(unsigned int bgra) { @@ -613,6 +685,8 @@ KX_GameObject::SetVisible( { if (GetSGNode()) { m_bVisible = v; + if (m_pGraphicController) + m_pGraphicController->Activate(m_bVisible); if (recursive) setVisible_recursive(GetSGNode(), v); } @@ -1081,7 +1155,6 @@ CListValue* KX_GameObject::GetChildrenRecursive() /* ------- python stuff ---------------------------------------------------*/ PyMethodDef KX_GameObject::Methods[] = { - {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O}, {"applyForce", (PyCFunction) KX_GameObject::sPyApplyForce, METH_VARARGS}, {"applyTorque", (PyCFunction) KX_GameObject::sPyApplyTorque, METH_VARARGS}, {"applyRotation", (PyCFunction) KX_GameObject::sPyApplyRotation, METH_VARARGS}, @@ -1100,7 +1173,7 @@ PyMethodDef KX_GameObject::Methods[] = { {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS}, {"applyImpulse", (PyCFunction) KX_GameObject::sPyApplyImpulse, METH_VARARGS}, {"setCollisionMargin", (PyCFunction) KX_GameObject::sPySetCollisionMargin, METH_O}, - {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_O}, + {"setParent", (PyCFunction)KX_GameObject::sPySetParent,METH_VARARGS}, {"setVisible",(PyCFunction) KX_GameObject::sPySetVisible, METH_VARARGS}, {"setOcclusion",(PyCFunction) KX_GameObject::sPySetOcclusion, METH_VARARGS}, {"removeParent", (PyCFunction)KX_GameObject::sPyRemoveParent,METH_NOARGS}, @@ -1116,10 +1189,15 @@ PyMethodDef KX_GameObject::Methods[] = { KX_PYMETHODTABLE_O(KX_GameObject, getDistanceTo), KX_PYMETHODTABLE_O(KX_GameObject, getVectTo), KX_PYMETHODTABLE(KX_GameObject, sendMessage), - + + // dict style access for props + {"has_key",(PyCFunction) KX_GameObject::sPyhas_key, METH_O}, + {"get",(PyCFunction) KX_GameObject::sPyget, METH_VARARGS}, + // deprecated {"getPosition", (PyCFunction) KX_GameObject::sPyGetPosition, METH_NOARGS}, {"setPosition", (PyCFunction) KX_GameObject::sPySetPosition, METH_O}, + {"setWorldPosition", (PyCFunction) KX_GameObject::sPySetWorldPosition, METH_O}, {"getOrientation", (PyCFunction) KX_GameObject::sPyGetOrientation, METH_NOARGS}, {"setOrientation", (PyCFunction) KX_GameObject::sPySetOrientation, METH_O}, {"getState",(PyCFunction) KX_GameObject::sPyGetState, METH_NOARGS}, @@ -1147,13 +1225,14 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("state", KX_GameObject, pyattr_get_state, pyattr_set_state), KX_PYATTRIBUTE_RO_FUNCTION("meshes", KX_GameObject, pyattr_get_meshes), KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation), - KX_PYATTRIBUTE_RO_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation), + KX_PYATTRIBUTE_RW_FUNCTION("worldOrientation",KX_GameObject,pyattr_get_worldOrientation,pyattr_set_worldOrientation), KX_PYATTRIBUTE_RW_FUNCTION("localPosition", KX_GameObject, pyattr_get_localPosition, pyattr_set_localPosition), KX_PYATTRIBUTE_RW_FUNCTION("worldPosition", KX_GameObject, pyattr_get_worldPosition, pyattr_set_worldPosition), - KX_PYATTRIBUTE_RW_FUNCTION("localScaling", KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling), - KX_PYATTRIBUTE_RO_FUNCTION("worldScaling", KX_GameObject, pyattr_get_worldScaling), - - KX_PYATTRIBUTE_RO_FUNCTION("__dict__", KX_GameObject, pyattr_get_dir_dict), + KX_PYATTRIBUTE_RW_FUNCTION("localScale", KX_GameObject, pyattr_get_localScaling, pyattr_set_localScaling), + KX_PYATTRIBUTE_RO_FUNCTION("worldScale", KX_GameObject, pyattr_get_worldScaling), + KX_PYATTRIBUTE_RO_FUNCTION("children", KX_GameObject, pyattr_get_children), + KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive), + KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict), /* Experemental, dont rely on these yet */ KX_PYATTRIBUTE_RO_FUNCTION("sensors", KX_GameObject, pyattr_get_sensors), @@ -1193,8 +1272,8 @@ PyObject* KX_GameObject::PyReplaceMesh(PyObject* value) PyObject* KX_GameObject::PyEndObject() { - KX_Scene *scene = KX_GetActiveScene(); + scene->DelayedRemoveObject(this); Py_RETURN_NONE; @@ -1208,21 +1287,6 @@ PyObject* KX_GameObject::PyGetPosition() return PyObjectFrom(NodeGetWorldPosition()); } - -Py_ssize_t KX_GameObject::Map_Len(PyObject* self_v) -{ - KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); - - if (self==NULL) /* not sure what to do here */ - return 0; - - Py_ssize_t len= self->GetPropertyCount(); - if(self->m_attr_dict) - len += PyDict_Size(self->m_attr_dict); - return len; -} - - PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item) { KX_GameObject* self= static_cast<KX_GameObject*>BGE_PROXY_REF(self_v); @@ -1231,7 +1295,7 @@ PyObject *KX_GameObject::Map_GetItem(PyObject *self_v, PyObject *item) PyObject* pyconvert; if (self==NULL) { - PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); return NULL; } @@ -1265,7 +1329,7 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) PyErr_Clear(); if (self==NULL) { - PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); return -1; } @@ -1281,7 +1345,7 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) if (del==0) { if(attr_str) PyErr_Format(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key \"%s\" could not be set", attr_str); - else PyErr_SetString(PyExc_KeyError, "gameOb[key] = value: KX_GameObject, key could not be set"); + else PyErr_SetString(PyExc_KeyError, "del gameOb[key]: KX_GameObject, key could not be deleted"); return -1; } else if (self->m_attr_dict) { @@ -1292,9 +1356,9 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) int set= 0; /* as CValue */ - if(attr_str) + if(attr_str && BGE_PROXY_CHECK_TYPE(val)==0) /* dont allow GameObjects for eg to be assigned to CValue props */ { - CValue* vallie = self->ConvertPythonToValue(val); + CValue* vallie = self->ConvertPythonToValue(val, ""); /* error unused */ if(vallie) { @@ -1345,17 +1409,21 @@ int KX_GameObject::Map_SetItem(PyObject *self_v, PyObject *key, PyObject *val) return 0; /* success */ } - +/* Cant set the len otherwise it can evaluate as false */ PyMappingMethods KX_GameObject::Mapping = { - (lenfunc)KX_GameObject::Map_Len, /*inquiry mp_length */ + (lenfunc)NULL , /*inquiry mp_length */ (binaryfunc)KX_GameObject::Map_GetItem, /*binaryfunc mp_subscript */ (objobjargproc)KX_GameObject::Map_SetItem, /*objobjargproc mp_ass_subscript */ }; - PyTypeObject KX_GameObject::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_GameObject", sizeof(PyObjectPlus_Proxy), 0, @@ -1396,8 +1464,10 @@ PyObject* KX_GameObject::pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DE { KX_GameObject* self= static_cast<KX_GameObject*>(self_v); KX_GameObject* parent = self->GetParent(); - if (parent) + if (parent) { + parent->Release(); /* self->GetParent() AddRef's */ return parent->GetProxy(); + } Py_RETURN_NONE; } @@ -1415,13 +1485,13 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd MT_Scalar val = PyFloat_AsDouble(value); if (val < 0.0f) { /* also accounts for non float */ PyErr_SetString(PyExc_AttributeError, "gameOb.mass = float: KX_GameObject, expected a float zero or above"); - return 1; + return PY_SET_ATTR_FAIL; } if (spc) spc->SetMass(val); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1438,13 +1508,13 @@ int KX_GameObject::pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF MT_Scalar val = PyFloat_AsDouble(value); if (val < 0.0f) { /* also accounts for non float */ PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMin = float: KX_GameObject, expected a float zero or above"); - return 1; + return PY_SET_ATTR_FAIL; } if (spc) spc->SetLinVelocityMin(val); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_GameObject::pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1461,13 +1531,13 @@ int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF MT_Scalar val = PyFloat_AsDouble(value); if (val < 0.0f) { /* also accounts for non float */ PyErr_SetString(PyExc_AttributeError, "gameOb.linVelocityMax = float: KX_GameObject, expected a float zero or above"); - return 1; + return PY_SET_ATTR_FAIL; } if (spc) spc->SetLinVelocityMax(val); - return 0; + return PY_SET_ATTR_SUCCESS; } @@ -1483,12 +1553,12 @@ int KX_GameObject::pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *at int param = PyObject_IsTrue( value ); if (param == -1) { PyErr_SetString(PyExc_AttributeError, "gameOb.visible = bool: KX_GameObject, expected True or False"); - return 1; + return PY_SET_ATTR_FAIL; } self->SetVisible(param, false); self->UpdateBuckets(false); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1502,11 +1572,11 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D KX_GameObject* self= static_cast<KX_GameObject*>(self_v); MT_Point3 pos; if (!PyVecTo(value, pos)) - return 1; + return PY_SET_ATTR_FAIL; self->NodeSetWorldPosition(pos); self->NodeUpdateGS(0.f); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1523,11 +1593,11 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D KX_GameObject* self= static_cast<KX_GameObject*>(self_v); MT_Point3 pos; if (!PyVecTo(value, pos)) - return 1; + return PY_SET_ATTR_FAIL; self->NodeSetLocalPosition(pos); self->NodeUpdateGS(0.f); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1546,6 +1616,26 @@ PyObject* KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYAT return PyObjectFrom(self->NodeGetWorldOrientation()); } +int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + + /* if value is not a sequence PyOrientationTo makes an error */ + MT_Matrix3x3 rot; + if (!PyOrientationTo(value, rot, "gameOb.worldOrientation = sequence: KX_GameObject, ")) + return PY_SET_ATTR_FAIL; + + if (self->GetSGNode() && self->GetSGNode()->GetSGParent()) { + self->NodeSetLocalOrientation(self->GetSGNode()->GetSGParent()->GetWorldOrientation().inverse()*rot); + } + else { + self->NodeSetLocalOrientation(rot); + } + + self->NodeUpdateGS(0.f); + return PY_SET_ATTR_SUCCESS; +} + PyObject* KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self= static_cast<KX_GameObject*>(self_v); @@ -1561,12 +1651,12 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT /* if value is not a sequence PyOrientationTo makes an error */ MT_Matrix3x3 rot; - if (!PyOrientationTo(value, rot, "gameOb.orientation = sequence: KX_GameObject, ")) - return NULL; + if (!PyOrientationTo(value, rot, "gameOb.localOrientation = sequence: KX_GameObject, ")) + return PY_SET_ATTR_FAIL; self->NodeSetLocalOrientation(rot); self->NodeUpdateGS(0.f); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1589,11 +1679,11 @@ int KX_GameObject::pyattr_set_localScaling(void *self_v, const KX_PYATTRIBUTE_DE KX_GameObject* self= static_cast<KX_GameObject*>(self_v); MT_Vector3 scale; if (!PyVecTo(value, scale)) - return 1; + return PY_SET_ATTR_FAIL; self->NodeSetLocalScale(scale); self->NodeUpdateGS(0.f); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1615,12 +1705,12 @@ int KX_GameObject::pyattr_set_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF SG_Node* sg_parent= self->GetSGNode()->GetSGParent(); if (val < 0.0f) { /* also accounts for non float */ PyErr_SetString(PyExc_AttributeError, "gameOb.timeOffset = float: KX_GameObject, expected a float zero or above"); - return 1; + return PY_SET_ATTR_FAIL; } if (sg_parent && sg_parent->IsSlowParent()) static_cast<KX_SlowParentRelation *>(sg_parent->GetParentRelation())->SetTimeOffset(val); } - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_GameObject::pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1639,16 +1729,16 @@ int KX_GameObject::pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attr if (state_i == -1 && PyErr_Occurred()) { PyErr_SetString(PyExc_TypeError, "gameOb.state = int: KX_GameObject, expected an int bit field"); - return 1; + return PY_SET_ATTR_FAIL; } state |= state_i; if ((state & ((1<<30)-1)) == 0) { PyErr_SetString(PyExc_AttributeError, "gameOb.state = int: KX_GameObject, state bitfield was not between 0 and 30 (1<<0 and 1<<29)"); - return 1; + return PY_SET_ATTR_FAIL; } self->SetState(state); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -1657,10 +1747,10 @@ PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE PyObject *meshes= PyList_New(self->m_meshes.size()); int i; - for(i=0; i < self->m_meshes.size(); i++) + for(i=0; i < (int)self->m_meshes.size(); i++) { KX_MeshProxy* meshproxy = new KX_MeshProxy(self->m_meshes[i]); - PyList_SET_ITEM(meshes, i, meshproxy->GetProxy()); + PyList_SET_ITEM(meshes, i, meshproxy->NewProxy(true)); } return meshes; @@ -1669,69 +1759,40 @@ PyObject* KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE /* experemental! */ PyObject* KX_GameObject::pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast<KX_GameObject*>(self_v); - SCA_SensorList& sensors= self->GetSensors(); - PyObject* resultlist = PyList_New(sensors.size()); - - for (unsigned int index=0;index<sensors.size();index++) - PyList_SET_ITEM(resultlist, index, sensors[index]->GetProxy()); - - return resultlist; + return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_SENSORS); } PyObject* KX_GameObject::pyattr_get_controllers(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_GameObject* self= static_cast<KX_GameObject*>(self_v); - SCA_ControllerList& controllers= self->GetControllers(); - PyObject* resultlist = PyList_New(controllers.size()); - - for (unsigned int index=0;index<controllers.size();index++) - PyList_SET_ITEM(resultlist, index, controllers[index]->GetProxy()); - - return resultlist; + return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_CONTROLLERS); } PyObject* KX_GameObject::pyattr_get_actuators(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { + return KX_PythonSeq_CreatePyObject((static_cast<KX_GameObject*>(self_v))->m_proxy, KX_PYGENSEQ_OB_TYPE_ACTUATORS); +} + +PyObject* KX_GameObject::pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ KX_GameObject* self= static_cast<KX_GameObject*>(self_v); - SCA_ActuatorList& actuators= self->GetActuators(); - PyObject* resultlist = PyList_New(actuators.size()); - - for (unsigned int index=0;index<actuators.size();index++) - PyList_SET_ITEM(resultlist, index, actuators[index]->GetProxy()); - - return resultlist; + return self->GetChildren()->NewProxy(true); } -/* __dict__ only for the purpose of giving useful dir() results */ -PyObject* KX_GameObject::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +PyObject* KX_GameObject::pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self= static_cast<KX_GameObject*>(self_v); + return self->GetChildrenRecursive()->NewProxy(true); +} + +PyObject* KX_GameObject::pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self= static_cast<KX_GameObject*>(self_v); - PyObject *dict_str = PyString_FromString("__dict__"); - PyObject *dict= py_getattr_dict(self->SCA_IObject::py_getattro(dict_str), Type.tp_dict); - Py_DECREF(dict_str); - - if(dict==NULL) - return NULL; - - /* Not super fast getting as a list then making into dict keys but its only for dir() */ - PyObject *list= self->ConvertKeysToPython(); - if(list) - { - int i; - for(i=0; i<PyList_Size(list); i++) - PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None); - } - else - PyErr_Clear(); - - Py_DECREF(list); - /* Add m_attr_dict if we have it */ - if(self->m_attr_dict) - PyDict_Update(dict, self->m_attr_dict); + if(self->m_attr_dict==NULL) + self->m_attr_dict= PyDict_New(); - return dict; + Py_INCREF(self->m_attr_dict); + return self->m_attr_dict; } /* We need these because the macros have a return in them */ @@ -1772,11 +1833,38 @@ PyObject* KX_GameObject::py_getattro(PyObject *attr) return object; } +PyObject* KX_GameObject::py_getattro_dict() { + //py_getattro_dict_up(SCA_IObject); + PyObject *dict= py_getattr_dict(SCA_IObject::py_getattro_dict(), Type.tp_dict); + if(dict==NULL) + return NULL; + + /* normally just return this but KX_GameObject has some more items */ + + + /* Not super fast getting as a list then making into dict keys but its only for dir() */ + PyObject *list= ConvertKeysToPython(); + if(list) + { + int i; + for(i=0; i<PyList_Size(list); i++) + PyDict_SetItem(dict, PyList_GET_ITEM(list, i), Py_None); + } + else + PyErr_Clear(); + + Py_DECREF(list); + + /* Add m_attr_dict if we have it */ + if(m_attr_dict) + PyDict_Update(dict, m_attr_dict); + + return dict; +} + int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro method { - int ret; - - ret= py_setattro__internal(attr, value); + int ret= py_setattro__internal(attr, value); if (ret==PY_SET_ATTR_SUCCESS) { /* remove attribute in our own dict to avoid double ups */ @@ -1789,7 +1877,7 @@ int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro m if (ret==PY_SET_ATTR_COERCE_FAIL) { /* CValue attribute exists, remove CValue and add PyDict value */ - RemoveProperty(STR_String(PyString_AsString(attr))); + RemoveProperty(PyString_AsString(attr)); ret= PY_SET_ATTR_MISSING; } @@ -1814,16 +1902,18 @@ int KX_GameObject::py_setattro(PyObject *attr, PyObject *value) // py_setattro m int KX_GameObject::py_delattro(PyObject *attr) { + ShowDeprecationWarning("del ob.attr", "del ob['attr'] for user defined properties"); + char *attr_str= PyString_AsString(attr); - if (RemoveProperty(STR_String(attr_str))) // XXX - should call CValues instead but its only 2 lines here - return 0; + if (RemoveProperty(attr_str)) // XXX - should call CValues instead but its only 2 lines here + return PY_SET_ATTR_SUCCESS; if (m_attr_dict && (PyDict_DelItem(m_attr_dict, attr) == 0)) - return 0; + return PY_SET_ATTR_SUCCESS; PyErr_Format(PyExc_AttributeError, "del gameOb.myAttr: KX_GameObject, attribute \"%s\" dosnt exist", attr_str); - return 1; + return PY_SET_ATTR_MISSING; } @@ -2008,14 +2098,8 @@ PyObject* KX_GameObject::PyGetVelocity(PyObject* args) MT_Point3 point(0.0,0.0,0.0); PyObject* pypos = NULL; - if (PyArg_ParseTuple(args, "|O:getVelocity", &pypos)) - { - if (pypos) - PyVecTo(pypos, point); - } - else { + if (!PyArg_ParseTuple(args, "|O:getVelocity", &pypos) || (pypos && !PyVecTo(pypos, point))) return NULL; - } if (m_pPhysicsController1) { @@ -2075,35 +2159,49 @@ PyObject* KX_GameObject::PyGetParent() { ShowDeprecationWarning("getParent()", "the parent property"); KX_GameObject* parent = this->GetParent(); - if (parent) + if (parent) { + parent->Release(); /* self->GetParent() AddRef's */ return parent->GetProxy(); + } Py_RETURN_NONE; } -PyObject* KX_GameObject::PySetParent(PyObject* value) +PyObject* KX_GameObject::PySetParent(PyObject* args) { + KX_Scene *scene = KX_GetActiveScene(); + PyObject* pyobj; KX_GameObject *obj; - if (!ConvertPythonToGameObject(value, &obj, false, "gameOb.setParent(value): KX_GameObject")) - return NULL; + int addToCompound=1, ghost=1; - this->SetParent(KX_GetActiveScene(), obj); + if (!PyArg_ParseTuple(args,"O|ii:setParent", &pyobj, &addToCompound, &ghost)) { + return NULL; // Python sets a simple error + } + if (!ConvertPythonToGameObject(pyobj, &obj, true, "gameOb.setParent(obj): KX_GameObject")) + return NULL; + if (obj) + this->SetParent(scene, obj, addToCompound, ghost); Py_RETURN_NONE; } PyObject* KX_GameObject::PyRemoveParent() { KX_Scene *scene = KX_GetActiveScene(); + this->RemoveParent(scene); Py_RETURN_NONE; } PyObject* KX_GameObject::PyGetChildren() { + ShowDeprecationWarning("getChildren()", "the children property"); + return GetChildren()->NewProxy(true); } PyObject* KX_GameObject::PyGetChildrenRecursive() { + ShowDeprecationWarning("getChildrenRecursive()", "the childrenRecursive property"); + return GetChildrenRecursive()->NewProxy(true); } @@ -2203,23 +2301,15 @@ PyObject* KX_GameObject::PyGetOrientation() //keywords PyObject* KX_GameObject::PySetOrientation(PyObject* value) { ShowDeprecationWarning("setOrientation()", "the orientation property"); - MT_Matrix3x3 matrix; - if (PyObject_IsMT_Matrix(value, 3) && PyMatTo(value, matrix)) - { - NodeSetLocalOrientation(matrix); - NodeUpdateGS(0.f); - Py_RETURN_NONE; - } + MT_Matrix3x3 rot; + + /* if value is not a sequence PyOrientationTo makes an error */ + if (!PyOrientationTo(value, rot, "gameOb.setOrientation(sequence): KX_GameObject, ")) + return NULL; - MT_Quaternion quat; - if (PyVecTo(value, quat)) - { - matrix.setRotation(quat); - NodeSetLocalOrientation(matrix); - NodeUpdateGS(0.f); - Py_RETURN_NONE; - } - return NULL; + NodeSetLocalOrientation(rot); + NodeUpdateGS(0.f); + Py_RETURN_NONE; } PyObject* KX_GameObject::PyAlignAxisToVect(PyObject* args) @@ -2256,7 +2346,7 @@ PyObject* KX_GameObject::PyGetAxisVect(PyObject* value) PyObject* KX_GameObject::PySetPosition(PyObject* value) { - ShowDeprecationWarning("setPosition()", "the position property"); + ShowDeprecationWarning("setPosition()", "the localPosition property"); MT_Point3 pos; if (PyVecTo(value, pos)) { @@ -2270,6 +2360,7 @@ PyObject* KX_GameObject::PySetPosition(PyObject* value) PyObject* KX_GameObject::PySetWorldPosition(PyObject* value) { + ShowDeprecationWarning("setWorldPosition()", "the worldPosition property"); MT_Point3 pos; if (PyVecTo(value, pos)) { @@ -2474,6 +2565,34 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCastTo, Py_RETURN_NONE; } +/* faster then Py_BuildValue since some scripts call raycast a lot */ +static PyObject *none_tuple_3() +{ + PyObject *ret= PyTuple_New(3); + PyTuple_SET_ITEM(ret, 0, Py_None); + PyTuple_SET_ITEM(ret, 1, Py_None); + PyTuple_SET_ITEM(ret, 2, Py_None); + + Py_INCREF(Py_None); + Py_INCREF(Py_None); + Py_INCREF(Py_None); + return ret; +} +static PyObject *none_tuple_4() +{ + PyObject *ret= PyTuple_New(4); + PyTuple_SET_ITEM(ret, 0, Py_None); + PyTuple_SET_ITEM(ret, 1, Py_None); + PyTuple_SET_ITEM(ret, 2, Py_None); + PyTuple_SET_ITEM(ret, 3, Py_None); + + Py_INCREF(Py_None); + Py_INCREF(Py_None); + Py_INCREF(Py_None); + Py_INCREF(Py_None); + return ret; +} + KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, "rayCast(to,from,dist,prop,face,xray,poly): cast a ray and return 3-tuple (object,hit,normal) or 4-tuple (object,hit,normal,polygon) of contact point with object within dist that matches prop.\n" " If no hit, return (None,None,None) or (None,None,None,None).\n" @@ -2541,12 +2660,14 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, if (dist != 0.0f) { MT_Vector3 toDir = toPoint-fromPoint; if (MT_fuzzyZero(toDir.length2())) { - return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + //return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + return none_tuple_3(); } toDir.normalize(); toPoint = fromPoint + (dist) * toDir; } else if (MT_fuzzyZero((toPoint-fromPoint).length2())) { - return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + //return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + return none_tuple_3(); } PHY_IPhysicsEnvironment* pe = GetPhysicsEnvironment(); @@ -2594,9 +2715,11 @@ KX_PYMETHODDEF_DOC(KX_GameObject, rayCast, } // no hit if (poly) - return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None); + //return Py_BuildValue("OOOO", Py_None, Py_None, Py_None, Py_None); + return none_tuple_4(); else - return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + //return Py_BuildValue("OOO", Py_None, Py_None, Py_None); + return none_tuple_3(); } KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, @@ -2606,6 +2729,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, "body = Message body (string)" "to = Name of object to send the message to") { + KX_Scene *scene = KX_GetActiveScene(); char* subject; char* body = (char *)""; char* to = (char *)""; @@ -2613,12 +2737,58 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_GameObject, sendMessage, if (!PyArg_ParseTuple(args, "s|sss:sendMessage", &subject, &body, &to)) return NULL; + + scene->GetNetworkScene()->SendMessage(to, from, subject, body); + Py_RETURN_NONE; +} - KX_GetActiveScene()->GetNetworkScene()->SendMessage(to, from, subject, body); +/* dict style access */ - Py_RETURN_NONE; + +/* Matches python dict.get(key, [default]) */ +PyObject* KX_GameObject::Pyget(PyObject *args) +{ + PyObject *key; + PyObject* def = Py_None; + PyObject* ret; + + if (!PyArg_ParseTuple(args, "O|O:get", &key, &def)) + return NULL; + + + if(PyString_Check(key)) { + CValue *item = GetProperty(PyString_AsString(key)); + if (item) { + ret = item->ConvertValueToPython(); + if(ret) + return ret; + else + return item->GetProxy(); + } + } + + if (m_attr_dict && (ret=PyDict_GetItem(m_attr_dict, key))) { + Py_INCREF(ret); + return ret; + } + + Py_INCREF(def); + return def; +} + +/* Matches python dict.has_key() */ +PyObject* KX_GameObject::Pyhas_key(PyObject* value) +{ + if(PyString_Check(value) && GetProperty(PyString_AsString(value))) + Py_RETURN_TRUE; + + if (m_attr_dict && PyDict_GetItem(m_attr_dict, value)) + Py_RETURN_TRUE; + + Py_RETURN_FALSE; } + /* --------------------------------------------------------------------- * Some stuff taken from the header * --------------------------------------------------------------------- */ @@ -2641,6 +2811,7 @@ void KX_GameObject::Relink(GEN_Map<GEN_HashedPtr, void*> *map_parameter) } } + bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py_none_ok, const char *error_prefix) { if (value==NULL) { @@ -2671,12 +2842,15 @@ bool ConvertPythonToGameObject(PyObject * value, KX_GameObject **object, bool py } } - if (PyObject_TypeCheck(value, &KX_GameObject::Type)) { + if ( PyObject_TypeCheck(value, &KX_GameObject::Type) || + PyObject_TypeCheck(value, &KX_LightObject::Type) || + PyObject_TypeCheck(value, &KX_Camera::Type) ) + { *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value); /* sets the error */ if (*object==NULL) { - PyErr_Format(PyExc_RuntimeError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); + PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); return false; } diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index ec02dc17b75..dbdea97031d 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -77,6 +77,7 @@ protected: STR_String m_text; int m_layer; std::vector<RAS_MeshObject*> m_meshes; + SG_QList m_meshSlots; // head of mesh slots of this struct Object* m_pBlenderObject; struct Object* m_pBlenderGroupObject; @@ -170,7 +171,7 @@ public: /** * Sets the parent of this object to a game object */ - void SetParent(KX_Scene *scene, KX_GameObject *obj); + void SetParent(KX_Scene *scene, KX_GameObject *obj, bool addToCompound=true, bool ghost=true); /** * Removes the parent of this object to a game object @@ -192,11 +193,6 @@ public: ~KX_GameObject( ); - CValue* - AddRef() { - /* temporarily to find memleaks */ return CValue::AddRef(); - } - /** * @section Stuff which is here due to poor design. * Inherited from CValue and needs an implementation. @@ -245,7 +241,7 @@ public: /** * Inherited from CValue -- returns the name of this object. */ - STR_String + STR_String& GetName( ); @@ -254,15 +250,7 @@ public: */ void SetName( - STR_String name - ); - - /** - * Inherited from CValue -- does nothing. - */ - void - ReplicaSetName( - STR_String name + const char *name ); /** @@ -279,9 +267,7 @@ public: * data owned by this class is deep copied. Called internally */ virtual void - ProcessReplica( - KX_GameObject* replica - ); + ProcessReplica(); /** * Return the linear velocity of the game object. @@ -395,6 +381,10 @@ public: { m_pGraphicController = graphiccontroller; } + /* + * @add/remove the graphic controller to the physic system + */ + void ActivateGraphicController(bool recurse); /** * @section Coordinate system manipulation functions @@ -570,6 +560,13 @@ public: static void UpdateTransformFunc(SG_IObject* node, void* gameobj, void* scene); /** + * only used for sensor objects + */ + void SynchronizeTransform(); + + static void SynchronizeTransformFunc(SG_IObject* node, void* gameobj, void* scene); + + /** * Function to set IPO option at start of IPO */ void @@ -816,6 +813,7 @@ public: */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); // py_setattro method virtual int py_delattro(PyObject *attr); virtual PyObject* py_repr(void) @@ -860,7 +858,7 @@ public: KX_PYMETHOD_VARARGS(KX_GameObject,ApplyImpulse); KX_PYMETHOD_O(KX_GameObject,SetCollisionMargin); KX_PYMETHOD_NOARGS(KX_GameObject,GetParent); - KX_PYMETHOD_O(KX_GameObject,SetParent); + KX_PYMETHOD_VARARGS(KX_GameObject,SetParent); KX_PYMETHOD_NOARGS(KX_GameObject,RemoveParent); KX_PYMETHOD_NOARGS(KX_GameObject,GetChildren); KX_PYMETHOD_NOARGS(KX_GameObject,GetChildrenRecursive); @@ -874,6 +872,11 @@ public: KX_PYMETHOD_DOC_O(KX_GameObject,getDistanceTo); KX_PYMETHOD_DOC_O(KX_GameObject,getVectTo); KX_PYMETHOD_DOC_VARARGS(KX_GameObject, sendMessage); + + /* Dict access */ + KX_PYMETHOD_VARARGS(KX_GameObject,get); + KX_PYMETHOD_O(KX_GameObject,has_key); + /* attributes */ static PyObject* pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_parent(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); @@ -893,6 +896,7 @@ public: static PyObject* pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); @@ -903,9 +907,9 @@ public: static PyObject* pyattr_get_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_state(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_meshes(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); - - /* for dir(), python3 uses __dir__() */ - static PyObject* pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_children(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_children_recursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_attrDict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); /* Experemental! */ static PyObject* pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_IPO_SGController.cpp b/source/gameengine/Ketsji/KX_IPO_SGController.cpp index 55a7e2ade60..bd7e09d1dda 100644 --- a/source/gameengine/Ketsji/KX_IPO_SGController.cpp +++ b/source/gameengine/Ketsji/KX_IPO_SGController.cpp @@ -194,7 +194,8 @@ bool KX_IpoSGController::Update(double currentTime) else newPosition = m_ipo_start_point + newPosition; } - ob->SetLocalPosition(newPosition); + if (m_game_object) + m_game_object->NodeSetLocalPosition(newPosition); } } //modifies orientation? @@ -233,7 +234,8 @@ bool KX_IpoSGController::Update(double currentTime) rotation = m_ipo_start_orient * rotation; else rotation = rotation * m_ipo_start_orient; - ob->SetLocalOrientation(rotation); + if (m_game_object) + m_game_object->NodeSetLocalOrientation(rotation); } } else if (m_ipo_channels_active[OB_ROT_X] || m_ipo_channels_active[OB_ROT_Y] || m_ipo_channels_active[OB_ROT_Z]) { if (m_ipo_euler_initialized) { @@ -265,7 +267,8 @@ bool KX_IpoSGController::Update(double currentTime) else if (m_ipo_channels_active[OB_DROT_Z]) { roll += m_ipo_xform.GetDeltaEulerAngles()[2]; } - ob->SetLocalOrientation(MT_Vector3(yaw, pitch, roll)); + if (m_game_object) + m_game_object->NodeSetLocalOrientation(MT_Vector3(yaw, pitch, roll)); } } else if (m_ipo_start_initialized) { // only DROT, treat as Add @@ -286,7 +289,8 @@ bool KX_IpoSGController::Update(double currentTime) // dRot are always local MT_Matrix3x3 rotation(MT_Vector3(yaw, pitch, roll)); rotation = m_ipo_start_orient * rotation; - ob->SetLocalOrientation(rotation); + if (m_game_object) + m_game_object->NodeSetLocalOrientation(rotation); } } //modifies scale? @@ -322,8 +326,8 @@ bool KX_IpoSGController::Update(double currentTime) if (m_ipo_add) { newScale = m_ipo_start_scale * newScale; } - - ob->SetLocalScale(newScale); + if (m_game_object) + m_game_object->NodeSetLocalScale(newScale); } m_modified=false; @@ -342,6 +346,7 @@ SG_Controller* KX_IpoSGController::GetReplica(class SG_Node* destnode) KX_IpoSGController* iporeplica = new KX_IpoSGController(*this); // clear object that ipo acts on in the replica. iporeplica->ClearObject(); + iporeplica->SetGameObject((KX_GameObject*)destnode->GetSGClientObject()); // dirty hack, ask Gino for a better solution in the ipo implementation // hacken en zagen, in what we call datahiding, not written for replication :( diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.cpp b/source/gameengine/Ketsji/KX_IPhysicsController.cpp index a38222c5f7e..673acabd774 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.cpp +++ b/source/gameengine/Ketsji/KX_IPhysicsController.cpp @@ -35,9 +35,10 @@ #include "PHY_DynamicTypes.h" -KX_IPhysicsController::KX_IPhysicsController(bool dyna, bool compound, void* userdata) +KX_IPhysicsController::KX_IPhysicsController(bool dyna, bool sensor, bool compound, void* userdata) : m_bDyna(dyna), + m_bSensor(sensor), m_bCompound(compound), m_suspendDynamics(false), m_userdata(userdata) diff --git a/source/gameengine/Ketsji/KX_IPhysicsController.h b/source/gameengine/Ketsji/KX_IPhysicsController.h index 10b66da7b76..81c01045071 100644 --- a/source/gameengine/Ketsji/KX_IPhysicsController.h +++ b/source/gameengine/Ketsji/KX_IPhysicsController.h @@ -49,11 +49,12 @@ class KX_IPhysicsController : public SG_Controller { protected: bool m_bDyna; + bool m_bSensor; bool m_bCompound; bool m_suspendDynamics; void* m_userdata; public: - KX_IPhysicsController(bool dyna,bool compound, void* userdata); + KX_IPhysicsController(bool dyna,bool sensor,bool compound, void* userdata); virtual ~KX_IPhysicsController(); @@ -74,6 +75,7 @@ public: virtual void getOrientation(MT_Quaternion& orn)=0; virtual void setOrientation(const MT_Matrix3x3& orn)=0; + virtual void SetTransform()=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; @@ -100,10 +102,18 @@ public: m_bDyna = isDynamic; } + void SetSensor(bool isSensor) { + m_bSensor = isSensor; + } + bool IsDyna(void) { return m_bDyna; } + bool IsSensor(void) { + return m_bSensor; + } + bool IsCompound(void) { return m_bCompound; } diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index f04e3c79a8e..3ec0598ac03 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -164,14 +164,14 @@ bool KX_IpoActuator::Update(double curtime, bool frame) // result = true if animation has to be continued, false if animation stops // maybe there are events for us in the queue ! bool bNegativeEvent = false; - int numevents = 0; + bool numevents = false; bool bIpoStart = false; curtime -= KX_KetsjiEngine::GetSuspendedDelta(); if (frame) { - numevents = m_events.size(); + numevents = m_posevent || m_negevent; bNegativeEvent = IsNegativeEvent(); RemoveAllEvents(); } @@ -273,7 +273,7 @@ bool KX_IpoActuator::Update(double curtime, bool frame) { result = false; m_bNegativeEvent = false; - numevents = 0; + numevents = false; } if (!m_bIpoPlaying) { @@ -413,8 +413,13 @@ int KX_IpoActuator::string2mode(char* modename) { /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_IpoActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_IpoActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -440,9 +445,8 @@ PyParentObject KX_IpoActuator::Parents[] = { }; PyMethodDef KX_IpoActuator::Methods[] = { - {"set", (PyCFunction) KX_IpoActuator::sPySet, METH_VARARGS, (PY_METHODCHAR)Set_doc}, - // deprecated + {"set", (PyCFunction) KX_IpoActuator::sPySet, METH_VARARGS, (PY_METHODCHAR)Set_doc}, {"setProperty", (PyCFunction) KX_IpoActuator::sPySetProperty, METH_VARARGS, (PY_METHODCHAR)SetProperty_doc}, {"setStart", (PyCFunction) KX_IpoActuator::sPySetStart, METH_VARARGS, (PY_METHODCHAR)SetStart_doc}, {"getStart", (PyCFunction) KX_IpoActuator::sPyGetStart, METH_NOARGS, (PY_METHODCHAR)GetStart_doc}, @@ -460,11 +464,11 @@ PyMethodDef KX_IpoActuator::Methods[] = { }; PyAttributeDef KX_IpoActuator::Attributes[] = { - KX_PYATTRIBUTE_FLOAT_RW("startFrame", 0, 300000, KX_IpoActuator, m_startframe), - KX_PYATTRIBUTE_FLOAT_RW("endFrame", 0, 300000, KX_IpoActuator, m_endframe), + KX_PYATTRIBUTE_FLOAT_RW("frameStart", 0, 300000, KX_IpoActuator, m_startframe), + KX_PYATTRIBUTE_FLOAT_RW("frameEnd", 0, 300000, KX_IpoActuator, m_endframe), KX_PYATTRIBUTE_STRING_RW("propName", 0, 64, false, KX_IpoActuator, m_propname), KX_PYATTRIBUTE_STRING_RW("framePropName", 0, 64, false, KX_IpoActuator, m_framepropname), - KX_PYATTRIBUTE_INT_RW("type", KX_ACT_IPO_NODEF+1, KX_ACT_IPO_MAX-1, true, KX_IpoActuator, m_type), + KX_PYATTRIBUTE_INT_RW("mode", KX_ACT_IPO_NODEF+1, KX_ACT_IPO_MAX-1, true, KX_IpoActuator, m_type), KX_PYATTRIBUTE_BOOL_RW("useIpoAsForce", KX_IpoActuator, m_ipo_as_force), KX_PYATTRIBUTE_BOOL_RW("useIpoAdd", KX_IpoActuator, m_ipo_add), KX_PYATTRIBUTE_BOOL_RW("useIpoLocal", KX_IpoActuator, m_ipo_local), @@ -477,6 +481,10 @@ PyObject* KX_IpoActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); } +PyObject* KX_IpoActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_IpoActuator::py_setattro(PyObject *attr, PyObject *value) // py_setattro method { py_setattro_up(SCA_IActuator); @@ -492,7 +500,7 @@ const char KX_IpoActuator::Set_doc[] = "\tSet the properties of the actuator.\n"; PyObject* KX_IpoActuator::PySet(PyObject* args) { - ShowDeprecationWarning("set()", "a number properties"); + ShowDeprecationWarning("set()", "a range properties"); /* sets modes PLAY, PINGPONG, FLIPPER, LOOPSTOP, LOOPEND */ /* arg 1 = mode string, arg 2 = startframe, arg3 = stopframe, */ @@ -554,7 +562,7 @@ const char KX_IpoActuator::SetStart_doc[] = "\tSet the frame from which the ipo starts playing.\n"; PyObject* KX_IpoActuator::PySetStart(PyObject* args) { - ShowDeprecationWarning("setStart()", "the startFrame property"); + ShowDeprecationWarning("setStart()", "the frameStart property"); float startArg; if(!PyArg_ParseTuple(args, "f:setStart", &startArg)) { @@ -570,7 +578,7 @@ const char KX_IpoActuator::GetStart_doc[] = "getStart()\n" "\tReturns the frame from which the ipo starts playing.\n"; PyObject* KX_IpoActuator::PyGetStart() { - ShowDeprecationWarning("getStart()", "the startFrame property"); + ShowDeprecationWarning("getStart()", "the frameStart property"); return PyFloat_FromDouble(m_startframe); } @@ -580,7 +588,7 @@ const char KX_IpoActuator::SetEnd_doc[] = "\t - frame: last frame to use (int)\n" "\tSet the frame at which the ipo stops playing.\n"; PyObject* KX_IpoActuator::PySetEnd(PyObject* args) { - ShowDeprecationWarning("setEnd()", "the endFrame property"); + ShowDeprecationWarning("setEnd()", "the frameEnd property"); float endArg; if(!PyArg_ParseTuple(args, "f:setEnd", &endArg)) { return NULL; @@ -595,7 +603,7 @@ const char KX_IpoActuator::GetEnd_doc[] = "getEnd()\n" "\tReturns the frame at which the ipo stops playing.\n"; PyObject* KX_IpoActuator::PyGetEnd() { - ShowDeprecationWarning("getEnd()", "the endFrame property"); + ShowDeprecationWarning("getEnd()", "the frameEnd property"); return PyFloat_FromDouble(m_endframe); } @@ -661,7 +669,7 @@ const char KX_IpoActuator::SetType_doc[] = "\t - mode: Play, PingPong, Flipper, LoopStop, LoopEnd or FromProp (string)\n" "\tSet the operation mode of the actuator.\n"; PyObject* KX_IpoActuator::PySetType(PyObject* args) { - ShowDeprecationWarning("setType()", "the type property"); + ShowDeprecationWarning("setType()", "the mode property"); int typeArg; if (!PyArg_ParseTuple(args, "i:setType", &typeArg)) { @@ -680,7 +688,7 @@ const char KX_IpoActuator::GetType_doc[] = "getType()\n" "\tReturns the operation mode of the actuator.\n"; PyObject* KX_IpoActuator::PyGetType() { - ShowDeprecationWarning("getType()", "the type property"); + ShowDeprecationWarning("getType()", "the mode property"); return PyInt_FromLong(m_type); } diff --git a/source/gameengine/Ketsji/KX_IpoActuator.h b/source/gameengine/Ketsji/KX_IpoActuator.h index 184ad5512de..9ea597def1e 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.h +++ b/source/gameengine/Ketsji/KX_IpoActuator.h @@ -128,8 +128,6 @@ public: virtual CValue* GetReplica() { KX_IpoActuator* replica = new KX_IpoActuator(*this);//m_float,GetName()); replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; }; @@ -142,6 +140,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); //KX_PYMETHOD_DOC diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 83a2fa8a448..b30b79e7f23 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -77,6 +77,8 @@ #include "RAS_FramingManager.h" #include "stdio.h" +#include "DNA_world_types.h" +#include "DNA_scene_types.h" // If define: little test for Nzc: guarded drawing. If the canvas is // not valid, skip rendering this frame. @@ -97,6 +99,8 @@ const char KX_KetsjiEngine::m_profileLabels[tc_numCategories][15] = { }; double KX_KetsjiEngine::m_ticrate = DEFAULT_LOGIC_TIC_RATE; +int KX_KetsjiEngine::m_maxLogicFrame = 5; +int KX_KetsjiEngine::m_maxPhysicsFrame = 5; double KX_KetsjiEngine::m_anim_framerate = 25.0; double KX_KetsjiEngine::m_suspendedtime = 0.0; double KX_KetsjiEngine::m_suspendeddelta = 0.0; @@ -145,8 +149,6 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_stereo(false), m_curreye(0), - m_usedome(false), - m_logger(NULL), // Set up timing info display variables @@ -164,7 +166,9 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_overrideFrameColor(false), m_overrideFrameColorR(0.0), m_overrideFrameColorG(0.0), - m_overrideFrameColorB(0.0) + m_overrideFrameColorB(0.0), + + m_usedome(false) { // Initialize the time logger m_logger = new KX_TimeCategoryLogger (25); @@ -261,9 +265,9 @@ void KX_KetsjiEngine::SetSceneConverter(KX_ISceneConverter* sceneconverter) m_sceneconverter = sceneconverter; } -void KX_KetsjiEngine::InitDome(float size, short res, short mode, short angle, float resbuf, struct Text* text) +void KX_KetsjiEngine::InitDome(short res, short mode, short angle, float resbuf, short tilt, struct Text* text) { - m_dome = new KX_Dome(m_canvas, m_rasterizer, m_rendertools,this, size, res, mode, angle, resbuf, text); + m_dome = new KX_Dome(m_canvas, m_rasterizer, m_rendertools,this, res, mode, angle, resbuf, tilt, text); m_usedome = true; } @@ -271,7 +275,6 @@ void KX_KetsjiEngine::RenderDome() { GLuint viewport[4]={0}; glGetIntegerv(GL_VIEWPORT,(GLint *)viewport); -// unsigned int m_viewport[4] = {viewport[0], viewport[1], viewport[2], viewport[3]}; m_dome->SetViewPort(viewport); @@ -295,11 +298,6 @@ void KX_KetsjiEngine::RenderDome() return; KX_SceneList::iterator sceneit; - for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); sceneit++) - { - // do this only once per scene - (*sceneit)->UpdateMeshTransformations(); - } int n_renders=m_dome->GetNumberRenders();// usually 4 or 6 for (int i=0;i<n_renders;i++){ @@ -353,7 +351,6 @@ void KX_KetsjiEngine::RenderDome() m_dome->BindImages(i); } -// m_dome->Dome_PostRender(scene, cam, stereomode); m_canvas->EndFrame();//XXX do we really need that? m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight()); @@ -381,7 +378,8 @@ void KX_KetsjiEngine::RenderDome() m_dome->Draw(); - //run 2dfilters + // run the 2dfilters and motion blur once for all the scenes + PostRenderFrame(); EndFrame(); } @@ -398,7 +396,20 @@ void KX_KetsjiEngine::StartEngine(bool clearIpo) m_firstframe = true; m_bInitialized = true; - m_ticrate = DEFAULT_LOGIC_TIC_RATE; + // there is always one scene enabled at startup + World* world = m_scenes[0]->GetBlenderScene()->world; + if (world) + { + m_ticrate = world->ticrate; + m_maxLogicFrame = world->maxlogicstep; + m_maxPhysicsFrame = world->maxphystep; + } + else + { + m_ticrate = DEFAULT_LOGIC_TIC_RATE; + m_maxLogicFrame = 5; + m_maxPhysicsFrame = 5; + } if (m_game2ipo) { @@ -511,7 +522,8 @@ void KX_KetsjiEngine::EndFrame() bool KX_KetsjiEngine::NextFrame() { - + double timestep = 1.0/m_ticrate; + double framestep = timestep; // static hidden::Clock sClock; m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true); @@ -520,7 +532,7 @@ m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(),true); //sClock.reset(); if (m_bFixedTime) - m_clockTime += 1./m_ticrate; + m_clockTime += timestep; else { @@ -548,24 +560,29 @@ else // PIL_sleep_ms(1); KX_SceneList::iterator sceneit; - int frameOut = 5; - if (frames>frameOut) + if (frames>m_maxPhysicsFrame) { // printf("framedOut: %d\n",frames); - m_frameTime+=(frames-frameOut)*(1.0/m_ticrate); - frames = frameOut; + m_frameTime+=(frames-m_maxPhysicsFrame)*timestep; + frames = m_maxPhysicsFrame; } bool doRender = frames>0; + if (frames > m_maxLogicFrame) + { + framestep = (frames*timestep)/m_maxLogicFrame; + frames = m_maxLogicFrame; + } + while (frames) { - m_frameTime += 1.0/m_ticrate; + m_frameTime += framestep; for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit) // for each scene, call the proceed functions @@ -644,7 +661,7 @@ else // Perform physics calculations on the scene. This can involve // many iterations of the physics solver. - scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,1.0/m_ticrate);//m_deltatimerealDeltaTime); + scene->GetPhysicsEnvironment()->proceedDeltaTime(m_frameTime,timestep,framestep);//m_deltatimerealDeltaTime); m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2_UPDATE); @@ -717,7 +734,7 @@ else // Perform physics calculations on the scene. This can involve // many iterations of the physics solver. m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); - scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,0.f); + scene->GetPhysicsEnvironment()->proceedDeltaTime(m_clockTime,timestep,timestep); // Update scenegraph after physics step. This maps physics calculations // into node positions. m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); @@ -817,8 +834,8 @@ void KX_KetsjiEngine::Render() // pass the scene's worldsettings to the rasterizer SetWorldSettings(scene->GetWorldInfo()); - // do this only once per scene - scene->UpdateMeshTransformations(); + // this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes + //scene->UpdateMeshTransformations(); // shadow buffers RenderShadowBuffers(scene); @@ -906,9 +923,6 @@ void KX_KetsjiEngine::Render() } } // if(m_rasterizer->Stereo()) - // run the 2dfilters and motion blur once for all the scenes - PostRenderFrame(); - EndFrame(); } @@ -1000,7 +1014,7 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) wi->getAmbientColorBlue() ); - if (m_drawingmode == RAS_IRasterizer::KX_TEXTURED) + if (m_drawingmode >= RAS_IRasterizer::KX_SOLID) { if (wi->hasMist()) { @@ -1012,10 +1026,6 @@ void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) wi->getMistColorBlue() ); } - else - { - m_rasterizer->DisableFog(); - } } } } @@ -1097,7 +1107,7 @@ void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect area = userviewport; } - else if ( m_overrideCam || (scene->GetName() != m_overrideSceneName) || m_overrideCamUseOrtho ) { + else if ( !m_overrideCam || (scene->GetName() != m_overrideSceneName) || m_overrideCamUseOrtho ) { RAS_FramingManager::ComputeViewport( scene->GetFramingType(), m_canvas->GetDisplayArea(), @@ -1117,16 +1127,13 @@ void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) { - CListValue *objectlist = scene->GetObjectList(); + CListValue *lightlist = scene->GetLightList(); int i, drawmode; m_rendertools->SetAuxilaryClientInfo(scene); - for(i=0; i<objectlist->GetCount(); i++) { - KX_GameObject *gameobj = (KX_GameObject*)objectlist->GetValue(i); - - if(!gameobj->IsLight()) - continue; + for(i=0; i<lightlist->GetCount(); i++) { + KX_GameObject *gameobj = (KX_GameObject*)lightlist->GetValue(i); KX_LightObject *light = (KX_LightObject*)gameobj; @@ -1135,7 +1142,7 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) if(m_drawingmode == RAS_IRasterizer::KX_TEXTURED && light->HasShadowBuffer()) { /* make temporary camera */ RAS_CameraData camdata = RAS_CameraData(); - KX_Camera *cam = new KX_Camera(scene, scene->m_callbacks, camdata, false); + KX_Camera *cam = new KX_Camera(scene, scene->m_callbacks, camdata, true, true); cam->SetName("__shadow__cam__"); MT_Transform camtrans; @@ -1167,13 +1174,11 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) { bool override_camera; RAS_Rect viewport, area; - float left, right, bottom, top, nearfrust, farfrust, focallength; - const float ortho = 100.0; + float nearfrust, farfrust, focallength; // KX_Camera* cam = scene->GetActiveCamera(); if (!cam) return; - GetSceneViewport(scene, cam, area, viewport); // store the computed viewport in the scene @@ -1191,19 +1196,24 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) override_camera = override_camera && (cam->GetName() == "__default__cam__"); if (override_camera && m_overrideCamUseOrtho) { - MT_CmMatrix4x4 projmat = m_overrideCamProjMat; - m_rasterizer->SetProjectionMatrix(projmat); + m_rasterizer->SetProjectionMatrix(m_overrideCamProjMat); + if (!cam->hasValidProjectionMatrix()) { + // needed to get frustrum planes for culling + MT_Matrix4x4 projmat; + projmat.setValue(m_overrideCamProjMat.getPointer()); + cam->SetProjectionMatrix(projmat); + } } else if (cam->hasValidProjectionMatrix() && !cam->GetViewport() ) { m_rasterizer->SetProjectionMatrix(cam->GetProjectionMatrix()); } else { RAS_FrameFrustum frustum; - float lens = cam->GetLens(); bool orthographic = !cam->GetCameraData()->m_perspective; nearfrust = cam->GetCameraNear(); farfrust = cam->GetCameraFar(); focallength = cam->GetFocalLength(); + MT_Matrix4x4 projmat; if(override_camera) { nearfrust = m_overrideCamNear; @@ -1211,50 +1221,58 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) } if (orthographic) { - lens *= ortho; - nearfrust = (nearfrust + 1.0)*ortho; - farfrust *= ortho; - } - - RAS_FramingManager::ComputeFrustum( - scene->GetFramingType(), - area, - viewport, - lens, - nearfrust, - farfrust, - frustum - ); - left = frustum.x1 * m_cameraZoom; - right = frustum.x2 * m_cameraZoom; - bottom = frustum.y1 * m_cameraZoom; - top = frustum.y2 * m_cameraZoom; - nearfrust = frustum.camnear; - farfrust = frustum.camfar; + RAS_FramingManager::ComputeOrtho( + scene->GetFramingType(), + area, + viewport, + cam->GetScale(), + nearfrust, + farfrust, + frustum + ); + if (!cam->GetViewport()) { + frustum.x1 *= m_cameraZoom; + frustum.x2 *= m_cameraZoom; + frustum.y1 *= m_cameraZoom; + frustum.y2 *= m_cameraZoom; + } + projmat = m_rasterizer->GetOrthoMatrix( + frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar); - MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( - left, right, bottom, top, nearfrust, farfrust, focallength); + } else { + RAS_FramingManager::ComputeFrustum( + scene->GetFramingType(), + area, + viewport, + cam->GetLens(), + nearfrust, + farfrust, + frustum + ); + if (!cam->GetViewport()) { + frustum.x1 *= m_cameraZoom; + frustum.x2 *= m_cameraZoom; + frustum.y1 *= m_cameraZoom; + frustum.y2 *= m_cameraZoom; + } + projmat = m_rasterizer->GetFrustumMatrix( + frustum.x1, frustum.x2, frustum.y1, frustum.y2, frustum.camnear, frustum.camfar, focallength); + } cam->SetProjectionMatrix(projmat); // Otherwise the projection matrix for each eye will be the same... - if (m_rasterizer->Stereo()) + if (!orthographic && m_rasterizer->Stereo()) cam->InvalidateProjectionMatrix(); } MT_Transform camtrans(cam->GetWorldToCamera()); - if (!cam->GetCameraData()->m_perspective) - camtrans.getOrigin()[2] *= ortho; MT_Matrix4x4 viewmat(camtrans); - m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldPosition(), - cam->GetCameraLocation(), cam->GetCameraOrientation()); + m_rasterizer->SetViewMatrix(viewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective); cam->SetModelviewMatrix(viewmat); - //redundant, already done in Render() - //scene->UpdateMeshTransformations(); - // The following actually reschedules all vertices to be // redrawn. There is a cache between the actual rescheduling // and this call though. Visibility is imparted when this call @@ -1274,6 +1292,9 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) scene->GetPhysicsEnvironment()->debugDrawWorld(); m_rasterizer->FlushDebugLines(); + + //it's running once for every scene (i.e. overlay scenes have it running twice). That's not the ideal. + PostRenderFrame(); } void KX_KetsjiEngine::PostRenderFrame() @@ -1401,7 +1422,7 @@ void KX_KetsjiEngine::RenderDebugProperties() m_canvas->GetWidth(), m_canvas->GetHeight()); double time = m_logger->GetAverage((KX_TimeCategory)j); - debugtxt.Format("%2.2f %%", time/tottime * 100.f); + debugtxt.Format("%.3fms (%2.2f %%)", time*1000.f, time/tottime * 100.f); m_rendertools->RenderText2D(RAS_IRenderTools::RAS_TEXT_PADDED, debugtxt.Ptr(), xcoord + 60 ,ycoord, @@ -1719,6 +1740,26 @@ void KX_KetsjiEngine::SetTicRate(double ticrate) m_ticrate = ticrate; } +int KX_KetsjiEngine::GetMaxLogicFrame() +{ + return m_maxLogicFrame; +} + +void KX_KetsjiEngine::SetMaxLogicFrame(int frame) +{ + m_maxLogicFrame = frame; +} + +int KX_KetsjiEngine::GetMaxPhysicsFrame() +{ + return m_maxPhysicsFrame; +} + +void KX_KetsjiEngine::SetMaxPhysicsFrame(int frame) +{ + m_maxPhysicsFrame = frame; +} + double KX_KetsjiEngine::GetAnimFrameRate() { return m_anim_framerate; @@ -1729,6 +1770,11 @@ double KX_KetsjiEngine::GetClockTime(void) const return m_clockTime; } +double KX_KetsjiEngine::GetRealTime(void) const +{ + return m_kxsystem->GetTimeInSeconds(); +} + void KX_KetsjiEngine::SetAnimFrameRate(double framerate) { m_anim_framerate = framerate; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index a8ccd6100d7..6fa379e551a 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -103,6 +103,8 @@ private: double m_previousClockTime;//previous clock time double m_remainingTime; + static int m_maxLogicFrame; /* maximum number of consecutive logic frame */ + static int m_maxPhysicsFrame; /* maximum number of consecutive physics frame */ static double m_ticrate; static double m_anim_framerate; /* for animation playback only - ipo and action */ @@ -210,7 +212,7 @@ public: RAS_IRenderTools* GetRenderTools(){return m_rendertools;}; /// Dome functions - void InitDome(float size, short res, short mode, short angle, float resbuf, struct Text* text); + void InitDome(short res, short mode, short angle, float resbuf, short tilt, struct Text* text); void EndDome(); void RenderDome(); bool m_usedome; @@ -269,6 +271,7 @@ public: */ double GetClockTime(void) const; + double GetRealTime(void) const; /** * Returns the difference between the local time of the scene (when it * was running and not suspended) and the "curtime" @@ -283,6 +286,22 @@ public: * Sets the number of logic updates per second. */ static void SetTicRate(double ticrate); + /** + * Gets the maximum number of logic frame before render frame + */ + static int GetMaxLogicFrame(); + /** + * Sets the maximum number of logic frame before render frame + */ + static void SetMaxLogicFrame(int frame); + /** + * Gets the maximum number of physics frame before render frame + */ + static int GetMaxPhysicsFrame(); + /** + * Sets the maximum number of physics frame before render frame + */ + static void SetMaxPhysicsFrame(int frame); /** * Gets the framerate for playing animations. (actions and ipos) diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 713838c88ec..fe575384a35 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -82,10 +82,7 @@ CValue* KX_LightObject::GetReplica() KX_LightObject* replica = new KX_LightObject(*this); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); - - ProcessReplica(replica); + replica->ProcessReplica(); replica->m_lightobj.m_worldmatrix = replica->GetOpenGLMatrixPtr(); m_rendertools->AddLight(&replica->m_lightobj); @@ -105,8 +102,11 @@ void KX_LightObject::Update() { GPULamp *lamp; - if((lamp = GetGPULamp())) { + if((lamp = GetGPULamp()) != NULL && GetSGNode()) { float obmat[4][4]; + // lights don't get their openGL matrix updated, do it now + if (GetSGNode()->IsDirty()) + GetOpenGLMatrix(); double *dobmat = GetOpenGLMatrixPtr()->getPointer(); for(int i=0; i<4; i++) @@ -114,6 +114,8 @@ void KX_LightObject::Update() obmat[i][j] = (float)*dobmat; GPU_lamp_update(lamp, m_lightobj.m_layer, obmat); + GPU_lamp_update_colors(lamp, m_lightobj.m_red, m_lightobj.m_green, + m_lightobj.m_blue, m_lightobj.m_energy); } } @@ -163,8 +165,7 @@ void KX_LightObject::BindShadowBuffer(RAS_IRasterizer *ras, KX_Camera *cam, MT_T /* setup rasterizer transformations */ ras->SetProjectionMatrix(projectionmat); - ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldPosition(), - cam->GetCameraLocation(), cam->GetCameraOrientation()); + ras->SetViewMatrix(modelviewmat, cam->NodeGetWorldOrientation(), cam->NodeGetWorldPosition(), cam->GetCameraData()->m_perspective); } void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) @@ -173,160 +174,23 @@ void KX_LightObject::UnbindShadowBuffer(RAS_IRasterizer *ras) GPU_lamp_shadow_buffer_unbind(lamp); } -PyObject* KX_LightObject::py_getattro(PyObject *attr) -{ - char *attr_str= PyString_AsString(attr); - - if (!strcmp(attr_str, "layer")) - return PyInt_FromLong(m_lightobj.m_layer); - - if (!strcmp(attr_str, "energy")) - return PyFloat_FromDouble(m_lightobj.m_energy); - - if (!strcmp(attr_str, "distance")) - return PyFloat_FromDouble(m_lightobj.m_distance); - - if (!strcmp(attr_str, "colour") || !strcmp(attr_str, "color")) - return Py_BuildValue("[fff]", m_lightobj.m_red, m_lightobj.m_green, m_lightobj.m_blue); - - if (!strcmp(attr_str, "lin_attenuation")) - return PyFloat_FromDouble(m_lightobj.m_att1); - - if (!strcmp(attr_str, "quad_attenuation")) - return PyFloat_FromDouble(m_lightobj.m_att2); - - if (!strcmp(attr_str, "spotsize")) - return PyFloat_FromDouble(m_lightobj.m_spotsize); - - if (!strcmp(attr_str, "spotblend")) - return PyFloat_FromDouble(m_lightobj.m_spotblend); - - if (!strcmp(attr_str, "SPOT")) - return PyInt_FromLong(RAS_LightObject::LIGHT_SPOT); - - if (!strcmp(attr_str, "SUN")) - return PyInt_FromLong(RAS_LightObject::LIGHT_SUN); - - if (!strcmp(attr_str, "NORMAL")) - return PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL); - - if (!strcmp(attr_str, "type")) - return PyInt_FromLong(m_lightobj.m_type); - - py_getattro_up(KX_GameObject); -} - +/* ------------------------------------------------------------------------- */ +/* Python Integration Hooks */ +/* ------------------------------------------------------------------------- */ -int KX_LightObject::py_setattro(PyObject *attr, PyObject *pyvalue) -{ - char *attr_str= PyString_AsString(attr); - - if (PyInt_Check(pyvalue)) - { - int value = PyInt_AsLong(pyvalue); - if (!strcmp(attr_str, "layer")) - { - m_lightobj.m_layer = value; - return PY_SET_ATTR_SUCCESS; - } - - if (!strcmp(attr_str, "type")) - { - if (value >= RAS_LightObject::LIGHT_SPOT && value <= RAS_LightObject::LIGHT_NORMAL) - m_lightobj.m_type = (RAS_LightObject::LightType) value; - return PY_SET_ATTR_SUCCESS; - } - } - - if (PyFloat_Check(pyvalue) || PyInt_Check(pyvalue)) - { - float value = PyFloat_AsDouble(pyvalue); - if (!strcmp(attr_str, "energy")) - { - m_lightobj.m_energy = value; - return PY_SET_ATTR_SUCCESS; - } - - if (!strcmp(attr_str, "distance")) - { - m_lightobj.m_distance = value; - return PY_SET_ATTR_SUCCESS; - } - - if (!strcmp(attr_str, "lin_attenuation")) - { - m_lightobj.m_att1 = value; - return PY_SET_ATTR_SUCCESS; - } - - if (!strcmp(attr_str, "quad_attenuation")) - { - m_lightobj.m_att2 = value; - return PY_SET_ATTR_SUCCESS; - } - - if (!strcmp(attr_str, "spotsize")) - { - m_lightobj.m_spotsize = value; - return PY_SET_ATTR_SUCCESS; - } - - if (!strcmp(attr_str, "spotblend")) - { - m_lightobj.m_spotblend = value; - return PY_SET_ATTR_SUCCESS; - } - } - - if (PySequence_Check(pyvalue)) - { - if (!strcmp(attr_str, "colour") || !strcmp(attr_str, "color")) - { - MT_Vector3 color; - if (PyVecTo(pyvalue, color)) - { - m_lightobj.m_red = color[0]; - m_lightobj.m_green = color[1]; - m_lightobj.m_blue = color[2]; - return PY_SET_ATTR_SUCCESS; - } - return PY_SET_ATTR_FAIL; - } - } - - if (!strcmp(attr_str, "SPOT") || !strcmp(attr_str, "SUN") || !strcmp(attr_str, "NORMAL")) - { - PyErr_Format(PyExc_RuntimeError, "Attribute %s is read only.", attr_str); - return PY_SET_ATTR_FAIL; - } - - return KX_GameObject::py_setattro(attr, pyvalue); +PyObject* KX_LightObject::py_getattro_dict() { + py_getattro_dict_up(KX_GameObject); } -PyMethodDef KX_LightObject::Methods[] = { - {NULL,NULL} //Sentinel -}; - -PyAttributeDef KX_LightObject::Attributes[] = { - KX_PYATTRIBUTE_DUMMY("layer"), - KX_PYATTRIBUTE_DUMMY("energy"), - KX_PYATTRIBUTE_DUMMY("distance"), - KX_PYATTRIBUTE_DUMMY("colour"), - KX_PYATTRIBUTE_DUMMY("color"), - KX_PYATTRIBUTE_DUMMY("lin_attenuation"), - KX_PYATTRIBUTE_DUMMY("quad_attenuation"), - KX_PYATTRIBUTE_DUMMY("spotsize"), - KX_PYATTRIBUTE_DUMMY("spotblend"), - KX_PYATTRIBUTE_DUMMY("SPOT"), - KX_PYATTRIBUTE_DUMMY("SUN"), - KX_PYATTRIBUTE_DUMMY("NORMAL"), - KX_PYATTRIBUTE_DUMMY("type"), - { NULL } //Sentinel -}; PyTypeObject KX_LightObject::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_LightObject", sizeof(PyObjectPlus_Proxy), 0, @@ -352,3 +216,103 @@ PyParentObject KX_LightObject::Parents[] = { &CValue::Type, NULL }; + +PyMethodDef KX_LightObject::Methods[] = { + {NULL,NULL} //Sentinel +}; + +PyAttributeDef KX_LightObject::Attributes[] = { + KX_PYATTRIBUTE_INT_RW("layer", 1, 20, true, KX_LightObject, m_lightobj.m_layer), + KX_PYATTRIBUTE_FLOAT_RW("energy", 0, 10, KX_LightObject, m_lightobj.m_energy), + KX_PYATTRIBUTE_FLOAT_RW("distance", 0.01, 5000, KX_LightObject, m_lightobj.m_distance), + KX_PYATTRIBUTE_RW_FUNCTION("color", KX_LightObject, pyattr_get_color, pyattr_set_color), + KX_PYATTRIBUTE_RW_FUNCTION("colour", KX_LightObject, pyattr_get_color, pyattr_set_color), + KX_PYATTRIBUTE_FLOAT_RW("lin_attenuation", 0, 1, KX_LightObject, m_lightobj.m_att1), + KX_PYATTRIBUTE_FLOAT_RW("quad_attenuation", 0, 1, KX_LightObject, m_lightobj.m_att2), + KX_PYATTRIBUTE_FLOAT_RW("spotsize", 1, 180, KX_LightObject, m_lightobj.m_spotsize), + KX_PYATTRIBUTE_FLOAT_RW("spotblend", 0, 1, KX_LightObject, m_lightobj.m_spotblend), + KX_PYATTRIBUTE_RO_FUNCTION("SPOT", KX_LightObject, pyattr_get_typeconst), + KX_PYATTRIBUTE_RO_FUNCTION("SUN", KX_LightObject, pyattr_get_typeconst), + KX_PYATTRIBUTE_RO_FUNCTION("NORMAL", KX_LightObject, pyattr_get_typeconst), + KX_PYATTRIBUTE_RW_FUNCTION("type", KX_LightObject, pyattr_get_type, pyattr_set_type), + { NULL } //Sentinel +}; + +PyObject* KX_LightObject::pyattr_get_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_LightObject* self = static_cast<KX_LightObject*>(self_v); + return Py_BuildValue("[fff]", self->m_lightobj.m_red, self->m_lightobj.m_green, self->m_lightobj.m_blue); +} + +int KX_LightObject::pyattr_set_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_LightObject* self = static_cast<KX_LightObject*>(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->m_lightobj.m_red = color[0]; + self->m_lightobj.m_green = color[1]; + self->m_lightobj.m_blue = color[2]; + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +PyObject* KX_LightObject::pyattr_get_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + PyObject* retvalue; + + const char* type = attrdef->m_name; + + if(strcmp(type, "SPOT")) { + retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_SPOT); + } else if (strcmp(type, "SUN")) { + retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_SUN); + } else if (strcmp(type, "NORMAL")) { + retvalue = PyInt_FromLong(RAS_LightObject::LIGHT_NORMAL); + } + + return retvalue; +} + +PyObject* KX_LightObject::pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_LightObject* self = static_cast<KX_LightObject*>(self_v); + return PyInt_FromLong(self->m_lightobj.m_type); +} + +int KX_LightObject::pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value) +{ + KX_LightObject* self = static_cast<KX_LightObject*>(self_v); + int val = PyInt_AsLong(value); + if((val==-1 && PyErr_Occurred()) || val<0 || val>2) { + PyErr_SetString(PyExc_ValueError, "light.type= val: KX_LightObject, expected an int between 0 and 2"); + return PY_SET_ATTR_FAIL; + } + + switch(val) { + case 0: + self->m_lightobj.m_type = self->m_lightobj.LIGHT_SPOT; + break; + case 1: + self->m_lightobj.m_type = self->m_lightobj.LIGHT_SUN; + break; + case 2: + self->m_lightobj.m_type = self->m_lightobj.LIGHT_NORMAL; + break; + } + + return PY_SET_ATTR_SUCCESS; +} + + +PyObject* KX_LightObject::py_getattro(PyObject *attr) +{ + py_getattro_up(KX_GameObject); +} + +int KX_LightObject::py_setattro(PyObject *attr, PyObject *value) +{ + py_setattro_up(KX_GameObject); +} diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 4559954c8d7..35f25515e3b 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -63,8 +63,16 @@ public: void Update(); virtual PyObject* py_getattro(PyObject *attr); /* lens, near, far, projection_matrix */ + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *pyvalue); + /* attributes */ + static PyObject* pyattr_get_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_color(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value); + static PyObject* pyattr_get_typeconst(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_type(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject* value); + virtual bool IsLight(void) { return true; } }; diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 6be1da55ff8..11effa1ca98 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -46,8 +46,13 @@ #include "PyObjectPlus.h" PyTypeObject KX_MeshProxy::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_MeshProxy", sizeof(PyObjectPlus_Proxy), 0, @@ -66,7 +71,6 @@ PyTypeObject KX_MeshProxy::Type = { PyParentObject KX_MeshProxy::Parents[] = { &KX_MeshProxy::Type, - &SCA_IObject::Type, &CValue::Type, &PyObjectPlus::Type, NULL @@ -105,17 +109,21 @@ void KX_MeshProxy::SetMeshModified(bool v) PyObject* KX_MeshProxy::py_getattro(PyObject *attr) { - py_getattro_up(SCA_IObject); + py_getattro_up(CValue); +} + +PyObject* KX_MeshProxy::py_getattro_dict() { + py_getattro_dict_up(CValue); } int KX_MeshProxy::py_setattro(PyObject *attr, PyObject* value) { - py_setattro_up(SCA_IObject); + py_setattro_up(CValue); } KX_MeshProxy::KX_MeshProxy(RAS_MeshObject* mesh) - : SCA_IObject(&Type), m_meshobj(mesh) + : CValue(&Type), m_meshobj(mesh) { } @@ -131,10 +139,9 @@ CValue* KX_MeshProxy::CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValu const STR_String & KX_MeshProxy::GetText() {return m_meshobj->GetName();}; double KX_MeshProxy::GetNumber() { return -1;} -STR_String KX_MeshProxy::GetName() { return m_meshobj->GetName();} -void KX_MeshProxy::SetName(STR_String name) { }; +STR_String& KX_MeshProxy::GetName() { return m_meshobj->GetName();} +void KX_MeshProxy::SetName(const char *name) { }; CValue* KX_MeshProxy::GetReplica() { return NULL;} -void KX_MeshProxy::ReplicaSetName(STR_String name) {}; // stuff for python integration @@ -213,24 +220,20 @@ PyObject* KX_MeshProxy::PyGetVertexArrayLength(PyObject* args, PyObject* kwds) PyObject* KX_MeshProxy::PyGetVertex(PyObject* args, PyObject* kwds) { - int vertexindex= 1; - int matindex= 1; - PyObject* vertexob = NULL; + int vertexindex; + int matindex; - if (PyArg_ParseTuple(args,"ii:getVertex",&matindex,&vertexindex)) - { - RAS_TexVert* vertex = m_meshobj->GetVertex(matindex,vertexindex); - if (vertex) - { - vertexob = (new KX_VertexProxy(this, vertex))->NewProxy(true); - } - } - else { + if (!PyArg_ParseTuple(args,"ii:getVertex",&matindex,&vertexindex)) + return NULL; + + RAS_TexVert* vertex = m_meshobj->GetVertex(matindex,vertexindex); + + if(vertex==NULL) { + PyErr_SetString(PyExc_ValueError, "mesh.getVertex(mat_idx, vert_idx): KX_MeshProxy, could not get a vertex at the given indicies"); return NULL; } - - return vertexob; - + + return (new KX_VertexProxy(this, vertex))->NewProxy(true); } PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds) @@ -262,8 +265,12 @@ PyObject* KX_MeshProxy::PyGetPolygon(PyObject* args, PyObject* kwds) KX_PYMETHODDEF_DOC(KX_MeshProxy, reinstancePhysicsMesh, "Reinstance the physics mesh.") { +#if 0 //this needs to be reviewed, it is dependend on Sumo/Solid. Who is using this ? - Py_RETURN_NONE;//(KX_ReInstanceShapeFromMesh(m_meshobj)) ? Py_RETURN_TRUE : Py_RETURN_FALSE; + if(KX_ReInstanceShapeFromMesh(m_meshobj)) + Py_RETURN_TRUE; +#endif + Py_RETURN_FALSE; } PyObject* KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -341,7 +348,7 @@ bool ConvertPythonToMesh(PyObject * value, RAS_MeshObject **object, bool py_none /* sets the error */ if (*object==NULL) { - PyErr_Format(PyExc_RuntimeError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); + PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); return false; } diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index aeecefc09e6..bfdd4be4118 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -34,7 +34,7 @@ /* utility conversion function */ bool ConvertPythonToMesh(PyObject * value, class RAS_MeshObject **object, bool py_none_ok, const char *error_prefix); -class KX_MeshProxy : public SCA_IObject +class KX_MeshProxy : public CValue { Py_Header; @@ -51,13 +51,13 @@ public: virtual const STR_String & GetText(); virtual double GetNumber(); virtual RAS_MeshObject* GetMesh() { return m_meshobj; } - virtual STR_String GetName(); - virtual void SetName(STR_String name); // Set the name of the value - virtual void ReplicaSetName(STR_String name); + virtual STR_String& GetName(); + virtual void SetName(const char *name); // Set the name of the value virtual CValue* GetReplica(); // stuff for python integration virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); KX_PYMETHOD(KX_MeshProxy,GetNumMaterials); // Deprecated diff --git a/source/gameengine/Ketsji/KX_MotionState.cpp b/source/gameengine/Ketsji/KX_MotionState.cpp index b4d58dccfdf..60455d33312 100644 --- a/source/gameengine/Ketsji/KX_MotionState.cpp +++ b/source/gameengine/Ketsji/KX_MotionState.cpp @@ -73,6 +73,11 @@ void KX_MotionState::getWorldOrientation(float* ori) mat.getValue(ori); } +void KX_MotionState::setWorldOrientation(const float* ori) +{ + m_node->SetLocalOrientation(ori); +} + void KX_MotionState::setWorldPosition(float posX,float posY,float posZ) { m_node->SetLocalPosition(MT_Point3(posX,posY,posZ)); diff --git a/source/gameengine/Ketsji/KX_MotionState.h b/source/gameengine/Ketsji/KX_MotionState.h index 7ba3ca2f85c..0e43e88fbeb 100644 --- a/source/gameengine/Ketsji/KX_MotionState.h +++ b/source/gameengine/Ketsji/KX_MotionState.h @@ -45,6 +45,7 @@ public: virtual void setWorldPosition(float posX,float posY,float posZ); virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal); virtual void getWorldOrientation(float* ori); + virtual void setWorldOrientation(const float* ori); virtual void calculateWorldTransformations(); }; diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index 87b5c81392d..fde10a493db 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -86,7 +86,7 @@ void KX_MouseFocusSensor::Init() m_hitNormal.setValue(0,0,1); } -bool KX_MouseFocusSensor::Evaluate(CValue* event) +bool KX_MouseFocusSensor::Evaluate() { bool result = false; bool obHasFocus = false; @@ -119,7 +119,7 @@ bool KX_MouseFocusSensor::Evaluate(CValue* event) * mode is never used, because the converter never makes this * sensor for a mouse-key event. It is here for * completeness. */ - result = SCA_MouseSensor::Evaluate(event); + result = SCA_MouseSensor::Evaluate(); m_positive_event = (m_val!=0); } @@ -197,13 +197,15 @@ bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam) * division by 0.0...*/ RAS_Rect area, viewport; + short m_y_inv = m_kxengine->GetCanvas()->GetHeight()-m_y; + m_kxengine->GetSceneViewport(m_kxscene, cam, area, viewport); /* Check if the mouse is in the viewport */ if (( m_x < viewport.m_x2 && // less then right m_x > viewport.m_x1 && // more then then left - m_y < viewport.m_y2 && // below top - m_y > viewport.m_y1) == 0) // above bottom + m_y_inv < viewport.m_y2 && // below top + m_y_inv > viewport.m_y1) == 0) // above bottom { return false; } @@ -217,6 +219,10 @@ bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam) MT_Vector4 frompoint; MT_Vector4 topoint; + /* m_y_inv - inverting for a bounds check is only part of it, now make relative to view bounds */ + m_y_inv = (viewport.m_y2 - m_y_inv) + viewport.m_y1; + + /* There's some strangeness I don't fully get here... These values * _should_ be wrong! - see from point Z values */ @@ -229,19 +235,18 @@ bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam) * behind of the near and far clip planes. */ frompoint.setValue( (2 * (m_x-x_lb) / width) - 1.0, - 1.0 - (2 * (m_y - y_lb) / height), + 1.0 - (2 * (m_y_inv - y_lb) / height), + /*cam->GetCameraData()->m_perspective ? 0.0:cdata->m_clipstart,*/ /* real clipstart is scaled in ortho for some reason, zero is ok */ 0.0, /* nearclip, see above comments */ 1.0 ); topoint.setValue( (2 * (m_x-x_lb) / width) - 1.0, - 1.0 - (2 * (m_y-y_lb) / height), - 1.0, /* farclip, see above comments */ + 1.0 - (2 * (m_y_inv-y_lb) / height), + cam->GetCameraData()->m_perspective ? 1.0:cam->GetCameraData()->m_clipend, /* farclip, see above comments */ 1.0 ); /* camera to world */ MT_Transform wcs_camcs_tranform = cam->GetWorldToCamera(); - if (!cam->GetCameraData()->m_perspective) - wcs_camcs_tranform.getOrigin()[2] *= 100.0; MT_Transform cams_wcs_transform; cams_wcs_transform.invert(wcs_camcs_tranform); @@ -335,8 +340,13 @@ const MT_Vector3& KX_MouseFocusSensor::HitNormal() const /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_MouseFocusSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_MouseFocusSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -387,6 +397,10 @@ PyObject* KX_MouseFocusSensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_MouseSensor); } +PyObject* KX_MouseFocusSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_MouseSensor); +} + const char KX_MouseFocusSensor::GetHitObject_doc[] = "getHitObject()\n" diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.h b/source/gameengine/Ketsji/KX_MouseFocusSensor.h index 8de1f88c5c3..29d674eb305 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.h +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.h @@ -63,13 +63,13 @@ class KX_MouseFocusSensor : public SCA_MouseSensor virtual CValue* GetReplica() { CValue* replica = new KX_MouseFocusSensor(*this); // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; }; /** * @attention Overrides default evaluate. */ - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual void Init(); virtual bool IsPositiveTrigger() { @@ -89,7 +89,8 @@ class KX_MouseFocusSensor : public SCA_MouseSensor /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ - virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRayTarget); KX_PYMETHOD_DOC_NOARGS(KX_MouseFocusSensor,GetRaySource); diff --git a/source/gameengine/Ketsji/KX_NearSensor.cpp b/source/gameengine/Ketsji/KX_NearSensor.cpp index 0489b7090e9..44842b7f5b3 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.cpp +++ b/source/gameengine/Ketsji/KX_NearSensor.cpp @@ -36,6 +36,7 @@ #include "KX_Scene.h" // needed to create a replica #include "PHY_IPhysicsEnvironment.h" #include "PHY_IPhysicsController.h" +#include "PHY_IMotionState.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -62,7 +63,7 @@ KX_NearSensor::KX_NearSensor(SCA_EventManager* eventmgr, { gameobj->getClientInfo()->m_sensors.remove(this); - m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::NEAR); + m_client_info = new KX_ClientObjectInfo(gameobj, KX_ClientObjectInfo::SENSOR); m_client_info->m_sensors.push_back(this); //DT_ShapeHandle shape = (DT_ShapeHandle) vshape; @@ -81,81 +82,50 @@ void KX_NearSensor::SynchronizeTransform() // not linked to the parent object, must synchronize it. if (m_physCtrl) { + PHY_IMotionState* motionState = m_physCtrl->GetMotionState(); KX_GameObject* parent = ((KX_GameObject*)GetParent()); - MT_Vector3 pos = parent->NodeGetWorldPosition(); - MT_Quaternion orn = parent->NodeGetWorldOrientation().getRotation(); - m_physCtrl->setPosition(pos.x(),pos.y(),pos.z()); - m_physCtrl->setOrientation(orn.x(),orn.y(),orn.z(),orn.w()); - m_physCtrl->calcXform(); + const MT_Point3& pos = parent->NodeGetWorldPosition(); + float ori[12]; + parent->NodeGetWorldOrientation().getValue(ori); + motionState->setWorldPosition(pos[0], pos[1], pos[2]); + motionState->setWorldOrientation(ori); + m_physCtrl->WriteMotionStateToDynamics(true); } } -void KX_NearSensor::RegisterSumo(KX_TouchEventManager *touchman) -{ - if (m_physCtrl) - { - touchman->GetPhysicsEnvironment()->addSensor(m_physCtrl); - } -} - -void KX_NearSensor::UnregisterSumo(KX_TouchEventManager* touchman) +CValue* KX_NearSensor::GetReplica() { - if (m_physCtrl) - { - touchman->GetPhysicsEnvironment()->removeSensor(m_physCtrl); - } + KX_NearSensor* replica = new KX_NearSensor(*this); + replica->ProcessReplica(); + return replica; } -CValue* KX_NearSensor::GetReplica() +void KX_NearSensor::ProcessReplica() { - KX_NearSensor* replica = new KX_NearSensor(*this); - replica->m_colliders = new CListValue(); - replica->Init(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); + KX_TouchSensor::ProcessReplica(); - replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::NEAR); + m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::SENSOR); - if (replica->m_physCtrl) + if (m_physCtrl) { - replica->m_physCtrl = replica->m_physCtrl->GetReplica(); - if (replica->m_physCtrl) + m_physCtrl = m_physCtrl->GetReplica(); + if (m_physCtrl) { //static_cast<KX_TouchEventManager*>(m_eventmgr)->GetPhysicsEnvironment()->addSensor(replica->m_physCtrl); - replica->m_physCtrl->SetMargin(m_Margin); - replica->m_physCtrl->setNewClientInfo(replica->m_client_info); + m_physCtrl->SetMargin(m_Margin); + m_physCtrl->setNewClientInfo(m_client_info); } } - //Wrong: the parent object could be a child, this code works only if it is a root parent. - //Anyway, at this stage, the parent object is already synchronized, nothing to do. - //bool parentUpdated = false; - //((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL, parentUpdated); - replica->SynchronizeTransform(); - - return replica; } - - 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); - - -/* KX_ClientObjectInfo *client_info = gameobj->getClientInfo(); - client_info->m_gameobject = gameobj; - client_info->m_auxilary_info = NULL; - - client_info->m_sensors.push_back(this); - SCA_ISensor::ReParent(parent); -*/ - //Not needed, was done in GetReplica() already - //bool parentUpdated = false; - //((KX_GameObject*)GetParent())->GetSGNode()->ComputeWorldTransforms(NULL,parentUpdated); - //SynchronizeTransform(); - SCA_ISensor::ReParent(parent); + //Synchronize here with the actual parent. + SynchronizeTransform(); } @@ -177,7 +147,7 @@ KX_NearSensor::~KX_NearSensor() } -bool KX_NearSensor::Evaluate(CValue* event) +bool KX_NearSensor::Evaluate() { bool result = false; // KX_GameObject* parent = static_cast<KX_GameObject*>(GetParent()); @@ -286,8 +256,13 @@ bool KX_NearSensor::NewHandleCollision(void* obj1,void* obj2,const PHY_CollData /* ------------------------------------------------------------------------- */ PyTypeObject KX_NearSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_NearSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -334,6 +309,10 @@ PyObject* KX_NearSensor::py_getattro(PyObject *attr) py_getattro_up(KX_TouchSensor); } +PyObject* KX_NearSensor::py_getattro_dict() { + py_getattro_dict_up(KX_TouchSensor); +} + int KX_NearSensor::py_setattro(PyObject*attr, PyObject* value) { py_setattro_up(KX_TouchSensor); diff --git a/source/gameengine/Ketsji/KX_NearSensor.h b/source/gameengine/Ketsji/KX_NearSensor.h index 26c5feb4e67..63099e181a0 100644 --- a/source/gameengine/Ketsji/KX_NearSensor.h +++ b/source/gameengine/Ketsji/KX_NearSensor.h @@ -70,19 +70,21 @@ public: virtual ~KX_NearSensor(); virtual void SynchronizeTransform(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual void ProcessReplica(); + virtual bool Evaluate(); virtual void ReParent(SCA_IObject* parent); virtual bool NewHandleCollision(void* obj1,void* obj2, 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 bool BroadPhaseSensorFilterCollision(void*obj1,void*obj2) { return false; }; + virtual sensortype GetSensorType() { return ST_NEAR; } /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); //No methods diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 861c5757971..eaae04d406d 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -31,6 +31,7 @@ #include "KX_ObjectActuator.h" #include "KX_GameObject.h" +#include "KX_PyMath.h" // For PyVecTo - should this include be put in PyObjectPlus? #include "KX_IPhysicsController.h" #ifdef HAVE_CONFIG_H @@ -44,6 +45,7 @@ KX_ObjectActuator:: KX_ObjectActuator( SCA_IObject* gameobj, + KX_GameObject* refobj, const MT_Vector3& force, const MT_Vector3& torque, const MT_Vector3& dloc, @@ -68,6 +70,7 @@ KX_ObjectActuator( m_previous_error(0.0,0.0,0.0), m_error_accumulator(0.0,0.0,0.0), m_bitLocalFlag (flag), + m_reference(refobj), m_active_combined_velocity (false), m_linear_damping_active(false), m_angular_damping_active(false) @@ -76,10 +79,20 @@ KX_ObjectActuator( { // in servo motion, the force is local if the target velocity is local m_bitLocalFlag.Force = m_bitLocalFlag.LinearVelocity; + + m_pid = m_torque; } + if (m_reference) + m_reference->RegisterActuator(this); UpdateFuzzyFlags(); } +KX_ObjectActuator::~KX_ObjectActuator() +{ + if (m_reference) + m_reference->UnregisterActuator(this); +} + bool KX_ObjectActuator::Update() { @@ -128,11 +141,23 @@ bool KX_ObjectActuator::Update() if (mass < MT_EPSILON) return false; MT_Vector3 v = parent->GetLinearVelocity(m_bitLocalFlag.LinearVelocity); + if (m_reference) + { + const MT_Point3& mypos = parent->NodeGetWorldPosition(); + const MT_Point3& refpos = m_reference->NodeGetWorldPosition(); + MT_Point3 relpos; + relpos = (mypos-refpos); + MT_Vector3 vel= m_reference->GetVelocity(relpos); + if (m_bitLocalFlag.LinearVelocity) + // must convert in local space + vel = parent->NodeGetWorldOrientation().transposed()*vel; + v -= vel; + } MT_Vector3 e = m_linear_velocity - v; MT_Vector3 dv = e - m_previous_error; MT_Vector3 I = m_error_accumulator + e; - m_force = m_torque.x()*e+m_torque.y()*I+m_torque.z()*dv; + m_force = m_pid.x()*e+m_pid.y()*I+m_pid.z()*dv; // to automatically adapt the PID coefficient to mass; m_force *= mass; if (m_bitLocalFlag.Torque) @@ -253,13 +278,37 @@ CValue* KX_ObjectActuator::GetReplica() KX_ObjectActuator* replica = new KX_ObjectActuator(*this);//m_float,GetName()); replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); - return replica; } +void KX_ObjectActuator::ProcessReplica() +{ + SCA_IActuator::ProcessReplica(); + if (m_reference) + m_reference->RegisterActuator(this); +} +bool KX_ObjectActuator::UnlinkObject(SCA_IObject* clientobj) +{ + if (clientobj == (SCA_IObject*)m_reference) + { + // this object is being deleted, we cannot continue to use it as reference. + m_reference = NULL; + return true; + } + return false; +} + +void KX_ObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) +{ + void **h_obj = (*obj_map)[m_reference]; + if (h_obj) { + if (m_reference) + m_reference->UnregisterActuator(this); + m_reference = (KX_GameObject*)(*h_obj); + m_reference->RegisterActuator(this); + } +} /* some 'standard' utilities... */ bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type) @@ -277,8 +326,13 @@ bool KX_ObjectActuator::isValid(KX_ObjectActuator::KX_OBJECT_ACT_VEC_TYPE type) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_ObjectActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_ObjectActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -304,6 +358,7 @@ PyParentObject KX_ObjectActuator::Parents[] = { }; PyMethodDef KX_ObjectActuator::Methods[] = { + // Deprecated -----> {"getForce", (PyCFunction) KX_ObjectActuator::sPyGetForce, METH_NOARGS}, {"setForce", (PyCFunction) KX_ObjectActuator::sPySetForce, METH_VARARGS}, {"getTorque", (PyCFunction) KX_ObjectActuator::sPyGetTorque, METH_NOARGS}, @@ -327,18 +382,188 @@ PyMethodDef KX_ObjectActuator::Methods[] = { {"setPID", (PyCFunction) KX_ObjectActuator::sPyGetPID, METH_NOARGS}, {"getPID", (PyCFunction) KX_ObjectActuator::sPySetPID, METH_VARARGS}, - + // <----- Deprecated {NULL,NULL} //Sentinel }; PyAttributeDef KX_ObjectActuator::Attributes[] = { + KX_PYATTRIBUTE_VECTOR_RW_CHECK("force", -1000, 1000, false, KX_ObjectActuator, m_force, PyUpdateFuzzyFlags), + KX_PYATTRIBUTE_BOOL_RW("useLocalForce", KX_ObjectActuator, m_bitLocalFlag.Force), + KX_PYATTRIBUTE_VECTOR_RW_CHECK("torque", -1000, 1000, false, KX_ObjectActuator, m_torque, PyUpdateFuzzyFlags), + KX_PYATTRIBUTE_BOOL_RW("useLocalTorque", KX_ObjectActuator, m_bitLocalFlag.Torque), + KX_PYATTRIBUTE_VECTOR_RW_CHECK("dLoc", -1000, 1000, false, KX_ObjectActuator, m_dloc, PyUpdateFuzzyFlags), + KX_PYATTRIBUTE_BOOL_RW("useLocalDLoc", KX_ObjectActuator, m_bitLocalFlag.DLoc), + KX_PYATTRIBUTE_VECTOR_RW_CHECK("dRot", -1000, 1000, false, KX_ObjectActuator, m_drot, PyUpdateFuzzyFlags), + KX_PYATTRIBUTE_BOOL_RW("useLocalDRot", KX_ObjectActuator, m_bitLocalFlag.DRot), + KX_PYATTRIBUTE_VECTOR_RW_CHECK("linV", -1000, 1000, false, KX_ObjectActuator, m_linear_velocity, PyUpdateFuzzyFlags), + KX_PYATTRIBUTE_BOOL_RW("useLocalLinV", KX_ObjectActuator, m_bitLocalFlag.LinearVelocity), + KX_PYATTRIBUTE_VECTOR_RW_CHECK("angV", -1000, 1000, false, KX_ObjectActuator, m_angular_velocity, PyUpdateFuzzyFlags), + KX_PYATTRIBUTE_BOOL_RW("useLocalAngV", KX_ObjectActuator, m_bitLocalFlag.AngularVelocity), + KX_PYATTRIBUTE_SHORT_RW("damping", 0, 1000, false, KX_ObjectActuator, m_damping), + KX_PYATTRIBUTE_RW_FUNCTION("forceLimitX", KX_ObjectActuator, pyattr_get_forceLimitX, pyattr_set_forceLimitX), + KX_PYATTRIBUTE_RW_FUNCTION("forceLimitY", KX_ObjectActuator, pyattr_get_forceLimitY, pyattr_set_forceLimitY), + KX_PYATTRIBUTE_RW_FUNCTION("forceLimitZ", KX_ObjectActuator, pyattr_get_forceLimitZ, pyattr_set_forceLimitZ), + KX_PYATTRIBUTE_VECTOR_RW_CHECK("pid", -100, 200, true, KX_ObjectActuator, m_pid, PyCheckPid), + KX_PYATTRIBUTE_RW_FUNCTION("reference", KX_ObjectActuator,pyattr_get_reference,pyattr_set_reference), { NULL } //Sentinel }; PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); -}; +} + + +PyObject* KX_ObjectActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + +int KX_ObjectActuator::py_setattro(PyObject *attr, PyObject *value) +{ + py_setattro_up(SCA_IActuator); +} + +/* Attribute get/set functions */ + +PyObject* KX_ObjectActuator::pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v); + PyObject *retVal = PyList_New(3); + + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[0])); + PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.Torque)); + + return retVal; +} + +int KX_ObjectActuator::pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v); + + PyObject* seq = PySequence_Fast(value, ""); + if (seq && PySequence_Fast_GET_SIZE(seq) == 3) + { + self->m_drot[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); + self->m_dloc[0] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); + self->m_bitLocalFlag.Torque = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); + + if (!PyErr_Occurred()) + { + Py_DECREF(seq); + return PY_SET_ATTR_SUCCESS; + } + } + + Py_XDECREF(seq); + + PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool"); + return PY_SET_ATTR_FAIL; +} + +PyObject* KX_ObjectActuator::pyattr_get_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v); + PyObject *retVal = PyList_New(3); + + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[1])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[1])); + PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.DLoc)); + + return retVal; +} + +int KX_ObjectActuator::pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v); + + PyObject* seq = PySequence_Fast(value, ""); + if (seq && PySequence_Fast_GET_SIZE(seq) == 3) + { + self->m_drot[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); + self->m_dloc[1] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); + self->m_bitLocalFlag.DLoc = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); + + if (!PyErr_Occurred()) + { + Py_DECREF(seq); + return PY_SET_ATTR_SUCCESS; + } + } + + Py_XDECREF(seq); + + PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool"); + return PY_SET_ATTR_FAIL; +} + +PyObject* KX_ObjectActuator::pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v); + PyObject *retVal = PyList_New(3); + + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(self->m_drot[2])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(self->m_dloc[2])); + PyList_SET_ITEM(retVal, 2, PyBool_FromLong(self->m_bitLocalFlag.DRot)); + + return retVal; +} + +int KX_ObjectActuator::pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_ObjectActuator* self = reinterpret_cast<KX_ObjectActuator*>(self_v); + + PyObject* seq = PySequence_Fast(value, ""); + if (seq && PySequence_Fast_GET_SIZE(seq) == 3) + { + self->m_drot[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)); + self->m_dloc[2] = PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)); + self->m_bitLocalFlag.DRot = (PyInt_AsLong(PySequence_Fast_GET_ITEM(value, 2)) != 0); + + if (!PyErr_Occurred()) + { + Py_DECREF(seq); + return PY_SET_ATTR_SUCCESS; + } + } + + Py_XDECREF(seq); + + PyErr_SetString(PyExc_ValueError, "expected a sequence of 2 floats and a bool"); + return PY_SET_ATTR_FAIL; +} + +PyObject* KX_ObjectActuator::pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self); + if (!actuator->m_reference) + Py_RETURN_NONE; + + return actuator->m_reference->GetProxy(); +} + +int KX_ObjectActuator::pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_ObjectActuator* actuator = static_cast<KX_ObjectActuator*>(self); + KX_GameObject *refOb; + + if (!ConvertPythonToGameObject(value, &refOb, true, "actu.reference = value: KX_ObjectActuator")) + return PY_SET_ATTR_FAIL; + + if (actuator->m_reference) + actuator->m_reference->UnregisterActuator(actuator); + + if(refOb==NULL) { + actuator->m_reference= NULL; + } + else { + actuator->m_reference = refOb; + actuator->m_reference->RegisterActuator(actuator); + } + + return PY_SET_ATTR_SUCCESS; +} + /* 1. set ------------------------------------------------------------------ */ /* Removed! */ @@ -346,18 +571,20 @@ PyObject* KX_ObjectActuator::py_getattro(PyObject *attr) { /* 2. getForce */ PyObject* KX_ObjectActuator::PyGetForce() { + ShowDeprecationWarning("getForce()", "the force and the useLocalForce properties"); PyObject *retVal = PyList_New(4); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_force[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_force[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_force[2])); - PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force)); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_force[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_force[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_force[2])); + PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Force)); return retVal; } /* 3. setForce */ PyObject* KX_ObjectActuator::PySetForce(PyObject* args) { + ShowDeprecationWarning("setForce()", "the force and the useLocalForce properties"); float vecArg[3]; int bToggle = 0; if (!PyArg_ParseTuple(args, "fffi:setForce", &vecArg[0], &vecArg[1], @@ -373,18 +600,20 @@ PyObject* KX_ObjectActuator::PySetForce(PyObject* args) /* 4. getTorque */ PyObject* KX_ObjectActuator::PyGetTorque() { + ShowDeprecationWarning("getTorque()", "the torque and the useLocalTorque properties"); PyObject *retVal = PyList_New(4); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_torque[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_torque[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_torque[2])); - PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque)); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_torque[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_torque[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_torque[2])); + PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.Torque)); return retVal; } /* 5. setTorque */ PyObject* KX_ObjectActuator::PySetTorque(PyObject* args) { + ShowDeprecationWarning("setTorque()", "the torque and the useLocalTorque properties"); float vecArg[3]; int bToggle = 0; if (!PyArg_ParseTuple(args, "fffi:setTorque", &vecArg[0], &vecArg[1], @@ -400,18 +629,20 @@ PyObject* KX_ObjectActuator::PySetTorque(PyObject* args) /* 6. getDLoc */ PyObject* KX_ObjectActuator::PyGetDLoc() { + ShowDeprecationWarning("getDLoc()", "the dLoc and the useLocalDLoc properties"); PyObject *retVal = PyList_New(4); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_dloc[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_dloc[2])); - PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc)); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_dloc[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_dloc[2])); + PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DLoc)); return retVal; } /* 7. setDLoc */ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* args) { + ShowDeprecationWarning("setDLoc()", "the dLoc and the useLocalDLoc properties"); float vecArg[3]; int bToggle = 0; if(!PyArg_ParseTuple(args, "fffi:setDLoc", &vecArg[0], &vecArg[1], @@ -427,18 +658,20 @@ PyObject* KX_ObjectActuator::PySetDLoc(PyObject* args) /* 8. getDRot */ PyObject* KX_ObjectActuator::PyGetDRot() { + ShowDeprecationWarning("getDRot()", "the dRot and the useLocalDRot properties"); PyObject *retVal = PyList_New(4); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_drot[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_drot[2])); - PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot)); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_drot[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_drot[2])); + PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.DRot)); return retVal; } /* 9. setDRot */ PyObject* KX_ObjectActuator::PySetDRot(PyObject* args) { + ShowDeprecationWarning("setDRot()", "the dRot and the useLocalDRot properties"); float vecArg[3]; int bToggle = 0; if (!PyArg_ParseTuple(args, "fffi:setDRot", &vecArg[0], &vecArg[1], @@ -453,18 +686,20 @@ PyObject* KX_ObjectActuator::PySetDRot(PyObject* args) /* 10. getLinearVelocity */ PyObject* KX_ObjectActuator::PyGetLinearVelocity() { + ShowDeprecationWarning("getLinearVelocity()", "the linV and the useLocalLinV properties"); PyObject *retVal = PyList_New(4); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2])); - PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity)); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_linear_velocity[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_linear_velocity[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_linear_velocity[2])); + PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.LinearVelocity)); return retVal; } /* 11. setLinearVelocity */ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* args) { + ShowDeprecationWarning("setLinearVelocity()", "the linV and the useLocalLinV properties"); float vecArg[3]; int bToggle = 0; if (!PyArg_ParseTuple(args, "fffi:setLinearVelocity", &vecArg[0], &vecArg[1], @@ -480,17 +715,19 @@ PyObject* KX_ObjectActuator::PySetLinearVelocity(PyObject* args) { /* 12. getAngularVelocity */ PyObject* KX_ObjectActuator::PyGetAngularVelocity() { + ShowDeprecationWarning("getAngularVelocity()", "the angV and the useLocalAngV properties"); PyObject *retVal = PyList_New(4); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2])); - PyList_SetItem(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity)); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_angular_velocity[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_angular_velocity[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_angular_velocity[2])); + PyList_SET_ITEM(retVal, 3, BoolToPyArg(m_bitLocalFlag.AngularVelocity)); return retVal; } /* 13. setAngularVelocity */ PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* args) { + ShowDeprecationWarning("setAngularVelocity()", "the angV and the useLocalAngV properties"); float vecArg[3]; int bToggle = 0; if (!PyArg_ParseTuple(args, "fffi:setAngularVelocity", &vecArg[0], &vecArg[1], @@ -505,6 +742,7 @@ PyObject* KX_ObjectActuator::PySetAngularVelocity(PyObject* args) { /* 13. setDamping */ PyObject* KX_ObjectActuator::PySetDamping(PyObject* args) { + ShowDeprecationWarning("setDamping()", "the damping property"); int damping = 0; if (!PyArg_ParseTuple(args, "i:setDamping", &damping) || damping < 0 || damping > 1000) { return NULL; @@ -515,22 +753,25 @@ PyObject* KX_ObjectActuator::PySetDamping(PyObject* args) { /* 13. getVelocityDamping */ PyObject* KX_ObjectActuator::PyGetDamping() { + ShowDeprecationWarning("getDamping()", "the damping property"); return Py_BuildValue("i",m_damping); } /* 6. getForceLimitX */ PyObject* KX_ObjectActuator::PyGetForceLimitX() { + ShowDeprecationWarning("getForceLimitX()", "the forceLimitX property"); PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[0])); - PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque)); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[0])); + PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.Torque)); return retVal; } /* 7. setForceLimitX */ PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* args) { + ShowDeprecationWarning("setForceLimitX()", "the forceLimitX property"); float vecArg[2]; int bToggle = 0; if(!PyArg_ParseTuple(args, "ffi:setForceLimitX", &vecArg[0], &vecArg[1], &bToggle)) { @@ -545,17 +786,19 @@ PyObject* KX_ObjectActuator::PySetForceLimitX(PyObject* args) /* 6. getForceLimitY */ PyObject* KX_ObjectActuator::PyGetForceLimitY() { + ShowDeprecationWarning("getForceLimitY()", "the forceLimitY property"); PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[1])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[1])); - PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc)); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[1])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[1])); + PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DLoc)); return retVal; } /* 7. setForceLimitY */ PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* args) { + ShowDeprecationWarning("setForceLimitY()", "the forceLimitY property"); float vecArg[2]; int bToggle = 0; if(!PyArg_ParseTuple(args, "ffi:setForceLimitY", &vecArg[0], &vecArg[1], &bToggle)) { @@ -570,17 +813,19 @@ PyObject* KX_ObjectActuator::PySetForceLimitY(PyObject* args) /* 6. getForceLimitZ */ PyObject* KX_ObjectActuator::PyGetForceLimitZ() { + ShowDeprecationWarning("getForceLimitZ()", "the forceLimitZ property"); PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_drot[2])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_dloc[2])); - PyList_SetItem(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot)); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_drot[2])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_dloc[2])); + PyList_SET_ITEM(retVal, 2, BoolToPyArg(m_bitLocalFlag.DRot)); return retVal; } /* 7. setForceLimitZ */ PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* args) { + ShowDeprecationWarning("setForceLimitZ()", "the forceLimitZ property"); float vecArg[2]; int bToggle = 0; if(!PyArg_ParseTuple(args, "ffi:setForceLimitZ", &vecArg[0], &vecArg[1], &bToggle)) { @@ -595,22 +840,24 @@ PyObject* KX_ObjectActuator::PySetForceLimitZ(PyObject* args) /* 4. getPID */ PyObject* KX_ObjectActuator::PyGetPID() { + ShowDeprecationWarning("getPID()", "the pid property"); PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_torque[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_torque[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_torque[2])); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_pid[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_pid[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_pid[2])); return retVal; } /* 5. setPID */ PyObject* KX_ObjectActuator::PySetPID(PyObject* args) { + ShowDeprecationWarning("setPID()", "the pid property"); float vecArg[3]; if (!PyArg_ParseTuple(args, "fff:setPID", &vecArg[0], &vecArg[1], &vecArg[2])) { return NULL; } - m_torque.setValue(vecArg); + m_pid.setValue(vecArg); Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index a812942a0ae..f9bd2a0c748 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -35,8 +35,10 @@ #include "SCA_IActuator.h" #include "MT_Vector3.h" +class KX_GameObject; + // -// Bitfield that stores the flags for each CValue derived class +// Stores the flags for each CValue derived class // struct KX_LocalFlags { KX_LocalFlags() : @@ -55,20 +57,20 @@ struct KX_LocalFlags { { } - unsigned short Force : 1; - unsigned short Torque : 1; - unsigned short DRot : 1; - unsigned short DLoc : 1; - unsigned short LinearVelocity : 1; - unsigned short AngularVelocity : 1; - unsigned short AddOrSetLinV : 1; - unsigned short ServoControl : 1; - unsigned short ZeroForce : 1; - unsigned short ZeroTorque : 1; - unsigned short ZeroDRot : 1; - unsigned short ZeroDLoc : 1; - unsigned short ZeroLinearVelocity : 1; - unsigned short ZeroAngularVelocity : 1; + bool Force; + bool Torque; + bool DRot; + bool DLoc; + bool LinearVelocity; + bool AngularVelocity; + bool AddOrSetLinV; + bool ServoControl; + bool ZeroForce; + bool ZeroTorque; + bool ZeroDRot; + bool ZeroDLoc; + bool ZeroLinearVelocity; + bool ZeroAngularVelocity; }; class KX_ObjectActuator : public SCA_IActuator @@ -80,7 +82,8 @@ class KX_ObjectActuator : public SCA_IActuator MT_Vector3 m_dloc; MT_Vector3 m_drot; MT_Vector3 m_linear_velocity; - MT_Vector3 m_angular_velocity; + MT_Vector3 m_angular_velocity; + MT_Vector3 m_pid; MT_Scalar m_linear_length2; MT_Scalar m_angular_length2; // used in damping @@ -91,7 +94,7 @@ class KX_ObjectActuator : public SCA_IActuator MT_Vector3 m_previous_error; MT_Vector3 m_error_accumulator; KX_LocalFlags m_bitLocalFlag; - + KX_GameObject* m_reference; // A hack bool -- oh no sorry everyone // This bool is used to check if we have informed // the physics object that we are no longer @@ -120,6 +123,7 @@ public: KX_ObjectActuator( SCA_IObject* gameobj, + KX_GameObject* refobj, const MT_Vector3& force, const MT_Vector3& torque, const MT_Vector3& dloc, @@ -130,8 +134,11 @@ public: const KX_LocalFlags& flag, PyTypeObject* T=&Type ); - + ~KX_ObjectActuator(); CValue* GetReplica(); + void ProcessReplica(); + bool UnlinkObject(SCA_IObject* clientobj); + void Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map); void SetForceLoc(const double force[3]) { /*m_force=force;*/ } void UpdateFuzzyFlags() @@ -154,6 +161,8 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); + virtual int py_setattro(PyObject *attr, PyObject *value); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetForce); KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForce); @@ -177,6 +186,53 @@ public: KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetForceLimitZ); KX_PYMETHOD_NOARGS(KX_ObjectActuator,GetPID); KX_PYMETHOD_VARARGS(KX_ObjectActuator,SetPID); + + /* Attributes */ + static PyObject* pyattr_get_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_forceLimitX(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_forceLimitY(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_forceLimitZ(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_reference(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + + // This lets the attribute macros use UpdateFuzzyFlags() + static int PyUpdateFuzzyFlags(void *self, const PyAttributeDef *attrdef) + { + KX_ObjectActuator* act = reinterpret_cast<KX_ObjectActuator*>(self); + act->UpdateFuzzyFlags(); + return 0; + } + + // This is the keep the PID values in check after they are assigned with Python + static int PyCheckPid(void *self, const PyAttributeDef *attrdef) + { + KX_ObjectActuator* act = reinterpret_cast<KX_ObjectActuator*>(self); + + //P 0 to 200 + if (act->m_pid[0] < 0) { + act->m_pid[0] = 0; + } else if (act->m_pid[0] > 200) { + act->m_pid[0] = 200; + } + + //I 0 to 3 + if (act->m_pid[1] < 0) { + act->m_pid[1] = 0; + } else if (act->m_pid[1] > 3) { + act->m_pid[1] = 3; + } + + //D -100 to 100 + if (act->m_pid[2] < -100) { + act->m_pid[2] = -100; + } else if (act->m_pid[2] > 100) { + act->m_pid[2] = 100; + } + + return 0; + } }; #endif //__KX_OBJECTACTUATOR diff --git a/source/gameengine/Ketsji/KX_OdePhysicsController.h b/source/gameengine/Ketsji/KX_OdePhysicsController.h index 21b7e632d83..8c3974c38a3 100644 --- a/source/gameengine/Ketsji/KX_OdePhysicsController.h +++ b/source/gameengine/Ketsji/KX_OdePhysicsController.h @@ -70,6 +70,7 @@ public: virtual void setOrientation(const MT_Matrix3x3& orn); virtual void setPosition(const MT_Point3& pos); virtual void setScaling(const MT_Vector3& scaling); + virtual void SetTransform() {} virtual MT_Scalar GetMass(); virtual MT_Vector3 getReactionForce(); virtual void setRigidBody(bool rigid); diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 0093cf5f313..cd2ed456c48 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -48,10 +48,14 @@ KX_ParentActuator::KX_ParentActuator(SCA_IObject *gameobj, int mode, + bool addToCompound, + bool ghost, SCA_IObject *ob, PyTypeObject* T) : SCA_IActuator(gameobj, T), m_mode(mode), + m_addToCompound(addToCompound), + m_ghost(ghost), m_ob(ob) { if (m_ob) @@ -73,8 +77,6 @@ CValue* KX_ParentActuator::GetReplica() KX_ParentActuator* replica = new KX_ParentActuator(*this); // replication just copy the m_base pointer => common random generator replica->ProcessReplica(); - CValue::AddDataToReplica(replica); - return replica; } @@ -123,7 +125,7 @@ bool KX_ParentActuator::Update() switch (m_mode) { case KX_PARENT_SET: if (m_ob) - obj->SetParent(scene, (KX_GameObject*)m_ob); + obj->SetParent(scene, (KX_GameObject*)m_ob, m_addToCompound, m_ghost); break; case KX_PARENT_REMOVE: obj->RemoveParent(scene); @@ -139,8 +141,13 @@ bool KX_ParentActuator::Update() /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_ParentActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_ParentActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -175,6 +182,9 @@ PyMethodDef KX_ParentActuator::Methods[] = { PyAttributeDef KX_ParentActuator::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("object", KX_ParentActuator, pyattr_get_object, pyattr_set_object), + KX_PYATTRIBUTE_INT_RW("mode", KX_PARENT_NODEF+1, KX_PARENT_MAX-1, true, KX_ParentActuator, m_mode), + KX_PYATTRIBUTE_BOOL_RW("compound", KX_ParentActuator, m_addToCompound), + KX_PYATTRIBUTE_BOOL_RW("ghost", KX_ParentActuator, m_ghost), { NULL } //Sentinel }; @@ -193,7 +203,7 @@ int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE KX_GameObject *gameobj; if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_ParentActuator")) - return 1; // ConvertPythonToGameObject sets the error + return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error if (actuator->m_ob != NULL) actuator->m_ob->UnregisterActuator(actuator); @@ -203,7 +213,7 @@ int KX_ParentActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUTE if (actuator->m_ob) actuator->m_ob->RegisterActuator(actuator); - return 0; + return PY_SET_ATTR_SUCCESS; } @@ -211,6 +221,10 @@ PyObject* KX_ParentActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); } +PyObject* KX_ParentActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_ParentActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); } @@ -259,7 +273,7 @@ PyObject* KX_ParentActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_ob->GetName()); + return PyString_FromString(m_ob->GetName().ReadPtr()); else return m_ob->GetProxy(); } diff --git a/source/gameengine/Ketsji/KX_ParentActuator.h b/source/gameengine/Ketsji/KX_ParentActuator.h index f9f0b73b876..148375e994c 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.h +++ b/source/gameengine/Ketsji/KX_ParentActuator.h @@ -46,6 +46,9 @@ class KX_ParentActuator : public SCA_IActuator /** Mode */ int m_mode; + /** option */ + bool m_addToCompound; + bool m_ghost; /** Object to set as parent */ SCA_IObject *m_ob; @@ -57,11 +60,14 @@ class KX_ParentActuator : public SCA_IActuator KX_PARENT_NODEF = 0, KX_PARENT_SET, KX_PARENT_REMOVE, + KX_PARENT_MAX }; KX_ParentActuator(class SCA_IObject* gameobj, int mode, + bool addToCompound, + bool ghost, SCA_IObject *ob, PyTypeObject* T=&Type); virtual ~KX_ParentActuator(); @@ -77,6 +83,7 @@ class KX_ParentActuator : public SCA_IActuator /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); /* These are used to get and set m_ob */ diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp index fda639c09e0..c968e50957e 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.cpp @@ -113,8 +113,13 @@ PyAttributeDef KX_PhysicsObjectWrapper::Attributes[] = { //python specific stuff PyTypeObject KX_PhysicsObjectWrapper::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_PhysicsObjectWrapper", sizeof(PyObjectPlus_Proxy), 0, @@ -136,11 +141,14 @@ PyParentObject KX_PhysicsObjectWrapper::Parents[] = { NULL }; -PyObject* KX_PhysicsObjectWrapper::py_getattro(PyObject *attr) +PyObject* KX_PhysicsObjectWrapper::py_getattro(PyObject *attr) { py_getattro_up(PyObjectPlus); } +PyObject* KX_PhysicsObjectWrapper::py_getattro_dict() { + py_getattro_dict_up(PyObjectPlus); +} int KX_PhysicsObjectWrapper::py_setattro(PyObject *attr,PyObject *pyobj) { diff --git a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h index 7e10dc3ccf4..1b59686babc 100644 --- a/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h +++ b/source/gameengine/Ketsji/KX_PhysicsObjectWrapper.h @@ -37,6 +37,7 @@ class KX_PhysicsObjectWrapper : public PyObjectPlus Py_Header; virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); public: KX_PhysicsObjectWrapper(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsEnvironment* physenv,PyTypeObject *T = &Type); diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index 2e5dd72db0e..b56b5500c39 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -39,8 +39,13 @@ #include "KX_PyMath.h" PyTypeObject KX_PolyProxy::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_PolyProxy", sizeof(PyObjectPlus_Proxy), 0, @@ -59,8 +64,8 @@ PyTypeObject KX_PolyProxy::Type = { PyParentObject KX_PolyProxy::Parents[] = { &KX_PolyProxy::Type, - &SCA_IObject::Type, &CValue::Type, + &PyObjectPlus::Type, NULL }; @@ -79,6 +84,7 @@ PyMethodDef KX_PolyProxy::Methods[] = { PyAttributeDef KX_PolyProxy::Attributes[] = { /* All dummy's so they come up in a dir() */ + //KX_PYATTRIBUTE_TODO("DummyProps"), KX_PYATTRIBUTE_DUMMY("matname"), KX_PYATTRIBUTE_DUMMY("texture"), KX_PYATTRIBUTE_DUMMY("material"), @@ -156,7 +162,11 @@ PyObject* KX_PolyProxy::py_getattro(PyObject *attr) { return PyInt_FromLong(m_polygon->IsCollider()); } - py_getattro_up(SCA_IObject); + py_getattro_up(CValue); +} + +PyObject* KX_PolyProxy::py_getattro_dict() { + py_getattro_dict_up(CValue); } KX_PolyProxy::KX_PolyProxy(const RAS_MeshObject*mesh, RAS_Polygon* polygon) @@ -176,11 +186,9 @@ CValue* KX_PolyProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { re STR_String sPolyName="polygone"; const STR_String & KX_PolyProxy::GetText() {return sPolyName;}; double KX_PolyProxy::GetNumber() { return -1;} -STR_String KX_PolyProxy::GetName() { return sPolyName;} -void KX_PolyProxy::SetName(STR_String) { }; +STR_String& KX_PolyProxy::GetName() { return sPolyName;} +void KX_PolyProxy::SetName(const char *) { }; CValue* KX_PolyProxy::GetReplica() { return NULL;} -void KX_PolyProxy::ReplicaSetName(STR_String) {}; - // stuff for python integration diff --git a/source/gameengine/Ketsji/KX_PolyProxy.h b/source/gameengine/Ketsji/KX_PolyProxy.h index 275e65da810..d8fd36fec6c 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.h +++ b/source/gameengine/Ketsji/KX_PolyProxy.h @@ -31,7 +31,7 @@ #include "SCA_IObject.h" -class KX_PolyProxy : public SCA_IObject +class KX_PolyProxy : public CValue { Py_Header; protected: @@ -46,14 +46,14 @@ public: CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); const STR_String & GetText(); double GetNumber(); - STR_String GetName(); - void SetName(STR_String name); // Set the name of the value - void ReplicaSetName(STR_String name); + STR_String& GetName(); + void SetName(const char *name); // Set the name of the value CValue* GetReplica(); // stuff for python integration virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getMaterialIndex) KX_PYMETHOD_DOC_NOARGS(KX_PolyProxy,getNumVertex) diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 46d04486cc6..506c167a905 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -51,22 +51,37 @@ #include "KX_PyMath.h" -KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, - Material *material, - int tile, - int tilexrep, - int tileyrep, - int mode, - int transp, - bool alpha, - bool zsort, - int lightlayer, - struct MTFace* tface, - unsigned int* mcol, - PyTypeObject *T) +KX_PolygonMaterial::KX_PolygonMaterial(PyTypeObject *T) : PyObjectPlus(T), - RAS_IPolyMaterial(texname, - STR_String(material?material->id.name:""), + RAS_IPolyMaterial(), + + m_tface(NULL), + m_mcol(NULL), + m_material(NULL), + m_pymaterial(NULL), + m_pass(0) +{ +} + +void KX_PolygonMaterial::Initialize( + const STR_String &texname, + Material* ma, + int materialindex, + int tile, + int tilexrep, + int tileyrep, + int mode, + int transp, + bool alpha, + bool zsort, + int lightlayer, + struct MTFace* tface, + unsigned int* mcol) +{ + RAS_IPolyMaterial::Initialize( + texname, + ma?ma->id.name:"", + materialindex, tile, tilexrep, tileyrep, @@ -74,13 +89,12 @@ KX_PolygonMaterial::KX_PolygonMaterial(const STR_String &texname, transp, alpha, zsort, - lightlayer), - m_tface(tface), - m_mcol(mcol), - m_material(material), - m_pymaterial(0), - m_pass(0) -{ + lightlayer); + m_tface = tface; + m_mcol = mcol; + m_material = ma; + m_pymaterial = 0; + m_pass = 0; } KX_PolygonMaterial::~KX_PolygonMaterial() @@ -158,15 +172,32 @@ void KX_PolygonMaterial::DefaultActivate(RAS_IRasterizer* rasty, TCachingInfo& c 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); + if (m_material) + rasty->SetPolygonOffset(-m_material->zoffs, 0.0); } - 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); - if (m_material) - rasty->SetPolygonOffset(-m_material->zoffs, 0.0); + //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); + //if (m_material) + // rasty->SetPolygonOffset(-m_material->zoffs, 0.0); +} + +void KX_PolygonMaterial::GetMaterialRGBAColor(unsigned char *rgba) const +{ + if (m_material) { + *rgba++ = (unsigned char) (m_material->r*255.0); + *rgba++ = (unsigned char) (m_material->g*255.0); + *rgba++ = (unsigned char) (m_material->b*255.0); + *rgba++ = (unsigned char) (m_material->alpha*255.0); + } else + RAS_IPolyMaterial::GetMaterialRGBAColor(rgba); } + //---------------------------------------------------------------------------- //Python @@ -189,7 +220,7 @@ PyAttributeDef KX_PolygonMaterial::Attributes[] = { KX_PYATTRIBUTE_INT_RW("tilexrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tilexrep), KX_PYATTRIBUTE_INT_RW("tileyrep", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_tileyrep), KX_PYATTRIBUTE_INT_RW("drawingmode", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_drawingmode), - KX_PYATTRIBUTE_INT_RW("lightlayer", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_lightlayer), + //KX_PYATTRIBUTE_INT_RW("lightlayer", INT_MIN, INT_MAX, true, KX_PolygonMaterial, m_lightlayer), KX_PYATTRIBUTE_BOOL_RW("transparent", KX_PolygonMaterial, m_alpha), KX_PYATTRIBUTE_BOOL_RW("zsort", KX_PolygonMaterial, m_zsort), @@ -208,8 +239,13 @@ PyAttributeDef KX_PolygonMaterial::Attributes[] = { }; PyTypeObject KX_PolygonMaterial::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_PolygonMaterial", sizeof(PyObjectPlus_Proxy), 0, @@ -237,6 +273,10 @@ PyObject* KX_PolygonMaterial::py_getattro(PyObject *attr) py_getattro_up(PyObjectPlus); } +PyObject* KX_PolygonMaterial::py_getattro_dict() { + py_getattro_dict_up(PyObjectPlus); +} + int KX_PolygonMaterial::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(PyObjectPlus); @@ -346,10 +386,10 @@ int KX_PolygonMaterial::pyattr_set_diffuse(void *self_v, const KX_PYATTRIBUTE_DE MT_Vector3 vec; if (!PyVecTo(value, vec)) - return -1; + return PY_SET_ATTR_FAIL; self->m_diffuse= vec; - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_PolygonMaterial::pyattr_get_specular(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -364,8 +404,8 @@ int KX_PolygonMaterial::pyattr_set_specular(void *self_v, const KX_PYATTRIBUTE_D MT_Vector3 vec; if (!PyVecTo(value, vec)) - return -1; + return PY_SET_ATTR_FAIL; self->m_specular= vec; - return 0; + return PY_SET_ATTR_SUCCESS; } diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 9865a66e836..89ecb026da9 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -53,14 +53,14 @@ private: MTFace* m_tface; unsigned int* m_mcol; Material* m_material; - PyObject* m_pymaterial; mutable int m_pass; public: - - KX_PolygonMaterial(const STR_String &texname, + KX_PolygonMaterial(PyTypeObject *T = &Type); + void Initialize(const STR_String &texname, Material* ma, + int materialindex, int tile, int tilexrep, int tileyrep, @@ -70,8 +70,8 @@ public: bool zsort, int lightlayer, struct MTFace* tface, - unsigned int* mcol, - PyTypeObject *T = &Type); + unsigned int* mcol); + virtual ~KX_PolygonMaterial(); /** @@ -107,8 +107,8 @@ public: { return m_mcol; } - - + virtual void GetMaterialRGBAColor(unsigned char *rgba) const; + KX_PYMETHOD_DOC(KX_PolygonMaterial, updateTexture); KX_PYMETHOD_DOC(KX_PolygonMaterial, setTexture); KX_PYMETHOD_DOC(KX_PolygonMaterial, activate); @@ -117,6 +117,7 @@ public: KX_PYMETHOD_DOC(KX_PolygonMaterial, loadProgram); virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *pyvalue); virtual PyObject* py_repr(void) { return PyString_FromString(m_material ? ((ID *)m_material)->name+2 : ""); } diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index 2c65c184a9c..a098d99864f 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -33,6 +33,7 @@ #include "KX_PhysicsObjectWrapper.h" #include "PHY_IPhysicsController.h" #include "PHY_IVehicle.h" +#include "MT_Matrix3x3.h" #include "PyObjectPlus.h" @@ -404,6 +405,8 @@ static PyObject* gPyCreateConstraint(PyObject* self, int physicsid=0,physicsid2 = 0,constrainttype=0,extrainfo=0; int len = PyTuple_Size(args); int success = 1; + int flag = 0; + float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1; if (len == 3) { @@ -420,6 +423,11 @@ static PyObject* gPyCreateConstraint(PyObject* self, success = PyArg_ParseTuple(args,"iiiffffff",&physicsid,&physicsid2,&constrainttype, &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); } + else if (len == 10) + { + success = PyArg_ParseTuple(args,"iiiffffffi",&physicsid,&physicsid2,&constrainttype, + &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); + } else if (len==4) { success = PyArg_ParseTuple(args,"iiii",&physicsid,&physicsid2,&constrainttype,&extrainfo); @@ -435,7 +443,31 @@ static PyObject* gPyCreateConstraint(PyObject* self, PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2; if (physctrl) //TODO:check for existance of this pointer! { - int constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ,0); + PHY_ConstraintType ct = (PHY_ConstraintType) constrainttype; + int constraintid =0; + + if (ct == PHY_GENERIC_6DOF_CONSTRAINT) + { + //convert from euler angle into axis + float radsPerDeg = 6.283185307179586232f / 360.f; + + //we need to pass a full constraint frame, not just axis + //localConstraintFrameBasis + MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*axisX,radsPerDeg*axisY,radsPerDeg*axisZ)); + MT_Vector3 axis0 = localCFrame.getColumn(0); + MT_Vector3 axis1 = localCFrame.getColumn(1); + MT_Vector3 axis2 = localCFrame.getColumn(2); + + constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype, + pivotX,pivotY,pivotZ, + (float)axis0.x(),(float)axis0.y(),(float)axis0.z(), + (float)axis1.x(),(float)axis1.y(),(float)axis1.z(), + (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag); + + } else + { + constraintid = PHY_GetActiveEnvironment()->createConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ,0); + } KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment()); @@ -565,6 +597,19 @@ static struct PyMethodDef physicsconstraints_methods[] = { }; +#if (PY_VERSION_HEX >= 0x03000000) +static struct PyModuleDef PhysicsConstraints_module_def = { + {}, /* m_base */ + "PhysicsConstraints", /* m_name */ + PhysicsConstraints_module_documentation, /* m_doc */ + 0, /* m_size */ + physicsconstraints_methods, /* m_methods */ + 0, /* m_reload */ + 0, /* m_traverse */ + 0, /* m_clear */ + 0, /* m_free */ +}; +#endif PyObject* initPythonConstraintBinding() { @@ -573,10 +618,24 @@ PyObject* initPythonConstraintBinding() PyObject* m; PyObject* d; - - m = Py_InitModule4("PhysicsConstraints", physicsconstraints_methods, + /* Use existing module where possible + * be careful not to init any runtime vars after this */ + m = PyImport_ImportModule( "PhysicsConstraints" ); + if(m) { + Py_DECREF(m); + return m; + } + else { + PyErr_Clear(); + +#if (PY_VERSION_HEX >= 0x03000000) + m = PyModule_Create(&PhysicsConstraints_module_def); +#else + m = Py_InitModule4("PhysicsConstraints", physicsconstraints_methods, PhysicsConstraints_module_documentation, (PyObject*)NULL,PYTHON_API_VERSION); +#endif + } // Add some symbolic constants to the module d = PyModule_GetDict(m); diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index 0093a72808e..051d7ae7dba 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -75,9 +75,8 @@ bool PyObject_IsMT_Matrix(PyObject *pymat, unsigned int rank) return false; } -bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &mat, const char *error_prefix) +bool PyOrientationTo(PyObject* pyval, MT_Matrix3x3 &rot, const char *error_prefix) { - MT_Matrix3x3 rot; int size= PySequence_Size(pyval); if (size == 4) diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index 00f7c5cad93..a7ce4bc6930 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -40,6 +40,7 @@ #include "MT_Matrix4x4.h" #include "KX_Python.h" +#include "PyObjectPlus.h" inline unsigned int Size(const MT_Matrix4x4&) { return 4; } inline unsigned int Size(const MT_Matrix3x3&) { return 3; } @@ -116,6 +117,19 @@ bool PyVecTo(PyObject* pyval, T& vec) return true; } + else if (BGE_PROXY_CHECK_TYPE(pyval)) + { /* note, include this check because PySequence_Check does too much introspection + * on the PyObject (like getting its __class__, on a BGE type this means searching up + * the parent list each time only to discover its not a sequence. + * GameObjects are often used as an alternative to vectors so this is a common case + * better to do a quick check for it, likely the error below will be ignored. + * + * This is not 'correct' since we have proxy type CListValues's which could + * contain floats/ints but there no cases of CValueLists being this way + */ + PyErr_Format(PyExc_AttributeError, "expected a sequence type"); + return false; + } else if (PySequence_Check(pyval)) { unsigned int numitems = PySequence_Size(pyval); diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index ffcf7d7162e..fc3e48f504c 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -49,6 +49,9 @@ #include "KX_KetsjiEngine.h" #include "KX_RadarSensor.h" #include "KX_RaySensor.h" +#include "KX_SceneActuator.h" +#include "KX_GameActuator.h" +#include "KX_ParentActuator.h" #include "KX_SCA_DynamicActuator.h" #include "SCA_IInputDevice.h" @@ -83,10 +86,16 @@ #include "KX_PythonInitTypes.h" +/* we only need this to get a list of libraries from the main struct */ +#include "DNA_ID.h" + extern "C" { - #include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use. #include "bpy_internal_import.h" /* from the blender python api, but we want to import text too! */ +#if PY_VERSION_HEX < 0x03000000 + #include "Mathutils.h" // Blender.Mathutils module copied here so the blenderlayer can use. + #include "Geometry.h" // Blender.Geometry module copied here so the blenderlayer can use. #include "BGL.h" +#endif } #endif @@ -100,13 +109,13 @@ extern "C" { //#include "BPY_extern.h" #endif +#include "BKE_main.h" #include "BKE_utildefines.h" #include "BKE_global.h" #include "BLI_blenlib.h" #include "GPU_material.h" static void setSandbox(TPythonSecurityLevel level); -static void clearGameModules(); // 'local' copy of canvas ptr, for window height/width python scripts static RAS_ICanvas* gp_Canvas = NULL; @@ -114,6 +123,9 @@ static KX_Scene* gp_KetsjiScene = NULL; static KX_KetsjiEngine* gp_KetsjiEngine = NULL; static RAS_IRasterizer* gp_Rasterizer = NULL; static char gp_GamePythonPath[FILE_MAXDIR + FILE_MAXFILE] = ""; +static char gp_GamePythonPathOrig[FILE_MAXDIR + FILE_MAXFILE] = ""; // not super happy about this, but we need to remember the first loaded file for the global/dict load save +static PyObject *gp_OrigPythonSysPath= NULL; +static PyObject *gp_OrigPythonSysModules= NULL; void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color) { @@ -220,13 +232,13 @@ static PyObject* gPyGetSpectrum(PyObject*) for (int index = 0; index < 512; index++) { - PyList_SetItem(resultlist, index, PyFloat_FromDouble(spectrum[index])); + PyList_SET_ITEM(resultlist, index, PyFloat_FromDouble(spectrum[index])); } } else { for (int index = 0; index < 512; index++) { - PyList_SetItem(resultlist, index, PyFloat_FromDouble(0.0)); + PyList_SET_ITEM(resultlist, index, PyFloat_FromDouble(0.0)); } } @@ -286,6 +298,36 @@ static PyObject* gPyGetLogicTicRate(PyObject*) return PyFloat_FromDouble(KX_KetsjiEngine::GetTicRate()); } +static PyObject* gPySetMaxLogicFrame(PyObject*, PyObject* args) +{ + int frame; + if (!PyArg_ParseTuple(args, "i:setMaxLogicFrame", &frame)) + return NULL; + + KX_KetsjiEngine::SetMaxLogicFrame(frame); + Py_RETURN_NONE; +} + +static PyObject* gPyGetMaxLogicFrame(PyObject*) +{ + return PyInt_FromLong(KX_KetsjiEngine::GetMaxLogicFrame()); +} + +static PyObject* gPySetMaxPhysicsFrame(PyObject*, PyObject* args) +{ + int frame; + if (!PyArg_ParseTuple(args, "i:setMaxPhysicsFrame", &frame)) + return NULL; + + KX_KetsjiEngine::SetMaxPhysicsFrame(frame); + Py_RETURN_NONE; +} + +static PyObject* gPyGetMaxPhysicsFrame(PyObject*) +{ + return PyInt_FromLong(KX_KetsjiEngine::GetMaxPhysicsFrame()); +} + static PyObject* gPySetPhysicsTicRate(PyObject*, PyObject* args) { float ticrate; @@ -477,6 +519,10 @@ static struct PyMethodDef game_methods[] = { {"setGravity",(PyCFunction) gPySetGravity, METH_O, (PY_METHODCHAR)"set Gravitation"}, {"getSpectrum",(PyCFunction) gPyGetSpectrum, METH_NOARGS, (PY_METHODCHAR)"get audio spectrum"}, {"stopDSP",(PyCFunction) gPyStopDSP, METH_VARARGS, (PY_METHODCHAR)"stop using the audio dsp (for performance reasons)"}, + {"getMaxLogicFrame", (PyCFunction) gPyGetMaxLogicFrame, METH_NOARGS, (PY_METHODCHAR)"Gets the max number of logic frame per render frame"}, + {"setMaxLogicFrame", (PyCFunction) gPySetMaxLogicFrame, METH_VARARGS, (PY_METHODCHAR)"Sets the max number of logic frame per render frame"}, + {"getMaxPhysicsFrame", (PyCFunction) gPyGetMaxPhysicsFrame, METH_NOARGS, (PY_METHODCHAR)"Gets the max number of physics frame per render frame"}, + {"setMaxPhysicsFrame", (PyCFunction) gPySetMaxPhysicsFrame, METH_VARARGS, (PY_METHODCHAR)"Sets the max number of physics farme per render frame"}, {"getLogicTicRate", (PyCFunction) gPyGetLogicTicRate, METH_NOARGS, (PY_METHODCHAR)"Gets the logic tic rate"}, {"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, (PY_METHODCHAR)"Sets the logic tic rate"}, {"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, (PY_METHODCHAR)"Gets the physics tic rate"}, @@ -487,7 +533,6 @@ static struct PyMethodDef game_methods[] = { {NULL, (PyCFunction) NULL, 0, NULL } }; - static PyObject* gPyGetWindowHeight(PyObject*, PyObject* args) { return PyInt_FromLong((gp_Canvas ? gp_Canvas->GetHeight() : 0)); @@ -636,6 +681,17 @@ static PyObject* gPySetMistColor(PyObject*, PyObject* value) Py_RETURN_NONE; } +static PyObject* gPyDisableMist(PyObject*) +{ + + if (!gp_Rasterizer) { + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); + return NULL; + } + gp_Rasterizer->DisableFog(); + + Py_RETURN_NONE; +} static PyObject* gPySetMistStart(PyObject*, PyObject* args) @@ -724,7 +780,7 @@ static PyObject* gPyEnableMotionBlur(PyObject*, PyObject* args) Py_RETURN_NONE; } -static PyObject* gPyDisableMotionBlur(PyObject*, PyObject* args) +static PyObject* gPyDisableMotionBlur(PyObject*) { if (!gp_Rasterizer) { PyErr_SetString(PyExc_RuntimeError, "Rasterizer.disableMotionBlur(), Rasterizer not available"); @@ -780,16 +836,17 @@ static PyObject* gPySetGLSLMaterialSetting(PyObject*, /* display lists and GLSL materials need to be remade */ if(G.fileflags != fileflags) { + GPU_materials_free(); if(gp_KetsjiEngine) { KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes(); KX_SceneList::iterator it; for(it=scenes->begin(); it!=scenes->end(); it++) - if((*it)->GetBucketManager()) + if((*it)->GetBucketManager()) { (*it)->GetBucketManager()->ReleaseDisplayLists(); + (*it)->GetBucketManager()->ReleaseMaterials(); + } } - - GPU_materials_free(); } Py_RETURN_NONE; @@ -850,7 +907,7 @@ static PyObject* gPyGetMaterialType(PyObject*) { int flag; - if(G.fileflags & (G_FILE_GAME_MAT|G_FILE_GAME_MAT_GLSL)) + if(G.fileflags & G_FILE_GAME_MAT_GLSL) flag = KX_BLENDER_GLSL_MATERIAL; else if(G.fileflags & G_FILE_GAME_MAT) flag = KX_BLENDER_MULTITEX_MATERIAL; @@ -904,11 +961,12 @@ static struct PyMethodDef rasterizer_methods[] = { METH_VARARGS, "setMousePosition(int x,int y)"}, {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"}, {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"}, + {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"}, {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"}, {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"}, {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, - {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_VARARGS,"disable motion blur"}, + {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"}, {"setEyeSeparation", (PyCFunction) gPySetEyeSeparation, METH_VARARGS, "set the eye separation for stereo mode"}, @@ -938,7 +996,19 @@ static char Rasterizer_module_documentation[] = "This is the Python API for the game engine of Rasterizer" ; - +#if (PY_VERSION_HEX >= 0x03000000) +static struct PyModuleDef GameLogic_module_def = { + {}, /* m_base */ + "GameLogic", /* m_name */ + GameLogic_module_documentation, /* m_doc */ + 0, /* m_size */ + game_methods, /* m_methods */ + 0, /* m_reload */ + 0, /* m_traverse */ + 0, /* m_clear */ + 0, /* m_free */ +}; +#endif PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook { @@ -950,12 +1020,29 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack gp_KetsjiScene = scene; gUseVisibilityTemp=false; - - // Create the module and add the functions - m = Py_InitModule4("GameLogic", game_methods, - GameLogic_module_documentation, - (PyObject*)NULL,PYTHON_API_VERSION); - + + PyObjectPlus::ClearDeprecationWarning(); /* Not that nice to call here but makes sure warnings are reset between loading scenes */ + + /* Use existing module where possible + * be careful not to init any runtime vars after this */ + m = PyImport_ImportModule( "GameLogic" ); + if(m) { + Py_DECREF(m); + return m; + } + else { + PyErr_Clear(); + + // Create the module and add the functions +#if (PY_VERSION_HEX >= 0x03000000) + m = PyModule_Create(&GameLogic_module_def); +#else + m = Py_InitModule4("GameLogic", game_methods, + GameLogic_module_documentation, + (PyObject*)NULL,PYTHON_API_VERSION); +#endif + } + // Add some symbolic constants to the module d = PyModule_GetDict(m); @@ -1172,6 +1259,28 @@ PyObject* initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_LOCAL, KX_ConstraintActuator::KX_ACT_CONSTRAINT_LOCAL); KX_MACRO_addTypesToDict(d, KX_ACT_CONSTRAINT_DOROTFH, KX_ConstraintActuator::KX_ACT_CONSTRAINT_DOROTFH); + /* Game Actuator Modes */ + KX_MACRO_addTypesToDict(d, KX_GAME_LOAD, KX_GameActuator::KX_GAME_LOAD); + KX_MACRO_addTypesToDict(d, KX_GAME_START, KX_GameActuator::KX_GAME_START); + KX_MACRO_addTypesToDict(d, KX_GAME_RESTART, KX_GameActuator::KX_GAME_RESTART); + KX_MACRO_addTypesToDict(d, KX_GAME_QUIT, KX_GameActuator::KX_GAME_QUIT); + KX_MACRO_addTypesToDict(d, KX_GAME_SAVECFG, KX_GameActuator::KX_GAME_SAVECFG); + KX_MACRO_addTypesToDict(d, KX_GAME_LOADCFG, KX_GameActuator::KX_GAME_LOADCFG); + + /* Scene Actuator Modes */ + KX_MACRO_addTypesToDict(d, KX_SCENE_RESTART, KX_SceneActuator::KX_SCENE_RESTART); + KX_MACRO_addTypesToDict(d, KX_SCENE_SET_SCENE, KX_SceneActuator::KX_SCENE_SET_SCENE); + KX_MACRO_addTypesToDict(d, KX_SCENE_SET_CAMERA, KX_SceneActuator::KX_SCENE_SET_CAMERA); + KX_MACRO_addTypesToDict(d, KX_SCENE_ADD_FRONT_SCENE, KX_SceneActuator::KX_SCENE_ADD_FRONT_SCENE); + KX_MACRO_addTypesToDict(d, KX_SCENE_ADD_BACK_SCENE, KX_SceneActuator::KX_SCENE_ADD_BACK_SCENE); + KX_MACRO_addTypesToDict(d, KX_SCENE_REMOVE_SCENE, KX_SceneActuator::KX_SCENE_REMOVE_SCENE); + KX_MACRO_addTypesToDict(d, KX_SCENE_SUSPEND, KX_SceneActuator::KX_SCENE_SUSPEND); + KX_MACRO_addTypesToDict(d, KX_SCENE_RESUME, KX_SceneActuator::KX_SCENE_RESUME); + + /* Parent Actuator Modes */ + KX_MACRO_addTypesToDict(d, KX_PARENT_SET, KX_ParentActuator::KX_PARENT_SET); + KX_MACRO_addTypesToDict(d, KX_PARENT_REMOVE, KX_ParentActuator::KX_PARENT_REMOVE); + // Check for errors if (PyErr_Occurred()) { @@ -1238,7 +1347,7 @@ PyObject *KXpy_import(PyObject *self, PyObject *args) /* quick hack for GamePython modules TODO: register builtin modules properly by ExtendInittab */ if (!strcmp(name, "GameLogic") || !strcmp(name, "GameKeys") || !strcmp(name, "PhysicsConstraints") || - !strcmp(name, "Rasterizer") || !strcmp(name, "Mathutils") || !strcmp(name, "BGL")) { + !strcmp(name, "Rasterizer") || !strcmp(name, "Mathutils") || !strcmp(name, "BGL") || !strcmp(name, "Geometry")) { return PyImport_ImportModuleEx(name, globals, locals, fromlist); } @@ -1359,20 +1468,141 @@ void setSandbox(TPythonSecurityLevel level) } } +/* Explanation of + * + * - backupPySysObjects() : stores sys.path in gp_OrigPythonSysPath + * - initPySysObjects(main) : initializes the blendfile and library paths + * - restorePySysObjects() : restores sys.path from gp_OrigPythonSysPath + * + * These exist so the current blend dir "//" can always be used to import modules from. + * the reason we need a few functions for this is that python is not only used by the game engine + * so we cant just add to sys.path all the time, it would leave pythons state in a mess. + * It would also be incorrect since loading blend files for new levels etc would alwasy add to sys.path + * + * To play nice with blenders python, the sys.path is backed up and the current blendfile along + * with all its lib paths are added to the sys path. + * When loading a new blendfile, the original sys.path is restored and the new paths are added over the top. + */ + +/** + * So we can have external modules mixed with our blend files. + */ +static void backupPySysObjects(void) +{ + PyObject *sys_path= PySys_GetObject("path"); /* should never fail */ + PyObject *sys_mods= PySys_GetObject("modules"); /* should never fail */ + + /* paths */ + Py_XDECREF(gp_OrigPythonSysPath); /* just incase its set */ + gp_OrigPythonSysPath = PyList_GetSlice(sys_path, 0, INT_MAX); /* copy the list */ + + /* modules */ + Py_XDECREF(gp_OrigPythonSysModules); /* just incase its set */ + gp_OrigPythonSysModules = PyDict_Copy(sys_mods); /* copy the list */ + +} + +/* for initPySysObjects only, + * takes a blend path and adds a scripts dir from it + * + * "/home/me/foo.blend" -> "/home/me/scripts" + */ +static void initPySysObjects__append(PyObject *sys_path, char *filename) +{ + PyObject *item; + char expanded[FILE_MAXDIR + FILE_MAXFILE]; + + BLI_split_dirfile_basic(filename, expanded, NULL); /* get the dir part of filename only */ + BLI_convertstringcode(expanded, gp_GamePythonPath); /* filename from lib->filename is (always?) absolute, so this may not be needed but it wont hurt */ + BLI_cleanup_file(gp_GamePythonPath, expanded); /* Dont use BLI_cleanup_dir because it adds a slash - BREAKS WIN32 ONLY */ + item= PyString_FromString(expanded); + +// printf("SysPath - '%s', '%s', '%s'\n", expanded, filename, gp_GamePythonPath); + + if(PySequence_Index(sys_path, item) == -1) { + PyErr_Clear(); /* PySequence_Index sets a ValueError */ + PyList_Insert(sys_path, 0, item); + } + + Py_DECREF(item); +} +static void initPySysObjects(Main *maggie) +{ + PyObject *sys_path= PySys_GetObject("path"); /* should never fail */ + + if (gp_OrigPythonSysPath==NULL) { + /* backup */ + backupPySysObjects(); + } + else { + /* get the original sys path when the BGE started */ + PyList_SetSlice(sys_path, 0, INT_MAX, gp_OrigPythonSysPath); + } + + Library *lib= (Library *)maggie->library.first; + + while(lib) { + /* lib->name wont work in some cases (on win32), + * even when expanding with gp_GamePythonPath, using lib->filename is less trouble */ + initPySysObjects__append(sys_path, lib->filename); + lib= (Library *)lib->id.next; + } + + initPySysObjects__append(sys_path, gp_GamePythonPath); + +// fprintf(stderr, "\nNew Path: %d ", PyList_Size(sys_path)); +// PyObject_Print(sys_path, stderr, 0); +} + +static void restorePySysObjects(void) +{ + if (gp_OrigPythonSysPath==NULL) + return; + + PyObject *sys_path= PySys_GetObject("path"); /* should never fail */ + PyObject *sys_mods= PySys_GetObject("modules"); /* should never fail */ + + /* paths */ + PyList_SetSlice(sys_path, 0, INT_MAX, gp_OrigPythonSysPath); + Py_DECREF(gp_OrigPythonSysPath); + gp_OrigPythonSysPath= NULL; + + /* modules */ + PyDict_Clear(sys_mods); + PyDict_Update(sys_mods, gp_OrigPythonSysModules); + Py_DECREF(gp_OrigPythonSysModules); + gp_OrigPythonSysModules= NULL; + + +// fprintf(stderr, "\nRestore Path: %d ", PyList_Size(sys_path)); +// PyObject_Print(sys_path, stderr, 0); +} + /** * Python is not initialised. */ PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv) { + /* Yet another gotcha in the py api + * Cant run PySys_SetArgv more then once because this adds the + * binary dir to the sys.path each time. + * Id have thaught python being totally restarted would make this ok but + * somehow it remembers the sys.path - Campbell + */ + static bool first_time = true; + +#if (PY_VERSION_HEX < 0x03000000) STR_String pname = progname; Py_SetProgramName(pname.Ptr()); +#endif Py_NoSiteFlag=1; Py_FrozenFlag=1; Py_Initialize(); - if(argv) /* browser plugins dont currently set this */ +#if (PY_VERSION_HEX < 0x03000000) + if(argv && first_time) /* browser plugins dont currently set this */ PySys_SetArgv(argc, argv); - +#endif //importBlenderModules() setSandbox(level); @@ -1380,24 +1610,37 @@ PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur /* XXX 2.5 bpy_import_main_set(maggie); */ + initPySysObjects(maggie); + + first_time = false; + + PyObjectPlus::ClearDeprecationWarning(); + PyObject* moduleobj = PyImport_AddModule("__main__"); return PyModule_GetDict(moduleobj); } void exitGamePlayerPythonScripting() -{ - //clearGameModules(); // were closing python anyway +{ + /* since python restarts we cant let the python backup of the sys.path hang around in a global pointer */ + restorePySysObjects(); /* get back the original sys.path and clear the backup */ + Py_Finalize(); /* XXX 2.5 bpy_import_main_set(NULL); */ + PyObjectPlus::ClearDeprecationWarning(); } + + /** * Python is already initialized. */ PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie) { +#if (PY_VERSION_HEX < 0x03000000) STR_String pname = progname; Py_SetProgramName(pname.Ptr()); +#endif Py_NoSiteFlag=1; Py_FrozenFlag=1; @@ -1406,53 +1649,35 @@ PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLev /* XXX 2.5 bpy_import_main_set(maggie); */ - /* run this to clear game modules and user modules which - * may contain references to in game data */ - clearGameModules(); + initPySysObjects(maggie); + PyObjectPlus::NullDeprecationWarning(); + PyObject* moduleobj = PyImport_AddModule("__main__"); return PyModule_GetDict(moduleobj); } -static void clearModule(PyObject *modules, const char *name) -{ - PyObject *mod= PyDict_GetItemString(modules, name); - - if (mod==NULL) - return; - - PyDict_Clear(PyModule_GetDict(mod)); /* incase there are any circular refs */ - PyDict_DelItemString(modules, name); -} - -static void clearGameModules() -{ - /* Note, user modules could still reference these modules - * but since the dict's are cleared their members wont be accessible */ - - PyObject *modules= PySys_GetObject((char *)"modules"); - clearModule(modules, "Expression"); - clearModule(modules, "CValue"); - clearModule(modules, "PhysicsConstraints"); - clearModule(modules, "GameLogic"); - clearModule(modules, "Rasterizer"); - clearModule(modules, "GameKeys"); - clearModule(modules, "VideoTexture"); - clearModule(modules, "Mathutils"); - clearModule(modules, "BGL"); - PyErr_Clear(); // incase some of these were alredy removed. - - /* clear user defined modules */ - /* XXX 2.5 bpy_text_clear_modules(); */ -} - void exitGamePythonScripting() { - clearGameModules(); + restorePySysObjects(); /* get back the original sys.path and clear the backup */ /* XXX 2.5 bpy_import_main_set(NULL); */ + PyObjectPlus::ClearDeprecationWarning(); } +#if (PY_VERSION_HEX >= 0x03000000) +static struct PyModuleDef Rasterizer_module_def = { + {}, /* m_base */ + "Rasterizer", /* m_name */ + Rasterizer_module_documentation, /* m_doc */ + 0, /* m_size */ + rasterizer_methods, /* m_methods */ + 0, /* m_reload */ + 0, /* m_traverse */ + 0, /* m_clear */ + 0, /* m_free */ +}; +#endif PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) { @@ -1464,10 +1689,25 @@ PyObject* initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) PyObject* d; PyObject* item; - // Create the module and add the functions - m = Py_InitModule4("Rasterizer", rasterizer_methods, + /* Use existing module where possible + * be careful not to init any runtime vars after this */ + m = PyImport_ImportModule( "Rasterizer" ); + if(m) { + Py_DECREF(m); + return m; + } + else { + PyErr_Clear(); + + // Create the module and add the functions +#if (PY_VERSION_HEX >= 0x03000000) + m = PyModule_Create(&Rasterizer_module_def); +#else + m = Py_InitModule4("Rasterizer", rasterizer_methods, Rasterizer_module_documentation, (PyObject*)NULL,PYTHON_API_VERSION); +#endif + } // Add some symbolic constants to the module d = PyModule_GetDict(m); @@ -1517,7 +1757,12 @@ static PyObject* gPyEventToString(PyObject*, PyObject* value) dict = PyModule_GetDict(mod); while (PyDict_Next(dict, &pos, &key, &val)) { +#if (PY_VERSION_HEX >= 0x03000000) + if (PyObject_RichCompareBool(value, val, Py_EQ)) { +#else if (PyObject_Compare(value, val)==0) { +#endif + ret = key; break; } @@ -1559,17 +1804,44 @@ static struct PyMethodDef gamekeys_methods[] = { }; +#if (PY_VERSION_HEX >= 0x03000000) +static struct PyModuleDef GameKeys_module_def = { + {}, /* m_base */ + "GameKeys", /* m_name */ + GameKeys_module_documentation, /* m_doc */ + 0, /* m_size */ + gamekeys_methods, /* m_methods */ + 0, /* m_reload */ + 0, /* m_traverse */ + 0, /* m_clear */ + 0, /* m_free */ +}; +#endif PyObject* initGameKeys() { PyObject* m; PyObject* d; PyObject* item; - - // Create the module and add the functions - m = Py_InitModule4("GameKeys", gamekeys_methods, + + /* Use existing module where possible */ + m = PyImport_ImportModule( "GameKeys" ); + if(m) { + Py_DECREF(m); + return m; + } + else { + PyErr_Clear(); + + // Create the module and add the functions +#if (PY_VERSION_HEX >= 0x03000000) + m = PyModule_Create(&GameKeys_module_def); +#else + m = Py_InitModule4("GameKeys", gamekeys_methods, GameKeys_module_documentation, (PyObject*)NULL,PYTHON_API_VERSION); +#endif + } // Add some symbolic constants to the module d = PyModule_GetDict(m); @@ -1698,15 +1970,26 @@ PyObject* initGameKeys() return d; } +#if PY_VERSION_HEX < 0x03000000 PyObject* initMathutils() { return NULL; //XXX Mathutils_Init("Mathutils"); // Use as a top level module in BGE } +PyObject* initGeometry() +{ + return NULL; // XXX Geometry_Init("Geometry"); // Use as a top level module in BGE +} + PyObject* initBGL() { return NULL; // XXX 2.5 BGL_Init("BGL"); // Use as a top level module in BGE } +#else // TODO Py3k conversion +PyObject* initMathutils() {Py_INCREF(Py_None);return Py_None;} +PyObject* initGeometry() {Py_INCREF(Py_None);return Py_None;} +PyObject* initBGL() {Py_INCREF(Py_None);return Py_None;} +#endif void KX_SetActiveScene(class KX_Scene* scene) { @@ -1794,9 +2077,9 @@ int loadGamePythonConfig(char *marshal_buffer, int marshal_length) void pathGamePythonConfig( char *path ) { - int len = strlen(gp_GamePythonPath); + int len = strlen(gp_GamePythonPathOrig); // Always use the first loaded blend filename - BLI_strncpy(path, gp_GamePythonPath, sizeof(gp_GamePythonPath)); + BLI_strncpy(path, gp_GamePythonPathOrig, sizeof(gp_GamePythonPathOrig)); /* replace extension */ if (BLI_testextensie(path, ".blend")) { @@ -1809,5 +2092,16 @@ void pathGamePythonConfig( char *path ) void setGamePythonPath(char *path) { BLI_strncpy(gp_GamePythonPath, path, sizeof(gp_GamePythonPath)); + BLI_cleanup_file(NULL, gp_GamePythonPath); /* not absolutely needed but makes resolving path problems less confusing later */ + + if (gp_GamePythonPathOrig[0] == '\0') + BLI_strncpy(gp_GamePythonPathOrig, path, sizeof(gp_GamePythonPathOrig)); } +// we need this so while blender is open (not blenderplayer) +// loading new blendfiles will reset this on starting the +// engine but loading blend files within the BGE wont overwrite gp_GamePythonPathOrig +void resetGamePythonPath() +{ + gp_GamePythonPathOrig[0] == '\0'; +} diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index 11360197b95..8f102d13a18 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -45,6 +45,7 @@ PyObject* initGameKeys(); PyObject* initRasterizer(class RAS_IRasterizer* rasty,class RAS_ICanvas* canvas); PyObject* initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, struct Main *maggie, int argc, char** argv); PyObject* initMathutils(); +PyObject* initGeometry(); PyObject* initBGL(); PyObject* initVideoTexture(void); void exitGamePlayerPythonScripting(); @@ -52,6 +53,7 @@ PyObject* initGamePythonScripting(const STR_String& progname, TPythonSecurityLev void exitGamePythonScripting(); void setGamePythonPath(char *path); +void resetGamePythonPath(); void pathGamePythonConfig( char *path ); int saveGamePythonConfig( char **marshal_buffer); int loadGamePythonConfig(char *marshal_buffer, int marshal_length); diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index dcd11b551a1..83c4dcbb34c 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -51,6 +51,7 @@ #include "KX_PhysicsObjectWrapper.h" #include "KX_PolyProxy.h" #include "KX_PolygonMaterial.h" +#include "KX_PythonSeq.h" #include "KX_SCA_AddObjectActuator.h" #include "KX_SCA_EndObjectActuator.h" #include "KX_SCA_ReplaceMeshActuator.h" @@ -84,6 +85,7 @@ #include "SCA_PropertySensor.h" #include "SCA_PythonController.h" #include "SCA_RandomActuator.h" +#include "SCA_IController.h" void initPyObjectPlusType(PyTypeObject **parents) @@ -225,9 +227,10 @@ void initPyTypes(void) PyType_Ready_Attr(dict, SCA_RandomSensor); PyType_Ready_Attr(dict, SCA_XNORController); PyType_Ready_Attr(dict, SCA_XORController); + PyType_Ready_Attr(dict, SCA_IController); - - + /* Normal python type */ + PyType_Ready(&KX_PythonSeq_Type); } #endif
\ No newline at end of file diff --git a/source/gameengine/Ketsji/KX_PythonSeq.cpp b/source/gameengine/Ketsji/KX_PythonSeq.cpp new file mode 100644 index 00000000000..cc8021fc2e4 --- /dev/null +++ b/source/gameengine/Ketsji/KX_PythonSeq.cpp @@ -0,0 +1,382 @@ +/** + * $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: none of this file. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + * Readonly sequence wrapper for lookups on logic bricks + */ + + +#include "KX_PythonSeq.h" +#include "KX_GameObject.h" +#include "SCA_ISensor.h" +#include "SCA_IController.h" +#include "SCA_IActuator.h" + + +PyObject *KX_PythonSeq_CreatePyObject( PyObject *base, short type ) +{ + KX_PythonSeq *seq = PyObject_NEW( KX_PythonSeq, &KX_PythonSeq_Type); + seq->base = base; + Py_INCREF(base); /* so we can always access to check if its valid */ + seq->type = type; + seq->iter = -1; /* init */ + return (PyObject *)seq; + } + + static void KX_PythonSeq_dealloc( KX_PythonSeq * self ) +{ + Py_DECREF(self->base); + PyObject_DEL( self ); +} + +static Py_ssize_t KX_PythonSeq_len( PyObject * self ) +{ + PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); + + if(self_plus==NULL) { + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return -1; + } + + switch(((KX_PythonSeq *)self)->type) { + case KX_PYGENSEQ_CONT_TYPE_SENSORS: + return ((SCA_IController *)self_plus)->GetLinkedSensors().size(); + case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: + return ((SCA_IController *)self_plus)->GetLinkedActuators().size(); + case KX_PYGENSEQ_OB_TYPE_SENSORS: + return ((KX_GameObject *)self_plus)->GetSensors().size(); + case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: + return ((KX_GameObject *)self_plus)->GetControllers().size(); + case KX_PYGENSEQ_OB_TYPE_ACTUATORS: + return ((KX_GameObject *)self_plus)->GetActuators().size(); + default: + /* Should never happen */ + PyErr_SetString(PyExc_SystemError, "invalid type, internal error"); + return -1; + } +} + +static PyObject *KX_PythonSeq_getIndex(PyObject* self, int index) +{ + PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); + + if(self_plus==NULL) { + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return NULL; + } + + switch(((KX_PythonSeq *)self)->type) { + case KX_PYGENSEQ_CONT_TYPE_SENSORS: + { + vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors(); + if(index<0) index += linkedsensors.size(); + if(index<0 || index>= linkedsensors.size()) { + PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); + return NULL; + } + return linkedsensors[index]->GetProxy(); + } + case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: + { + vector<SCA_IActuator*>& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators(); + if(index<0) index += linkedactuators.size(); + if(index<0 || index>= linkedactuators.size()) { + PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); + return NULL; + } + return linkedactuators[index]->GetProxy(); + } + case KX_PYGENSEQ_OB_TYPE_SENSORS: + { + SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors(); + if(index<0) index += linkedsensors.size(); + if(index<0 || index>= linkedsensors.size()) { + PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); + return NULL; + } + return linkedsensors[index]->GetProxy(); + } + case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: + { + SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers(); + if(index<0) index += linkedcontrollers.size(); + if(index<0 || index>= linkedcontrollers.size()) { + PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); + return NULL; + } + return linkedcontrollers[index]->GetProxy(); + } + case KX_PYGENSEQ_OB_TYPE_ACTUATORS: + { + SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators(); + if(index<0) index += linkedactuators.size(); + if(index<0 || index>= linkedactuators.size()) { + PyErr_SetString(PyExc_IndexError, "seq[i]: index out of range"); + return NULL; + } + return linkedactuators[index]->GetProxy(); + } + } + + PyErr_SetString(PyExc_SystemError, "invalid sequence type, this is a bug"); + return NULL; +} + + +static PyObject * KX_PythonSeq_subscript(PyObject * self, PyObject *key) +{ + PyObjectPlus *self_plus= BGE_PROXY_REF(((KX_PythonSeq *)self)->base); + char *name = NULL; + + if(self_plus==NULL) { + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return NULL; + } + + if (PyInt_Check(key)) { + return KX_PythonSeq_getIndex(self, PyInt_AS_LONG( key )); + } else if ( PyString_Check(key) ) { + name = PyString_AsString( key ); + } else { + PyErr_SetString( PyExc_TypeError, "expected a string or an index" ); + return NULL; + } + + switch(((KX_PythonSeq *)self)->type) { + case KX_PYGENSEQ_CONT_TYPE_SENSORS: + { + vector<SCA_ISensor*>& linkedsensors = ((SCA_IController *)self_plus)->GetLinkedSensors(); + SCA_ISensor* sensor; + for (unsigned int index=0;index<linkedsensors.size();index++) { + sensor = linkedsensors[index]; + if (sensor->GetName() == name) + return sensor->GetProxy(); + } + break; + } + case KX_PYGENSEQ_CONT_TYPE_ACTUATORS: + { + vector<SCA_IActuator*>& linkedactuators = ((SCA_IController *)self_plus)->GetLinkedActuators(); + SCA_IActuator* actuator; + for (unsigned int index=0;index<linkedactuators.size();index++) { + actuator = linkedactuators[index]; + if (actuator->GetName() == name) + return actuator->GetProxy(); + } + break; + } + case KX_PYGENSEQ_OB_TYPE_SENSORS: + { + SCA_SensorList& linkedsensors= ((KX_GameObject *)self_plus)->GetSensors(); + SCA_ISensor *sensor; + for (unsigned int index=0;index<linkedsensors.size();index++) { + sensor= linkedsensors[index]; + if (sensor->GetName() == name) + return sensor->GetProxy(); + } + break; + } + case KX_PYGENSEQ_OB_TYPE_CONTROLLERS: + { + SCA_ControllerList& linkedcontrollers= ((KX_GameObject *)self_plus)->GetControllers(); + SCA_IController *controller; + for (unsigned int index=0;index<linkedcontrollers.size();index++) { + controller= linkedcontrollers[index]; + if (controller->GetName() == name) + return controller->GetProxy(); + } + break; + } + case KX_PYGENSEQ_OB_TYPE_ACTUATORS: + { + SCA_ActuatorList& linkedactuators= ((KX_GameObject *)self_plus)->GetActuators(); + SCA_IActuator *actuator; + for (unsigned int index=0;index<linkedactuators.size();index++) { + actuator= linkedactuators[index]; + if (actuator->GetName() == name) + return actuator->GetProxy(); + } + break; + } + } + + PyErr_Format( PyExc_KeyError, "requested item \"%s\" does not exist", name); + return NULL; +} + +static PyMappingMethods KX_PythonSeq_as_mapping = { + KX_PythonSeq_len, /* mp_length */ + KX_PythonSeq_subscript, /* mp_subscript */ + 0, /* mp_ass_subscript */ +}; + + +/* + * Initialize the interator index + */ + +static PyObject *KX_PythonSeq_getIter(KX_PythonSeq *self) +{ + if(BGE_PROXY_REF(self->base)==NULL) { + PyErr_SetString(PyExc_SystemError, BGE_PROXY_ERROR_MSG); + return NULL; + } + + /* create a new iterator if were alredy using this one */ + if (self->iter == -1) { + self->iter = 0; + Py_INCREF(self); + return (PyObject *)self; + } else { + return KX_PythonSeq_CreatePyObject(self->base, self->type); + } + } + + +/* + * Return next KX_PythonSeq iter. + */ + +static PyObject *KX_PythonSeq_nextIter(KX_PythonSeq *self) +{ + PyObject *object = KX_PythonSeq_getIndex((PyObject *)self, self->iter); + + self->iter++; + if( object==NULL ) { + self->iter= -1; /* for reuse */ + PyErr_SetString(PyExc_StopIteration, "iterator at end"); + } + return object; /* can be NULL for end of iterator */ +} + + +static int KX_PythonSeq_compare( KX_PythonSeq * a, KX_PythonSeq * b ) /* TODO - python3.x wants richcmp */ +{ + return ( a->type == b->type && a->base == b->base) ? 0 : -1; +} + +/* + * repr function + * convert to a list and get its string value + */ +static PyObject *KX_PythonSeq_repr( KX_PythonSeq * self ) +{ + PyObject *list = PySequence_List((PyObject *)self); + PyObject *repr = PyObject_Repr(list); + Py_DECREF(list); + return repr; +} + + +/*****************************************************************************/ +/* Python KX_PythonSeq_Type structure definition: */ +/*****************************************************************************/ +PyTypeObject KX_PythonSeq_Type = { +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif + /* For printing, in format "<module>.<name>" */ + "KX_PythonSeq", /* char *tp_name; */ + sizeof( KX_PythonSeq ), /* int tp_basicsize; */ + 0, /* tp_itemsize; For allocation */ + + /* Methods to implement standard operations */ + + ( destructor ) KX_PythonSeq_dealloc, /* destructor tp_dealloc; */ + NULL, /* printfunc tp_print; */ + NULL, /* getattrfunc tp_getattr; */ + NULL, /* setattrfunc tp_setattr; */ + ( cmpfunc ) KX_PythonSeq_compare, /* cmpfunc tp_compare; */ + ( reprfunc ) KX_PythonSeq_repr, /* reprfunc tp_repr; */ + + /* Method suites for standard classes */ + + NULL, /* PyNumberMethods *tp_as_number; */ + NULL, /* PySequenceMethods *tp_as_sequence; */ + &KX_PythonSeq_as_mapping, /* PyMappingMethods *tp_as_mapping; */ + + /* More standard operations (here for binary compatibility) */ + + NULL, /* hashfunc tp_hash; */ + NULL, /* ternaryfunc tp_call; */ + NULL, /* reprfunc tp_str; */ + NULL, /* getattrofunc tp_getattro; */ + NULL, /* setattrofunc tp_setattro; */ + + /* Functions to access object as input/output buffer */ + NULL, /* PyBufferProcs *tp_as_buffer; */ + + /*** Flags to define presence of optional/expanded features ***/ + Py_TPFLAGS_DEFAULT, /* long tp_flags; */ + + NULL, /* char *tp_doc; Documentation string */ + /*** Assigned meaning in release 2.0 ***/ + /* call function for all accessible objects */ + NULL, /* traverseproc tp_traverse; */ + + /* delete references to contained objects */ + NULL, /* inquiry tp_clear; */ + + /*** Assigned meaning in release 2.1 ***/ + /*** rich comparisons ***/ + NULL, /* richcmpfunc tp_richcompare; */ + + /*** weak reference enabler ***/ + 0, /* long tp_weaklistoffset; */ + + /*** Added in release 2.2 ***/ + /* Iterators */ + ( getiterfunc) KX_PythonSeq_getIter, /* getiterfunc tp_iter; */ + ( iternextfunc ) KX_PythonSeq_nextIter, /* iternextfunc tp_iternext; */ + + /*** Attribute descriptor and subclassing stuff ***/ + NULL, /* struct PyMethodDef *tp_methods; */ + NULL, /* struct PyMemberDef *tp_members; */ + NULL, /* struct PyGetSetDef *tp_getset; */ + NULL, /* struct _typeobject *tp_base; */ + NULL, /* PyObject *tp_dict; */ + NULL, /* descrgetfunc tp_descr_get; */ + NULL, /* descrsetfunc tp_descr_set; */ + 0, /* long tp_dictoffset; */ + NULL, /* initproc tp_init; */ + NULL, /* allocfunc tp_alloc; */ + NULL, /* newfunc tp_new; */ + /* Low-level free-memory routine */ + NULL, /* freefunc tp_free; */ + /* For PyObject_IS_GC */ + NULL, /* inquiry tp_is_gc; */ + NULL, /* PyObject *tp_bases; */ + /* method resolution order */ + NULL, /* PyObject *tp_mro; */ + NULL, /* PyObject *tp_cache; */ + NULL, /* PyObject *tp_subclasses; */ + NULL, /* PyObject *tp_weaklist; */ + NULL +}; diff --git a/source/gameengine/Ketsji/KX_PythonSeq.h b/source/gameengine/Ketsji/KX_PythonSeq.h new file mode 100644 index 00000000000..15a016224a9 --- /dev/null +++ b/source/gameengine/Ketsji/KX_PythonSeq.h @@ -0,0 +1,60 @@ +/** + * $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): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + * Readonly sequence wrapper for lookups on logic bricks + */ + +#ifndef _adr_py_seq_h_ // only process once, +#define _adr_py_seq_h_ // even if multiply included + +#include "PyObjectPlus.h" + +// ------------------------- +enum KX_PYGENSEQ_TYPE { + KX_PYGENSEQ_CONT_TYPE_SENSORS, + KX_PYGENSEQ_CONT_TYPE_ACTUATORS, + KX_PYGENSEQ_OB_TYPE_SENSORS, + KX_PYGENSEQ_OB_TYPE_CONTROLLERS, + KX_PYGENSEQ_OB_TYPE_ACTUATORS +}; + +/* The Main PyType Object defined in Main.c */ +extern PyTypeObject KX_PythonSeq_Type; + +#define BPy_KX_PythonSeq_Check(v) \ + ((v)->ob_type == &KX_PythonSeq_Type) + +typedef struct { + PyObject_VAR_HEAD + PyObject *base; + short type; + short iter; +} KX_PythonSeq; + +PyObject *KX_PythonSeq_CreatePyObject(PyObject *base, short type); + +#endif // _adr_py_seq_h_ diff --git a/source/gameengine/Ketsji/KX_RadarSensor.cpp b/source/gameengine/Ketsji/KX_RadarSensor.cpp index 8277e7ef19c..064dc9126ac 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.cpp +++ b/source/gameengine/Ketsji/KX_RadarSensor.cpp @@ -30,6 +30,7 @@ #include "KX_GameObject.h" #include "KX_PyMath.h" #include "PHY_IPhysicsController.h" +#include "PHY_IMotionState.h" #ifdef HAVE_CONFIG_H #include <config.h> @@ -66,7 +67,7 @@ KX_RadarSensor::KX_RadarSensor(SCA_EventManager* eventmgr, m_coneheight(coneheight), m_axis(axis) { - m_client_info->m_type = KX_ClientObjectInfo::RADAR; + m_client_info->m_type = KX_ClientObjectInfo::SENSOR; //m_client_info->m_clientobject = gameobj; //m_client_info->m_auxilary_info = NULL; //sumoObj->setClientObject(&m_client_info); @@ -80,35 +81,10 @@ KX_RadarSensor::~KX_RadarSensor() CValue* KX_RadarSensor::GetReplica() { KX_RadarSensor* replica = new KX_RadarSensor(*this); - replica->m_colliders = new CListValue(); - replica->Init(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); - - replica->m_client_info = new KX_ClientObjectInfo(m_client_info->m_gameobject, KX_ClientObjectInfo::RADAR); - - 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! - //>m_sumoObj = new SM_Object(DT_NewCone(m_coneradius, m_coneheight),NULL,NULL,NULL); - //replica->m_sumoObj->setMargin(m_Margin); - //replica->m_sumoObj->setClientObject(replica->m_client_info); - //Wrong: see KX_TouchSensor - //bool parentUpdated = false; - //((KX_GameObject*)replica->GetParent())->GetSGNode()->ComputeWorldTransforms(NULL,parentUpdated); - replica->SynchronizeTransform(); - + replica->ProcessReplica(); return replica; } - /** * Transforms the collision object. A cone is not correctly centered * for usage. */ @@ -188,11 +164,13 @@ void KX_RadarSensor::SynchronizeTransform() if (m_physCtrl) { - 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(); + PHY_IMotionState* motionState = m_physCtrl->GetMotionState(); + const MT_Point3& pos = trans.getOrigin(); + float ori[12]; + trans.getBasis().getValue(ori); + motionState->setWorldPosition(pos[0], pos[1], pos[2]); + motionState->setWorldOrientation(ori); + m_physCtrl->WriteMotionStateToDynamics(true); } } @@ -212,9 +190,9 @@ PyObject* KX_RadarSensor::PyGetConeOrigin() { PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_cone_origin[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_cone_origin[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_cone_origin[2])); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_cone_origin[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_cone_origin[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_cone_origin[2])); return retVal; } @@ -228,9 +206,9 @@ PyObject* KX_RadarSensor::PyGetConeTarget() { PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_cone_target[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_cone_target[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_cone_target[2])); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_cone_target[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_cone_target[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_cone_target[2])); return retVal; } @@ -251,8 +229,13 @@ PyObject* KX_RadarSensor::PyGetConeHeight() { /* Python Integration Hooks */ /* ------------------------------------------------------------------------- */ PyTypeObject KX_RadarSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_RadarSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -294,6 +277,7 @@ PyMethodDef KX_RadarSensor::Methods[] = { PyAttributeDef KX_RadarSensor::Attributes[] = { KX_PYATTRIBUTE_FLOAT_ARRAY_RO("coneOrigin", KX_RadarSensor, m_cone_origin, 3), KX_PYATTRIBUTE_FLOAT_ARRAY_RO("coneTarget", KX_RadarSensor, m_cone_target, 3), + KX_PYATTRIBUTE_FLOAT_RO("distance", KX_RadarSensor, m_coneheight), KX_PYATTRIBUTE_FLOAT_RW("angle", 0, 360, KX_RadarSensor, m_coneradius), KX_PYATTRIBUTE_INT_RW("axis", 0, 5, true, KX_RadarSensor, m_axis), {NULL} //Sentinel @@ -304,6 +288,10 @@ PyObject* KX_RadarSensor::py_getattro(PyObject *attr) py_getattro_up(KX_NearSensor); } +PyObject* KX_RadarSensor::py_getattro_dict() { + py_getattro_dict_up(KX_NearSensor); +} + int KX_RadarSensor::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(KX_NearSensor); diff --git a/source/gameengine/Ketsji/KX_RadarSensor.h b/source/gameengine/Ketsji/KX_RadarSensor.h index c3a941696ce..2e5a0e68bed 100644 --- a/source/gameengine/Ketsji/KX_RadarSensor.h +++ b/source/gameengine/Ketsji/KX_RadarSensor.h @@ -90,7 +90,9 @@ public: }; virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); + virtual sensortype GetSensorType() { return ST_RADAR; } //Deprecated -----> KX_PYMETHOD_DOC_NOARGS(KX_RadarSensor,GetConeOrigin); diff --git a/source/gameengine/Ketsji/KX_RayEventManager.cpp b/source/gameengine/Ketsji/KX_RayEventManager.cpp index 1af29151adf..50fa4f5e310 100644 --- a/source/gameengine/Ketsji/KX_RayEventManager.cpp +++ b/source/gameengine/Ketsji/KX_RayEventManager.cpp @@ -44,9 +44,10 @@ using namespace std; void KX_RayEventManager::NextFrame() { - for (set<class SCA_ISensor*>::const_iterator i= m_sensors.begin();!(i==m_sensors.end());i++) + SG_DList::iterator<SCA_ISensor> it(m_sensors); + for (it.begin();!it.end();++it) { - (*i)->Activate(m_logicmgr, NULL); + (*it)->Activate(m_logicmgr); } } diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index 06c04dbf10d..78a61e9d95e 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -88,8 +88,7 @@ KX_RaySensor::~KX_RaySensor() CValue* KX_RaySensor::GetReplica() { KX_RaySensor* replica = new KX_RaySensor(*this); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); replica->Init(); return replica; @@ -179,7 +178,7 @@ bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo* client) return true; } -bool KX_RaySensor::Evaluate(CValue* event) +bool KX_RaySensor::Evaluate() { bool result = false; bool reset = m_reset && m_level; @@ -321,8 +320,13 @@ bool KX_RaySensor::Evaluate(CValue* event) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_RaySensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_RaySensor", sizeof(PyObjectPlus_Proxy), 0, @@ -362,7 +366,7 @@ PyAttributeDef KX_RaySensor::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("useMaterial", KX_RaySensor, m_bFindMaterial), KX_PYATTRIBUTE_BOOL_RW("useXRay", KX_RaySensor, m_bXRay), KX_PYATTRIBUTE_FLOAT_RW("range", 0, 10000, KX_RaySensor, m_distance), - KX_PYATTRIBUTE_STRING_RW("property", 0, 100, false, KX_RaySensor, m_propertyname), + KX_PYATTRIBUTE_STRING_RW("propName", 0, 100, false, KX_RaySensor, m_propertyname), KX_PYATTRIBUTE_INT_RW("axis", 0, 5, true, KX_RaySensor, m_axis), KX_PYATTRIBUTE_FLOAT_ARRAY_RO("hitPosition", KX_RaySensor, m_hitPosition, 3), KX_PYATTRIBUTE_FLOAT_ARRAY_RO("rayDirection", KX_RaySensor, m_rayDirection, 3), @@ -404,9 +408,9 @@ PyObject* KX_RaySensor::PyGetHitPosition() PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_hitPosition[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_hitPosition[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_hitPosition[2])); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_hitPosition[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_hitPosition[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_hitPosition[2])); return retVal; } @@ -420,9 +424,9 @@ PyObject* KX_RaySensor::PyGetRayDirection() PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_rayDirection[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_rayDirection[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_rayDirection[2])); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_rayDirection[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_rayDirection[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_rayDirection[2])); return retVal; } @@ -436,9 +440,9 @@ PyObject* KX_RaySensor::PyGetHitNormal() PyObject *retVal = PyList_New(3); - PyList_SetItem(retVal, 0, PyFloat_FromDouble(m_hitNormal[0])); - PyList_SetItem(retVal, 1, PyFloat_FromDouble(m_hitNormal[1])); - PyList_SetItem(retVal, 2, PyFloat_FromDouble(m_hitNormal[2])); + PyList_SET_ITEM(retVal, 0, PyFloat_FromDouble(m_hitNormal[0])); + PyList_SET_ITEM(retVal, 1, PyFloat_FromDouble(m_hitNormal[1])); + PyList_SET_ITEM(retVal, 2, PyFloat_FromDouble(m_hitNormal[2])); return retVal; } @@ -449,6 +453,10 @@ PyObject* KX_RaySensor::py_getattro(PyObject *attr) { py_getattro_up(SCA_ISensor); } +PyObject* KX_RaySensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int KX_RaySensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); } diff --git a/source/gameengine/Ketsji/KX_RaySensor.h b/source/gameengine/Ketsji/KX_RaySensor.h index a5d7d15c60c..9efb046742f 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.h +++ b/source/gameengine/Ketsji/KX_RaySensor.h @@ -67,7 +67,7 @@ public: virtual ~KX_RaySensor(); virtual CValue* GetReplica(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual bool IsPositiveTrigger(); virtual void Init(); @@ -87,6 +87,7 @@ public: virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); // Deprecated -----> diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index c45d89a2815..75435b97797 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -86,7 +86,7 @@ KX_SCA_AddObjectActuator::~KX_SCA_AddObjectActuator() if (m_OriginalObject) m_OriginalObject->UnregisterActuator(this); if (m_lastCreatedObject) - m_lastCreatedObject->Release(); + m_lastCreatedObject->UnregisterActuator(this); } @@ -124,7 +124,6 @@ CValue* KX_SCA_AddObjectActuator::GetReplica() // this will copy properties and so on... replica->ProcessReplica(); - CValue::AddDataToReplica(replica); return replica; } @@ -145,6 +144,12 @@ bool KX_SCA_AddObjectActuator::UnlinkObject(SCA_IObject* clientobj) m_OriginalObject = NULL; return true; } + if (clientobj == m_lastCreatedObject) + { + // this object is being deleted, we cannot continue to track it. + m_lastCreatedObject = NULL; + return true; + } return false; } @@ -166,8 +171,13 @@ void KX_SCA_AddObjectActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_SCA_AddObjectActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_SCA_AddObjectActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -231,7 +241,7 @@ int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYAT KX_GameObject *gameobj; if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SCA_AddObjectActuator")) - return 1; // ConvertPythonToGameObject sets the error + return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error if (actuator->m_OriginalObject != NULL) actuator->m_OriginalObject->UnregisterActuator(actuator); @@ -241,7 +251,7 @@ int KX_SCA_AddObjectActuator::pyattr_set_object(void *self, const struct KX_PYAT if (actuator->m_OriginalObject) actuator->m_OriginalObject->RegisterActuator(actuator); - return 0; + return PY_SET_ATTR_SUCCESS; } PyObject* KX_SCA_AddObjectActuator::pyattr_get_objectLastCreated(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) @@ -259,6 +269,10 @@ PyObject* KX_SCA_AddObjectActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* KX_SCA_AddObjectActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_SCA_AddObjectActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); @@ -347,7 +361,7 @@ PyObject* KX_SCA_AddObjectActuator::PyGetObject(PyObject* args) Py_RETURN_NONE; if (ret_name_only) - return PyString_FromString(m_OriginalObject->GetName()); + return PyString_FromString(m_OriginalObject->GetName().ReadPtr()); else return m_OriginalObject->GetProxy(); } @@ -455,13 +469,21 @@ void KX_SCA_AddObjectActuator::InstantAddObject() // keep a copy of the last object, to allow python scripters to change it if (m_lastCreatedObject) { - //careful with destruction, it might still have outstanding collision callbacks - m_scene->DelayedReleaseObject(m_lastCreatedObject); - m_lastCreatedObject->Release(); + //Let's not keep a reference to the object: it's bad, if the object is deleted + //this will force to keep a "zombie" in the game for no good reason. + //m_scene->DelayedReleaseObject(m_lastCreatedObject); + //m_lastCreatedObject->Release(); + + //Instead we use the registration mechanism + m_lastCreatedObject->UnregisterActuator(this); + m_lastCreatedObject = NULL; } m_lastCreatedObject = replica; - m_lastCreatedObject->AddRef(); + // no reference + //m_lastCreatedObject->AddRef(); + // but registration + m_lastCreatedObject->RegisterActuator(this); // finished using replica? then release it replica->Release(); } diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h index 4ece5a6d83b..6746b7d1bc6 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.h @@ -111,6 +111,7 @@ public: Update(); virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); SCA_IObject* diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index 83dfdc2484c..a50764a54e6 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -50,8 +50,13 @@ PyTypeObject KX_SCA_DynamicActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_SCA_DynamicActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -85,7 +90,7 @@ PyMethodDef KX_SCA_DynamicActuator::Methods[] = { }; PyAttributeDef KX_SCA_DynamicActuator::Attributes[] = { - KX_PYATTRIBUTE_SHORT_RW("operation",0,4,false,KX_SCA_DynamicActuator,m_dyn_operation), + KX_PYATTRIBUTE_SHORT_RW("mode",0,4,false,KX_SCA_DynamicActuator,m_dyn_operation), KX_PYATTRIBUTE_FLOAT_RW("mass",0.0,FLT_MAX,KX_SCA_DynamicActuator,m_setmass), { NULL } //Sentinel }; @@ -96,6 +101,10 @@ PyObject* KX_SCA_DynamicActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* KX_SCA_DynamicActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_SCA_DynamicActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); @@ -112,7 +121,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, setOperation, "\t 3 = disable rigid body\n" "Change the dynamic status of the parent object.\n") { - ShowDeprecationWarning("setOperation()", "the operation property"); + ShowDeprecationWarning("setOperation()", "the mode property"); int dyn_operation; if (!PyArg_ParseTuple(args, "i:setOperation", &dyn_operation)) @@ -132,7 +141,7 @@ KX_PYMETHODDEF_DOC(KX_SCA_DynamicActuator, getOperation, "Returns the operation type of this actuator.\n" ) { - ShowDeprecationWarning("getOperation()", "the operation property"); + ShowDeprecationWarning("getOperation()", "the mode property"); return PyInt_FromLong((long)m_dyn_operation); } @@ -210,10 +219,6 @@ CValue* KX_SCA_DynamicActuator::GetReplica() return NULL; replica->ProcessReplica(); - - // this will copy properties and so on... - CValue::AddDataToReplica(replica); - return replica; }; diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h index 99855124bdb..4add707f8cd 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.h @@ -75,6 +75,7 @@ class KX_SCA_DynamicActuator : public SCA_IActuator virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* 1. setOperation */ diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index 3b42577810e..728254e7f48 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -82,8 +82,6 @@ CValue* KX_SCA_EndObjectActuator::GetReplica() if (replica == NULL) return NULL; replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; }; @@ -94,8 +92,13 @@ CValue* KX_SCA_EndObjectActuator::GetReplica() /* ------------------------------------------------------------------------- */ PyTypeObject KX_SCA_EndObjectActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_SCA_EndObjectActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -136,4 +139,8 @@ PyObject* KX_SCA_EndObjectActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* KX_SCA_EndObjectActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + /* eof */ diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h index 2940246f443..70d72f1f8da 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.h @@ -65,6 +65,7 @@ class KX_SCA_EndObjectActuator : public SCA_IActuator /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); }; /* end of class KX_EditObjectActuator : public SCA_PropertyActuator */ diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index 38f8d581d55..00842d7012a 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -53,8 +53,13 @@ PyTypeObject KX_SCA_ReplaceMeshActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_SCA_ReplaceMeshActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -99,6 +104,10 @@ PyObject* KX_SCA_ReplaceMeshActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* KX_SCA_ReplaceMeshActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_SCA_ReplaceMeshActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); @@ -119,10 +128,10 @@ int KX_SCA_ReplaceMeshActuator::pyattr_set_mesh(void *self, const struct KX_PYAT RAS_MeshObject* new_mesh; if (!ConvertPythonToMesh(value, &new_mesh, true, "actuator.mesh = value: KX_SCA_ReplaceMeshActuator")) - return 1; + return PY_SET_ATTR_FAIL; actuator->m_mesh = new_mesh; - return 0; + return PY_SET_ATTR_SUCCESS; } /* 1. setMesh */ @@ -213,9 +222,6 @@ CValue* KX_SCA_ReplaceMeshActuator::GetReplica() replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); - return replica; }; diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h index 7a18df2356d..0e7f7852701 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.h @@ -72,6 +72,7 @@ class KX_SCA_ReplaceMeshActuator : public SCA_IActuator void InstantReplaceMesh(); virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); static PyObject* pyattr_get_mesh(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp index 0e7571031e8..cb933419c57 100644 --- a/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp +++ b/source/gameengine/Ketsji/KX_SG_BoneParentNodeRelationship.cpp @@ -125,7 +125,9 @@ UpdateChildCoordinates( else { child->SetWorldFromLocalTransform(); } - child->SetModified(false); + child->ClearModified(); + // this node must always be updated, so reschedule it for next time + child->ActivateRecheduleUpdateCallback(); return valid_parent_transform; } diff --git a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp index c3b0c21c8e0..c49b6d671a7 100644 --- a/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp +++ b/source/gameengine/Ketsji/KX_SG_NodeRelationships.cpp @@ -63,7 +63,7 @@ UpdateChildCoordinates( if (parent==NULL) { /* Simple case */ child->SetWorldFromLocalTransform(); - child->SetModified(false); + child->ClearModified(); return true; //false; } else { @@ -75,7 +75,7 @@ UpdateChildCoordinates( child->SetWorldScale(p_world_scale * child->GetLocalScale()); child->SetWorldOrientation(p_world_rotation * child->GetLocalOrientation()); child->SetWorldPosition(p_world_pos + p_world_scale * (p_world_rotation * child->GetLocalPosition())); - child->SetModified(false); + child->ClearModified(); return true; } } @@ -137,7 +137,7 @@ UpdateChildCoordinates( child->SetWorldPosition(child->GetLocalPosition()); child->SetWorldOrientation(child->GetLocalOrientation()); - child->SetModified(false); + child->ClearModified(); return true; //parent != NULL; } @@ -259,7 +259,9 @@ UpdateChildCoordinates( child->SetWorldScale(child_w_scale); child->SetWorldPosition(child_w_pos); child->SetWorldOrientation(child_w_rotation); - child->SetModified(false); + child->ClearModified(); + // this node must always be updated, so reschedule it for next time + child->ActivateRecheduleUpdateCallback(); return true; //parent != NULL; } diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index aa7bd65f240..c0d8a7090c4 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -34,7 +34,7 @@ #include "KX_Scene.h" #include "MT_assert.h" - +#include "SND_Scene.h" #include "KX_KetsjiEngine.h" #include "KX_BlenderMaterial.h" #include "RAS_IPolygonMaterial.h" @@ -80,6 +80,7 @@ #include "KX_BlenderSceneConverter.h" #include "KX_MotionState.h" +#include "BL_ModifierDeformer.h" #include "BL_ShapeDeformer.h" #include "BL_DeformableGameObject.h" @@ -110,7 +111,22 @@ void* KX_SceneDestructionFunc(SG_IObject* node,void* gameobj,void* scene) return NULL; }; -SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks(KX_SceneReplicationFunc,KX_SceneDestructionFunc,KX_GameObject::UpdateTransformFunc); +bool KX_Scene::KX_ScenegraphUpdateFunc(SG_IObject* node,void* gameobj,void* scene) +{ + return ((SG_Node*)node)->Schedule(((KX_Scene*)scene)->m_sghead); +} + +bool KX_Scene::KX_ScenegraphRescheduleFunc(SG_IObject* node,void* gameobj,void* scene) +{ + return ((SG_Node*)node)->Reschedule(((KX_Scene*)scene)->m_sghead); +} + +SG_Callbacks KX_Scene::m_callbacks = SG_Callbacks( + KX_SceneReplicationFunc, + KX_SceneDestructionFunc, + KX_GameObject::UpdateTransformFunc, + KX_Scene::KX_ScenegraphUpdateFunc, + KX_Scene::KX_ScenegraphRescheduleFunc); // temporarily var until there is a button in the userinterface // (defined in KX_PythonInit.cpp) @@ -148,7 +164,6 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_lightlist= new CListValue(); m_inactivelist = new CListValue(); m_euthanasyobjects = new CListValue(); - m_delayReleaseObjects = new CListValue(); m_logicmgr = new SCA_LogicManager(); @@ -192,9 +207,6 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_rootnode = NULL; m_bucketmanager=new RAS_BucketManager(); - - m_canvasDesignWidth = 0; - m_canvasDesignHeight = 0; m_attr_dict = PyDict_New(); /* new ref */ } @@ -231,8 +243,6 @@ KX_Scene::~KX_Scene() if (m_euthanasyobjects) m_euthanasyobjects->Release(); - if (m_delayReleaseObjects) - m_delayReleaseObjects->Release(); if (m_logicmgr) delete m_logicmgr; @@ -254,13 +264,6 @@ KX_Scene::~KX_Scene() Py_DECREF(m_attr_dict); } -void KX_Scene::SetProjectionMatrix(MT_CmMatrix4x4& pmat) -{ - m_projectionmat = pmat; -} - - - RAS_BucketManager* KX_Scene::GetBucketManager() { return m_bucketmanager; @@ -408,11 +411,11 @@ void KX_Scene::RemoveNodeDestructObject(class SG_IObject* node,class CValue* gam KX_GameObject* orgobj = (KX_GameObject*)gameobj; if (NewRemoveObject(orgobj) != 0) { - // object is not yet deleted (this can happen when it hangs in an add object actuator - // last object created reference. It's a bad situation, don't know how to fix it exactly - // The least I can do, is remove the reference to the node in the object as the node - // will in any case be deleted. This ensures that the object will not try to use the node - // when it is finally deleted (see KX_GameObject destructor) + // object is not yet deleted because a reference is hanging somewhere. + // This should not happen anymore since we use proxy object for Python + // confident enough to put an assert? + //assert(false); + printf("Zombie object! name=%s\n", orgobj->GetName().ReadPtr()); orgobj->SetSGNode(NULL); PHY_IGraphicController* ctrl = orgobj->GetGraphicController(); if (ctrl) @@ -477,6 +480,8 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal // this is the list of object that are send to the graphics pipeline m_objectlist->Add(newobj->AddRef()); + if (newobj->IsLight()) + m_lightlist->Add(newobj->AddRef()); newobj->AddMeshUser(); // logic cannot be replicated, until the whole hierarchy is replicated. @@ -537,8 +542,9 @@ void KX_Scene::ReplicateLogic(KX_GameObject* newobj) vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators(); // disconnect the sensors and actuators - cont->UnlinkAllSensors(); - cont->UnlinkAllActuators(); + // do it directly on the list at this controller is not connected to anything at this stage + cont->GetLinkedSensors().clear(); + cont->GetLinkedActuators().clear(); // now relink each sensor for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());its++) @@ -716,16 +722,20 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // 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 offset(group->dupli_ofs); MT_Point3 newpos = groupobj->NodeGetWorldPosition() + newscale*(groupobj->NodeGetWorldOrientation() * (gameobj->NodeGetWorldPosition()-offset)); replica->NodeSetLocalPosition(newpos); - + // set the orientation after position for softbody! + MT_Matrix3x3 newori = groupobj->NodeGetWorldOrientation() * gameobj->NodeGetWorldOrientation(); + replica->NodeSetLocalOrientation(newori); + // update scenegraph for entire tree of children replica->GetSGNode()->UpdateWorldData(0); replica->GetSGNode()->SetBBox(gameobj->GetSGNode()->BBox()); replica->GetSGNode()->SetRadius(gameobj->GetSGNode()->Radius()); + // we can now add the graphic controller to the physic engine + replica->ActivateGraphicController(true); + // done with replica replica->Release(); } @@ -836,6 +846,8 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, replica->GetSGNode()->UpdateWorldData(0); replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox()); replica->GetSGNode()->SetRadius(originalobj->GetSGNode()->Radius()); + // the size is correct, we can add the graphic controller to the physic engine + replica->ActivateGraphicController(true); // now replicate logic vector<KX_GameObject*>::iterator git; @@ -889,7 +901,7 @@ void KX_Scene::RemoveObject(class CValue* gameobj) { KX_GameObject* newobj = (KX_GameObject*) gameobj; - // first disconnect child from parent + // disconnect child from parent SG_Node* node = newobj->GetSGNode(); if (node) @@ -903,12 +915,6 @@ void KX_Scene::RemoveObject(class CValue* gameobj) //newobj->SetSGNode(0); } -void KX_Scene::DelayedReleaseObject(CValue* gameobj) -{ - m_delayReleaseObjects->Add(gameobj->AddRef()); -} - - void KX_Scene::DelayedRemoveObject(class CValue* gameobj) { //KX_GameObject* newobj = (KX_GameObject*) gameobj; @@ -925,6 +931,13 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) int ret; KX_GameObject* newobj = (KX_GameObject*) gameobj; + /* Invalidate the python reference, since the object may exist in script lists + * its possible that it wont be automatically invalidated, so do it manually here, + * + * if for some reason the object is added back into the scene python can always get a new Proxy + */ + newobj->InvalidateProxy(); + // 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 @@ -954,7 +967,7 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) for (SCA_ActuatorList::iterator ita = actuators.begin(); !(ita==actuators.end());ita++) { - m_logicmgr->RemoveDestroyedActuator(*ita); + m_logicmgr->RemoveActuator(*ita); } // the sensors/controllers/actuators must also be released, this is done in ~SCA_IObject @@ -1038,6 +1051,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) Object* oldblendobj = static_cast<struct Object*>(m_logicmgr->FindBlendObjByGameMeshName(mesh->GetName())); Mesh* blendmesh = mesh->GetMesh(); + bool bHasModifier = BL_ModifierDeformer::HasCompatibleDeformer(blendobj); bool bHasShapeKey = blendmesh->key != NULL && blendmesh->key->type==KEY_RELATIVE; bool bHasDvert = blendmesh->dvert != NULL; bool bHasArmature = @@ -1053,10 +1067,39 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) if (oldblendobj==NULL) { std::cout << "warning: ReplaceMesh() new mesh is not used in an object from the current scene, you will get incorrect behavior" << std::endl; - bHasShapeKey= bHasDvert= bHasArmature= false; + bHasShapeKey= bHasDvert= bHasArmature=bHasModifier= false; } - if (bHasShapeKey) + if (bHasModifier) + { + BL_ModifierDeformer* modifierDeformer; + if (bHasShapeKey || bHasArmature) + { + modifierDeformer = new BL_ModifierDeformer( + newobj, + m_blenderScene, + oldblendobj, blendobj, + static_cast<BL_SkinMeshObject*>(mesh), + true, + static_cast<BL_ArmatureObject*>( parentobj ) + ); + releaseParent= false; + modifierDeformer->LoadShapeDrivers(blendobj->parent); + } + else + { + modifierDeformer = new BL_ModifierDeformer( + newobj, + m_blenderScene, + oldblendobj, blendobj, + static_cast<BL_SkinMeshObject*>(mesh), + false, + NULL + ); + } + newobj->SetDeformer(modifierDeformer); + } + else if (bHasShapeKey) { BL_ShapeDeformer* shapeDeformer; if (bHasArmature) @@ -1066,6 +1109,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) oldblendobj, blendobj, static_cast<BL_SkinMeshObject*>(mesh), true, + true, static_cast<BL_ArmatureObject*>( parentobj ) ); releaseParent= false; @@ -1078,6 +1122,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) oldblendobj, blendobj, static_cast<BL_SkinMeshObject*>(mesh), false, + true, NULL ); } @@ -1090,6 +1135,7 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) oldblendobj, blendobj, static_cast<BL_SkinMeshObject*>(mesh), true, + true, static_cast<BL_ArmatureObject*>( parentobj ) ); releaseParent= false; @@ -1112,24 +1158,6 @@ void KX_Scene::ReplaceMesh(class CValue* obj,void* meshobj) gameobj->AddMeshUser(); } - - -MT_CmMatrix4x4& KX_Scene::GetViewMatrix() -{ - MT_Scalar cammat[16]; - m_active_camera->GetWorldToCamera().getValue(cammat); - m_viewmat = cammat; - return m_viewmat; -} - - - -MT_CmMatrix4x4& KX_Scene::GetProjectionMatrix() -{ - return m_projectionmat; -} - - KX_Camera* KX_Scene::FindCamera(KX_Camera* cam) { list<KX_Camera*>::iterator it = m_cameras.begin(); @@ -1423,24 +1451,17 @@ void KX_Scene::LogicEndFrame() { m_logicmgr->EndFrame(); int numobj = m_euthanasyobjects->GetCount(); - int i; - for (i = numobj - 1; i >= 0; i--) - { - KX_GameObject* gameobj = (KX_GameObject*)m_euthanasyobjects->GetValue(i); - // KX_Scene::RemoveObject will also remove the object from this list - // that's why we start from the end - this->RemoveObject(gameobj); - } - numobj= m_delayReleaseObjects->GetCount(); - for (i = numobj-1;i>=0;i--) + KX_GameObject* obj; + + while ((numobj = m_euthanasyobjects->GetCount()) > 0) { - KX_GameObject* gameobj = (KX_GameObject*)m_delayReleaseObjects->GetValue(i); - // This list is not for object removal, but just object release - gameobj->Release(); + // remove the object from this list to make sure we will not hit it again + obj = (KX_GameObject*)m_euthanasyobjects->GetValue(numobj-1); + m_euthanasyobjects->Remove(numobj-1); + obj->Release(); + RemoveObject(obj); } - // empty the list as we have removed all references - m_delayReleaseObjects->Resize(0); } @@ -1450,15 +1471,28 @@ void KX_Scene::LogicEndFrame() */ void KX_Scene::UpdateParents(double curtime) { -// int numrootobjects = GetRootParentList()->GetCount(); + // we use the SG dynamic list + SG_Node* node; - for (int i=0; i<GetRootParentList()->GetCount(); i++) + while ((node = SG_Node::GetNextScheduled(m_sghead)) != NULL) { - KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i); - parentobj->NodeUpdateGS(curtime); + node->UpdateWorldData(curtime); } -} + //for (int i=0; i<GetRootParentList()->GetCount(); i++) + //{ + // KX_GameObject* parentobj = (KX_GameObject*)GetRootParentList()->GetValue(i); + // parentobj->NodeUpdateGS(curtime); + //} + + // the list must be empty here + assert(m_sghead.Empty()); + // some nodes may be ready for reschedule, move them to schedule list for next time + while ((node = SG_Node::GetNextRescheduled(m_sghead)) != NULL) + { + node->Schedule(m_sghead); + } +} RAS_MaterialBucket* KX_Scene::FindBucket(class RAS_IPolyMaterial* polymat, bool &bucketCreated) @@ -1579,8 +1613,13 @@ double KX_Scene::getSuspendedDelta() //Python PyTypeObject KX_Scene::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_Scene", sizeof(PyObjectPlus_Proxy), 0, @@ -1604,9 +1643,9 @@ PyParentObject KX_Scene::Parents[] = { }; PyMethodDef KX_Scene::Methods[] = { - KX_PYMETHODTABLE(KX_Scene, getLightList), - KX_PYMETHODTABLE(KX_Scene, getObjectList), - KX_PYMETHODTABLE(KX_Scene, getName), + KX_PYMETHODTABLE_NOARGS(KX_Scene, getLightList), + KX_PYMETHODTABLE_NOARGS(KX_Scene, getObjectList), + KX_PYMETHODTABLE_NOARGS(KX_Scene, getName), KX_PYMETHODTABLE(KX_Scene, addObject), {NULL,NULL} //Sentinel @@ -1624,46 +1663,81 @@ PyObject* KX_Scene::pyattr_get_objects(void *self_v, const KX_PYATTRIBUTE_DEF *a return self->GetObjectList()->GetProxy(); } +PyObject* KX_Scene::pyattr_get_objects_inactive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self= static_cast<KX_Scene*>(self_v); + return self->GetInactiveList()->GetProxy(); +} + +PyObject* KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self= static_cast<KX_Scene*>(self_v); + return self->GetLightList()->GetProxy(); +} + +PyObject* KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + /* With refcounts in this case... + * the new CListValue is owned by python, so its possible python holds onto it longer then the BGE + * however this is the same with "scene.objects + []", when you make a copy by adding lists. + */ + + KX_Scene* self= static_cast<KX_Scene*>(self_v); + CListValue* clist = new CListValue(); + + /* return self->GetCameras()->GetProxy(); */ + + list<KX_Camera*>::iterator it = self->GetCameras()->begin(); + while (it != self->GetCameras()->end()) { + clist->Add((*it)->AddRef()); + it++; + } + + return clist->NewProxy(true); +} + PyObject* KX_Scene::pyattr_get_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Scene* self= static_cast<KX_Scene*>(self_v); return self->GetActiveCamera()->GetProxy(); } -/* __dict__ only for the purpose of giving useful dir() results */ -PyObject* KX_Scene::pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) + +int KX_Scene::pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_Scene* self= static_cast<KX_Scene*>(self_v); - /* Useually done by py_getattro_up but in this case we want to include m_attr_dict dict */ - PyObject *dict_str= PyString_FromString("__dict__"); - PyObject *dict= py_getattr_dict(self->PyObjectPlus::py_getattro(dict_str), Type.tp_dict); - Py_DECREF(dict_str); + KX_Camera *camOb; - PyDict_Update(dict, self->m_attr_dict); - return dict; + if (!ConvertPythonToCamera(value, &camOb, false, "scene.active_camera = value: KX_Scene")) + return PY_SET_ATTR_FAIL; + + self->SetActiveCamera(camOb); + return PY_SET_ATTR_SUCCESS; } + PyAttributeDef KX_Scene::Attributes[] = { - KX_PYATTRIBUTE_RO_FUNCTION("name", KX_Scene, pyattr_get_name), - KX_PYATTRIBUTE_RO_FUNCTION("objects", KX_Scene, pyattr_get_objects), - KX_PYATTRIBUTE_RO_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera), - KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), - KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), + KX_PYATTRIBUTE_RO_FUNCTION("name", KX_Scene, pyattr_get_name), + KX_PYATTRIBUTE_RO_FUNCTION("objects", KX_Scene, pyattr_get_objects), + KX_PYATTRIBUTE_RO_FUNCTION("objectsInactive", KX_Scene, pyattr_get_objects_inactive), KX_PYATTRIBUTE_RO_FUNCTION("lights", KX_Scene, pyattr_get_lights), + KX_PYATTRIBUTE_RO_FUNCTION("cameras", KX_Scene, pyattr_get_cameras), + KX_PYATTRIBUTE_RO_FUNCTION("lights", KX_Scene, pyattr_get_lights), + KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera), + KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), + KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius), - KX_PYATTRIBUTE_BOOL_RO("dbvt_culling", KX_Scene, m_dbvt_culling), - KX_PYATTRIBUTE_RO_FUNCTION("__dict__", KX_Scene, pyattr_get_dir_dict), + KX_PYATTRIBUTE_BOOL_RO("dbvt_culling", KX_Scene, m_dbvt_culling), { NULL } //Sentinel }; - PyObject* KX_Scene::py_getattro__internal(PyObject *attr) { py_getattro_up(PyObjectPlus); } -int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *pyvalue) +int KX_Scene::py_setattro__internal(PyObject *attr, PyObject *value) { - return PyObjectPlus::py_setattro(attr, pyvalue); + py_setattro_up(PyObjectPlus); } PyObject* KX_Scene::py_getattro(PyObject *attr) @@ -1685,6 +1759,18 @@ PyObject* KX_Scene::py_getattro(PyObject *attr) return object; } +PyObject* KX_Scene::py_getattro_dict() { + //py_getattro_dict_up(PyObjectPlus); + + PyObject *dict= py_getattr_dict(PyObjectPlus::py_getattro_dict(), Type.tp_dict); + if(dict==NULL) + return NULL; + + /* normally just return this but KX_Scene has some more items */ + + PyDict_Update(dict, m_attr_dict); + return dict; +} int KX_Scene::py_setattro(PyObject *attr, PyObject *value) { @@ -1715,6 +1801,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getLightList, "Returns a list of all lights in the scene.\n" ) { + ShowDeprecationWarning("getLightList()", "the lights property"); return m_lightlist->GetProxy(); } @@ -1723,7 +1810,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getObjectList, "Returns a list of all game objects in the scene.\n" ) { - // ShowDeprecationWarning("getObjectList()", "the objects property"); // XXX Grr, why doesnt this work? + ShowDeprecationWarning("getObjectList()", "the objects property"); return m_objectlist->GetProxy(); } @@ -1732,6 +1819,7 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_Scene, getName, "Returns the name of the scene.\n" ) { + ShowDeprecationWarning("getName()", "the name property"); return PyString_FromString(GetName()); } @@ -1753,5 +1841,9 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time); + + // release here because AddReplicaObject AddRef's + // the object is added to the scene so we dont want python to own a reference + replica->Release(); return replica->GetProxy(); -}
\ No newline at end of file +} diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index a06c66ec5dd..79d3f7fd828 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -32,8 +32,6 @@ #include "KX_PhysicsEngineEnums.h" -#include "MT_CmMatrix4x4.h" - #include <vector> #include <set> #include <list> @@ -43,7 +41,7 @@ #include "SG_IObject.h" #include "SCA_IScene.h" #include "MT_Transform.h" -#include "SND_Scene.h" + #include "RAS_FramingManager.h" #include "RAS_Rect.h" @@ -110,16 +108,16 @@ protected: * LogicEndFrame() via a call to RemoveObject(). */ CListValue* m_euthanasyobjects; - /** - * The list of objects that couldn't be released during logic update. - * for example, AddObject actuator sometimes releases an object that was cached from previous frame - */ - CListValue* m_delayReleaseObjects; CListValue* m_objectlist; CListValue* m_parentlist; // all 'root' parents CListValue* m_lightlist; CListValue* m_inactivelist; // all objects that are not in the active layer + + SG_QList m_sghead; // list of nodes that needs scenegraph update + // the Dlist is not object that must be updated + // the Qlist is for objects that needs to be rescheduled + // for updates after udpate is over (slow parent, bone parent) /** * The tree of objects in the scene. @@ -191,20 +189,6 @@ protected: */ KX_Camera* m_active_camera; - /** - * The projection and view matrices of this scene - * The projection matrix is computed externally by KX_Engine - * The view mat is stored as a side effect of GetViewMatrix() - * and is totally unnessary. - */ - MT_CmMatrix4x4 m_projectionmat; - MT_CmMatrix4x4 m_viewmat; - - /** Desired canvas width set at design time. */ - unsigned int m_canvasDesignWidth; - /** Desired canvas height set at design time. */ - unsigned int m_canvasDesignHeight; - /** * Another temporary variable outstaying its welcome * used in AddReplicaObject to map game objects to their @@ -318,6 +302,8 @@ public: /** * Update all transforms according to the scenegraph. */ + static bool KX_ScenegraphUpdateFunc(SG_IObject* node,void* gameobj,void* scene); + static bool KX_ScenegraphRescheduleFunc(SG_IObject* node,void* gameobj,void* scene); void UpdateParents(double curtime); void DupliGroupRecurse(CValue* gameobj, int level); bool IsObjectInGroup(CValue* gameobj) @@ -335,8 +321,6 @@ public: void RemoveObject(CValue* gameobj); void DelayedRemoveObject(CValue* gameobj); - void DelayedReleaseObject(CValue* gameobj); - int NewRemoveObject(CValue* gameobj); void ReplaceMesh(CValue* gameobj, void* meshobj); @@ -422,25 +406,6 @@ public: class KX_Camera* ); - /** Return the viewmatrix as used by the last frame. */ - MT_CmMatrix4x4& - GetViewMatrix( - ); - - /** - * Return the projectionmatrix as used by the last frame. This is - * set by hand :) - */ - MT_CmMatrix4x4& - GetProjectionMatrix( - ); - - /** Sets the projection matrix. */ - void - SetProjectionMatrix( - MT_CmMatrix4x4& pmat - ); - /** * Activates new desired canvas width set at design time. * @param width The new desired width. @@ -592,14 +557,16 @@ public: /* attributes */ static PyObject* pyattr_get_name(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_objects(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_objects_inactive(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_lights(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_cameras(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); - - /* for dir(), python3 uses __dir__() */ - static PyObject* pyattr_get_dir_dict(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); - + static int pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); virtual PyObject* py_getattro(PyObject *attr); /* name, active_camera, gravity, suspended, viewport, framing, activity_culling, activity_culling_radius */ - virtual int py_setattro(PyObject *attr, PyObject *pyvalue); + virtual PyObject* py_getattro_dict(); + + virtual int py_setattro(PyObject *attr, PyObject *value); virtual int py_delattro(PyObject *attr); virtual PyObject* py_repr(void) { return PyString_FromString(GetName().ReadPtr()); } diff --git a/source/gameengine/Ketsji/KX_SceneActuator.cpp b/source/gameengine/Ketsji/KX_SceneActuator.cpp index f54d8542260..1b790ec9824 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.cpp +++ b/source/gameengine/Ketsji/KX_SceneActuator.cpp @@ -76,9 +76,6 @@ CValue* KX_SceneActuator::GetReplica() { KX_SceneActuator* replica = new KX_SceneActuator(*this); replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); - return replica; } @@ -226,8 +223,13 @@ KX_Scene* KX_SceneActuator::FindScene(char * sceneName) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_SceneActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_SceneActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -262,7 +264,7 @@ PyMethodDef KX_SceneActuator::Methods[] = //Deprecated functions ------> {"setUseRestart", (PyCFunction) KX_SceneActuator::sPySetUseRestart, METH_VARARGS, (PY_METHODCHAR)SetUseRestart_doc}, {"setScene", (PyCFunction) KX_SceneActuator::sPySetScene, METH_VARARGS, (PY_METHODCHAR)SetScene_doc}, - {"setCamera", (PyCFunction) KX_SceneActuator::sPySetCamera, METH_VARARGS, (PY_METHODCHAR)SetCamera_doc}, + {"setCamera", (PyCFunction) KX_SceneActuator::sPySetCamera, METH_O, (PY_METHODCHAR)SetCamera_doc}, {"getUseRestart", (PyCFunction) KX_SceneActuator::sPyGetUseRestart, METH_NOARGS, (PY_METHODCHAR)GetUseRestart_doc}, {"getScene", (PyCFunction) KX_SceneActuator::sPyGetScene, METH_NOARGS, (PY_METHODCHAR)GetScene_doc}, {"getCamera", (PyCFunction) KX_SceneActuator::sPyGetCamera, METH_NOARGS, (PY_METHODCHAR)GetCamera_doc}, @@ -273,6 +275,8 @@ PyMethodDef KX_SceneActuator::Methods[] = PyAttributeDef KX_SceneActuator::Attributes[] = { KX_PYATTRIBUTE_STRING_RW("scene",0,32,true,KX_SceneActuator,m_nextSceneName), KX_PYATTRIBUTE_RW_FUNCTION("camera",KX_SceneActuator,pyattr_get_camera,pyattr_set_camera), + KX_PYATTRIBUTE_BOOL_RW("useRestart", KX_SceneActuator, m_restart), + KX_PYATTRIBUTE_INT_RW("mode", KX_SCENE_NODEF+1, KX_SCENE_MAX-1, true, KX_SceneActuator, m_mode), { NULL } //Sentinel }; @@ -281,6 +285,10 @@ PyObject* KX_SceneActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* KX_SceneActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_SceneActuator::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IActuator); @@ -300,51 +308,21 @@ int KX_SceneActuator::pyattr_set_camera(void *self, const struct KX_PYATTRIBUTE_ KX_SceneActuator* actuator = static_cast<KX_SceneActuator*>(self); KX_Camera *camOb; - if(value==Py_None) - { - if (actuator->m_camera) - actuator->m_camera->UnregisterActuator(actuator); - + if (!ConvertPythonToCamera(value, &camOb, true, "actu.camera = value: KX_SceneActuator")) + return PY_SET_ATTR_FAIL; + + if (actuator->m_camera) + actuator->m_camera->UnregisterActuator(actuator); + + if(camOb==NULL) { actuator->m_camera= NULL; - return 0; } - - if (PyObject_TypeCheck(value, &KX_Camera::Type)) - { - KX_Camera *camOb= static_cast<KX_Camera*>BGE_PROXY_REF(value); - - if(camOb==NULL) - { - PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); - return 1; - } - - if (actuator->m_camera) - actuator->m_camera->UnregisterActuator(actuator); - + else { actuator->m_camera = camOb; actuator->m_camera->RegisterActuator(actuator); - return 0; - } - - if (PyString_Check(value)) - { - char *camName = PyString_AsString(value); - - camOb = actuator->FindCamera(camName); - if (camOb) - { - if (actuator->m_camera) - actuator->m_camera->UnregisterActuator(actuator); - actuator->m_camera = camOb; - actuator->m_camera->RegisterActuator(actuator); - return 0; - } - PyErr_SetString(PyExc_TypeError, "not a valid camera name"); - return 1; } - PyErr_SetString(PyExc_TypeError, "expected a string or a camera object reference"); - return 1; + + return PY_SET_ATTR_SUCCESS; } @@ -355,7 +333,7 @@ const char KX_SceneActuator::SetUseRestart_doc[] = "\tSet flag to 1 to restart the scene.\n" ; PyObject* KX_SceneActuator::PySetUseRestart(PyObject* args) { - ShowDeprecationWarning("setUseRestart()", "(no replacement)"); + ShowDeprecationWarning("setUseRestart()", "the useRestart property"); int boolArg; if (!PyArg_ParseTuple(args, "i:setUseRestart", &boolArg)) @@ -376,7 +354,7 @@ const char KX_SceneActuator::GetUseRestart_doc[] = "\tReturn whether the scene will be restarted.\n" ; PyObject* KX_SceneActuator::PyGetUseRestart() { - ShowDeprecationWarning("getUseRestart()", "(no replacement)"); + ShowDeprecationWarning("getUseRestart()", "the useRestart property"); return PyInt_FromLong(!(m_restart == 0)); } @@ -423,47 +401,24 @@ const char KX_SceneActuator::SetCamera_doc[] = "setCamera(camera)\n" "\t- camera: string\n" "\tSet the camera to switch to.\n" ; -PyObject* KX_SceneActuator::PySetCamera(PyObject* args) +PyObject* KX_SceneActuator::PySetCamera(PyObject* value) { ShowDeprecationWarning("setCamera()", "the camera property"); - PyObject *cam; - if (PyArg_ParseTuple(args, "O!:setCamera", &KX_Camera::Type, &cam)) - { - KX_Camera *new_camera; - - new_camera = static_cast<KX_Camera*>BGE_PROXY_REF(cam); - if(new_camera==NULL) - { - PyErr_SetString(PyExc_RuntimeError, BGE_PROXY_ERROR_MSG); - return NULL; - } - - if (m_camera) - m_camera->UnregisterActuator(this); - - m_camera= new_camera; - - m_camera->RegisterActuator(this); - Py_RETURN_NONE; - } - PyErr_Clear(); - - /* one argument: a scene, ignore the rest */ - char *camName; - if(!PyArg_ParseTuple(args, "s:setCamera", &camName)) - { + KX_Camera *camOb; + + if (!ConvertPythonToCamera(value, &camOb, true, "actu.setCamera(value): KX_SceneActuator")) return NULL; + + if (m_camera) + m_camera->UnregisterActuator(this); + + if(camOb==NULL) { + m_camera= NULL; } - - KX_Camera *camOb = FindCamera(camName); - if (camOb) - { - if (m_camera) - m_camera->UnregisterActuator(this); + else { m_camera = camOb; m_camera->RegisterActuator(this); } - Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_SceneActuator.h b/source/gameengine/Ketsji/KX_SceneActuator.h index 803c5106a60..2412dd02590 100644 --- a/source/gameengine/Ketsji/KX_SceneActuator.h +++ b/source/gameengine/Ketsji/KX_SceneActuator.h @@ -93,6 +93,7 @@ class KX_SceneActuator : public SCA_IActuator /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); /* 1. set */ @@ -107,7 +108,7 @@ class KX_SceneActuator : public SCA_IActuator /* 5. getScene: */ KX_PYMETHOD_DOC_NOARGS(KX_SceneActuator,GetScene); /* 6. setCamera: */ - KX_PYMETHOD_DOC_VARARGS(KX_SceneActuator,SetCamera); + KX_PYMETHOD_DOC_O(KX_SceneActuator,SetCamera); /* 7. getCamera: */ KX_PYMETHOD_DOC_NOARGS(KX_SceneActuator,GetCamera); diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index 412be497c5a..5c02a2db646 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -83,19 +83,19 @@ CValue* KX_SoundActuator::GetReplica() { KX_SoundActuator* replica = new KX_SoundActuator(*this); replica->ProcessReplica(); + return replica; +}; + +void KX_SoundActuator::ProcessReplica() +{ + SCA_IActuator::ProcessReplica(); if (m_soundObject) { SND_SoundObject* soundobj = new SND_SoundObject(*m_soundObject); - replica->setSoundObject(soundobj); + setSoundObject(soundobj); m_soundScene->AddObject(soundobj); } - - // this will copy properties and so on... - CValue::AddDataToReplica(replica); - return replica; -}; - - +} bool KX_SoundActuator::Update(double curtime, bool frame) { @@ -234,8 +234,13 @@ void KX_SoundActuator::setSoundObject(class SND_SoundObject* soundobject) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_SoundActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_SoundActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -290,7 +295,7 @@ PyMethodDef KX_SoundActuator::Methods[] = { }; PyAttributeDef KX_SoundActuator::Attributes[] = { - KX_PYATTRIBUTE_RW_FUNCTION("filename", KX_SoundActuator, pyattr_get_filename, pyattr_set_filename), + KX_PYATTRIBUTE_RW_FUNCTION("fileName", KX_SoundActuator, pyattr_get_filename, pyattr_set_filename), KX_PYATTRIBUTE_RW_FUNCTION("volume", KX_SoundActuator, pyattr_get_gain, pyattr_set_gain), KX_PYATTRIBUTE_RW_FUNCTION("pitch", KX_SoundActuator, pyattr_get_pitch, pyattr_set_pitch), KX_PYATTRIBUTE_RW_FUNCTION("rollOffFactor", KX_SoundActuator, pyattr_get_rollOffFactor, pyattr_set_rollOffFactor), @@ -298,7 +303,7 @@ PyAttributeDef KX_SoundActuator::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("position", KX_SoundActuator, pyattr_get_position, pyattr_set_position), KX_PYATTRIBUTE_RW_FUNCTION("velocity", KX_SoundActuator, pyattr_get_velocity, pyattr_set_velocity), KX_PYATTRIBUTE_RW_FUNCTION("orientation", KX_SoundActuator, pyattr_get_orientation, pyattr_set_orientation), - KX_PYATTRIBUTE_ENUM_RW("type",KX_SoundActuator::KX_SOUNDACT_NODEF+1,KX_SoundActuator::KX_SOUNDACT_MAX-1,false,KX_SoundActuator,m_type), + KX_PYATTRIBUTE_ENUM_RW("mode",KX_SoundActuator::KX_SOUNDACT_NODEF+1,KX_SoundActuator::KX_SOUNDACT_MAX-1,false,KX_SoundActuator,m_type), { NULL } //Sentinel }; @@ -340,6 +345,10 @@ PyObject* KX_SoundActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* KX_SoundActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_SoundActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); } @@ -355,7 +364,7 @@ PyObject* KX_SoundActuator::pyattr_get_filename(void *self, const struct KX_PYAT char* name = objectname.Ptr(); if (!name) { - PyErr_SetString(PyExc_RuntimeError, "value = actuator.filename: KX_SoundActuator, unable to get sound filename"); + PyErr_SetString(PyExc_RuntimeError, "value = actuator.fileName: KX_SoundActuator, unable to get sound fileName"); return NULL; } else return PyString_FromString(name); @@ -441,13 +450,13 @@ int KX_SoundActuator::pyattr_set_filename(void *self, const struct KX_PYATTRIBUT // void *soundPointer = NULL; /*unused*/ if (!PyArg_Parse(value, "s", &soundName)) - return 1; + return PY_SET_ATTR_FAIL; if (actuator->m_soundObject) { actuator->m_soundObject->SetObjectName(soundName); } - return 0; + return PY_SET_ATTR_SUCCESS; } @@ -456,12 +465,12 @@ int KX_SoundActuator::pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DE float gain = 1.0; KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); if (!PyArg_Parse(value, "f", &gain)) - return 1; + return PY_SET_ATTR_FAIL; if (actuator->m_soundObject) actuator->m_soundObject->SetGain(gain); - return 0; + return PY_SET_ATTR_SUCCESS; } int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -469,12 +478,12 @@ int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_D float pitch = 1.0; KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); if (!PyArg_Parse(value, "f", &pitch)) - return 1; + return PY_SET_ATTR_FAIL; if (actuator->m_soundObject) actuator->m_soundObject->SetPitch(pitch); - return 0; + return PY_SET_ATTR_SUCCESS; } int KX_SoundActuator::pyattr_set_rollOffFactor(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -482,12 +491,12 @@ int KX_SoundActuator::pyattr_set_rollOffFactor(void *self, const struct KX_PYATT KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); float rollofffactor = 1.0; if (!PyArg_Parse(value, "f", &rollofffactor)) - return 1; + return PY_SET_ATTR_FAIL; if (actuator->m_soundObject) actuator->m_soundObject->SetRollOffFactor(rollofffactor); - return 0; + return PY_SET_ATTR_SUCCESS; } int KX_SoundActuator::pyattr_set_looping(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -495,12 +504,12 @@ int KX_SoundActuator::pyattr_set_looping(void *self, const struct KX_PYATTRIBUTE KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); int looping = 1; if (!PyArg_Parse(value, "i", &looping)) - return 1; + return PY_SET_ATTR_FAIL; if (actuator->m_soundObject) actuator->m_soundObject->SetLoopMode(looping); - return 0; + return PY_SET_ATTR_SUCCESS; } int KX_SoundActuator::pyattr_set_position(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -510,12 +519,12 @@ int KX_SoundActuator::pyattr_set_position(void *self, const struct KX_PYATTRIBUT KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); if (!PyArg_ParseTuple(value, "fff", &pos[0], &pos[1], &pos[2])) - return 1; + return PY_SET_ATTR_FAIL; if (actuator->m_soundObject) actuator->m_soundObject->SetPosition(MT_Vector3(pos)); - return 0; + return PY_SET_ATTR_SUCCESS; } int KX_SoundActuator::pyattr_set_velocity(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -525,12 +534,12 @@ int KX_SoundActuator::pyattr_set_velocity(void *self, const struct KX_PYATTRIBUT if (!PyArg_ParseTuple(value, "fff", &vel[0], &vel[1], &vel[2])) - return 1; + return PY_SET_ATTR_FAIL; if (actuator->m_soundObject) actuator->m_soundObject->SetVelocity(MT_Vector3(vel)); - return 0; + return PY_SET_ATTR_SUCCESS; } @@ -542,21 +551,22 @@ int KX_SoundActuator::pyattr_set_orientation(void *self, const struct KX_PYATTRI /* if value is not a sequence PyOrientationTo makes an error */ if (!PyOrientationTo(value, rot, "actuator.orientation = value: KX_SoundActuator")) - return NULL; + return PY_SET_ATTR_FAIL; + /* Since not having m_soundObject didn't do anything in the old version, + * it probably should be kept that way */ if (!actuator->m_soundObject) - return 0; /* Since not having m_soundObject didn't do anything in the old version, - * it probably should be kept that way */ + return PY_SET_ATTR_SUCCESS; actuator->m_soundObject->SetOrientation(rot); - return 0; + return PY_SET_ATTR_SUCCESS; } // Deprecated -----> PyObject* KX_SoundActuator::PySetFilename(PyObject* args) { char *soundName = NULL; - ShowDeprecationWarning("setFilename()", "the filename property"); + ShowDeprecationWarning("setFilename()", "the fileName property"); // void *soundPointer = NULL; /*unused*/ if (!PyArg_ParseTuple(args, "s", &soundName)) @@ -567,7 +577,7 @@ PyObject* KX_SoundActuator::PySetFilename(PyObject* args) PyObject* KX_SoundActuator::PyGetFilename() { - ShowDeprecationWarning("getFilename()", "the filename property"); + ShowDeprecationWarning("getFilename()", "the fileName property"); if (!m_soundObject) { return PyString_FromString(""); @@ -576,7 +586,7 @@ PyObject* KX_SoundActuator::PyGetFilename() char* name = objectname.Ptr(); if (!name) { - PyErr_SetString(PyExc_RuntimeError, "Unable to get sound filename"); + PyErr_SetString(PyExc_RuntimeError, "Unable to get sound fileName"); return NULL; } else return PyString_FromString(name); @@ -750,7 +760,7 @@ PyObject* KX_SoundActuator::PySetOrientation(PyObject* args) PyObject* KX_SoundActuator::PySetType(PyObject* args) { int typeArg; - ShowDeprecationWarning("setType()", "the type property"); + ShowDeprecationWarning("setType()", "the mode property"); if (!PyArg_ParseTuple(args, "i:setType", &typeArg)) { return NULL; @@ -766,7 +776,7 @@ PyObject* KX_SoundActuator::PySetType(PyObject* args) PyObject* KX_SoundActuator::PyGetType() { - ShowDeprecationWarning("getType()", "the type property"); + ShowDeprecationWarning("getType()", "the mode property"); return PyInt_FromLong(m_type); } // <----- diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index d5e678bbecd..a7491355667 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -75,12 +75,14 @@ public: virtual bool Update(double curtime, bool frame); CValue* GetReplica(); + void ProcessReplica(); /* -------------------------------------------------------------------- */ /* Python interface --------------------------------------------------- */ /* -------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); KX_PYMETHOD_DOC_NOARGS(KX_SoundActuator, startSound); diff --git a/source/gameengine/Ketsji/KX_StateActuator.cpp b/source/gameengine/Ketsji/KX_StateActuator.cpp index 976e7ea5204..f6979eee0f4 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.cpp +++ b/source/gameengine/Ketsji/KX_StateActuator.cpp @@ -55,6 +55,9 @@ KX_StateActuator::~KX_StateActuator( // intentionally empty } +// used to put state actuator to be executed before any other actuators +SG_QList KX_StateActuator::m_stateActuatorHead; + CValue* KX_StateActuator::GetReplica( void @@ -62,8 +65,6 @@ KX_StateActuator::GetReplica( { KX_StateActuator* replica = new KX_StateActuator(*this); replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; } @@ -72,7 +73,10 @@ KX_StateActuator::Update() { bool bNegativeEvent = IsNegativeEvent(); unsigned int objMask; - + + // execution of state actuator means that we are in the execution phase, reset this pointer + // because all the active actuator of this object will be removed for sure. + m_gameobj->m_firstState = NULL; RemoveAllEvents(); if (bNegativeEvent) return false; @@ -101,6 +105,31 @@ KX_StateActuator::Update() return false; } +// this function is only used to deactivate actuators outside the logic loop +// e.g. when an object is deleted. +void KX_StateActuator::Deactivate() +{ + if (QDelink()) + { + // the actuator was in the active list + if (m_stateActuatorHead.QEmpty()) + // no more state object active + m_stateActuatorHead.Delink(); + } +} + +void KX_StateActuator::Activate(SG_DList& head) +{ + // sort the state actuators per object on the global list + if (QEmpty()) + { + InsertSelfActiveQList(m_stateActuatorHead, &m_gameobj->m_firstState); + // add front to make sure it runs before other actuators + head.AddFront(&m_stateActuatorHead); + } +} + + /* ------------------------------------------------------------------------- */ /* Python functions */ /* ------------------------------------------------------------------------- */ @@ -109,8 +138,13 @@ KX_StateActuator::Update() /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_StateActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_StateActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -156,7 +190,11 @@ PyAttributeDef KX_StateActuator::Attributes[] = { PyObject* KX_StateActuator::py_getattro(PyObject *attr) { py_getattro_up(SCA_IActuator); -}; +} + +PyObject* KX_StateActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} int KX_StateActuator::py_setattro(PyObject *attr, PyObject* value) { diff --git a/source/gameengine/Ketsji/KX_StateActuator.h b/source/gameengine/Ketsji/KX_StateActuator.h index 4a64894259d..a4191a4c5fd 100644 --- a/source/gameengine/Ketsji/KX_StateActuator.h +++ b/source/gameengine/Ketsji/KX_StateActuator.h @@ -33,6 +33,13 @@ #include "SCA_IActuator.h" + +/* + * Use of SG_DList : element of actuator being deactivated + * Head: SCA_LogicManager::m_removedActuators + * Use of SG_QList : element of global activated state actuator list + * Head: KX_StateActuator::m_stateActuatorHead + */ class KX_StateActuator : public SCA_IActuator { Py_Header; @@ -46,6 +53,11 @@ class KX_StateActuator : public SCA_IActuator OP_NEG, OP_COUNT }; + // SG_Dlist: element of objects with active actuators, always put in front of the list + // Head: SCA_LogicManager::m_activeActuators + // SG_QList: Head of active state actuators list globally + // Elements: KX_StateActuator + static SG_QList m_stateActuatorHead; int m_operation; int m_mask; @@ -71,11 +83,15 @@ class KX_StateActuator : public SCA_IActuator virtual bool Update(); + virtual void Deactivate(); + virtual void Activate(SG_DList& head); + /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); //KX_PYMETHOD_DOC KX_PYMETHOD_DOC_VARARGS(KX_StateActuator,SetOperation); diff --git a/source/gameengine/Ketsji/KX_SumoPhysicsController.h b/source/gameengine/Ketsji/KX_SumoPhysicsController.h index 083d89896f6..278994c6ae7 100644 --- a/source/gameengine/Ketsji/KX_SumoPhysicsController.h +++ b/source/gameengine/Ketsji/KX_SumoPhysicsController.h @@ -53,7 +53,7 @@ public: class SM_Object* sumoObj, class PHY_IMotionState* motionstate ,bool dyna) - : KX_IPhysicsController(dyna,false,NULL) , + : KX_IPhysicsController(dyna,false,false,NULL) , SumoPhysicsController(sumoScene,/*solidscene,*/sumoObj,motionstate,dyna) { }; @@ -83,6 +83,7 @@ public: virtual void getOrientation(MT_Quaternion& orn); virtual void setOrientation(const MT_Matrix3x3& orn); + virtual void SetTransform() {} 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 48d4cf59a2b..712a512995e 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp +++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp @@ -85,14 +85,35 @@ bool KX_TouchEventManager::newBroadphaseResponse(void *client_data, PHY_IPhysicsController* ctrl = static_cast<PHY_IPhysicsController*>(object1); KX_ClientObjectInfo* info = (ctrl) ? static_cast<KX_ClientObjectInfo*>(ctrl->getNewClientInfo()) : NULL; // This call back should only be called for controllers of Near and Radar sensor - if (info && - info->m_sensors.size() == 1 && - (info->m_type == KX_ClientObjectInfo::NEAR || - info->m_type == KX_ClientObjectInfo::RADAR)) + if (!info) + return true; + + switch (info->m_type) { - // only one sensor for this type of object - KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(*info->m_sensors.begin()); - return touchsensor->BroadPhaseFilterCollision(object1,object2); + case KX_ClientObjectInfo::SENSOR: + if (info->m_sensors.size() == 1) + { + // only one sensor for this type of object + KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(*info->m_sensors.begin()); + return touchsensor->BroadPhaseFilterCollision(object1,object2); + } + break; + case KX_ClientObjectInfo::OBSENSOR: + case KX_ClientObjectInfo::OBACTORSENSOR: + // this object may have multiple collision sensors, + // check is any of them is interested in this object + for(std::list<SCA_ISensor*>::iterator it = info->m_sensors.begin(); + it != info->m_sensors.end(); + ++it) + { + if ((*it)->GetSensorType() == SCA_ISensor::ST_TOUCH) + { + KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(*it); + if (touchsensor->BroadPhaseSensorFilterCollision(object1, object2)) + return true; + } + } + return false; } return true; } @@ -100,7 +121,7 @@ bool KX_TouchEventManager::newBroadphaseResponse(void *client_data, void KX_TouchEventManager::RegisterSensor(SCA_ISensor* sensor) { KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(sensor); - if (m_sensors.insert(touchsensor).second) + if (m_sensors.AddBack(touchsensor)) // the sensor was effectively inserted, register it touchsensor->RegisterSumo(this); } @@ -108,7 +129,7 @@ void KX_TouchEventManager::RegisterSensor(SCA_ISensor* sensor) void KX_TouchEventManager::RemoveSensor(SCA_ISensor* sensor) { KX_TouchSensor* touchsensor = static_cast<KX_TouchSensor*>(sensor); - if (m_sensors.erase(touchsensor)) + if (touchsensor->Delink()) // the sensor was effectively removed, unregister it touchsensor->UnregisterSumo(this); } @@ -117,12 +138,10 @@ void KX_TouchEventManager::RemoveSensor(SCA_ISensor* sensor) void KX_TouchEventManager::EndFrame() { - set<SCA_ISensor*>::iterator it; - for ( it = m_sensors.begin(); - !(it==m_sensors.end());it++) + SG_DList::iterator<KX_TouchSensor> it(m_sensors); + for (it.begin();!it.end();++it) { - ((KX_TouchSensor*)*it)->EndFrame(); - + (*it)->EndFrame(); } } @@ -130,12 +149,11 @@ void KX_TouchEventManager::EndFrame() void KX_TouchEventManager::NextFrame() { - if (m_sensors.size() > 0) + if (!m_sensors.Empty()) { - set<SCA_ISensor*>::iterator it; - - for (it = m_sensors.begin();!(it==m_sensors.end());++it) - static_cast<KX_TouchSensor*>(*it)->SynchronizeTransform(); + SG_DList::iterator<KX_TouchSensor> it(m_sensors); + for (it.begin();!it.end();++it) + (*it)->SynchronizeTransform(); for (std::set<NewCollision>::iterator cit = m_newCollisions.begin(); cit != m_newCollisions.end(); ++cit) { @@ -161,7 +179,7 @@ void KX_TouchEventManager::NextFrame() m_newCollisions.clear(); - for (it = m_sensors.begin();!(it==m_sensors.end());++it) - (*it)->Activate(m_logicmgr,NULL); + for (it.begin();!it.end();++it) + (*it)->Activate(m_logicmgr); } } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 5a6e8e6f501..c06acd4a873 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -66,10 +66,10 @@ void KX_TouchSensor::UnregisterToManager() { // before unregistering the sensor, make sure we release all references EndFrame(); - m_eventmgr->RemoveSensor(this); + SCA_ISensor::UnregisterToManager(); } -bool KX_TouchSensor::Evaluate(CValue* event) +bool KX_TouchSensor::Evaluate() { bool result = false; bool reset = m_reset && m_level; @@ -142,13 +142,17 @@ KX_TouchSensor::~KX_TouchSensor() CValue* KX_TouchSensor::GetReplica() { KX_TouchSensor* replica = new KX_TouchSensor(*this); - replica->m_colliders = new CListValue(); - replica->Init(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); + replica->ProcessReplica(); return replica; } +void KX_TouchSensor::ProcessReplica() +{ + SCA_ISensor::ProcessReplica(); + m_colliders = new CListValue(); + Init(); +} + void KX_TouchSensor::ReParent(SCA_IObject* parent) { KX_GameObject *gameobj = static_cast<KX_GameObject *>(parent); @@ -169,21 +173,69 @@ void KX_TouchSensor::RegisterSumo(KX_TouchEventManager *touchman) { if (m_physCtrl) { - touchman->GetPhysicsEnvironment()->requestCollisionCallback(m_physCtrl); - // collision - // Deprecated - + if (touchman->GetPhysicsEnvironment()->requestCollisionCallback(m_physCtrl)) + { + KX_ClientObjectInfo* client_info = static_cast<KX_ClientObjectInfo*>(m_physCtrl->getNewClientInfo()); + if (client_info->isSensor()) + touchman->GetPhysicsEnvironment()->addSensor(m_physCtrl); + } } } - void KX_TouchSensor::UnregisterSumo(KX_TouchEventManager* touchman) { if (m_physCtrl) { - touchman->GetPhysicsEnvironment()->removeCollisionCallback(m_physCtrl); + if (touchman->GetPhysicsEnvironment()->removeCollisionCallback(m_physCtrl)) + { + // no more sensor on the controller, can remove it if it is a sensor object + KX_ClientObjectInfo* client_info = static_cast<KX_ClientObjectInfo*>(m_physCtrl->getNewClientInfo()); + if (client_info->isSensor()) + touchman->GetPhysicsEnvironment()->removeSensor(m_physCtrl); + } } } +// this function is called only for sensor objects +// return true if the controller can collide with the object +bool KX_TouchSensor::BroadPhaseSensorFilterCollision(void*obj1,void*obj2) +{ + assert(obj1==m_physCtrl && obj2); + + KX_GameObject* myobj = (KX_GameObject*)GetParent(); + KX_GameObject* myparent = myobj->GetParent(); + KX_ClientObjectInfo* client_info = static_cast<KX_ClientObjectInfo*>(((PHY_IPhysicsController*)obj2)->getNewClientInfo()); + KX_ClientObjectInfo* my_client_info = static_cast<KX_ClientObjectInfo*>(m_physCtrl->getNewClientInfo()); + KX_GameObject* otherobj = ( client_info ? client_info->m_gameobject : NULL); + + // first, decrement refcount as GetParent() increases it + if (myparent) + myparent->Release(); + + // we can only check on persistent characteristic: m_link and m_suspended are not + // good candidate because they are transient. That must be handled at another level + if (!otherobj || + otherobj == myparent || // don't interact with our parent + (my_client_info->m_type == KX_ClientObjectInfo::OBACTORSENSOR && + client_info->m_type != KX_ClientObjectInfo::ACTOR)) // only with actor objects + return false; + + bool found = m_touchedpropname.IsEmpty(); + if (!found) + { + if (m_bFindMaterial) + { + if (client_info->m_auxilary_info) + { + found = (!strcmp(m_touchedpropname.Ptr(), (char*)client_info->m_auxilary_info)); + } + } else + { + found = (otherobj->GetProperty(m_touchedpropname) != NULL); + } + } + return found; +} + bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_CollData* colldata) { // KX_TouchEventManager* toucheventmgr = (KX_TouchEventManager*)m_eventmgr; @@ -242,8 +294,13 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll /* ------------------------------------------------------------------------- */ /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_TouchSensor::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_TouchSensor", sizeof(PyObjectPlus_Proxy), 0, @@ -283,11 +340,11 @@ PyMethodDef KX_TouchSensor::Methods[] = { }; PyAttributeDef KX_TouchSensor::Attributes[] = { - KX_PYATTRIBUTE_STRING_RW("property",0,100,false,KX_TouchSensor,m_touchedpropname), + KX_PYATTRIBUTE_STRING_RW("propName",0,100,false,KX_TouchSensor,m_touchedpropname), KX_PYATTRIBUTE_BOOL_RW("useMaterial",KX_TouchSensor,m_bFindMaterial), - KX_PYATTRIBUTE_BOOL_RW("pulseCollisions",KX_TouchSensor,m_bTouchPulse), - KX_PYATTRIBUTE_RO_FUNCTION("objectHit", KX_TouchSensor, pyattr_get_object_hit), - KX_PYATTRIBUTE_RO_FUNCTION("objectHitList", KX_TouchSensor, pyattr_get_object_hit_list), + KX_PYATTRIBUTE_BOOL_RW("usePulseCollision",KX_TouchSensor,m_bTouchPulse), + KX_PYATTRIBUTE_RO_FUNCTION("hitObject", KX_TouchSensor, pyattr_get_object_hit), + KX_PYATTRIBUTE_RO_FUNCTION("hitObjectList", KX_TouchSensor, pyattr_get_object_hit_list), { NULL } //Sentinel }; @@ -296,6 +353,10 @@ PyObject* KX_TouchSensor::py_getattro(PyObject *attr) py_getattro_up(SCA_ISensor); } +PyObject* KX_TouchSensor::py_getattro_dict() { + py_getattro_dict_up(SCA_ISensor); +} + int KX_TouchSensor::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_ISensor); @@ -312,7 +373,7 @@ const char KX_TouchSensor::SetProperty_doc[] = "\tmaterials."; PyObject* KX_TouchSensor::PySetProperty(PyObject* value) { - ShowDeprecationWarning("setProperty()", "the propertyName property"); + ShowDeprecationWarning("setProperty()", "the propName property"); char *nameArg= PyString_AsString(value); if (nameArg==NULL) { PyErr_SetString(PyExc_ValueError, "expected a "); @@ -329,6 +390,8 @@ const char KX_TouchSensor::GetProperty_doc[] = "\tgetTouchMaterial() to find out whether this sensor\n" "\tlooks for properties or materials."; PyObject* KX_TouchSensor::PyGetProperty() { + ShowDeprecationWarning("getProperty()", "the propName property"); + return PyString_FromString(m_touchedpropname); } @@ -337,7 +400,7 @@ const char KX_TouchSensor::GetHitObject_doc[] = ; PyObject* KX_TouchSensor::PyGetHitObject() { - ShowDeprecationWarning("getHitObject()", "the objectHit property"); + ShowDeprecationWarning("getHitObject()", "the hitObject property"); /* to do: do Py_IncRef if the object is already known in Python */ /* otherwise, this leaks memory */ if (m_hitObject) @@ -353,7 +416,7 @@ const char KX_TouchSensor::GetHitObjectList_doc[] = "\tbut only those matching the property/material condition.\n"; PyObject* KX_TouchSensor::PyGetHitObjectList() { - ShowDeprecationWarning("getHitObjectList()", "the objectHitList property"); + ShowDeprecationWarning("getHitObjectList()", "the hitObjectList property"); /* to do: do Py_IncRef if the object is already known in Python */ /* otherwise, this leaks memory */ /* Edit, this seems ok and not to leak memory - Campbell */ return m_colliders->GetProxy(); diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index 15ef653c1b2..476c63e89db 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -84,8 +84,9 @@ public: virtual ~KX_TouchSensor(); virtual CValue* GetReplica(); + virtual void ProcessReplica(); virtual void SynchronizeTransform(); - virtual bool Evaluate(CValue* event); + virtual bool Evaluate(); virtual void Init(); virtual void ReParent(SCA_IObject* parent); @@ -102,7 +103,8 @@ public: // obj1 = sensor physical controller, obj2 = physical controller of second object // return value = true if collision should be checked on pair of object virtual bool BroadPhaseFilterCollision(void*obj1,void*obj2) { return true; } - + virtual bool BroadPhaseSensorFilterCollision(void*obj1,void*obj2); + virtual sensortype GetSensorType() { return ST_TOUCH; } virtual bool IsPositiveTrigger() { @@ -121,6 +123,7 @@ public: /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); //Deprecated -----> diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index fbf43de6cf4..5a50d0fb944 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -83,6 +83,10 @@ KX_TrackToActuator::KX_TrackToActuator(SCA_IObject *gameobj, // if so, store the initial local rotation // this is needed to revert the effect of the parent inverse node (TBC) m_parentlocalmat = m_parentobj->GetSGNode()->GetLocalOrientation(); + // use registration mechanism rather than AddRef, it creates zombie objects + m_parentobj->RegisterActuator(this); + // GetParent did AddRef, undo here + m_parentobj->Release(); } } } @@ -189,7 +193,7 @@ KX_TrackToActuator::~KX_TrackToActuator() if (m_object) m_object->UnregisterActuator(this); if (m_parentobj) - m_parentobj->Release(); + m_parentobj->UnregisterActuator(this); } /* end of destructor */ void KX_TrackToActuator::ProcessReplica() @@ -198,7 +202,7 @@ void KX_TrackToActuator::ProcessReplica() if (m_object) m_object->RegisterActuator(this); if (m_parentobj) - m_parentobj->AddRef(); + m_parentobj->RegisterActuator(this); SCA_IActuator::ProcessReplica(); } @@ -211,6 +215,11 @@ bool KX_TrackToActuator::UnlinkObject(SCA_IObject* clientobj) m_object = NULL; return true; } + if (clientobj == m_parentobj) + { + m_parentobj = NULL; + return true; + } return false; } @@ -227,9 +236,9 @@ void KX_TrackToActuator::Relink(GEN_Map<GEN_HashedPtr, void*> *obj_map) void **h_parobj = (*obj_map)[m_parentobj]; if (h_parobj) { if (m_parentobj) - m_parentobj->Release(); + m_parentobj->UnregisterActuator(this); m_parentobj= (KX_GameObject*)(*h_parobj); - m_parentobj->AddRef(); + m_parentobj->RegisterActuator(this); } } @@ -425,8 +434,13 @@ bool KX_TrackToActuator::Update(double curtime, bool frame) /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_TrackToActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_TrackToActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -490,7 +504,7 @@ int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUT KX_GameObject *gameobj; if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_TrackToActuator")) - return 1; // ConvertPythonToGameObject sets the error + return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error if (actuator->m_object != NULL) actuator->m_object->UnregisterActuator(actuator); @@ -500,7 +514,7 @@ int KX_TrackToActuator::pyattr_set_object(void *self, const struct KX_PYATTRIBUT if (actuator->m_object) actuator->m_object->RegisterActuator(actuator); - return 0; + return PY_SET_ATTR_SUCCESS; } @@ -509,6 +523,10 @@ PyObject* KX_TrackToActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* KX_TrackToActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_TrackToActuator::py_setattro(PyObject *attr, PyObject* value) { py_setattro_up(SCA_IActuator); diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.h b/source/gameengine/Ketsji/KX_TrackToActuator.h index 99505f93cfe..c4cc2b1f062 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.h +++ b/source/gameengine/Ketsji/KX_TrackToActuator.h @@ -61,8 +61,6 @@ class KX_TrackToActuator : public SCA_IActuator virtual CValue* GetReplica() { KX_TrackToActuator* replica = new KX_TrackToActuator(*this); replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; }; @@ -73,6 +71,7 @@ class KX_TrackToActuator : public SCA_IActuator /* Python part */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject* value); /* These are used to get and set m_ob */ diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 1a6fb196db5..8146d04a878 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -273,8 +273,13 @@ PyObject* KX_VehicleWrapper::PyGetConstraintType(PyObject* args) //python specific stuff PyTypeObject KX_VehicleWrapper::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_VehicleWrapper", sizeof(PyObjectPlus_Proxy), 0, @@ -303,32 +308,13 @@ PyObject* KX_VehicleWrapper::py_getattro(PyObject *attr) py_getattro_up(PyObjectPlus); } -int KX_VehicleWrapper::py_setattro(PyObject *attr,PyObject* pyobj) -{ - /* TODO - strange setattr, needs updating */ - PyTypeObject* type = pyobj->ob_type; - int result = 1; - - if (type == &PyList_Type) - { - result = 0; - } - if (type == &PyFloat_Type) - { - result = 0; +PyObject* KX_VehicleWrapper::py_getattro_dict() { + py_getattro_dict_up(PyObjectPlus); +} - } - if (type == &PyInt_Type) - { - result = 0; - } - if (type == &PyString_Type) - { - result = 0; - } - if (result) - result = PyObjectPlus::py_setattro(attr,pyobj); - return result; +int KX_VehicleWrapper::py_setattro(PyObject *attr,PyObject* value) +{ + py_setattro_up(PyObjectPlus); }; diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h index de7fe75cfba..c2b5e3d9251 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.h +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h @@ -13,6 +13,7 @@ class KX_VehicleWrapper : public PyObjectPlus { Py_Header; virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); std::vector<PHY_IMotionState*> m_motionStates; diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 88f63334285..4b0ad083473 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -37,8 +37,13 @@ #include "KX_PyMath.h" PyTypeObject KX_VertexProxy::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_VertexProxy", sizeof(PyObjectPlus_Proxy), 0, @@ -57,8 +62,8 @@ PyTypeObject KX_VertexProxy::Type = { PyParentObject KX_VertexProxy::Parents[] = { &KX_VertexProxy::Type, - &SCA_IObject::Type, &CValue::Type, + &PyObjectPlus::Type, NULL }; @@ -79,6 +84,7 @@ PyMethodDef KX_VertexProxy::Methods[] = { }; PyAttributeDef KX_VertexProxy::Attributes[] = { + //KX_PYATTRIBUTE_TODO("DummyProps"), KX_PYATTRIBUTE_DUMMY("x"), KX_PYATTRIBUTE_DUMMY("y"), @@ -156,7 +162,11 @@ KX_VertexProxy::py_getattro(PyObject *attr) return PyObjectFrom(MT_Vector3(m_vertex->getNormal())); } - py_getattro_up(SCA_IObject); + py_getattro_up(CValue); +} + +PyObject* KX_VertexProxy::py_getattro_dict() { + py_getattro_dict_up(CValue); } int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) @@ -312,7 +322,7 @@ int KX_VertexProxy::py_setattro(PyObject *attr, PyObject *pyvalue) } } - return SCA_IObject::py_setattro(attr, pyvalue); + return CValue::py_setattro(attr, pyvalue); } KX_VertexProxy::KX_VertexProxy(KX_MeshProxy*mesh, RAS_TexVert* vertex) @@ -333,11 +343,9 @@ CValue* KX_VertexProxy::CalcFinal(VALUE_DATA_TYPE, VALUE_OPERATOR, CValue *) { STR_String sVertexName="vertex"; const STR_String & KX_VertexProxy::GetText() {return sVertexName;}; double KX_VertexProxy::GetNumber() { return -1;} -STR_String KX_VertexProxy::GetName() { return sVertexName;} -void KX_VertexProxy::SetName(STR_String) { }; +STR_String& KX_VertexProxy::GetName() { return sVertexName;} +void KX_VertexProxy::SetName(const char *) { }; CValue* KX_VertexProxy::GetReplica() { return NULL;} -void KX_VertexProxy::ReplicaSetName(STR_String) {}; - // stuff for python integration @@ -427,9 +435,10 @@ PyObject* KX_VertexProxy::PyGetUV2() PyObject* KX_VertexProxy::PySetUV2(PyObject* args) { MT_Point2 vec; - unsigned int unit=0; + unsigned int unit= RAS_TexVert::SECOND_UV; + PyObject* list= NULL; - if(!PyArg_ParseTuple(args, "Oi:setUV2", &list, &unit)) + if(!PyArg_ParseTuple(args, "O|i:setUV2", &list, &unit)) return NULL; if (!PyVecTo(list, vec)) diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 67a15d96768..42db5fbc322 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -31,7 +31,7 @@ #include "SCA_IObject.h" -class KX_VertexProxy : public SCA_IObject +class KX_VertexProxy : public CValue { Py_Header; protected: @@ -47,14 +47,14 @@ public: CValue* CalcFinal(VALUE_DATA_TYPE dtype, VALUE_OPERATOR op, CValue *val); const STR_String & GetText(); double GetNumber(); - STR_String GetName(); - void SetName(STR_String name); // Set the name of the value - void ReplicaSetName(STR_String name); + STR_String& GetName(); + void SetName(const char *name); // Set the name of the value CValue* GetReplica(); // stuff for python integration virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *pyvalue); KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp index ba59d0d3d47..d848065ad73 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.cpp +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.cpp @@ -64,8 +64,6 @@ KX_VisibilityActuator::GetReplica( { KX_VisibilityActuator* replica = new KX_VisibilityActuator(*this); replica->ProcessReplica(); - // this will copy properties and so on... - CValue::AddDataToReplica(replica); return replica; } @@ -94,8 +92,13 @@ KX_VisibilityActuator::Update() /* Integration hooks ------------------------------------------------------- */ PyTypeObject KX_VisibilityActuator::Type = { - PyObject_HEAD_INIT(NULL) - 0, +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ + 0, /* ob_size */ +#endif "KX_VisibilityActuator", sizeof(PyObjectPlus_Proxy), 0, @@ -133,8 +136,8 @@ KX_VisibilityActuator::Methods[] = { PyAttributeDef KX_VisibilityActuator::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("visibility", KX_VisibilityActuator, m_visible), - KX_PYATTRIBUTE_BOOL_RW("occlusion", KX_VisibilityActuator, m_occlusion), - KX_PYATTRIBUTE_BOOL_RW("recursion", KX_VisibilityActuator, m_recursive), + KX_PYATTRIBUTE_BOOL_RW("useOcclusion", KX_VisibilityActuator, m_occlusion), + KX_PYATTRIBUTE_BOOL_RW("useRecursion", KX_VisibilityActuator, m_recursive), { NULL } //Sentinel }; @@ -143,6 +146,10 @@ PyObject* KX_VisibilityActuator::py_getattro(PyObject *attr) py_getattro_up(SCA_IActuator); } +PyObject* KX_VisibilityActuator::py_getattro_dict() { + py_getattro_dict_up(SCA_IActuator); +} + int KX_VisibilityActuator::py_setattro(PyObject *attr, PyObject *value) { py_setattro_up(SCA_IActuator); diff --git a/source/gameengine/Ketsji/KX_VisibilityActuator.h b/source/gameengine/Ketsji/KX_VisibilityActuator.h index 04633bce665..45aba50f645 100644 --- a/source/gameengine/Ketsji/KX_VisibilityActuator.h +++ b/source/gameengine/Ketsji/KX_VisibilityActuator.h @@ -70,6 +70,7 @@ class KX_VisibilityActuator : public SCA_IActuator /* --------------------------------------------------------------------- */ virtual PyObject* py_getattro(PyObject *attr); + virtual PyObject* py_getattro_dict(); virtual int py_setattro(PyObject *attr, PyObject *value); // Deprecated -----> diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index 921aba9c11f..5ab15c9eab3 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -8,25 +8,28 @@ defs = '' # XXX 2.5 # Mathutils C files. -#sources.extend([\ -# '#source/blender/python/api2_2x/Mathutils.c',\ -# '#source/blender/python/api2_2x/constant.c',\ -# '#source/blender/python/api2_2x/euler.c',\ -# '#source/blender/python/api2_2x/gen_utils.c',\ -# '#source/blender/python/api2_2x/matrix.c',\ -# '#source/blender/python/api2_2x/point.c',\ -# '#source/blender/python/api2_2x/quat.c',\ -# '#source/blender/python/api2_2x/vector.c',\ -#]) -# -#sources.extend([\ -# '#source/blender/python/api2_2x/bpy_internal_import.c' -#]) -# -# -#sources.extend([\ -# '#source/blender/python/api2_2x/BGL.c' -#]) +""" +if not env['BF_PYTHON_VERSION'].startswith('3'): + # TODO - py3 support + sources.extend([\ + '#source/blender/python/api2_2x/Mathutils.c',\ + '#source/blender/python/api2_2x/Geometry.c',\ + '#source/blender/python/api2_2x/euler.c',\ + '#source/blender/python/api2_2x/matrix.c',\ + '#source/blender/python/api2_2x/quat.c',\ + '#source/blender/python/api2_2x/vector.c',\ + '#source/blender/python/api2_2x/constant.c',\ + ]) + + sources.extend([\ + '#source/blender/python/api2_2x/BGL.c' + ]) + +sources.extend([\ + '#source/blender/python/api2_2x/bpy_internal_import.c' +]) +""" + incs = '. #source/blender/python/api2_2x' # Only for Mathutils! and bpy_internal_import.h, be very careful diff --git a/source/gameengine/Network/NG_NetworkScene.cpp b/source/gameengine/Network/NG_NetworkScene.cpp index 22263a2bdda..f8e489a8f48 100644 --- a/source/gameengine/Network/NG_NetworkScene.cpp +++ b/source/gameengine/Network/NG_NetworkScene.cpp @@ -119,7 +119,7 @@ void NG_NetworkScene::AddObject(NG_NetworkObject* object) { if (! m_networkdevice->IsOnline()) return; - STR_String name = object->GetName(); + const STR_String& name = object->GetName(); m_networkObjects.insert(name, object); } @@ -130,7 +130,7 @@ void NG_NetworkScene::RemoveObject(NG_NetworkObject* object) { if (! m_networkdevice->IsOnline()) return; - STR_String name = object->GetName(); + const STR_String& name = object->GetName(); m_networkObjects.remove(name); } diff --git a/source/gameengine/Physics/BlOde/OdePhysicsController.cpp b/source/gameengine/Physics/BlOde/OdePhysicsController.cpp index efe4554d970..5efd0994311 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsController.cpp +++ b/source/gameengine/Physics/BlOde/OdePhysicsController.cpp @@ -379,7 +379,10 @@ bool ODEPhysicsController::SynchronizeMotionStates(float time) return false; //it update the worldpos } - +PHY_IMotionState* ODEPhysicsController::GetMotionState() +{ + return m_MotionState; +} // kinematic methods diff --git a/source/gameengine/Physics/BlOde/OdePhysicsController.h b/source/gameengine/Physics/BlOde/OdePhysicsController.h index e97afdb68c3..544d11da2ca 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsController.h +++ b/source/gameengine/Physics/BlOde/OdePhysicsController.h @@ -102,6 +102,7 @@ public: virtual void WriteDynamicsToMotionState() {}; virtual void WriteMotionStateToDynamics(bool nondynaonly); + virtual class PHY_IMotionState* GetMotionState(); /** call from Scene Graph Node to 'update'. diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp index 2e8ee31058f..54e97858b7f 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.cpp @@ -75,7 +75,7 @@ float ODEPhysicsEnvironment::getFixedTimeStep() -bool ODEPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep1) +bool ODEPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep1,float interval) { float deltaTime = timeStep1; diff --git a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h index 2e4709cf420..54e4f7f90e1 100644 --- a/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h +++ b/source/gameengine/Physics/BlOde/OdePhysicsEnvironment.h @@ -44,7 +44,7 @@ public: // Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep); + virtual bool proceedDeltaTime(double curTime,float timeStep,float interval); virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep); virtual float getFixedTimeStep(); @@ -64,8 +64,8 @@ public: virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) { } - virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl) {} - virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl) {} + virtual bool requestCollisionCallback(PHY_IPhysicsController* ctrl) {return false;} + virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl) {return false;} 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/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt index ec2cdede683..02f2aa635af 100644 --- a/source/gameengine/Physics/Bullet/CMakeLists.txt +++ b/source/gameengine/Physics/Bullet/CMakeLists.txt @@ -32,6 +32,7 @@ SET(INC ../../../../extern/bullet2/src ../../../../extern/glew/include ../../../../intern/moto/include + ../../../../intern/guardedalloc ../../../kernel/gen_system ../../../../intern/string ../../../../intern/SoundSystem @@ -41,6 +42,8 @@ SET(INC ../../GameLogic ../../SceneGraph ../../../../source/blender/makesdna + ../../../../source/blender/blenlib + ../../../../source/blender/blenkernel ${PYTHON_INC} ) diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.cpp b/source/gameengine/Physics/Bullet/CcdGraphicController.cpp index caf18fd28ba..2dbbb7fa4a0 100644 --- a/source/gameengine/Physics/Bullet/CcdGraphicController.cpp +++ b/source/gameengine/Physics/Bullet/CcdGraphicController.cpp @@ -47,11 +47,24 @@ void CcdGraphicController::setLocalAabb(const btVector3& aabbMin,const btVector3 void CcdGraphicController::setLocalAabb(const MT_Point3& aabbMin,const MT_Point3& aabbMax) { - m_localAabbMin = btVector3(aabbMin[0],aabbMin[1],aabbMin[2]); - m_localAabbMax = btVector3(aabbMax[0],aabbMax[1],aabbMax[2]); + m_localAabbMin.setValue(aabbMin[0],aabbMin[1],aabbMin[2]); + m_localAabbMax.setValue(aabbMax[0],aabbMax[1],aabbMax[2]); SetGraphicTransform(); } +void CcdGraphicController::setLocalAabb(const PHY__Vector3& aabbMin,const PHY__Vector3& aabbMax) +{ + m_localAabbMin.setValue(aabbMin[0],aabbMin[1],aabbMin[2]); + m_localAabbMax.setValue(aabbMax[0],aabbMax[1],aabbMax[2]); + SetGraphicTransform(); +} + +void CcdGraphicController::setLocalAabb(const float* aabbMin,const float* aabbMax) +{ + m_localAabbMin.setValue(aabbMin[0],aabbMin[1],aabbMin[2]); + m_localAabbMax.setValue(aabbMax[0],aabbMax[1],aabbMax[2]); + SetGraphicTransform(); +} void CcdGraphicController::getAabb(btVector3& aabbMin, btVector3& aabbMax) { @@ -105,8 +118,17 @@ PHY_IGraphicController* CcdGraphicController::GetReplica(class PHY_IMotionState* replica->m_motionState = motionState; replica->m_newClientInfo = NULL; replica->m_handle = NULL; - m_phyEnv->addCcdGraphicController(replica); + // don't add the graphic controller now: work around a bug in Bullet with rescaling, + // (the scale of the controller is not yet defined). + //m_phyEnv->addCcdGraphicController(replica); return replica; } +void CcdGraphicController::Activate(bool active) +{ + if (active) + m_phyEnv->addCcdGraphicController(this); + else + m_phyEnv->removeCcdGraphicController(this); +} diff --git a/source/gameengine/Physics/Bullet/CcdGraphicController.h b/source/gameengine/Physics/Bullet/CcdGraphicController.h index 8faa0944313..b0626f902c2 100644 --- a/source/gameengine/Physics/Bullet/CcdGraphicController.h +++ b/source/gameengine/Physics/Bullet/CcdGraphicController.h @@ -38,6 +38,8 @@ public: void setLocalAabb(const btVector3& aabbMin,const btVector3& aabbMax); void setLocalAabb(const MT_Point3& aabbMin,const MT_Point3& aabbMax); + virtual void setLocalAabb(const PHY__Vector3& aabbMin,const PHY__Vector3& aabbMax); + virtual void setLocalAabb(const float aabbMin[3],const float aabbMax[3]); PHY_IMotionState* GetMotionState() { return m_motionState; } void getAabb(btVector3& aabbMin, btVector3& aabbMax); @@ -53,6 +55,10 @@ public: * Updates the Aabb based on the motion state */ virtual bool SetGraphicTransform(); + /** + * Add/remove to environment + */ + virtual void Activate(bool active); // client info for culling virtual void* getNewClientInfo() { return m_newClientInfo; } diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 0b9da8f46d3..d22c09b4d3e 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -35,6 +35,10 @@ subject to the following restrictions: #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" +extern "C"{ +#include "BKE_cdderivedmesh.h" +} + class BP_Proxy; ///todo: fill all the empty CcdPhysicsController methods, hook them up to the btRigidBody class @@ -88,16 +92,19 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) } -btTransform CcdPhysicsController::GetTransformFromMotionState(PHY_IMotionState* motionState) +btTransform& CcdPhysicsController::GetTransformFromMotionState(PHY_IMotionState* motionState) { - btTransform trans; - float tmp[3]; - motionState->getWorldPosition(tmp[0],tmp[1],tmp[2]); - trans.setOrigin(btVector3(tmp[0],tmp[1],tmp[2])); - - btQuaternion orn; - motionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]); - trans.setRotation(orn); + static btTransform trans; + btVector3 tmp; + motionState->getWorldPosition(tmp.m_floats[0], tmp.m_floats[1], tmp.m_floats[2]); + trans.setOrigin(tmp); + + float ori[12]; + motionState->getWorldOrientation(ori); + trans.getBasis().setFromOpenGLSubMatrix(ori); + //btQuaternion orn; + //motionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]); + //trans.setRotation(orn); return trans; } @@ -114,18 +121,18 @@ public: } - virtual void getWorldTransform(btTransform& worldTrans ) const + void getWorldTransform(btTransform& worldTrans ) const { - float pos[3]; - float quatOrn[4]; + btVector3 pos; + float ori[12]; - m_blenderMotionState->getWorldPosition(pos[0],pos[1],pos[2]); - m_blenderMotionState->getWorldOrientation(quatOrn[0],quatOrn[1],quatOrn[2],quatOrn[3]); - worldTrans.setOrigin(btVector3(pos[0],pos[1],pos[2])); - worldTrans.setBasis(btMatrix3x3(btQuaternion(quatOrn[0],quatOrn[1],quatOrn[2],quatOrn[3]))); + m_blenderMotionState->getWorldPosition(pos.m_floats[0],pos.m_floats[1],pos.m_floats[2]); + m_blenderMotionState->getWorldOrientation(ori); + worldTrans.setOrigin(pos); + worldTrans.getBasis().setFromOpenGLSubMatrix(ori); } - virtual void setWorldTransform(const btTransform& worldTrans) + void setWorldTransform(const btTransform& worldTrans) { m_blenderMotionState->setWorldPosition(worldTrans.getOrigin().getX(),worldTrans.getOrigin().getY(),worldTrans.getOrigin().getZ()); btQuaternion rotQuat = worldTrans.getRotation(); @@ -178,12 +185,12 @@ void CcdPhysicsController::CreateRigidbody() rbci.m_restitution = m_cci.m_restitution; - int nodecount = 0; + + - int numtriangles = 1; btVector3 p(0,0,0);// = getOrigin(); - btScalar h = 1.f; + btSoftRigidDynamicsWorld* softDynaWorld = (btSoftRigidDynamicsWorld*)m_cci.m_physicsEnv->getDynamicsWorld(); @@ -289,7 +296,11 @@ void CcdPhysicsController::CreateRigidbody() } } - + if (m_cci.m_margin > 0.f) + { + psb->getCollisionShape()->setMargin(m_cci.m_margin); + psb->updateBounds(); + } m_object = psb; @@ -489,10 +500,12 @@ void CcdPhysicsController::CreateRigidbody() //convert collision flags! //special case: a near/radar sensor controller should not be defined static or it will //generate loads of static-static collision messages on the console - if ((m_cci.m_collisionFilterGroup & CcdConstructionInfo::SensorFilter) != 0) + if (m_cci.m_bSensor) { // reset the flags that have been set so far GetCollisionObject()->setCollisionFlags(0); + // sensor must never go to sleep: they need to detect continously + GetCollisionObject()->setActivationState(DISABLE_DEACTIVATION); } GetCollisionObject()->setCollisionFlags(m_object->getCollisionFlags() | m_cci.m_collisionFlags); btRigidBody* body = GetRigidBody(); @@ -506,6 +519,8 @@ void CcdPhysicsController::CreateRigidbody() { body->setAngularFactor(0.f); } + body->setContactProcessingThreshold(m_cci.m_contactProcessingThreshold); + } if (m_object && m_cci.m_do_anisotropic) { @@ -572,10 +587,22 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) btSoftBody* sb = GetSoftBody(); if (sb) { - btVector3 aabbMin,aabbMax; - sb->getAabb(aabbMin,aabbMax); - btVector3 worldPos = (aabbMax+aabbMin)*0.5f; - m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); + if (sb->m_pose.m_bframe) + { + btVector3 worldPos = sb->m_pose.m_com; + btQuaternion worldquat; + btMatrix3x3 trs = sb->m_pose.m_rot*sb->m_pose.m_scl; + trs.getRotation(worldquat); + m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); + m_MotionState->setWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]); + } + else + { + btVector3 aabbMin,aabbMax; + sb->getAabb(aabbMin,aabbMax); + btVector3 worldPos = (aabbMax+aabbMin)*0.5f; + m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); + } m_MotionState->calculateWorldTransformations(); return true; } @@ -597,12 +624,13 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len)); } - const btVector3& worldPos = body->getCenterOfMassPosition(); + const btTransform& xform = body->getCenterOfMassTransform(); + const btMatrix3x3& worldOri = xform.getBasis(); + const btVector3& worldPos = xform.getOrigin(); + float ori[12]; + worldOri.getOpenGLSubMatrix(ori); + m_MotionState->setWorldOrientation(ori); m_MotionState->setWorldPosition(worldPos[0],worldPos[1],worldPos[2]); - - const btQuaternion& worldquat = body->getOrientation(); - m_MotionState->setWorldOrientation(worldquat[0],worldquat[1],worldquat[2],worldquat[3]); - m_MotionState->calculateWorldTransformations(); float scale[3]; @@ -639,8 +667,10 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) void CcdPhysicsController::WriteMotionStateToDynamics(bool nondynaonly) { - + btTransform& xform = CcdPhysicsController::GetTransformFromMotionState(m_MotionState); + SetCenterOfMassTransform(xform); } + void CcdPhysicsController::WriteDynamicsToMotionState() { } @@ -657,12 +687,12 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta if (m_shapeInfo) { m_shapeInfo->AddRef(); - m_collisionShape = m_shapeInfo->CreateBulletShape(); + m_collisionShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin); if (m_collisionShape) { // new shape has no scaling, apply initial scaling - m_collisionShape->setMargin(m_cci.m_margin); + //m_collisionShape->setMargin(m_cci.m_margin); m_collisionShape->setLocalScaling(m_cci.m_scaling); if (m_cci.m_mass) @@ -670,19 +700,29 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta } } + // load some characterists that are not + btRigidBody* oldbody = GetRigidBody(); m_object = 0; CreateRigidbody(); - btRigidBody* body = GetRigidBody(); - if (body) { if (m_cci.m_mass) { body->setMassProps(m_cci.m_mass, m_cci.m_localInertiaTensor * m_cci.m_inertiaFactor); } - } - m_cci.m_physicsEnv->addCcdPhysicsController(this); + + if (oldbody) + { + body->setLinearFactor(oldbody->getLinearFactor()); + body->setAngularFactor(oldbody->getAngularFactor()); + if (oldbody->getActivationState() == DISABLE_DEACTIVATION) + body->setActivationState(DISABLE_DEACTIVATION); + } + } + // sensor object are added when needed + if (!m_cci.m_bSensor) + m_cci.m_physicsEnv->addCcdPhysicsController(this); /* SM_Object* dynaparent=0; @@ -759,10 +799,13 @@ void CcdPhysicsController::RelativeTranslate(float dlocX,float dlocY,float dloc m_object->activate(true); if (m_object->isStaticObject()) { - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + if (!m_cci.m_bSensor) + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + // kinematic object should not set the transform, it disturbs the velocity interpolation + return; } - btRigidBody* body = GetRigidBody(); + // btRigidBody* body = GetRigidBody(); // not used anymore btVector3 dloc(dlocX,dlocY,dlocZ); btTransform xform = m_object->getWorldTransform(); @@ -785,7 +828,10 @@ void CcdPhysicsController::RelativeRotate(const float rotval[9],bool local) m_object->activate(true); if (m_object->isStaticObject()) { - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + if (!m_cci.m_bSensor) + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + // kinematic object should not set the transform, it disturbs the velocity interpolation + return; } btMatrix3x3 drotmat( rotval[0],rotval[4],rotval[8], @@ -808,10 +854,9 @@ void CcdPhysicsController::RelativeRotate(const float rotval[9],bool local) void CcdPhysicsController::GetWorldOrientation(btMatrix3x3& mat) { - float orn[4]; - m_MotionState->getWorldOrientation(orn[0],orn[1],orn[2],orn[3]); - btQuaternion quat(orn[0],orn[1],orn[2],orn[3]); - mat.setRotation(quat); + float ori[12]; + m_MotionState->getWorldOrientation(ori); + mat.setFromOpenGLSubMatrix(ori); } void CcdPhysicsController::getOrientation(float &quatImag0,float &quatImag1,float &quatImag2,float &quatReal) @@ -829,7 +874,10 @@ void CcdPhysicsController::setOrientation(float quatImag0,float quatImag1,float m_object->activate(true); if (m_object->isStaticObject()) { - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + if (!m_cci.m_bSensor) + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + // kinematic object should not set the transform, it disturbs the velocity interpolation + return; } // not required //m_MotionState->setWorldOrientation(quatImag0,quatImag1,quatImag2,quatReal); @@ -850,7 +898,7 @@ void CcdPhysicsController::setWorldOrientation(const btMatrix3x3& orn) if (m_object) { m_object->activate(true); - if (m_object->isStaticObject()) + if (m_object->isStaticObject() && !m_cci.m_bSensor) { m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); } @@ -881,7 +929,10 @@ void CcdPhysicsController::setPosition(float posX,float posY,float posZ) m_object->activate(true); if (m_object->isStaticObject()) { - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + if (!m_cci.m_bSensor) + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + // kinematic object should not set the transform, it disturbs the velocity interpolation + return; } // not required, this function is only used to update the physic controller //m_MotionState->setWorldPosition(posX,posY,posZ); @@ -893,9 +944,19 @@ void CcdPhysicsController::setPosition(float posX,float posY,float posZ) // not required //m_bulletMotionState->setWorldTransform(xform); } +} - +void CcdPhysicsController::forceWorldTransform(const btMatrix3x3& mat, const btVector3& pos) +{ + if (m_object) + { + btTransform& xform = m_object->getWorldTransform(); + xform.setBasis(mat); + xform.setOrigin(pos); + } } + + void CcdPhysicsController::resolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) { } @@ -945,14 +1006,24 @@ void CcdPhysicsController::ApplyTorque(float torqueX,float torqueY,float torque m_object->activate(); if (m_object->isStaticObject()) { - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + if (!m_cci.m_bSensor) + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + return; } if (local) { torque = xform.getBasis()*torque; } if (body) + { + //workaround for incompatibility between 'DYNAMIC' game object, and angular factor + //a DYNAMIC object has some inconsistency: it has no angular effect due to collisions, but still has torque + const btVector3& angFac = body->getAngularFactor(); + btVector3 tmpFac(0,0,1); + body->setAngularFactor(tmpFac); body->applyTorque(torque); + body->setAngularFactor(angFac); + } } } @@ -966,27 +1037,26 @@ void CcdPhysicsController::ApplyForce(float forceX,float forceY,float forceZ,bo m_object->activate(); if (m_object->isStaticObject()) { - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + if (!m_cci.m_bSensor) + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + return; } - + btTransform xform = m_object->getWorldTransform(); + + if (local) + { + force = xform.getBasis()*force; + } + btRigidBody* body = GetRigidBody(); + if (body) + body->applyCentralForce(force); + btSoftBody* soft = GetSoftBody(); + if (soft) { - btTransform xform = m_object->getWorldTransform(); - - if (local) - { - force = xform.getBasis()*force; - } - btRigidBody* body = GetRigidBody(); - if (body) - body->applyCentralForce(force); - btSoftBody* soft = GetSoftBody(); - if (soft) - { - // the force is applied on each node, must reduce it in the same extend - if (soft->m_nodes.size() > 0) - force /= soft->m_nodes.size(); - soft->addForce(force); - } + // the force is applied on each node, must reduce it in the same extend + if (soft->m_nodes.size() > 0) + force /= soft->m_nodes.size(); + soft->addForce(force); } } } @@ -998,19 +1068,18 @@ void CcdPhysicsController::SetAngularVelocity(float ang_velX,float ang_velY,flo m_object->activate(true); if (m_object->isStaticObject()) { - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); - } else + if (!m_cci.m_bSensor) + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + return; + } + btTransform xform = m_object->getWorldTransform(); + if (local) { - btTransform xform = m_object->getWorldTransform(); - if (local) - { - angvel = xform.getBasis()*angvel; - } - btRigidBody* body = GetRigidBody(); - if (body) - body->setAngularVelocity(angvel); - + angvel = xform.getBasis()*angvel; } + btRigidBody* body = GetRigidBody(); + if (body) + body->setAngularVelocity(angvel); } } @@ -1023,7 +1092,8 @@ void CcdPhysicsController::SetLinearVelocity(float lin_velX,float lin_velY,floa m_object->activate(true); if (m_object->isStaticObject()) { - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + if (!m_cci.m_bSensor) + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); return; } @@ -1057,7 +1127,9 @@ void CcdPhysicsController::applyImpulse(float attachX,float attachY,float attac m_object->activate(); if (m_object->isStaticObject()) { - m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + if (!m_cci.m_bSensor) + m_object->setCollisionFlags(m_object->getCollisionFlags() | btCollisionObject::CF_KINEMATIC_OBJECT); + return; } btVector3 pos(attachX,attachY,attachZ); @@ -1184,7 +1256,7 @@ PHY_IPhysicsController* CcdPhysicsController::GetReplica() if (m_shapeInfo) { // This situation does not normally happen - cinfo.m_collisionShape = m_shapeInfo->CreateBulletShape(); + cinfo.m_collisionShape = m_shapeInfo->CreateBulletShape(0.01); } else if (m_collisionShape) { @@ -1251,28 +1323,22 @@ void DefaultMotionState::getWorldScaling(float& scaleX,float& scaleY,float& scal void DefaultMotionState::getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal) { - quatIma0 = m_worldTransform.getRotation().x(); - quatIma1 = m_worldTransform.getRotation().y(); - quatIma2 = m_worldTransform.getRotation().z(); - quatReal = m_worldTransform.getRotation()[3]; + btQuaternion quat = m_worldTransform.getRotation(); + quatIma0 = quat.x(); + quatIma1 = quat.y(); + quatIma2 = quat.z(); + quatReal = quat[3]; } void DefaultMotionState::getWorldOrientation(float* ori) { - *ori++ = m_worldTransform.getBasis()[0].x(); - *ori++ = m_worldTransform.getBasis()[1].x(); - *ori++ = m_worldTransform.getBasis()[1].x(); - *ori++ = 0.f; - *ori++ = m_worldTransform.getBasis()[0].y(); - *ori++ = m_worldTransform.getBasis()[1].y(); - *ori++ = m_worldTransform.getBasis()[1].y(); - *ori++ = 0.f; - *ori++ = m_worldTransform.getBasis()[0].z(); - *ori++ = m_worldTransform.getBasis()[1].z(); - *ori++ = m_worldTransform.getBasis()[1].z(); - *ori++ = 0.f; + m_worldTransform.getBasis().getOpenGLSubMatrix(ori); } +void DefaultMotionState::setWorldOrientation(const float* ori) +{ + m_worldTransform.getBasis().setFromOpenGLSubMatrix(ori); +} void DefaultMotionState::setWorldPosition(float posX,float posY,float posZ) { btVector3 pos(posX,posY,posZ); @@ -1293,9 +1359,9 @@ void DefaultMotionState::calculateWorldTransformations() // Shape constructor std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> CcdShapeConstructionInfo::m_meshShapeMap; -CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mesh, bool polytope) +CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope, bool gimpact) { - if (polytope) + if (polytope || dm || gimpact) // not yet supported return NULL; @@ -1305,9 +1371,9 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes return NULL; } -bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bool useGimpact) +bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool polytope,bool useGimpact) { - int numpolys; + int numpolys, numverts; m_useGimpact = useGimpact; @@ -1316,6 +1382,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo assert(IsUnused()); m_shapeType = PHY_SHAPE_NONE; m_meshObject = NULL; + bool free_dm = false; // No mesh object or mesh has no polys if (!meshobj || meshobj->HasColliderPolygon()==false) { @@ -1325,164 +1392,182 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo return false; } - numpolys = meshobj->NumPolygons(); + if (!dm) { + free_dm = true; + dm = CDDM_from_mesh(meshobj->GetMesh(), NULL); + } + + MVert *mvert = dm->getVertArray(dm); + MFace *mface = dm->getFaceArray(dm); + numpolys = dm->getNumFaces(dm); + numverts = dm->getNumVerts(dm); + int* index = (int*)dm->getFaceDataArray(dm, CD_ORIGINDEX); m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; /* Convert blender geometry into bullet mesh, need these vars for mapping */ - vector<bool> vert_tag_array(meshobj->GetMesh()->totvert, false); + vector<bool> vert_tag_array(numverts, false); unsigned int tot_bt_verts= 0; - unsigned int orig_index; - int i; if (polytope) { // Tag verts we're using for (int p2=0; p2<numpolys; p2++) { - RAS_Polygon* poly= meshobj->GetPolygon(p2); + MFace* mf = &mface[p2]; + RAS_Polygon* poly = meshobj->GetPolygon(index[p2]); // only add polygons that have the collision flag set if (poly->IsCollider()) { - for(i=0; i<poly->VertexCount(); i++) { - orig_index= poly->GetVertex(i)->getOrigIndex(); - if (vert_tag_array[orig_index]==false) - { - vert_tag_array[orig_index]= true; - tot_bt_verts++; - } - } + if (vert_tag_array[mf->v1]==false) {vert_tag_array[mf->v1]= true;tot_bt_verts++;} + if (vert_tag_array[mf->v2]==false) {vert_tag_array[mf->v2]= true;tot_bt_verts++;} + if (vert_tag_array[mf->v3]==false) {vert_tag_array[mf->v3]= true;tot_bt_verts++;} + if (mf->v4 && vert_tag_array[mf->v4]==false) {vert_tag_array[mf->v4]= true;tot_bt_verts++;} } } - m_vertexArray.resize(tot_bt_verts); + m_vertexArray.resize(tot_bt_verts*3); - btVector3 *bt= &m_vertexArray[0]; + btScalar *bt= &m_vertexArray[0]; for (int p2=0; p2<numpolys; p2++) { - RAS_Polygon* poly= meshobj->GetPolygon(p2); + MFace* mf = &mface[p2]; + RAS_Polygon* poly= meshobj->GetPolygon(index[p2]); // only add polygons that have the collisionflag set if (poly->IsCollider()) { - for(i=0; i<poly->VertexCount(); i++) { - RAS_TexVert *v= poly->GetVertex(i); - orig_index= v->getOrigIndex(); - - if (vert_tag_array[orig_index]==true) - { - const float* vtx = v->getXYZ(); - vert_tag_array[orig_index]= false; - - bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]); - bt++; - } + if (vert_tag_array[mf->v1]==true) + { + const float* vtx = mvert[mf->v1].co; + vert_tag_array[mf->v1]= false; + *bt++ = vtx[0]; + *bt++ = vtx[1]; + *bt++ = vtx[2]; + } + if (vert_tag_array[mf->v2]==true) + { + const float* vtx = mvert[mf->v2].co; + vert_tag_array[mf->v2]= false; + *bt++ = vtx[0]; + *bt++ = vtx[1]; + *bt++ = vtx[2]; + } + if (vert_tag_array[mf->v3]==true) + { + const float* vtx = mvert[mf->v3].co; + vert_tag_array[mf->v3]= false; + *bt++ = vtx[0]; + *bt++ = vtx[1]; + *bt++ = vtx[2]; + } + if (mf->v4 && vert_tag_array[mf->v4]==true) + { + const float* vtx = mvert[mf->v4].co; + vert_tag_array[mf->v4]= false; + *bt++ = vtx[0]; + *bt++ = vtx[1]; + *bt++ = vtx[2]; } } } } else { unsigned int tot_bt_tris= 0; - vector<int> vert_remap_array(meshobj->GetMesh()->totvert, 0); + vector<int> vert_remap_array(numverts, 0); // Tag verts we're using for (int p2=0; p2<numpolys; p2++) { - RAS_Polygon* poly= meshobj->GetPolygon(p2); + MFace* mf = &mface[p2]; + RAS_Polygon* poly= meshobj->GetPolygon(index[p2]); // only add polygons that have the collision flag set if (poly->IsCollider()) { - for(i=0; i<poly->VertexCount(); i++) { - orig_index= poly->GetVertex(i)->getOrigIndex(); - if (vert_tag_array[orig_index]==false) - { - vert_tag_array[orig_index]= true; - vert_remap_array[orig_index]= tot_bt_verts; - tot_bt_verts++; - } - } - - tot_bt_tris += (i==4 ? 2:1); /* a quad or a tri */ + if (vert_tag_array[mf->v1]==false) + {vert_tag_array[mf->v1]= true;vert_remap_array[mf->v1]= tot_bt_verts;tot_bt_verts++;} + if (vert_tag_array[mf->v2]==false) + {vert_tag_array[mf->v2]= true;vert_remap_array[mf->v2]= tot_bt_verts;tot_bt_verts++;} + if (vert_tag_array[mf->v3]==false) + {vert_tag_array[mf->v3]= true;vert_remap_array[mf->v3]= tot_bt_verts;tot_bt_verts++;} + if (mf->v4 && vert_tag_array[mf->v4]==false) + {vert_tag_array[mf->v4]= true;vert_remap_array[mf->v4]= tot_bt_verts;tot_bt_verts++;} + tot_bt_tris += (mf->v4 ? 2:1); /* a quad or a tri */ } } - m_vertexArray.resize(tot_bt_verts); + m_vertexArray.resize(tot_bt_verts*3); m_polygonIndexArray.resize(tot_bt_tris); m_triFaceArray.resize(tot_bt_tris*3); - btVector3 *bt= &m_vertexArray[0]; + btScalar *bt= &m_vertexArray[0]; int *poly_index_pt= &m_polygonIndexArray[0]; int *tri_pt= &m_triFaceArray[0]; - for (int p2=0; p2<numpolys; p2++) { - RAS_Polygon* poly= meshobj->GetPolygon(p2); + MFace* mf = &mface[p2]; + RAS_Polygon* poly= meshobj->GetPolygon(index[p2]); // only add polygons that have the collisionflag set if (poly->IsCollider()) { - RAS_TexVert *v1= poly->GetVertex(0); - RAS_TexVert *v2= poly->GetVertex(1); - RAS_TexVert *v3= poly->GetVertex(2); - int i1= v1->getOrigIndex(); - int i2= v2->getOrigIndex(); - int i3= v3->getOrigIndex(); - const float* vtx; + MVert *v1= &mvert[mf->v1]; + MVert *v2= &mvert[mf->v2]; + MVert *v3= &mvert[mf->v3]; // the face indicies - tri_pt[0]= vert_remap_array[i1]; - tri_pt[1]= vert_remap_array[i2]; - tri_pt[2]= vert_remap_array[i3]; + tri_pt[0]= vert_remap_array[mf->v1]; + tri_pt[1]= vert_remap_array[mf->v2]; + tri_pt[2]= vert_remap_array[mf->v3]; tri_pt= tri_pt+3; // m_polygonIndexArray - *poly_index_pt= p2; + *poly_index_pt= index[p2]; poly_index_pt++; // the vertex location - if (vert_tag_array[i1]==true) { /* *** v1 *** */ - vert_tag_array[i1]= false; - vtx = v1->getXYZ(); - bt->setX(vtx[0]); bt->setY( vtx[1]); bt->setZ(vtx[2]); - bt++; + if (vert_tag_array[mf->v1]==true) { /* *** v1 *** */ + vert_tag_array[mf->v1]= false; + *bt++ = v1->co[0]; + *bt++ = v1->co[1]; + *bt++ = v1->co[2]; } - if (vert_tag_array[i2]==true) { /* *** v2 *** */ - vert_tag_array[i2]= false; - vtx = v2->getXYZ(); - bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]); - bt++; + if (vert_tag_array[mf->v2]==true) { /* *** v2 *** */ + vert_tag_array[mf->v2]= false; + *bt++ = v2->co[0]; + *bt++ = v2->co[1]; + *bt++ = v2->co[2]; } - if (vert_tag_array[i3]==true) { /* *** v3 *** */ - vert_tag_array[i3]= false; - vtx = v3->getXYZ(); - bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]); - bt++; + if (vert_tag_array[mf->v3]==true) { /* *** v3 *** */ + vert_tag_array[mf->v3]= false; + *bt++ = v3->co[0]; + *bt++ = v3->co[1]; + *bt++ = v3->co[2]; } - if (poly->VertexCount()==4) + if (mf->v4) { - RAS_TexVert *v4= poly->GetVertex(3); - int i4= v4->getOrigIndex(); + MVert *v4= &mvert[mf->v4]; - tri_pt[0]= vert_remap_array[i1]; - tri_pt[1]= vert_remap_array[i3]; - tri_pt[2]= vert_remap_array[i4]; + tri_pt[0]= vert_remap_array[mf->v1]; + tri_pt[1]= vert_remap_array[mf->v3]; + tri_pt[2]= vert_remap_array[mf->v4]; tri_pt= tri_pt+3; // m_polygonIndexArray - *poly_index_pt= p2; + *poly_index_pt= index[p2]; poly_index_pt++; // the vertex location - if (vert_tag_array[i4]==true) { /* *** v4 *** */ - vert_tag_array[i4]= false; - vtx = v4->getXYZ(); - bt->setX(vtx[0]); bt->setY(vtx[1]); bt->setZ(vtx[2]); - bt++; + if (vert_tag_array[mf->v4]==true) { /* *** v4 *** */ + vert_tag_array[mf->v4]= false; + *bt++ = v4->co[0]; + *bt++ = v4->co[1]; + *bt++ = v4->co[2]; } } } @@ -1514,7 +1599,13 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, bool polytope,bo #endif m_meshObject = meshobj; - if (!polytope) + if (free_dm) { + dm->release(dm); + dm = NULL; + } + + // sharing only on static mesh at present, if you change that, you must also change in FindMesh + if (!polytope && !dm && !useGimpact) { // triangle shape can be shared, store the mesh object in the map m_meshShapeMap.insert(std::pair<RAS_MeshObject*,CcdShapeConstructionInfo*>(meshobj,this)); @@ -1533,15 +1624,13 @@ bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo) return true; } -btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() +btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin) { btCollisionShape* collisionShape = 0; - btTriangleMeshShape* concaveShape = 0; - btCompoundShape* compoundShape = 0; - CcdShapeConstructionInfo* nextShapeInfo; + btCompoundShape* compoundShape = 0; if (m_shapeType == PHY_SHAPE_PROXY && m_shapeProxy != NULL) - return m_shapeProxy->CreateBulletShape(); + return m_shapeProxy->CreateBulletShape(margin); switch (m_shapeType) { @@ -1550,22 +1639,27 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() case PHY_SHAPE_BOX: collisionShape = new btBoxShape(m_halfExtend); + collisionShape->setMargin(margin); break; case PHY_SHAPE_SPHERE: collisionShape = new btSphereShape(m_radius); + collisionShape->setMargin(margin); break; case PHY_SHAPE_CYLINDER: collisionShape = new btCylinderShapeZ(m_halfExtend); + collisionShape->setMargin(margin); break; case PHY_SHAPE_CONE: collisionShape = new btConeShapeZ(m_radius, m_height); + collisionShape->setMargin(margin); break; case PHY_SHAPE_POLYTOPE: - collisionShape = new btConvexHullShape(&m_vertexArray[0].getX(), m_vertexArray.size()); + collisionShape = new btConvexHullShape(&m_vertexArray[0], m_vertexArray.size()/3, 3*sizeof(btScalar)); + collisionShape->setMargin(margin); break; case PHY_SHAPE_MESH: @@ -1582,13 +1676,13 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() m_polygonIndexArray.size(), &m_triFaceArray[0], 3*sizeof(int), - m_vertexArray.size(), - (btScalar*) &m_vertexArray[0].x(), - sizeof(btVector3) + m_vertexArray.size()/3, + &m_vertexArray[0], + 3*sizeof(btScalar) ); btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(indexVertexArrays); - + gimpactShape->setMargin(margin); collisionShape = gimpactShape; gimpactShape->updateBound(); @@ -1606,13 +1700,14 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() collisionMeshData->m_weldingThreshold = m_weldingThreshold1; bool removeDuplicateVertices=true; // m_vertexArray not in multiple of 3 anymore, use m_triFaceArray - for(int i=0; i<m_triFaceArray.size(); i+=3) { - collisionMeshData->addTriangle( - m_vertexArray[m_triFaceArray[i]], - m_vertexArray[m_triFaceArray[i+1]], - m_vertexArray[m_triFaceArray[i+2]], - removeDuplicateVertices - ); + for(unsigned int i=0; i<m_triFaceArray.size(); i+=3) { + btScalar *bt = &m_vertexArray[3*m_triFaceArray[i]]; + btVector3 v1(bt[0], bt[1], bt[2]); + bt = &m_vertexArray[3*m_triFaceArray[i+1]]; + btVector3 v2(bt[0], bt[1], bt[2]); + bt = &m_vertexArray[3*m_triFaceArray[i+2]]; + btVector3 v3(bt[0], bt[1], bt[2]); + collisionMeshData->addTriangle(v1, v2, v3, removeDuplicateVertices); } indexVertexArrays = collisionMeshData; @@ -1622,9 +1717,9 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() m_polygonIndexArray.size(), &m_triFaceArray[0], 3*sizeof(int), - m_vertexArray.size(), - (btScalar*) &m_vertexArray[0].x(), - sizeof(btVector3)); + m_vertexArray.size()/3, + &m_vertexArray[0], + 3*sizeof(btScalar)); } // this shape will be shared and not deleted until shapeInfo is deleted @@ -1632,6 +1727,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() m_unscaledShape->recalcLocalAabb(); } collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); + collisionShape->setMargin(margin); } break; @@ -1643,7 +1739,7 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape() sit != m_shapeArray.end(); sit++) { - collisionShape = (*sit)->CreateBulletShape(); + collisionShape = (*sit)->CreateBulletShape(margin); if (collisionShape) { collisionShape->setLocalScaling((*sit)->m_childScale); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 4510bbddf65..d73759bac76 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -36,6 +36,7 @@ extern bool gDisableDeactivation; class CcdPhysicsEnvironment; class btMotionState; class RAS_MeshObject; +struct DerivedMesh; class btCollisionShape; @@ -59,7 +60,7 @@ class CcdShapeConstructionInfo public: - static CcdShapeConstructionInfo* FindMesh(RAS_MeshObject* mesh, bool polytope); + static CcdShapeConstructionInfo* FindMesh(class RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope, bool gimpact); CcdShapeConstructionInfo() : m_shapeType(PHY_SHAPE_NONE), @@ -139,7 +140,7 @@ public: return true; } - bool SetMesh(RAS_MeshObject* mesh, bool polytope,bool useGimpact); + bool SetMesh(class RAS_MeshObject* mesh, struct DerivedMesh* dm, bool polytope,bool useGimpact); RAS_MeshObject* GetMesh(void) { return m_meshObject; @@ -151,7 +152,7 @@ public: return m_shapeProxy; } - btCollisionShape* CreateBulletShape(); + btCollisionShape* CreateBulletShape(btScalar margin); // member variables PHY_ShapeType m_shapeType; @@ -161,8 +162,8 @@ public: btTransform m_childTrans; btVector3 m_childScale; void* m_userData; - btAlignedObjectArray<btVector3> m_vertexArray; // Contains both vertex array for polytope shape and - // triangle array for concave mesh shape. + btAlignedObjectArray<btScalar> m_vertexArray; // Contains both vertex array for polytope shape and + // triangle array for concave mesh shape. Each vertex is 3 consecutive values // In this case a triangle is made of 3 consecutive points std::vector<int> m_polygonIndexArray; // Contains the array of polygon index in the // original mesh that correspond to shape triangles. @@ -173,11 +174,7 @@ public: void setVertexWeldingThreshold1(float threshold) { - m_weldingThreshold1 = threshold; - } - float getVertexWeldingThreshold1() const - { - return m_weldingThreshold1; + m_weldingThreshold1 = threshold*threshold; } protected: static std::map<RAS_MeshObject*, CcdShapeConstructionInfo*> m_meshShapeMap; @@ -225,6 +222,7 @@ struct CcdConstructionInfo m_collisionFlags(0), m_bRigid(false), m_bSoft(false), + m_bSensor(false), m_collisionFilterGroup(DefaultFilter), m_collisionFilterMask(AllFilter), m_collisionShape(0), @@ -233,7 +231,8 @@ struct CcdConstructionInfo m_physicsEnv(0), m_inertiaFactor(1.f), m_do_anisotropic(false), - m_anisotropicFriction(1.f,1.f,1.f) + m_anisotropicFriction(1.f,1.f,1.f), + m_contactProcessingThreshold(1e10) { } @@ -291,6 +290,7 @@ struct CcdConstructionInfo int m_collisionFlags; bool m_bRigid; bool m_bSoft; + bool m_bSensor; ///optional use of collision group/mask: ///only collision with object goups that match the collision mask. @@ -318,6 +318,13 @@ struct CcdConstructionInfo btScalar m_fh_distance; ///< The range above the surface where Fh is active. bool m_fh_normal; ///< Should the object slide off slopes? float m_radius;//for fh backwards compatibility + + ///m_contactProcessingThreshold allows to process contact points with positive distance + ///normally only contacts with negative distance (penetration) are solved + ///however, rigid body stacking is more stable when positive contacts are still passed into the constraint solver + ///this might sometimes lead to collisions with 'internal edges' such as a sliding character controller + ///so disable/set m_contactProcessingThreshold to zero for sliding characters etc. + float m_contactProcessingThreshold;///< Process contacts with positive distance in range [0..INF] }; @@ -329,7 +336,7 @@ class btSoftBody; ///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution. class CcdPhysicsController : public PHY_IPhysicsController { - +protected: btCollisionObject* m_object; @@ -364,8 +371,8 @@ class CcdPhysicsController : public PHY_IPhysicsController return (--m_registerCount == 0) ? true : false; } - protected: - void setWorldOrientation(const btMatrix3x3& mat); + void setWorldOrientation(const btMatrix3x3& mat); + void forceWorldTransform(const btMatrix3x3& mat, const btVector3& pos); public: @@ -410,6 +417,7 @@ class CcdPhysicsController : public PHY_IPhysicsController virtual void WriteMotionStateToDynamics(bool nondynaonly); virtual void WriteDynamicsToMotionState(); + // controller replication virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl); @@ -508,7 +516,7 @@ class CcdPhysicsController : public PHY_IPhysicsController void SetCenterOfMassTransform(btTransform& xform); - static btTransform GetTransformFromMotionState(PHY_IMotionState* motionState); + static btTransform& GetTransformFromMotionState(PHY_IMotionState* motionState); void setAabb(const btVector3& aabbMin,const btVector3& aabbMax); @@ -566,6 +574,7 @@ class DefaultMotionState : public PHY_IMotionState virtual void setWorldPosition(float posX,float posY,float posZ); virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal); virtual void getWorldOrientation(float* ori); + virtual void setWorldOrientation(const float* ori); virtual void calculateWorldTransformations(); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index 3e1e0294321..bc7ccacc39b 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -415,61 +415,7 @@ void CcdPhysicsEnvironment::addCcdPhysicsController(CcdPhysicsController* ctrl) obj->setActivationState(ISLAND_SLEEPING); } - - //CollisionObject(body,ctrl->GetCollisionFilterGroup(),ctrl->GetCollisionFilterMask()); - assert(obj->getBroadphaseHandle()); - - btBroadphaseInterface* scene = getBroadphase(); - - - btCollisionShape* shapeinterface = ctrl->GetCollisionShape(); - - assert(shapeinterface); - - const btTransform& t = ctrl->GetCollisionObject()->getWorldTransform(); - - - btVector3 minAabb,maxAabb; - - shapeinterface->getAabb(t,minAabb,maxAabb); - - float timeStep = 0.02f; - - - //extent it with the motion - - if (body) - { - btVector3 linMotion = body->getLinearVelocity()*timeStep; - - float maxAabbx = maxAabb.getX(); - float maxAabby = maxAabb.getY(); - float maxAabbz = maxAabb.getZ(); - float minAabbx = minAabb.getX(); - float minAabby = minAabb.getY(); - float minAabbz = minAabb.getZ(); - - if (linMotion.x() > 0.f) - maxAabbx += linMotion.x(); - else - minAabbx += linMotion.x(); - if (linMotion.y() > 0.f) - maxAabby += linMotion.y(); - else - minAabby += linMotion.y(); - if (linMotion.z() > 0.f) - maxAabbz += linMotion.z(); - else - minAabbz += linMotion.z(); - - - minAabb = btVector3(minAabbx,minAabby,minAabbz); - maxAabb = btVector3(maxAabbx,maxAabby,maxAabbz); - } - - - } @@ -480,6 +426,13 @@ void CcdPhysicsEnvironment::removeCcdPhysicsController(CcdPhysicsController* ctr btRigidBody* body = ctrl->GetRigidBody(); if (body) { + for (int i=body->getNumConstraintRefs()-1;i>=0;i--) + { + btTypedConstraint* con = body->getConstraintRef(i); + m_dynamicsWorld->removeConstraint(con); + body->removeConstraintRef(con); + //delete con; //might be kept by python KX_ConstraintWrapper + } m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); } else { @@ -533,6 +486,12 @@ void CcdPhysicsEnvironment::enableCcdPhysicsController(CcdPhysicsController* ctr { btCollisionObject* obj = ctrl->GetCollisionObject(); obj->setUserPointer(ctrl); + // update the position of the object from the user + if (ctrl->GetMotionState()) + { + btTransform xform = CcdPhysicsController::GetTransformFromMotionState(ctrl->GetMotionState()); + ctrl->SetCenterOfMassTransform(xform); + } m_dynamicsWorld->addCollisionObject(obj, ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); } @@ -573,7 +532,7 @@ void CcdPhysicsEnvironment::refreshCcdPhysicsController(CcdPhysicsController* ct void CcdPhysicsEnvironment::addCcdGraphicController(CcdGraphicController* ctrl) { - if (m_cullingTree) + if (m_cullingTree && !ctrl->getBroadphaseHandle()) { btVector3 minAabb; btVector3 maxAabb; @@ -617,7 +576,7 @@ void CcdPhysicsEnvironment::debugDrawWorld() m_dynamicsWorld->debugDrawWorld(); } -bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) +bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float interval) { std::set<CcdPhysicsController*>::iterator it; int i; @@ -627,14 +586,9 @@ bool CcdPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) (*it)->SynchronizeMotionStates(timeStep); } - processFhSprings(curTime,timeStep); - float subStep = timeStep / float(m_numTimeSubSteps); - for (i=0;i<m_numTimeSubSteps;i++) - { -// m_dynamicsWorld->stepSimulation(subStep,20,1./240.);//perform always a full simulation step - m_dynamicsWorld->stepSimulation(subStep,0);//perform always a full simulation step - } + i = m_dynamicsWorld->stepSimulation(interval,25,subStep);//perform always a full simulation step + processFhSprings(curTime,i*subStep); for (it=m_controllers.begin(); it!=m_controllers.end(); it++) { @@ -686,9 +640,11 @@ public: }; -void CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep) +void CcdPhysicsEnvironment::processFhSprings(double curTime,float interval) { std::set<CcdPhysicsController*>::iterator it; + // dynamic of Fh spring is based on a timestep of 1/60 + int numIter = (int)(interval*60.0001f); for (it=m_controllers.begin(); it!=m_controllers.end(); it++) { @@ -700,8 +656,6 @@ void CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep) //printf("has Fh or RotFh\n"); //re-implement SM_FhObject.cpp using btCollisionWorld::rayTest and info from ctrl->getConstructionInfo() //send a ray from {0.0, 0.0, 0.0} towards {0.0, 0.0, -10.0}, in local coordinates - - CcdPhysicsController* parentCtrl = ctrl->getParentCtrl(); btRigidBody* parentBody = parentCtrl?parentCtrl->GetRigidBody() : 0; btRigidBody* cl_object = parentBody ? parentBody : body; @@ -748,82 +702,78 @@ void CcdPhysicsEnvironment::processFhSprings(double curTime,float timeStep) btVector3 normal = resultCallback.m_hitNormalWorld; normal.normalize(); - - if (ctrl->getConstructionInfo().m_do_fh) + for (int i=0; i<numIter; i++) { - btVector3 lspot = cl_object->getCenterOfMassPosition() - + rayDirLocal * resultCallback.m_closestHitFraction; + if (ctrl->getConstructionInfo().m_do_fh) + { + btVector3 lspot = cl_object->getCenterOfMassPosition() + + rayDirLocal * resultCallback.m_closestHitFraction; + + + lspot -= hit_object->getCenterOfMassPosition(); + btVector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocityInLocalPoint(lspot); + btScalar rel_vel_ray = ray_dir.dot(rel_vel); + btScalar spring_extent = 1.0 - distance / hitObjShapeProps.m_fh_distance; + + btScalar i_spring = spring_extent * hitObjShapeProps.m_fh_spring; + btScalar i_damp = rel_vel_ray * hitObjShapeProps.m_fh_damping; + + cl_object->setLinearVelocity(cl_object->getLinearVelocity() + (-(i_spring + i_damp) * ray_dir)); + if (hitObjShapeProps.m_fh_normal) + { + cl_object->setLinearVelocity(cl_object->getLinearVelocity()+(i_spring + i_damp) *(normal - normal.dot(ray_dir) * ray_dir)); + } + btVector3 lateral = rel_vel - rel_vel_ray * ray_dir; + + + if (ctrl->getConstructionInfo().m_do_anisotropic) { + //Bullet basis contains no scaling/shear etc. + const btMatrix3x3& lcs = cl_object->getCenterOfMassTransform().getBasis(); + btVector3 loc_lateral = lateral * lcs; + const btVector3& friction_scaling = cl_object->getAnisotropicFriction(); + loc_lateral *= friction_scaling; + lateral = lcs * loc_lateral; + } - lspot -= hit_object->getCenterOfMassPosition(); - btVector3 rel_vel = cl_object->getLinearVelocity() - hit_object->getVelocityInLocalPoint(lspot); - btScalar rel_vel_ray = ray_dir.dot(rel_vel); - btScalar spring_extent = 1.0 - distance / hitObjShapeProps.m_fh_distance; - - btScalar i_spring = spring_extent * hitObjShapeProps.m_fh_spring; - btScalar i_damp = rel_vel_ray * hitObjShapeProps.m_fh_damping; - - cl_object->setLinearVelocity(cl_object->getLinearVelocity() + (-(i_spring + i_damp) * ray_dir)); - if (hitObjShapeProps.m_fh_normal) - { - cl_object->setLinearVelocity(cl_object->getLinearVelocity()+(i_spring + i_damp) *(normal - normal.dot(ray_dir) * ray_dir)); - } - - btVector3 lateral = rel_vel - rel_vel_ray * ray_dir; - - - if (ctrl->getConstructionInfo().m_do_anisotropic) { - //Bullet basis contains no scaling/shear etc. - const btMatrix3x3& lcs = cl_object->getCenterOfMassTransform().getBasis(); - btVector3 loc_lateral = lateral * lcs; - const btVector3& friction_scaling = cl_object->getAnisotropicFriction(); - loc_lateral *= friction_scaling; - lateral = lcs * loc_lateral; + btScalar rel_vel_lateral = lateral.length(); + + if (rel_vel_lateral > SIMD_EPSILON) { + btScalar friction_factor = hit_object->getFriction();//cl_object->getFriction(); + + btScalar max_friction = friction_factor * btMax(btScalar(0.0), i_spring); + + btScalar rel_mom_lateral = rel_vel_lateral / cl_object->getInvMass(); + + btVector3 friction = (rel_mom_lateral > max_friction) ? + -lateral * (max_friction / rel_vel_lateral) : + -lateral; + + cl_object->applyCentralImpulse(friction); + } } - btScalar rel_vel_lateral = lateral.length(); - if (rel_vel_lateral > SIMD_EPSILON) { - btScalar friction_factor = hit_object->getFriction();//cl_object->getFriction(); + if (ctrl->getConstructionInfo().m_do_rot_fh) { + btVector3 up2 = cl_object->getWorldTransform().getBasis().getColumn(2); - btScalar max_friction = friction_factor * btMax(btScalar(0.0), i_spring); + btVector3 t_spring = up2.cross(normal) * hitObjShapeProps.m_fh_spring; + btVector3 ang_vel = cl_object->getAngularVelocity(); - btScalar rel_mom_lateral = rel_vel_lateral / cl_object->getInvMass(); + // only rotations that tilt relative to the normal are damped + ang_vel -= ang_vel.dot(normal) * normal; - btVector3 friction = (rel_mom_lateral > max_friction) ? - -lateral * (max_friction / rel_vel_lateral) : - -lateral; + btVector3 t_damp = ang_vel * hitObjShapeProps.m_fh_damping; - cl_object->applyCentralImpulse(friction); + cl_object->setAngularVelocity(cl_object->getAngularVelocity() + (t_spring - t_damp)); } } - - - if (ctrl->getConstructionInfo().m_do_rot_fh) { - btVector3 up2 = cl_object->getWorldTransform().getBasis().getColumn(2); - - btVector3 t_spring = up2.cross(normal) * hitObjShapeProps.m_fh_spring; - btVector3 ang_vel = cl_object->getAngularVelocity(); - - // only rotations that tilt relative to the normal are damped - ang_vel -= ang_vel.dot(normal) * normal; - - btVector3 t_damp = ang_vel * hitObjShapeProps.m_fh_damping; - - cl_object->setAngularVelocity(cl_object->getAngularVelocity() + (t_spring - t_damp)); - } - } - - } - - } } - } void CcdPhysicsEnvironment::setDebugMode(int debugMode) @@ -972,7 +922,7 @@ int CcdPhysicsEnvironment::createUniversalD6Constraint( bool useReferenceFrameA = true; - genericConstraint = new btGeneric6DofConstraint( + genericConstraint = new btGeneric6DofSpringConstraint( *rb0,*rb1, frameInA,frameInB,useReferenceFrameA); genericConstraint->setLinearLowerLimit(linearMinLimits); @@ -1053,7 +1003,7 @@ struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResul virtual btScalar addSingleResult(btCollisionWorld::LocalRayResult& rayResult,bool normalInWorldSpace) { - CcdPhysicsController* curHit = static_cast<CcdPhysicsController*>(rayResult.m_collisionObject->getUserPointer()); + //CcdPhysicsController* curHit = static_cast<CcdPhysicsController*>(rayResult.m_collisionObject->getUserPointer()); // save shape information as ClosestRayResultCallback::AddSingleResult() does not do it if (rayResult.m_localShapeInfo) { @@ -1071,10 +1021,6 @@ struct FilterClosestRayResultCallback : public btCollisionWorld::ClosestRayResul PHY_IPhysicsController* CcdPhysicsEnvironment::rayTest(PHY_IRayCastFilterCallback &filterCallback, float fromX,float fromY,float fromZ, float toX,float toY,float toZ) { - - - float minFraction = 1.f; - btVector3 rayFrom(fromX,fromY,fromZ); btVector3 rayTo(toX,toY,toZ); @@ -1224,7 +1170,7 @@ struct OcclusionBuffer { m_initialized=false; m_occlusion = false; - m_buffer == NULL; + m_buffer = NULL; m_bufferSize = 0; } // multiplication of column major matrices: m=m1*m2 @@ -1332,8 +1278,7 @@ struct OcclusionBuffer static bool project(btVector4* p,int n) { for(int i=0;i<n;++i) - { - const btScalar iw=1/p[i][3]; + { p[i][2]=1/p[i][3]; p[i][0]*=p[i][2]; p[i][1]*=p[i][2]; @@ -1651,7 +1596,7 @@ struct OcclusionBuffer 6,5,1,2, 7,6,2,3, 5,4,0,1}; - for(int i=0;i<(sizeof(d)/sizeof(d[0]));) + for(unsigned int i=0;i<(sizeof(d)/sizeof(d[0]));) { const btVector4 p[]={ x[d[i++]], x[d[i++]], @@ -1841,6 +1786,45 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment() } +float CcdPhysicsEnvironment::getConstraintParam(int constraintId,int param) +{ + btTypedConstraint* typedConstraint = getConstraintById(constraintId); + switch (typedConstraint->getUserConstraintType()) + { + case PHY_GENERIC_6DOF_CONSTRAINT: + { + + switch (param) + { + case 0: case 1: case 2: + { + //param = 0..2 are linear constraint values + btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; + genCons->calculateTransforms(); + return genCons->getRelativePivotPosition(param); + break; + } + case 3: case 4: case 5: + { + //param = 3..5 are relative constraint (Euler) angles + btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; + genCons->calculateTransforms(); + return genCons->getAngle(param-3); + break; + } + default: + { + } + } + break; + }; + default: + { + }; + }; + return 0.f; +} + void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float value0,float value1) { btTypedConstraint* typedConstraint = getConstraintById(constraintId); @@ -1848,9 +1832,63 @@ void CcdPhysicsEnvironment::setConstraintParam(int constraintId,int param,float { case PHY_GENERIC_6DOF_CONSTRAINT: { - //param = 1..12, min0,max0,min1,max1...min6,max6 - btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; - genCons->setLimit(param,value0,value1); + + switch (param) + { + case 0: case 1: case 2: case 3: case 4: case 5: + { + //param = 0..5 are constraint limits, with low/high limit value + btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; + genCons->setLimit(param,value0,value1); + break; + } + case 6: case 7: case 8: + { + //param = 6,7,8 are translational motors, with value0=target velocity, value1 = max motor force + btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; + int transMotorIndex = param-6; + btTranslationalLimitMotor* transMotor = genCons->getTranslationalLimitMotor(); + transMotor->m_targetVelocity[transMotorIndex]= value0; + transMotor->m_maxMotorForce[transMotorIndex]=value1; + transMotor->m_enableMotor[transMotorIndex] = (value1>0.f); + break; + } + case 9: case 10: case 11: + { + //param = 9,10,11 are rotational motors, with value0=target velocity, value1 = max motor force + btGeneric6DofConstraint* genCons = (btGeneric6DofConstraint*)typedConstraint; + int angMotorIndex = param-9; + btRotationalLimitMotor* rotMotor = genCons->getRotationalLimitMotor(angMotorIndex); + rotMotor->m_enableMotor = (value1 > 0.f); + rotMotor->m_targetVelocity = value0; + rotMotor->m_maxMotorForce = value1; + break; + } + + case 12: case 13: case 14: case 15: case 16: case 17: + { + //param 13-17 are for motorized springs on each of the degrees of freedom + btGeneric6DofSpringConstraint* genCons = (btGeneric6DofSpringConstraint*)typedConstraint; + int springIndex = param-12; + if (value0!=0.f) + { + bool springEnabled = true; + genCons->setStiffness(springIndex,value0); + genCons->setDamping(springIndex,value1); + genCons->enableSpring(springIndex,springEnabled); + genCons->setEquilibriumPoint(springIndex); + } else + { + bool springEnabled = false; + genCons->enableSpring(springIndex,springEnabled); + } + break; + } + + default: + { + } + } break; }; default: @@ -1887,29 +1925,20 @@ void CcdPhysicsEnvironment::addSensor(PHY_IPhysicsController* ctrl) // 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; - //ctrl1->GetRigidBody()->getBroadphaseHandle()->m_collisionFilterGroup = btBroadphaseProxy::SensorTrigger; - //todo: make this 'sensor'! - - requestCollisionCallback(ctrl); - //printf("addSensor\n"); } -void CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) +bool CcdPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) { CcdPhysicsController* ccdCtrl = (CcdPhysicsController*)ctrl; - if (ccdCtrl->Unregister()) - m_triggerControllers.erase(ccdCtrl); + if (!ccdCtrl->Unregister()) + return false; + m_triggerControllers.erase(ccdCtrl); + return true; } void CcdPhysicsEnvironment::removeSensor(PHY_IPhysicsController* ctrl) { - removeCollisionCallback(ctrl); - disableCcdPhysicsController((CcdPhysicsController*)ctrl); } @@ -1945,19 +1974,18 @@ void CcdPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCal m_triggerCallbacksUserPtrs[response_class] = user; } -void CcdPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctrl) +bool CcdPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctrl) { CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl); - if (ccdCtrl->Register()) - m_triggerControllers.insert(ccdCtrl); + if (!ccdCtrl->Register()) + return false; + m_triggerControllers.insert(ccdCtrl); + return true; } void CcdPhysicsEnvironment::CallbackTriggers() { - - CcdPhysicsController* ctrl0=0,*ctrl1=0; - if (m_triggerCallbacks[PHY_OBJECT_RESPONSE] || (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints))) { //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback @@ -2099,12 +2127,13 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateSphereController(float radi // declare this object as Dyamic rather then static!! // The reason as it is designed to detect all type of object, including static object // It would cause static-static message to be printed on the console otherwise - cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE/* | btCollisionObject::CF_KINEMATIC_OBJECT*/; + cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE | btCollisionObject::CF_STATIC_OBJECT; DefaultMotionState* motionState = new DefaultMotionState(); cinfo.m_MotionState = motionState; // we will add later the possibility to select the filter from option cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter; cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter; + cinfo.m_bSensor = true; motionState->m_worldTransform.setIdentity(); motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2])); @@ -2373,7 +2402,7 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl frameInB = inv * globalFrameA; bool useReferenceFrameA = true; - genericConstraint = new btGeneric6DofConstraint( + genericConstraint = new btGeneric6DofSpringConstraint( *rb0,*rb1, frameInA,frameInB,useReferenceFrameA); @@ -2397,7 +2426,7 @@ int CcdPhysicsEnvironment::createConstraint(class PHY_IPhysicsController* ctrl frameInB = rb0->getCenterOfMassTransform() * frameInA; bool useReferenceFrameA = true; - genericConstraint = new btGeneric6DofConstraint( + genericConstraint = new btGeneric6DofSpringConstraint( *rb0,s_fixedObject2, frameInA,frameInB,useReferenceFrameA); } @@ -2558,13 +2587,14 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float conera cinfo.m_collisionShape = new btConeShape(coneradius,coneheight); cinfo.m_MotionState = 0; cinfo.m_physicsEnv = this; - cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE; + cinfo.m_collisionFlags |= btCollisionObject::CF_NO_CONTACT_RESPONSE | btCollisionObject::CF_STATIC_OBJECT; DefaultMotionState* motionState = new DefaultMotionState(); cinfo.m_MotionState = motionState; // we will add later the possibility to select the filter from option cinfo.m_collisionFilterMask = CcdConstructionInfo::AllFilter ^ CcdConstructionInfo::SensorFilter; cinfo.m_collisionFilterGroup = CcdConstructionInfo::SensorFilter; + cinfo.m_bSensor = true; motionState->m_worldTransform.setIdentity(); // motionState->m_worldTransform.setOrigin(btVector3(position[0],position[1],position[2])); diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index f861621ae37..bc5491e00cc 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -114,7 +114,7 @@ protected: virtual void beginFrame(); virtual void endFrame() {}; /// Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep); + virtual bool proceedDeltaTime(double curTime,float timeStep,float interval); virtual void debugDrawWorld(); // virtual bool proceedDeltaTimeOneStep(float timeStep); @@ -149,7 +149,10 @@ protected: const btVector3& angularMaxLimits,int flags ); + virtual void setConstraintParam(int constraintId,int param,float value,float value1); + + virtual float getConstraintParam(int constraintId,int param); virtual void removeConstraint(int constraintid); @@ -179,8 +182,8 @@ protected: virtual void addSensor(PHY_IPhysicsController* ctrl); 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 bool requestCollisionCallback(PHY_IPhysicsController* ctrl); + virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl); //These two methods are used *solely* to create controllers for Near/Radar sensor! Don't use for anything else virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position); virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight); diff --git a/source/gameengine/Physics/Bullet/Makefile b/source/gameengine/Physics/Bullet/Makefile index 48e537bb6a3..19b17de275a 100644 --- a/source/gameengine/Physics/Bullet/Makefile +++ b/source/gameengine/Physics/Bullet/Makefile @@ -51,4 +51,6 @@ CPPFLAGS += -I../../Expressions CPPFLAGS += -I../../GameLogic CPPFLAGS += -I../../SceneGraph CPPFLAGS += -I../../../../source/blender/makesdna +CPPFLAGS += -I../../../../source/blender/blenkernel +CPPFLAGS += -I../../../../source/blender/blenlib diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript index ab2c68ddfd5..ed53e8112cd 100644 --- a/source/gameengine/Physics/Bullet/SConscript +++ b/source/gameengine/Physics/Bullet/SConscript @@ -14,7 +14,10 @@ incs += ' #source/gameengine/Expressions' incs += ' #source/gameengine/GameLogic' incs += ' #source/gameengine/SceneGraph' incs += ' #source/blender/makesdna' +incs += ' #source/blender/blenkernel' +incs += ' #source/blender/blenlib' incs += ' #intern/SoundSystem' +incs += ' #intern/guardedalloc' incs += ' ' + env['BF_BULLET_INC'] incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp index ba196b5cf55..e41574ff181 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp @@ -57,7 +57,7 @@ void DummyPhysicsEnvironment::endFrame() -bool DummyPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) +bool DummyPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float interval) { //step physics simulation, typically perform diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index 4e15e6ec130..8dbd137f9de 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -48,7 +48,7 @@ public: virtual void beginFrame(); virtual void endFrame(); // Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep); + virtual bool proceedDeltaTime(double curTime,float timeStep,float interval); virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep); virtual float getFixedTimeStep(); @@ -79,8 +79,8 @@ public: virtual void addTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) { } - virtual void requestCollisionCallback(PHY_IPhysicsController* ctrl) {} - virtual void removeCollisionCallback(PHY_IPhysicsController* ctrl) {} + virtual bool requestCollisionCallback(PHY_IPhysicsController* ctrl) { return false; } + virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl) { return false;} virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position) {return 0;} virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight) { return 0;} @@ -88,6 +88,11 @@ public: { } + virtual float getConstraintParam(int constraintId,int param) + { + return 0.f; + } + }; #endif //_DUMMYPHYSICSENVIRONMENT diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp index 3451e6c3ec8..56caa9236bf 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp +++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.cpp @@ -390,6 +390,11 @@ void SumoPhysicsController::PostProcessReplica(class PHY_IMotionState* motionst m_sumoScene->add(* (m_sumoObj)); } +PHY_IMotionState* SumoPhysicsController::GetMotionState() +{ + return m_MotionState; +} + void SumoPhysicsController::SetSimulatedTime(float) { } diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsController.h b/source/gameengine/Physics/Sumo/SumoPhysicsController.h index 415bc1e3982..adf29649f18 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsController.h +++ b/source/gameengine/Physics/Sumo/SumoPhysicsController.h @@ -110,6 +110,7 @@ public: virtual void WriteDynamicsToMotionState() {}; virtual void WriteMotionStateToDynamics(bool nondynaonly); + virtual class PHY_IMotionState* GetMotionState(); /** * call from Scene Graph Node to 'update'. diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp index 3be5e027345..b4daf0a3f80 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.cpp @@ -81,7 +81,7 @@ float SumoPhysicsEnvironment::getFixedTimeStep() } -bool SumoPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep) +bool SumoPhysicsEnvironment::proceedDeltaTime(double curTime,float timeStep,float interval) { bool result = false; @@ -213,7 +213,7 @@ void SumoPhysicsEnvironment::addTouchCallback(int response_class, PHY_ResponseCa m_sumoScene->addTouchCallback(sumoRespClass,SumoPHYCallbackBridge::StaticSolidToPHYCallback,bridge); } -void SumoPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctrl) +bool SumoPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ctrl) { SumoPhysicsController* smctrl = dynamic_cast<SumoPhysicsController*>(ctrl); MT_assert(smctrl); @@ -225,12 +225,15 @@ void SumoPhysicsEnvironment::requestCollisionCallback(PHY_IPhysicsController* ct smObject->setPhysicsClientObject(ctrl); m_sumoScene->requestCollisionCallback(*smObject); + return true; } + return false; } -void SumoPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) +bool SumoPhysicsEnvironment::removeCollisionCallback(PHY_IPhysicsController* ctrl) { // intentionally empty + return false; } PHY_IPhysicsController* SumoPhysicsEnvironment::CreateSphereController(float radius,const PHY__Vector3& position) diff --git a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h index 418a361a065..5ae33eb4b0e 100644 --- a/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h +++ b/source/gameengine/Physics/Sumo/SumoPhysicsEnvironment.h @@ -54,7 +54,7 @@ public: virtual void beginFrame(); virtual void endFrame(); // Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep); + virtual bool proceedDeltaTime(double curTime,float timeStep,float interval); virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep); virtual float getFixedTimeStep(); @@ -83,11 +83,15 @@ public: virtual void addSensor(PHY_IPhysicsController* ctrl); 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 bool requestCollisionCallback(PHY_IPhysicsController* ctrl); + virtual bool removeCollisionCallback(PHY_IPhysicsController* ctrl); virtual PHY_IPhysicsController* CreateSphereController(float radius,const PHY__Vector3& position); virtual PHY_IPhysicsController* CreateConeController(float coneradius,float coneheight); + virtual float getConstraintParam(int constraintId,int param) + { + return 0.f; + } virtual void setConstraintParam(int constraintId,int param,float value,float value1) { } diff --git a/source/gameengine/Physics/common/PHY_IGraphicController.h b/source/gameengine/Physics/common/PHY_IGraphicController.h index 36b8a978e87..470d42cb84a 100644 --- a/source/gameengine/Physics/common/PHY_IGraphicController.h +++ b/source/gameengine/Physics/common/PHY_IGraphicController.h @@ -47,6 +47,9 @@ class PHY_IGraphicController : public PHY_IController SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding') */ virtual bool SetGraphicTransform()=0; + virtual void Activate(bool active=true)=0; + virtual void setLocalAabb(const PHY__Vector3& aabbMin,const PHY__Vector3& aabbMax)=0; + virtual void setLocalAabb(const float* aabbMin,const float* aabbMax)=0; virtual PHY_IGraphicController* GetReplica(class PHY_IMotionState* motionstate) {return 0;} diff --git a/source/gameengine/Physics/common/PHY_IMotionState.h b/source/gameengine/Physics/common/PHY_IMotionState.h index 64bb810ee7c..f7bcbd4f2d0 100644 --- a/source/gameengine/Physics/common/PHY_IMotionState.h +++ b/source/gameengine/Physics/common/PHY_IMotionState.h @@ -45,10 +45,12 @@ class PHY_IMotionState virtual void getWorldOrientation(float& quatIma0,float& quatIma1,float& quatIma2,float& quatReal)=0; // ori = array 12 floats, [0..3] = first column + 0, [4..7] = second colum, [8..11] = third column virtual void getWorldOrientation(float* ori)=0; + virtual void setWorldOrientation(const float* ori)=0; virtual void setWorldPosition(float posX,float posY,float posZ)=0; virtual void setWorldOrientation(float quatIma0,float quatIma1,float quatIma2,float quatReal)=0; + virtual void calculateWorldTransformations()=0; }; diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h index 770426b48db..d7b8cb0b54f 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsController.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h @@ -31,7 +31,7 @@ #include "PHY_IController.h" - +class PHY_IMotionState; /** PHY_IPhysicsController is the abstract simplified Interface to a physical object. @@ -53,6 +53,7 @@ class PHY_IPhysicsController : public PHY_IController virtual void WriteMotionStateToDynamics(bool nondynaonly)=0; virtual void WriteDynamicsToMotionState()=0; + virtual class PHY_IMotionState* GetMotionState() = 0; // controller replication virtual void PostProcessReplica(class PHY_IMotionState* motionstate,class PHY_IPhysicsController* parentctrl)=0; diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 9a4500c3214..c76e9d175ce 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -89,7 +89,7 @@ class PHY_IPhysicsEnvironment virtual void beginFrame() = 0; virtual void endFrame() = 0; /// Perform an integration step of duration 'timeStep'. - virtual bool proceedDeltaTime(double curTime,float timeStep)=0; + virtual bool proceedDeltaTime(double curTime,float timeStep,float interval)=0; ///draw debug lines (make sure to call this during the render phase, otherwise lines are not drawn properly) virtual void debugDrawWorld(){} virtual void setFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep)=0; @@ -152,13 +152,14 @@ class PHY_IPhysicsEnvironment virtual void addSensor(PHY_IPhysicsController* ctrl)=0; 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; + virtual bool requestCollisionCallback(PHY_IPhysicsController* ctrl)=0; + virtual bool 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; virtual void setConstraintParam(int constraintId,int param,float value,float value1) = 0; + virtual float getConstraintParam(int constraintId,int param) = 0; }; #endif //_IPHYSICSENVIRONMENT diff --git a/source/gameengine/PyDoc/API_intro.py b/source/gameengine/PyDoc/API_intro.py new file mode 100644 index 00000000000..ad37e34fbac --- /dev/null +++ b/source/gameengine/PyDoc/API_intro.py @@ -0,0 +1,103 @@ +# This is not a real module, it's simply an introductory text. + +""" +The Blender Game Engine Python API Reference +============================================ + + See U{release notes<http://wiki.blender.org/index.php/Dev:Ref/Release_Notes/2.49/Game_Engine>} for updates, changes and new functionality in the Game Engine Python API. + + Top Module: + ----------- + + - L{GameLogic} + - L{GameKeys} + - L{GameTypes} + - L{Mathutils} + - L{Geometry} + - L{BGL} + + Undocumented modules: + --------------------- + - VideoTexture + - CValue + - Expression + - PhysicsConstraints + + +Introduction: +============= + + This reference documents the Blender Python API, a growing collection of + Python modules (libraries) that give access to part of the program's internal + data and functions. + + Through scripting Blender can be extended in real-time via + U{Python <www.python.org>}, an impressive high level, multi-paradigm, open + source language. Newcomers are recommended to start with the tutorial that + comes with it. + + This opens many interesting possibilities not available with logic bricks. + + Game Engine API Stability: + -------------------------- + + When writing python scripts there are a number of situations you should avoid to prevent crashes or unstable behavior. + While the API tries to prevent problems there are some situations where error checking would be too time consuming. + + Known cases: + - Memory Limits. + + There is nothing stopping you from filling a list or making a string so big that that causes blender to run out of memory, in this case python should rasie a MemoryError, but its likely blender will crash before this point. + + - Accessing any data that has been freed. + + For instance accessing a KX_GameObject after its End Object actuator runs. + This will cause a SystemError, however for L{KX_MeshProxy}, L{KX_VertexProxy} and L{KX_VertexProxy} it will crash the blender game engine. + + See: L{GameTypes.PyObjectPlus.invalid} which many types inherit. + + - Mixing L{KX_GameObject} between scenes. + + For instance tracking/parenting an L{KX_GameObject} object to an object from other scene. + + External Modules: + ----------------- + + Since 2.49 support for importing modules has been added. + + This allows you to import any blender textblock with a .py extension. + + External python scripts may be imported as modules when the script is in the same directory as the blend file. + + The current blend files path is included in the sys.path for loading modules. + All linked libraries will also be included so you can be sure when linking in assets from another blend file the scripts will load too. + + A note to newbie script writers: + -------------------------------- + + Interpreted languages are known to be much slower than compiled code, but for + many applications the difference is negligible or acceptable. Also, with + profiling (or even simple direct timing with L{Blender.sys.time<Sys.time>}) to + identify slow areas and well thought optimizations, the speed can be + I{considerably} improved in many cases. Try some of the best BPython scripts + to get an idea of what can be done, you may be surprised. + +@author: The Blender Python Team +@requires: Blender 2.49 or newer. +@version: 2.49 +@see: U{www.blender.org<http://www.blender.org>}: documentation and forum +@see: U{blenderartists.org<http://blenderartists.org>}: user forum +@see: U{projects.blender.org<http://projects.blender.org>} +@see: U{www.python.org<http://www.python.org>} +@see: U{www.python.org/doc<http://www.python.org/doc>} +@see: U{Blending into Python<en.wikibooks.org/wiki/Blender_3D:_Blending_Into_Python>}: User contributed documentation, featuring a blender/python cookbook with many examples. + +@note: the official version of this reference guide is only updated for each + new Blender release. But you can build the current SVN + version yourself: install epydoc, grab all files in the + source/gameengine/PyDoc/ folder of Blender's SVN and use the + epy_docgen.sh script also found there to generate the html docs. + Naturally you will also need a recent Blender binary to try the new + features. If you prefer not to compile it yourself, there is a testing + builds forum at U{blender.org<http://www.blender.org>}. +""" diff --git a/source/gameengine/PyDoc/BL_ActionActuator.py b/source/gameengine/PyDoc/BL_ActionActuator.py deleted file mode 100644 index 480681dc14a..00000000000 --- a/source/gameengine/PyDoc/BL_ActionActuator.py +++ /dev/null @@ -1,230 +0,0 @@ -# $Id$ -# Documentation for BL_ActionActuator -import SCA_ILogicBrick -from SCA_IActuator import * - - -class BL_ActionActuator(SCA_IActuator): - """ - Action Actuators apply an action to an actor. - - @ivar action: The name of the action to set as the current action. - @type action: string - @ivar start: Specifies the starting frame of the animation. - @type start: float - @ivar end: Specifies the ending frame of the animation. - @type end: float - @ivar blendin: Specifies the number of frames of animation to generate when making transitions between actions. - @type blendin: float - @ivar priority: Sets the priority of this actuator. Actuators will lower - priority numbers will override actuators with higher - numbers. - @type priority: integer - @ivar frame: Sets the current frame for the animation. - @type frame: float - @ivar property: Sets the property to be used in FromProp playback mode. - @type property: string - @ivar blendTime: Sets the internal frame timer. This property must be in - the range from 0.0 to blendin. - @type blendTime: float - @ivar type: The operation mode of the actuator. KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND - @type type: integer - @ivar continue: The actions continue option, True or False. - 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. - @type: boolean - @ivar frameProperty: The name of the property that is set to the current frame number. - @type frameProperty: string - """ - def setChannel(channel, matrix, mode = False): - """ - @param channel: A string specifying the name of the bone channel. - @type channel: string - @param matrix: A 4x4 matrix specifying the overriding transformation - as an offset from the bone's rest position. - @type matrix: list [[float]] - @param mode: True for armature/world space, False for bone space - @type mode: boolean - """ - - #--The following methods are deprecated-- - def setAction(action, reset = True): - """ - DEPRECATED: use the 'action' property - 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): - """ - DEPRECATED: use the 'start' property - Specifies the starting frame of the animation. - - @param start: the starting frame of the animation - @type start: float - """ - - def setEnd(end): - """ - DEPRECATED: use the 'end' property - Specifies the ending frame of the animation. - - @param end: the ending frame of the animation - @type end: float - """ - def setBlendin(blendin): - """ - DEPRECATED: use the 'blendin' property - 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): - """ - DEPRECATED: use the 'priority' property - 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): - """ - DEPRECATED: use the 'frame' property - Sets the current frame for the animation. - - @param frame: Specifies the new current frame for the animation - @type frame: float - """ - - def setProperty(prop): - """ - DEPRECATED: use the 'property' property - 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): - """ - DEPRECATED: use the 'blendTime' property - 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): - """ - DEPRECATED: use the 'type' property - 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): - """ - DEPRECATED: use the 'continue' property - Set the actions continue option True or False. see getContinue. - - @param cont: The continue option. - @type cont: bool - """ - - def getType(): - """ - DEPRECATED: use the 'type' property - 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(): - """ - DEPRECATED: use the 'continue' property - 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(): - """ - DEPRECATED: use the 'action' property - getAction() returns the name of the action associated with this actuator. - - @rtype: string - """ - - def getStart(): - """ - DEPRECATED: use the 'start' property - Returns the starting frame of the action. - - @rtype: float - """ - def getEnd(): - """ - DEPRECATED: use the 'end' property - Returns the last frame of the action. - - @rtype: float - """ - def getBlendin(): - """ - DEPRECATED: use the 'blendin' property - Returns the number of interpolation animation frames to be generated when this actuator is triggered. - - @rtype: float - """ - def getPriority(): - """ - DEPRECATED: use the 'priority' property - Returns the priority for this actuator. Actuators with lower Priority numbers will - override actuators with higher numbers. - - @rtype: integer - """ - def getFrame(): - """ - DEPRECATED: use the 'frame' property - Returns the current frame number. - - @rtype: float - """ - def getProperty(): - """ - DEPRECATED: use the 'property' property - Returns the name of the property to be used in FromProp mode. - - @rtype: string - """ - def setFrameProperty(prop): - """ - DEPRECATED: use the 'frameProperty' property - @param prop: A string specifying the property of the object that will be updated with the action frame number. - @type prop: string - """ - def getFrameProperty(): - """ - DEPRECATED: use the 'frameProperty' property - Returns the name of the property that is set to the current frame number. - - @rtype: string - """ diff --git a/source/gameengine/PyDoc/BL_Shader.py b/source/gameengine/PyDoc/BL_Shader.py deleted file mode 100644 index 182b73d437b..00000000000 --- a/source/gameengine/PyDoc/BL_Shader.py +++ /dev/null @@ -1,228 +0,0 @@ -class BL_Shader: # (PyObjectPlus) - """ - BL_Shader GLSL shaders. - - All placeholders have a __ prefix - """ - - def __setUniformfv(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - - def __delSource(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __getFragmentProg(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __getVertexProg(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __isValid(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setAttrib(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setNumberOfPasses(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setSampler(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setSource(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniform1f(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniform1i(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniform2f(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniform2i(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniform3f(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniform3i(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniform4f(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniform4i(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniformDef(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniformMatrix3(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniformMatrix4(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setUniformiv(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __validate(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ diff --git a/source/gameengine/PyDoc/BL_ShapeActionActuator.py b/source/gameengine/PyDoc/BL_ShapeActionActuator.py deleted file mode 100644 index e1e8b039749..00000000000 --- a/source/gameengine/PyDoc/BL_ShapeActionActuator.py +++ /dev/null @@ -1,199 +0,0 @@ -# $Id$ -# Documentation for BL_ShapeActionActuator -from SCA_IActuator import * -from SCA_ILogicBrick import * - -class BL_ShapeActionActuator(SCA_IActuator): - """ - ShapeAction Actuators apply an shape action to an mesh object.\ - - @ivar action: The name of the action to set as the current shape action. - @type action: string - @ivar start: Specifies the starting frame of the shape animation. - @type start: float - @ivar end: Specifies the ending frame of the shape animation. - @type end: float - @ivar blendin: Specifies the number of frames of animation to generate when making transitions between actions. - @type blendin: float - @ivar priority: Sets the priority of this actuator. Actuators will lower - priority numbers will override actuators with higher - numbers. - @type priority: integer - @ivar frame: Sets the current frame for the animation. - @type frame: float - @ivar property: Sets the property to be used in FromProp playback mode. - @type property: string - @ivar blendTime: Sets the internal frame timer. This property must be in - the range from 0.0 to blendin. - @type blendTime: float - @ivar type: The operation mode of the actuator. - KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, - KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND - @type type: integer - @ivar frameProperty: The name of the property that is set to the current frame number. - @type frameProperty: string - - """ - def setAction(action, reset = True): - """ - DEPRECATED: use the 'action' property - 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): - """ - DEPRECATED: use the 'start' property - Specifies the starting frame of the animation. - - @param start: the starting frame of the animation - @type start: float - """ - - def setEnd(end): - """ - DEPRECATED: use the 'end' property - Specifies the ending frame of the animation. - - @param end: the ending frame of the animation - @type end: float - """ - def setBlendin(blendin): - """ - DEPRECATED: use the 'blendin' property - 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): - """ - DEPRECATED: use the 'priority' property - 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): - """ - DEPRECATED: use the 'frame' property - Sets the current frame for the animation. - - @param frame: Specifies the new current frame for the animation - @type frame: float - """ - - def setProperty(prop): - """ - DEPRECATED: use the 'property' property - 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): - """ - DEPRECATED: use the 'blendTime' property - 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): - """ - DEPRECATED: use the 'type' property - 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 getType(): - """ - DEPRECATED: use the 'type' property - 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 getAction(): - """ - DEPRECATED: use the 'action' property - getAction() returns the name of the action associated with this actuator. - - @rtype: string - """ - - def getStart(): - """ - DEPRECATED: use the 'start' property - Returns the starting frame of the action. - - @rtype: float - """ - def getEnd(): - """ - DEPRECATED: use the 'end' property - Returns the last frame of the action. - - @rtype: float - """ - def getBlendin(): - """ - DEPRECATED: use the 'blendin' property - Returns the number of interpolation animation frames to be generated when this actuator is triggered. - - @rtype: float - """ - def getPriority(): - """ - DEPRECATED: use the 'priority' property - Returns the priority for this actuator. Actuators with lower Priority numbers will - override actuators with higher numbers. - - @rtype: integer - """ - def getFrame(): - """ - DEPRECATED: use the 'frame' property - Returns the current frame number. - - @rtype: float - """ - def getProperty(): - """ - DEPRECATED: use the 'property' property - Returns the name of the property to be used in FromProp mode. - - @rtype: string - """ - def setFrameProperty(prop): - """ - DEPRECATED: use the 'frameProperty' property - @param prop: A string specifying the property of the object that will be updated with the action frame number. - @type prop: string - """ - def getFrameProperty(): - """ - DEPRECATED: use the 'frameProperty' property - Returns the name of the property that is set to the current frame number. - - @rtype: string - """ diff --git a/source/gameengine/PyDoc/CListValue.py b/source/gameengine/PyDoc/CListValue.py deleted file mode 100644 index e9fc4215bb6..00000000000 --- a/source/gameengine/PyDoc/CListValue.py +++ /dev/null @@ -1,59 +0,0 @@ -class CListValue: # (PyObjectPlus) - """ - CListValue - - This is a list like object used in the game engine internally that behaves similar to a python list in most ways. - - As well as the normal index lookup. - C{val= clist[i]} - - CListValue supports string lookups. - C{val= scene.objects["OBCube"]} - - Other operations such as C{len(clist), list(clist), clist[0:10]} are also supported. - """ - def append(val): - """ - Add an item to the list (like pythons append) - - Warning: Appending values to the list can cause crashes when the list is used internally by the game engine. - """ - - def count(val): - """ - Count the number of instances of a value in the list. - - @rtype: integer - @return: number of instances - """ - def index(val): - """ - Return the index of a value in the list. - - @rtype: integer - @return: The index of the value in the list. - """ - def reverse(): - """ - Reverse the order of the list. - """ - def from_id(id): - """ - This is a funtion especially for the game engine to return a value with a spesific id. - - Since object names are not always unique, the id of an object can be used to get an object from the CValueList. - - Example. - - C{myObID = id(gameObject)} - - C{...} - - C{ob= scene.objects.from_id(myObID)} - - Where myObID is an int or long from the id function. - - This has the advantage that you can store the id in places you could not store a gameObject. - - Warning: the id is derived from a memory location and will be different each time the game engine starts. - """
\ No newline at end of file diff --git a/source/gameengine/PyDoc/GameKeys.py b/source/gameengine/PyDoc/GameKeys.py index 310f2b0d506..e798f6c901b 100644 --- a/source/gameengine/PyDoc/GameKeys.py +++ b/source/gameengine/PyDoc/GameKeys.py @@ -5,126 +5,6 @@ Documentation for the GameKeys module. This module holds key constants for the SCA_KeyboardSensor. -Alphabet keys -------------- - - AKEY - - BKEY - - CKEY - - DKEY - - EKEY - - FKEY - - GKEY - - HKEY - - IKEY - - JKEY - - KKEY - - LKEY - - MKEY - - NKEY - - OKEY - - PKEY - - QKEY - - RKEY - - SKEY - - TKEY - - UKEY - - VKEY - - WKEY - - XKEY - - YKEY - - ZKEY - -Number keys ------------ - - ZEROKEY - - ONEKEY - - TWOKEY - - THREEKEY - - FOURKEY - - FIVEKEY - - SIXKEY - - SEVENKEY - - EIGHTKEY - - NINEKEY - -Shift Modifiers ---------------- - - CAPSLOCKKEY - - - LEFTCTRLKEY - - LEFTALTKEY - - RIGHTALTKEY - - RIGHTCTRLKEY - - RIGHTSHIFTKEY - - LEFTSHIFTKEY - -Arrow Keys ----------- - - LEFTARROWKEY - - DOWNARROWKEY - - RIGHTARROWKEY - - UPARROWKEY - -Numberpad Keys --------------- - - PAD0 - - PAD1 - - PAD2 - - PAD3 - - PAD4 - - PAD5 - - PAD6 - - PAD7 - - PAD8 - - PAD9 - - PADPERIOD - - PADSLASHKEY - - PADASTERKEY - - PADMINUS - - PADENTER - - PADPLUSKEY - -Function Keys -------------- - - F1KEY - - F2KEY - - F3KEY - - F4KEY - - F5KEY - - F6KEY - - F7KEY - - F8KEY - - F9KEY - - F10KEY - - F11KEY - - F12KEY - -Other Keys ----------- - - ACCENTGRAVEKEY - - BACKSLASHKEY - - BACKSPACEKEY - - COMMAKEY - - DELKEY - - ENDKEY - - EQUALKEY - - ESCKEY - - HOMEKEY - - INSERTKEY - - LEFTBRACKETKEY - - LINEFEEDKEY - - MINUSKEY - - PAGEDOWNKEY - - PAGEUPKEY - - PAUSEKEY - - PERIODKEY - - QUOTEKEY - - RIGHTBRACKETKEY - - RETKEY - - SEMICOLONKEY - - SLASHKEY - - SPACEKEY - - TABKEY Example:: # Set a connected keyboard sensor to accept F1 @@ -156,7 +36,120 @@ Example:: # Activate Left! if key[0] == GameKeys.DKEY: # Activate Right! - + +@group Alphabet keys: AKEY, BKEY, CKEY, DKEY, EKEY, FKEY, GKEY, HKEY, IKEY, JKEY, KKEY, LKEY, MKEY, NKEY, OKEY, PKEY, QKEY, RKEY, SKEY, TKEY, UKEY, VKEY, WKEY, XKEY, YKEY, ZKEY +@var AKEY: +@var BKEY: +@var CKEY: +@var DKEY: +@var EKEY: +@var FKEY: +@var GKEY: +@var HKEY: +@var IKEY: +@var JKEY: +@var KKEY: +@var LKEY: +@var MKEY: +@var NKEY: +@var OKEY: +@var PKEY: +@var QKEY: +@var RKEY: +@var SKEY: +@var TKEY: +@var UKEY: +@var VKEY: +@var WKEY: +@var XKEY: +@var YKEY: +@var ZKEY: + +@group Number keys: ZEROKEY, ONEKEY, TWOKEY, THREEKEY, FOURKEY, FIVEKEY, SIXKEY, SEVENKEY, EIGHTKEY, NINEKEY +@var ZEROKEY: +@var ONEKEY: +@var TWOKEY: +@var THREEKEY: +@var FOURKEY: +@var FIVEKEY: +@var SIXKEY: +@var SEVENKEY: +@var EIGHTKEY: +@var NINEKEY: + +@group Modifiers: CAPSLOCKKEY, LEFTCTRLKEY, LEFTALTKEY, RIGHTALTKEY, RIGHTCTRLKEY, RIGHTSHIFTKEY, LEFTSHIFTKEY +@var CAPSLOCKKEY: +@var LEFTCTRLKEY: +@var LEFTALTKEY: +@var RIGHTALTKEY: +@var RIGHTCTRLKEY: +@var RIGHTSHIFTKEY: +@var LEFTSHIFTKEY: + +@group Arrow Keys: LEFTARROWKEY, DOWNARROWKEY, RIGHTARROWKEY, UPARROWKEY +@var LEFTARROWKEY: +@var DOWNARROWKEY: +@var RIGHTARROWKEY: +@var UPARROWKEY: + +@group Numberpad Keys: PAD0, PAD1, PAD2, PAD3, PAD4, PAD5, PAD6, PAD7, PAD8, PAD9, PADPERIOD, PADSLASHKEY, PADASTERKEY, PADMINUS, PADENTER, PADPLUSKEY +@var PAD0: +@var PAD1: +@var PAD2: +@var PAD3: +@var PAD4: +@var PAD5: +@var PAD6: +@var PAD7: +@var PAD8: +@var PAD9: +@var PADPERIOD: +@var PADSLASHKEY: +@var PADASTERKEY: +@var PADMINUS: +@var PADENTER: +@var PADPLUSKEY: + +@group Function Keys: F1KEY, F2KEY, F3KEY, F4KEY, F5KEY, F6KEY, F7KEY, F8KEY, F9KEY, F10KEY, F11KEY, F12KEY +@var F1KEY: +@var F2KEY: +@var F3KEY: +@var F4KEY: +@var F5KEY: +@var F6KEY: +@var F7KEY: +@var F8KEY: +@var F9KEY: +@var F10KEY: +@var F11KEY: +@var F12KEY: + +@group Other Keys: ACCENTGRAVEKEY, BACKSLASHKEY, BACKSPACEKEY, COMMAKEY, DELKEY, ENDKEY, EQUALKEY, ESCKEY, HOMEKEY, INSERTKEY, LEFTBRACKETKEY, LINEFEEDKEY, MINUSKEY, PAGEDOWNKEY, PAGEUPKEY, PAUSEKEY, PERIODKEY, QUOTEKEY, RIGHTBRACKETKEY, RETKEY, SEMICOLONKEY, SLASHKEY, SPACEKEY, TABKEY +@var ACCENTGRAVEKEY: +@var BACKSLASHKEY: +@var BACKSPACEKEY: +@var COMMAKEY: +@var DELKEY: +@var ENDKEY: +@var EQUALKEY: +@var ESCKEY: +@var HOMEKEY: +@var INSERTKEY: +@var LEFTBRACKETKEY: +@var LINEFEEDKEY: +@var MINUSKEY: +@var PAGEDOWNKEY: +@var PAGEUPKEY: +@var PAUSEKEY: +@var PERIODKEY: +@var QUOTEKEY: +@var RIGHTBRACKETKEY: +@var RETKEY: +@var SEMICOLONKEY: +@var SLASHKEY: +@var SPACEKEY: +@var TABKEY: + """ def EventToString(event): @@ -174,8 +167,8 @@ def EventToCharacter(event, shift): @type event: int @param event: key event from GameKeys or the keyboard sensor. - @type event: bool - @param event: set to true if shift is held. + @type shift: bool + @param shift: set to true if shift is held. @rtype: string """ diff --git a/source/gameengine/PyDoc/GameLogic.py b/source/gameengine/PyDoc/GameLogic.py index 1996aa3f8a9..3ec30a63c58 100644 --- a/source/gameengine/PyDoc/GameLogic.py +++ b/source/gameengine/PyDoc/GameLogic.py @@ -2,29 +2,15 @@ """ Documentation for the GameLogic Module. ======================================= - - Modules available in the game engine: - - GameLogic - - L{GameKeys} - - L{Rasterizer} - - L{GameTypes} - - Undocumented modules: - - VideoTexture - - CValue - - Expression - - PhysicsConstraints - - All the other modules are accessible through the methods in GameLogic. - See L{WhatsNew} for updates, changes and new functionality in the Game Engine Python API. + Module to access logic functions, imported automatically into the python controllers namespace. Examples:: # To get the controller thats running this python script: - co = GameLogic.getCurrentController() # GameLogic is automatically imported + cont = GameLogic.getCurrentController() # GameLogic is automatically imported # To get the game object this controller is on: - obj = co.getOwner() + obj = cont.owner L{KX_GameObject} and L{KX_Camera} or L{KX_LightObject} methods are available depending on the type of object:: # To get a sensor linked to this controller. @@ -32,55 +18,59 @@ Documentation for the GameLogic Module. # +---------------------+ +--------+ # | Sensor "sensorname" +--+ Python + # +---------------------+ +--------+ - sens = co.getSensor("sensorname") + sens = cont.sensors["sensorname"] - # To get a list of all sensors: - sensors = co.getSensors() + # To get a sequence of all sensors: + sensors = co.sensors See the sensor's reference for available methods: - - L{DelaySensor<SCA_DelaySensor.SCA_DelaySensor>} - - L{JoystickSensor<SCA_JoystickSensor.SCA_JoystickSensor>} - - L{KeyboardSensor<SCA_KeyboardSensor.SCA_KeyboardSensor>} - - L{MouseFocusSensor<KX_MouseFocusSensor.KX_MouseFocusSensor>} - - L{MouseSensor<SCA_MouseSensor.SCA_MouseSensor>} - - L{NearSensor<KX_NearSensor.KX_NearSensor>} - - L{NetworkMessageSensor<KX_NetworkMessageSensor.KX_NetworkMessageSensor>} - - L{PropertySensor<SCA_PropertySensor.SCA_PropertySensor>} - - L{RadarSensor<KX_RadarSensor.KX_RadarSensor>} - - L{RandomSensor<SCA_RandomSensor.SCA_RandomSensor>} - - L{RaySensor<KX_RaySensor.KX_RaySensor>} - - L{TouchSensor<KX_TouchSensor.KX_TouchSensor>} + - L{DelaySensor<GameTypes.SCA_DelaySensor>} + - L{JoystickSensor<GameTypes.SCA_JoystickSensor>} + - L{KeyboardSensor<GameTypes.SCA_KeyboardSensor>} + - L{MouseFocusSensor<GameTypes.KX_MouseFocusSensor>} + - L{MouseSensor<GameTypes.SCA_MouseSensor>} + - L{NearSensor<GameTypes.KX_NearSensor>} + - L{NetworkMessageSensor<GameTypes.KX_NetworkMessageSensor>} + - L{PropertySensor<GameTypes.SCA_PropertySensor>} + - L{RadarSensor<GameTypes.KX_RadarSensor>} + - L{RandomSensor<GameTypes.SCA_RandomSensor>} + - L{RaySensor<GameTypes.KX_RaySensor>} + - L{TouchSensor<GameTypes.KX_TouchSensor>} You can also access actuators linked to the controller:: # To get an actuator attached to the controller: # +--------+ +-------------------------+ # + Python +--+ Actuator "actuatorname" | # +--------+ +-------------------------+ - actuator = co.getActuator("actuatorname") + actuator = co.actuators["actuatorname"] # Activate an actuator - GameLogic.addActiveActuator(actuator, True) + controller.activate(actuator) See the actuator's reference for available methods: - - L{ActionActuator<BL_ActionActuator.BL_ActionActuator>} - - L{AddObjectActuator<KX_SCA_AddObjectActuator.KX_SCA_AddObjectActuator>} - - L{CameraActuator<KX_CameraActuator.KX_CameraActuator>} - - L{CDActuator<KX_CDActuator.KX_CDActuator>} - - L{ConstraintActuator<KX_ConstraintActuator.KX_ConstraintActuator>} - - L{EndObjectActuator<KX_SCA_EndObjectActuator.KX_SCA_EndObjectActuator>} - - L{GameActuator<KX_GameActuator.KX_GameActuator>} - - L{IpoActuator<KX_IpoActuator.KX_IpoActuator>} - - L{NetworkMessageActuator<KX_NetworkMessageActuator.KX_NetworkMessageActuator>} - - L{ObjectActuator<KX_ObjectActuator.KX_ObjectActuator>} - - L{PropertyActuator<SCA_PropertyActuator.SCA_PropertyActuator>} - - L{RandomActuator<SCA_RandomActuator.SCA_RandomActuator>} - - L{ReplaceMeshActuator<KX_SCA_ReplaceMeshActuator.KX_SCA_ReplaceMeshActuator>} - - L{SceneActuator<KX_SceneActuator.KX_SceneActuator>} - - L{SoundActuator<KX_SoundActuator.KX_SoundActuator>} - - L{TrackToActuator<KX_TrackToActuator.KX_TrackToActuator>} - - L{VisibilityActuator<KX_VisibilityActuator.KX_VisibilityActuator>} - - L{DynamicActuator<KX_SCA_DynamicActuator.KX_SCA_DynamicActuator>} - + - L{2DFilterActuator<GameTypes.SCA_2DFilterActuator>} + - L{ActionActuator<GameTypes.BL_ActionActuator>} + - L{AddObjectActuator<GameTypes.KX_SCA_AddObjectActuator>} + - L{CameraActuator<GameTypes.KX_CameraActuator>} + - L{CDActuator<GameTypes.KX_CDActuator>} + - L{ConstraintActuator<GameTypes.KX_ConstraintActuator>} + - L{DynamicActuator<GameTypes.KX_SCA_DynamicActuator>} + - L{EndObjectActuator<GameTypes.KX_SCA_EndObjectActuator>} + - L{GameActuator<GameTypes.KX_GameActuator>} + - L{IpoActuator<GameTypes.KX_IpoActuator>} + - L{NetworkMessageActuator<GameTypes.KX_NetworkMessageActuator>} + - L{ObjectActuator<GameTypes.KX_ObjectActuator>} + - L{ParentActuator<GameTypes.KX_ParentActuator>} + - L{PropertyActuator<GameTypes.SCA_PropertyActuator>} + - L{RandomActuator<GameTypes.SCA_RandomActuator>} + - L{ReplaceMeshActuator<GameTypes.KX_SCA_ReplaceMeshActuator>} + - L{SceneActuator<GameTypes.KX_SceneActuator>} + - L{ShapeActionActuator<GameTypes.BL_ShapeActionActuator>} + - L{SoundActuator<GameTypes.KX_SoundActuator>} + - L{StateActuator<GameTypes.KX_StateActuator>} + - L{TrackToActuator<GameTypes.KX_TrackToActuator>} + - L{VisibilityActuator<GameTypes.KX_VisibilityActuator>} + Most logic brick's methods are accessors for the properties available in the logic buttons. Consult the logic bricks documentation for more information on how each logic brick works. @@ -92,7 +82,7 @@ Documentation for the GameLogic Module. cam = scene.active_camera Matricies as used by the game engine are B{row major}:: - matrix[row][col] = blah + matrix[row][col] = float L{KX_Camera} has some examples using matricies. @@ -100,29 +90,37 @@ Documentation for the GameLogic Module. @var KX_TRUE: True value used by some modules. @var KX_FALSE: False value used by some modules. -@group Property Sensor: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL, KX_PROPSENSOR_INTERVAL, KX_PROPSENSOR_CHANGED, KX_PROPSENSOR_EXPRESSION +@group Property Sensor: KX_PROPSENSOR_* @var KX_PROPSENSOR_EQUAL: Activate when the property is equal to the sensor value. @var KX_PROPSENSOR_NOTEQUAL: Activate when the property is not equal to the sensor value. @var KX_PROPSENSOR_INTERVAL: Activate when the property is between the specified limits. @var KX_PROPSENSOR_CHANGED: Activate when the property changes @var KX_PROPSENSOR_EXPRESSION: Activate when the expression matches -@group Constraint Actuator: KX_CONSTRAINTACT_LOCX, KX_CONSTRAINTACT_LOCY, KX_CONSTRAINTACT_LOCZ, KX_CONSTRAINTACT_ROTX, KX_CONSTRAINTACT_ROTY, KX_CONSTRAINTACT_ROTZ +@group Constraint Actuator: KX_CONSTRAINTACT_* @var KX_CONSTRAINTACT_LOCX: See L{KX_ConstraintActuator} @var KX_CONSTRAINTACT_LOCY: See L{KX_ConstraintActuator} @var KX_CONSTRAINTACT_LOCZ: See L{KX_ConstraintActuator} @var KX_CONSTRAINTACT_ROTX: See L{KX_ConstraintActuator} @var KX_CONSTRAINTACT_ROTY: See L{KX_ConstraintActuator} @var KX_CONSTRAINTACT_ROTZ: See L{KX_ConstraintActuator} +@var KX_CONSTRAINTACT_DIRNX: See L{KX_ConstraintActuator} +@var KX_CONSTRAINTACT_DIRNY: See L{KX_ConstraintActuator} +@var KX_CONSTRAINTACT_DIRPX: See L{KX_ConstraintActuator} +@var KX_CONSTRAINTACT_DIRPY: See L{KX_ConstraintActuator} +@var KX_CONSTRAINTACT_ORIX: See L{KX_ConstraintActuator} +@var KX_CONSTRAINTACT_ORIY: See L{KX_ConstraintActuator} +@var KX_CONSTRAINTACT_ORIZ: See L{KX_ConstraintActuator} -@group IPO Actuator: KX_IPOACT_PLAY, KX_IPOACT_PINGPONG, KX_IPOACT_FLIPPER, KX_IPOACT_LOOPSTOP, KX_IPOACT_LOOPEND +@group IPO Actuator: KX_IPOACT_* @var KX_IPOACT_PLAY: See L{KX_IpoActuator} @var KX_IPOACT_PINGPONG: See L{KX_IpoActuator} @var KX_IPOACT_FLIPPER: See L{KX_IpoActuator} @var KX_IPOACT_LOOPSTOP: See L{KX_IpoActuator} @var KX_IPOACT_LOOPEND: See L{KX_IpoActuator} +@var KX_IPOACT_FROM_PROP: See L{KX_IpoActuator} -@group Random Distributions: KX_RANDOMACT_BOOL_CONST, KX_RANDOMACT_BOOL_UNIFORM, KX_RANDOMACT_BOOL_BERNOUILLI, KX_RANDOMACT_INT_CONST, KX_RANDOMACT_INT_UNIFORM, KX_RANDOMACT_INT_POISSON, KX_RANDOMACT_FLOAT_CONST, KX_RANDOMACT_FLOAT_UNIFORM, KX_RANDOMACT_FLOAT_NORMAL, KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL +@group Random Distributions: KX_RANDOMACT_* @var KX_RANDOMACT_BOOL_CONST: See L{SCA_RandomActuator} @var KX_RANDOMACT_BOOL_UNIFORM: See L{SCA_RandomActuator} @var KX_RANDOMACT_BOOL_BERNOUILLI: See L{SCA_RandomActuator} @@ -134,14 +132,14 @@ Documentation for the GameLogic Module. @var KX_RANDOMACT_FLOAT_NORMAL: See L{SCA_RandomActuator} @var KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL: See L{SCA_RandomActuator} -@group Action Actuator: KX_ACTIONACT_PLAY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND, KX_ACTIONACT_PROPERTY +@group Action Actuator: KX_ACTIONACT_* @var KX_ACTIONACT_PLAY: See L{BL_ActionActuator} @var KX_ACTIONACT_FLIPPER: See L{BL_ActionActuator} @var KX_ACTIONACT_LOOPSTOP: See L{BL_ActionActuator} @var KX_ACTIONACT_LOOPEND: See L{BL_ActionActuator} @var KX_ACTIONACT_PROPERTY: See L{BL_ActionActuator} -@group Sound Actuator: KX_SOUNDACT_PLAYSTOP, KX_SOUNDACT_PLAYEND, KX_SOUNDACT_LOOPSTOP, KX_SOUNDACT_LOOPEND, KX_SOUNDACT_LOOPBIDIRECTIONAL, KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP +@group Sound Actuator: KX_SOUNDACT_* @var KX_SOUNDACT_PLAYSTOP: See L{KX_SoundActuator} @var KX_SOUNDACT_PLAYEND: See L{KX_SoundActuator} @var KX_SOUNDACT_LOOPSTOP: See L{KX_SoundActuator} @@ -149,7 +147,7 @@ Documentation for the GameLogic Module. @var KX_SOUNDACT_LOOPBIDIRECTIONAL: See L{KX_SoundActuator} @var KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: See L{KX_SoundActuator} -@group Radar Sensor: KX_RADAR_AXIS_POS_X, KX_RADAR_AXIS_POS_Y, KX_RADAR_AXIS_POS_Z, KX_RADAR_AXIS_NEG_X, KX_RADAR_AXIS_NEG_Y, KX_RADAR_AXIS_NEG_Z +@group Radar Sensor: KX_RADAR_* @var KX_RADAR_AXIS_POS_X: See L{KX_RadarSensor} @var KX_RADAR_AXIS_POS_Y: See L{KX_RadarSensor} @var KX_RADAR_AXIS_POS_Z: See L{KX_RadarSensor} @@ -157,7 +155,7 @@ Documentation for the GameLogic Module. @var KX_RADAR_AXIS_NEG_Y: See L{KX_RadarSensor} @var KX_RADAR_AXIS_NEG_Z: See L{KX_RadarSensor} -@group Ray Sensor: KX_RAY_AXIS_POS_X, KX_RAY_AXIS_POS_Y, KX_RAY_AXIS_POS_Z, KX_RAY_AXIS_NEG_X, KX_RAY_AXIS_NEG_Y, KX_RAY_AXIS_NEG_Z +@group Ray Sensor: KX_RAY_* @var KX_RAY_AXIS_POS_X: See L{KX_RaySensor} @var KX_RAY_AXIS_POS_Y: See L{KX_RaySensor} @var KX_RAY_AXIS_POS_Z: See L{KX_RaySensor} @@ -165,26 +163,153 @@ Documentation for the GameLogic Module. @var KX_RAY_AXIS_NEG_Y: See L{KX_RaySensor} @var KX_RAY_AXIS_NEG_Z: See L{KX_RaySensor} -@group Dynamic Actuator: KX_DYN_RESTORE_DYNAMICS, KX_DYN_DISABLE_DYNAMICS, KX_DYN_ENABLE_RIGID_BODY, KX_DYN_DISABLE_RIGID_BODY, KX_DYN_SET_MASS +@group Dynamic Actuator: KX_DYN_* @var KX_DYN_RESTORE_DYNAMICS: See L{KX_SCA_DynamicActuator} @var KX_DYN_DISABLE_DYNAMICS: See L{KX_SCA_DynamicActuator} @var KX_DYN_ENABLE_RIGID_BODY: See L{KX_SCA_DynamicActuator} @var KX_DYN_DISABLE_RIGID_BODY: See L{KX_SCA_DynamicActuator} @var KX_DYN_SET_MASS: See L{KX_SCA_DynamicActuator} -@group Input Status: KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED +@group Game Actuator: KX_GAME_* +@var KX_GAME_LOAD: See L{KX_GameActuator} +@var KX_GAME_START: See L{KX_GameActuator} +@var KX_GAME_RESTART: See L{KX_GameActuator} +@var KX_GAME_QUIT: See L{KX_GameActuator} +@var KX_GAME_SAVECFG: See L{KX_GameActuator} +@var KX_GAME_LOADCFG: See L{KX_GameActuator} + +@group Scene Actuator: KX_SCENE_* +@var KX_SCENE_RESTART: See L{KX_SceneActuator} +@var KX_SCENE_SET_SCENE: See L{KX_SceneActuator} +@var KX_SCENE_SET_CAMERA: See L{KX_SceneActuator} +@var KX_SCENE_ADD_FRONT_SCENE: See L{KX_SceneActuator} +@var KX_SCENE_ADD_BACK_SCENE: See L{KX_SceneActuator} +@var KX_SCENE_REMOVE_SCENE: See L{KX_SceneActuator} +@var KX_SCENE_SUSPEND: See L{KX_SceneActuator} +@var KX_SCENE_RESUME: See L{KX_SceneActuator} + +@group Input Status: KX_INPUT_* @var KX_INPUT_NONE: See L{SCA_MouseSensor} @var KX_INPUT_JUST_ACTIVATED: See L{SCA_MouseSensor} @var KX_INPUT_ACTIVE: See L{SCA_MouseSensor} @var KX_INPUT_JUST_RELEASED: See L{SCA_MouseSensor} -@group Mouse Buttons: KX_MOUSE_BUT_LEFT, KX_MOUSE_BUT_MIDDLE, KX_MOUSE_BUT_RIGHT +@group Mouse Buttons: KX_MOUSE_BUT_* @var KX_MOUSE_BUT_LEFT: See L{SCA_MouseSensor} @var KX_MOUSE_BUT_MIDDLE: See L{SCA_MouseSensor} @var KX_MOUSE_BUT_RIGHT: See L{SCA_MouseSensor} + +@group States: KX_STATE* +@var KX_STATE1: +@var KX_STATE10: +@var KX_STATE11: +@var KX_STATE12: +@var KX_STATE13: +@var KX_STATE14: +@var KX_STATE15: +@var KX_STATE16: +@var KX_STATE17: +@var KX_STATE18: +@var KX_STATE19: +@var KX_STATE2: +@var KX_STATE20: +@var KX_STATE21: +@var KX_STATE22: +@var KX_STATE23: +@var KX_STATE24: +@var KX_STATE25: +@var KX_STATE26: +@var KX_STATE27: +@var KX_STATE28: +@var KX_STATE29: +@var KX_STATE3: +@var KX_STATE30: +@var KX_STATE4: +@var KX_STATE5: +@var KX_STATE6: +@var KX_STATE7: +@var KX_STATE8: +@var KX_STATE9: +@var KX_STATE_OP_CLR: +@var KX_STATE_OP_CPY: +@var KX_STATE_OP_NEG: +@var KX_STATE_OP_SET: + +@group 2D Filter: RAS_2DFILTER_* +@var RAS_2DFILTER_BLUR: +@var RAS_2DFILTER_CUSTOMFILTER: +@var RAS_2DFILTER_DILATION: +@var RAS_2DFILTER_DISABLED: +@var RAS_2DFILTER_ENABLED: +@var RAS_2DFILTER_EROSION: +@var RAS_2DFILTER_GRAYSCALE: +@var RAS_2DFILTER_INVERT: +@var RAS_2DFILTER_LAPLACIAN: +@var RAS_2DFILTER_MOTIONBLUR: +@var RAS_2DFILTER_NOFILTER: +@var RAS_2DFILTER_PREWITT: +@var RAS_2DFILTER_SEPIA: +@var RAS_2DFILTER_SHARPEN: +@var RAS_2DFILTER_SOBEL: + +@group Constraint Actuator: KX_ACT_CONSTRAINT_* +@var KX_ACT_CONSTRAINT_DISTANCE: +@var KX_ACT_CONSTRAINT_DOROTFH: +@var KX_ACT_CONSTRAINT_FHNX: +@var KX_ACT_CONSTRAINT_FHNY: +@var KX_ACT_CONSTRAINT_FHNZ: +@var KX_ACT_CONSTRAINT_FHPX: +@var KX_ACT_CONSTRAINT_FHPY: +@var KX_ACT_CONSTRAINT_FHPZ: +@var KX_ACT_CONSTRAINT_LOCAL: +@var KX_ACT_CONSTRAINT_MATERIAL: +@var KX_ACT_CONSTRAINT_NORMAL: +@var KX_ACT_CONSTRAINT_PERMANENT: + +@group Parent Actuator: KX_PARENT_* +@var KX_PARENT_REMOVE: +@var KX_PARENT_SET: + +@group Shader: MODELMATRIX*, MODELVIEWMATRIX*, VIEWMATRIX*, CAM_POS, CONSTANT_TIMER +@var VIEWMATRIX: +@var VIEWMATRIX_INVERSE: +@var VIEWMATRIX_INVERSETRANSPOSE: +@var VIEWMATRIX_TRANSPOSE: +@var MODELMATRIX: +@var MODELMATRIX_INVERSE: +@var MODELMATRIX_INVERSETRANSPOSE: +@var MODELMATRIX_TRANSPOSE: +@var MODELVIEWMATRIX: +@var MODELVIEWMATRIX_INVERSE: +@var MODELVIEWMATRIX_INVERSETRANSPOSE: +@var MODELVIEWMATRIX_TRANSPOSE: +@var CAM_POS: Current camera position +@var CONSTANT_TIMER: Current camera position +@var SHD_TANGENT: Current camera position + +@group Blender Material: BL_* +@var BL_DST_ALPHA: +@var BL_DST_COLOR: +@var BL_ONE: +@var BL_ONE_MINUS_DST_ALPHA: +@var BL_ONE_MINUS_DST_COLOR: +@var BL_ONE_MINUS_SRC_ALPHA: +@var BL_ONE_MINUS_SRC_COLOR: +@var BL_SRC_ALPHA: +@var BL_SRC_ALPHA_SATURATE: +@var BL_SRC_COLOR: +@var BL_ZERO: + +@group Deprecated: addActiveActuator """ +import GameTypes + +# TODO +# globalDict +# error + def getCurrentController(): """ Gets the Python controller associated with this Python script. @@ -197,10 +322,19 @@ def getCurrentScene(): @rtype: L{KX_Scene} """ +def getSceneList(): + """ + Gets a list of the current scenes loaded in the game engine. + + @note: Scenes in your blend file that have not been converted wont be in this list. This list will only contain scenes such as overlays scenes. + + @rtype: list of L{KX_Scene} + """ def addActiveActuator(actuator, activate): """ Activates the given actuator. + @deprecated: Use L{GameTypes.SCA_PythonController.activate} and L{GameTypes.SCA_PythonController.deactivate} instead. @type actuator: L{SCA_IActuator} or the actuator name as a string. @type activate: boolean @param activate: whether to activate or deactivate the given actuator. @@ -218,10 +352,6 @@ def sendMessage(subject, body="", to="", message_from=""): @param message_from: The name of the object that the message is coming from (optional) @type message_from: string """ -def getRandomFloat(): - """ - Returns a random floating point value in the range [0...1) - """ def setGravity(gravity): """ Sets the world gravity. @@ -242,6 +372,38 @@ def stopDSP(): Only the fmod sound driver supports this. DSP can be computationally expensive. """ +def getMaxLogicFrame(): + """ + Gets the maximum number of logic frame per render frame. + + @return: The maximum number of logic frame per render frame + @rtype: interger + """ +def setMaxLogicFrame(maxlogic): + """ + Sets the maximum number of logic frame that are executed per render frame. + This does not affect the physic system that still runs at full frame rate. + + @param maxlogic: The new maximum number of logic frame per render frame. Valid values: 1..5 + @type maxlogic: integer + """ +def getMaxPhysicsFrame(): + """ + Gets the maximum number of physics frame per render frame. + + @return: The maximum number of physics frame per render frame + @rtype: interger + """ +def setMaxPhysicsFrame(maxphysics): + """ + Sets the maximum number of physics timestep that are executed per render frame. + Higher value allows physics to keep up with realtime even if graphics slows down the game. + Physics timestep is fixed and equal to 1/tickrate (see setLogicTicRate) + maxphysics/ticrate is the maximum delay of the renderer that physics can compensate. + + @param maxphysics: The new maximum number of physics timestep per render frame. Valid values: 1..5. + @type maxphysics: integer + """ def getLogicTicRate(): """ Gets the logic update frequency. @@ -254,13 +416,14 @@ def setLogicTicRate(ticrate): Sets the logic update frequency. The logic update frequency is the number of times logic bricks are executed every second. - The default is 30 Hz. + The default is 60 Hz. @param ticrate: The new logic update frequency (in Hz). @type ticrate: float """ def getPhysicsTicRate(): """ + NOT IMPLEMENTED Gets the physics update frequency @return: The physics update frequency in Hz @@ -268,6 +431,7 @@ def getPhysicsTicRate(): """ def setPhysicsTicRate(ticrate): """ + NOT IMPLEMENTED Sets the physics update frequency The physics update frequency is the number of times the physics system is executed every second. @@ -276,6 +440,8 @@ def setPhysicsTicRate(ticrate): @param ticrate: The new update frequency (in Hz). @type ticrate: float """ + +#{ Utility functions def getAverageFrameRate(): """ Gets the estimated average framerate @@ -283,7 +449,6 @@ def getAverageFrameRate(): @return: The estimed average framerate in frames per second @rtype: float """ - def expandPath(path): """ Converts a blender internal path into a proper file system path. @@ -309,3 +474,12 @@ def getBlendFileList(path = "//"): @return: A list of filenames, with no directory prefix @rtype: list """ +def PrintGLInfo(): + """ + Prints GL Extension Info into the console + """ +def getRandomFloat(): + """ + Returns a random floating point value in the range [0...1) + """ +#} diff --git a/source/gameengine/PyDoc/GameTypes.py b/source/gameengine/PyDoc/GameTypes.py index 2b07a18247c..4ab175a8f6c 100644 --- a/source/gameengine/PyDoc/GameTypes.py +++ b/source/gameengine/PyDoc/GameTypes.py @@ -1,75 +1,5796 @@ -# $Id$ """ -GameEngine Types -================ -@var BL_ActionActuator: L{BL_ActionActuator<BL_ActionActuator.BL_ActionActuator>} -@var BL_Shader: L{BL_Shader<BL_Shader.BL_Shader>} -@var BL_ShapeActionActuator: L{BL_ShapeActionActuator<BL_ShapeActionActuator.BL_ShapeActionActuator>} -@var CListValue: L{CListValue<CListValue.CListValue>} -@var CValue: L{CValue<CValue.CValue>} -@var KX_BlenderMaterial: L{KX_BlenderMaterial<KX_BlenderMaterial.KX_BlenderMaterial>} -@var KX_CDActuator: L{KX_CDActuator<KX_CDActuator.KX_CDActuator>} -@var KX_Camera: L{KX_Camera<KX_Camera.KX_Camera>} -@var KX_CameraActuator: L{KX_CameraActuator<KX_CameraActuator.KX_CameraActuator>} -@var KX_ConstraintActuator: L{KX_ConstraintActuator<KX_ConstraintActuator.KX_ConstraintActuator>} -@var KX_ConstraintWrapper: L{KX_ConstraintWrapper<KX_ConstraintWrapper.KX_ConstraintWrapper>} -@var KX_GameActuator: L{KX_GameActuator<KX_GameActuator.KX_GameActuator>} -@var KX_GameObject: L{KX_GameObject<KX_GameObject.KX_GameObject>} -@var KX_IpoActuator: L{KX_IpoActuator<KX_IpoActuator.KX_IpoActuator>} -@var KX_LightObject: L{KX_LightObject<KX_LightObject.KX_LightObject>} -@var KX_MeshProxy: L{KX_MeshProxy<KX_MeshProxy.KX_MeshProxy>} -@var KX_MouseFocusSensor: L{KX_MouseFocusSensor<KX_MouseFocusSensor.KX_MouseFocusSensor>} -@var KX_NearSensor: L{KX_NearSensor<KX_NearSensor.KX_NearSensor>} -@var KX_NetworkMessageActuator: L{KX_NetworkMessageActuator<KX_NetworkMessageActuator.KX_NetworkMessageActuator>} -@var KX_NetworkMessageSensor: L{KX_NetworkMessageSensor<KX_NetworkMessageSensor.KX_NetworkMessageSensor>} -@var KX_ObjectActuator: L{KX_ObjectActuator<KX_ObjectActuator.KX_ObjectActuator>} -@var KX_ParentActuator: L{KX_ParentActuator<KX_ParentActuator.KX_ParentActuator>} -@var KX_PhysicsObjectWrapper: L{KX_PhysicsObjectWrapper<KX_PhysicsObjectWrapper.KX_PhysicsObjectWrapper>} -@var KX_PolyProxy: L{KX_PolyProxy<KX_PolyProxy.KX_PolyProxy>} -@var KX_PolygonMaterial: L{KX_PolygonMaterial<KX_PolygonMaterial.KX_PolygonMaterial>} -@var KX_RadarSensor: L{KX_RadarSensor<KX_RadarSensor.KX_RadarSensor>} -@var KX_RaySensor: L{KX_RaySensor<KX_RaySensor.KX_RaySensor>} -@var KX_SCA_AddObjectActuator: L{KX_SCA_AddObjectActuator<KX_SCA_AddObjectActuator.KX_SCA_AddObjectActuator>} -@var KX_SCA_DynamicActuator: L{KX_SCA_DynamicActuator<KX_SCA_DynamicActuator.KX_SCA_DynamicActuator>} -@var KX_SCA_EndObjectActuator: L{KX_SCA_EndObjectActuator<KX_SCA_EndObjectActuator.KX_SCA_EndObjectActuator>} -@var KX_SCA_ReplaceMeshActuator: L{KX_SCA_ReplaceMeshActuator<KX_SCA_ReplaceMeshActuator.KX_SCA_ReplaceMeshActuator>} -@var KX_Scene: L{KX_Scene<KX_Scene.KX_Scene>} -@var KX_SceneActuator: L{KX_SceneActuator<KX_SceneActuator.KX_SceneActuator>} -@var KX_SoundActuator: L{KX_SoundActuator<KX_SoundActuator.KX_SoundActuator>} -@var KX_StateActuator: L{KX_StateActuator<KX_StateActuator.KX_StateActuator>} -@var KX_TouchSensor: L{KX_TouchSensor<KX_TouchSensor.KX_TouchSensor>} -@var KX_TrackToActuator: L{KX_TrackToActuator<KX_TrackToActuator.KX_TrackToActuator>} -@var KX_VehicleWrapper: L{KX_VehicleWrapper<KX_VehicleWrapper.KX_VehicleWrapper>} -@var KX_VertexProxy: L{KX_VertexProxy<KX_VertexProxy.KX_VertexProxy>} -@var KX_VisibilityActuator: L{KX_VisibilityActuator<KX_VisibilityActuator.KX_VisibilityActuator>} -@var PyObjectPlus: L{PyObjectPlus<PyObjectPlus.PyObjectPlus>} -@var SCA_2DFilterActuator: L{SCA_2DFilterActuator<SCA_2DFilterActuator.SCA_2DFilterActuator>} -@var SCA_ANDController: L{SCA_ANDController<SCA_ANDController.SCA_ANDController>} -@var SCA_ActuatorSensor: L{SCA_ActuatorSensor<SCA_ActuatorSensor.SCA_ActuatorSensor>} -@var SCA_AlwaysSensor: L{SCA_AlwaysSensor<SCA_AlwaysSensor.SCA_AlwaysSensor>} -@var SCA_DelaySensor: L{SCA_DelaySensor<SCA_DelaySensor.SCA_DelaySensor>} -@var SCA_ILogicBrick: L{SCA_ILogicBrick<SCA_ILogicBrick.SCA_ILogicBrick>} -@var SCA_IObject: L{SCA_IObject<SCA_IObject.SCA_IObject>} -@var SCA_ISensor: L{SCA_ISensor<SCA_ISensor.SCA_ISensor>} -@var SCA_JoystickSensor: L{SCA_JoystickSensor<SCA_JoystickSensor.SCA_JoystickSensor>} -@var SCA_KeyboardSensor: L{SCA_KeyboardSensor<SCA_KeyboardSensor.SCA_KeyboardSensor>} -@var SCA_MouseSensor: L{SCA_MouseSensor<SCA_MouseSensor.SCA_MouseSensor>} -@var SCA_NANDController: L{SCA_NANDController<SCA_NANDController.SCA_NANDController>} -@var SCA_NORController: L{SCA_NORController<SCA_NORController.SCA_NORController>} -@var SCA_ORController: L{SCA_ORController<SCA_ORController.SCA_ORController>} -@var SCA_PropertyActuator: L{SCA_PropertyActuator<SCA_PropertyActuator.SCA_PropertyActuator>} -@var SCA_PropertySensor: L{SCA_PropertySensor<SCA_PropertySensor.SCA_PropertySensor>} -@var SCA_PythonController: L{SCA_PythonController<SCA_PythonController.SCA_PythonController>} -@var SCA_RandomActuator: L{SCA_RandomActuator<SCA_RandomActuator.SCA_RandomActuator>} -@var SCA_RandomSensor: L{SCA_RandomSensor<SCA_RandomSensor.SCA_RandomSensor>} -@var SCA_XNORController: L{SCA_XNORController<SCA_XNORController.SCA_XNORController>} -@var SCA_XORController: L{SCA_XORController<SCA_XORController.SCA_XORController>} +Documentation for the GameTypes Module. +======================================= + +@group Base: PyObjectPlus, CValue, CPropValue, SCA_ILogicBrick, SCA_IObject, SCA_ISensor, SCA_IController, SCA_IActuator + +@group Object: KX_GameObject, KX_LightObject, KX_Camera + +@group Mesh: KX_MeshProxy, KX_PolyProxy, KX_VertexProxy + +@group Shading: KX_PolygonMaterial, KX_BlenderMaterial, BL_Shader + +@group Sensors: SCA_ActuatorSensor, SCA_AlwaysSensor, SCA_DelaySensor, SCA_JoystickSensor, SCA_KeyboardSensor, KX_MouseFocusSensor, SCA_MouseSensor, KX_NearSensor, KX_NetworkMessageSensor, SCA_PropertySensor, KX_RadarSensor, SCA_RandomSensor, KX_RaySensor, KX_TouchSensor + +@group Actuators: SCA_2DFilterActuator, BL_ActionActuator, KX_SCA_AddObjectActuator, KX_CameraActuator, KX_CDActuator, KX_ConstraintActuator, KX_SCA_DynamicActuator, KX_SCA_EndObjectActuator, KX_GameActuator, KX_IpoActuator, KX_NetworkMessageActuator, KX_ObjectActuator, KX_ParentActuator, SCA_PropertyActuator, SCA_RandomActuator, KX_SCA_ReplaceMeshActuator, KX_SceneActuator, BL_ShapeActionActuator, KX_SoundActuator, KX_StateActuator, KX_TrackToActuator, KX_VisibilityActuator + +@group Controllers: SCA_ANDController, SCA_NANDController, SCA_NORController, SCA_ORController, SCA_PythonController, SCA_XNORController, SCA_XORController +""" +import GameLogic + +class PyObjectPlus: + """ + PyObjectPlus base class of most other types in the Game Engine. + + @ivar invalid: Test if the object has been freed by the game engine and is no longer valid. + + Normally this is not a problem but when storing game engine data in the GameLogic module, + KX_Scenes or other KX_GameObjects its possible to hold a reference to invalid data. + Calling an attribute or method on an invalid object will raise a SystemError. + + The invalid attribute allows testing for this case without exception handling. + @type invalid: bool + """ + + def isA(game_type): + """ + Check if this is a type or a subtype game_type. + + @param game_type: the name of the type or the type its self from the L{GameTypes} module. + @type game_type: string or type + @return: True if this object is a type or a subtype of game_type. + @rtype: bool + """ + +class CValue(PyObjectPlus): + """ + This class is a basis for other classes. + @ivar name: The name of this CValue derived object (read-only). + @type name: string + @group Deprecated: getName + """ + def getName(): + """ + Returns the name of the CValue. + + @deprecated: Use the L{name} attribute instead. + @note: in most cases the CValue's subclasses will override this function. + @rtype: string + """ + +class CPropValue(CValue): + """ + This class has no python functions + """ + pass + +class SCA_ILogicBrick(CValue): + """ + Base class for all logic bricks. + + @ivar executePriority: This determines the order controllers are evaluated, and actuators are activated (lower priority is executed first). + @type executePriority: int + @ivar owner: The game object this logic brick is attached to (read-only). + @type owner: L{KX_GameObject} or None in exceptional cases. + @ivar name: The name of this logic brick (read-only). + @type name: string + """ + +#{ Deprecated + def getOwner(): + """ + Gets the game object associated with this logic brick. + + @deprecated: Use the L{owner} attribute instead. + @rtype: L{KX_GameObject} + """ + + def setExecutePriority(priority): + """ + Sets the priority of this logic brick. + + This determines the order controllers are evaluated, and actuators are activated. + Bricks with lower priority will be executed first. + + @deprecated: Use the L{executePriority} attribute instead. + @type priority: integer + @param priority: the priority of this logic brick. + """ + def getExecutePriority(): + """ + Gets the execution priority of this logic brick. + + @deprecated: Use the L{executePriority} attribute instead. + @rtype: integer + @return: this logic bricks current priority. + """ +#} + +class SCA_IObject(CValue): + """ + This class has no python functions + """ + pass + +class SCA_ISensor(SCA_ILogicBrick): + """ + Base class for all sensor logic bricks. + + @ivar usePosPulseMode: Flag to turn positive pulse mode on and off. + @type usePosPulseMode: boolean + @ivar useNegPulseMode: Flag to turn negative pulse mode on and off. + @type useNegPulseMode: boolean + @ivar frequency: The frequency for pulse mode sensors. + @type frequency: int + @ivar level: Option whether to detect level or edge transition when entering a state. + 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. + note: mutually exclusive with L{tap}, enabling will disable L{tap}. + @type level: boolean + @ivar tap: When enabled only sensors that are just activated will send a positive event, + after this they will be detected as negative by the controllers. + This will make a key thats held act as if its only tapped for an instant. + note: mutually exclusive with L{level}, enabling will disable L{level}. + @type tap: boolean + @ivar invert: Flag to set if this sensor activates on positive or negative events. + @type invert: boolean + @ivar triggered: True if this sensor brick is in a positive state. (read-only) + @type triggered: boolean + @ivar positive: True if this sensor brick is in a positive state. (read-only) + @type positive: boolean + """ + + def reset(): + """ + Reset sensor internal state, effect depends on the type of sensor and settings. + + The sensor is put in its initial state as if it was just activated. + """ +#{ Deprecated + def isPositive(): + """ + True if this sensor brick is in a positive state. + + @deprecated: use L{positive} + """ + + def isTriggered(): + """ + True if this sensor brick has triggered the current controller. + + @deprecated: use L{triggered} + """ + + def getUsePosPulseMode(): + """ + True if the sensor is in positive pulse mode. + + @deprecated: use L{usePosPulseMode} + """ + def setUsePosPulseMode(pulse): + """ + Sets positive pulse mode. + + @type pulse: boolean + @param pulse: If True, will activate positive pulse mode for this sensor. + @deprecated: use L{usePosPulseMode} + """ + def getFrequency(): + """ + The frequency for pulse mode sensors. + + @rtype: integer + @return: the pulse frequency in 1/50 sec. + @deprecated: use L{frequency} + """ + def setFrequency(freq): + """ + Sets the frequency for pulse mode sensors. + + @type freq: integer + @return: the pulse frequency in 1/50 sec. + @deprecated: use L{frequency} + """ + def getUseNegPulseMode(): + """ + True if the sensor is in negative pulse mode. + + @deprecated: use L{useNegPulseMode} + """ + def setUseNegPulseMode(pulse): + """ + Sets negative pulse mode. + + @type pulse: boolean + @param pulse: If True, will activate negative pulse mode for this sensor. + @deprecated: use L{useNegPulseMode} + """ + def getInvert(): + """ + True if this sensor activates on negative events. + + @deprecated: use L{invert} + """ + def setInvert(invert): + """ + Sets if this sensor activates on positive or negative events. + + @type invert: boolean + @param invert: true if activates on negative events; false if activates on positive events. + @deprecated: use L{invert} + """ + 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 + @deprecated: use L{level} + """ + 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 + @deprecated: use L{level} + """ +#} + +class SCA_IController(SCA_ILogicBrick): + """ + Base class for all controller logic bricks. + + @ivar state: the controllers state bitmask. + This can be used with the GameObject's state to test if the controller is active. + @type state: int bitmask + @ivar sensors: a list of sensors linked to this controller + - note: the sensors are not necessarily owned by the same object. + - note: when objects are instanced in dupligroups links may be lost from objects outside the dupligroup. + @type sensors: sequence supporting index/string lookups and iteration. + @ivar actuators: a list of actuators linked to this controller. + - note: the sensors are not necessarily owned by the same object. + - note: when objects are instanced in dupligroups links may be lost from objects outside the dupligroup. + @type actuators: sequence supporting index/string lookups and iteration. + @ivar useHighPriority: When set the controller executes always before all other controllers that dont have this set. + note: Order of execution between high priority controllers is not guaranteed. + @type useHighPriority: bool + """ +#{ Deprecated + def getState(): + """ + Get the controllers state bitmask, this can be used with the GameObject's state to test if the the controller is active. + This for instance will always be true however you could compare with a previous state to see when the state was activated. + GameLogic.getCurrentController().state & GameLogic.getCurrentController().owner.state + @deprecated: Use the L{state} property + @rtype: int + """ + def getSensors(): + """ + Gets a list of all sensors attached to this controller. + @deprecated: use the L{sensors} property + @rtype: list [L{SCA_ISensor}] + """ + def getSensor(name): + """ + Gets the named linked sensor. + @deprecated: use the L{sensors}[name] property + @type name: string + @rtype: L{SCA_ISensor} + """ + def getActuators(): + """ + Gets a list of all actuators linked to this controller. + @deprecated: Use the L{actuators} property + @rtype: list [L{SCA_IActuator}] + """ + def getActuator(name): + """ + Gets the named linked actuator. + @deprecated: use the L{actuators}[name] property + @type name: string + @rtype: L{SCA_IActuator} + """ +#} + +class SCA_IActuator(SCA_ILogicBrick): + """ + Base class for all actuator logic bricks. + """ + +class BL_ActionActuator(SCA_IActuator): + """ + Action Actuators apply an action to an actor. + + @ivar action: The name of the action to set as the current action. + @type action: string + @ivar frameStart: Specifies the starting frame of the animation. + @type frameStart: float + @ivar frameEnd: Specifies the ending frame of the animation. + @type frameEnd: float + @ivar blendIn: Specifies the number of frames of animation to generate when making transitions between actions. + @type blendIn: float + @ivar priority: Sets the priority of this actuator. Actuators will lower + priority numbers will override actuators with higher + numbers. + @type priority: integer + @ivar frame: Sets the current frame for the animation. + @type frame: float + @ivar propName: Sets the property to be used in FromProp playback mode. + @type propName: string + @ivar blendTime: Sets the internal frame timer. This property must be in + the range from 0.0 to blendIn. + @type blendTime: float + @ivar mode: The operation mode of the actuator. KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND + @type mode: integer + @ivar useContinue: The actions continue option, True or False. + 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. + @type useContinue: boolean + @ivar framePropName: The name of the property that is set to the current frame number. + @type framePropName: string + """ + def setChannel(channel, matrix, mode = False): + """ + @param channel: A string specifying the name of the bone channel. + @type channel: string + @param matrix: A 4x4 matrix specifying the overriding transformation + as an offset from the bone's rest position. + @type matrix: list [[float]] + @param mode: True for armature/world space, False for bone space + @type mode: boolean + """ + +#{ Deprecated + def setAction(action, reset = True): + """ + Sets the current action. + @deprecated: use the L{action} property + @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. + @deprecated: Use the L{frameStart} property + @param start: the starting frame of the animation + @type start: float + """ + + def setEnd(end): + """ + Specifies the ending frame of the animation. + @deprecated: use the L{frameEnd} property + @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. + @deprecated: use the L{blendIn} property + @param blendin: the number of frames in transition. + @type blendin: float + """ + + def setPriority(priority): + """ + Sets the priority of this actuator. + + @deprecated: Use use the L{priority} property + @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. + + @deprecated: use the L{frame} property + @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. + + @deprecated: use the L{property} property + @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. + + @deprecated: use the L{blendTime} property + @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 + + @deprecated: use the L{type} property + @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. + + @deprecated: use the L{useContinue} property + @param cont: The continue option. + @type cont: bool + """ + + def getType(): + """ + Returns the operation mode of the actuator + + @deprecated: use the L{type} property + @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. + + @deprecated: use the L{useContinue} property + @rtype: bool + """ + + def getAction(): + """ + getAction() returns the name of the action associated with this actuator. + + @deprecated: use the L{action} property + @rtype: string + """ + + def getStart(): + """ + Returns the starting frame of the action. + + @deprecated: use the L{frameStart} property + @rtype: float + """ + def getEnd(): + """ + Returns the last frame of the action. + + @deprecated: use the L{frameEnd} property + @rtype: float + """ + def getBlendin(): + """ + Returns the number of interpolation animation frames to be generated when this actuator is triggered. + + @deprecated: use the L{blendIn} property + @rtype: float + """ + def getPriority(): + """ + Returns the priority for this actuator. Actuators with lower Priority numbers will + override actuators with higher numbers. + + @deprecated: use the L{priority} property + @rtype: integer + """ + def getFrame(): + """ + Returns the current frame number. + + @deprecated: use the L{frame} property + @rtype: float + """ + def getProperty(): + """ + Returns the name of the property to be used in FromProp mode. + + @deprecated: use the L{property} property + @rtype: string + """ + def setFrameProperty(prop): + """ + @deprecated: use the L{framePropName} property + @param prop: A string specifying the property of the object that will be updated with the action frame number. + @type prop: string + """ + def getFrameProperty(): + """ + Returns the name of the property that is set to the current frame number. + + @deprecated: use the L{framePropName} property + @rtype: string + """ +#} + +class BL_Shader(PyObjectPlus): + """ + BL_Shader GLSL shaders. + + TODO - Description + """ + + def setUniformfv(name, fList): + """ + Set a uniform with a list of float values + + @param name: the uniform name + @type name: string + + @param fList: a list (2, 3 or 4 elements) of float values + @type fList: list[float] + """ + + def delSource(): + """ + Clear the shader. Use this method before the source is changed with L{setSource}. + """ + def getFragmentProg(): + """ + Returns the fragment program. + + @rtype: string + @return: The fragment program. + """ + def getVertexProg(): + """ + Get the vertex program. + + @rtype: string + @return: The vertex program. + """ + def isValid(): + """ + Check if the shader is valid. + + @rtype: bool + @return: True if the shader is valid + """ + def setAttrib(enum): + """ + Set attribute location. (The parameter is ignored a.t.m. and the value of "tangent" is always used.) + + @param enum: attribute location value + @type enum: integer + """ + def setNumberOfPasses( max_pass ): + """ + Set the maximum number of passes. Not used a.t.m. + + @param max_pass: the maximum number of passes + @type max_pass: integer + """ + def setSampler(name, index): + """ + Set uniform texture sample index. + + @param name: Uniform name + @type name: string + + @param index: Texture sample index. + @type index: integer + """ + def setSource(vertexProgram, fragmentProgram): + """ + Set the vertex and fragment programs + + @param vertexProgram: Vertex program + @type vertexProgram: string + + @param fragmentProgram: Fragment program + @type fragmentProgram: string + """ + def setUniform1f(name, fx): + """ + Set a uniform with 1 float value. + + @param name: the uniform name + @type name: string + + @param fx: Uniform value + @type fx: float + """ + def setUniform1i(name, ix): + """ + Set a uniform with an integer value. + + @param name: the uniform name + @type name: string + + @param ix: the uniform value + @type ix: integer + """ + def setUniform2f(name, fx, fy): + """ + Set a uniform with 2 float values + + @param name: the uniform name + @type name: string + + @param fx: first float value + @type fx: float + + @param fy: second float value + @type fy: float + """ + def setUniform2i(name, ix, iy): + """ + Set a uniform with 2 integer values + + @param name: the uniform name + @type name: string + + @param ix: first integer value + @type ix: integer + + @param iy: second integer value + @type iy: integer + """ + def setUniform3f(name, fx,fy,fz): + """ + Set a uniform with 3 float values. + + @param name: the uniform name + @type name: string + + @param fx: first float value + @type fx: float + + @param fy: second float value + @type fy: float + + @param fz: third float value + @type fz: float + """ + def setUniform3i(name, ix,iy,iz): + """ + Set a uniform with 3 integer values + + @param name: the uniform name + @type name: string + + @param ix: first integer value + @type ix: integer + + @param iy: second integer value + @type iy: integer + + @param iz: third integer value + @type iz: integer + """ + def setUniform4f(name, fx,fy,fz,fw): + """ + Set a uniform with 4 float values. + + @param name: the uniform name + @type name: string + + @param fx: first float value + @type fx: float + + @param fy: second float value + @type fy: float + + @param fz: third float value + @type fz: float + + @param fw: fourth float value + @type fw: float + """ + def setUniform4i(name, ix,iy,iz, iw): + """ + Set a uniform with 4 integer values + + @param name: the uniform name + @type name: string + + @param ix: first integer value + @type ix: integer + + @param iy: second integer value + @type iy: integer + + @param iz: third integer value + @type iz: integer + + @param iw: fourth integer value + @type iw: integer + """ + def setUniformDef(name, type): + """ + Define a new uniform + + @param name: the uniform name + @type name: string + + @param type: uniform type + @type type: UNI_NONE, UNI_INT, UNI_FLOAT, UNI_INT2, UNI_FLOAT2, UNI_INT3, UNI_FLOAT3, UNI_INT4, UNI_FLOAT4, UNI_MAT3, UNI_MAT4, UNI_MAX + """ + def setUniformMatrix3(name, mat, transpose): + """ + Set a uniform with a 3x3 matrix value + + @param name: the uniform name + @type name: string + + @param mat: A 3x3 matrix [[f,f,f], [f,f,f], [f,f,f]] + @type mat: 3x3 matrix + + @param transpose: set to True to transpose the matrix + @type transpose: bool + """ + def setUniformMatrix4(name, mat, transpose): + """ + Set a uniform with a 4x4 matrix value + + @param name: the uniform name + @type name: string + + @param mat: A 4x4 matrix [[f,f,f,f], [f,f,f,f], [f,f,f,f], [f,f,f,f]] + @type mat: 4x4 matrix + + @param transpose: set to True to transpose the matrix + @type transpose: bool + """ + def setUniformiv(name, iList): + """ + Set a uniform with a list of integer values + + @param name: the uniform name + @type name: string + + @param iList: a list (2, 3 or 4 elements) of integer values + @type iList: list[integer] + """ + def validate(): + """ + Validate the shader object. + + """ + +class BL_ShapeActionActuator(SCA_IActuator): + """ + ShapeAction Actuators apply an shape action to an mesh object.\ + + @ivar action: The name of the action to set as the current shape action. + @type action: string + @ivar frameStart: Specifies the starting frame of the shape animation. + @type frameStart: float + @ivar frameEnd: Specifies the ending frame of the shape animation. + @type frameEnd: float + @ivar blendIn: Specifies the number of frames of animation to generate when making transitions between actions. + @type blendIn: float + @ivar priority: Sets the priority of this actuator. Actuators will lower + priority numbers will override actuators with higher + numbers. + @type priority: integer + @ivar frame: Sets the current frame for the animation. + @type frame: float + @ivar propName: Sets the property to be used in FromProp playback mode. + @type propName: string + @ivar blendTime: Sets the internal frame timer. This property must be in + the range from 0.0 to blendin. + @type blendTime: float + @ivar mode: The operation mode of the actuator. + KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, + KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND + @type mode: integer + @ivar framePropName: The name of the property that is set to the current frame number. + @type framePropName: string + + """ +#{ Deprecated + def setAction(action, reset = True): + """ + Sets the current action. + + @deprecated: use the L{action} property + @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. + + @deprecated: use the L{frameStart} property + @param start: the starting frame of the animation + @type start: float + """ + + def setEnd(end): + """ + Specifies the ending frame of the animation. + + @deprecated: use the L{frameEnd} property + @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. + + @deprecated: use the L{blendIn} property + @param blendin: the number of frames in transition. + @type blendin: float + """ + + def setPriority(priority): + """ + Sets the priority of this actuator. + + @deprecated: use the L{priority} property + @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. + + @deprecated: use the L{frame} property + @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. + + @deprecated: use the L{property} property + @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. + + @deprecated: use the L{blendTime} property + @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 + + @deprecated: use the L{type} property + @param mode: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND + @type mode: integer + """ + + def getType(): + """ + Returns the operation mode of the actuator + + @deprecated: use the L{type} property + @rtype: integer + @return: KX_ACTIONACT_PLAY, KX_ACTIONACT_PROPERTY, KX_ACTIONACT_FLIPPER, KX_ACTIONACT_LOOPSTOP, KX_ACTIONACT_LOOPEND + """ + + def getAction(): + """ + getAction() returns the name of the action associated with this actuator. + + @deprecated: use the L{action} property + @rtype: string + """ + + def getStart(): + """ + Returns the starting frame of the action. + + @deprecated: use the L{frameStart} property + @rtype: float + """ + def getEnd(): + """ + Returns the last frame of the action. + + @deprecated: use the L{frameEnd} property + @rtype: float + """ + def getBlendin(): + """ + Returns the number of interpolation animation frames to be generated when this actuator is triggered. + + @deprecated: use the L{blendIn} property + @rtype: float + """ + def getPriority(): + """ + Returns the priority for this actuator. Actuators with lower Priority numbers will + override actuators with higher numbers. + + @deprecated: use the L{priority} property + @rtype: integer + """ + def getFrame(): + """ + Returns the current frame number. + + @deprecated: use the L{frame} property + @rtype: float + """ + def getProperty(): + """ + Returns the name of the property to be used in FromProp mode. + + @deprecated: use the L{property} property + @rtype: string + """ + def setFrameProperty(prop): + """ + @deprecated: use the L{framePropName} property + @param prop: A string specifying the property of the object that will be updated with the action frame number. + @type prop: string + """ + def getFrameProperty(): + """ + Returns the name of the property that is set to the current frame number. + + @deprecated: use the L{framePropName} property + @rtype: string + """ +#} + +class CListValue(CPropValue): + """ + CListValue + + This is a list like object used in the game engine internally that behaves similar to a python list in most ways. + + As well as the normal index lookup. + C{val= clist[i]} + + CListValue supports string lookups. + C{val= scene.objects["OBCube"]} + + Other operations such as C{len(clist), list(clist), clist[0:10]} are also supported. + """ + def append(val): + """ + Add an item to the list (like pythons append) + + Warning: Appending values to the list can cause crashes when the list is used internally by the game engine. + """ + + def count(val): + """ + Count the number of instances of a value in the list. + + @rtype: integer + @return: number of instances + """ + def index(val): + """ + Return the index of a value in the list. + + @rtype: integer + @return: The index of the value in the list. + """ + def reverse(): + """ + Reverse the order of the list. + """ + def get(key, default=None): + """ + Return the value matching key, or the default value if its not found. + @return: The key value or a default. + """ + def has_key(key): + """ + Return True if the key is found. + @rtype: boolean + @return: The key value or a default. + """ + def from_id(id): + """ + This is a funtion especially for the game engine to return a value with a spesific id. + + Since object names are not always unique, the id of an object can be used to get an object from the CValueList. + + Example. + + C{myObID = id(gameObject)} + + C{...} + + C{ob= scene.objects.from_id(myObID)} + + Where myObID is an int or long from the id function. + + This has the advantage that you can store the id in places you could not store a gameObject. + + Warning: the id is derived from a memory location and will be different each time the game engine starts. + """ + +class KX_BlenderMaterial(PyObjectPlus): # , RAS_IPolyMaterial) + """ + KX_BlenderMaterial + + """ + + def getShader(): + """ + Returns the material's shader. + + @rtype: L{BL_Shader} + @return: the material's shader + """ + + def setBlending(src, dest): + """ + Set the pixel color arithmetic functions. + + @param src: Specifies how the red, green, blue, + and alpha source blending factors are computed. + @type src: GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_SRC_ALPHA_SATURATE + + + @param dest: Specifies how the red, green, blue, + and alpha destination blending factors are computed. + @type dest: GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_SRC_ALPHA_SATURATE + + """ + def getMaterialIndex(): + """ + Returns the material's index. + + @rtype: integer + @return: the material's index + """ + +class KX_CDActuator(SCA_IActuator): + """ + CD Controller actuator. + @ivar volume: controls the volume to set the CD to. 0.0 = silent, 1.0 = max volume. + @type volume: float + @ivar track: the track selected to be played + @type track: integer + @ivar gain: the gain (volume) of the CD between 0.0 and 1.0. + @type gain: float + """ + def startCD(): + """ + Starts the CD playing. + """ + def stopCD(): + """ + Stops the CD playing. + """ + def pauseCD(): + """ + Pauses the CD. + """ + def resumeCD(): + """ + Resumes the CD after a pause. + """ + def playAll(): + """ + Plays the CD from the beginning. + """ + def playTrack(trackNumber): + """ + Plays the track selected. + """ +#{ Deprecated + def setGain(gain): + """ + Sets the gain (volume) of the CD. + + @deprecated: Use the L{volume} property. + @type gain: float + @param gain: the gain to set the CD to. 0.0 = silent, 1.0 = max volume. + """ + def getGain(): + """ + Gets the current gain (volume) of the CD. + + @deprecated: Use the L{volume} property. + @rtype: float + @return: Between 0.0 (silent) and 1.0 (max volume) + """ +#} + +class KX_CameraActuator(SCA_IActuator): + """ + Applies changes to a camera. + + @ivar min: minimum distance to the target object maintained by the actuator + @type min: float + @ivar max: maximum distance to stay from the target object + @type max: float + @ivar height: height to stay above the target object + @type height: float + @ivar useXY: axis this actuator is tracking, true=X, false=Y + @type useXY: boolean + @ivar object: the object this actuator tracks. + @type object: KX_GameObject or None + @author: snail + """ +#{ Deprecated + def getObject(name_only = 1): + """ + Returns the name of the object this actuator tracks. + + @deprecated: Use the L{object} attribute instead. + @type name_only: bool + @param name_only: optional argument, when 0 return a KX_GameObject + @rtype: string, KX_GameObject or None if no object is set + """ + + def setObject(target): + """ + Sets the object this actuator tracks. + + @deprecated: Use the L{object} attribute instead. + @param target: the object to track. + @type target: L{KX_GameObject}, string or None + """ + + def getMin(): + """ + Returns the minimum distance to target maintained by the actuator. + + @deprecated: Use the L{min} attribute instead. + @rtype: float + """ + + def setMin(distance): + """ + Sets the minimum distance to the target object maintained by the + actuator. + + @deprecated: Use the L{min} attribute instead. + @param distance: The minimum distance to maintain. + @type distance: float + """ + + def getMax(): + """ + Gets the maximum distance to stay from the target object. + + @deprecated: Use the L{max} attribute instead. + @rtype: float + """ + + def setMax(distance): + """ + Sets the maximum distance to stay from the target object. + + @deprecated: Use the L{max} attribute instead. + @param distance: The maximum distance to maintain. + @type distance: float + """ + + def getHeight(): + """ + Returns the height to stay above the target object. + + @deprecated: Use the L{height} attribute instead. + @rtype: float + """ + + def setHeight(height): + """ + Sets the height to stay above the target object. + + @deprecated: Use the L{height} attribute instead. + @type height: float + @param height: The height to stay above the target object. + """ + + def setXY(xaxis): + """ + Sets the axis to get behind. + + @deprecated: Use the L{useXY} attribute instead. + @param xaxis: False to track Y axis, True to track X axis. + @type xaxis: boolean + """ + + def getXY(): + """ + Returns the axis this actuator is tracking. + + @deprecated: Use the L{useXY} attribute instead. + @return: True if tracking X axis, False if tracking Y axis. + @rtype: boolean + """ +#} + +class KX_ConstraintActuator(SCA_IActuator): + """ + A constraint actuator limits the position, rotation, distance or orientation of an object. + + Properties: + + @ivar damp: time constant of the constraint expressed in frame (not use by Force field constraint) + @type damp: integer + + @ivar rotDamp: time constant for the rotation expressed in frame (only for the distance constraint) + 0 = use damp for rotation as well + @type rotDamp: integer + + @ivar direction: the reference direction in world coordinate for the orientation constraint + @type direction: 3-tuple of float: [x,y,z] + + @ivar option: Binary combination of the following values: + Applicable to Distance constraint: + - KX_ACT_CONSTRAINT_NORMAL ( 64) : Activate alignment to surface + - KX_ACT_CONSTRAINT_DISTANCE ( 512) : Activate distance control + - KX_ACT_CONSTRAINT_LOCAL (1024) : direction of the ray is along the local axis + Applicable to Force field constraint: + - KX_ACT_CONSTRAINT_DOROTFH (2048) : Force field act on rotation as well + Applicable to both: + - KX_ACT_CONSTRAINT_MATERIAL ( 128) : Detect material rather than property + - KX_ACT_CONSTRAINT_PERMANENT ( 256) : No deactivation if ray does not hit target + @type option: integer + + @ivar time: activation time of the actuator. The actuator disables itself after this many frame. + If set to 0, the actuator is not limited in time. + @type time: integer + + @ivar propName: the name of the property or material for the ray detection of the distance constraint. + @type propName: string + + @ivar min: The lower bound of the constraint + For the rotation and orientation constraint, it represents radiant + @type min: float + + @ivar distance: the target distance of the distance constraint + @type distance: float + + @ivar max: the upper bound of the constraint. + For rotation and orientation constraints, it represents radiant. + @type max: float + + @ivar rayLength: the length of the ray of the distance constraint. + @type rayLength: float + + @ivar limit: type of constraint, use one of the following constant: + KX_ACT_CONSTRAINT_LOCX ( 1) : limit X coord + KX_ACT_CONSTRAINT_LOCY ( 2) : limit Y coord + KX_ACT_CONSTRAINT_LOCZ ( 3) : limit Z coord + KX_ACT_CONSTRAINT_ROTX ( 4) : limit X rotation + KX_ACT_CONSTRAINT_ROTY ( 5) : limit Y rotation + KX_ACT_CONSTRAINT_ROTZ ( 6) : limit Z rotation + KX_ACT_CONSTRAINT_DIRPX ( 7) : set distance along positive X axis + KX_ACT_CONSTRAINT_DIRPY ( 8) : set distance along positive Y axis + KX_ACT_CONSTRAINT_DIRPZ ( 9) : set distance along positive Z axis + KX_ACT_CONSTRAINT_DIRNX (10) : set distance along negative X axis + KX_ACT_CONSTRAINT_DIRNY (11) : set distance along negative Y axis + KX_ACT_CONSTRAINT_DIRNZ (12) : set distance along negative Z axis + KX_ACT_CONSTRAINT_ORIX (13) : set orientation of X axis + KX_ACT_CONSTRAINT_ORIY (14) : set orientation of Y axis + KX_ACT_CONSTRAINT_ORIZ (15) : set orientation of Z axis + KX_ACT_CONSTRAINT_FHPX (16) : set force field along positive X axis + KX_ACT_CONSTRAINT_FHPY (17) : set force field along positive Y axis + KX_ACT_CONSTRAINT_FHPZ (18) : set force field along positive Z axis + KX_ACT_CONSTRAINT_FHNX (19) : set force field along negative X axis + KX_ACT_CONSTRAINT_FHNY (20) : set force field along negative Y axis + KX_ACT_CONSTRAINT_FHNZ (21) : set force field along negative Z axis + @type limit: integer + """ +#{ Deprecated + def setDamp(time): + """ + Sets the time this constraint is delayed. + + @param time: The number of frames to delay. + Negative values are ignored. + @type time: integer + """ + def getDamp(): + """ + Returns the damping time of the constraint. + + @rtype: integer + """ + def setMin(lower): + """ + Sets the lower bound of the constraint. + + For rotational and orientation constraints, lower is specified in degrees. + + @type lower: float + """ + def getMin(): + """ + Gets the lower bound of the constraint. + + For rotational and orientation constraints, the lower bound is returned in radians. + + @rtype: float + """ + def setMax(upper): + """ + Sets the upper bound of the constraint. + + For rotational and orientation constraints, upper is specified in degrees. + + @type upper: float + """ + def getMax(): + """ + Gets the upper bound of the constraint. + + For rotational and orientation constraints, the upper bound is returned in radians. + + @rtype: float + """ + def setLimit(limit): + """ + Sets the type of constraint. + + See module L{GameLogic} for valid constraint types. + + @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(): + """ + Gets the type of constraint. + + 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, 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 + """ +#} + +class KX_ConstraintWrapper(PyObjectPlus): + """ + KX_ConstraintWrapper + + """ + def getConstraintId(val): + """ + Returns the contraint's ID + + @rtype: integer + @return: the constraint's ID + """ + +class KX_GameActuator(SCA_IActuator): + """ + The game actuator loads a new .blend file, restarts the current .blend file or quits the game. + + Properties: + + @ivar fileName: the new .blend file to load + @type fileName: string. + @ivar mode: The mode of this actuator + @type mode: Constant in... + - L{GameLogic.KX_GAME_LOAD} + - L{GameLogic.KX_GAME_START} + - L{GameLogic.KX_GAME_RESTART} + - L{GameLogic.KX_GAME_QUIT} + - L{GameLogic.KX_GAME_SAVECFG} + - L{GameLogic.KX_GAME_LOADCFG} + """ +#{ Deprecated + def getFile(): + """ + Returns the filename of the new .blend file to load. + + @deprecated: use the L{fileName} property + @rtype: string + """ + def setFile(filename): + """ + Sets the new .blend file to load. + + @deprecated: use the L{fileName} property + @param filename: The file name this actuator will load. + @type filename: string + """ +#} + +class KX_GameObject(SCA_IObject): + """ + All game objects are derived from this class. + + Properties assigned to game objects are accessible as attributes of this class. + - note: Calling ANY method or attribute on an object that has been removed from a scene will raise a SystemError, if an object may have been removed since last accessing it use the L{invalid} attribute to check. + + @ivar name: The object's name. (read-only) + - note: Currently (Blender 2.49) the prefix "OB" is added to all objects name. This may change in blender 2.5. + @type name: string. + @ivar mass: The object's mass + - note: The object must have a physics controller for the mass to be applied, otherwise the mass value will be returned as 0.0 + @type mass: float + @ivar linVelocityMin: Enforces the object keeps moving at a minimum velocity. + - note: Applies to dynamic and rigid body objects only. + - note: A value of 0.0 disables this option. + - note: While objects are stationary the minimum velocity will not be applied. + @type linVelocityMin: float + @ivar linVelocityMax: Clamp the maximum linear velocity to prevent objects moving beyond a set speed. + - note: Applies to dynamic and rigid body objects only. + - note: A value of 0.0 disables this option (rather then setting it stationary). + @type linVelocityMax: float + @ivar localInertia: the object's inertia vector in local coordinates. Read only. + @type localInertia: list [ix, iy, iz] + @ivar parent: The object's parent object. (read-only) + @type parent: L{KX_GameObject} or None + @ivar visible: visibility flag. + - note: Game logic will still run for invisible objects. + @type visible: boolean + @ivar occlusion: occlusion capability flag. + @type occlusion: boolean + @ivar position: The object's position. + + deprecated: use L{localPosition} and L{worldPosition} + @type position: list [x, y, z] On write: local position, on read: world position + @ivar orientation: The object's orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector. + + deprecated: use L{localOrientation} and L{worldOrientation} + @type orientation: 3x3 Matrix [[float]] On write: local orientation, on read: world orientation + @ivar scaling: The object's scaling factor. list [sx, sy, sz] + + deprecated: use L{localScale} and L{worldScale} + @type scaling: list [sx, sy, sz] On write: local scaling, on read: world scaling + @ivar localOrientation: The object's local orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector. + @type localOrientation: 3x3 Matrix [[float]] + @ivar worldOrientation: The object's world orientation. + @type worldOrientation: 3x3 Matrix [[float]] + @ivar localScale: The object's local scaling factor. + @type localScale: list [sx, sy, sz] + @ivar worldScale: The object's world scaling factor. Read-only + @type worldScale: list [sx, sy, sz] + @ivar localPosition: The object's local position. + @type localPosition: list [x, y, z] + @ivar worldPosition: The object's world position. + @type worldPosition: list [x, y, z] + @ivar timeOffset: adjust the slowparent delay at runtime. + @type timeOffset: float + @ivar state: the game object's state bitmask, using the first 30 bits, one bit must always be set. + @type state: int + @ivar meshes: a list meshes for this object. + - note: Most objects use only 1 mesh. + - note: Changes to this list will not update the KX_GameObject. + @type meshes: list of L{KX_MeshProxy} + @ivar sensors: a sequence of L{SCA_ISensor} objects with string/index lookups and iterator support. + - note: This attribute is experemental and may be removed (but probably wont be). + - note: Changes to this list will not update the KX_GameObject. + @type sensors: list + @ivar controllers: a sequence of L{SCA_IController} objects with string/index lookups and iterator support. + - note: This attribute is experemental and may be removed (but probably wont be). + - note: Changes to this list will not update the KX_GameObject. + @type controllers: list of L{SCA_ISensor}. + @ivar actuators: a list of L{SCA_IActuator} with string/index lookups and iterator support. + - note: This attribute is experemental and may be removed (but probably wont be). + - note: Changes to this list will not update the KX_GameObject. + @type actuators: list + @ivar attrDict: get the objects internal python attribute dictionary for direct (faster) access. + @type attrDict: dict + @ivar children: direct children of this object, (read-only). + @type children: L{CListValue} of L{KX_GameObject}'s + @ivar childrenRecursive: all children of this object including childrens children, (read-only). + @type childrenRecursive: L{CListValue} of L{KX_GameObject}'s + @group Deprecated: getPosition, setPosition, setWorldPosition, getOrientation, setOrientation, getState, setState, getParent, getVisible, getMass, getMesh, getChildren, getChildrenRecursive + @group Property Access: get, has_key, attrDict, getPropertyNames + """ + def endObject(): + """ + Delete this object, can be used inpace of the EndObject Actuator. + The actual removal of the object from the scene is delayed. + """ + def replaceMesh(mesh): + """ + Replace the mesh of this object with a new mesh. This works the same was as the actuator. + @type mesh: L{KX_MeshProxy} or mesh name + """ + def getVisible(): + """ + Gets the game object's visible flag. + + @deprecated: use L{visible} + @rtype: boolean + """ + def setVisible(visible, recursive): + """ + Sets the game object's visible flag. + + @type visible: boolean + @type recursive: boolean + @param recursive: optional argument to set all childrens visibility flag too. + """ + def setOcclusion(occlusion, recursive): + """ + Sets the game object's occlusion capability. + + @type occlusion: boolean + @type recursive: boolean + @param recursive: optional argument to set all childrens occlusion flag too. + """ + def getState(): + """ + Gets the game object's state bitmask. + + @deprecated: use L{state} + @rtype: int + @return: the objects state. + """ + def setState(state): + """ + Sets the game object's state flag. + The bitmasks for states from 1 to 30 can be set with (1<<0, 1<<1, 1<<2 ... 1<<29) + @deprecated: use L{state} + @type state: integer + """ + def setPosition(pos): + """ + Sets the game object's position. + Global coordinates for root object, local for child objects. + + @deprecated: use L{localPosition} + @type pos: [x, y, z] + @param pos: the new position, in local coordinates. + """ + def setWorldPosition(pos): + """ + Sets the game object's position in world coordinates regardless if the object is root or child. + + @deprecated: use L{worldPosition} + @type pos: [x, y, z] + @param pos: the new position, in world coordinates. + """ + def getPosition(): + """ + Gets the game object's position. + + @deprecated: use L{worldPosition} + @rtype: list [x, y, z] + @return: the object's position in world coordinates. + """ + def setOrientation(orn): + """ + Sets the game object's orientation. + + @deprecated: use L{localOrientation} + @type orn: 3x3 rotation matrix, or Quaternion. + @param orn: a rotation matrix specifying the new rotation. + @note: When using this matrix with Blender.Mathutils.Matrix() types, it will need to be transposed. + """ + def alignAxisToVect(vect, axis, factor): + """ + Aligns any of the game object's axis along the given vector. + + @type vect: 3d vector. + @param vect: a vector to align the axis. + @type axis: integer. + @param axis:The axis you want to align + - 0: X axis + - 1: Y axis + - 2: Z axis (default) + @type factor: float + @param factor: Only rotate a feaction of the distance to the target vector (0.0 - 1.0) + """ + def getAxisVect(vect): + """ + Returns the axis vector rotates by the objects worldspace orientation. + This is the equivalent if multiplying the vector by the orientation matrix. + + @type vect: 3d vector. + @param vect: a vector to align the axis. + @rtype: 3d vector. + @return: The vector in relation to the objects rotation. + + """ + def getOrientation(): + """ + Gets the game object's orientation. + + @deprecated: use L{worldOrientation} + @rtype: 3x3 rotation matrix + @return: The game object's rotation matrix + @note: When using this matrix with Blender.Mathutils.Matrix() types, it will need to be transposed. + """ + def applyMovement(movement, local = 0): + """ + Sets the game object's movement. + + @type movement: 3d vector. + @param movement: movement vector. + @type local: boolean + @param local: - False: you get the "global" movement ie: relative to world orientation (default). + - True: you get the "local" movement ie: relative to object orientation. + """ + def applyRotation(rotation, local = 0): + """ + Sets the game object's rotation. + + @type rotation: 3d vector. + @param rotation: rotation vector. + @type local: boolean + @param local: - False: you get the "global" rotation ie: relative to world orientation (default). + - True: you get the "local" rotation ie: relative to object orientation. + """ + def applyForce(force, local = 0): + """ + Sets the game object's force. + + This requires a dynamic object. + + @type force: 3d vector. + @param force: force vector. + @type local: boolean + @param local: - False: you get the "global" force ie: relative to world orientation (default). + - True: you get the "local" force ie: relative to object orientation. + """ + def applyTorque(torque, local = 0): + """ + Sets the game object's torque. + + This requires a dynamic object. + + @type torque: 3d vector. + @param torque: torque vector. + @type local: boolean + @param local: - False: you get the "global" torque ie: relative to world orientation (default). + - True: you get the "local" torque ie: relative to object orientation. + """ + def getLinearVelocity(local = 0): + """ + Gets the game object's linear velocity. + + This method returns the game object's velocity through it's centre of mass, + ie no angular velocity component. + + @type local: boolean + @param local: - False: you get the "global" velocity ie: relative to world orientation (default). + - True: you get the "local" velocity ie: relative to object orientation. + @rtype: list [vx, vy, vz] + @return: the object's linear velocity. + """ + def setLinearVelocity(velocity, local = 0): + """ + Sets the game object's linear velocity. + + This method sets game object's velocity through it's centre of mass, + ie no angular velocity component. + + This requires a dynamic object. + + @type velocity: 3d vector. + @param velocity: linear velocity vector. + @type local: boolean + @param local: - False: you get the "global" velocity ie: relative to world orientation (default). + - True: you get the "local" velocity ie: relative to object orientation. + """ + def getAngularVelocity(local = 0): + """ + Gets the game object's angular velocity. + + @type local: boolean + @param local: - False: you get the "global" velocity ie: relative to world orientation (default). + - True: you get the "local" velocity ie: relative to object orientation. + @rtype: list [vx, vy, vz] + @return: the object's angular velocity. + """ + def setAngularVelocity(velocity, local = 0): + """ + Sets the game object's angular velocity. + + This requires a dynamic object. + + @type velocity: 3d vector. + @param velocity: angular velocity vector. + @type local: boolean + @param local: - False: you get the "global" velocity ie: relative to world orientation (default). + - True: you get the "local" velocity ie: relative to object orientation. + """ + def getVelocity(point): + """ + Gets the game object's velocity at the specified point. + + Gets the game object's velocity at the specified point, including angular + components. + + @type point: list [x, y, z] + @param point: the point to return the velocity for, in local coordinates. (optional: default = [0, 0, 0]) + @rtype: list [vx, vy, vz] + @return: the velocity at the specified point. + """ + def getMass(): + """ + Gets the game object's mass. + + @deprecated: use L{mass} + @rtype: float + @return: the object's mass. + """ + def getReactionForce(): + """ + Gets the game object's reaction force. + + The reaction force is the force applied to this object over the last simulation timestep. + This also includes impulses, eg from collisions. + + (B{This is not implimented for bullet physics at the moment}) + + @rtype: list [fx, fy, fz] + @return: the reaction force of this object. + """ + def applyImpulse(point, impulse): + """ + Applies an impulse to the game object. + + This will apply the specified impulse to the game object at the specified point. + If point != getPosition(), applyImpulse will also change the object's angular momentum. + Otherwise, only linear momentum will change. + + @type point: list [x, y, z] + @param point: the point to apply the impulse to (in world coordinates) + """ + def suspendDynamics(): + """ + Suspends physics for this object. + """ + def restoreDynamics(): + """ + Resumes physics for this object. + @Note: The objects linear velocity will be applied from when the dynamics were suspended. + """ + def enableRigidBody(): + """ + Enables rigid body physics for this object. + + Rigid body physics allows the object to roll on collisions. + @Note: This is not working with bullet physics yet. + """ + def disableRigidBody(): + """ + Disables rigid body physics for this object. + @Note: This is not working with bullet physics yet. The angular is removed but rigid body physics can still rotate it later. + """ + def getParent(): + """ + Gets this object's parent. + + @deprecated: use L{parent} + @rtype: L{KX_GameObject} + @return: this object's parent object, or None if this object has no parent. + """ + def setParent(parent,compound,ghost): + """ + Sets this object's parent. + Control the shape status with the optional compound and ghost parameters: + compound=1: the object shape should be added to the parent compound shape (default) + compound=0: the object should keep its individual shape. + In that case you can control if it should be ghost or not: + ghost=1 if the object should be made ghost while parented (default) + ghost=0 if the object should be solid while parented + Note: if the object type is sensor, it stays ghost regardless of ghost parameter + + @type parent: L{KX_GameObject} + @param parent: new parent object. + @type compound: int + @param compound: whether the shape should be added to the parent compound shape + @type ghost: int + @param ghost: whether the object should be ghost while parented + """ + def removeParent(): + """ + Removes this objects parent. + """ + def getChildren(): + """ + Return a list of immediate children of this object. + @rtype: L{CListValue} of L{KX_GameObject} + @return: a list of all this objects children. + """ + def getChildrenRecursive(): + """ + Return a list of children of this object, including all their childrens children. + @rtype: L{CListValue} of L{KX_GameObject} + @return: a list of all this objects children recursivly. + """ + def getMesh(mesh): + """ + Gets the mesh object for this object. + + @type mesh: integer + @param mesh: the mesh object to return (optional: default mesh = 0) + @rtype: L{KX_MeshProxy} + @return: the first mesh object associated with this game object, or None if this object has no meshs. + """ + def getPhysicsId(): + """ + Returns the user data object associated with this game object's physics controller. + """ + def getPropertyNames(): + """ + Gets a list of all property names. + @rtype: list + @return: All property names for this object. + """ + def getDistanceTo(other): + """ + Returns the distance to another object or point. + + @param other: a point or another L{KX_GameObject} to measure the distance to. + @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. + + The ray is always casted from the center of the object, ignoring the object itself. + The ray is casted towards the center of another object or an explicit [x,y,z] point. + Use rayCast() if you need to retrieve the hit point + + @param other: [x,y,z] or object towards which the ray is casted + @type other: L{KX_GameObject} or 3-tuple + @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other + @type dist: float + @param prop: property name that object must have; can be omitted => detect any object + @type prop: string + @rtype: L{KX_GameObject} + @return: the first object hit or None if no object or object does not match prop + """ + def rayCast(objto,objfrom,dist,prop,face,xray,poly): + """ + Look from a point/object to another point/object and find first object hit within dist that matches prop. + if poly is 0, returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit. + if poly is 1, returns a 4-tuple with in addition a L{KX_PolyProxy} as 4th element. + + Ex:: + # shoot along the axis gun-gunAim (gunAim should be collision-free) + ob,point,normal = gun.rayCast(gunAim,None,50) + if ob: + # hit something + + Notes: + The ray ignores the object on which the method is called. + It is casted from/to object center or explicit [x,y,z] points. + + The face paremeter determines the orientation of the normal:: + 0 => hit normal is always oriented towards the ray origin (as if you casted the ray from outside) + 1 => hit normal is the real face normal (only for mesh object, otherwise face has no effect) + + The ray has X-Ray capability if xray parameter is 1, otherwise the first object hit (other than self object) stops the ray. + The prop and xray parameters interact as follow:: + prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray. + prop off, xray on : idem. + prop on, xray off: return closest hit if it matches prop, no hit otherwise. + prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray. + The L{KX_PolyProxy} 4th element of the return tuple when poly=1 allows to retrieve information on the polygon hit by the ray. + If there is no hit or the hit object is not a static mesh, None is returned as 4th element. + + The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects. + + @param objto: [x,y,z] or object to which the ray is casted + @type objto: L{KX_GameObject} or 3-tuple + @param objfrom: [x,y,z] or object from which the ray is casted; None or omitted => use self object center + @type objfrom: L{KX_GameObject} or 3-tuple or None + @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to + @type dist: float + @param prop: property name that object must have; can be omitted or "" => detect any object + @type prop: string + @param face: normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin + @type face: int + @param xray: X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object + @type xray: int + @param poly: polygon option: 1=>return value is a 4-tuple and the 4th element is a L{KX_PolyProxy} + @type poly: int + @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz)) + or 4-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz), L{KX_PolyProxy}) + @return: (object,hitpoint,hitnormal) or (object,hitpoint,hitnormal,polygon) + If no hit, returns (None,None,None) or (None,None,None,None) + If the object hit is not a static mesh, polygon is None + """ + def setCollisionMargin(margin): + """ + Set the objects collision margin. + + note: If this object has no physics controller (a physics ID of zero), this function will raise RuntimeError. + + @type margin: float + @param margin: the collision margin distance in blender units. + """ + def sendMessage(subject, body="", to=""): + """ + Sends a message. + + @param subject: The subject of the message + @type subject: string + @param body: The body of the message (optional) + @type body: string + @param to: The name of the object to send the message to (optional) + @type to: string + """ + def get(key, default=None): + """ + Return the value matching key, or the default value if its not found. + @return: The key value or a default. + """ + def has_key(key): + """ + Return True if the key is found. + @rtype: boolean + @return: The key value or a default. + """ + + +class KX_IpoActuator(SCA_IActuator): + """ + IPO actuator activates an animation. + + @ivar frameStart: Start frame. + @type frameStart: float + @ivar frameEnd: End frame. + @type frameEnd: float + @ivar propName: Use this property to define the Ipo position + @type propName: string + @ivar framePropName: Assign this property this action current frame number + @type framePropName: string + @ivar mode: Play mode for the ipo. (In GameLogic.KX_IPOACT_PLAY, KX_IPOACT_PINGPONG, KX_IPOACT_FLIPPER, KX_IPOACT_LOOPSTOP, KX_IPOACT_LOOPEND, KX_IPOACT_FROM_PROP) + @type mode: int + @ivar useIpoAsForce: Apply Ipo as a global or local force depending on the local option (dynamic objects only) + @type useIpoAsForce: bool + @ivar useIpoAdd: Ipo is added to the current loc/rot/scale in global or local coordinate according to Local flag + @type useIpoAdd: bool + @ivar useIpoLocal: Let the ipo acts in local coordinates, used in Force and Add mode. + @type useIpoLocal: bool + @ivar useChildren: Update IPO on all children Objects as well + @type useChildren: bool + """ +#{ Deprecated + def set(mode, startframe, endframe, force): + """ + Sets the properties of the actuator. + + @deprecated: use other attributes. + @param mode: "Play", "PingPong", "Flipper", "LoopStop", "LoopEnd" or "FromProp" + @type mode: string + @param startframe: first frame to use + @type startframe: integer + @param endframe: last frame to use + @type endframe: integer + @param force: special mode + @type force: integer (0=normal, 1=interpret location as force, 2=additive) + """ + def setProperty(property): + """ + Sets the name of the property to be used in FromProp mode. + + @deprecated: use L{propName} + @type property: string + """ + def setStart(startframe): + """ + Sets the frame from which the IPO starts playing. + + @deprecated: use L{frameStart} + @type startframe: integer + """ + def getStart(): + """ + Returns the frame from which the IPO starts playing. + + @deprecated: use L{frameStart} + @rtype: integer + """ + def setEnd(endframe): + """ + Sets the frame at which the IPO stops playing. + + @deprecated: use L{frameEnd} + @type endframe: integer + """ + def getEnd(): + """ + Returns the frame at which the IPO stops playing. + + @deprecated: use L{frameEnd} + @rtype: integer + """ + def setIpoAsForce(force): + """ + Set whether to interpret the ipo as a force rather than a displacement. + + @deprecated: use L{useIpoAsForce} + @type force: boolean + @param force: KX_TRUE or KX_FALSE + """ + def getIpoAsForce(): + """ + Returns whether to interpret the ipo as a force rather than a displacement. + + @deprecated: use L{useIpoAsForce} + @rtype: boolean + """ + def setIpoAdd(add): + """ + Set whether to interpret the ipo as additive rather than absolute. + + @deprecated: use L{useIpoAdd} + @type add: boolean + @param add: KX_TRUE or KX_FALSE + """ + def getIpoAdd(): + """ + Returns whether to interpret the ipo as additive rather than absolute. + + @deprecated: use L{useIpoAdd} + @rtype: boolean + """ + def setType(mode): + """ + Sets the operation mode of the actuator. + + @deprecated: use L{type} + @param mode: KX_IPOACT_PLAY, KX_IPOACT_PINGPONG, KX_IPOACT_FLIPPER, KX_IPOACT_LOOPSTOP, KX_IPOACT_LOOPEND + @type mode: string + """ + def getType(): + """ + Returns the operation mode of the actuator. + + @deprecated: use L{type} + @rtype: integer + @return: KX_IPOACT_PLAY, KX_IPOACT_PINGPONG, KX_IPOACT_FLIPPER, KX_IPOACT_LOOPSTOP, KX_IPOACT_LOOPEND + """ + def setForceIpoActsLocal(local): + """ + Set whether to apply the force in the object's local + coordinates rather than the world global coordinates. + + @deprecated: use L{useIpoLocal} + @param local: Apply the ipo-as-force in the object's local + coordinates? (KX_TRUE, KX_FALSE) + @type local: boolean + """ + def getForceIpoActsLocal(): + """ + Return whether to apply the force in the object's local + coordinates rather than the world global coordinates. + + @deprecated: use L{useIpoLocal} + """ +#} + +class KX_LightObject(KX_GameObject): + """ + A Light object. + + Example: + + # Turn on a red alert light. + import GameLogic + + co = GameLogic.getCurrentController() + light = co.owner + + light.energy = 1.0 + light.colour = [1.0, 0.0, 0.0] + + @group Constants: NORMAL, SPOT, SUN + @ivar SPOT: A spot light source. See attribute 'type' + @ivar SUN: A point light source with no attenuation. See attribute 'type' + @ivar NORMAL: A point light source. See attribute 'type' + + @ivar type: The type of light - must be SPOT, SUN or NORMAL + @ivar layer: The layer mask that this light affects object on. + @type layer: bitfield + @ivar energy: The brightness of this light. + @type energy: float + @ivar distance: The maximum distance this light can illuminate. (SPOT and NORMAL lights only) + @type distance: float + @ivar colour: The colour of this light. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0] + @type colour: list [r, g, b] + @ivar color: Synonym for colour. + @ivar lin_attenuation: The linear component of this light's attenuation. (SPOT and NORMAL lights only) + @type lin_attenuation: float + @ivar quad_attenuation: The quadratic component of this light's attenuation (SPOT and NORMAL lights only) + @type quad_attenuation: float + @ivar spotsize: The cone angle of the spot light, in degrees. (float) (SPOT lights only) + 0.0 <= spotsize <= 180.0. Spotsize = 360.0 is also accepted. + @ivar spotblend: Specifies the intensity distribution of the spot light. (float) (SPOT lights only) + Higher values result in a more focused light source. + 0.0 <= spotblend <= 1.0. + + """ + +class KX_MeshProxy(SCA_IObject): + """ + A mesh object. + + You can only change the vertex properties of a mesh object, not the mesh topology. + + To use mesh objects effectively, you should know a bit about how the game engine handles them. + 1. Mesh Objects are converted from Blender at scene load. + 2. The Converter groups polygons by Material. This means they can be sent to the + renderer efficiently. A material holds: + 1. The texture. + 2. The Blender material. + 3. The Tile properties + 4. The face properties - (From the "Texture Face" panel) + 5. Transparency & z sorting + 6. Light layer + 7. Polygon shape (triangle/quad) + 8. Game Object + 3. Verticies will be split by face if necessary. Verticies can only be shared between + faces if: + 1. They are at the same position + 2. UV coordinates are the same + 3. Their normals are the same (both polygons are "Set Smooth") + 4. They are the same colour + For example: a cube has 24 verticies: 6 faces with 4 verticies per face. + + The correct method of iterating over every L{KX_VertexProxy} in a game object:: + import GameLogic + + co = GameLogic.getCurrentController() + obj = co.owner + + m_i = 0 + mesh = obj.getMesh(m_i) # There can be more than one mesh... + while mesh != None: + for mat in range(mesh.getNumMaterials()): + for v_index in range(mesh.getVertexArrayLength(mat)): + vertex = mesh.getVertex(mat, v_index) + # Do something with vertex here... + # ... eg: colour the vertex red. + vertex.colour = [1.0, 0.0, 0.0, 1.0] + m_i += 1 + mesh = obj.getMesh(m_i) + + @ivar materials: + @type materials: list of L{KX_BlenderMaterial} or L{KX_PolygonMaterial} types + + @ivar numPolygons: + @type numPolygons: integer + + @ivar numMaterials: + @type numMaterials: integer + """ + + def getNumMaterials(): + """ + Gets the number of materials associated with this object. + + @rtype: integer + """ + + def getMaterialName(matid): + """ + Gets the name of the specified material. + + @type matid: integer + @param matid: the specified material. + @rtype: string + @return: the attached material name. + """ + def getTextureName(matid): + """ + Gets the name of the specified material's texture. + + @type matid: integer + @param matid: the specified material + @rtype: string + @return: the attached material's texture name. + """ + def getVertexArrayLength(matid): + """ + Gets the length of the vertex array associated with the specified material. + + There is one vertex array for each material. + + @type matid: integer + @param matid: the specified material + @rtype: integer + @return: the number of verticies in the vertex array. + """ + def getVertex(matid, index): + """ + Gets the specified vertex from the mesh object. + + @type matid: integer + @param matid: the specified material + @type index: integer + @param index: the index into the vertex array. + @rtype: L{KX_VertexProxy} + @return: a vertex object. + """ + def getNumPolygons(): + """ + Returns the number of polygon in the mesh. + + @rtype: integer + """ + def getPolygon(index): + """ + Gets the specified polygon from the mesh. + + @type index: integer + @param index: polygon number + @rtype: L{KX_PolyProxy} + @return: a polygon object. + """ + def reinstancePhysicsMesh(): + """ + Updates the physics system with the changed mesh. + + A mesh must have only one material with collision flags, + and have all collision primitives in one vertex array (ie. < 65535 verts) and + be either a polytope or polyheder mesh. If you don't get a warning in the + console when the collision type is polytope, the mesh is suitable for reinstance. + @bug: This currently does not work. + @rtype: boolean + @return: True if reinstance succeeded, False if it failed. + """ + +class SCA_MouseSensor(SCA_ISensor): + """ + Mouse Sensor logic brick. + + Properties: + + @ivar position: current [x,y] coordinates of the mouse, in frame coordinates (pixels) + @type position: [integer,interger] + @ivar mode: sensor mode: 1=KX_MOUSESENSORMODE_LEFTBUTTON 2=KX_MOUSESENSORMODE_MIDDLEBUTTON + 3=KX_MOUSESENSORMODE_RIGHTBUTTON 4=KX_MOUSESENSORMODE_WHEELUP + 5=KX_MOUSESENSORMODE_WHEELDOWN 9=KX_MOUSESENSORMODE_MOVEMENT + @type mode: integer + """ + + def getXPosition(): + """ + Gets the x coordinate of the mouse. + + @deprecated: use the L{position} property + @rtype: integer + @return: the current x coordinate of the mouse, in frame coordinates (pixels) + """ + def getYPosition(): + """ + Gets the y coordinate of the mouse. + + @deprecated: use the L{position} property + @rtype: integer + @return: the current y coordinate of the mouse, in frame coordinates (pixels). + """ + def getButtonStatus(button): + """ + Get the mouse button status. + + @type button: int + @param button: value in GameLogic members KX_MOUSE_BUT_LEFT, KX_MOUSE_BUT_MIDDLE, KX_MOUSE_BUT_RIGHT + + @rtype: integer + @return: value in GameLogic members KX_INPUT_NONE, KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED + """ + +class KX_MouseFocusSensor(SCA_MouseSensor): + """ + The mouse focus sensor detects when the mouse is over the current game object. + + The mouse focus sensor works by transforming the mouse coordinates from 2d device + space to 3d space then raycasting away from the camera. + + @ivar raySource: The worldspace source of the ray (the view position) + @type raySource: list (vector of 3 floats) + @ivar rayTarget: The worldspace target of the ray. + @type rayTarget: list (vector of 3 floats) + @ivar rayDirection: The L{rayTarget} - L{raySource} normalized. + @type rayDirection: list (normalized vector of 3 floats) + @ivar hitObject: the last object the mouse was over. + @type hitObject: L{KX_GameObject} or None + @ivar hitPosition: The worldspace position of the ray intersecton. + @type hitPosition: list (vector of 3 floats) + @ivar hitNormal: the worldspace normal from the face at point of intersection. + @type hitNormal: list (normalized vector of 3 floats) + """ +#{ Deprecated + def getHitNormal(): + """ + Returns the normal (in worldcoordinates) at the point of collision where the object was hit by this ray. + + @deprecated: use the L{hitNormal} property + @rtype: list [x, y, z] + @return: the ray collision normal. + """ + def getHitObject(): + """ + Returns the object that was hit by this ray or None. + + @deprecated: use the L{hitObject} property + @rtype: L{KX_GameObject} or None + @return: the collision object. + """ + def getHitPosition(): + """ + Returns the position (in worldcoordinates) at the point of collision where the object was hit by this ray. + + @deprecated: use the L{hitPosition} property + @rtype: list [x, y, z] + @return: the ray collision position. + """ + def getRayDirection(): + """ + Returns the normalized direction (in worldcoordinates) of the ray cast by the mouse. + + @deprecated: use the L{rayDirection} property + @rtype: list [x, y, z] + @return: the ray direction. + """ + def getRaySource(): + """ + Returns the position (in worldcoordinates) the ray was cast from by the mouse. + + @deprecated: use the L{raySource} property + @rtype: list [x, y, z] + @return: the ray source. + """ + def getRayTarget(): + """ + Returns the target of the ray (in worldcoordinates) that seeks the focus object. + + @deprecated: use the L{rayTarget} property + @rtype: list [x, y, z] + @return: the ray target. + """ +#} + +class KX_TouchSensor(SCA_ISensor): + """ + Touch sensor detects collisions between objects. + + @ivar propName: The property or material to collide with. + @type propName: string + @ivar useMaterial: Determines if the sensor is looking for a property or material. + KX_True = Find material; KX_False = Find property + @type useMaterial: boolean + @ivar usePulseCollision: The last collided object. + @type usePulseCollision: bool + @ivar hitObject: The last collided object. (read-only) + @type hitObject: L{KX_GameObject} or None + @ivar hitObjectList: A list of colliding objects. (read-only) + @type hitObjectList: L{CListValue} of L{KX_GameObject} + """ +#{ Deprecated + def setProperty(name): + """ + Set the property or material to collide with. Use + setTouchMaterial() to switch between properties and + materials. + + @deprecated: use the L{property} property + @type name: string + """ + + def getProperty(): + """ + Returns the property or material to collide with. Use + getTouchMaterial() to find out whether this sensor + looks for properties or materials. + + @deprecated: use the L{property} property + @rtype: string + """ + def getHitObject(): + """ + Returns the last object hit by this touch sensor. + + @deprecated: use the L{hitObject} property + @rtype: L{KX_GameObject} + """ + def getHitObjectList(): + """ + Returns a list of all objects hit in the last frame. (B{deprecated}) + + Only objects that have the requisite material/property are listed. + + @deprecated: use the L{hitObjectList} property + @rtype: L{CListValue} of L{hitObjectList} + """ + def getTouchMaterial(): + """ + Returns KX_TRUE if this sensor looks for a specific material, + KX_FALSE if it looks for a specific property. (B{deprecated}) + + @deprecated: use the L{useMaterial} property + """ +#} + +class KX_NearSensor(KX_TouchSensor): + """ + A near sensor is a specialised form of touch sensor. + + @ivar distance: The near sensor activates when an object is within this distance. + @type distance: float + @ivar resetDistance: The near sensor deactivates when the object exceeds this distance. + @type resetDistance: float + """ + +class KX_NetworkMessageActuator(SCA_IActuator): + """ + Message Actuator + + @ivar propName: Messages will only be sent to objects with the given property name. + @type propName: string + @ivar subject: The subject field of the message. + @type subject: string + @ivar body: The body of the message. + @type body: string + @ivar usePropBody: Send a property instead of a regular body message. + @type usePropBody: boolean + """ +#{Deprecated + def setToPropName(name): + """ + Messages will only be sent to objects with the given property name. + + @deprecated: Use the L{propName} attribute instead. + @type name: string + """ + def setSubject(subject): + """ + Sets the subject field of the message. + + @deprecated: Use the L{subject} attribute instead. + @type subject: string + """ + def setBodyType(bodytype): + """ + Sets the type of body to send. + + @deprecated: Use the L{usePropBody} attribute instead. + @type bodytype: boolean + @param bodytype: True to send the value of a property, False to send the body text. + """ + def setBody(body): + """ + Sets the message body. + + @deprecated: Use the L{body} attribute instead. + @type body: string + @param body: if the body type is True, this is the name of the property to send. + if the body type is False, this is the text to send. + """ +#} + +class KX_NetworkMessageSensor(SCA_ISensor): + """ + The Message Sensor logic brick. + + Currently only loopback (local) networks are supported. + + @ivar subject: The subject the sensor is looking for. + @type subject: string + @ivar frameMessageCount: The number of messages received since the last frame. + (Read-only) + @type frameMessageCount: int + @ivar subjects: The list of message subjects received. (Read-only) + @type subjects: list of strings + @ivar bodies: The list of message bodies received. (Read-only) + @type bodies: list of strings + """ +#{ Deprecated + def setSubjectFilterText(subject): + """ + Change the message subject text that this sensor is listening to. + + @deprecated: Use the L{subject} attribute instead. + @type subject: string + @param subject: the new message subject to listen for. + """ + + def getFrameMessageCount(): + """ + Get the number of messages received since the last frame. + + @deprecated: Use the L{frameMessageCount} attribute instead. + @rtype: integer + """ + def getBodies(): + """ + Gets the list of message bodies. + + @deprecated: Use the L{bodies} attribute instead. + @rtype: list + """ + def getSubject(): + """ + Gets the message subject this sensor is listening for from the Subject: field. + + @deprecated: Use the L{subject} attribute instead. + @rtype: string + """ + def getSubjects(): + """ + Gets the list of message subjects received. + + @deprecated: Use the L{subjects} attribute instead. + @rtype: list + """ +#} + +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. + + @ivar force: The force applied by the actuator + @type force: list [x, y, z] + @ivar useLocalForce: A flag specifying if the force is local + @type useLocalForce: bool + @ivar torque: The torque applied by the actuator + @type torque: list [x, y, z] + @ivar useLocalTorque: A flag specifying if the torque is local + @type useLocalTorque: bool + @ivar dLoc: The displacement vector applied by the actuator + @type dLoc: list [x, y, z] + @ivar useLocalDLoc: A flag specifying if the dLoc is local + @type useLocalDLoc: bool + @ivar dRot: The angular displacement vector applied by the actuator + - note: Since the displacement is applied every frame, you must adjust the displacement + based on the frame rate, or you game experience will depend on the player's computer + speed. + @type dRot: list [x, y, z] + @ivar useLocalDRot: A flag specifying if the dRot is local + @type useLocalDRot: bool + @ivar linV: The linear velocity applied by the actuator + @type linV: list [x, y, z] + @ivar useLocalLinV: A flag specifying if the linear velocity is local + - note: This is the target speed for servo controllers + @type useLocalLinV: bool + @ivar angV: The angular velocity applied by the actuator + @type angV: list [x, y, z] + @ivar useLocalAngV: A flag specifying if the angular velocity is local + @type useLocalAngV: bool + + @ivar damping: The damping parameter of the servo controller + @type damping: short + + @ivar forceLimitX: The min/max force limit along the X axis and activates or deactivates the limits in the servo controller + @type forceLimitX: list [min(float), max(float), bool] + @ivar forceLimitY: The min/max force limit along the Y axis and activates or deactivates the limits in the servo controller + @type forceLimitY: list [min(float), max(float), bool] + @ivar forceLimitZ: The min/max force limit along the Z axis and activates or deactivates the limits in the servo controller + @type forceLimitZ: list [min(float), max(float), bool] + + @ivar pid: The PID coefficients of the servo controller + @type pid: list of floats [proportional, integral, derivate] + @ivar reference: The object that is used as reference to compute the velocity for the servo controller. + @type reference: KX_GameObject or None + + @group Deprecated: getForce, setForce, getTorque, setTorque, getDLoc, setDLoc, getDRot, setDRot, getLinearVelocity, setLinearVelocity, getAngularVelocity, + setAngularVelocity, getDamping, setDamping, getForceLimitX, setForceLimitX, getForceLimitY, setForceLimitY, getForceLimitZ, setForceLimitZ, + getPID, setPID + """ + def getForce(): + """ + Returns the force applied by the actuator. + + @deprecated: Use L{force} and L{useLocalForce} instead. + @rtype: list [fx, fy, fz, local] + @return: A four item list, containing the vector force, and a flag specifying whether the force is local. + """ + def setForce(fx, fy, fz, local): + """ + Sets the force applied by the actuator. + + @deprecated: Use L{force} and L{useLocalForce} instead. + @type fx: float + @param fx: the x component of the force. + @type fy: float + @param fy: the z component of the force. + @type fz: float + @param fz: the z component of the force. + @type local: boolean + @param local: - False: the force is applied in world coordinates. + - True: the force is applied in local coordinates. + """ + def getTorque(): + """ + Returns the torque applied by the actuator. + + @deprecated: Use L{torque} and L{useLocalTorque} instead. + @rtype: list [S{Tau}x, S{Tau}y, S{Tau}z, local] + @return: A four item list, containing the vector torque, and a flag specifying whether + the torque is applied in local coordinates (True) or world coordinates (False) + """ + def setTorque(tx, ty, tz, local): + """ + Sets the torque applied by the actuator. + + @deprecated: Use L{torque} and L{useLocalTorque} instead. + @type tx: float + @param tx: the x component of the torque. + @type ty: float + @param ty: the z component of the torque. + @type tz: float + @param tz: the z component of the torque. + @type local: boolean + @param local: - False: the torque is applied in world coordinates. + - True: the torque is applied in local coordinates. + """ + def getDLoc(): + """ + Returns the displacement vector applied by the actuator. + + @deprecated: Use L{dLoc} and L{useLocalDLoc} instead. + @rtype: list [dx, dy, dz, local] + @return: A four item list, containing the vector displacement, and whether + the displacement is applied in local coordinates (True) or world + coordinates (False) + """ + def setDLoc(dx, dy, dz, local): + """ + Sets the displacement vector applied by the actuator. + + Since the displacement is applied every frame, you must adjust the displacement + based on the frame rate, or you game experience will depend on the player's computer + speed. + + @deprecated: Use L{dLoc} and L{useLocalDLoc} instead. + @type dx: float + @param dx: the x component of the displacement vector. + @type dy: float + @param dy: the z component of the displacement vector. + @type dz: float + @param dz: the z component of the displacement vector. + @type local: boolean + @param local: - False: the displacement vector is applied in world coordinates. + - True: the displacement vector is applied in local coordinates. + """ + def getDRot(): + """ + Returns the angular displacement vector applied by the actuator. + + @deprecated: Use L{dRot} and L{useLocalDRot} instead. + @rtype: list [dx, dy, dz, local] + @return: A four item list, containing the angular displacement vector, and whether + the displacement is applied in local coordinates (True) or world coordinates (False) + """ + def setDRot(dx, dy, dz, local): + """ + Sets the angular displacement vector applied by the actuator. + + Since the displacement is applied every frame, you must adjust the displacement + based on the frame rate, or you game experience will depend on the player's computer + speed. + + @deprecated: Use L{dRot} and L{useLocalDRot} instead. + @type dx: float + @param dx: the x component of the angular displacement vector. + @type dy: float + @param dy: the z component of the angular displacement vector. + @type dz: float + @param dz: the z component of the angular displacement vector. + @type local: boolean + @param local: - False: the angular displacement vector is applied in world coordinates. + - True: the angular displacement vector is applied in local coordinates. + """ + def getLinearVelocity(): + """ + Returns the linear velocity applied by the actuator. + For the servo control actuator, this is the target speed. + + @deprecated: Use L{linV} and L{useLocalLinV} instead. + @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) + """ + def setLinearVelocity(vx, vy, vz, local): + """ + Sets the linear velocity applied by the actuator. + For the servo control actuator, sets the target speed. + + @deprecated: Use L{linV} and L{useLocalLinV} instead. + @type vx: float + @param vx: the x component of the velocity vector. + @type vy: float + @param vy: the z component of the velocity vector. + @type vz: float + @param vz: the z component of the velocity vector. + @type local: boolean + @param local: - False: the velocity vector is in world coordinates. + - True: the velocity vector is in local coordinates. + """ + def getAngularVelocity(): + """ + Returns the angular velocity applied by the actuator. + + @deprecated: Use L{angV} and L{useLocalAngV} instead. + @rtype: list [S{omega}x, S{omega}y, S{omega}z, local] + @return: A four item list, containing the vector velocity, and whether + the velocity is applied in local coordinates (True) or world + coordinates (False) + """ + def setAngularVelocity(wx, wy, wz, local): + """ + Sets the angular velocity applied by the actuator. + + @deprecated: Use L{angV} and L{useLocalAngV} instead. + @type wx: float + @param wx: the x component of the velocity vector. + @type wy: float + @param wy: the z component of the velocity vector. + @type wz: float + @param wz: 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. + """ + def getDamping(): + """ + Returns the damping parameter of the servo controller. + + @deprecated: Use L{damping} instead. + @rtype: integer + @return: the time constant of the servo controller in frame unit. + """ + def setDamping(damp): + """ + Sets the damping parameter of the servo controller. + + @deprecated: Use L{damping} instead. + @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. + + @deprecated: Use L{forceLimitX} instead. + @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. + + @deprecated: Use L{forceLimitX} instead. + @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. + + @deprecated: Use L{forceLimitY} instead. + @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. + + @deprecated: Use L{forceLimitY} instead. + @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. + + @deprecated: Use L{forceLimitZ} instead. + @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. + + @deprecated: Use L{forceLimitZ} instead. + @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. + + @deprecated: Use L{pid} instead. + @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. + + @deprecated: Use L{pid} instead. + @type P: flat + @param P: proportional coefficient + @type I: float + @param I: Integral coefficient + @type D: float + @param D: Derivate coefficient + """ + +class KX_ParentActuator(SCA_IActuator): + """ + The parent actuator can set or remove an objects parent object. + @ivar object: the object this actuator sets the parent too. + @type object: KX_GameObject or None + @ivar mode: The mode of this actuator + @type mode: int from 0 to 1 L{GameLogic.Parent Actuator} + @ivar compound: Whether the object shape should be added to the parent compound shape when parenting + Effective only if the parent is already a compound shape + @type compound: bool + @ivar ghost: whether the object should be made ghost when parenting + Effective only if the shape is not added to the parent compound shape + @type ghost: bool + + """ + def setObject(object): + """ + Sets the object to set as parent. + + Object can be either a L{KX_GameObject} or the name of the object. + + @deprecated: Use the L{object} property. + @type object: L{KX_GameObject}, string or None + """ + def getObject(name_only = 1): + """ + Returns the name of the object to change to. + + @deprecated: Use the L{object} property. + @type name_only: bool + @param name_only: optional argument, when 0 return a KX_GameObject + @rtype: string, KX_GameObject or None if no object is set + """ + +class KX_PhysicsObjectWrapper(PyObjectPlus): + """ + KX_PhysicsObjectWrapper + + """ + def setActive(active): + """ + Set the object to be active. + + @param active: set to True to be active + @type active: bool + """ + + def setAngularVelocity(x, y, z, local): + """ + Set the angular velocity of the object. + + @param x: angular velocity for the x-axis + @type x: float + + @param y: angular velocity for the y-axis + @type y: float + + @param z: angular velocity for the z-axis + @type z: float + + @param local: set to True for local axis + @type local: bool + """ + def setLinearVelocity(x, y, z, local): + """ + Set the linear velocity of the object. + + @param x: linear velocity for the x-axis + @type x: float + + @param y: linear velocity for the y-axis + @type y: float + + @param z: linear velocity for the z-axis + @type z: float + + @param local: set to True for local axis + @type local: bool + """ + def setPosition(x, y, z): + """ + Set the position of the object + + @param x: x coordinate + @type x: float + + @param y: y coordinate + @type y: float + + @param z: z coordinate + @type z: float + """ + +class KX_PolyProxy(SCA_IObject): + """ + A polygon holds the index of the vertex forming the poylgon. + + Note: + The polygon attributes are read-only, you need to retrieve the vertex proxy if you want + to change the vertex settings. + + @ivar matname: The name of polygon material, empty if no material. + @type matname: string + @ivar material: The material of the polygon + @type material: L{KX_PolygonMaterial} or L{KX_BlenderMaterial} + @ivar texture: The texture name of the polygon. + @type texture: string + @ivar matid: The material index of the polygon, use this to retrieve vertex proxy from mesh proxy + @type matid: integer + @ivar v1: vertex index of the first vertex of the polygon, use this to retrieve vertex proxy from mesh proxy + @type v1: integer + @ivar v2: vertex index of the second vertex of the polygon, use this to retrieve vertex proxy from mesh proxy + @type v2: integer + @ivar v3: vertex index of the third vertex of the polygon, use this to retrieve vertex proxy from mesh proxy + @type v3: integer + @ivar v4: vertex index of the fourth vertex of the polygon, 0 if polygon has only 3 vertex + use this to retrieve vertex proxy from mesh proxy + @type v4: integer + @ivar visible: visible state of the polygon: 1=visible, 0=invisible + @type visible: integer + @ivar collide: collide state of the polygon: 1=receives collision, 0=collision free. + @type collide: integer + """ + + def getMaterialName(): + """ + Returns the polygon material name with MA prefix + + @rtype: string + @return: material name + """ + def getMaterial(): + """ + Returns the polygon material + + @rtype: L{KX_PolygonMaterial} or L{KX_BlenderMaterial} + """ + def getTextureName(): + """ + Returns the polygon texture name + + @rtype: string + @return: texture name + """ + def getMaterialIndex(): + """ + Returns the material bucket index of the polygon. + This index and the ones returned by getVertexIndex() are needed to retrieve the vertex proxy from L{KX_MeshProxy}. + + @rtype: integer + @return: the material index in the mesh + """ + def getNumVertex(): + """ + Returns the number of vertex of the polygon. + + @rtype: integer + @return: number of vertex, 3 or 4. + """ + def isVisible(): + """ + Returns whether the polygon is visible or not + + @rtype: integer + @return: 0=invisible, 1=visible + """ + def isCollider(): + """ + Returns whether the polygon is receives collision or not + + @rtype: integer + @return: 0=collision free, 1=receives collision + """ + def getVertexIndex(vertex): + """ + Returns the mesh vertex index of a polygon vertex + This index and the one returned by getMaterialIndex() are needed to retrieve the vertex proxy from L{KX_MeshProxy}. + + @type vertex: integer + @param vertex: index of the vertex in the polygon: 0->3 + @rtype: integer + @return: mesh vertex index + """ + def getMesh(): + """ + Returns a mesh proxy + + @rtype: L{KX_MeshProxy} + @return: mesh proxy + """ + +class KX_PolygonMaterial: + """ + This is the interface to materials in the game engine. + + Materials define the render state to be applied to mesh objects. + + Warning: Some of the methods/variables are CObjects. If you mix these up, + you will crash blender. + + This example requires: + - PyOpenGL http://pyopengl.sourceforge.net/ + - GLEWPy http://glewpy.sourceforge.net/ + Example:: + + import GameLogic + import OpenGL + from OpenGL.GL import * + from OpenGL.GLU import * + import glew + from glew import * + + glewInit() + + vertex_shader = \"\"\" + + void main(void) + { + gl_Position = ftransform(); + } + \"\"\" + + fragment_shader =\"\"\" + + void main(void) + { + gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + } + \"\"\" + + class MyMaterial: + def __init__(self): + self.pass_no = 0 + # Create a shader + self.m_program = glCreateProgramObjectARB() + # Compile the vertex shader + self.shader(GL_VERTEX_SHADER_ARB, (vertex_shader)) + # Compile the fragment shader + self.shader(GL_FRAGMENT_SHADER_ARB, (fragment_shader)) + # Link the shaders together + self.link() + + def PrintInfoLog(self, tag, object): + \"\"\" + PrintInfoLog prints the GLSL compiler log + \"\"\" + print "Tag: def PrintGLError(self, tag = ""): + + def PrintGLError(self, tag = ""): + \"\"\" + Prints the current GL error status + \"\"\" + if len(tag): + print tag + err = glGetError() + if err != GL_NO_ERROR: + print "GL Error: %s\\n"%(gluErrorString(err)) + + def shader(self, type, shaders): + \"\"\" + shader compiles a GLSL shader and attaches it to the current + program. + + type should be either GL_VERTEX_SHADER_ARB or GL_FRAGMENT_SHADER_ARB + shaders should be a sequence of shader source to compile. + \"\"\" + # Create a shader object + shader_object = glCreateShaderObjectARB(type) + + # Add the source code + glShaderSourceARB(shader_object, len(shaders), shaders) + + # Compile the shader + glCompileShaderARB(shader_object) + + # Print the compiler log + self.PrintInfoLog("vertex shader", shader_object) + + # Check if compiled, and attach if it did + compiled = glGetObjectParameterivARB(shader_object, GL_OBJECT_COMPILE_STATUS_ARB) + if compiled: + glAttachObjectARB(self.m_program, shader_object) + + # Delete the object (glAttachObjectARB makes a copy) + glDeleteObjectARB(shader_object) + + # print the gl error log + self.PrintGLError() + + def link(self): + \"\"\" + Links the shaders together. + \"\"\" + # clear error indicator + glGetError() + + glLinkProgramARB(self.m_program) + + self.PrintInfoLog("link", self.m_program) + + linked = glGetObjectParameterivARB(self.m_program, GL_OBJECT_LINK_STATUS_ARB) + if not linked: + print "Shader failed to link" + return + + glValidateProgramARB(self.m_program) + valid = glGetObjectParameterivARB(self.m_program, GL_OBJECT_VALIDATE_STATUS_ARB) + if not valid: + print "Shader failed to validate" + return + + def activate(self, rasty, cachingInfo, mat): + self.pass_no+=1 + if (self.pass_no == 1): + glDisable(GL_COLOR_MATERIAL) + glUseProgramObjectARB(self.m_program) + return True + + glEnable(GL_COLOR_MATERIAL) + glUseProgramObjectARB(0) + self.pass_no = 0 + return False + + obj = GameLogic.getCurrentController().owner + + mesh = obj.meshes[0] + + for mat in mesh.materials: + mat.setCustomMaterial(MyMaterial()) + print mat.texture + + @ivar texture: Texture name + @type texture: string (read-only) + + @ivar gl_texture: OpenGL texture handle (eg for glBindTexture(GL_TEXTURE_2D, gl_texture) + @type gl_texture: integer (read-only) + + @ivar material: Material name + @type material: string (read-only) + + @ivar tface: Texture face properties + @type tface: CObject (read-only) + + @ivar tile: Texture is tiling + @type tile: boolean + @ivar tilexrep: Number of tile repetitions in x direction. + @type tilexrep: integer + @ivar tileyrep: Number of tile repetitions in y direction. + @type tileyrep: integer + + @ivar drawingmode: Drawing mode for the material. + - 2 (drawingmode & 4) Textured + - 4 (drawingmode & 16) Light + - 14 (drawingmode & 16384) 3d Polygon Text + @type drawingmode: bitfield + + @ivar transparent: This material is transparent. All meshes with this + material will be rendered after non transparent meshes from back + to front. + @type transparent: boolean + + @ivar zsort: Transparent polygons in meshes with this material will be sorted back to + front before rendering. + Non-Transparent polygons will be sorted front to back before rendering. + @type zsort: boolean + + @ivar lightlayer: Light layers this material affects. + @type lightlayer: bitfield. + + @ivar triangle: Mesh data with this material is triangles. It's probably not safe to change this. + @type triangle: boolean + + @ivar diffuse: The diffuse colour of the material. black = [0.0, 0.0, 0.0] white = [1.0, 1.0, 1.0] + @type diffuse: list [r, g, b] + @ivar specular: The specular colour of the material. black = [0.0, 0.0, 0.0] white = [1.0, 1.0, 1.0] + @type specular: list [r, g, b] + @ivar shininess: The shininess (specular exponent) of the material. 0.0 <= shininess <= 128.0 + @type shininess: float + @ivar specularity: The amount of specular of the material. 0.0 <= specularity <= 1.0 + @type specularity: float + """ + def updateTexture(tface, rasty): + """ + Updates a realtime animation. + + @param tface: Texture face (eg mat.tface) + @type tface: CObject + @param rasty: Rasterizer + @type rasty: CObject + """ + def setTexture(tface): + """ + Sets texture render state. + + Example:: + mat.setTexture(mat.tface) + + @param tface: Texture face + @type tface: CObject + """ + def activate(rasty, cachingInfo): + """ + Sets material parameters for this object for rendering. + + Material Parameters set: + 1. Texture + 2. Backface culling + 3. Line drawing + 4. Specular Colour + 5. Shininess + 6. Diffuse Colour + 7. Polygon Offset. + + @param rasty: Rasterizer instance. + @type rasty: CObject + @param cachingInfo: Material cache instance. + @type cachingInfo: CObject + """ + def setCustomMaterial(material): + """ + Sets the material state setup object. + + Using this method, you can extend or completely replace the gameengine material + to do your own advanced multipass effects. + + Use this method to register your material class. Instead of the normal material, + your class's activate method will be called just before rendering the mesh. + This should setup the texture, material, and any other state you would like. + It should return True to render the mesh, or False if you are finished. You should + clean up any state Blender does not set before returning False. + + Activate Method Definition:: + def activate(self, rasty, cachingInfo, material): + + Example:: + class PyMaterial: + def __init__(self): + self.pass_no = -1 + + def activate(self, rasty, cachingInfo, material): + # Activate the material here. + # + # The activate method will be called until it returns False. + # Every time the activate method returns True the mesh will + # be rendered. + # + # rasty is a CObject for passing to material.updateTexture() + # and material.activate() + # cachingInfo is a CObject for passing to material.activate() + # material is the KX_PolygonMaterial instance this material + # was added to + + # default material properties: + self.pass_no += 1 + if self.pass_no == 0: + material.activate(rasty, cachingInfo) + # Return True to do this pass + return True + + # clean up and return False to finish. + self.pass_no = -1 + return False + + # Create a new Python Material and pass it to the renderer. + mat.setCustomMaterial(PyMaterial()) + + @param material: The material object. + @type material: instance + """ + +class KX_RadarSensor(KX_NearSensor): + """ + Radar sensor is a near sensor with a conical sensor object. + + @ivar coneOrigin: The origin of the cone with which to test. The origin + is in the middle of the cone. + (read-only) + @type coneOrigin: list of floats [x, y, z] + @ivar coneTarget: The center of the bottom face of the cone with which to test. + (read-only) + @type coneTarget: list of floats [x, y, z] + @ivar distance: The height of the cone with which to test. + @type distance: float + @ivar angle: The angle of the cone (in degrees) with which to test. + @type angle: float from 0 to 360 + @ivar axis: The axis on which the radar cone is cast + @type axis: int from 0 to 5 + KX_RADAR_AXIS_POS_X, KX_RADAR_AXIS_POS_Y, KX_RADAR_AXIS_POS_Z, + KX_RADAR_AXIS_NEG_X, KX_RADAR_AXIS_NEG_Y, KX_RADAR_AXIS_NEG_Z + """ +#{Deprecated + #--The following methods are deprecated, please use properties instead. + def getConeOrigin(): + """ + Returns the origin of the cone with which to test. The origin + is in the middle of the cone. + + @deprecated: Use the L{coneOrigin} property. + @rtype: list [x, y, z] + """ + + def getConeTarget(): + """ + Returns the center of the bottom face of the cone with which to test. + + @deprecated: Use the L{coneTarget} property. + @rtype: list [x, y, z] + """ +#} + + def getConeHeight(): + """ + Returns the height of the cone with which to test. + + @rtype: float + """ + +class KX_RaySensor(SCA_ISensor): + """ + A ray sensor detects the first object in a given direction. + + @ivar propName: The property the ray is looking for. + @type propName: string + @ivar range: The distance of the ray. + @type range: float + @ivar useMaterial: Whether or not to look for a material (false = property) + @type useMaterial: boolean + @ivar useXRay: Whether or not to use XRay. + @type useXRay: boolean + @ivar hitObject: The game object that was hit by the ray. (Read-only) + @type hitObject: KX_GameObject + @ivar hitPosition: The position (in worldcoordinates) where the object was hit by the ray. (Read-only) + @type hitPosition: list [x, y, z] + @ivar hitNormal: The normal (in worldcoordinates) of the object at the location where the object was hit by the ray. (Read-only) + @type hitNormal: list [x, y, z] + @ivar rayDirection: The direction from the ray (in worldcoordinates). (Read-only) + @type rayDirection: list [x, y, z] + @ivar axis: The axis the ray is pointing on. + @type axis: int from 0 to 5 + KX_RAY_AXIS_POS_X, KX_RAY_AXIS_POS_Y, KX_RAY_AXIS_POS_Z, + KX_RAY_AXIS_NEG_X, KX_RAY_AXIS_NEG_Y, KX_RAY_AXIS_NEG_Z + """ +#{ Deprecated + def getHitObject(): + """ + Returns the game object that was hit by this ray. + + @deprecated: Use the L{hitObject} attribute instead. + @rtype: KX_GameObject + """ + def getHitPosition(): + """ + Returns the position (in worldcoordinates) where the object was hit by this ray. + + @deprecated: Use the L{hitPosition} attribute instead. + @rtype: list [x, y, z] + """ + def getHitNormal(): + """ + Returns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray. + + @deprecated: Use the L{hitNormal} attribute instead. + @rtype: list [nx, ny, nz] + """ + def getRayDirection(): + """ + Returns the direction from the ray (in worldcoordinates) + + @deprecated: Use the L{rayDirection} attribute instead. + @rtype: list [dx, dy, dz] + """ +#} + +class KX_SCA_AddObjectActuator(SCA_IActuator): + """ + Edit Object Actuator (in Add Object Mode) + @ivar object: the object this actuator adds. + @type object: KX_GameObject or None + @ivar objectLastCreated: the last added object from this actuator (read-only). + @type objectLastCreated: KX_GameObject or None + @ivar time: the lifetime of added objects, in frames. Set to 0 to disable automatic deletion. + @type time: integer + @ivar linearVelocity: the initial linear velocity of added objects. + @type linearVelocity: list [vx, vy, vz] + @ivar angularVelocity: the initial angular velocity of added objects. + @type angularVelocity: list [vx, vy, vz] + + @warning: An Add Object actuator will be ignored if at game start, the linked object doesn't exist + (or is empty) or the linked object is in an active layer. + + This will genereate a warning in the console: + + C{ERROR: GameObject I{OBName} has a AddObjectActuator I{ActuatorName} without object (in 'nonactive' layer)} + """ +#{Deprecated + def setObject(object): + """ + Sets the game object to add. + + A copy of the object will be added to the scene when the actuator is activated. + + If the object does not exist, this function is ignored. + + object can either be a L{KX_GameObject} or the name of an object or None. + + @deprecated: use the L{object} property + @type object: L{KX_GameObject}, string or None + """ + def getObject(name_only = 0): + """ + Returns the name of the game object to be added. + + Returns None if no game object has been assigned to be added. + + @deprecated: use the L{object} property + @type name_only: bool + @param name_only: optional argument, when 0 return a KX_GameObject + @rtype: string, KX_GameObject or None if no object is set + """ + def setTime(time): + """ + Sets the lifetime of added objects, in frames. + + If time == 0, the object will last forever. + + @deprecated: use the L{time} property + @type time: integer + @param time: The minimum value for time is 0. + """ + def getTime(): + """ + Returns the lifetime of the added object, in frames. + + @deprecated: use the L{time} property + @rtype: integer + """ + def setLinearVelocity(vx, vy, vz): + """ + Sets the initial linear velocity of added objects. + + @deprecated: use the L{linearVelocity} property + @type vx: float + @param vx: the x component of the initial linear velocity. + @type vy: float + @param vy: the y component of the initial linear velocity. + @type vz: float + @param vz: the z component of the initial linear velocity. + """ + def getLinearVelocity(): + """ + Returns the initial linear velocity of added objects. + + @deprecated: use the L{linearVelocity} property + @rtype: list [vx, vy, vz] + """ + def setAngularVelocity(vx, vy, vz): + """ + Sets the initial angular velocity of added objects. + + @deprecated: use the L{angularVelocity} property + @type vx: float + @param vx: the x component of the initial angular velocity. + @type vy: float + @param vy: the y component of the initial angular velocity. + @type vz: float + @param vz: the z component of the initial angular velocity. + """ + def getAngularVelocity(): + """ + Returns the initial angular velocity of added objects. + + @deprecated: use the L{angularVelocity} property + @rtype: list [vx, vy, vz] + """ + def getLastCreatedObject(): + """ + Returns the last object created by this actuator. + + @deprecated: use the L{objectLastCreated} property + @rtype: L{KX_GameObject} + @return: A L{KX_GameObject} or None if no object has been created. + """ +#} + def instantAddObject(): + """ + Returns the last object created by this actuator. The object can then be accessed from L{objectLastCreated}. + + @rtype: None + """ + +class KX_SCA_DynamicActuator(SCA_IActuator): + """ + Dynamic Actuator. + @ivar mode: the type of operation of the actuator, 0-4 + KX_DYN_RESTORE_DYNAMICS, KX_DYN_DISABLE_DYNAMICS, + KX_DYN_ENABLE_RIGID_BODY, KX_DYN_DISABLE_RIGID_BODY, KX_DYN_SET_MASS + @type mode: integer + @ivar mass: the mass value for the KX_DYN_SET_MASS operation + @type mass: float + """ +#{ Deprecated + def setOperation(operation): + """ + Set the type of operation when the actuator is activated: + - 0 = restore dynamics + - 1 = disable dynamics + - 2 = enable rigid body + - 3 = disable rigid body + - 4 = set mass + + @deprecated: Use the L{mode} attribute instead. + """ + def getOperation(): + """ + return the type of operation + @deprecated: Use the L{mode} attribute instead. + """ +#} + +class KX_SCA_EndObjectActuator(SCA_IActuator): + """ + Edit Object Actuator (in End Object mode) + + This actuator has no python methods. + """ + +class KX_SCA_ReplaceMeshActuator(SCA_IActuator): + """ + Edit Object actuator, in Replace Mesh mode. + + Example:: + # Level-of-detail + # Switch a game object's mesh based on its depth in the camera view. + # +----------+ +-----------+ +-------------------------------------+ + # | Always +-----+ Python +-----+ Edit Object (Replace Mesh) LOD.Mesh | + # +----------+ +-----------+ +-------------------------------------+ + import GameLogic + + # List detail meshes here + # Mesh (name, near, far) + # Meshes overlap so that they don't 'pop' when on the edge of the distance. + meshes = ((".Hi", 0.0, -20.0), + (".Med", -15.0, -50.0), + (".Lo", -40.0, -100.0) + ) + + co = GameLogic.getCurrentController() + obj = co.owner + act = co.actuators["LOD." + obj.name] + cam = GameLogic.getCurrentScene().active_camera + + def Depth(pos, plane): + return pos[0]*plane[0] + pos[1]*plane[1] + pos[2]*plane[2] + plane[3] + + # Depth is negative and decreasing further from the camera + depth = Depth(obj.position, cam.world_to_camera[2]) + + newmesh = None + curmesh = None + # Find the lowest detail mesh for depth + for mesh in meshes: + if depth < mesh[1] and depth > mesh[2]: + newmesh = mesh + if "ME" + obj.name + mesh[0] == act.getMesh(): + curmesh = mesh + + if newmesh != None and "ME" + obj.name + newmesh[0] != act.getMesh(): + # The mesh is a different mesh - switch it. + # Check the current mesh is not a better fit. + if curmesh == None or curmesh[1] < depth or curmesh[2] > depth: + act.mesh = obj.getName() + newmesh[0] + GameLogic.addActiveActuator(act, True) + + @warning: Replace mesh actuators will be ignored if at game start, the + named mesh doesn't exist. + + This will generate a warning in the console: + + C{ERROR: GameObject I{OBName} ReplaceMeshActuator I{ActuatorName} without object} + + @ivar mesh: L{KX_MeshProxy} or the name of the mesh that will replace the current one + Set to None to disable actuator + @type mesh: L{KX_MeshProxy} or None if no mesh is set + """ + def setMesh(name): + """ + Sets the name of the mesh that will replace the current one. + When the name is None it will unset the mesh value so no action is taken. + + @deprecated: Use the L{mesh} attribute instead. + @type name: string or None + """ + def getMesh(): + """ + Returns the name of the mesh that will replace the current one. + + Returns None if no mesh has been scheduled to be added. + + @deprecated: Use the L{mesh} attribute instead. + @rtype: string or None + """ + def instantReplaceMesh(): + """ + Immediately replace mesh without delay. + @rtype: None + """ + +class KX_Scene(PyObjectPlus): + """ + An active scene that gives access to objects, cameras, lights and scene attributes. + + The activity culling stuff is supposed to disable logic bricks when their owner gets too far + from the active camera. It was taken from some code lurking at the back of KX_Scene - who knows + what it does! + + Example:: + import GameLogic + + # get the scene + scene = GameLogic.getCurrentScene() + + # print all the objects in the scene + for obj in scene.objects: + print obj.name + + # get an object named 'Cube' + obj = scene.objects["OBCube"] + + # get the first object in the scene. + obj = scene.objects[0] + + Example:: + # Get the depth of an object in the camera view. + import GameLogic + + obj = GameLogic.getCurrentController().owner + cam = GameLogic.getCurrentScene().active_camera + + # Depth is negative and decreasing further from the camera + depth = obj.position[0]*cam.world_to_camera[2][0] + obj.position[1]*cam.world_to_camera[2][1] + obj.position[2]*cam.world_to_camera[2][2] + cam.world_to_camera[2][3] + + @bug: All attributes are read only at the moment. + + @ivar name: The scene's name, (read-only). + @type name: string + @ivar objects: A list of objects in the scene, (read-only). + @type objects: L{CListValue} of L{KX_GameObject} + @ivar objectsInactive: A list of objects on background layers (used for the addObject actuator), (read-only). + @type objectsInactive: L{CListValue} of L{KX_GameObject} + @ivar lights: A list of lights in the scene, (read-only). + @type lights: L{CListValue} of L{KX_LightObject} + @ivar cameras: A list of cameras in the scene, (read-only). + @type cameras: L{CListValue} of L{KX_Camera} + @ivar active_camera: The current active camera. + note: this can be set directly from python to avoid using the L{KX_SceneActuator}. + @type active_camera: L{KX_Camera} + @ivar suspended: True if the scene is suspended, (read-only). + @type suspended: boolean + @ivar activity_culling: True if the scene is activity culling + @type activity_culling: boolean + @ivar activity_culling_radius: The distance outside which to do activity culling. Measured in manhattan distance. + @type activity_culling_radius: float + @ivar dbvt_culling: True when Dynamic Bounding box Volume Tree is set (read-only). + @type dbvt_culling: bool + @group Deprecated: getLightList, getObjectList, getName + """ + + def getLightList(): + """ + Returns the list of lights in the scene. + + @deprecated: Use the L{lights} attribute instead. + @rtype: list [L{KX_LightObject}] + """ + def getObjectList(): + """ + Returns the list of objects in the scene. + + @deprecated: Use the L{objects} attribute instead. + @rtype: list [L{KX_GameObject}] + """ + def getName(): + """ + Returns the name of the scene. + + @deprecated: Use the L{name} attribute instead. + @rtype: string + """ + + def addObject(object, other, time=0): + """ + Adds an object to the scene like the Add Object Actuator would, and returns the created object. + + @param object: The object to add + @type object: L{KX_GameObject} or string + @param other: The object's center to use when adding the object + @type other: L{KX_GameObject} or string + @param time: The lifetime of the added object, in frames. A time of 0 means the object will last forever. + @type time: int + + @rtype: L{KX_GameObject} + """ + +class KX_SceneActuator(SCA_IActuator): + """ + Scene Actuator logic brick. + + @warning: Scene actuators that use a scene name will be ignored if at game start, the + named scene doesn't exist or is empty + + This will generate a warning in the console: + + C{ERROR: GameObject I{OBName} has a SceneActuator I{ActuatorName} (SetScene) without scene} + + @ivar scene: the name of the scene to change to/overlay/underlay/remove/suspend/resume + @type scene: string. + @ivar camera: the camera to change to. + When setting the attribute, you can use either a L{KX_Camera} or the name of the camera. + @type camera: L{KX_Camera} on read, string or L{KX_Camera} on write + @ivar useRestart: Set flag to True to restart the sene + @type useRestart: bool + @ivar mode: The mode of the actuator + @type mode: int from 0 to 5 L{GameLogic.Scene Actuator} + """ +#{ Deprecated + def setUseRestart(flag): + """ + Set flag to True to restart the scene. + + @deprecated: Use the L{useRestart} attribute instead. + @type flag: boolean + """ + def setScene(scene): + """ + Sets the name of the scene to change to/overlay/underlay/remove/suspend/resume. + + @deprecated: use the L{scene} attribute instead. + @type scene: string + """ + def setCamera(camera): + """ + Sets the camera to change to. + + Camera can be either a L{KX_Camera} or the name of the camera. + + @deprecated: use the L{camera} attribute instead. + @type camera: L{KX_Camera} or string + """ + def getUseRestart(): + """ + Returns True if the scene will be restarted. + + @deprecated: use the L{useRestart} attribute instead. + @rtype: boolean + """ + def getScene(): + """ + Returns the name of the scene to change to/overlay/underlay/remove/suspend/resume. + + Returns an empty string ("") if no scene has been set. + + @deprecated: use the L{scene} attribute instead. + @rtype: string + """ + def getCamera(): + """ + Returns the name of the camera to change to. + + @deprecated: use the L{camera} attribute instead. + @rtype: string + """ +#} + +class KX_SoundActuator(SCA_IActuator): + """ + Sound Actuator. + + The L{startSound()}, L{pauseSound()} and L{stopSound()} do not require + the actuator to be activated - they act instantly provided that the actuator has + been activated once at least. + + @ivar fileName: The filename of the sound this actuator plays. + @type fileName: string + + @ivar volume: The volume (gain) of the sound. + @type volume: float + + @ivar pitch: The pitch of the sound. + @type pitch: float + + @ivar rollOffFactor: The roll off factor. Rolloff defines the rate of attenuation as the sound gets further away. + @type rollOffFactor: float + + @ivar looping: The loop mode of the actuator. + @type looping: integer + + @ivar position: The position of the sound as a list: [x, y, z]. + @type position: float array + + @ivar velocity: The velocity of the emitter as a list: [x, y, z]. The relative velocity to the observer determines the pitch. List of 3 floats: [x, y, z]. + @type velocity: float array + + @ivar orientation: The orientation of the sound. When setting the orientation you can also use quaternion [float,float,float,float] or euler angles [float,float,float] + @type orientation: 3x3 matrix [[float]] + + @ivar mode: The operation mode of the actuator. You can use one of the following constants: + - KX_SOUNDACT_PLAYSTOP (1) + - KX_SOUNDACT_PLAYEND (2) + - KX_SOUNDACT_LOOPSTOP (3) + - KX_SOUNDACT_LOOPEND (4) + - KX_SOUNDACT_LOOPBIDIRECTIONAL (5) + - KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP (6) + @type mode: integer + """ + +#{ Play Methods + def startSound(): + """ + Starts the sound. + """ + def pauseSound(): + """ + Pauses the sound. + """ + def stopSound(): + """ + Stops the sound. + """ +#} + +#{ Deprecated + def setFilename(filename): + """ + Sets the filename of the sound this actuator plays. + + @deprecated: Use the L{fileName} attribute instead. + @type filename: string + """ + def getFilename(): + """ + Returns the filename of the sound this actuator plays. + + @deprecated: Use the L{fileName} attribute instead. + @rtype: string + """ + def setGain(gain): + """ + Sets the gain (volume) of the sound + + @deprecated: Use the L{volume} attribute instead. + @type gain: float + @param gain: 0.0 (quiet) <= gain <= 1.0 (loud) + """ + def getGain(): + """ + Gets the gain (volume) of the sound. + + @deprecated: Use the L{volume} attribute instead. + @rtype: float + """ + def setPitch(pitch): + """ + Sets the pitch of the sound. + + @deprecated: Use the L{pitch} attribute instead. + @type pitch: float + """ + def getPitch(): + """ + Returns the pitch of the sound. + + @deprecated: Use the L{pitch} attribute instead. + @rtype: float + """ + def setRollOffFactor(rolloff): + """ + Sets the rolloff factor for the sounds. + + Rolloff defines the rate of attenuation as the sound gets further away. + Higher rolloff factors shorten the distance at which the sound can be heard. + + @deprecated: Use the L{rollOffFactor} attribute instead. + @type rolloff: float + """ + def getRollOffFactor(): + """ + Returns the rolloff factor for the sound. + + @deprecated: Use the L{rollOffFactor} attribute instead. + @rtype: float + """ + def setLooping(loop): + """ + Sets the loop mode of the actuator. + + @bug: There are no constants defined for this method! + @param loop: - Play Stop 1 + - Play End 2 + - Loop Stop 3 + - Loop End 4 + - Bidirection Stop 5 + - Bidirection End 6 + + @deprecated: Use the L{looping} attribute instead. + @type loop: integer + """ + def getLooping(): + """ + Returns the current loop mode of the actuator. + + @deprecated: Use the L{looping} attribute instead. + @rtype: integer + """ + def setPosition(x, y, z): + """ + Sets the position this sound will come from. + + @deprecated: Use the L{position} attribute instead. + @type x: float + @param x: The x coordinate of the sound. + @type y: float + @param y: The y coordinate of the sound. + @type z: float + @param z: The z coordinate of the sound. + """ + def setVelocity(vx, vy, vz): + """ + Sets the velocity this sound is moving at. + + The sound's pitch is determined from the velocity. + + @deprecated: Use the L{velocity} attribute instead. + @type vx: float + @param vx: The vx coordinate of the sound. + @type vy: float + @param vy: The vy coordinate of the sound. + @type vz: float + @param vz: The vz coordinate of the sound. + """ + def setOrientation(o11, o12, o13, o21, o22, o23, o31, o32, o33): + """ + Sets the orientation of the sound. + + The nine parameters specify a rotation matrix:: + | o11, o12, o13 | + | o21, o22, o23 | + | o31, o32, o33 | + @deprecated: Use the L{orientation} attribute instead. + """ + + def setType(mode): + """ + Sets the operation mode of the actuator. + + @deprecated: Use the L{type} attribute instead. + @param mode: KX_SOUNDACT_PLAYSTOP, KX_SOUNDACT_PLAYEND, KX_SOUNDACT_LOOPSTOP, KX_SOUNDACT_LOOPEND, KX_SOUNDACT_LOOPBIDIRECTIONAL, KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP + @type mode: integer + """ + + def getType(): + """ + Returns the operation mode of the actuator. + + @deprecated: Use the L{type} attribute instead. + @rtype: integer + @return: KX_SOUNDACT_PLAYSTOP, KX_SOUNDACT_PLAYEND, KX_SOUNDACT_LOOPSTOP, KX_SOUNDACT_LOOPEND, KX_SOUNDACT_LOOPBIDIRECTIONAL, KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP + """ +#} + +class KX_StateActuator(SCA_IActuator): + """ + State actuator changes the state mask of parent object. + + Property: + + @ivar operation: type of bit operation to be applied on object state mask. + You can use one of the following constant: + - KX_STATE_OP_CPY (0) : Copy state mask + - KX_STATE_OP_SET (1) : Add bits to state mask + - KX_STATE_OP_CLR (2) : Substract bits to state mask + - KX_STATE_OP_NEG (3) : Invert bits to state mask + @type operation: integer + + @ivar mask: value that defines the bits that will be modified by the operation. + The bits that are 1 in the mask 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 mask to the object state + @type mask: integer + """ + 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. + + @deprecated: Use the L{operation} attribute instead. + @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. + + @deprecated: Use the L{mask} attribute instead. + @param mask: bits that will be modified + @type mask: integer + """ + +class KX_TrackToActuator(SCA_IActuator): + """ + Edit Object actuator in Track To mode. + + @warning: Track To Actuators will be ignored if at game start, the + object to track to is invalid. + + This will generate a warning in the console: + + C{ERROR: GameObject I{OBName} no object in EditObjectActuator I{ActuatorName}} + + @ivar object: the object this actuator tracks. + @type object: KX_GameObject or None + @ivar time: the time in frames with which to delay the tracking motion + @type time: integer + @ivar use3D: the tracking motion to use 3D + @type use3D: boolean + + """ +#{ Deprecated + def setObject(object): + """ + Sets the object to track. + + @deprecated: Use the L{object} attribute instead. + @type object: L{KX_GameObject}, string or None + @param object: Either a reference to a game object or the name of the object to track. + """ + def getObject(name_only): + """ + Returns the name of the object to track. + + @deprecated: Use the L{object} attribute instead. + @type name_only: bool + @param name_only: optional argument, when 0 return a KX_GameObject + @rtype: string, KX_GameObject or None if no object is set + """ + def setTime(time): + """ + Sets the time in frames with which to delay the tracking motion. + + @deprecated: Use the L{time} attribute instead. + @type time: integer + """ + def getTime(): + """ + Returns the time in frames with which the tracking motion is delayed. + + @deprecated: Use the L{time} attribute instead. + @rtype: integer + """ + def setUse3D(use3d): + """ + DEPRECATED: Use the property. + Sets the tracking motion to use 3D. + + @deprecated: Use the L{use3D} attribute instead. + @type use3d: boolean + @param use3d: - True: allow the tracking motion to extend in the z-direction. + - False: lock the tracking motion to the x-y plane. + """ + def getUse3D(): + """ + Returns True if the tracking motion will track in the z direction. + + @deprecated: Use the L{use3D} attribute instead. + @rtype: boolean + """ +#} + +class KX_VehicleWrapper(PyObjectPlus): + """ + KX_VehicleWrapper + + TODO - description + """ + + def addWheel(wheel, attachPos, attachDir, axleDir, suspensionRestLength, wheelRadius, hasSteering): + + """ + Add a wheel to the vehicle + + @param wheel: The object to use as a wheel. + @type wheel: L{KX_GameObject} or a KX_GameObject name + @param attachPos: The position that this wheel will attach to. + @type attachPos: vector of 3 floats + @param attachDir: The direction this wheel points. + @type attachDir: vector of 3 floats + @param axleDir: The direction of this wheels axle. + @type axleDir: vector of 3 floats + @param suspensionRestLength: TODO - Description + @type suspensionRestLength: float + @param wheelRadius: The size of the wheel. + @type wheelRadius: float + """ + + def applyBraking(force, wheelIndex): + """ + Apply a braking force to the specified wheel + + @param force: the brake force + @type force: float + + @param wheelIndex: index of the wheel where the force needs to be applied + @type wheelIndex: integer + """ + def applyEngineForce(force, wheelIndex): + """ + Apply an engine force to the specified wheel + + @param force: the engine force + @type force: float + + @param wheelIndex: index of the wheel where the force needs to be applied + @type wheelIndex: integer + """ + def getConstraintId(): + """ + Get the constraint ID + + @rtype: integer + @return: the constraint id + """ + def getConstraintType(): + """ + Returns the constraint type. + + @rtype: integer + @return: constraint type + """ + def getNumWheels(): + """ + Returns the number of wheels. + + @rtype: integer + @return: the number of wheels for this vehicle + """ + def getWheelOrientationQuaternion(wheelIndex): + """ + Returns the wheel orientation as a quaternion. + + @param wheelIndex: the wheel index + @type wheelIndex: integer + + @rtype: TODO - type should be quat as per method name but from the code it looks like a matrix + @return: TODO Description + """ + def getWheelPosition(wheelIndex): + """ + Returns the position of the specified wheel + + @param wheelIndex: the wheel index + @type wheelIndex: integer + + @rtype: list[x, y, z] + @return: position vector + """ + def getWheelRotation(wheelIndex): + """ + Returns the rotation of the specified wheel + + @param wheelIndex: the wheel index + @type wheelIndex: integer + + @rtype: float + @return: the wheel rotation + """ + def setRollInfluence(rollInfluece, wheelIndex): + """ + Set the specified wheel's roll influence. + The higher the roll influence the more the vehicle will tend to roll over in corners. + + @param rollInfluece: the wheel roll influence + @type rollInfluece: float + + @param wheelIndex: the wheel index + @type wheelIndex: integer + """ + def setSteeringValue(steering, wheelIndex): + """ + Set the specified wheel's steering + + @param steering: the wheel steering + @type steering: float + + @param wheelIndex: the wheel index + @type wheelIndex: integer + """ + def setSuspensionCompression(compression, wheelIndex): + """ + Set the specified wheel's compression + + @param compression: the wheel compression + @type compression: float + + @param wheelIndex: the wheel index + @type wheelIndex: integer + """ + def setSuspensionDamping(damping, wheelIndex): + """ + Set the specified wheel's damping + + @param damping: the wheel damping + @type damping: float + + @param wheelIndex: the wheel index + @type wheelIndex: integer + """ + def setSuspensionStiffness(stiffness, wheelIndex): + """ + Set the specified wheel's stiffness + + @param stiffness: the wheel stiffness + @type stiffness: float + + @param wheelIndex: the wheel index + @type wheelIndex: integer + """ + def setTyreFriction(friction, wheelIndex): + """ + Set the specified wheel's tyre friction + + @param friction: the tyre friction + @type friction: float + + @param wheelIndex: the wheel index + @type wheelIndex: integer + """ + +class KX_VertexProxy(SCA_IObject): + """ + A vertex holds position, UV, colour and normal information. + + Note: + The physics simulation is NOT currently updated - physics will not respond + to changes in the vertex position. + + @ivar XYZ: The position of the vertex. + @type XYZ: list [x, y, z] + @ivar UV: The texture coordinates of the vertex. + @type UV: list [u, v] + @ivar normal: The normal of the vertex + @type normal: list [nx, ny, nz] + @ivar colour: The colour of the vertex. + Black = [0.0, 0.0, 0.0, 1.0], White = [1.0, 1.0, 1.0, 1.0] + @type colour: list [r, g, b, a] + @ivar color: Synonym for colour. + + @group Position: x, y, z + @ivar x: The x coordinate of the vertex. + @type x: float + @ivar y: The y coordinate of the vertex. + @type y: float + @ivar z: The z coordinate of the vertex. + @type z: float + + @group Texture Coordinates: u, v + @ivar u: The u texture coordinate of the vertex. + @type u: float + @ivar v: The v texture coordinate of the vertex. + @type v: float + + @ivar u2: The second u texture coordinate of the vertex. + @type u2: float + @ivar v2: The second v texture coordinate of the vertex. + @type v2: float + + @group Colour: r, g, b, a + @ivar r: The red component of the vertex colour. 0.0 <= r <= 1.0 + @type r: float + @ivar g: The green component of the vertex colour. 0.0 <= g <= 1.0 + @type g: float + @ivar b: The blue component of the vertex colour. 0.0 <= b <= 1.0 + @type b: float + @ivar a: The alpha component of the vertex colour. 0.0 <= a <= 1.0 + @type a: float + """ + + def getXYZ(): + """ + Gets the position of this vertex. + + @rtype: list [x, y, z] + @return: this vertexes position in local coordinates. + """ + def setXYZ(pos): + """ + Sets the position of this vertex. + + @type pos: list [x, y, z] + @param pos: the new position for this vertex in local coordinates. + """ + def getUV(): + """ + Gets the UV (texture) coordinates of this vertex. + + @rtype: list [u, v] + @return: this vertexes UV (texture) coordinates. + """ + def setUV(uv): + """ + Sets the UV (texture) coordinates of this vertex. + + @type uv: list [u, v] + """ + def getUV2(): + """ + Gets the 2nd UV (texture) coordinates of this vertex. + + @rtype: list [u, v] + @return: this vertexes UV (texture) coordinates. + """ + def setUV2(uv, unit): + """ + Sets the 2nd UV (texture) coordinates of this vertex. + + @type uv: list [u, v] + @param unit: optional argument, FLAT==1, SECOND_UV==2, defaults to SECOND_UV + @param unit: int + """ + def getRGBA(): + """ + Gets the colour of this vertex. + + The colour is represented as four bytes packed into an integer value. The colour is + packed as RGBA. + + Since Python offers no way to get each byte without shifting, you must use the struct module to + access colour in an machine independent way. + + Because of this, it is suggested you use the r, g, b and a attributes or the colour attribute instead. + + Example:: + import struct; + col = struct.unpack('4B', struct.pack('I', v.getRGBA())) + # col = (r, g, b, a) + # black = ( 0, 0, 0, 255) + # white = (255, 255, 255, 255) + + @rtype: integer + @return: packed colour. 4 byte integer with one byte per colour channel in RGBA format. + """ + def setRGBA(col): + """ + Sets the colour of this vertex. + + See getRGBA() for the format of col, and its relevant problems. Use the r, g, b and a attributes + or the colour attribute instead. + + setRGBA() also accepts a four component list as argument col. The list represents the colour as [r, g, b, a] + with black = [0.0, 0.0, 0.0, 1.0] and white = [1.0, 1.0, 1.0, 1.0] + + Example:: + v.setRGBA(0xff0000ff) # Red + v.setRGBA(0xff00ff00) # Green on little endian, transparent purple on big endian + v.setRGBA([1.0, 0.0, 0.0, 1.0]) # Red + v.setRGBA([0.0, 1.0, 0.0, 1.0]) # Green on all platforms. + + @type col: integer or list [r, g, b, a] + @param col: the new colour of this vertex in packed RGBA format. + """ + def getNormal(): + """ + Gets the normal vector of this vertex. + + @rtype: list [nx, ny, nz] + @return: normalised normal vector. + """ + def setNormal(normal): + """ + Sets the normal vector of this vertex. + + @type normal: sequence of floats [r, g, b] + @param normal: the new normal of this vertex. + """ + +class KX_VisibilityActuator(SCA_IActuator): + """ + Visibility Actuator. + @ivar visibility: whether the actuator makes its parent object visible or invisible + @type visibility: boolean + @ivar useOcclusion: whether the actuator makes its parent object an occluder or not + @type useOcclusion: boolean + @ivar useRecursion: whether the visibility/occlusion should be propagated to all children of the object + @type useRecursion: boolean + """ +#{ Deprecated + def set(visible): + """ + Sets whether the actuator makes its parent object visible or invisible. + + @deprecated: Use the L{visibility} attribute instead. + @param visible: - True: Makes its parent visible. + - False: Makes its parent invisible. + """ +#} + +class SCA_2DFilterActuator(SCA_IActuator): + """ + Create, enable and disable 2D filters + + Properties: + + The following properties don't have an immediate effect. + You must active the actuator to get the result. + The actuator is not persistent: it automatically stops itself after setting up the filter + but the filter remains active. To stop a filter you must activate the actuator with 'type' + set to RAS_2DFILTER_DISABLED or RAS_2DFILTER_NOFILTER. + + @ivar shaderText: shader source code for custom shader + @type shaderText: string + @ivar disableMotionBlur: action on motion blur: 0=enable, 1=disable + @type disableMotionBlur: integer + @ivar mode: type of 2D filter, use one of the following constants: + RAS_2DFILTER_ENABLED (-2) : enable the filter that was previously disabled + RAS_2DFILTER_DISABLED (-1) : disable the filter that is currently active + RAS_2DFILTER_NOFILTER (0) : disable and destroy the filter that is currently active + RAS_2DFILTER_MOTIONBLUR (1) : create and enable preset filters + RAS_2DFILTER_BLUR (2) + RAS_2DFILTER_SHARPEN (3) + RAS_2DFILTER_DILATION (4) + RAS_2DFILTER_EROSION (5) + RAS_2DFILTER_LAPLACIAN (6) + RAS_2DFILTER_SOBEL (7) + RAS_2DFILTER_PREWITT (8) + RAS_2DFILTER_GRAYSCALE (9) + RAS_2DFILTER_SEPIA (10) + RAS_2DFILTER_INVERT (11) + RAS_2DFILTER_CUSTOMFILTER (12) : customer filter, the code code is set via shaderText property + @type mode: integer + @ivar passNumber: order number of filter in the stack of 2D filters. Filters are executed in increasing order of passNb. + Only be one filter can be defined per passNb. + @type passNumber: integer (0-100) + @ivar value: argument for motion blur filter + @type value: float (0.0-100.0) + """ + +class SCA_ANDController(SCA_IController): + """ + An AND controller activates only when all linked sensors are activated. + + There are no special python methods for this controller. + """ + +class SCA_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. + + Properties: + + @ivar actuator: the name of the actuator that the sensor is monitoring. + @type actuator: string + """ +#{Deprecated + def getActuator(): + """ + Return the Actuator with which the sensor operates. + + @deprecated: Use the L{actuator} attribute instead. + @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. + + @deprecated: Use the L{actuator} attribute instead. + @param name: actuator name + @type name: string + """ +#} + +class SCA_AlwaysSensor(SCA_ISensor): + """ + This sensor is always activated. + """ + +class SCA_DelaySensor(SCA_ISensor): + """ + The Delay sensor generates positive and negative triggers at precise time, + expressed in number of frames. The delay parameter defines the length + of the initial OFF period. A positive trigger is generated at the end of this period. + The duration parameter defines the length of the ON period following the OFF period. + There is a negative trigger at the end of the ON period. If duration is 0, the sensor + stays ON and there is no negative trigger. + The sensor runs the OFF-ON cycle once unless the repeat option is set: the + OFF-ON cycle repeats indefinately (or the OFF cycle if duration is 0). + Use SCA_ISensor::reset() at any time to restart sensor. + + Properties: + + @ivar delay: length of the initial OFF period as number of frame, 0 for immediate trigger. + @type delay: integer. + @ivar duration: length of the ON period in number of frame after the initial OFF period. + If duration is greater than 0, a negative trigger is sent at the end of the ON pulse. + @type duration: integer + @ivar repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once. + @type repeat: integer + """ +#{Deprecated + def setDelay(delay): + """ + Set the initial delay before the positive trigger. + + @deprecated: Use the L{delay} attribute instead. + @param delay: length of the initial OFF period as number of frame, 0 for immediate trigger + @type delay: integer + """ + def setDuration(duration): + """ + Set the duration of the ON pulse after initial delay and the generation of the positive trigger. + If duration is greater than 0, a negative trigger is sent at the end of the ON pulse. + + @deprecated: Use the L{duration} attribute instead. + @param duration: length of the ON period in number of frame after the initial OFF period + @type duration: integer + """ + def setRepeat(repeat): + """ + Set if the sensor repeat mode. + + @deprecated: Use the L{repeat} attribute instead. + @param repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once. + @type repeat: integer + """ + def getDelay(): + """ + Return the delay parameter value. + + @deprecated: Use the L{delay} attribute instead. + @rtype: integer + """ + def getDuration(): + """ + Return the duration parameter value + + @deprecated: Use the L{duration} attribute instead. + @rtype: integer + """ + def getRepeat(): + """ + Return the repeat parameter value + + @deprecated: Use the L{repeat} attribute instead. + @rtype: KX_TRUE or KX_FALSE + """ +#} + +class SCA_JoystickSensor(SCA_ISensor): + """ + This sensor detects player joystick events. + + Properties: + + @ivar axisValues: (read-only) The state of the joysticks axis as a list of values L{numAxis} long. + each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing. + The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls. + left:[-32767, 0, ...], right:[32767, 0, ...], up:[0, -32767, ...], down:[0, 32767, ...] + @type axisValues: list of ints + + @ivar axisSingle: (read-only) like L{axisValues} but returns a single axis value that is set by the sensor. + Only use this for "Single Axis" type sensors otherwise it will raise an error. + @type axisSingle: int + + @ivar hatValues: (read-only) The state of the joysticks hats as a list of values L{numHats} long. + each spesifying the direction of the hat from 1 to 12, 0 when inactive. + Hat directions are as follows... + - 0:None + - 1:Up + - 2:Right + - 4:Down + - 8:Left + - 3:Up - Right + - 6:Down - Right + - 12:Down - Left + - 9:Up - Left + + @type hatValues: list of ints + + @ivar hatSingle: (read-only) like L{hatValues} but returns a single hat direction value that is set by the sensor. + @type hatSingle: int + + @ivar numAxis: (read-only) The number of axes for the joystick at this index. + @type numAxis: integer + @ivar numButtons: (read-only) The number of buttons for the joystick at this index. + @type numButtons: integer + @ivar numHats: (read-only) The number of hats for the joystick at this index. + @type numHats: integer + @ivar connected: (read-only) True if a joystick is connected at this joysticks index. + @type connected: boolean + @ivar index: The joystick index to use (from 0 to 7). The first joystick is always 0. + @type index: integer + @ivar threshold: Axis threshold. Joystick axis motion below this threshold wont trigger an event. Use values between (0 and 32767), lower values are more sensitive. + @type threshold: integer + @ivar button: The button index the sensor reacts to (first button = 0). When the "All Events" toggle is set, this option has no effect. + @type button: integer + @ivar axis: The axis this sensor reacts to, as a list of two values [axisIndex, axisDirection] + axisIndex: the axis index to use when detecting axis movement, 1=primary directional control, 2=secondary directional control. + axisDirection: 0=right, 1=up, 2=left, 3=down + @type axis: [integer, integer] + @ivar hat: The hat the sensor reacts to, as a list of two values: [hatIndex, hatDirection] + hatIndex: the hat index to use when detecting hat movement, 1=primary hat, 2=secondary hat (4 max). + hatDirection: 1-12 + @type hat: [integer, integer] + """ + + def getButtonActiveList(): + """ + Returns a list containing the indicies of the currently pressed buttons. + @rtype: list + """ + def getButtonStatus(buttonIndex): + """ + Returns a bool of the current pressed state of the specified button. + @param buttonIndex: the button index, 0=first button + @type buttonIndex: integer + @rtype: bool + """ +#{Deprecated + def getIndex(): + """ + Returns the joystick index to use (from 1 to 8). + + @deprecated: Use the L{index} attribute instead. + @rtype: integer + """ + def setIndex(index): + """ + Sets the joystick index to use. + + @deprecated: Use the L{index} attribute instead. + @param index: The index of this joystick sensor, Clamped between 1 and 8. + @type index: integer + @note: This is only useful when you have more then 1 joystick connected to your computer - multiplayer games. + """ + def getAxis(): + """ + Returns the current axis this sensor reacts to. See L{getAxisValue()<SCA_JoystickSensor.getAxisValue>} for the current axis state. + + @deprecated: Use the L{axis} attribute instead. + @rtype: list + @return: 2 values returned are [axisIndex, axisDirection] - see L{setAxis()<SCA_JoystickSensor.setAxis>} for their purpose. + @note: When the "All Events" toggle is set, this option has no effect. + """ + def setAxis(axisIndex, axisDirection): + """ + @deprecated: Use the L{axis} attribute instead. + @param axisIndex: Set the axis index to use when detecting axis movement. + @type axisIndex: integer from 1 to 2 + @param axisDirection: Set the axis direction used for detecting motion. 0:right, 1:up, 2:left, 3:down. + @type axisDirection: integer from 0 to 3 + @note: When the "All Events" toggle is set, this option has no effect. + """ + def getAxisValue(): + """ + Returns the state of the joysticks axis. See differs to L{getAxis()<SCA_JoystickSensor.getAxis>} returning the current state of the joystick. + + @deprecated: Use the L{axisValues} attribute instead. + @rtype: list + @return: 4 values, each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing. + + The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls. + + left:[-32767, 0, ...], right:[32767, 0, ...], up:[0, -32767, ...], down:[0, 32767, ...] + @note: Some gamepads only set the axis on and off like a button. + """ + def getThreshold(): + """ + Get the axis threshold. See L{setThreshold()<SCA_JoystickSensor.setThreshold>} for details. + + @deprecated: Use the L{threshold} attribute instead. + @rtype: integer + """ + def setThreshold(threshold): + """ + Set the axis threshold. + + @deprecated: Use the L{threshold} attribute instead. + @param threshold: Joystick axis motion below this threshold wont trigger an event. Use values between (0 and 32767), lower values are more sensitive. + @type threshold: integer + """ + def getButton(): + """ + Returns the button index the sensor reacts to. See L{getButtonValue()<SCA_JoystickSensor.getButtonValue>} for a list of pressed buttons. + + @deprecated: Use the L{button} attribute instead. + @rtype: integer + @note: When the "All Events" toggle is set, this option has no effect. + """ + def setButton(index): + """ + Sets the button index the sensor reacts to when the "All Events" option is not set. + + @deprecated: Use the L{button} attribute instead. + @note: When the "All Events" toggle is set, this option has no effect. + """ + def getButtonValue(): + """ + Returns a list containing the indicies of the currently pressed buttons. + + @deprecated: Use the L{getButtonActiveList} method instead. + @rtype: list + """ + def getHat(): + """ + Returns the current hat direction this sensor is set to. + [hatNumber, hatDirection]. + + @deprecated: Use the L{hat} attribute instead. + @rtype: list + @note: When the "All Events" toggle is set, this option has no effect. + """ + def setHat(index,direction): + """ + Sets the hat index the sensor reacts to when the "All Events" option is not set. + + @deprecated: Use the L{hat} attribute instead. + @type index: integer + """ + def getNumAxes(): + """ + Returns the number of axes for the joystick at this index. + + @deprecated: Use the L{numAxis} attribute instead. + @rtype: integer + """ + def getNumButtons(): + """ + Returns the number of buttons for the joystick at this index. + + @deprecated: Use the L{numButtons} attribute instead. + @rtype: integer + """ + def getNumHats(): + """ + Returns the number of hats for the joystick at this index. + + @deprecated: Use the L{numHats} attribute instead. + @rtype: integer + """ + def isConnected(): + """ + Returns True if a joystick is detected at this joysticks index. + + @deprecated: Use the L{connected} attribute instead. + @rtype: bool + """ +#} + +class SCA_KeyboardSensor(SCA_ISensor): + """ + A keyboard sensor detects player key presses. + + See module L{GameKeys} for keycode values. + + @ivar key: The key code this sensor is looking for. + @type key: keycode from L{GameKeys} module + @ivar hold1: The key code for the first modifier this sensor is looking for. + @type hold1: keycode from L{GameKeys} module + @ivar hold2: The key code for the second modifier this sensor is looking for. + @type hold2: keycode from L{GameKeys} module + @ivar toggleProperty: The name of the property that indicates whether or not to log keystrokes as a string. + @type toggleProperty: string + @ivar targetProperty: The name of the property that receives keystrokes in case in case a string is logged. + @type targetProperty: string + @ivar useAllKeys: Flag to determine whether or not to accept all keys. + @type useAllKeys: boolean + @ivar events: a list of pressed keys that have either been pressed, or just released, or are active this frame. (read-only). + + - 'keycode' matches the values in L{GameKeys}. + - 'status' uses... + - L{GameLogic.KX_INPUT_NONE} + - L{GameLogic.KX_INPUT_JUST_ACTIVATED} + - L{GameLogic.KX_INPUT_ACTIVE} + - L{GameLogic.KX_INPUT_JUST_RELEASED} + + @type events: list [[keycode, status], ...] + """ + + def getKeyStatus(keycode): + """ + Get the status of a key. + + @rtype: key state L{GameLogic} members (KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED) + @return: The state of the given key + @type keycode: integer + @param keycode: The code that represents the key you want to get the state of + """ + +#{Deprecated + def getKey(): + """ + Returns the key code this sensor is looking for. + + @deprecated: Use the L{key} attribute instead. + @rtype: keycode from L{GameKeys} module + """ + + def setKey(keycode): + """ + Set the key this sensor should listen for. + + @deprecated: Use the L{key} attribute instead. + @type keycode: keycode from L{GameKeys} module + """ + + def getHold1(): + """ + Returns the key code for the first modifier this sensor is looking for. + + @deprecated: Use the L{hold1} attribute instead. + @rtype: keycode from L{GameKeys} module + """ + + def setHold1(keycode): + """ + Sets the key code for the first modifier this sensor should look for. + + @deprecated: Use the L{hold1} attribute instead. + @type keycode: keycode from L{GameKeys} module + """ + + def getHold2(): + """ + Returns the key code for the second modifier this sensor is looking for. + + @deprecated: Use the L{hold2} attribute instead. + @rtype: keycode from L{GameKeys} module + """ + + def setHold2(keycode): + """ + Sets the key code for the second modifier this sensor should look for. + + @deprecated: Use the L{hold2} attribute instead. + @type keycode: keycode from L{GameKeys} module + """ + + def getPressedKeys(): + """ + Get a list of keys that have either been pressed, or just released this frame. + + @deprecated: Use the L{events} attribute instead. + @rtype: list of key status. [[keycode, status]] + """ + + def getCurrentlyPressedKeys(): + """ + Get a list of currently pressed keys that have either been pressed, or just released + + @deprecated: Use the L{events} attribute instead. + @rtype: list of key status. [[keycode, status]] + """ +#} + +class SCA_NANDController(SCA_IController): + """ + An NAND controller activates when all linked sensors are not active. + + There are no special python methods for this controller. + """ + +class SCA_NORController(SCA_IController): + """ + An NOR controller activates only when all linked sensors are de-activated. + + There are no special python methods for this controller. + """ + +class SCA_ORController(SCA_IController): + """ + An OR controller activates when any connected sensor activates. + + There are no special python methods for this controller. + """ + +class SCA_PropertyActuator(SCA_IActuator): + """ + Property Actuator + + Properties: + + @ivar propName: the property on which to operate. + @type propName: string + @ivar value: the value with which the actuator operates. + @type value: string + @ivar mode: TODO - add constants to game logic dict!. + @type mode: int + """ +#{ Deprecated + def setProperty(prop): + """ + Set the property on which to operate. + + If there is no property of this name, the call is ignored. + + @deprecated: Use the L{propName} attribute instead. + @type prop: string + @param prop: The name of the property to set. + """ + def getProperty(): + """ + Returns the name of the property on which to operate. + + @deprecated: Use the L{propName} attribute instead. + @rtype: string + """ + def setValue(value): + """ + Set the value with which the actuator operates. + + If the value is not compatible with the type of the + property, the subsequent action is ignored. + + @deprecated: Use the L{value} attribute instead. + @type value: string + """ + def getValue(): + """ + Gets the value with which this actuator operates. + + @deprecated: Use the L{value} attribute instead. + @rtype: string + """ +#} + +class SCA_PropertySensor(SCA_ISensor): + """ + Activates when the game object property matches. + + Properties: + + @ivar mode: type of check on the property: + KX_PROPSENSOR_EQUAL(1), KX_PROPSENSOR_NOTEQUAL(2), KX_PROPSENSOR_INTERVAL(3), + KX_PROPSENSOR_CHANGED(4), KX_PROPSENSOR_EXPRESSION(5) + @type mode: integer + @ivar propName: the property the sensor operates. + @type propName: string + @ivar value: the value with which the sensor compares to the value of the property. + @type value: string + """ +#{ Deprecated + def getType(): + """ + Gets when to activate this sensor. + + @deprecated: Use the L{mode} attribute instead. + @return: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL, + KX_PROPSENSOR_INTERVAL, KX_PROPSENSOR_CHANGED, + or KX_PROPSENSOR_EXPRESSION. + """ + + def setType(checktype): + """ + Set the type of check to perform. + + @deprecated: Use the L{mode} attribute instead. + @type checktype: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL, + KX_PROPSENSOR_INTERVAL, KX_PROPSENSOR_CHANGED, + or KX_PROPSENSOR_EXPRESSION. + """ + + def getProperty(): + """ + Return the property with which the sensor operates. + + @deprecated: Use the L{propName} attribute instead. + @rtype: string + @return: the name of the property this sensor is watching. + """ + def setProperty(name): + """ + Sets the property with which to operate. If there is no property + of that name, this call is ignored. + + @deprecated: Use the L{propName} attribute instead. + @type name: string. + """ + def getValue(): + """ + Return the value with which the sensor compares to the value of the property. + + @deprecated: Use the L{value} attribute instead. + @rtype: string + @return: the value of the property this sensor is watching. + """ + def setValue(value): + """ + Set the value with which the sensor operates. If the value + is not compatible with the type of the property, the subsequent + action is ignored. + + @deprecated: Use the L{value} attribute instead. + @type value: string + """ +#} + +class SCA_PythonController(SCA_IController): + """ + A Python controller uses a Python script to activate it's actuators, + based on it's sensors. + + Properties: + + @ivar script: The value of this variable depends on the execution methid. + - When 'Script' execution mode is set this value contains the entire python script as a single string (not the script name as you might expect) which can be modified to run different scripts. + - When 'Module' execution mode is set this value will contain a single line string - module name and function "module.func" or "package.modile.func" where the module names are python textblocks or external scripts. + note: once this is set the script name given for warnings will remain unchanged. + @type script: string + @ivar mode: the execution mode for this controller (read-only). + - Script: 0, Execite the L{script} as a python code. + - Module: 1, Execite the L{script} as a module and function. + @type mode: int + + @group Deprecated: getScript, setScript + """ + def activate(actuator): + """ + Activates an actuator attached to this controller. + @type actuator: actuator or the actuator name as a string + """ + def deactivate(actuator): + """ + Deactivates an actuator attached to this controller. + @type actuator: actuator or the actuator name as a string + """ + def getScript(): + """ + Gets the Python script body this controller executes. + + @deprecated: Use the L{script} attribute instead. + @rtype: string + """ + def setScript(script_body): + """ + Sets the Python script string this controller executes. + + @deprecated: Use the L{script} attribute instead. + @type script_body: string. + """ + +class SCA_RandomActuator(SCA_IActuator): + """ + Random Actuator + + Properties: + + @ivar seed: Seed of the random number generator. + Equal seeds produce equal series. If the seed is 0, + the generator will produce the same value on every call. + @type seed: integer + @ivar para1: the first parameter of the active distribution. + Refer to the documentation of the generator types for the meaning + of this value. + @type para1: float, read-only + @ivar para2: the second parameter of the active distribution. + Refer to the documentation of the generator types for the meaning + of this value. + @type para2: float, read-only + @ivar distribution: distribution type: + KX_RANDOMACT_BOOL_CONST, KX_RANDOMACT_BOOL_UNIFORM, KX_RANDOMACT_BOOL_BERNOUILLI, + KX_RANDOMACT_INT_CONST, KX_RANDOMACT_INT_UNIFORM, KX_RANDOMACT_INT_POISSON, + KX_RANDOMACT_FLOAT_CONST, KX_RANDOMACT_FLOAT_UNIFORM, KX_RANDOMACT_FLOAT_NORMAL, + KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL + @type distribution: integer, read-only + @ivar propName: the name of the property to set with the random value. + If the generator and property types do not match, the assignment is ignored. + @type propName: string + + """ + def setBoolConst(value): + """ + Sets this generator to produce a constant boolean value. + + @param value: The value to return. + @type value: boolean + """ + def setBoolUniform(): + """ + Sets this generator to produce a uniform boolean distribution. + + The generator will generate True or False with 50% chance. + """ + def setBoolBernouilli(value): + """ + Sets this generator to produce a Bernouilli distribution. + + @param value: Specifies the proportion of False values to produce. + - 0.0: Always generate True + - 1.0: Always generate False + @type value: float + """ + def setIntConst(value): + """ + Sets this generator to always produce the given value. + + @param value: the value this generator produces. + @type value: integer + """ + def setIntUniform(lower_bound, upper_bound): + """ + Sets this generator to produce a random value between the given lower and + upper bounds (inclusive). + + @type lower_bound: integer + @type upper_bound: integer + """ + def setIntPoisson(value): + """ + Generate a Poisson-distributed number. + + This performs a series of Bernouilli tests with parameter value. + It returns the number of tries needed to achieve succes. + + @type value: float + """ + def setFloatConst(value): + """ + Always generate the given value. + + @type value: float + """ + def setFloatUniform(lower_bound, upper_bound): + """ + Generates a random float between lower_bound and upper_bound with a + uniform distribution. + + @type lower_bound: float + @type upper_bound: float + """ + def setFloatNormal(mean, standard_deviation): + """ + Generates a random float from the given normal distribution. + + @type mean: float + @param mean: The mean (average) value of the generated numbers + @type standard_deviation: float + @param standard_deviation: The standard deviation of the generated numbers. + """ + def setFloatNegativeExponential(half_life): + """ + Generate negative-exponentially distributed numbers. + + The half-life 'time' is characterized by half_life. + + @type half_life: float + """ +#{ Deprecated + def setSeed(seed): + """ + Sets the seed of the random number generator. + + Equal seeds produce equal series. If the seed is 0, + the generator will produce the same value on every call. + + @deprecated: Use the L{seed} attribute instead. + @type seed: integer + """ + def getSeed(): + """ + Returns the initial seed of the generator. + + @deprecated: Use the L{seed} attribute instead. + @rtype: integer + """ + def getPara1(): + """ + Returns the first parameter of the active distribution. + + Refer to the documentation of the generator types for the meaning + of this value. + + @deprecated: Use the L{para1} attribute instead. + @rtype: float + """ + def getPara2(): + """ + Returns the second parameter of the active distribution. + + Refer to the documentation of the generator types for the meaning + of this value. + + @deprecated: Use the L{para2} attribute instead. + @rtype: float + """ + def getDistribution(): + """ + Returns the type of random distribution. + + @deprecated: Use the L{distribution} attribute instead. + @rtype: distribution type + @return: KX_RANDOMACT_BOOL_CONST, KX_RANDOMACT_BOOL_UNIFORM, KX_RANDOMACT_BOOL_BERNOUILLI, + KX_RANDOMACT_INT_CONST, KX_RANDOMACT_INT_UNIFORM, KX_RANDOMACT_INT_POISSON, + KX_RANDOMACT_FLOAT_CONST, KX_RANDOMACT_FLOAT_UNIFORM, KX_RANDOMACT_FLOAT_NORMAL, + KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL + """ + def setProperty(property): + """ + Set the property to which the random value is assigned. + + If the generator and property types do not match, the assignment is ignored. + + @deprecated: Use the L{propName} attribute instead. + @type property: string + @param property: The name of the property to set. + """ + def getProperty(): + """ + Returns the name of the property to set. + + @deprecated: Use the L{propName} attribute instead. + @rtype: string + """ +#} + + +class SCA_RandomSensor(SCA_ISensor): + """ + This sensor activates randomly. + + @ivar lastDraw: The seed of the random number generator. + @type lastDraw: int + @ivar seed: The seed of the random number generator. + @type seed: int + """ + + def setSeed(seed): + """ + Sets the seed of the random number generator. + + If the seed is 0, the generator will produce the same value on every call. + + @type seed: integer. + """ + def getSeed(): + """ + Returns the initial seed of the generator. Equal seeds produce equal random + series. + + @rtype: integer + """ + def getLastDraw(): + """ + Returns the last random number generated. + + @rtype: integer + """ + +class SCA_XNORController(SCA_IController): + """ + An XNOR controller activates when all linked sensors are the same (activated or inative). + + There are no special python methods for this controller. + """ + +class SCA_XORController(SCA_IController): + """ + An XOR controller activates when there is the input is mixed, but not when all are on or off. + + There are no special python methods for this controller. + """ + +class KX_Camera(KX_GameObject): + """ + A Camera object. + + @group Constants: INSIDE, INTERSECT, OUTSIDE + @ivar INSIDE: see sphereInsideFrustum() and boxInsideFrustum() + @ivar INTERSECT: see sphereInsideFrustum() and boxInsideFrustum() + @ivar OUTSIDE: see sphereInsideFrustum() and boxInsideFrustum() + + @ivar lens: The camera's lens value. + @type lens: float + @ivar near: The camera's near clip distance. + @type near: float + @ivar far: The camera's far clip distance. + @type far: float + @ivar perspective: True if this camera has a perspective transform, False for an orthographic projection. + @type perspective: boolean + @ivar frustum_culling: True if this camera is frustum culling. + @type frustum_culling: boolean + @ivar projection_matrix: This camera's 4x4 projection matrix. + @type projection_matrix: 4x4 Matrix [[float]] + @ivar modelview_matrix: This camera's 4x4 model view matrix. (read-only) + Regenerated every frame from the camera's position and orientation. + @type modelview_matrix: 4x4 Matrix [[float]] + @ivar camera_to_world: This camera's camera to world transform. (read-only) + Regenerated every frame from the camera's position and orientation. + @type camera_to_world: 4x4 Matrix [[float]] + @ivar world_to_camera: This camera's world to camera transform. (read-only) + Regenerated every frame from the camera's position and orientation. + This is camera_to_world inverted. + @type world_to_camera: 4x4 Matrix [[float]] + @ivar useViewport: True when the camera is used as a viewport, set True to enable a viewport for this camera. + @type useViewport: bool + + @group Deprecated: enableViewport, getProjectionMatrix, setProjectionMatrix + """ + + def sphereInsideFrustum(centre, radius): + """ + Tests the given sphere against the view frustum. + + @note: when the camera is first initialized the result will be invalid because the projection matrix has not been set. + @param centre: The centre of the sphere (in world coordinates.) + @type centre: list [x, y, z] + @param radius: the radius of the sphere + @type radius: float + @return: INSIDE, OUTSIDE or INTERSECT + + Example:: + import GameLogic + co = GameLogic.getCurrentController() + cam = co.owner + + # A sphere of radius 4.0 located at [x, y, z] = [1.0, 1.0, 1.0] + if (cam.sphereInsideFrustum([1.0, 1.0, 1.0], 4) != cam.OUTSIDE): + # Sphere is inside frustum ! + # Do something useful ! + else: + # Sphere is outside frustum + """ + def boxInsideFrustum(box): + """ + Tests the given box against the view frustum. + + Example:: + import GameLogic + co = GameLogic.getCurrentController() + cam = co.owner + + # Box to test... + box = [] + box.append([-1.0, -1.0, -1.0]) + box.append([-1.0, -1.0, 1.0]) + box.append([-1.0, 1.0, -1.0]) + box.append([-1.0, 1.0, 1.0]) + box.append([ 1.0, -1.0, -1.0]) + box.append([ 1.0, -1.0, 1.0]) + box.append([ 1.0, 1.0, -1.0]) + box.append([ 1.0, 1.0, 1.0]) + + if (cam.boxInsideFrustum(box) != cam.OUTSIDE): + # Box is inside/intersects frustum ! + # Do something useful ! + else: + # Box is outside the frustum ! + + @note: when the camera is first initialized the result will be invalid because the projection matrix has not been set. + @return: INSIDE, OUTSIDE or INTERSECT + @type box: list + @param box: Eight (8) corner points of the box (in world coordinates.) + """ + def pointInsideFrustum(point): + """ + Tests the given point against the view frustum. + + Example:: + import GameLogic + co = GameLogic.getCurrentController() + cam = co.owner + + # Test point [0.0, 0.0, 0.0] + if (cam.pointInsideFrustum([0.0, 0.0, 0.0])): + # Point is inside frustum ! + # Do something useful ! + else: + # Box is outside the frustum ! + + @note: when the camera is first initialized the result will be invalid because the projection matrix has not been set. + @rtype: boolean + @return: True if the given point is inside this camera's viewing frustum. + @type point: [x, y, z] + @param point: The point to test (in world coordinates.) + """ + def getCameraToWorld(): + """ + Returns the camera-to-world transform. + + @rtype: matrix (4x4 list) + @return: the camera-to-world transform matrix. + """ + def getWorldToCamera(): + """ + Returns the world-to-camera transform. + + This returns the inverse matrix of getCameraToWorld(). + + @rtype: matrix (4x4 list) + @return: the world-to-camera transform matrix. + """ + def getProjectionMatrix(): + """ + Returns the camera's projection matrix. + + @deprecated: Use the L{projection_matrix} attribute instead. + @rtype: matrix (4x4 list) + @return: the camera's projection matrix. + """ + def setProjectionMatrix(matrix): + """ + Sets the camera's projection matrix. + + You should use normalised device coordinates for the clipping planes: + left = -1.0, right = 1.0, top = 1.0, bottom = -1.0, near = cam.near, far = cam.far + + Example:: + import GameLogic + + def Scale(matrix, size): + for y in range(4): + for x in range(4): + matrix[y][x] = matrix[y][x] * size[y] + return matrix + + # Generate a perspective projection matrix + def Perspective(cam): + return [[cam.near, 0.0 , 0.0 , 0.0 ], + [0.0 , cam.near, 0.0 , 0.0 ], + [0.0 , 0.0 , -(cam.far+cam.near)/(cam.far-cam.near), -2.0*cam.far*cam.near/(cam.far - cam.near)], + [0.0 , 0.0 , -1.0 , 0.0 ]] + + # Generate an orthographic projection matrix + # You will need to scale the camera + def Orthographic(cam): + return [[1.0/cam.scaling[0], 0.0 , 0.0 , 0.0 ], + [0.0 , 1.0/cam.scaling[1], 0.0 , 0.0 ], + [0.0 , 0.0 , -2.0/(cam.far-cam.near), -(cam.far+cam.near)/(cam.far-cam.near)], + [0.0 , 0.0 , 0.0 , 1.0 ]] + + # Generate an isometric projection matrix + def Isometric(cam): + return Scale([[0.707, 0.0 , 0.707, 0.0], + [0.408, 0.816,-0.408, 0.0], + [0.0 , 0.0 , 0.0 , 0.0], + [0.0 , 0.0 , 0.0 , 1.0]], + [1.0/cam.scaling[0], 1.0/cam.scaling[1], 1.0/cam.scaling[2], 1.0]) + + co = GameLogic.getCurrentController() + cam = co.owner + cam.setProjectionMatrix(Perspective(cam))) + + @deprecated: Use the L{projection_matrix} attribute instead. + @type matrix: 4x4 matrix. + @param matrix: The new projection matrix for this camera. + """ + + def enableViewport(viewport): + """ + Use this camera to draw a viewport on the screen (for split screen games or overlay scenes). The viewport region is defined with L{setViewport}. + + @deprecated: Use the L{useViewport} attribute instead. + @type viewport: bool + @param viewport: the new viewport status + """ + def setOnTop(): + """ + Set this cameras viewport ontop of all other viewport. + """ + def setViewport(left, bottom, right, top): + """ + Sets the region of this viewport on the screen in pixels. + + Use L{Rasterizer.getWindowHeight} L{Rasterizer.getWindowWidth} to calculate values relative to the entire display. + + @type left: int + @type bottom: int + @type right: int + @type top: int + """ + def getScreenPosition(arg): + """ + Gets the position of an object projected on screen space. + + Example: + # For an object in the middle of the screen, coord = [0.5,0.5] + coord = camera.getScreenPosition(object) + + @param arg: L{KX_GameObject}, object name or list [x, y, z] + @rtype: list [x, y] + @return: the object's position in screen coordinates. + """ + def getScreenVect(x, y): + """ + Gets the vector from the camera position in the screen coordinate direction. + + Example: + # Gets the vector of the camera front direction: + m_vect = camera.getScreenVect(0.5,0.5) + + @type x: float + @type y: float + @rtype: 3d vector + @return: the vector from a screen coordinate. + """ + def getScreenRay(x, y, dist, property): + """ + Look towards a screen coordinate (x,y) and find first object hit within dist that matches prop. + The ray is similar to KX_GameObject->rayCastTo. + + Example: + # Gets an object with a property "wall" in front of the camera within a distance of 100: + target = camera.getScreenRay(0.5,0.5,100,"wall") + + @type x: float + @type y: float + @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other + @type dist: float + @param property: property name that object must have; can be omitted => detect any object + @type property: string + @rtype: L{KX_GameObject} + @return: the first object hit or None if no object or object does not match prop + """ + +# Util func to extract all attrs +""" +import types +attrs = [] +for name, val in locals().items(): + if name.startswith('__'): + continue + if type(val) == types.ClassType: + for line in val.__doc__.split('\n'): + if '@ivar' in line: + attrs.append(name + '::' + line.split()[1].replace(':', '')) + +for a in attrs: + print a """ -if 0: - # Use to print out all the links - for i in a.split('\n'): - if i.startswith('@var'): - var = i.split(' ')[1].split(':')[0] - print '@var %s: L{%s<%s.%s>}' % (var, var, var, var) +# Util func to construct a mapping from deprecated attrs to new ones. +""" +import types +import re +import pprint +depAttrs = {} +for name, val in locals().items(): + if name.startswith('__'): + continue + if type(val) == types.ClassType: + print "\t# %s" % name + + # Inspect each attribute. + for attrName in dir(val): + if attrName.startswith('__'): + continue + attr = getattr(val, attrName) + + # Check whether this attribute is deprecated by searching each line. + newAttrName = None + for line in attr.__doc__.split('\n'): + match = re.search(r'@deprecated.*L{(\w+)}', line) + if match: + newAttrName = match.group(1) + break + if not newAttrName: + continue + + # Store the mappings to new attributes in a list (because there + # could be collisions). + if not depAttrs.has_key(attrName): + depAttrs[attrName] = {} + mapping = depAttrs[attrName] + + for line in val.__doc__.split('\n'): + if ("@type %s:" % newAttrName) in line: + # The attribute is being replaced in this class (i.e. the + # deprecated attribute wasn't inherited from a parent). We + # have a winner! + funcType = None + if 'sequence' in line: + funcType = 'Keyed' + else: + funcType = 'Simple' + + if attrName.startswith('get') or attrName.startswith('is'): + func = "replace%sGetter" % funcType + elif attrName.startswith('set') or attrName.startswith('enable'): + func = "replace%sSetter" % funcType + else: + func = 'UNKNOWN' + + # Another mapping, from a conversion tuple to lists of class + # names. + conversion = (func, newAttrName) + if not mapping.has_key(conversion): + mapping[conversion] = [] + mapping[conversion].append(name) + break + +pprint.pprint(depAttrs, width = 100) +""" diff --git a/source/gameengine/PyDoc/KX_BlenderMaterial.py b/source/gameengine/PyDoc/KX_BlenderMaterial.py deleted file mode 100644 index 21417db1802..00000000000 --- a/source/gameengine/PyDoc/KX_BlenderMaterial.py +++ /dev/null @@ -1,38 +0,0 @@ -class KX_BlenderMaterial: # (PyObjectPlus) - """ - KX_BlenderMaterial - - All placeholders have a __ prefix - """ - - def __getShader(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - - def __setBlending(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __getMaterialIndex(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ diff --git a/source/gameengine/PyDoc/KX_CDActuator.py b/source/gameengine/PyDoc/KX_CDActuator.py deleted file mode 100644 index e1067674e7e..00000000000 --- a/source/gameengine/PyDoc/KX_CDActuator.py +++ /dev/null @@ -1,55 +0,0 @@ -# $Id$ -# Documentation for CD Actuator -from SCA_IActuator import * - -class KX_CDActuator(SCA_IActuator): - """ - CD Controller actuator. - @ivar volume: controls the volume to set the CD to. 0.0 = silent, 1.0 = max volume. - @type volume: float - @ivar track: the track selected to be played - @type track: integer - @ivar gain: the gain (volume) of the CD between 0.0 and 1.0. - @type gain: float - """ - def startCD(): - """ - Starts the CD playing. - """ - def stopCD(): - """ - Stops the CD playing. - """ - def pauseCD(): - """ - Pauses the CD. - """ - def resumeCD(): - """ - Resumes the CD after a pause. - """ - def playAll(): - """ - Plays the CD from the beginning. - """ - def playTrack(trackNumber): - """ - Plays the track selected. - """ - def setGain(gain): - """ - DEPRECATED: Use the volume property. - Sets the gain (volume) of the CD. - - @type gain: float - @param gain: the gain to set the CD to. 0.0 = silent, 1.0 = max volume. - """ - def getGain(): - """ - DEPRECATED: Use the volume property. - Gets the current gain (volume) of the CD. - - @rtype: float - @return: Between 0.0 (silent) and 1.0 (max volume) - """ - diff --git a/source/gameengine/PyDoc/KX_Camera.py b/source/gameengine/PyDoc/KX_Camera.py deleted file mode 100644 index f5d0d45f968..00000000000 --- a/source/gameengine/PyDoc/KX_Camera.py +++ /dev/null @@ -1,209 +0,0 @@ -# $Id$ -# Documentation for Camera game objects. -from KX_GameObject import * - -class KX_Camera(KX_GameObject): - """ - A Camera object. - - @group Constants: INSIDE, INTERSECT, OUTSIDE - @ivar INSIDE: see sphereInsideFrustum() and boxInsideFrustum() - @ivar INTERSECT: see sphereInsideFrustum() and boxInsideFrustum() - @ivar OUTSIDE: see sphereInsideFrustum() and boxInsideFrustum() - - @ivar lens: The camera's lens value. - @type lens: float - @ivar near: The camera's near clip distance. - @type near: float - @ivar far: The camera's far clip distance. - @type far: float - @ivar perspective: True if this camera has a perspective transform. - - If perspective is False, this camera has an orthographic transform. - - Note that the orthographic transform is faked by multiplying the lens attribute - by 100.0 and translating the camera 100.0 along the z axis. - - This is the same as Blender. If you want a true orthographic transform, see L{setProjectionMatrix}. - @type perspective: boolean - @ivar frustum_culling: True if this camera is frustum culling. - @type frustum_culling: boolean - @ivar projection_matrix: This camera's 4x4 projection matrix. - @type projection_matrix: 4x4 Matrix [[float]] - @ivar modelview_matrix: This camera's 4x4 model view matrix. (read only) - Regenerated every frame from the camera's position and orientation. - @type modelview_matrix: 4x4 Matrix [[float]] - @ivar camera_to_world: This camera's camera to world transform. (read only) - Regenerated every frame from the camera's position and orientation. - @type camera_to_world: 4x4 Matrix [[float]] - @ivar world_to_camera: This camera's world to camera transform. (read only) - Regenerated every frame from the camera's position and orientation. - This is camera_to_world inverted. - @type world_to_camera: 4x4 Matrix [[float]] - """ - - def sphereInsideFrustum(centre, radius): - """ - Tests the given sphere against the view frustum. - - @param centre: The centre of the sphere (in world coordinates.) - @type centre: list [x, y, z] - @param radius: the radius of the sphere - @type radius: float - @return: INSIDE, OUTSIDE or INTERSECT - - Example:: - import GameLogic - co = GameLogic.getCurrentController() - cam = co.GetOwner() - - # A sphere of radius 4.0 located at [x, y, z] = [1.0, 1.0, 1.0] - if (cam.sphereInsideFrustum([1.0, 1.0, 1.0], 4) != cam.OUTSIDE): - # Sphere is inside frustum ! - # Do something useful ! - else: - # Sphere is outside frustum - """ - def boxInsideFrustum(box): - """ - Tests the given box against the view frustum. - - Example:: - import GameLogic - co = GameLogic.getCurrentController() - cam = co.GetOwner() - - # Box to test... - box = [] - box.append([-1.0, -1.0, -1.0]) - box.append([-1.0, -1.0, 1.0]) - box.append([-1.0, 1.0, -1.0]) - box.append([-1.0, 1.0, 1.0]) - box.append([ 1.0, -1.0, -1.0]) - box.append([ 1.0, -1.0, 1.0]) - box.append([ 1.0, 1.0, -1.0]) - box.append([ 1.0, 1.0, 1.0]) - - if (cam.boxInsideFrustum(box) != cam.OUTSIDE): - # Box is inside/intersects frustum ! - # Do something useful ! - else: - # Box is outside the frustum ! - - @return: INSIDE, OUTSIDE or INTERSECT - @type box: list - @param box: Eight (8) corner points of the box (in world coordinates.) - """ - def pointInsideFrustum(point): - """ - Tests the given point against the view frustum. - - Example:: - import GameLogic - co = GameLogic.getCurrentController() - cam = co.GetOwner() - - # Test point [0.0, 0.0, 0.0] - if (cam.pointInsideFrustum([0.0, 0.0, 0.0])): - # Point is inside frustum ! - # Do something useful ! - else: - # Box is outside the frustum ! - - @rtype: boolean - @return: True if the given point is inside this camera's viewing frustum. - @type point: [x, y, z] - @param point: The point to test (in world coordinates.) - """ - def getCameraToWorld(): - """ - Returns the camera-to-world transform. - - @rtype: matrix (4x4 list) - @return: the camera-to-world transform matrix. - """ - def getWorldToCamera(): - """ - Returns the world-to-camera transform. - - This returns the inverse matrix of getCameraToWorld(). - - @rtype: matrix (4x4 list) - @return: the world-to-camera transform matrix. - """ - def getProjectionMatrix(): - """ - Returns the camera's projection matrix. - - @rtype: matrix (4x4 list) - @return: the camera's projection matrix. - """ - def setProjectionMatrix(matrix): - """ - Sets the camera's projection matrix. - - You should use normalised device coordinates for the clipping planes: - left = -1.0, right = 1.0, top = 1.0, bottom = -1.0, near = cam.near, far = cam.far - - Example:: - import GameLogic - - def Scale(matrix, size): - for y in range(4): - for x in range(4): - matrix[y][x] = matrix[y][x] * size[y] - return matrix - - # Generate a perspective projection matrix - def Perspective(cam): - return [[cam.near, 0.0 , 0.0 , 0.0 ], - [0.0 , cam.near, 0.0 , 0.0 ], - [0.0 , 0.0 , -(cam.far+cam.near)/(cam.far-cam.near), -2.0*cam.far*cam.near/(cam.far - cam.near)], - [0.0 , 0.0 , -1.0 , 0.0 ]] - - # Generate an orthographic projection matrix - # You will need to scale the camera - def Orthographic(cam): - return [[1.0/cam.scaling[0], 0.0 , 0.0 , 0.0 ], - [0.0 , 1.0/cam.scaling[1], 0.0 , 0.0 ], - [0.0 , 0.0 , -2.0/(cam.far-cam.near), -(cam.far+cam.near)/(cam.far-cam.near)], - [0.0 , 0.0 , 0.0 , 1.0 ]] - - # Generate an isometric projection matrix - def Isometric(cam): - return Scale([[0.707, 0.0 , 0.707, 0.0], - [0.408, 0.816,-0.408, 0.0], - [0.0 , 0.0 , 0.0 , 0.0], - [0.0 , 0.0 , 0.0 , 1.0]], - [1.0/cam.scaling[0], 1.0/cam.scaling[1], 1.0/cam.scaling[2], 1.0]) - - co = GameLogic.getCurrentController() - cam = co.getOwner() - cam.setProjectionMatrix(Perspective(cam))) - - @type matrix: 4x4 matrix. - @param matrix: The new projection matrix for this camera. - """ - - def enableViewport(viewport): - """ - Use this camera to draw a viewport on the screen (for split screen games or overlay scenes). The viewport region is defined with L{setViewport}. - - @type viewport: bool - @param viewport: the new viewport status - """ - def setOnTop(): - """ - Set this cameras viewport ontop of all other viewport. - """ - def setViewport(left, bottom, right, top): - """ - Sets the region of this viewport on the screen in pixels. - - Use L{Rasterizer.getWindowHeight} L{Rasterizer.getWindowWidth} to calculate values relative to the entire display. - - @type left: int - @type bottom: int - @type right: int - @type top: int - """ diff --git a/source/gameengine/PyDoc/KX_CameraActuator.py b/source/gameengine/PyDoc/KX_CameraActuator.py deleted file mode 100644 index 6ffc55a5854..00000000000 --- a/source/gameengine/PyDoc/KX_CameraActuator.py +++ /dev/null @@ -1,98 +0,0 @@ -# $Id$ -# Documentation for KX_CameraActuator -from SCA_IActuator import * - -class KX_CameraActuator(SCA_IActuator): - """ - Applies changes to a camera. - - @ivar min: minimum distance to the target object maintained by the actuator - @type min: float - @ivar max: maximum distance to stay from the target object - @type max: float - @ivar height: height to stay above the target object - @type height: float - @ivar xy: axis this actuator is tracking, true=X, false=Y - @type xy: boolean - @ivar object: the object this actuator tracks. - @type object: KX_GameObject or None - @author: snail - """ - def getObject(name_only = 1): - """ - Returns the name of the object this actuator tracks. - - @type name_only: bool - @param name_only: optional argument, when 0 return a KX_GameObject - @rtype: string, KX_GameObject or None if no object is set - """ - - def setObject(target): - """ - Sets the object this actuator tracks. - - @param target: the object to track. - @type target: L{KX_GameObject}, string or None - """ - - def getMin(): - """ - Returns the minimum distance to target maintained by the actuator. - - @rtype: float - """ - - def setMin(distance): - """ - Sets the minimum distance to the target object maintained by the - actuator. - - @param distance: The minimum distance to maintain. - @type distance: float - """ - - def getMax(): - """ - Gets the maximum distance to stay from the target object. - - @rtype: float - """ - - def setMax(distance): - """ - Sets the maximum distance to stay from the target object. - - @param distance: The maximum distance to maintain. - @type distance: float - """ - - def getHeight(): - """ - Returns the height to stay above the target object. - - @rtype: float - """ - - def setHeight(height): - """ - Sets the height to stay above the target object. - - @type height: float - @param height: The height to stay above the target object. - """ - - def setXY(xaxis): - """ - Sets the axis to get behind. - - @param xaxis: False to track Y axis, True to track X axis. - @type xaxis: boolean - """ - - def getXY(): - """ - Returns the axis this actuator is tracking. - - @return: True if tracking X axis, False if tracking Y axis. - @rtype: boolean - """ diff --git a/source/gameengine/PyDoc/KX_ConstraintActuator.py b/source/gameengine/PyDoc/KX_ConstraintActuator.py deleted file mode 100644 index a30b859548b..00000000000 --- a/source/gameengine/PyDoc/KX_ConstraintActuator.py +++ /dev/null @@ -1,249 +0,0 @@ -# $Id$ -# Documentation for KX_ConstraintActuator -from SCA_IActuator import * - -class KX_ConstraintActuator(SCA_IActuator): - """ - A constraint actuator limits the position, rotation, distance or orientation of an object. - - Properties: - - @ivar damp: time constant of the constraint expressed in frame (not use by Force field constraint) - @type damp: integer - - @ivar rotDamp: time constant for the rotation expressed in frame (only for the distance constraint) - 0 = use damp for rotation as well - @type rotDamp: integer - - @ivar direction: the reference direction in world coordinate for the orientation constraint - @type direction: 3-tuple of float: [x,y,z] - - @ivar option: Binary combination of the following values: - Applicable to Distance constraint: - KX_ACT_CONSTRAINT_NORMAL ( 64) : Activate alignment to surface - KX_ACT_CONSTRAINT_DISTANCE ( 512) : Activate distance control - KX_ACT_CONSTRAINT_LOCAL (1024) : direction of the ray is along the local axis - Applicable to Force field constraint: - KX_ACT_CONSTRAINT_DOROTFH (2048) : Force field act on rotation as well - Applicable to both: - KX_ACT_CONSTRAINT_MATERIAL ( 128) : Detect material rather than property - KX_ACT_CONSTRAINT_PERMANENT ( 256) : No deactivation if ray does not hit target - @type option: integer - - @ivar time: activation time of the actuator. The actuator disables itself after this many frame. - If set to 0, the actuator is not limited in time. - @type time: integer - - @ivar property: the name of the property or material for the ray detection of the distance constraint. - @type property: string - - @ivar min: The lower bound of the constraint - For the rotation and orientation constraint, it represents radiant - @type min: float - - @ivar distance: the target distance of the distance constraint - @type distance: float - - @ivar max: the upper bound of the constraint. - For rotation and orientation constraints, it represents radiant. - @type max: float - - @ivar rayLength: the length of the ray of the distance constraint. - @type rayLength: float - - @ivar limit: type of constraint, use one of the following constant: - KX_ACT_CONSTRAINT_LOCX ( 1) : limit X coord - KX_ACT_CONSTRAINT_LOCY ( 2) : limit Y coord - KX_ACT_CONSTRAINT_LOCZ ( 3) : limit Z coord - KX_ACT_CONSTRAINT_ROTX ( 4) : limit X rotation - KX_ACT_CONSTRAINT_ROTY ( 5) : limit Y rotation - KX_ACT_CONSTRAINT_ROTZ ( 6) : limit Z rotation - KX_ACT_CONSTRAINT_DIRPX ( 7) : set distance along positive X axis - KX_ACT_CONSTRAINT_DIRPY ( 8) : set distance along positive Y axis - KX_ACT_CONSTRAINT_DIRPZ ( 9) : set distance along positive Z axis - KX_ACT_CONSTRAINT_DIRNX (10) : set distance along negative X axis - KX_ACT_CONSTRAINT_DIRNY (11) : set distance along negative Y axis - KX_ACT_CONSTRAINT_DIRNZ (12) : set distance along negative Z axis - KX_ACT_CONSTRAINT_ORIX (13) : set orientation of X axis - KX_ACT_CONSTRAINT_ORIY (14) : set orientation of Y axis - KX_ACT_CONSTRAINT_ORIZ (15) : set orientation of Z axis - KX_ACT_CONSTRAINT_FHPX (16) : set force field along positive X axis - KX_ACT_CONSTRAINT_FHPY (17) : set force field along positive Y axis - KX_ACT_CONSTRAINT_FHPZ (18) : set force field along positive Z axis - KX_ACT_CONSTRAINT_FHNX (19) : set force field along negative X axis - KX_ACT_CONSTRAINT_FHNY (20) : set force field along negative Y axis - KX_ACT_CONSTRAINT_FHNZ (21) : set force field along negative Z axis - @type limit: integer - """ - def setDamp(time): - """ - Sets the time this constraint is delayed. - - @param time: The number of frames to delay. - Negative values are ignored. - @type time: integer - """ - def getDamp(): - """ - Returns the damping time of the constraint. - - @rtype: integer - """ - def setMin(lower): - """ - Sets the lower bound of the constraint. - - For rotational and orientation constraints, lower is specified in degrees. - - @type lower: float - """ - def getMin(): - """ - Gets the lower bound of the constraint. - - For rotational and orientation constraints, the lower bound is returned in radians. - - @rtype: float - """ - def setMax(upper): - """ - Sets the upper bound of the constraint. - - For rotational and orientation constraints, upper is specified in degrees. - - @type upper: float - """ - def getMax(): - """ - Gets the upper bound of the constraint. - - For rotational and orientation constraints, the upper bound is returned in radians. - - @rtype: float - """ - def setLimit(limit): - """ - Sets the type of constraint. - - See module L{GameLogic} for valid constraint types. - - @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(): - """ - Gets the type of constraint. - - 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, 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_ConstraintWrapper.py b/source/gameengine/PyDoc/KX_ConstraintWrapper.py deleted file mode 100644 index 5b34e1609e8..00000000000 --- a/source/gameengine/PyDoc/KX_ConstraintWrapper.py +++ /dev/null @@ -1,28 +0,0 @@ -class KX_ConstraintWrapper: # (PyObjectPlus) - """ - KX_ConstraintWrapper - - All placeholders have a __ prefix - """ - def __getConstraintId(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - - def __testMethod(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - diff --git a/source/gameengine/PyDoc/KX_GameActuator.py b/source/gameengine/PyDoc/KX_GameActuator.py deleted file mode 100644 index fc5bd6005fc..00000000000 --- a/source/gameengine/PyDoc/KX_GameActuator.py +++ /dev/null @@ -1,29 +0,0 @@ -# $Id$ -# Documentation for KX_GameActuator -from SCA_IActuator import * - -class KX_GameActuator(SCA_IActuator): - """ - The game actuator loads a new .blend file, restarts the current .blend file or quits the game. - - Properties: - - @ivar file: the new .blend file to load - @type file: string. - """ - def getFile(): - """ - DEPRECATED: use the file property - Returns the filename of the new .blend file to load. - - @rtype: string - """ - def setFile(filename): - """ - DEPRECATED: use the file property - Sets the new .blend file to load. - - @param filename: The file name this actuator will load. - @type filename: string - """ - diff --git a/source/gameengine/PyDoc/KX_GameObject.py b/source/gameengine/PyDoc/KX_GameObject.py deleted file mode 100644 index 21ddf439924..00000000000 --- a/source/gameengine/PyDoc/KX_GameObject.py +++ /dev/null @@ -1,504 +0,0 @@ -# $Id$ -# Documentation for game objects - -# from SCA_IObject import * -# from SCA_ISensor import * -# from SCA_IController import * -# from SCA_IActuator import * - - -class KX_GameObject: # (SCA_IObject) - """ - All game objects are derived from this class. - - Properties assigned to game objects are accessible as attributes of this class. - - note: Calling ANY method or attribute on an object that has been removed from a scene will raise a RuntimeError, if an object may have been removed since last accessing it use the L{isValid} attribute to check. - - @ivar name: The object's name. (Read only) - - note: Currently (Blender 2.49) the prefix "OB" is added to all objects name. This may change in blender 2.5. - @type name: string. - @ivar mass: The object's mass - - note: The object must have a physics controller for the mass to be applied, otherwise the mass value will be returned as 0.0 - @type mass: float - @ivar linVelocityMin: Enforces the object keeps moving at a minimum velocity. - - note: Applies to dynamic and rigid body objects only. - - note: A value of 0.0 disables this option. - - note: While objects are stationary the minimum velocity will not be applied. - @type linVelocityMin: float - @ivar linVelocityMax: Clamp the maximum linear velocity to prevent objects moving beyond a set speed. - - note: Applies to dynamic and rigid body objects only. - - note: A value of 0.0 disables this option (rather then setting it stationary). - @type linVelocityMax: float - @ivar localInertia: the object's inertia vector in local coordinates. Read only. - @type localInertia: list [ix, iy, iz] - @ivar parent: The object's parent object. (Read only) - @type parent: L{KX_GameObject} or None - @ivar visible: visibility flag. - - note: Game logic will still run for invisible objects. - @type visible: boolean - @ivar occlusion: occlusion capability flag. - @type occlusion: boolean - @ivar position: The object's position. - DEPRECATED: use localPosition and worldPosition - @type position: list [x, y, z] On write: local position, on read: world position - @ivar orientation: The object's orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector. - DEPRECATED: use localOrientation and worldOrientation - @type orientation: 3x3 Matrix [[float]] On write: local orientation, on read: world orientation - @ivar scaling: The object's scaling factor. list [sx, sy, sz] - DEPRECATED: use localScaling and worldScaling - @type scaling: list [sx, sy, sz] On write: local scaling, on read: world scaling - @ivar localOrientation: The object's local orientation. 3x3 Matrix. You can also write a Quaternion or Euler vector. - @type localOrientation: 3x3 Matrix [[float]] - @ivar worldOrientation: The object's world orientation. Read-only. - @type worldOrientation: 3x3 Matrix [[float]] - @ivar localScaling: The object's local scaling factor. - @type localScaling: list [sx, sy, sz] - @ivar worldScaling: The object's world scaling factor. Read-only - @type worldScaling: list [sx, sy, sz] - @ivar localPosition: The object's local position. - @type localPosition: list [x, y, z] - @ivar worldPosition: The object's world position. - @type worldPosition: list [x, y, z] - @ivar timeOffset: adjust the slowparent delay at runtime. - @type timeOffset: float - @ivar state: the game object's state bitmask, using the first 30 bits, one bit must always be set. - @type state: int - @ivar meshes: a list meshes for this object. - - note: Most objects use only 1 mesh. - - note: Changes to this list will not update the KX_GameObject. - @type meshes: list of L{KX_MeshProxy} - @ivar sensors: a list of L{SCA_ISensor} objects. - - note: This attribute is experemental and may be removed (but probably wont be). - - note: Changes to this list will not update the KX_GameObject. - @type sensors: list - @ivar controllers: a list of L{SCA_IController} objects. - - note: This attribute is experemental and may be removed (but probably wont be). - - note: Changes to this list will not update the KX_GameObject. - @type controllers: list of L{SCA_ISensor}. - @ivar actuators: a list of L{SCA_IActuator} objects. - - note: This attribute is experemental and may be removed (but probably wont be). - - note: Changes to this list will not update the KX_GameObject. - @type actuators: list - @ivar isValid: Retuerns fails when the object has been removed from the scene and can no longer be used. - @type isValid: bool - """ - def endObject(visible): - """ - Delete this object, can be used inpace of the EndObject Actuator. - The actual removal of the object from the scene is delayed. - """ - def replaceMesh(mesh_name): - """ - Replace the mesh of this object with a new mesh. This works the same was as the actuator. - @type mesh_name: string - """ - def getVisible(): - """ - Gets the game object's visible flag. (B{deprecated}) - - @rtype: boolean - """ - def setVisible(visible, recursive): - """ - Sets the game object's visible flag. - - @type visible: boolean - @type recursive: boolean - @param recursive: optional argument to set all childrens visibility flag too. - """ - def setOcclusion(occlusion, recursive): - """ - Sets the game object's occlusion capability. - - @type visible: boolean - @type recursive: boolean - @param recursive: optional argument to set all childrens occlusion flag too. - """ - def getState(): - """ - Gets the game object's state bitmask. (B{deprecated}) - - @rtype: int - @return: the objects state. - """ - def setState(state): - """ - Sets the game object's state flag. (B{deprecated}). - The bitmasks for states from 1 to 30 can be set with (1<<0, 1<<1, 1<<2 ... 1<<29) - - @type state: integer - """ - def setPosition(pos): - """ - Sets the game object's position. (B{deprecated}) - Global coordinates for root object, local for child objects. - - - @type pos: [x, y, z] - @param pos: the new position, in local coordinates. - """ - def setWorldPosition(pos): - """ - Sets the game object's position in world coordinates regardless if the object is root or child. - - @type pos: [x, y, z] - @param pos: the new position, in world coordinates. - """ - def getPosition(): - """ - Gets the game object's position. (B{deprecated}) - - @rtype: list [x, y, z] - @return: the object's position in world coordinates. - """ - def setOrientation(orn): - """ - Sets the game object's orientation. (B{deprecated}) - - @type orn: 3x3 rotation matrix, or Quaternion. - @param orn: a rotation matrix specifying the new rotation. - @note: When using this matrix with Blender.Mathutils.Matrix() types, it will need to be transposed. - """ - def alignAxisToVect(vect, axis): - """ - Aligns any of the game object's axis along the given vector. - - @type vect: 3d vector. - @param vect: a vector to align the axis. - @type axis: integer. - @param axis:The axis you want to align - - 0: X axis - - 1: Y axis - - 2: Z axis (default) - """ - def getAxisVect(vect): - """ - Returns the axis vector rotates by the objects worldspace orientation. - This is the equivalent if multiplying the vector by the orientation matrix. - - @type vect: 3d vector. - @param vect: a vector to align the axis. - @rtype: 3d vector. - @return: The vector in relation to the objects rotation. - - """ - def getOrientation(): - """ - Gets the game object's orientation. (B{deprecated}) - - @rtype: 3x3 rotation matrix - @return: The game object's rotation matrix - @note: When using this matrix with Blender.Mathutils.Matrix() types, it will need to be transposed. - """ - def applyMovement(movement, local = 0): - """ - Sets the game object's movement. - - @type movement: 3d vector. - @param movement: movement vector. - @type local: boolean - @param local: - False: you get the "global" movement ie: relative to world orientation (default). - - True: you get the "local" movement ie: relative to object orientation. - """ - def applyRotation(rotation, local = 0): - """ - Sets the game object's rotation. - - @type rotation: 3d vector. - @param rotation: rotation vector. - @type local: boolean - @param local: - False: you get the "global" rotation ie: relative to world orientation (default). - - True: you get the "local" rotation ie: relative to object orientation. - """ - def applyForce(force, local = 0): - """ - Sets the game object's force. - - This requires a dynamic object. - - @type force: 3d vector. - @param force: force vector. - @type local: boolean - @param local: - False: you get the "global" force ie: relative to world orientation (default). - - True: you get the "local" force ie: relative to object orientation. - """ - def applyTorque(torque, local = 0): - """ - Sets the game object's torque. - - This requires a dynamic object. - - @type torque: 3d vector. - @param torque: torque vector. - @type local: boolean - @param local: - False: you get the "global" torque ie: relative to world orientation (default). - - True: you get the "local" torque ie: relative to object orientation. - """ - def getLinearVelocity(local = 0): - """ - Gets the game object's linear velocity. - - This method returns the game object's velocity through it's centre of mass, - ie no angular velocity component. - - @type local: boolean - @param local: - False: you get the "global" velocity ie: relative to world orientation (default). - - True: you get the "local" velocity ie: relative to object orientation. - @rtype: list [vx, vy, vz] - @return: the object's linear velocity. - """ - def setLinearVelocity(velocity, local = 0): - """ - Sets the game object's linear velocity. - - This method sets game object's velocity through it's centre of mass, - ie no angular velocity component. - - This requires a dynamic object. - - @type velocity: 3d vector. - @param velocity: linear velocity vector. - @type local: boolean - @param local: - False: you get the "global" velocity ie: relative to world orientation (default). - - True: you get the "local" velocity ie: relative to object orientation. - """ - def getAngularVelocity(local = 0): - """ - Gets the game object's angular velocity. - - @type local: boolean - @param local: - False: you get the "global" velocity ie: relative to world orientation (default). - - True: you get the "local" velocity ie: relative to object orientation. - @rtype: list [vx, vy, vz] - @return: the object's angular velocity. - """ - def setAngularVelocity(velocity, local = 0): - """ - Sets the game object's angular velocity. - - This requires a dynamic object. - - @type velocity: 3d vector. - @param velocity: angular velocity vector. - @type local: boolean - @param local: - False: you get the "global" velocity ie: relative to world orientation (default). - - True: you get the "local" velocity ie: relative to object orientation. - """ - def getVelocity(point): - """ - Gets the game object's velocity at the specified point. - - Gets the game object's velocity at the specified point, including angular - components. - - @type point: list [x, y, z] - @param point: the point to return the velocity for, in local coordinates. (optional: default = [0, 0, 0]) - @rtype: list [vx, vy, vz] - @return: the velocity at the specified point. - """ - def getMass(): - """ - Gets the game object's mass. (B{deprecated}) - - @rtype: float - @return: the object's mass. - """ - def getReactionForce(): - """ - Gets the game object's reaction force. - - The reaction force is the force applied to this object over the last simulation timestep. - This also includes impulses, eg from collisions. - - (B{This is not implimented for bullet physics at the moment}) - - @rtype: list [fx, fy, fz] - @return: the reaction force of this object. - """ - def applyImpulse(point, impulse): - """ - Applies an impulse to the game object. - - This will apply the specified impulse to the game object at the specified point. - If point != getPosition(), applyImpulse will also change the object's angular momentum. - Otherwise, only linear momentum will change. - - @type point: list [x, y, z] - @param point: the point to apply the impulse to (in world coordinates) - """ - def suspendDynamics(): - """ - Suspends physics for this object. - """ - def restoreDynamics(): - """ - Resumes physics for this object. - @Note: The objects linear velocity will be applied from when the dynamics were suspended. - """ - def enableRigidBody(): - """ - Enables rigid body physics for this object. - - Rigid body physics allows the object to roll on collisions. - @Note: This is not working with bullet physics yet. - """ - def disableRigidBody(): - """ - Disables rigid body physics for this object. - @Note: This is not working with bullet physics yet. The angular is removed but rigid body physics can still rotate it later. - """ - def getParent(): - """ - Gets this object's parent. (B{deprecated}) - - @rtype: L{KX_GameObject} - @return: this object's parent object, or None if this object has no parent. - """ - def setParent(parent): - """ - Sets this object's parent. - - @type parent: L{KX_GameObject} - @param parent: new parent object. - """ - def removeParent(): - """ - Removes this objects parent. - """ - def getChildren(): - """ - Return a list of immediate children of this object. - @rtype: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>} - @return: a list of all this objects children. - """ - def getChildrenRecursive(): - """ - Return a list of children of this object, including all their childrens children. - @rtype: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>} - @return: a list of all this objects children recursivly. - """ - def getMesh(mesh): - """ - Gets the mesh object for this object. - - @type mesh: integer - @param mesh: the mesh object to return (optional: default mesh = 0) - @rtype: L{KX_MeshProxy} - @return: the first mesh object associated with this game object, or None if this object has no meshs. - """ - def getPhysicsId(): - """ - Returns the user data object associated with this game object's physics controller. - """ - def getPropertyNames(): - """ - Gets a list of all property names. - @rtype: list - @return: All property names for this object. - """ - def getDistanceTo(other): - """ - Returns the distance to another object or point. - - @param other: a point or another L{KX_GameObject} to measure the distance to. - @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. - - The ray is always casted from the center of the object, ignoring the object itself. - The ray is casted towards the center of another object or an explicit [x,y,z] point. - Use rayCast() if you need to retrieve the hit point - - @param other: [x,y,z] or object towards which the ray is casted - @type other: L{KX_GameObject} or 3-tuple - @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to other - @type dist: float - @param prop: property name that object must have; can be omitted => detect any object - @type prop: string - @rtype: L{KX_GameObject} - @return: the first object hit or None if no object or object does not match prop - """ - def rayCast(objto,objfrom,dist,prop,face,xray,poly): - """ - Look from a point/object to another point/object and find first object hit within dist that matches prop. - if poly is 0, returns a 3-tuple with object reference, hit point and hit normal or (None,None,None) if no hit. - if poly is 1, returns a 4-tuple with in addition a L{KX_PolyProxy} as 4th element. - - Ex:: - # shoot along the axis gun-gunAim (gunAim should be collision-free) - ob,point,normal = gun.rayCast(gunAim,None,50) - if ob: - # hit something - - Notes: - The ray ignores the object on which the method is called. - It is casted from/to object center or explicit [x,y,z] points. - - The face paremeter determines the orientation of the normal:: - 0 => hit normal is always oriented towards the ray origin (as if you casted the ray from outside) - 1 => hit normal is the real face normal (only for mesh object, otherwise face has no effect) - - The ray has X-Ray capability if xray parameter is 1, otherwise the first object hit (other than self object) stops the ray. - The prop and xray parameters interact as follow:: - prop off, xray off: return closest hit or no hit if there is no object on the full extend of the ray. - prop off, xray on : idem. - prop on, xray off: return closest hit if it matches prop, no hit otherwise. - prop on, xray on : return closest hit matching prop or no hit if there is no object matching prop on the full extend of the ray. - The L{KX_PolyProxy} 4th element of the return tuple when poly=1 allows to retrieve information on the polygon hit by the ray. - If there is no hit or the hit object is not a static mesh, None is returned as 4th element. - - The ray ignores collision-free objects and faces that dont have the collision flag enabled, you can however use ghost objects. - - @param objto: [x,y,z] or object to which the ray is casted - @type objto: L{KX_GameObject} or 3-tuple - @param objfrom: [x,y,z] or object from which the ray is casted; None or omitted => use self object center - @type objfrom: L{KX_GameObject} or 3-tuple or None - @param dist: max distance to look (can be negative => look behind); 0 or omitted => detect up to to - @type dist: float - @param prop: property name that object must have; can be omitted => detect any object - @type prop: string - @param face: normal option: 1=>return face normal; 0 or omitted => normal is oriented towards origin - @type face: int - @param xray: X-ray option: 1=>skip objects that don't match prop; 0 or omitted => stop on first object - @type xray: int - @param poly: polygon option: 1=>return value is a 4-tuple and the 4th element is a L{KX_PolyProxy} - @type poly: int - @rtype: 3-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz)) - or 4-tuple (L{KX_GameObject}, 3-tuple (x,y,z), 3-tuple (nx,ny,nz), L{KX_PolyProxy}) - @return: (object,hitpoint,hitnormal) or (object,hitpoint,hitnormal,polygon) - If no hit, returns (None,None,None) or (None,None,None,None) - If the object hit is not a static mesh, polygon is None - """ - def setCollisionMargin(margin): - """ - Set the objects collision margin. - - note: If this object has no physics controller (a physics ID of zero), this function will raise RuntimeError. - - @type margin: float - @param margin: the collision margin distance in blender units. - """ - def sendMessage(subject, body="", to=""): - """ - Sends a message. - - @param subject: The subject of the message - @type subject: string - @param body: The body of the message (optional) - @type body: string - @param to: The name of the object to send the message to (optional) - @type to: string - """ diff --git a/source/gameengine/PyDoc/KX_IpoActuator.py b/source/gameengine/PyDoc/KX_IpoActuator.py deleted file mode 100644 index ebc0b855f0a..00000000000 --- a/source/gameengine/PyDoc/KX_IpoActuator.py +++ /dev/null @@ -1,124 +0,0 @@ -# $Id$ -# Documentation for KX_IpoActuator -from SCA_IActuator import * - -class KX_IpoActuator(SCA_IActuator): - """ - IPO actuator activates an animation. - - @ivar startFrame: Start frame. - @type startFrame: float - @ivar endFrame: End frame. - @type endFrame: float - @ivar propName: Use this property to define the Ipo position - @type propName: string - @ivar framePropName: Assign this property this action current frame number - @type framePropName: string - @ivar type: Play mode for the ipo. (In GameLogic.KX_IPOACT_PLAY, KX_IPOACT_PINGPONG, KX_IPOACT_FLIPPER, KX_IPOACT_LOOPSTOP, KX_IPOACT_LOOPEND, KX_IPOACT_FROM_PROP) - @type type: int - @ivar useIpoAsForce: Apply Ipo as a global or local force depending on the local option (dynamic objects only) - @type useIpoAsForce: bool - @ivar useIpoAdd: Ipo is added to the current loc/rot/scale in global or local coordinate according to Local flag - @type useIpoAdd: bool - @ivar useIpoLocal: Let the ipo acts in local coordinates, used in Force and Add mode. - @type useIpoLocal: bool - @ivar useChildren: Update IPO on all children Objects as well - @type useChildren: bool - """ - def set(mode, startframe, endframe, force): - """ - Sets the properties of the actuator. (B{deprecated}) - - @param mode: "Play", "PingPong", "Flipper", "LoopStop", "LoopEnd" or "FromProp" - @type mode: string - @param startframe: first frame to use - @type startframe: integer - @param endframe: last frame to use - @type endframe: integer - @param force: special mode - @type force: integer (0=normal, 1=interpret location as force, 2=additive) - """ - def setProperty(property): - """ - Sets the name of the property to be used in FromProp mode. (B{deprecated}) - - @type property: string - """ - def setStart(startframe): - """ - Sets the frame from which the IPO starts playing. (B{deprecated}) - - @type startframe: integer - """ - def getStart(): - """ - Returns the frame from which the IPO starts playing. (B{deprecated}) - - @rtype: integer - """ - def setEnd(endframe): - """ - Sets the frame at which the IPO stops playing. (B{deprecated}) - - @type endframe: integer - """ - def getEnd(): - """ - Returns the frame at which the IPO stops playing. (B{deprecated}) - - @rtype: integer - """ - def setIpoAsForce(force): - """ - Set whether to interpret the ipo as a force rather than a displacement. (B{deprecated}) - - @type force: boolean - @param force: KX_TRUE or KX_FALSE - """ - def getIpoAsForce(): - """ - Returns whether to interpret the ipo as a force rather than a displacement. (B{deprecated}) - - @rtype: boolean - """ - def setIpoAdd(add): - """ - Set whether to interpret the ipo as additive rather than absolute. (B{deprecated}) - - @type add: boolean - @param add: KX_TRUE or KX_FALSE - """ - def getIpoAdd(): - """ - Returns whether to interpret the ipo as additive rather than absolute. (B{deprecated}) - - @rtype: boolean - """ - def setType(mode): - """ - Sets the operation mode of the actuator. (B{deprecated}) - - @param mode: KX_IPOACT_PLAY, KX_IPOACT_PINGPONG, KX_IPOACT_FLIPPER, KX_IPOACT_LOOPSTOP, KX_IPOACT_LOOPEND - @type mode: string - """ - def getType(): - """ - Returns the operation mode of the actuator. (B{deprecated}) - - @rtype: integer - @return: KX_IPOACT_PLAY, KX_IPOACT_PINGPONG, KX_IPOACT_FLIPPER, KX_IPOACT_LOOPSTOP, KX_IPOACT_LOOPEND - """ - def setForceIpoActsLocal(local): - """ - Set whether to apply the force in the object's local - coordinates rather than the world global coordinates. (B{deprecated}) - - @param local: Apply the ipo-as-force in the object's local - coordinates? (KX_TRUE, KX_FALSE) - @type local: boolean - """ - def getForceIpoActsLocal(): - """ - Return whether to apply the force in the object's local - coordinates rather than the world global coordinates. (B{deprecated}) - """ diff --git a/source/gameengine/PyDoc/KX_LightObject.py b/source/gameengine/PyDoc/KX_LightObject.py deleted file mode 100644 index 8cc1787887b..00000000000 --- a/source/gameengine/PyDoc/KX_LightObject.py +++ /dev/null @@ -1,45 +0,0 @@ -# $Id$ -# Documentation for Light game objects. -from KX_GameObject import * - -class KX_LightObject(KX_GameObject): - """ - A Light object. - - Example: - - # Turn on a red alert light. - import GameLogic - - co = GameLogic.getCurrentController() - light = co.getOwner() - - light.energy = 1.0 - light.colour = [1.0, 0.0, 0.0] - - @group Constants: NORMAL, SPOT, SUN - @ivar SPOT: A spot light source. See attribute 'type' - @ivar SUN: A point light source with no attenuation. See attribute 'type' - @ivar NORMAL: A point light source. See attribute 'type' - - @ivar type: The type of light - must be SPOT, SUN or NORMAL - @ivar layer: The layer mask that this light affects object on. - @type layer: bitfield - @ivar energy: The brightness of this light. - @type energy: float - @ivar distance: The maximum distance this light can illuminate. (SPOT and NORMAL lights only) - @type distance: float - @ivar colour: The colour of this light. Black = [0.0, 0.0, 0.0], White = [1.0, 1.0, 1.0] - @type colour: list [r, g, b] - @ivar color: Synonym for colour. - @ivar lin_attenuation: The linear component of this light's attenuation. (SPOT and NORMAL lights only) - @type lin_attenuation: float - @ivar quad_attenuation: The quadratic component of this light's attenuation (SPOT and NORMAL lights only) - @type quad_attenuation: float - @ivar spotsize: The cone angle of the spot light, in degrees. (float) (SPOT lights only) - 0.0 <= spotsize <= 180.0. Spotsize = 360.0 is also accepted. - @ivar spotblend: Specifies the intensity distribution of the spot light. (float) (SPOT lights only) - Higher values result in a more focused light source. - 0.0 <= spotblend <= 1.0. - - """ diff --git a/source/gameengine/PyDoc/KX_MeshProxy.py b/source/gameengine/PyDoc/KX_MeshProxy.py deleted file mode 100644 index e8839ac484c..00000000000 --- a/source/gameengine/PyDoc/KX_MeshProxy.py +++ /dev/null @@ -1,132 +0,0 @@ -# $Id$ -# Documentation for KX_MeshProxy - -class KX_MeshProxy: - """ - A mesh object. - - You can only change the vertex properties of a mesh object, not the mesh topology. - - To use mesh objects effectively, you should know a bit about how the game engine handles them. - 1. Mesh Objects are converted from Blender at scene load. - 2. The Converter groups polygons by Material. This means they can be sent to the - renderer efficiently. A material holds: - 1. The texture. - 2. The Blender material. - 3. The Tile properties - 4. The face properties - (From the "Texture Face" panel) - 5. Transparency & z sorting - 6. Light layer - 7. Polygon shape (triangle/quad) - 8. Game Object - 3. Verticies will be split by face if necessary. Verticies can only be shared between - faces if: - 1. They are at the same position - 2. UV coordinates are the same - 3. Their normals are the same (both polygons are "Set Smooth") - 4. They are the same colour - For example: a cube has 24 verticies: 6 faces with 4 verticies per face. - - The correct method of iterating over every L{KX_VertexProxy} in a game object:: - import GameLogic - - co = GameLogic.getcurrentController() - obj = co.getOwner() - - m_i = 0 - mesh = obj.getMesh(m_i) # There can be more than one mesh... - while mesh != None: - for mat in range(mesh.getNumMaterials()): - for v_index in range(mesh.getVertexArrayLength(mat)): - vertex = mesh.getVertex(mat, v_index) - # Do something with vertex here... - # ... eg: colour the vertex red. - vertex.colour = [1.0, 0.0, 0.0, 1.0] - m_i += 1 - mesh = obj.getMesh(m_i) - - @ivar materials: - @type materials: list of L{KX_BlenderMaterial} or L{KX_PolygonMaterial} types - - @ivar numPolygons: - @type numPolygons: integer - - @ivar numMaterials: - @type numMaterials: integer - """ - - def getNumMaterials(): - """ - Gets the number of materials associated with this object. - - @rtype: integer - """ - - def getMaterialName(matid): - """ - Gets the name of the specified material. - - @type matid: integer - @param matid: the specified material. - @rtype: string - @return: the attached material name. - """ - def getTextureName(matid): - """ - Gets the name of the specified material's texture. - - @type matid: integer - @param matid: the specified material - @rtype: string - @return: the attached material's texture name. - """ - def getVertexArrayLength(matid): - """ - Gets the length of the vertex array associated with the specified material. - - There is one vertex array for each material. - - @type matid: integer - @param matid: the specified material - @rtype: integer - @return: the number of verticies in the vertex array. - """ - def getVertex(matid, index): - """ - Gets the specified vertex from the mesh object. - - @type matid: integer - @param matid: the specified material - @type index: integer - @param index: the index into the vertex array. - @rtype: L{KX_VertexProxy} - @return: a vertex object. - """ - def getNumPolygons(): - """ - Returns the number of polygon in the mesh. - - @rtype: integer - """ - def getPolygon(index): - """ - Gets the specified polygon from the mesh. - - @type index: integer - @param index: polygon number - @rtype: L{KX_PolyProxy} - @return: a polygon object. - """ - def reinstancePhysicsMesh(): - """ - Updates the physics system with the changed mesh. - - A mesh must have only one material with collision flags, - and have all collision primitives in one vertex array (ie. < 65535 verts) and - be either a polytope or polyheder mesh. If you don't get a warning in the - console when the collision type is polytope, the mesh is suitable for reinstance. - - @rtype: boolean - @return: True if reinstance succeeded, False if it failed. - """ - diff --git a/source/gameengine/PyDoc/KX_MouseFocusSensor.py b/source/gameengine/PyDoc/KX_MouseFocusSensor.py deleted file mode 100644 index 24f7716218b..00000000000 --- a/source/gameengine/PyDoc/KX_MouseFocusSensor.py +++ /dev/null @@ -1,67 +0,0 @@ -# $Id$ -# Documentation for KX_MouseFocusSensor -from SCA_MouseSensor import * - -class KX_MouseFocusSensor(SCA_MouseSensor): - """ - The mouse focus sensor detects when the mouse is over the current game object. - - The mouse focus sensor works by transforming the mouse coordinates from 2d device - space to 3d space then raycasting away from the camera. - - @ivar raySource: The worldspace source of the ray (the view position) - @type raySource: list (vector of 3 floats) - @ivar rayTarget: The worldspace target of the ray. - @type rayTarget: list (vector of 3 floats) - @ivar rayDirection: The L{rayTarget} - L{raySource} normalized. - @type rayDirection: list (normalized vector of 3 floats) - @ivar hitObject: the last object the mouse was over. - @type hitObject: L{KX_GameObject<KX_GameObject.KX_GameObject>} or None - @ivar hitPosition: The worldspace position of the ray intersecton. - @type hitPosition: list (vector of 3 floats) - @ivar hitNormal: the worldspace normal from the face at point of intersection. - @type hitNormal: list (normalized vector of 3 floats) - """ - - def getHitNormal(): - """ - Returns the normal (in worldcoordinates) at the point of collision where the object was hit by this ray. (B{deprecated}) - - @rtype: list [x, y, z] - @return: the ray collision normal. - """ - def getHitObject(): - """ - Returns the object that was hit by this ray or None. (B{deprecated}) - - @rtype: L{KX_GameObject} or None - @return: the collision object. - """ - def getHitPosition(): - """ - Returns the position (in worldcoordinates) at the point of collision where the object was hit by this ray. (B{deprecated}) - - @rtype: list [x, y, z] - @return: the ray collision position. - """ - def getRayDirection(): - """ - Returns the normalized direction (in worldcoordinates) of the ray cast by the mouse. (B{deprecated}) - - @rtype: list [x, y, z] - @return: the ray direction. - """ - def getRaySource(): - """ - Returns the position (in worldcoordinates) the ray was cast from by the mouse. (B{deprecated}) - - @rtype: list [x, y, z] - @return: the ray source. - """ - def getRayTarget(): - """ - Returns the target of the ray (in worldcoordinates) that seeks the focus object. (B{deprecated}) - - @rtype: list [x, y, z] - @return: the ray target. - """
\ No newline at end of file diff --git a/source/gameengine/PyDoc/KX_NearSensor.py b/source/gameengine/PyDoc/KX_NearSensor.py deleted file mode 100644 index a8c408827fe..00000000000 --- a/source/gameengine/PyDoc/KX_NearSensor.py +++ /dev/null @@ -1,14 +0,0 @@ -# $Id$ -# Documentation for KX_NearSensor -from KX_TouchSensor import * - -class KX_NearSensor(KX_TouchSensor): - """ - A near sensor is a specialised form of touch sensor. - - @ivar distance: The near sensor activates when an object is within this distance. - @type distance: float - @ivar resetDistance: The near sensor deactivates when the object exceeds this distance. - @type resetDistance: float - """ - diff --git a/source/gameengine/PyDoc/KX_NetworkMessageActuator.py b/source/gameengine/PyDoc/KX_NetworkMessageActuator.py deleted file mode 100644 index c9f48d47eb8..00000000000 --- a/source/gameengine/PyDoc/KX_NetworkMessageActuator.py +++ /dev/null @@ -1,49 +0,0 @@ -# $Id$ -# Documentation for KX_NetworkMessageActuator -from SCA_IActuator import * - -class KX_NetworkMessageActuator(SCA_IActuator): - """ - Message Actuator - - @ivar propName: Messages will only be sent to objects with the given property name. - @type propName: string - @ivar subject: The subject field of the message. - @type subject: string - @ivar body: The body of the message. - @type body: string - @ivar usePropBody: Send a property instead of a regular body message. - @type usePropBody: boolean - """ - def setToPropName(name): - """ - DEPRECATED: Use the propName property instead. - Messages will only be sent to objects with the given property name. - - @type name: string - """ - def setSubject(subject): - """ - DEPRECATED: Use the subject property instead. - Sets the subject field of the message. - - @type subject: string - """ - def setBodyType(bodytype): - """ - DEPRECATED: Use the usePropBody property instead. - Sets the type of body to send. - - @type bodytype: boolean - @param bodytype: True to send the value of a property, False to send the body text. - """ - def setBody(body): - """ - DEPRECATED: Use the body property instead. - Sets the message body. - - @type body: string - @param body: if the body type is True, this is the name of the property to send. - if the body type is False, this is the text to send. - """ - diff --git a/source/gameengine/PyDoc/KX_NetworkMessageSensor.py b/source/gameengine/PyDoc/KX_NetworkMessageSensor.py deleted file mode 100644 index 0fecad58437..00000000000 --- a/source/gameengine/PyDoc/KX_NetworkMessageSensor.py +++ /dev/null @@ -1,60 +0,0 @@ -# $Id$ -# Documentation for KX_NetworkMessageSensor -from SCA_ISensor import * - -class KX_NetworkMessageSensor(SCA_ISensor): - """ - The Message Sensor logic brick. - - Currently only loopback (local) networks are supported. - - @ivar subject: The subject the sensor is looking for. - @type subject: string - @ivar frameMessageCount: The number of messages received since the last frame. - (Read-only) - @type framemessageCount: int - @ivar subjects: The list of message subjects received. (Read-only) - @type subjects: list of strings - @ivar bodies: The list of message bodies received. (Read-only) - @type bodies: list of strings - """ - - - def setSubjectFilterText(subject): - """ - DEPRECATED: Use the subject property instead. - Change the message subject text that this sensor is listening to. - - @type subject: string - @param subject: the new message subject to listen for. - """ - - def getFrameMessageCount(): - """ - DEPRECATED: Use the frameMessageCount property instead. - Get the number of messages received since the last frame. - - @rtype: integer - """ - def getBodies(): - """ - DEPRECATED: Use the bodies property instead. - Gets the list of message bodies. - - @rtype: list - """ - def getSubject(): - """ - DEPRECATED: Use the subject property instead. - Gets the message subject this sensor is listening for from the Subject: field. - - @rtype: string - """ - def getSubjects(): - """ - DEPRECATED: Use the subjects property instead. - Gets the list of message subjects received. - - @rtype: list - """ -
\ No newline at end of file diff --git a/source/gameengine/PyDoc/KX_ObjectActuator.py b/source/gameengine/PyDoc/KX_ObjectActuator.py deleted file mode 100644 index b7b76473292..00000000000 --- a/source/gameengine/PyDoc/KX_ObjectActuator.py +++ /dev/null @@ -1,250 +0,0 @@ -# $Id$ -# Documentation for KX_ObjectActuator -from SCA_IActuator import * - -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(): - """ - Returns the force applied by the actuator. - - @rtype: list [fx, fy, fz, local] - @return: A four item list, containing the vector force, and a flag specifying whether the force is local. - """ - def setForce(fx, fy, fz, local): - """ - Sets the force applied by the actuator. - - @type fx: float - @param fx: the x component of the force. - @type fy: float - @param fy: the z component of the force. - @type fz: float - @param fz: the z component of the force. - @type local: boolean - @param local: - False: the force is applied in world coordinates. - - True: the force is applied in local coordinates. - """ - def getTorque(): - """ - Returns the torque applied by the actuator. - - @rtype: list [S{Tau}x, S{Tau}y, S{Tau}z, local] - @return: A four item list, containing the vector torque, and a flag specifying whether - the torque is applied in local coordinates (True) or world coordinates (False) - """ - def setTorque(tx, ty, tz, local): - """ - Sets the torque applied by the actuator. - - @type tx: float - @param tx: the x component of the torque. - @type ty: float - @param ty: the z component of the torque. - @type tz: float - @param tz: the z component of the torque. - @type local: boolean - @param local: - False: the torque is applied in world coordinates. - - True: the torque is applied in local coordinates. - """ - def getDLoc(): - """ - Returns the displacement vector applied by the actuator. - - @rtype: list [dx, dy, dz, local] - @return: A four item list, containing the vector displacement, and whether - the displacement is applied in local coordinates (True) or world - coordinates (False) - """ - def setDLoc(dx, dy, dz, local): - """ - Sets the displacement vector applied by the actuator. - - Since the displacement is applied every frame, you must adjust the displacement - based on the frame rate, or you game experience will depend on the player's computer - speed. - - @type dx: float - @param dx: the x component of the displacement vector. - @type dy: float - @param dy: the z component of the displacement vector. - @type dz: float - @param dz: the z component of the displacement vector. - @type local: boolean - @param local: - False: the displacement vector is applied in world coordinates. - - True: the displacement vector is applied in local coordinates. - """ - def getDRot(): - """ - Returns the angular displacement vector applied by the actuator. - - @rtype: list [dx, dy, dz, local] - @return: A four item list, containing the angular displacement vector, and whether - the displacement is applied in local coordinates (True) or world - coordinates (False) - """ - def setDRot(dx, dy, dz, local): - """ - Sets the angular displacement vector applied by the actuator. - - Since the displacement is applied every frame, you must adjust the displacement - based on the frame rate, or you game experience will depend on the player's computer - speed. - - @type dx: float - @param dx: the x component of the angular displacement vector. - @type dy: float - @param dy: the z component of the angular displacement vector. - @type dz: float - @param dz: the z component of the angular displacement vector. - @type local: boolean - @param local: - False: the angular displacement vector is applied in world coordinates. - - True: the angular displacement vector is applied in local coordinates. - """ - 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) - """ - 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. - @type vy: float - @param vy: the z component of the velocity vector. - @type vz: float - @param vz: the z component of the velocity vector. - @type local: boolean - @param local: - False: the velocity vector is in world coordinates. - - True: the velocity vector is in local coordinates. - """ - def getAngularVelocity(): - """ - Returns the angular velocity applied by the actuator. - - @rtype: list [S{omega}x, S{omega}y, S{omega}z, local] - @return: A four item list, containing the vector velocity, and whether - the velocity is applied in local coordinates (True) or world - coordinates (False) - """ - def setAngularVelocity(wx, wy, wz, local): - """ - Sets the angular velocity applied by the actuator. - - @type wx: float - @param wx: the x component of the velocity vector. - @type wy: float - @param wy: the z component of the velocity vector. - @type wz: float - @param wz: 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. - """ - 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_ParentActuator.py b/source/gameengine/PyDoc/KX_ParentActuator.py deleted file mode 100644 index 2f5d9515d0b..00000000000 --- a/source/gameengine/PyDoc/KX_ParentActuator.py +++ /dev/null @@ -1,27 +0,0 @@ -# $Id$ -# Documentation for KX_ParentActuator -from SCA_IActuator import * - -class KX_ParentActuator(SCA_IActuator): - """ - The parent actuator can set or remove an objects parent object. - @ivar object: the object this actuator sets the parent too. - @type object: KX_GameObject or None - """ - def setObject(object): - """ - DEPRECATED: Use the object property. - Sets the object to set as parent. - - Object can be either a L{KX_GameObject} or the name of the object. - - @type object: L{KX_GameObject}, string or None - """ - def getObject(name_only = 1): - """ - DEPRECATED: Use the object property. - Returns the name of the object to change to. - @type name_only: bool - @param name_only: optional argument, when 0 return a KX_GameObject - @rtype: string, KX_GameObject or None if no object is set - """ diff --git a/source/gameengine/PyDoc/KX_PhysicsObjectWrapper.py b/source/gameengine/PyDoc/KX_PhysicsObjectWrapper.py deleted file mode 100644 index 2171cf4c7b6..00000000000 --- a/source/gameengine/PyDoc/KX_PhysicsObjectWrapper.py +++ /dev/null @@ -1,47 +0,0 @@ -class KX_PhysicsObjectWrapper: # (PyObjectPlus) - """ - KX_PhysicsObjectWrapper - - All placeholders have a __ prefix - """ - def __setActive(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - - def __setAngularVelocity(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setLinearVelocity(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setPosition(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ diff --git a/source/gameengine/PyDoc/KX_PolyProxy.py b/source/gameengine/PyDoc/KX_PolyProxy.py deleted file mode 100644 index bcd42c2ac2e..00000000000 --- a/source/gameengine/PyDoc/KX_PolyProxy.py +++ /dev/null @@ -1,100 +0,0 @@ -# $Id$ -# Documentation for the polygon proxy class - -class KX_PolyProxy: - """ - A polygon holds the index of the vertex forming the poylgon. - - Note: - The polygon attributes are read-only, you need to retrieve the vertex proxy if you want - to change the vertex settings. - - @ivar matname: The name of polygon material, empty if no material. - @type matname: string - @ivar material: The material of the polygon - @type material: L{KX_PolygonMaterial} or KX_BlenderMaterial - @ivar texture: The texture name of the polygon. - @type texture: string - @ivar matid: The material index of the polygon, use this to retrieve vertex proxy from mesh proxy - @type matid: integer - @ivar v1: vertex index of the first vertex of the polygon, use this to retrieve vertex proxy from mesh proxy - @type v1: integer - @ivar v2: vertex index of the second vertex of the polygon, use this to retrieve vertex proxy from mesh proxy - @type v2: integer - @ivar v3: vertex index of the third vertex of the polygon, use this to retrieve vertex proxy from mesh proxy - @type v3: integer - @ivar v4: vertex index of the fourth vertex of the polygon, 0 if polygon has only 3 vertex - use this to retrieve vertex proxy from mesh proxy - @type v4: integer - @ivar visible: visible state of the polygon: 1=visible, 0=invisible - @type visible: integer - @ivar collide: collide state of the polygon: 1=receives collision, 0=collision free. - @type collide: integer - """ - - def getMaterialName(): - """ - Returns the polygon material name with MA prefix - - @rtype: string - @return: material name - """ - def getMaterial(): - """ - Returns the polygon material - - @rtype: L{KX_PolygonMaterial} or KX_BlenderMaterial - """ - def getTextureName(): - """ - Returns the polygon texture name - - @rtype: string - @return: texture name - """ - def getMaterialIndex(): - """ - Returns the material bucket index of the polygon. - This index and the ones returned by getVertexIndex() are needed to retrieve the vertex proxy from L{KX_MeshProxy}. - - @rtype: integer - @return: the material index in the mesh - """ - def getNumVertex(): - """ - Returns the number of vertex of the polygon. - - @rtype: integer - @return: number of vertex, 3 or 4. - """ - def isVisible(): - """ - Returns whether the polygon is visible or not - - @rtype: integer - @return: 0=invisible, 1=visible - """ - def isCollider(): - """ - Returns whether the polygon is receives collision or not - - @rtype: integer - @return: 0=collision free, 1=receives collision - """ - def getVertexIndex(vertex): - """ - Returns the mesh vertex index of a polygon vertex - This index and the one returned by getMaterialIndex() are needed to retrieve the vertex proxy from L{KX_MeshProxy}. - - @type vertex: integer - @param vertex: index of the vertex in the polygon: 0->3 - @rtype: integer - @return: mesh vertex index - """ - def getMesh(): - """ - Returns a mesh proxy - - @rtype: L{KX_MeshProxy} - @return: mesh proxy - """ diff --git a/source/gameengine/PyDoc/KX_PolygonMaterial.py b/source/gameengine/PyDoc/KX_PolygonMaterial.py deleted file mode 100644 index cfc4257f95d..00000000000 --- a/source/gameengine/PyDoc/KX_PolygonMaterial.py +++ /dev/null @@ -1,281 +0,0 @@ -# $Id$ - -class KX_PolygonMaterial: - """ - This is the interface to materials in the game engine. - - Materials define the render state to be applied to mesh objects. - - Warning: Some of the methods/variables are CObjects. If you mix these up, - you will crash blender. - - This example requires: - - PyOpenGL http://pyopengl.sourceforge.net/ - - GLEWPy http://glewpy.sourceforge.net/ - Example:: - - import GameLogic - import OpenGL - from OpenGL.GL import * - from OpenGL.GLU import * - import glew - from glew import * - - glewInit() - - vertex_shader = \"\"\" - - void main(void) - { - gl_Position = ftransform(); - } - \"\"\" - - fragment_shader =\"\"\" - - void main(void) - { - gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); - } - \"\"\" - - class MyMaterial: - def __init__(self): - self.pass_no = 0 - # Create a shader - self.m_program = glCreateProgramObjectARB() - # Compile the vertex shader - self.shader(GL_VERTEX_SHADER_ARB, (vertex_shader)) - # Compile the fragment shader - self.shader(GL_FRAGMENT_SHADER_ARB, (fragment_shader)) - # Link the shaders together - self.link() - - def PrintInfoLog(self, tag, object): - \"\"\" - PrintInfoLog prints the GLSL compiler log - \"\"\" - print "Tag: def PrintGLError(self, tag = ""): - - def PrintGLError(self, tag = ""): - \"\"\" - Prints the current GL error status - \"\"\" - if len(tag): - print tag - err = glGetError() - if err != GL_NO_ERROR: - print "GL Error: %s\\n"%(gluErrorString(err)) - - def shader(self, type, shaders): - \"\"\" - shader compiles a GLSL shader and attaches it to the current - program. - - type should be either GL_VERTEX_SHADER_ARB or GL_FRAGMENT_SHADER_ARB - shaders should be a sequence of shader source to compile. - \"\"\" - # Create a shader object - shader_object = glCreateShaderObjectARB(type) - - # Add the source code - glShaderSourceARB(shader_object, len(shaders), shaders) - - # Compile the shader - glCompileShaderARB(shader_object) - - # Print the compiler log - self.PrintInfoLog("vertex shader", shader_object) - - # Check if compiled, and attach if it did - compiled = glGetObjectParameterivARB(shader_object, GL_OBJECT_COMPILE_STATUS_ARB) - if compiled: - glAttachObjectARB(self.m_program, shader_object) - - # Delete the object (glAttachObjectARB makes a copy) - glDeleteObjectARB(shader_object) - - # print the gl error log - self.PrintGLError() - - def link(self): - \"\"\" - Links the shaders together. - \"\"\" - # clear error indicator - glGetError() - - glLinkProgramARB(self.m_program) - - self.PrintInfoLog("link", self.m_program) - - linked = glGetObjectParameterivARB(self.m_program, GL_OBJECT_LINK_STATUS_ARB) - if not linked: - print "Shader failed to link" - return - - glValidateProgramARB(self.m_program) - valid = glGetObjectParameterivARB(self.m_program, GL_OBJECT_VALIDATE_STATUS_ARB) - if not valid: - print "Shader failed to validate" - return - - def activate(self, rasty, cachingInfo, mat): - self.pass_no+=1 - if (self.pass_no == 1): - glDisable(GL_COLOR_MATERIAL) - glUseProgramObjectARB(self.m_program) - return True - - glEnable(GL_COLOR_MATERIAL) - glUseProgramObjectARB(0) - self.pass_no = 0 - return False - - obj = GameLogic.getCurrentController().getOwner() - - mesh = obj.getMesh(0) - - for mat in mesh.materials: - mat.setCustomMaterial(MyMaterial()) - print mat.texture - - @ivar texture: Texture name - @type texture: string (read only) - - @ivar gl_texture: OpenGL texture handle (eg for glBindTexture(GL_TEXTURE_2D, gl_texture) - @type gl_texture: integer (read only) - - @ivar material: Material name - @type material: string (read only) - - @ivar tface: Texture face properties - @type tface: CObject (read only) - - @ivar tile: Texture is tiling - @type tile: boolean - @ivar tilexrep: Number of tile repetitions in x direction. - @type tilexrep: integer - @ivar tileyrep: Number of tile repetitions in y direction. - @type tileyrep: integer - - @ivar drawingmode: Drawing mode for the material. - - 2 (drawingmode & 4) Textured - - 4 (drawingmode & 16) Light - - 14 (drawingmode & 16384) 3d Polygon Text - @type drawingmode: bitfield - - @ivar transparent: This material is transparent. All meshes with this - material will be rendered after non transparent meshes from back - to front. - @type transparent: boolean - - @ivar zsort: Transparent polygons in meshes with this material will be sorted back to - front before rendering. - Non-Transparent polygons will be sorted front to back before rendering. - @type zsort: boolean - - @ivar lightlayer: Light layers this material affects. - @type lightlayer: bitfield. - - @ivar triangle: Mesh data with this material is triangles. It's probably not safe to change this. - @type triangle: boolean - - @ivar diffuse: The diffuse colour of the material. black = [0.0, 0.0, 0.0] white = [1.0, 1.0, 1.0] - @type diffuse: list [r, g, b] - @ivar specular: The specular colour of the material. black = [0.0, 0.0, 0.0] white = [1.0, 1.0, 1.0] - @type specular: list [r, g, b] - @ivar shininess: The shininess (specular exponent) of the material. 0.0 <= shininess <= 128.0 - @type shininess: float - @ivar specularity: The amount of specular of the material. 0.0 <= specularity <= 1.0 - @type specularity: float - """ - def updateTexture(tface, rasty): - """ - Updates a realtime animation. - - @param tface: Texture face (eg mat.tface) - @type tface: CObject - @param rasty: Rasterizer - @type rasty: CObject - """ - def setTexture(tface): - """ - Sets texture render state. - - Example:: - mat.setTexture(mat.tface) - - @param tface: Texture face - @type tface: CObject - """ - def activate(rasty, cachingInfo): - """ - Sets material parameters for this object for rendering. - - Material Parameters set: - 1. Texture - 2. Backface culling - 3. Line drawing - 4. Specular Colour - 5. Shininess - 6. Diffuse Colour - 7. Polygon Offset. - - @param rasty: Rasterizer instance. - @type rasty: CObject - @param cachingInfo: Material cache instance. - @type cachingInfo: CObject - """ - def setCustomMaterial(material): - """ - Sets the material state setup object. - - Using this method, you can extend or completely replace the gameengine material - to do your own advanced multipass effects. - - Use this method to register your material class. Instead of the normal material, - your class's activate method will be called just before rendering the mesh. - This should setup the texture, material, and any other state you would like. - It should return True to render the mesh, or False if you are finished. You should - clean up any state Blender does not set before returning False. - - Activate Method Definition:: - def activate(self, rasty, cachingInfo, material): - - Example:: - class PyMaterial: - def __init__(self): - self.pass_no = -1 - - def activate(self, rasty, cachingInfo, material): - # Activate the material here. - # - # The activate method will be called until it returns False. - # Every time the activate method returns True the mesh will - # be rendered. - # - # rasty is a CObject for passing to material.updateTexture() - # and material.activate() - # cachingInfo is a CObject for passing to material.activate() - # material is the KX_PolygonMaterial instance this material - # was added to - - # default material properties: - self.pass_no += 1 - if self.pass_no == 0: - material.activate(rasty, cachingInfo) - # Return True to do this pass - return True - - # clean up and return False to finish. - self.pass_no = -1 - return False - - # Create a new Python Material and pass it to the renderer. - mat.setCustomMaterial(PyMaterial()) - - @param material: The material object. - @type material: instance - """ - diff --git a/source/gameengine/PyDoc/KX_RadarSensor.py b/source/gameengine/PyDoc/KX_RadarSensor.py deleted file mode 100644 index b68bf4ea0f3..00000000000 --- a/source/gameengine/PyDoc/KX_RadarSensor.py +++ /dev/null @@ -1,49 +0,0 @@ -# $Id$ -# Documentation for KX_RadarSensor -from KX_NearSensor import * - -class KX_RadarSensor(KX_NearSensor): - """ - Radar sensor is a near sensor with a conical sensor object. - - @ivar coneOrigin: The origin of the cone with which to test. The origin - is in the middle of the cone. - (Read only) - @type coneOrigin: list of floats [x, y, z] - @ivar coneTarget: The center of the bottom face of the cone with which to test. - (Read only) - @type coneTarget: list of floats [x, y, z] - @ivar distance: The height of the cone with which to test. - @type distance: float - @ivar angle: The angle of the cone (in degrees) with which to test. - @type angle: float from 0 to 360 - @ivar axis: The axis on which the radar cone is cast - @type axis: int from 0 to 5 - KX_RADAR_AXIS_POS_X, KX_RADAR_AXIS_POS_Y, KX_RADAR_AXIS_POS_Z, - KX_RADAR_AXIS_NEG_X, KX_RADAR_AXIS_NEG_Y, KX_RADAR_AXIS_NEG_Z - """ - - - #--The following methods are deprecated, please use properties instead. - def getConeOrigin(): - """ - Returns the origin of the cone with which to test. The origin - is in the middle of the cone. - - @rtype: list [x, y, z] - """ - - def getConeTarget(): - """ - Returns the center of the bottom face of the cone with which to test. - - @rtype: list [x, y, z] - """ - - def getConeHeight(): - """ - Returns the height of the cone with which to test. - - @rtype: float - """ - diff --git a/source/gameengine/PyDoc/KX_RaySensor.py b/source/gameengine/PyDoc/KX_RaySensor.py deleted file mode 100644 index b9de54e92a5..00000000000 --- a/source/gameengine/PyDoc/KX_RaySensor.py +++ /dev/null @@ -1,58 +0,0 @@ -# $Id$ -# Documentation for KX_RaySensor -from SCA_ISensor import * - -class KX_RaySensor(SCA_ISensor): - """ - A ray sensor detects the first object in a given direction. - - @ivar property: The property the ray is looking for. - @type property: string - @ivar range: The distance of the ray. - @type range: float - @ivar useMaterial: Whether or not to look for a material (false = property) - @type useMaterial: boolean - @ivar useXRay: Whether or not to use XRay. - @type useXRay: boolean - @ivar hitObject: The game object that was hit by the ray. (Read-only) - @type hitObject: KX_GameObject - @ivar hitPosition: The position (in worldcoordinates) where the object was hit by the ray. (Read-only) - @type hitPosition: list [x, y, z] - @ivar hitNormal: The normal (in worldcoordinates) of the object at the location where the object was hit by the ray. (Read-only) - @type hitNormal: list [x, y, z] - @ivar rayDirection: The direction from the ray (in worldcoordinates). (Read-only) - @type rayDirection: list [x, y, z] - @ivar axis: The axis the ray is pointing on. - @type axis: int from 0 to 5 - KX_RAY_AXIS_POS_X, KX_RAY_AXIS_POS_Y, KX_RAY_AXIS_POS_Z, - KX_RAY_AXIS_NEG_X, KX_RAY_AXIS_NEG_Y, KX_RAY_AXIS_NEG_Z - """ - - def getHitObject(): - """ - DEPRECATED: Use the hitObject property instead. - Returns the game object that was hit by this ray. - - @rtype: KX_GameObject - """ - def getHitPosition(): - """ - DEPRECATED: Use the hitPosition property instead. - Returns the position (in worldcoordinates) where the object was hit by this ray. - - @rtype: list [x, y, z] - """ - def getHitNormal(): - """ - DEPRECATED: Use the hitNormal property instead. - Returns the normal (in worldcoordinates) of the object at the location where the object was hit by this ray. - - @rtype: list [nx, ny, nz] - """ - def getRayDirection(): - """ - DEPRECATED: Use the rayDirection property instead. - Returns the direction from the ray (in worldcoordinates) - - @rtype: list [dx, dy, dz] - """ diff --git a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py b/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py deleted file mode 100644 index 572b864ff0a..00000000000 --- a/source/gameengine/PyDoc/KX_SCA_AddObjectActuator.py +++ /dev/null @@ -1,118 +0,0 @@ -# $Id$ -# Documentation for KX_SCA_AddObjectActuator -from SCA_IActuator import * - -class KX_SCA_AddObjectActuator(SCA_IActuator): - """ - Edit Object Actuator (in Add Object Mode) - @ivar object: the object this actuator adds. - @type object: KX_GameObject or None - @ivar objectLastCreated: the last added object from this actuator (read only). - @type objectLastCreated: KX_GameObject or None - @ivar time: the lifetime of added objects, in frames. - @type time: integer - @ivar linearVelocity: the initial linear velocity of added objects. - @type linearVelocity: list [vx, vy, vz] - @ivar angularVelocity: the initial angular velocity of added objects. - @type angularVelocity: list [vx, vy, vz] - - @warning: An Add Object actuator will be ignored if at game start, the linked object doesn't exist - (or is empty) or the linked object is in an active layer. - - This will genereate a warning in the console: - - C{ERROR: GameObject I{OBName} has a AddObjectActuator I{ActuatorName} without object (in 'nonactive' layer)} - """ - def setObject(object): - """ - DEPRECATED: use the object property - Sets the game object to add. - - A copy of the object will be added to the scene when the actuator is activated. - - If the object does not exist, this function is ignored. - - object can either be a L{KX_GameObject} or the name of an object or None. - - @type object: L{KX_GameObject}, string or None - """ - def getObject(name_only = 0): - """ - DEPRECATED: use the object property - Returns the name of the game object to be added. - - Returns None if no game object has been assigned to be added. - @type name_only: bool - @param name_only: optional argument, when 0 return a KX_GameObject - @rtype: string, KX_GameObject or None if no object is set - """ - def setTime(time): - """ - DEPRECATED: use the time property - Sets the lifetime of added objects, in frames. - - If time == 0, the object will last forever. - - @type time: integer - @param time: The minimum value for time is 0. - """ - def getTime(): - """ - DEPRECATED: use the time property - Returns the lifetime of the added object, in frames. - - @rtype: integer - """ - def setLinearVelocity(vx, vy, vz): - """ - DEPRECATED: use the linearVelocity property - Sets the initial linear velocity of added objects. - - @type vx: float - @param vx: the x component of the initial linear velocity. - @type vy: float - @param vy: the y component of the initial linear velocity. - @type vz: float - @param vz: the z component of the initial linear velocity. - """ - def getLinearVelocity(): - """ - DEPRECATED: use the linearVelocity property - Returns the initial linear velocity of added objects. - - @rtype: list [vx, vy, vz] - """ - def setAngularVelocity(vx, vy, vz): - """ - DEPRECATED: use the angularVelocity property - Sets the initial angular velocity of added objects. - - @type vx: float - @param vx: the x component of the initial angular velocity. - @type vy: float - @param vy: the y component of the initial angular velocity. - @type vz: float - @param vz: the z component of the initial angular velocity. - """ - def getAngularVelocity(): - """ - DEPRECATED: use the angularVelocity property - Returns the initial angular velocity of added objects. - - @rtype: list [vx, vy, vz] - """ - def getLastCreatedObject(): - """ - DEPRECATED: use the objectLastCreated property - Returns the last object created by this actuator. - - @rtype: L{KX_GameObject} - @return: A L{KX_GameObject} or None if no object has been created. - """ - def instantAddObject(): - """ - Returns the last object created by this actuator. The object can then be accessed from L{objectLastCreated}. - - @rtype: None - """ - diff --git a/source/gameengine/PyDoc/KX_SCA_DynamicActuator.py b/source/gameengine/PyDoc/KX_SCA_DynamicActuator.py deleted file mode 100644 index 22da159ce71..00000000000 --- a/source/gameengine/PyDoc/KX_SCA_DynamicActuator.py +++ /dev/null @@ -1,30 +0,0 @@ -# $Id$ -# Documentation for KX_SCA_DynamicActuator -from SCA_IActuator import * - -class KX_SCA_DynamicActuator(SCA_IActuator): - """ - Dynamic Actuator. - @ivar operation: the type of operation of the actuator, 0-4 - KX_DYN_RESTORE_DYNAMICS, KX_DYN_DISABLE_DYNAMICS, - KX_DYN_ENABLE_RIGID_BODY, KX_DYN_DISABLE_RIGID_BODY, KX_DYN_SET_MASS - @type operation: integer - @ivar mass: the mass value for the KX_DYN_SET_MASS operation - @type mass: float - """ - def setOperation(operation): - """ - DEPRECATED: Use the operation property instead. - Set the type of operation when the actuator is activated: - - 0 = restore dynamics - - 1 = disable dynamics - - 2 = enable rigid body - - 3 = disable rigid body - - 4 = set mass - """ - def getOperation(): - """ - DEPRECATED: Use the operation property instead. - return the type of operation - """ - diff --git a/source/gameengine/PyDoc/KX_SCA_EndObjectActuator.py b/source/gameengine/PyDoc/KX_SCA_EndObjectActuator.py deleted file mode 100644 index 8a7c79bb52b..00000000000 --- a/source/gameengine/PyDoc/KX_SCA_EndObjectActuator.py +++ /dev/null @@ -1,11 +0,0 @@ -# $Id$ -# Documentation for KX_SCA_EndObjectActuator -from SCA_IActuator import * - -class KX_SCA_EndObjectActuator(SCA_IActuator): - """ - Edit Object Actuator (in End Object mode) - - This actuator has no python methods. - """ - diff --git a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py b/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py deleted file mode 100644 index 951c118a99a..00000000000 --- a/source/gameengine/PyDoc/KX_SCA_ReplaceMeshActuator.py +++ /dev/null @@ -1,84 +0,0 @@ -# $Id$ -# Documentation for KX_SCA_ReplaceMeshActuator -from SCA_IActuator import * - -class KX_SCA_ReplaceMeshActuator(SCA_IActuator): - """ - Edit Object actuator, in Replace Mesh mode. - - Example:: - # Level-of-detail - # Switch a game object's mesh based on its depth in the camera view. - # +----------+ +-----------+ +-------------------------------------+ - # | Always +-----+ Python +-----+ Edit Object (Replace Mesh) LOD.Mesh | - # +----------+ +-----------+ +-------------------------------------+ - import GameLogic - - # List detail meshes here - # Mesh (name, near, far) - # Meshes overlap so that they don't 'pop' when on the edge of the distance. - meshes = ((".Hi", 0.0, -20.0), - (".Med", -15.0, -50.0), - (".Lo", -40.0, -100.0) - ) - - co = GameLogic.getCurrentController() - obj = co.getOwner() - act = co.getActuator("LOD." + obj.name) - cam = GameLogic.getCurrentScene().active_camera - - def Depth(pos, plane): - return pos[0]*plane[0] + pos[1]*plane[1] + pos[2]*plane[2] + plane[3] - - # Depth is negative and decreasing further from the camera - depth = Depth(obj.position, cam.world_to_camera[2]) - - newmesh = None - curmesh = None - # Find the lowest detail mesh for depth - for mesh in meshes: - if depth < mesh[1] and depth > mesh[2]: - newmesh = mesh - if "ME" + obj.name + mesh[0] == act.getMesh(): - curmesh = mesh - - if newmesh != None and "ME" + obj.name + newmesh[0] != act.getMesh(): - # The mesh is a different mesh - switch it. - # Check the current mesh is not a better fit. - if curmesh == None or curmesh[1] < depth or curmesh[2] > depth: - act.setMesh(obj.getName() + newmesh[0]) - GameLogic.addActiveActuator(act, True) - - @warning: Replace mesh actuators will be ignored if at game start, the - named mesh doesn't exist. - - This will generate a warning in the console: - - C{ERROR: GameObject I{OBName} ReplaceMeshActuator I{ActuatorName} without object} - - @ivar mesh: L{KX_MeshProxy} or the name of the mesh that will replace the current one - Set to None to disable actuator - @type mesh: L{KX_MeshProxy} or None if no mesh is set - """ - def setMesh(name): - """ - DEPRECATED: Use the mesh property instead. - Sets the name of the mesh that will replace the current one. - When the name is None it will unset the mesh value so no action is taken. - - @type name: string or None - """ - def getMesh(): - """ - DEPRECATED: Use the mesh property instead. - Returns the name of the mesh that will replace the current one. - - Returns None if no mesh has been scheduled to be added. - - @rtype: string or None - """ - def instantReplaceMesh(): - """ - Immediately replace mesh without delay. - @rtype: None - """
\ No newline at end of file diff --git a/source/gameengine/PyDoc/KX_Scene.py b/source/gameengine/PyDoc/KX_Scene.py deleted file mode 100644 index 5dcd560ee96..00000000000 --- a/source/gameengine/PyDoc/KX_Scene.py +++ /dev/null @@ -1,85 +0,0 @@ -# $Id$ -# Documentation for KX_Scene.py - -class KX_Scene: - """ - Scene. - - The activity culling stuff is supposed to disable logic bricks when their owner gets too far - from the active camera. It was taken from some code lurking at the back of KX_Scene - who knows - what it does! - - Example:: - import GameLogic - - # get the scene - scene = GameLogic.getCurrentScene() - - # print all the objects in the scene - for obj in scene.objects: - print obj.name - - # get an object named 'Cube' - obj = scene.objects["OBCube"] - - # get the first object in the scene. - obj = scene.objects[0] - - Example:: - # Get the depth of an object in the camera view. - import GameLogic - - obj = GameLogic.getCurrentController().getOwner() - cam = GameLogic.getCurrentScene().active_camera - - # Depth is negative and decreasing further from the camera - depth = obj.position[0]*cam.world_to_camera[2][0] + obj.position[1]*cam.world_to_camera[2][1] + obj.position[2]*cam.world_to_camera[2][2] + cam.world_to_camera[2][3] - - @bug: All attributes are read only at the moment. - - @ivar name: The scene's name - @type name: string - @ivar objects: A list of objects in the scene. - @type objects: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>} - @ivar active_camera: The current active camera - @type active_camera: L{KX_Camera} - @ivar suspended: True if the scene is suspended. - @type suspended: boolean - @ivar activity_culling: True if the scene is activity culling - @type activity_culling: boolean - @ivar activity_culling_radius: The distance outside which to do activity culling. Measured in manhattan distance. - @type activity_culling_radius: float - """ - - def getLightList(): - """ - Returns the list of lights in the scene. - - @rtype: list [L{KX_LightObject}] - """ - def getObjectList(): - """ - Returns the list of objects in the scene. - - @rtype: list [L{KX_GameObject}] - """ - def getName(): - """ - Returns the name of the scene. - - @rtype: string - """ - - def addObject(object, other, time=0): - """ - Adds an object to the scene like the Add Object Actuator would, and returns the created object. - - @param object: The object to add - @type object: L{KX_GameObject} or string - @param other: The object's center to use when adding the object - @type other: L{KX_GameObject} or string - @param time: The lifetime of the added object, in frames. A time of 0 means the object will last forever. - @type time: int - - @rtype: L{KX_GameObject} - """ diff --git a/source/gameengine/PyDoc/KX_SceneActuator.py b/source/gameengine/PyDoc/KX_SceneActuator.py deleted file mode 100644 index 6e27257533e..00000000000 --- a/source/gameengine/PyDoc/KX_SceneActuator.py +++ /dev/null @@ -1,67 +0,0 @@ -# $Id$ -# Documentation for KX_SceneActuator -from SCA_IActuator import * - -class KX_SceneActuator(SCA_IActuator): - """ - Scene Actuator logic brick. - - @warning: Scene actuators that use a scene name will be ignored if at game start, the - named scene doesn't exist or is empty - - This will generate a warning in the console: - - C{ERROR: GameObject I{OBName} has a SceneActuator I{ActuatorName} (SetScene) without scene} - - @ivar scene: the name of the scene to change to/overlay/underlay/remove/suspend/resume - @type scene: string. - @ivar camera: the camera to change to. - When setting the attribute, you can use either a L{KX_Camera} or the name of the camera. - @type camera: L{KX_Camera} on read, string or L{KX_Camera} on write - """ - def setUseRestart(flag): - """ - DEPRECATED - Set flag to True to restart the scene. - - @type flag: boolean - """ - def setScene(scene): - """ - DEPRECATED: use the scene property instead - Sets the name of the scene to change to/overlay/underlay/remove/suspend/resume. - - @type scene: string - """ - def setCamera(camera): - """ - DEPRECATED: use the camera property instead - Sets the camera to change to. - - Camera can be either a L{KX_Camera} or the name of the camera. - - @type camera: L{KX_Camera} or string - """ - def getUseRestart(): - """ - DEPRECATED - Returns True if the scene will be restarted. - - @rtype: boolean - """ - def getScene(): - """ - DEPRECATED: use the scene property instead - Returns the name of the scene to change to/overlay/underlay/remove/suspend/resume. - - Returns an empty string ("") if no scene has been set. - - @rtype: string - """ - def getCamera(): - """ - DEPRECATED: use the camera property instead - Returns the name of the camera to change to. - - @rtype: string - """ diff --git a/source/gameengine/PyDoc/KX_SoundActuator.py b/source/gameengine/PyDoc/KX_SoundActuator.py deleted file mode 100644 index 37ae3c6640d..00000000000 --- a/source/gameengine/PyDoc/KX_SoundActuator.py +++ /dev/null @@ -1,195 +0,0 @@ -# $Id$ -# Documentation for KX_SoundActuator -from SCA_IActuator import * - -class KX_SoundActuator(SCA_IActuator): - """ - Sound Actuator. - - The L{startSound()}, L{pauseSound()} and L{stopSound()} do not require - the actuator to be activated - they act instantly provided that the actuator has - been activated once at least. - - @ivar filename: Sets the filename of the sound this actuator plays. - @type filename: string - - @ivar volume: Sets the volume (gain) of the sound. - @type volume: float - - @ivar pitch: Sets the pitch of the sound. - @type pitch: float - - @ivar rollOffFactor: Sets the roll off factor. Rolloff defines the rate of attenuation as the sound gets further away. - @type rollOffFactor: float - - @ivar looping: Sets the loop mode of the actuator. - @type looping: integer - - @ivar position: Sets the position of the sound. - @type position: float array - - @ivar velocity: Sets the speed of the sound; The speed of the sound alter the pitch. - @type velocity: float array - - @ivar orientation: Sets the orientation of the sound. When setting the orientation you can - also use quaternion [float,float,float,float] or euler angles [float,float,float] - @type orientation: 3x3 matrix [[float]] - - @ivar type: Sets the operation mode of the actuator. You can use one of the following constant: - KX_SOUNDACT_PLAYSTOP (1) - KX_SOUNDACT_PLAYEND (2) - KX_SOUNDACT_LOOPSTOP (3) - KX_SOUNDACT_LOOPEND (4) - KX_SOUNDACT_LOOPBIDIRECTIONAL (5) - KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP (6) - @type type: integer - - @group Play Methods: startSound, pauseSound, stopSound. - """ - def setFilename(filename): - """ - DEPRECATED: Use the filename property instead. - Sets the filename of the sound this actuator plays. - - @type filename: string - """ - def getFilename(): - """ - DEPRECATED: Use the filename property instead. - Returns the filename of the sound this actuator plays. - - @rtype: string - """ - def startSound(): - """ - Starts the sound. - """ - def pauseSound(): - """ - Pauses the sound. - """ - def stopSound(): - """ - Stops the sound. - """ - def setGain(gain): - """ - DEPRECATED: Use the volume property instead - Sets the gain (volume) of the sound - - @type gain: float - @param gain: 0.0 (quiet) <= gain <= 1.0 (loud) - """ - def getGain(): - """ - DEPRECATED: Use the volume property instead. - Gets the gain (volume) of the sound. - - @rtype: float - """ - def setPitch(pitch): - """ - DEPRECATED: Use the pitch property instead. - Sets the pitch of the sound. - - @type pitch: float - """ - def getPitch(): - """ - DEPRECATED: Use the pitch property instead. - Returns the pitch of the sound. - - @rtype: float - """ - def setRollOffFactor(rolloff): - """ - DEPRECATED: Use the rollOffFactor property instead. - Sets the rolloff factor for the sounds. - - Rolloff defines the rate of attenuation as the sound gets further away. - Higher rolloff factors shorten the distance at which the sound can be heard. - - @type rolloff: float - """ - def getRollOffFactor(): - """ - DEPRECATED: Use the rollOffFactor property instead. - Returns the rolloff factor for the sound. - - @rtype: float - """ - def setLooping(loop): - """ - DEPRECATED: Use the looping property instead. - Sets the loop mode of the actuator. - - @bug: There are no constants defined for this method! - @param loop: - Play Stop 1 - - Play End 2 - - Loop Stop 3 - - Loop End 4 - - Bidirection Stop 5 - - Bidirection End 6 - @type loop: integer - """ - def getLooping(): - """ - DEPRECATED: Use the looping property instead. - Returns the current loop mode of the actuator. - - @rtype: integer - """ - def setPosition(x, y, z): - """ - DEPRECATED: Use the position property instead. - Sets the position this sound will come from. - - @type x: float - @param x: The x coordinate of the sound. - @type y: float - @param y: The y coordinate of the sound. - @type z: float - @param z: The z coordinate of the sound. - """ - def setVelocity(vx, vy, vz): - """ - DEPRECATED: Use the velocity property instead. - Sets the velocity this sound is moving at. - - The sound's pitch is determined from the velocity. - - @type vx: float - @param vx: The vx coordinate of the sound. - @type vy: float - @param vy: The vy coordinate of the sound. - @type vz: float - @param vz: The vz coordinate of the sound. - """ - def setOrientation(o11, o12, o13, o21, o22, o23, o31, o32, o33): - """ - DEPRECATED: Use the orientation property instead. - Sets the orientation of the sound. - - The nine parameters specify a rotation matrix:: - | o11, o12, o13 | - | o21, o22, o23 | - | o31, o32, o33 | - """ - - def setType(mode): - """ - DEPRECATED: Use the type property instead. - Sets the operation mode of the actuator. - - @param mode: KX_SOUNDACT_PLAYSTOP, KX_SOUNDACT_PLAYEND, KX_SOUNDACT_LOOPSTOP, KX_SOUNDACT_LOOPEND, KX_SOUNDACT_LOOPBIDIRECTIONAL, KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP - @type mode: integer - """ - - def getType(): - """ - DEPRECATED: Use the type property instead. - Returns the operation mode of the actuator. - - @rtype: integer - @return: KX_SOUNDACT_PLAYSTOP, KX_SOUNDACT_PLAYEND, KX_SOUNDACT_LOOPSTOP, KX_SOUNDACT_LOOPEND, KX_SOUNDACT_LOOPBIDIRECTIONAL, KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP - """ diff --git a/source/gameengine/PyDoc/KX_StateActuator.py b/source/gameengine/PyDoc/KX_StateActuator.py deleted file mode 100644 index fe3669d3809..00000000000 --- a/source/gameengine/PyDoc/KX_StateActuator.py +++ /dev/null @@ -1,44 +0,0 @@ -# $Id$ -# Documentation for KX_StateActuator -from SCA_IActuator import * - -class KX_StateActuator(SCA_IActuator): - """ - State actuator changes the state mask of parent object. - - Property: - - @ivar operation: type of bit operation to be applied on object state mask. - You can use one of the following constant: - KX_STATE_OP_CPY (0) : Copy state mask - KX_STATE_OP_SET (1) : Add bits to state mask - KX_STATE_OP_CLR (2) : Substract bits to state mask - KX_STATE_OP_NEG (3) : Invert bits to state mask - @type operation: integer - - @ivar mask: value that defines the bits that will be modified by the operation. - The bits that are 1 in the mask 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 mask to the object state - @type mask: integer - """ - def setOperation(op): - """ - DEPRECATED: Use the operation property instead. - 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): - """ - DEPRECATED: Use the mask property instead. - 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/KX_TouchSensor.py b/source/gameengine/PyDoc/KX_TouchSensor.py deleted file mode 100644 index f4fcbeefc62..00000000000 --- a/source/gameengine/PyDoc/KX_TouchSensor.py +++ /dev/null @@ -1,63 +0,0 @@ -# $Id$ -# Documentation for KX_TouchSensor -from SCA_ISensor import * -from KX_GameObject import * - -class KX_TouchSensor(SCA_ISensor): - """ - Touch sensor detects collisions between objects. - - @ivar property: The property or material to collide with. - @type property: string - @ivar useMaterial: Determines if the sensor is looking for a property or material. - KX_True = Find material; KX_False = Find property - @type useMaterial: boolean - @ivar pulseCollisions: The last collided object. - @type pulseCollisions: bool - @ivar objectHit: The last collided object. (Read Only) - @type objectHit: L{KX_GameObject} or None - @ivar objectHitList: A list of colliding objects. (Read Only) - @type objectHitList: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>} - """ - - #--The following methods are deprecated, please use properties instead. - def setProperty(name): - """ - DEPRECATED: use the property property - Set the property or material to collide with. Use - setTouchMaterial() to switch between properties and - materials. - @type name: string - """ - - def getProperty(): - """ - DEPRECATED: use the property property - Returns the property or material to collide with. Use - getTouchMaterial() to find out whether this sensor - looks for properties or materials. (B{deprecated}) - - @rtype: string - """ - def getHitObject(): - """ - DEPRECATED: use the objectHit property - Returns the last object hit by this touch sensor. (B{deprecated}) - - @rtype: L{KX_GameObject} - """ - def getHitObjectList(): - """ - DEPRECATED: use the objectHitList property - Returns a list of all objects hit in the last frame. (B{deprecated}) - - Only objects that have the requisite material/property are listed. - - @rtype: L{CListValue<CListValue.CListValue>} of L{KX_GameObject<KX_GameObject.KX_GameObject>} - """ - def getTouchMaterial(): - """ - DEPRECATED: use the useMaterial property - Returns KX_TRUE if this sensor looks for a specific material, - KX_FALSE if it looks for a specific property. (B{deprecated}) - """ diff --git a/source/gameengine/PyDoc/KX_TrackToActuator.py b/source/gameengine/PyDoc/KX_TrackToActuator.py deleted file mode 100644 index ee2dc5d6144..00000000000 --- a/source/gameengine/PyDoc/KX_TrackToActuator.py +++ /dev/null @@ -1,70 +0,0 @@ -# $Id$ -# Documentation for KX_TrackToActuator -from SCA_IActuator import * - -class KX_TrackToActuator(SCA_IActuator): - """ - Edit Object actuator in Track To mode. - - @warning: Track To Actuators will be ignored if at game start, the - object to track to is invalid. - - This will generate a warning in the console: - - C{ERROR: GameObject I{OBName} no object in EditObjectActuator I{ActuatorName}} - - @ivar object: the object this actuator tracks. - @type object: KX_GameObject or None - @ivar time: the time in frames with which to delay the tracking motion - @type time: integer - @ivar use3D: the tracking motion to use 3D - @type use3D: boolean - - """ - def setObject(object): - """ - DEPRECATED: Use the object property. - Sets the object to track. - - @type object: L{KX_GameObject}, string or None - @param object: Either a reference to a game object or the name of the object to track. - """ - def getObject(name_only): - """ - DEPRECATED: Use the object property. - Returns the name of the object to track. - - @type name_only: bool - @param name_only: optional argument, when 0 return a KX_GameObject - @rtype: string, KX_GameObject or None if no object is set - """ - def setTime(time): - """ - DEPRECATED: Use the time property. - Sets the time in frames with which to delay the tracking motion. - - @type time: integer - """ - def getTime(): - """ - DEPRECATED: Use the time property. - Returns the time in frames with which the tracking motion is delayed. - - @rtype: integer - """ - def setUse3D(use3d): - """ - DEPRECATED: Use the use3D property. - Sets the tracking motion to use 3D. - - @type use3d: boolean - @param use3d: - True: allow the tracking motion to extend in the z-direction. - - False: lock the tracking motion to the x-y plane. - """ - def getUse3D(): - """ - DEPRECATED: Use the use3D property. - Returns True if the tracking motion will track in the z direction. - - @rtype: boolean - """ diff --git a/source/gameengine/PyDoc/KX_VehicleWrapper.py b/source/gameengine/PyDoc/KX_VehicleWrapper.py deleted file mode 100644 index 087aa167475..00000000000 --- a/source/gameengine/PyDoc/KX_VehicleWrapper.py +++ /dev/null @@ -1,166 +0,0 @@ -class KX_VehicleWrapper: # (PyObjectPlus) - """ - KX_VehicleWrapper - - All placeholders have a __ prefix - """ - - def addWheel(wheel, attachPos, attachDir, axleDir, suspensionRestLength, wheelRadius, hasSteering): - - """ - TODO - Description - - @param wheel: The object to use as a wheel. - @type wheel: L{KX_GameObject<KX_GameObject.KX_GameObject>} or a KX_GameObject name - @param attachPos: The position that this wheel will attach to. - @type attachPos: vector of 3 floats - @param attachDir: The direction this wheel points. - @type attachDir: vector of 3 floats - @param axleDir: The direction of this wheels axle. - @type axleDir: vector of 3 floats - @param suspensionRestLength: TODO - Description - @type suspensionRestLength: float - @param wheelRadius: The size of the wheel. - @type wheelRadius: float - """ - - def __applyBraking(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __applyEngineForce(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __getConstraintId(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __getConstraintType(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __getNumWheels(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __getWheelOrientationQuaternion(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __getWheelPosition(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __getWheelRotation(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setRollInfluence(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setSteeringValue(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setSuspensionCompression(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setSuspensionDamping(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setSuspensionStiffness(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ - def __setTyreFriction(val): - """ - TODO - Description - - @param val: the starting frame of the animation - @type val: float - - @rtype: integer - @return: TODO Description - """ diff --git a/source/gameengine/PyDoc/KX_VertexProxy.py b/source/gameengine/PyDoc/KX_VertexProxy.py deleted file mode 100644 index 7ee5087b316..00000000000 --- a/source/gameengine/PyDoc/KX_VertexProxy.py +++ /dev/null @@ -1,148 +0,0 @@ -# $Id$ -# Documentation for the vertex proxy class - -class KX_VertexProxy: - """ - A vertex holds position, UV, colour and normal information. - - Note: - The physics simulation is NOT currently updated - physics will not respond - to changes in the vertex position. - - @ivar XYZ: The position of the vertex. - @type XYZ: list [x, y, z] - @ivar UV: The texture coordinates of the vertex. - @type UV: list [u, v] - @ivar normal: The normal of the vertex - @type normal: list [nx, ny, nz] - @ivar colour: The colour of the vertex. - Black = [0.0, 0.0, 0.0, 1.0], White = [1.0, 1.0, 1.0, 1.0] - @type colour: list [r, g, b, a] - @ivar color: Synonym for colour. - - @group Position: x, y, z - @ivar x: The x coordinate of the vertex. - @type x: float - @ivar y: The y coordinate of the vertex. - @type y: float - @ivar z: The z coordinate of the vertex. - @type z: float - - @group Texture Coordinates: u, v - @ivar u: The u texture coordinate of the vertex. - @type u: float - @ivar v: The v texture coordinate of the vertex. - @type v: float - - @ivar u2: The second u texture coordinate of the vertex. - @type u2: float - @ivar v2: The second v texture coordinate of the vertex. - @type v2: float - - @group Colour: r, g, b, a - @ivar r: The red component of the vertex colour. 0.0 <= r <= 1.0 - @type r: float - @ivar g: The green component of the vertex colour. 0.0 <= g <= 1.0 - @type g: float - @ivar b: The blue component of the vertex colour. 0.0 <= b <= 1.0 - @type b: float - @ivar a: The alpha component of the vertex colour. 0.0 <= a <= 1.0 - @type a: float - """ - - def getXYZ(): - """ - Gets the position of this vertex. - - @rtype: list [x, y, z] - @return: this vertexes position in local coordinates. - """ - def setXYZ(pos): - """ - Sets the position of this vertex. - - @type pos: list [x, y, z] - @param pos: the new position for this vertex in local coordinates. - """ - def getUV(): - """ - Gets the UV (texture) coordinates of this vertex. - - @rtype: list [u, v] - @return: this vertexes UV (texture) coordinates. - """ - def setUV(uv): - """ - Sets the UV (texture) coordinates of this vertex. - - @type uv: list [u, v] - """ - def getUV2(): - """ - Gets the 2nd UV (texture) coordinates of this vertex. - - @rtype: list [u, v] - @return: this vertexes UV (texture) coordinates. - """ - def setUV2(uv): - """ - Sets the 2nd UV (texture) coordinates of this vertex. - - @type uv: list [u, v] - """ - def getRGBA(): - """ - Gets the colour of this vertex. - - The colour is represented as four bytes packed into an integer value. The colour is - packed as RGBA. - - Since Python offers no way to get each byte without shifting, you must use the struct module to - access colour in an machine independent way. - - Because of this, it is suggested you use the r, g, b and a attributes or the colour attribute instead. - - Example:: - import struct; - col = struct.unpack('4B', struct.pack('I', v.getRGBA())) - # col = (r, g, b, a) - # black = ( 0, 0, 0, 255) - # white = (255, 255, 255, 255) - - @rtype: integer - @return: packed colour. 4 byte integer with one byte per colour channel in RGBA format. - """ - def setRGBA(col): - """ - Sets the colour of this vertex. - - See getRGBA() for the format of col, and its relevant problems. Use the r, g, b and a attributes - or the colour attribute instead. - - setRGBA() also accepts a four component list as argument col. The list represents the colour as [r, g, b, a] - with black = [0.0, 0.0, 0.0, 1.0] and white = [1.0, 1.0, 1.0, 1.0] - - Example:: - v.setRGBA(0xff0000ff) # Red - v.setRGBA(0xff00ff00) # Green on little endian, transparent purple on big endian - v.setRGBA([1.0, 0.0, 0.0, 1.0]) # Red - v.setRGBA([0.0, 1.0, 0.0, 1.0]) # Green on all platforms. - - @type col: integer or list [r, g, b, a] - @param col: the new colour of this vertex in packed RGBA format. - """ - def getNormal(): - """ - Gets the normal vector of this vertex. - - @rtype: list [nx, ny, nz] - @return: normalised normal vector. - """ - def setNormal(normal): - """ - Sets the normal vector of this vertex. - - @type normal: sequence of floats [r, g, b] - @param normal: the new normal of this vertex. - """ - diff --git a/source/gameengine/PyDoc/KX_VisibilityActuator.py b/source/gameengine/PyDoc/KX_VisibilityActuator.py deleted file mode 100644 index 36f25b2423c..00000000000 --- a/source/gameengine/PyDoc/KX_VisibilityActuator.py +++ /dev/null @@ -1,22 +0,0 @@ -# $Id$ -# Documentation for KX_VisibilityActuator -from SCA_IActuator import * - -class KX_VisibilityActuator(SCA_IActuator): - """ - Visibility Actuator. - @ivar visibility: whether the actuator makes its parent object visible or invisible - @type visibility: boolean - @ivar occlusion: whether the actuator makes its parent object an occluder or not - @type occlusion: boolean - @ivar recursion: whether the visibility/occlusion should be propagated to all children of the object - @type recursion: boolean - """ - def set(visible): - """ - DEPRECATED: Use the visibility property instead. - Sets whether the actuator makes its parent object visible or invisible. - - @param visible: - True: Makes its parent visible. - - False: Makes its parent invisible. - """ diff --git a/source/gameengine/PyDoc/Rasterizer.py b/source/gameengine/PyDoc/Rasterizer.py index 6a67cdcc71b..bafcfece473 100644 --- a/source/gameengine/PyDoc/Rasterizer.py +++ b/source/gameengine/PyDoc/Rasterizer.py @@ -43,7 +43,6 @@ Example Uses an L{SCA_MouseSensor}, and two L{KX_ObjectActuator}s to implement M @var KX_BLENDER_GLSL_MATERIAL: Materials approximating blender materials with GLSL. """ - def getWindowWidth(): """ Gets the width of the window (in pixels) @@ -105,6 +104,13 @@ def setMistColor(rgb): @type rgb: list [r, g, b] """ + +def setAmbientColor(rgb): + """ + Sets the color of ambient light. + + @type rgb: list [r, g, b] + """ def setMistStart(start): """ @@ -121,6 +127,13 @@ def setMistEnd(end): @type end: float """ +def disableMist(): + """ + Disables mist. + + @note: Set any of the mist properties to enable mist. + """ + def setEyeSeparation(eyesep): """ Sets the eye separation for stereo mode. @@ -194,3 +207,15 @@ def drawLine(fromVec,toVec,color): @type color: list [r, g, b] """ +def enableMotionBlur(factor): + """ + Enable the motion blue effect. + + @param factor: the ammount of motion blur to display. + @type factor: float [0.0 - 1.0] + """ + +def disableMotionBlur(): + """ + Disable the motion blue effect. + """ diff --git a/source/gameengine/PyDoc/SCA_2DFilterActuator.py b/source/gameengine/PyDoc/SCA_2DFilterActuator.py deleted file mode 100644 index 9a010e8f221..00000000000 --- a/source/gameengine/PyDoc/SCA_2DFilterActuator.py +++ /dev/null @@ -1,44 +0,0 @@ -# $Id$ -# Documentation for SCA_2DFilterActuator -from SCA_IActuator import * -from SCA_ILogicBrick import * - -class SCA_2DFilterActuator(SCA_IActuator): - """ - Create, enable and disable 2D filters - - Properties: - - The following properties don't have an immediate effect. - You must active the actuator to get the result. - The actuator is not persistent: it automatically stops itself after setting up the filter - but the filter remains active. To stop a filter you must activate the actuator with 'type' - set to RAS_2DFILTER_DISABLED or RAS_2DFILTER_NOFILTER. - - @ivar shaderText: shader source code for custom shader - @type shaderText: string - @ivar disableMotionBlur: action on motion blur: 0=enable, 1=disable - @type disableMotionBlur: integer - @ivar type: type of 2D filter, use one of the following constants: - RAS_2DFILTER_ENABLED (-2) : enable the filter that was previously disabled - RAS_2DFILTER_DISABLED (-1) : disable the filter that is currently active - RAS_2DFILTER_NOFILTER (0) : disable and destroy the filter that is currently active - RAS_2DFILTER_MOTIONBLUR (1) : create and enable preset filters - RAS_2DFILTER_BLUR (2) - RAS_2DFILTER_SHARPEN (3) - RAS_2DFILTER_DILATION (4) - RAS_2DFILTER_EROSION (5) - RAS_2DFILTER_LAPLACIAN (6) - RAS_2DFILTER_SOBEL (7) - RAS_2DFILTER_PREWITT (8) - RAS_2DFILTER_GRAYSCALE (9) - RAS_2DFILTER_SEPIA (10) - RAS_2DFILTER_INVERT (11) - RAS_2DFILTER_CUSTOMFILTER (12) : customer filter, the code code is set via shaderText property - @type type: integer - @ivar passNb: order number of filter in the stack of 2D filters. Filters are executed in increasing order of passNb. - Only be one filter can be defined per passNb. - @type passNb: integer (0-100) - @ivar value: argument for motion blur filter - @type value: float (0.0-100.0) - """ diff --git a/source/gameengine/PyDoc/SCA_ANDController.py b/source/gameengine/PyDoc/SCA_ANDController.py deleted file mode 100644 index 1717e613595..00000000000 --- a/source/gameengine/PyDoc/SCA_ANDController.py +++ /dev/null @@ -1,11 +0,0 @@ -# $Id$ -# Documentation for SCA_ANDController -from SCA_IController import * - -class SCA_ANDController(SCA_IController): - """ - An AND controller activates only when all linked sensors are activated. - - There are no special python methods for this controller. - """ - diff --git a/source/gameengine/PyDoc/SCA_ActuatorSensor.py b/source/gameengine/PyDoc/SCA_ActuatorSensor.py deleted file mode 100644 index 515354e8716..00000000000 --- a/source/gameengine/PyDoc/SCA_ActuatorSensor.py +++ /dev/null @@ -1,33 +0,0 @@ -# $Id$ -# Documentation for SCA_ActuatorSensor -from SCA_IActuator import * -from SCA_ISensor import * -from SCA_ILogicBrick import * - -class SCA_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. - - Properties: - - @ivar actuator: the name of the actuator that the sensor is monitoring. - @type actuator: string - """ - def getActuator(): - """ - DEPRECATED: use the actuator property - Return the Actuator with which the sensor operates. - - @rtype: string - """ - def setActuator(name): - """ - DEPRECATED: use the actuator property - 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/SCA_AlwaysSensor.py b/source/gameengine/PyDoc/SCA_AlwaysSensor.py deleted file mode 100644 index 54ab07a8a99..00000000000 --- a/source/gameengine/PyDoc/SCA_AlwaysSensor.py +++ /dev/null @@ -1,9 +0,0 @@ -# $Id$ -# Documentation for SCA_AlwaysSensor -from SCA_ISensor import * - -class SCA_AlwaysSensor(SCA_ISensor): - """ - This sensor is always activated. - """ - diff --git a/source/gameengine/PyDoc/SCA_DelaySensor.py b/source/gameengine/PyDoc/SCA_DelaySensor.py deleted file mode 100644 index 6560df6573e..00000000000 --- a/source/gameengine/PyDoc/SCA_DelaySensor.py +++ /dev/null @@ -1,72 +0,0 @@ -# $Id$ -# Documentation for SCA_DelaySensor -from SCA_ISensor import * - -class SCA_DelaySensor(SCA_ISensor): - """ - The Delay sensor generates positive and negative triggers at precise time, - expressed in number of frames. The delay parameter defines the length - of the initial OFF period. A positive trigger is generated at the end of this period. - The duration parameter defines the length of the ON period following the OFF period. - There is a negative trigger at the end of the ON period. If duration is 0, the sensor - stays ON and there is no negative trigger. - The sensor runs the OFF-ON cycle once unless the repeat option is set: the - OFF-ON cycle repeats indefinately (or the OFF cycle if duration is 0). - Use SCA_ISensor::reset() at any time to restart sensor. - - Properties: - - @ivar delay: length of the initial OFF period as number of frame, 0 for immediate trigger. - @type delay: integer. - @ivar duration: length of the ON period in number of frame after the initial OFF period. - If duration is greater than 0, a negative trigger is sent at the end of the ON pulse. - @type duration: integer - @ivar repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once. - @type repeat: integer - """ - def setDelay(delay): - """ - DEPRECATED: use the delay property - Set the initial delay before the positive trigger. - - @param delay: length of the initial OFF period as number of frame, 0 for immediate trigger - @type delay: integer - """ - def setDuration(duration): - """ - DEPRECATED: use the duration property - Set the duration of the ON pulse after initial delay and the generation of the positive trigger. - If duration is greater than 0, a negative trigger is sent at the end of the ON pulse. - - @param duration: length of the ON period in number of frame after the initial OFF period - @type duration: integer - """ - def setRepeat(repeat): - """ - DEPRECATED: use the repeat property - Set if the sensor repeat mode. - - @param repeat: 1 if the OFF-ON cycle should be repeated indefinately, 0 if it should run once. - @type repeat: integer - """ - def getDelay(): - """ - DEPRECATED: use the delay property - Return the delay parameter value. - - @rtype: integer - """ - def getDuration(): - """ - DEPRECATED: use the duration property - Return the duration parameter value - - @rtype: integer - """ - def getRepeat(): - """ - DEPRECATED: use the repeat property - Return the repeat parameter value - - @rtype: KX_TRUE or KX_FALSE - """ diff --git a/source/gameengine/PyDoc/SCA_IActuator.py b/source/gameengine/PyDoc/SCA_IActuator.py deleted file mode 100644 index ac47c15dc78..00000000000 --- a/source/gameengine/PyDoc/SCA_IActuator.py +++ /dev/null @@ -1,9 +0,0 @@ -# $Id$ -# Documentation for SCA_IActuator -from SCA_ILogicBrick import * - -class SCA_IActuator(SCA_ILogicBrick): - """ - Base class for all actuator logic bricks. - """ - diff --git a/source/gameengine/PyDoc/SCA_IController.py b/source/gameengine/PyDoc/SCA_IController.py deleted file mode 100644 index f83e7c97dce..00000000000 --- a/source/gameengine/PyDoc/SCA_IController.py +++ /dev/null @@ -1,9 +0,0 @@ -# $Id$ -# Documentation for KX_CameraActuator -from SCA_ILogicBrick import * - -class SCA_IController(SCA_ILogicBrick): - """ - Base class for all controller logic bricks. - """ - diff --git a/source/gameengine/PyDoc/SCA_ILogicBrick.py b/source/gameengine/PyDoc/SCA_ILogicBrick.py deleted file mode 100644 index 4688ba12bb6..00000000000 --- a/source/gameengine/PyDoc/SCA_ILogicBrick.py +++ /dev/null @@ -1,45 +0,0 @@ -# $Id$ -# Documentation for the logic brick base class SCA_ILogicBrick -from KX_GameObject import * - -class SCA_ILogicBrick: - """ - Base class for all logic bricks. - - @ivar executePriority: This determines the order controllers are evaluated, and actuators are activated (lower priority is executed first). - @type executePriority: int - @ivar owner: The game object this logic brick is attached to (read only). - @type owner: L{KX_GameObject<KX_GameObject.KX_GameObject>} or None in exceptional cases. - """ - - def getOwner(): - """ - Gets the game object associated with this logic brick. - - Deprecated: Use the "owner" property instead. - - @rtype: L{KX_GameObject<KX_GameObject.KX_GameObject>} - """ - - #--The following methods are deprecated-- - def setExecutePriority(priority): - """ - Sets the priority of this logic brick. - - This determines the order controllers are evaluated, and actuators are activated. - Bricks with lower priority will be executed first. - - Deprecated: Use the "executePriority" property instead. - - @type priority: integer - @param priority: the priority of this logic brick. - """ - def getExecutePriority(): - """ - Gets the execution priority of this logic brick. - - Deprecated: Use the "executePriority" property instead. - - @rtype: integer - @return: this logic bricks current priority. - """ diff --git a/source/gameengine/PyDoc/SCA_ISensor.py b/source/gameengine/PyDoc/SCA_ISensor.py deleted file mode 100644 index ab35996aa50..00000000000 --- a/source/gameengine/PyDoc/SCA_ISensor.py +++ /dev/null @@ -1,111 +0,0 @@ -# $Id$ -# Documentation for SCA_ISensor -from SCA_ILogicBrick import * - -class SCA_ISensor(SCA_ILogicBrick): - """ - Base class for all sensor logic bricks. - - @ivar usePosPulseMode: Flag to turn positive pulse mode on and off. - @type usePosPulseMode: boolean - @ivar useNegPulseMode: Flag to turn negative pulse mode on and off. - @type useNegPulseMode: boolean - @ivar frequency: The frequency for pulse mode sensors. - @type frequency: int - @ivar level: Flag to set whether to detect level or edge transition when entering a state. - 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. - @type level: boolean - @ivar invert: Flag to set if this sensor activates on positive or negative events. - @type invert: boolean - @ivar triggered: True if this sensor brick is in a positive state. (Read only) - @type triggered: boolean - @ivar positive: True if this sensor brick is in a positive state. (Read only) - @type positive: boolean - """ - - def reset(): - """ - Reset sensor internal state, effect depends on the type of sensor and settings. - - The sensor is put in its initial state as if it was just activated. - """ - - #--The following methods are deprecated-- - def isPositive(): - """ - True if this sensor brick is in a positive state. - """ - - def isTriggered(): - """ - True if this sensor brick has triggered the current controller. - """ - - def getUsePosPulseMode(): - """ - True if the sensor is in positive pulse mode. - """ - def setUsePosPulseMode(pulse): - """ - Sets positive pulse mode. - - @type pulse: boolean - @param pulse: If True, will activate positive pulse mode for this sensor. - """ - def getFrequency(): - """ - The frequency for pulse mode sensors. - - @rtype: integer - @return: the pulse frequency in 1/50 sec. - """ - def setFrequency(freq): - """ - Sets the frequency for pulse mode sensors. - - @type freq: integer - @return: the pulse frequency in 1/50 sec. - """ - def getUseNegPulseMode(): - """ - True if the sensor is in negative pulse mode. - """ - def setUseNegPulseMode(pulse): - """ - Sets negative pulse mode. - - @type pulse: boolean - @param pulse: If True, will activate negative pulse mode for this sensor. - """ - def getInvert(): - """ - True if this sensor activates on negative events. - """ - def setInvert(invert): - """ - Sets if this sensor activates on positive or negative events. - - @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/PyDoc/SCA_JoystickSensor.py b/source/gameengine/PyDoc/SCA_JoystickSensor.py deleted file mode 100644 index 13b006e8dd6..00000000000 --- a/source/gameengine/PyDoc/SCA_JoystickSensor.py +++ /dev/null @@ -1,169 +0,0 @@ -# $Id$ -# Documentation for SCA_RandomSensor -from SCA_ISensor import * - -class SCA_JoystickSensor(SCA_ISensor): - """ - This sensor detects player joystick events. - - Properties: - - @ivar axisValues: (read-only) The state of the joysticks axis as a list of values L{numAxis} long. - each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing. - The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls. - left:[-32767, 0, ...], right:[32767, 0, ...], up:[0, -32767, ...], down:[0, 32767, ...] - @type axisValues: list of ints - - @ivar axisSingle: (read-only) like L{axisValues} but returns a single axis value that is set by the sensor. - Only use this for "Single Axis" type sensors otherwise it will raise an error. - @type axisSingle: int - - @ivar numAxis: (read-only) The number of axes for the joystick at this index. - @type numAxis: integer - @ivar numButtons: (read-only) The number of buttons for the joystick at this index. - @type numButtons: integer - @ivar numHats: (read-only) The number of hats for the joystick at this index. - @type numHats: integer - @ivar connected: (read-only) True if a joystick is connected at this joysticks index. - @type connected: boolean - @ivar index: The joystick index to use (from 0 to 7). The first joystick is always 0. - @type index: integer - @ivar threshold: Axis threshold. Joystick axis motion below this threshold wont trigger an event. Use values between (0 and 32767), lower values are more sensitive. - @type threshold: integer - @ivar button: The button index the sensor reacts to (first button = 0). When the "All Events" toggle is set, this option has no effect. - @type button: integer - @ivar axis: The axis this sensor reacts to, as a list of two values [axisIndex, axisDirection] - axisIndex: the axis index to use when detecting axis movement, 1=primary directional control, 2=secondary directional control. - axisDirection: 0=right, 1=up, 2=left, 3=down - @type axis: [integer, integer] - @ivar hat: The hat the sensor reacts to, as a list of two values: [hatIndex, hatDirection] - hatIndex: the hat index to use when detecting hat movement, 1=primary hat, 2=secondary hat. - hatDirection: 0-11 - @type hat: [integer, integer] - """ - - def getButtonActiveList(): - """ - Returns a list containing the indicies of the currently pressed buttons. - @rtype: list - """ - def getButtonStatus(buttonIndex): - """ - Returns a bool of the current pressed state of the specified button. - @param buttonIndex: the button index, 0=first button - @type buttonIndex: integer - @rtype: bool - """ - def getIndex(): - """ - DEPRECATED: use the 'index' property. - Returns the joystick index to use (from 1 to 8). - @rtype: integer - """ - def setIndex(index): - """ - DEPRECATED: use the 'index' property. - Sets the joystick index to use. - @param index: The index of this joystick sensor, Clamped between 1 and 8. - @type index: integer - @note: This is only useful when you have more then 1 joystick connected to your computer - multiplayer games. - """ - def getAxis(): - """ - DEPRECATED: use the 'axis' property. - Returns the current axis this sensor reacts to. See L{getAxisValue()<SCA_JoystickSensor.getAxisValue>} for the current axis state. - @rtype: list - @return: 2 values returned are [axisIndex, axisDirection] - see L{setAxis()<SCA_JoystickSensor.setAxis>} for their purpose. - @note: When the "All Events" toggle is set, this option has no effect. - """ - def setAxis(axisIndex, axisDirection): - """ - DEPRECATED: use the 'axis' property. - @param axisIndex: Set the axis index to use when detecting axis movement. - @type axisIndex: integer from 1 to 2 - @param axisDirection: Set the axis direction used for detecting motion. 0:right, 1:up, 2:left, 3:down. - @type axisDirection: integer from 0 to 3 - @note: When the "All Events" toggle is set, this option has no effect. - """ - def getAxisValue(): - """ - DEPRECATED: use the 'axisPosition' property. - Returns the state of the joysticks axis. See differs to L{getAxis()<SCA_JoystickSensor.getAxis>} returning the current state of the joystick. - @rtype: list - @return: 4 values, each spesifying the value of an axis between -32767 and 32767 depending on how far the axis is pushed, 0 for nothing. - - The first 2 values are used by most joysticks and gamepads for directional control. 3rd and 4th values are only on some joysticks and can be used for arbitary controls. - - left:[-32767, 0, ...], right:[32767, 0, ...], up:[0, -32767, ...], down:[0, 32767, ...] - @note: Some gamepads only set the axis on and off like a button. - """ - def getThreshold(): - """ - DEPRECATED: use the 'threshold' property. - Get the axis threshold. See L{setThreshold()<SCA_JoystickSensor.setThreshold>} for details. - @rtype: integer - """ - def setThreshold(threshold): - """ - DEPRECATED: use the 'threshold' property. - Set the axis threshold. - @param threshold: Joystick axis motion below this threshold wont trigger an event. Use values between (0 and 32767), lower values are more sensitive. - @type threshold: integer - """ - def getButton(): - """ - DEPRECATED: use the 'button' property. - Returns the button index the sensor reacts to. See L{getButtonValue()<SCA_JoystickSensor.getButtonValue>} for a list of pressed buttons. - @rtype: integer - @note: When the "All Events" toggle is set, this option has no effect. - """ - def setButton(index): - """ - DEPRECATED: use the 'button' property. - Sets the button index the sensor reacts to when the "All Events" option is not set. - @note: When the "All Events" toggle is set, this option has no effect. - """ - def getButtonValue(): - """ - DEPRECATED: use the 'getButtonActiveList' method. - Returns a list containing the indicies of the currently pressed buttons. - @rtype: list - """ - def getHat(): - """ - DEPRECATED: use the 'hat' property. - Returns the current hat direction this sensor is set to. - [hatNumber, hatDirection]. - @rtype: list - @note: When the "All Events" toggle is set, this option has no effect. - """ - def setHat(index,direction): - """ - DEPRECATED: use the 'hat' property. - Sets the hat index the sensor reacts to when the "All Events" option is not set. - @type index: integer - """ - def getNumAxes(): - """ - DEPRECATED: use the 'numAxis' property. - Returns the number of axes for the joystick at this index. - @rtype: integer - """ - def getNumButtons(): - """ - DEPRECATED: use the 'numButtons' property. - Returns the number of buttons for the joystick at this index. - @rtype: integer - """ - def getNumHats(): - """ - DEPRECATED: use the 'numHats' property. - Returns the number of hats for the joystick at this index. - @rtype: integer - """ - def isConnected(): - """ - DEPRECATED: use the 'connected' property. - Returns True if a joystick is detected at this joysticks index. - @rtype: bool - """ diff --git a/source/gameengine/PyDoc/SCA_KeyboardSensor.py b/source/gameengine/PyDoc/SCA_KeyboardSensor.py deleted file mode 100644 index 8abb1fda762..00000000000 --- a/source/gameengine/PyDoc/SCA_KeyboardSensor.py +++ /dev/null @@ -1,116 +0,0 @@ -# $Id$ -# Documentation for SCA_KeyboardSensor -from SCA_ISensor import * - -class SCA_KeyboardSensor(SCA_ISensor): - """ - A keyboard sensor detects player key presses. - - See module L{GameKeys} for keycode values. - - @ivar key: The key code this sensor is looking for. - @type key: keycode from L{GameKeys} module - @ivar hold1: The key code for the first modifier this sensor is looking for. - @type hold1: keycode from L{GameKeys} module - @ivar hold2: The key code for the second modifier this sensor is looking for. - @type hold2: keycode from L{GameKeys} module - @ivar toggleProperty: The name of the property that indicates whether or not to log keystrokes as a string. - @type toggleProperty: string - @ivar targetProperty: The name of the property that receives keystrokes in case in case a string is logged. - @type targetProperty: string - @ivar useAllKeys: Flag to determine whether or not to accept all keys. - @type useAllKeys: boolean - @ivar events: a list of pressed keys that have either been pressed, or just released, or are active this frame. (read only). - - - 'keycode' matches the values in L{GameKeys}. - - 'status' uses... - - L{GameLogic.KX_INPUT_NONE} - - L{GameLogic.KX_INPUT_JUST_ACTIVATED} - - L{GameLogic.KX_INPUT_ACTIVE} - - L{GameLogic.KX_INPUT_JUST_RELEASED} - - @type events: list [[keycode, status], ...] - """ - - def getKeyStatus(keycode): - """ - Get the status of a key. - - @rtype: key state L{GameLogic} members (KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED) - @return: The state of the given key - @type keycode: integer - @param keycode: The code that represents the key you want to get the state of - """ - - #--The following methods are DEPRECATED-- - def getKey(): - """ - Returns the key code this sensor is looking for. - - B{DEPRECATED: Use the "key" property instead}. - - @rtype: keycode from L{GameKeys} module - """ - - def setKey(keycode): - """ - Set the key this sensor should listen for. - - B{DEPRECATED: Use the "key" property instead}. - - @type keycode: keycode from L{GameKeys} module - """ - - def getHold1(): - """ - Returns the key code for the first modifier this sensor is looking for. - - B{DEPRECATED: Use the "hold1" property instead}. - - @rtype: keycode from L{GameKeys} module - """ - - def setHold1(keycode): - """ - Sets the key code for the first modifier this sensor should look for. - - B{DEPRECATED: Use the "hold1" property instead}. - - @type keycode: keycode from L{GameKeys} module - """ - - def getHold2(): - """ - Returns the key code for the second modifier this sensor is looking for. - - B{DEPRECATED: Use the "hold2" property instead}. - - @rtype: keycode from L{GameKeys} module - """ - - def setHold2(keycode): - """ - Sets the key code for the second modifier this sensor should look for. - - B{DEPRECATED: Use the "hold2" property instead.} - - @type keycode: keycode from L{GameKeys} module - """ - - def getPressedKeys(): - """ - Get a list of keys that have either been pressed, or just released this frame. - - B{DEPRECATED: Use "events" instead.} - - @rtype: list of key status. [[keycode, status]] - """ - - def getCurrentlyPressedKeys(): - """ - Get a list of currently pressed keys that have either been pressed, or just released - - B{DEPRECATED: Use "events" instead.} - - @rtype: list of key status. [[keycode, status]] - """
\ No newline at end of file diff --git a/source/gameengine/PyDoc/SCA_MouseSensor.py b/source/gameengine/PyDoc/SCA_MouseSensor.py deleted file mode 100644 index 278ebe63b8a..00000000000 --- a/source/gameengine/PyDoc/SCA_MouseSensor.py +++ /dev/null @@ -1,44 +0,0 @@ -# $Id$ -# Documentation for SCA_MouseSensor -from SCA_ISensor import * - -class SCA_MouseSensor(SCA_ISensor): - """ - Mouse Sensor logic brick. - - Properties: - - @ivar position: current [x,y] coordinates of the mouse, in frame coordinates (pixels) - @type position: [integer,interger] - @ivar mode: sensor mode: 1=KX_MOUSESENSORMODE_LEFTBUTTON 2=KX_MOUSESENSORMODE_MIDDLEBUTTON - 3=KX_MOUSESENSORMODE_RIGHTBUTTON 4=KX_MOUSESENSORMODE_WHEELUP - 5=KX_MOUSESENSORMODE_WHEELDOWN 9=KX_MOUSESENSORMODE_MOVEMENT - @type mode: integer - """ - - def getXPosition(): - """ - DEPRECATED: use the position property - Gets the x coordinate of the mouse. - - @rtype: integer - @return: the current x coordinate of the mouse, in frame coordinates (pixels) - """ - def getYPosition(): - """ - DEPRECATED: use the position property - Gets the y coordinate of the mouse. - - @rtype: integer - @return: the current y coordinate of the mouse, in frame coordinates (pixels). - """ - def getButtonStatus(button): - """ - Get the mouse button status. - - @type button: int - @param button: value in GameLogic members KX_MOUSE_BUT_LEFT, KX_MOUSE_BUT_MIDDLE, KX_MOUSE_BUT_RIGHT - - @rtype: integer - @return: value in GameLogic members KX_INPUT_NONE, KX_INPUT_NONE, KX_INPUT_JUST_ACTIVATED, KX_INPUT_ACTIVE, KX_INPUT_JUST_RELEASED - """ diff --git a/source/gameengine/PyDoc/SCA_NANDController.py b/source/gameengine/PyDoc/SCA_NANDController.py deleted file mode 100644 index a864ff2981c..00000000000 --- a/source/gameengine/PyDoc/SCA_NANDController.py +++ /dev/null @@ -1,11 +0,0 @@ -# $Id$ -# Documentation for SCA_NANDController -from SCA_IController import * - -class SCA_NANDController(SCA_IController): - """ - An NAND controller activates when all linked sensors are not active. - - There are no special python methods for this controller. - """ - diff --git a/source/gameengine/PyDoc/SCA_NORController.py b/source/gameengine/PyDoc/SCA_NORController.py deleted file mode 100644 index 0bc0a71d7b1..00000000000 --- a/source/gameengine/PyDoc/SCA_NORController.py +++ /dev/null @@ -1,11 +0,0 @@ -# $Id$ -# Documentation for SCA_NORController -from SCA_IController import * - -class SCA_NORController(SCA_IController): - """ - An NOR controller activates only when all linked sensors are de-activated. - - There are no special python methods for this controller. - """ - diff --git a/source/gameengine/PyDoc/SCA_ORController.py b/source/gameengine/PyDoc/SCA_ORController.py deleted file mode 100644 index eeeb9de3afe..00000000000 --- a/source/gameengine/PyDoc/SCA_ORController.py +++ /dev/null @@ -1,11 +0,0 @@ -# $Id$ -# Documentation for SCA_ORController -from SCA_IController import * - -class SCA_ORController(SCA_IController): - """ - An OR controller activates when any connected sensor activates. - - There are no special python methods for this controller. - """ - diff --git a/source/gameengine/PyDoc/SCA_PropertyActuator.py b/source/gameengine/PyDoc/SCA_PropertyActuator.py deleted file mode 100644 index 52aefcae651..00000000000 --- a/source/gameengine/PyDoc/SCA_PropertyActuator.py +++ /dev/null @@ -1,49 +0,0 @@ -# $Id$ -# Documentation for SCA_PropertyActuator -from SCA_IActuator import * - -class SCA_PropertyActuator(SCA_IActuator): - """ - Property Actuator - - Properties: - - @ivar property: the property on which to operate. - @type property: string - @ivar value: the value with which the actuator operates. - @type value: string - """ - def setProperty(prop): - """ - DEPRECATED: use the 'property' property - Set the property on which to operate. - - If there is no property of this name, the call is ignored. - - @type prop: string - @param prop: The name of the property to set. - """ - def getProperty(): - """ - DEPRECATED: use the 'property' property - Returns the name of the property on which to operate. - - @rtype: string - """ - def setValue(value): - """ - DEPRECATED: use the 'value' property - Set the value with which the actuator operates. - - If the value is not compatible with the type of the - property, the subsequent action is ignored. - - @type value: string - """ - def getValue(): - """ - DEPRECATED: use the 'value' property - Gets the value with which this actuator operates. - - @rtype: string - """ diff --git a/source/gameengine/PyDoc/SCA_PropertySensor.py b/source/gameengine/PyDoc/SCA_PropertySensor.py deleted file mode 100644 index 949ffd3b703..00000000000 --- a/source/gameengine/PyDoc/SCA_PropertySensor.py +++ /dev/null @@ -1,74 +0,0 @@ -# $Id$ -# Documentation for SCA_PropertySensor -from SCA_ISensor import * - -class SCA_PropertySensor(SCA_ISensor): - """ - Activates when the game object property matches. - - Properties: - - @ivar type: type of check on the property: - KX_PROPSENSOR_EQUAL(1), KX_PROPSENSOR_NOTEQUAL(2), KX_PROPSENSOR_INTERVAL(3), - KX_PROPSENSOR_CHANGED(4), KX_PROPSENSOR_EXPRESSION(5) - @type type: integer - @ivar property: the property with which the sensor operates. - @type property: string - @ivar value: the value with which the sensor compares to the value of the property. - @type value: string - """ - - def getType(): - """ - DEPRECATED: use the type property - Gets when to activate this sensor. - - @return: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL, - KX_PROPSENSOR_INTERVAL, KX_PROPSENSOR_CHANGED, - or KX_PROPSENSOR_EXPRESSION. - """ - - def setType(checktype): - """ - DEPRECATED: use the type property - Set the type of check to perform. - - @type checktype: KX_PROPSENSOR_EQUAL, KX_PROPSENSOR_NOTEQUAL, - KX_PROPSENSOR_INTERVAL, KX_PROPSENSOR_CHANGED, - or KX_PROPSENSOR_EXPRESSION. - """ - - def getProperty(): - """ - DEPRECATED: use the property property - Return the property with which the sensor operates. - - @rtype: string - @return: the name of the property this sensor is watching. - """ - def setProperty(name): - """ - DEPRECATED: use the property property - Sets the property with which to operate. If there is no property - of that name, this call is ignored. - - @type name: string. - """ - def getValue(): - """ - DEPRECATED: use the value property - Return the value with which the sensor compares to the value of the property. - - @rtype: string - @return: the value of the property this sensor is watching. - """ - def setValue(value): - """ - DEPRECATED: use the value property - Set the value with which the sensor operates. If the value - is not compatible with the type of the property, the subsequent - action is ignored. - - @type value: string - """ - diff --git a/source/gameengine/PyDoc/SCA_PythonController.py b/source/gameengine/PyDoc/SCA_PythonController.py deleted file mode 100644 index 9684b41d481..00000000000 --- a/source/gameengine/PyDoc/SCA_PythonController.py +++ /dev/null @@ -1,77 +0,0 @@ -# $Id$ -# Documentation for SCA_PythonController -from SCA_IController import * - -class SCA_PythonController(SCA_IController): - """ - A Python controller uses a Python script to activate it's actuators, - based on it's sensors. - - Properties: - - @ivar script: the Python script this controller executes - @type script: string, read-only - @ivar state: the controllers state bitmask. - This can be used with the GameObject's state to test if the controller is active. - @type state: integer - """ - def activate(actuator): - """ - Activates an actuator attached to this controller. - @type actuator: actuator or the actuator name as a string - """ - def deactivate(actuator): - """ - Deactivates an actuator attached to this controller. - @type actuator: actuator or the actuator name as a string - """ - - def getSensors(): - """ - Gets a list of all sensors attached to this controller. - - @rtype: list [L{SCA_ISensor}] - """ - def getSensor(name): - """ - Gets the named linked sensor. - - @type name: string - @rtype: L{SCA_ISensor} - """ - def getActuators(): - """ - Gets a list of all actuators linked to this controller. - - @rtype: list [L{SCA_IActuator}] - """ - def getActuator(name): - """ - Gets the named linked actuator. - - @type name: string - @rtype: L{SCA_IActuator} - """ - def getScript(): - """ - DEPRECATED: use the script property - Gets the Python script this controller executes. - - @rtype: string - """ - def setScript(script): - """ - Sets the Python script this controller executes. - - @type script: string. - """ - def getState(): - """ - DEPRECATED: use the state property - Get the controllers state bitmask, this can be used with the GameObject's state to test if the the controller is active. - This for instance will always be true however you could compare with a previous state to see when the state was activated. - GameLogic.getCurrentController().getState() & GameLogic.getCurrentController().getOwner().getState() - - @rtype: int - """ - diff --git a/source/gameengine/PyDoc/SCA_RandomActuator.py b/source/gameengine/PyDoc/SCA_RandomActuator.py deleted file mode 100644 index 000a1af7846..00000000000 --- a/source/gameengine/PyDoc/SCA_RandomActuator.py +++ /dev/null @@ -1,175 +0,0 @@ -# $Id$ -# Documentation for SCA_RandomActuator -from SCA_IActuator import * - -class SCA_RandomActuator(SCA_IActuator): - """ - Random Actuator - - Properties: - - @ivar seed: Seed of the random number generator. - Equal seeds produce equal series. If the seed is 0, - the generator will produce the same value on every call. - @type seed: integer - @ivar para1: the first parameter of the active distribution. - Refer to the documentation of the generator types for the meaning - of this value. - @type para1: float, read-only - @ivar para2: the second parameter of the active distribution. - Refer to the documentation of the generator types for the meaning - of this value. - @type para2: float, read-only - @ivar distribution: distribution type: - KX_RANDOMACT_BOOL_CONST, KX_RANDOMACT_BOOL_UNIFORM, KX_RANDOMACT_BOOL_BERNOUILLI, - KX_RANDOMACT_INT_CONST, KX_RANDOMACT_INT_UNIFORM, KX_RANDOMACT_INT_POISSON, - KX_RANDOMACT_FLOAT_CONST, KX_RANDOMACT_FLOAT_UNIFORM, KX_RANDOMACT_FLOAT_NORMAL, - KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL - @type distribution: integer, read-only - @ivar property: the name of the property to set with the random value. - If the generator and property types do not match, the assignment is ignored. - @type property: string - - """ - def setSeed(seed): - """ - DEPRECATED: use the seed property - Sets the seed of the random number generator. - - Equal seeds produce equal series. If the seed is 0, - the generator will produce the same value on every call. - - @type seed: integer - """ - def getSeed(): - """ - DEPRECATED: use the seed property - Returns the initial seed of the generator. - - @rtype: integer - """ - def getPara1(): - """ - DEPRECATED: use the para1 property - Returns the first parameter of the active distribution. - - Refer to the documentation of the generator types for the meaning - of this value. - - @rtype: float - """ - def getPara2(): - """ - DEPRECATED: use the para2 property - Returns the second parameter of the active distribution. - - Refer to the documentation of the generator types for the meaning - of this value. - - @rtype: float - """ - def getDistribution(): - """ - DEPRECATED: use the distribution property - Returns the type of random distribution. - - @rtype: distribution type - @return: KX_RANDOMACT_BOOL_CONST, KX_RANDOMACT_BOOL_UNIFORM, KX_RANDOMACT_BOOL_BERNOUILLI, - KX_RANDOMACT_INT_CONST, KX_RANDOMACT_INT_UNIFORM, KX_RANDOMACT_INT_POISSON, - KX_RANDOMACT_FLOAT_CONST, KX_RANDOMACT_FLOAT_UNIFORM, KX_RANDOMACT_FLOAT_NORMAL, - KX_RANDOMACT_FLOAT_NEGATIVE_EXPONENTIAL - """ - def setProperty(property): - """ - DEPRECATED: use the property property - Set the property to which the random value is assigned. - - If the generator and property types do not match, the assignment is ignored. - - @type property: string - @param property: The name of the property to set. - """ - def getProperty(): - """ - DEPRECATED: use the property property - Returns the name of the property to set. - - @rtype: string - """ - def setBoolConst(value): - """ - Sets this generator to produce a constant boolean value. - - @param value: The value to return. - @type value: boolean - """ - def setBoolUniform(): - """ - Sets this generator to produce a uniform boolean distribution. - - The generator will generate True or False with 50% chance. - """ - def setBoolBernouilli(value): - """ - Sets this generator to produce a Bernouilli distribution. - - @param value: Specifies the proportion of False values to produce. - - 0.0: Always generate True - - 1.0: Always generate False - @type value: float - """ - def setIntConst(value): - """ - Sets this generator to always produce the given value. - - @param value: the value this generator produces. - @type value: integer - """ - def setIntUniform(lower_bound, upper_bound): - """ - Sets this generator to produce a random value between the given lower and - upper bounds (inclusive). - - @type lower_bound: integer - @type upper_bound: integer - """ - def setIntPoisson(value): - """ - Generate a Poisson-distributed number. - - This performs a series of Bernouilli tests with parameter value. - It returns the number of tries needed to achieve succes. - - @type value: float - """ - def setFloatConst(value): - """ - Always generate the given value. - - @type value: float - """ - def setFloatUniform(lower_bound, upper_bound): - """ - Generates a random float between lower_bound and upper_bound with a - uniform distribution. - - @type lower_bound: float - @type upper_bound: float - """ - def setFloatNormal(mean, standard_deviation): - """ - Generates a random float from the given normal distribution. - - @type mean: float - @param mean: The mean (average) value of the generated numbers - @type standard_deviation: float - @param standard_deviation: The standard deviation of the generated numbers. - """ - def setFloatNegativeExponential(half_life): - """ - Generate negative-exponentially distributed numbers. - - The half-life 'time' is characterized by half_life. - - @type half_life: float - """ diff --git a/source/gameengine/PyDoc/SCA_RandomSensor.py b/source/gameengine/PyDoc/SCA_RandomSensor.py deleted file mode 100644 index 6dc0a3c23c0..00000000000 --- a/source/gameengine/PyDoc/SCA_RandomSensor.py +++ /dev/null @@ -1,35 +0,0 @@ -# $Id$ -# Documentation for SCA_RandomSensor -from SCA_ISensor import * - -class SCA_RandomSensor(SCA_ISensor): - """ - This sensor activates randomly. - - @ivar lastDraw: The seed of the random number generator. - @type lastDraw: int - @ivar seed: The seed of the random number generator. - @type seed: int - """ - - def setSeed(seed): - """ - Sets the seed of the random number generator. - - If the seed is 0, the generator will produce the same value on every call. - - @type seed: integer. - """ - def getSeed(): - """ - Returns the initial seed of the generator. Equal seeds produce equal random - series. - - @rtype: integer - """ - def getLastDraw(): - """ - Returns the last random number generated. - - @rtype: integer - """ diff --git a/source/gameengine/PyDoc/SCA_XNORController.py b/source/gameengine/PyDoc/SCA_XNORController.py deleted file mode 100644 index 5fb2561f35a..00000000000 --- a/source/gameengine/PyDoc/SCA_XNORController.py +++ /dev/null @@ -1,11 +0,0 @@ -# $Id$ -# Documentation for SCA_XNORController -from SCA_IController import * - -class SCA_XNORController(SCA_IController): - """ - An XNOR controller activates when all linked sensors are the same (activated or inative). - - There are no special python methods for this controller. - """ - diff --git a/source/gameengine/PyDoc/SCA_XORController.py b/source/gameengine/PyDoc/SCA_XORController.py deleted file mode 100644 index 10e20fb0945..00000000000 --- a/source/gameengine/PyDoc/SCA_XORController.py +++ /dev/null @@ -1,11 +0,0 @@ -# $Id$ -# Documentation for SCA_XORController -from SCA_IController import * - -class SCA_XORController(SCA_IController): - """ - An XOR controller activates when there is the input is mixed, but not when all are on or off. - - There are no special python methods for this controller. - """ - diff --git a/source/gameengine/PyDoc/WhatsNew.py b/source/gameengine/PyDoc/WhatsNew.py deleted file mode 100644 index 4d86e6ef3c4..00000000000 --- a/source/gameengine/PyDoc/WhatsNew.py +++ /dev/null @@ -1,34 +0,0 @@ -# $Id$ -""" -New Python Functionality in this Version of Blender -=================================================== - -This document lists what has been changed in the Game Engine Python API. - -Blender CVS - - Added L{KX_GameObject}.getDistanceTo() method. (thanks Charlie C) - - Added L{KX_PolygonMaterial} module - -Blender 2.36 ------------- - - Added L{KX_CameraActuator} methods (thanks snail) - -Blender 2.35 ------------- - - Added tic rate methods to L{GameLogic} - - Added stereo eye separation and focal length methods to L{Rasterizer}. - - Fixed L{Rasterizer}.makeScreenshot() method. - - Added setLogicTicRate() and setPhysicsTicRate() to L{GameLogic} - -Blender 2.34 ------------- - - - Added getType() and setType() to L{BL_ActionActuator} and L{KX_SoundActuator} (sgefant) - - New Scene module: L{KX_Scene} - - New Camera module: L{KX_Camera} - - New Light module: L{KX_LightObject} - - Added attributes to L{KX_GameObject}, L{KX_VertexProxy} - - L{KX_SCA_AddObjectActuator}.setObject(), L{KX_TrackToActuator}.setObject() and - L{KX_SceneActuator}.setCamera() now accept L{KX_GameObject}s as parameters - -""" diff --git a/source/gameengine/PyDoc/bge_api_validate_py.txt b/source/gameengine/PyDoc/bge_api_validate_py.txt index 0920e5d3c7d..ebd74c06bb3 100644 --- a/source/gameengine/PyDoc/bge_api_validate_py.txt +++ b/source/gameengine/PyDoc/bge_api_validate_py.txt @@ -12,9 +12,17 @@ # # Currently it only prints missing modules and methods (not attributes) +import sys, os BGE_API_DOC_PATH = 'source/gameengine/PyDoc' + +mods = ['GameLogic', 'Rasterizer', 'GameKeys'] +mods_dict = {} +for m in mods: + mods_dict[m] = sys.modules[m] + + import GameTypes type_members = {} @@ -34,7 +42,7 @@ for type_name in dir(GameTypes): # print type_object.__name__ + '.' + k members.append(member) -import sys, os + doc_dir= os.path.join(os.getcwd(), BGE_API_DOC_PATH) @@ -42,13 +50,12 @@ if doc_dir not in sys.path: sys.path.append(doc_dir) -def check_attribute(type_mame, member): - filename = os.path.join(doc_dir, type_mame + '.py') - # print filename +def check_attribute(class_ob, member): + doc = class_ob.__doc__ + if not doc: + return False - file = open(filename, 'rU') - - for l in file: + for l in doc.split('\n'): l = l.strip() ''' @@ -58,14 +65,12 @@ def check_attribute(type_mame, member): ''' - if l.startswith('@ivar'): + if l.startswith('@ivar') or l.startswith('@var'): var = l.split()[1].split(':')[0] if var == member: - file.close() return True - file.close() return False @@ -77,20 +82,16 @@ print '\n\n\nChecking Docs' PRINT_OK = False +pymod = sys.modules['GameTypes'] +del sys.modules['GameTypes'] # temp remove +mod = __import__('GameTypes') # get the python module +reload(mod) # incase were editing it +sys.modules['GameTypes'] = pymod + for type_name in sorted(type_members.keys()): members = type_members[type_name] try: - mod = __import__(type_name) - if PRINT_OK: - print "type: %s" % type_name - except: - print "missing: %s - %s" % (type_name, str(sorted(members))) - continue - - reload(mod) # incase were editing it - - try: type_class = getattr(mod, type_name) except: print "missing class: %s.%s - %s" % (type_name, type_name, str(sorted(members))) @@ -102,9 +103,34 @@ for type_name in sorted(type_members.keys()): if PRINT_OK: print "\tfound: %s.%s" % (type_name, member) except: - if check_attribute(type_name, member): + if check_attribute(type_class, member): if PRINT_OK: print "\tfound attr: %s.%s" % (type_name, member) else: print "\tmissing: %s.%s" % (type_name, member) + +# Now check the modules +for mod_name, pymod in mods_dict.iteritems(): + print pymod + del sys.modules[mod_name] + + # Now well get the python version + pydoc = __import__(mod_name) + pydoc = reload(pydoc) # avoid using the out dated pyc file only + print pydoc.__file__ + + for member in sorted(dir(pymod)): + if hasattr(pydoc, member) or check_attribute(pydoc, member): + if PRINT_OK: + print "\tfound module attr: %s.%s" % (mod_name, member) + else: + print "\tmissing module attr: %s.%s" % (mod_name, member) + + # Restore real module + sys.modules[mod_name] = pymod + + +sys.path.pop() # remove the pydoc dir from our import paths + + diff --git a/source/gameengine/PyDoc/epy_docgen.sh b/source/gameengine/PyDoc/epy_docgen.sh index ddf39dcc081..dd30256f42f 100755 --- a/source/gameengine/PyDoc/epy_docgen.sh +++ b/source/gameengine/PyDoc/epy_docgen.sh @@ -7,5 +7,10 @@ # set posix locale so regex works properly for [A-Z]*.py LC_ALL=POSIX -epydoc --debug -v -o BPY_GE --url "http://www.blender.org" --top GameLogic \ - --name "Blender GameEngine" --no-private --no-frames --no-sourcecode --inheritance=included *.py +epydoc --debug -v -o BPY_GE --url "http://www.blender.org" --top API_intro \ + --name "Blender GameEngine" --no-private --no-sourcecode --inheritance=included \ + *.py \ + ../../../source/blender/python/api2_2x/doc/BGL.py \ + ../../../source/blender/python/api2_2x/doc/Mathutils.py \ + ../../../source/blender/python/api2_2x/doc/Geometry.py + diff --git a/source/gameengine/Rasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/CMakeLists.txt index 6d53ee53471..143209f5a54 100644 --- a/source/gameengine/Rasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/CMakeLists.txt @@ -29,6 +29,8 @@ FILE(GLOB SRC *.cpp) SET(INC . ../../../source/kernel/gen_system + ../../../source/blender/makesdna + ../../../source/gameengine/SceneGraph ../../../intern/string ../../../intern/moto/include ../../../extern/glew/include diff --git a/source/gameengine/Rasterizer/Makefile b/source/gameengine/Rasterizer/Makefile index 917f70c7108..eafa2ded2f2 100644 --- a/source/gameengine/Rasterizer/Makefile +++ b/source/gameengine/Rasterizer/Makefile @@ -40,6 +40,8 @@ CPPFLAGS += -I$(OPENGL_HEADERS) CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I../../kernel/gen_system +CPPFLAGS += -I../../blender/makesdna +CPPFLAGS += -I../SceneGraph CPPFLAGS += -I../BlenderRoutines CPPFLAGS += -I../Expressions diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp index 176da51b183..239031866ca 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp @@ -63,11 +63,9 @@ numberoffilters(0), need_tex_update(true) isshadersupported = GLEW_ARB_shader_objects && GLEW_ARB_fragment_shader && GLEW_ARB_multitexture; + /* used to return before 2.49 but need to initialize values so dont */ if(!isshadersupported) - { std::cout<<"shaders not supported!" << std::endl; - return; - } int passindex; for(passindex =0; passindex<MAX_RENDER_PASS; passindex++) diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.cpp b/source/gameengine/Rasterizer/RAS_BucketManager.cpp index ec290f89d9e..200b1c6c89f 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.cpp +++ b/source/gameengine/Rasterizer/RAS_BucketManager.cpp @@ -113,16 +113,26 @@ void RAS_BucketManager::OrderBuckets(const MT_Transform& cameratrans, BucketList const MT_Vector3 pnorm(cameratrans.getBasis()[2]); for (bit = buckets.begin(); bit != buckets.end(); ++bit) - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) - if (!mit->IsCulled()) - size++; + { + SG_DList::iterator<RAS_MeshSlot> mit((*bit)->GetActiveMeshSlots()); + for(mit.begin(); !mit.end(); ++mit) + size++; + } slots.resize(size); for (bit = buckets.begin(); bit != buckets.end(); ++bit) - for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) - if (!mit->IsCulled()) - slots[i++].set(&*mit, *bit, pnorm); + { + RAS_MaterialBucket* bucket = *bit; + RAS_MeshSlot* ms; + // remove the mesh slot form the list, it culls them automatically for next frame + for(ms = bucket->GetNextActiveMeshSlot(); + ms!= NULL; + ms = bucket->GetNextActiveMeshSlot()) + { + slots[i++].set(ms, bucket, pnorm); + } + } if(alpha) sort(slots.begin(), slots.end(), backtofront()); @@ -161,11 +171,28 @@ void RAS_BucketManager::RenderSolidBuckets( const MT_Transform& cameratrans, RAS_IRasterizer* rasty, RAS_IRenderTools* rendertools) { BucketList::iterator bit; - list<RAS_MeshSlot>::iterator mit; rasty->SetDepthMask(RAS_IRasterizer::KX_DEPTHMASK_ENABLED); for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { +#if 1 + RAS_MaterialBucket* bucket = *bit; + RAS_MeshSlot* ms; + // remove the mesh slot form the list, it culls them automatically for next frame + for(ms = bucket->GetNextActiveMeshSlot(); + ms!= NULL; + ms = bucket->GetNextActiveMeshSlot()) + { + rendertools->SetClientObject(rasty, ms->m_clientObj); + while (bucket->ActivateMaterial(cameratrans, rasty, rendertools)) + bucket->RenderMeshSlot(cameratrans, rasty, rendertools, *ms); + + // make this mesh slot culled automatically for next frame + // it will be culled out by frustrum culling + ms->SetCulled(true); + } +#else + list<RAS_MeshSlot>::iterator mit; for (mit = (*bit)->msBegin(); mit != (*bit)->msEnd(); ++mit) { if (mit->IsCulled()) continue; @@ -179,6 +206,7 @@ void RAS_BucketManager::RenderSolidBuckets( // it will be culled out by frustrum culling mit->SetCulled(true); } +#endif } /* this code draws meshes order front-to-back instead to reduce overdraw. @@ -276,3 +304,21 @@ void RAS_BucketManager::ReleaseDisplayLists(RAS_IPolyMaterial *mat) } } +void RAS_BucketManager::ReleaseMaterials(RAS_IPolyMaterial * mat) +{ + BucketList::iterator bit; + list<RAS_MeshSlot>::iterator mit; + + for (bit = m_SolidBuckets.begin(); bit != m_SolidBuckets.end(); ++bit) { + if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) { + (*bit)->GetPolyMaterial()->ReleaseMaterial(); + } + } + + for (bit = m_AlphaBuckets.begin(); bit != m_AlphaBuckets.end(); ++bit) { + if (mat == NULL || (mat == (*bit)->GetPolyMaterial())) { + (*bit)->GetPolyMaterial()->ReleaseMaterial(); + } + } +} + diff --git a/source/gameengine/Rasterizer/RAS_BucketManager.h b/source/gameengine/Rasterizer/RAS_BucketManager.h index 74526f365a0..2b81ddd3c82 100644 --- a/source/gameengine/Rasterizer/RAS_BucketManager.h +++ b/source/gameengine/Rasterizer/RAS_BucketManager.h @@ -58,6 +58,7 @@ public: void OptimizeBuckets(MT_Scalar distance); void ReleaseDisplayLists(RAS_IPolyMaterial * material = NULL); + void ReleaseMaterials(RAS_IPolyMaterial * material = NULL); private: void OrderBuckets(const MT_Transform& cameratrans, BucketList& buckets, vector<sortedmeshslot>& slots, bool alpha); diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h index e3af43fb839..c8f4d9a0a17 100644 --- a/source/gameengine/Rasterizer/RAS_CameraData.h +++ b/source/gameengine/Rasterizer/RAS_CameraData.h @@ -32,6 +32,7 @@ struct RAS_CameraData { float m_lens; + float m_scale; float m_clipstart; float m_clipend; bool m_perspective; @@ -42,10 +43,11 @@ struct RAS_CameraData int m_viewporttop; float m_focallength; - RAS_CameraData(float lens = 35.0, float clipstart = 0.1, float clipend = 5000.0, bool perspective = true, + RAS_CameraData(float lens = 35.0, float scale = 6.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), + m_scale(scale), m_clipstart(clipstart), m_clipend(clipend), m_perspective(perspective), diff --git a/source/gameengine/Rasterizer/RAS_Deformer.h b/source/gameengine/Rasterizer/RAS_Deformer.h index 3332ac4c0a7..fe9b1540af8 100644 --- a/source/gameengine/Rasterizer/RAS_Deformer.h +++ b/source/gameengine/Rasterizer/RAS_Deformer.h @@ -34,23 +34,47 @@ #pragma warning (disable:4786) // get rid of stupid stl-visual compiler debug warning #endif //WIN32 +#include <stdlib.h> #include "GEN_Map.h" +struct DerivedMesh; + class RAS_Deformer { public: - RAS_Deformer(){}; + RAS_Deformer() : m_pMesh(NULL), m_bDynamic(false) {}; virtual ~RAS_Deformer(){}; virtual void Relink(GEN_Map<class GEN_HashedPtr, void*>*map)=0; virtual bool Apply(class RAS_IPolyMaterial *polymat)=0; virtual bool Update(void)=0; - virtual RAS_Deformer *GetReplica(class KX_GameObject* replica)=0; + virtual bool UpdateBuckets(void)=0; + virtual RAS_Deformer *GetReplica()=0; + virtual void ProcessReplica()=0; virtual bool SkipVertexTransform() { return false; } + virtual bool ShareVertexArray() + { + return true; + } + virtual bool UseVertexArray() + { + return true; + } + // true when deformer produces varying vertex (shape or armature) + bool IsDynamic() + { + return m_bDynamic; + } + virtual struct DerivedMesh* GetFinalMesh() + { + return NULL; + } + protected: class RAS_MeshObject *m_pMesh; + bool m_bDynamic; }; #endif diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.cpp b/source/gameengine/Rasterizer/RAS_FramingManager.cpp index e2bbca48bb5..ea18ffb2298 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.cpp +++ b/source/gameengine/Rasterizer/RAS_FramingManager.cpp @@ -72,6 +72,39 @@ ComputeDefaultFrustum( void RAS_FramingManager:: +ComputeDefaultOrtho( + const float camnear, + const float camfar, + const float scale, + const float design_aspect_ratio, + RAS_FrameFrustum & frustum +) +{ + float halfSize = scale*0.5f; + float sizeX; + float sizeY; + + if (design_aspect_ratio > 1.f) { + // halfsize defines the width + sizeX = halfSize; + sizeY = halfSize/design_aspect_ratio; + } else { + // halfsize defines the height + sizeX = halfSize * design_aspect_ratio; + sizeY = halfSize; + } + + frustum.x2 = sizeX; + frustum.x1 = -frustum.x2; + frustum.y2 = sizeY; + frustum.y1 = -frustum.y2; + frustum.camnear = -camfar; + frustum.camfar = camfar; +} + + + void +RAS_FramingManager:: ComputeBestFitViewRect( const RAS_Rect &availableViewport, const float design_aspect_ratio, @@ -227,5 +260,73 @@ ComputeFrustum( } } + void +RAS_FramingManager:: + ComputeOrtho( + const RAS_FrameSettings &settings, + const RAS_Rect &availableViewport, + const RAS_Rect &viewport, + const float scale, + const float camnear, + const float camfar, + RAS_FrameFrustum &frustum + ) +{ + RAS_FrameSettings::RAS_FrameType type = settings.FrameType(); + + const float design_width = float(settings.DesignAspectWidth()); + const float design_height = float(settings.DesignAspectHeight()); + + float design_aspect_ratio = float(1); + + if (design_height == float(0)) { + // well this is ill defined + // lets just scale the thing + type = RAS_FrameSettings::e_frame_scale; + } else { + design_aspect_ratio = design_width/design_height; + } + + + ComputeDefaultOrtho( + camnear, + camfar, + scale, + design_aspect_ratio, + frustum + ); + + switch (type) { + + case RAS_FrameSettings::e_frame_extend: + { + RAS_Rect vt; + ComputeBestFitViewRect( + availableViewport, + design_aspect_ratio, + vt + ); + + // now scale the calculated frustum by the difference + // between vt and the viewport in each axis. + // These are always > 1 + + float x_scale = float(viewport.GetWidth())/float(vt.GetWidth()); + float y_scale = float(viewport.GetHeight())/float(vt.GetHeight()); + + frustum.x1 *= x_scale; + frustum.x2 *= x_scale; + frustum.y1 *= y_scale; + frustum.y2 *= y_scale; + + break; + } + case RAS_FrameSettings::e_frame_scale : + case RAS_FrameSettings::e_frame_bars: + default : + break; + } + +} diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h index 0a226ac30f9..4398e2d00c3 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.h +++ b/source/gameengine/Rasterizer/RAS_FramingManager.h @@ -209,6 +209,18 @@ public : static void + ComputeOrtho( + const RAS_FrameSettings &settings, + const RAS_Rect &availableViewport, + const RAS_Rect &viewport, + const float scale, + const float camnear, + const float camfar, + RAS_FrameFrustum &frustum + ); + + static + void ComputeFrustum( const RAS_FrameSettings &settings, const RAS_Rect &availableViewport, @@ -229,6 +241,16 @@ public : RAS_FrameFrustum & frustum ); + static + void + ComputeDefaultOrtho( + const float camnear, + const float camfar, + const float scale, + const float design_aspect_ratio, + RAS_FrameFrustum & frustum + ); + private : static diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index cd88112007b..6af00d63c2d 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -29,12 +29,71 @@ #include "RAS_IPolygonMaterial.h" #include "RAS_IRasterizer.h" +#include "DNA_image_types.h" +#include "DNA_meshdata_types.h" + #ifdef HAVE_CONFIG_H #include <config.h> #endif +void RAS_IPolyMaterial::Initialize( + const STR_String& texname, + const STR_String& matname, + int materialindex, + int tile, + int tilexrep, + int tileyrep, + int mode, + int transp, + bool alpha, + bool zsort, + int lightlayer) +{ + m_texturename = texname; + m_materialname = matname; + m_materialindex = materialindex; + m_tile = tile; + m_tilexrep = tilexrep; + m_tileyrep = tileyrep; + m_drawingmode = mode; + m_transp = transp; + m_alpha = alpha; + m_zsort = zsort; + //m_lightlayer = lightlayer; + m_polymatid = m_newpolymatid++; + m_flag = 0; + m_multimode = 0; + m_shininess = 35.0; + m_specular.setValue(0.5,0.5,0.5); + m_specularity = 1.0; + m_diffuse.setValue(0.5,0.5,0.5); +} + +RAS_IPolyMaterial::RAS_IPolyMaterial() + : m_texturename("__Dummy_Texture_Name__"), + m_materialname("__Dummy_Material_Name__"), + m_materialindex(0), + m_tile(0), + m_tilexrep(0), + m_tileyrep(0), + m_drawingmode (0), + m_transp(0), + m_alpha(false), + m_zsort(false), + //m_lightlayer(0), + m_polymatid(0), + m_flag(0), + m_multimode(0) +{ + m_shininess = 35.0; + m_specular = MT_Vector3(0.5,0.5,0.5); + m_specularity = 1.0; + m_diffuse = MT_Vector3(0.5,0.5,0.5); +} + RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, const STR_String& matname, + int materialindex, int tile, int tilexrep, int tileyrep, @@ -45,6 +104,7 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, int lightlayer) : m_texturename(texname), m_materialname(matname), + m_materialindex(materialindex), m_tile(tile), m_tilexrep(tilexrep), m_tileyrep(tileyrep), @@ -52,7 +112,7 @@ RAS_IPolyMaterial::RAS_IPolyMaterial(const STR_String& texname, m_transp(transp), m_alpha(alpha), m_zsort(zsort), - m_lightlayer(lightlayer), + //m_lightlayer(lightlayer), m_polymatid(m_newpolymatid++), m_flag(0), m_multimode(0) @@ -95,6 +155,15 @@ bool RAS_IPolyMaterial::Equals(const RAS_IPolyMaterial& lhs) const } } + +void RAS_IPolyMaterial::GetMaterialRGBAColor(unsigned char *rgba) const +{ + *rgba++ = 0xFF; + *rgba++ = 0xFF; + *rgba++ = 0xFF; + *rgba++ = 0xFF; +} + bool RAS_IPolyMaterial::Less(const RAS_IPolyMaterial& rhs) const { if (Equals(rhs)) @@ -103,10 +172,10 @@ bool RAS_IPolyMaterial::Less(const RAS_IPolyMaterial& rhs) const return m_polymatid < rhs.m_polymatid; } -int RAS_IPolyMaterial::GetLightLayer() const -{ - return m_lightlayer; -} +//int RAS_IPolyMaterial::GetLightLayer() const +//{ +// return m_lightlayer; +//} bool RAS_IPolyMaterial::IsAlpha() const { @@ -143,6 +212,25 @@ const STR_String& RAS_IPolyMaterial::GetTextureName() const return m_texturename; } +int RAS_IPolyMaterial::GetMaterialIndex() const +{ + return m_materialindex; +} + +Material *RAS_IPolyMaterial::GetBlenderMaterial() const +{ + return NULL; +} + +Scene* RAS_IPolyMaterial::GetBlenderScene() const +{ + return NULL; +} + +void RAS_IPolyMaterial::ReleaseMaterial() +{ +} + unsigned int RAS_IPolyMaterial::GetFlag() const { return m_flag; diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index e5b24070c4b..e19db35ccb5 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -39,6 +39,9 @@ #include "STR_HashedString.h" class RAS_IRasterizer; +struct MTFace; +struct Material; +struct Scene; enum MaterialProps { @@ -70,7 +73,8 @@ protected: int m_transp; bool m_alpha; bool m_zsort; - int m_lightlayer; + //int m_lightlayer; + int m_materialindex; unsigned int m_polymatid; static unsigned int m_newpolymatid; @@ -96,8 +100,10 @@ public: SHADOW =8192 }; + RAS_IPolyMaterial(); RAS_IPolyMaterial(const STR_String& texname, const STR_String& matname, + int materialindex, int tile, int tilexrep, int tileyrep, @@ -106,6 +112,17 @@ public: bool alpha, bool zsort, int lightlayer); + void Initialize(const STR_String& texname, + const STR_String& matname, + int materialindex, + int tile, + int tilexrep, + int tileyrep, + int mode, + int transp, + bool alpha, + bool zsort, + int lightlayer); virtual ~RAS_IPolyMaterial() {}; /** @@ -130,7 +147,7 @@ public: virtual bool Equals(const RAS_IPolyMaterial& lhs) const; bool Less(const RAS_IPolyMaterial& rhs) const; - int GetLightLayer() const; + //int GetLightLayer() const; bool IsAlpha() const; bool IsZSort() const; unsigned int hash() const; @@ -139,14 +156,18 @@ public: dword GetMaterialNameHash() const; const STR_String& GetTextureName() const; unsigned int GetFlag() const; + int GetMaterialIndex() const; + virtual Material* GetBlenderMaterial() const; + virtual Scene* GetBlenderScene() const; + virtual void ReleaseMaterial(); + virtual void GetMaterialRGBAColor(unsigned char *rgba) const; virtual bool UsesLighting(RAS_IRasterizer *rasty) const; virtual bool UsesObjectColor() const; - /* * PreCalculate texture gen */ - virtual void OnConstruction(){} + virtual void OnConstruction(int layer){} }; inline bool operator ==( const RAS_IPolyMaterial & rhs,const RAS_IPolyMaterial & lhs) diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index cfeda06e670..dc8c3c1ebf8 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -250,9 +250,9 @@ public: * Sets the modelview matrix. */ virtual void SetViewMatrix(const MT_Matrix4x4 & mat, - const MT_Vector3& campos, - const MT_Point3 &camLoc, - const MT_Quaternion &camOrientQuat)=0; + const MT_Matrix3x3 & ori, + const MT_Point3 & pos, + bool perspective)=0; /** */ virtual const MT_Point3& GetCameraPosition()=0; @@ -280,6 +280,7 @@ public: /** */ virtual void DisableFog()=0; + virtual bool IsFogEnabled()=0; virtual void SetBackColor(float red, float green, @@ -325,6 +326,26 @@ public: float focallength = 0.0f, bool perspective = true )=0; + + /** + * Generates a orthographic projection matrix from the specified frustum. + * @param left the left clipping plane + * @param right the right clipping plane + * @param bottom the bottom clipping plane + * @param top the top clipping plane + * @param frustnear the near clipping plane + * @param frustfar the far clipping plane + * @return a 4x4 matrix representing the projection transform. + */ + virtual MT_Matrix4x4 GetOrthoMatrix( + float left, + float right, + float bottom, + float top, + float frustnear, + float frustfar + )=0; + /** * Sets the specular color component of the lighting equation. */ diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 6beab28d61f..8e90c9a1c08 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -42,7 +42,7 @@ /* mesh slot */ -RAS_MeshSlot::RAS_MeshSlot() +RAS_MeshSlot::RAS_MeshSlot() : SG_QList() { m_clientObj = NULL; m_pDeformer = NULL; @@ -56,6 +56,7 @@ RAS_MeshSlot::RAS_MeshSlot() m_DisplayList = NULL; m_bDisplayList = true; m_joinSlot = NULL; + m_pDerivedMesh = NULL; } RAS_MeshSlot::~RAS_MeshSlot() @@ -81,12 +82,13 @@ RAS_MeshSlot::~RAS_MeshSlot() } } -RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot) +RAS_MeshSlot::RAS_MeshSlot(const RAS_MeshSlot& slot) : SG_QList() { RAS_DisplayArrayList::iterator it; m_clientObj = NULL; m_pDeformer = NULL; + m_pDerivedMesh = NULL; m_OpenGLMatrix = NULL; m_mesh = slot.m_mesh; m_bucket = slot.m_bucket; @@ -279,6 +281,63 @@ void RAS_MeshSlot::AddPolygonVertex(int offset) m_endindex++; } +void RAS_MeshSlot::SetDeformer(RAS_Deformer* deformer) +{ + if (deformer && m_pDeformer != deformer) { + RAS_DisplayArrayList::iterator it; + if (deformer->ShareVertexArray()) { + // this deformer uses the base vertex array, first release the current ones + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + (*it)->m_users--; + if((*it)->m_users == 0) + delete *it; + } + m_displayArrays.clear(); + // then hook to the base ones + RAS_MeshMaterial *mmat = m_mesh->GetMeshMaterial(m_bucket->GetPolyMaterial()); + if (mmat && mmat->m_baseslot) { + m_displayArrays = mmat->m_baseslot->m_displayArrays; + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + (*it)->m_users++; + } + } + } + else { + // no sharing + // we create local copy of RAS_DisplayArray when we have a deformer: + // this way we can avoid conflict between the vertex cache of duplicates + for(it=m_displayArrays.begin(); it!=m_displayArrays.end(); it++) { + if (deformer->UseVertexArray()) { + // the deformer makes use of vertex array, make sure we have our local copy + if ((*it)->m_users > 1) { + // only need to copy if there are other users + // note that this is the usual case as vertex arrays are held by the material base slot + RAS_DisplayArray *newarray = new RAS_DisplayArray(*(*it)); + newarray->m_users = 1; + (*it)->m_users--; + *it = newarray; + } + } else { + // the deformer is not using vertex array (Modifier), release them + (*it)->m_users--; + if((*it)->m_users == 0) + delete *it; + } + } + if (!deformer->UseVertexArray()) { + m_displayArrays.clear(); + m_startarray = 0; + m_startvertex = 0; + m_startindex = 0; + m_endarray = 0; + m_endvertex = 0; + m_endindex = 0; + } + } + } + m_pDeformer = deformer; +} + bool RAS_MeshSlot::Equals(RAS_MeshSlot *target) { if(!m_OpenGLMatrix || !target->m_OpenGLMatrix) @@ -422,21 +481,21 @@ bool RAS_MeshSlot::Split(bool force) return false; } + +#ifdef USE_SPLIT bool RAS_MeshSlot::IsCulled() { - list<RAS_MeshSlot*>::iterator it; - if(m_joinSlot) return true; if(!m_bCulled) return false; -#ifdef USE_SPLIT + list<RAS_MeshSlot*>::iterator it; for(it=m_joinedSlots.begin(); it!=m_joinedSlots.end(); it++) if(!(*it)->m_bCulled) return false; -#endif return true; } +#endif /* material bucket sorting */ @@ -558,7 +617,7 @@ void RAS_MaterialBucket::RenderMeshSlot(const MT_Transform& cameratrans, RAS_IRa // then it won't have texture coordinates for actual drawing. also // for zsort we can't make a display list, since the polygon order // changes all the time. - if(ms.m_pDeformer) + if(ms.m_pDeformer && ms.m_pDeformer->IsDynamic()) ms.m_bDisplayList = false; else if(!ms.m_DisplayList && rasty->GetDrawingMode() == RAS_IRasterizer::KX_SHADOW) ms.m_bDisplayList = false; diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index f5c8cd3e107..8db75b8b735 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -32,6 +32,7 @@ #include "RAS_TexVert.h" #include "GEN_Map.h" #include "STR_HashedString.h" +#include "SG_QList.h" #include "MT_Transform.h" #include "RAS_IPolygonMaterial.h" @@ -69,6 +70,7 @@ class RAS_DisplayArray; class RAS_MeshSlot; class RAS_MeshMaterial; class RAS_MaterialBucket; +struct DerivedMesh; /* An array with data used for OpenGL drawing */ @@ -88,7 +90,9 @@ public: /* Entry of a RAS_MeshObject into RAS_MaterialBucket */ typedef std::vector<RAS_DisplayArray*> RAS_DisplayArrayList; -class RAS_MeshSlot +// The QList is used to link the mesh slots to the object +// The DList is used to link the visible mesh slots to the material bucket +class RAS_MeshSlot : public SG_QList { friend class RAS_ListRasterizer; private: @@ -110,6 +114,7 @@ public: RAS_MeshObject* m_mesh; void* m_clientObj; RAS_Deformer* m_pDeformer; + DerivedMesh* m_pDerivedMesh; double* m_OpenGLMatrix; // visibility bool m_bVisible; @@ -148,6 +153,7 @@ public: /* used during construction */ void SetDisplayArray(int numverts); RAS_DisplayArray *CurrentDisplayArray(); + void SetDeformer(RAS_Deformer* deformer); void AddPolygon(int numverts); int AddVertex(const RAS_TexVert& tv); @@ -157,7 +163,11 @@ public: bool Split(bool force=false); bool Join(RAS_MeshSlot *target, MT_Scalar distance); bool Equals(RAS_MeshSlot *target); +#ifdef USE_SPLIT bool IsCulled(); +#else + bool IsCulled() { return m_bCulled; } +#endif void SetCulled(bool culled) { m_bCulled = culled; } }; @@ -168,7 +178,6 @@ class RAS_MeshMaterial public: RAS_MeshSlot *m_baseslot; class RAS_MaterialBucket *m_bucket; - GEN_Map<GEN_HashedPtr,RAS_MeshSlot*> m_slots; }; @@ -205,10 +214,23 @@ public: class RAS_MeshSlot* CopyMesh(class RAS_MeshSlot *ms); void RemoveMesh(class RAS_MeshSlot* ms); void Optimize(MT_Scalar distance); + void ActivateMesh(RAS_MeshSlot* slot) + { + m_activeMeshSlotsHead.AddBack(slot); + } + SG_DList& GetActiveMeshSlots() + { + return m_activeMeshSlotsHead; + } + RAS_MeshSlot* GetNextActiveMeshSlot() + { + return (RAS_MeshSlot*)m_activeMeshSlotsHead.Remove(); + } private: - list<RAS_MeshSlot> m_meshSlots; + list<RAS_MeshSlot> m_meshSlots; // all the mesh slots RAS_IPolyMaterial* m_material; + SG_DList m_activeMeshSlotsHead; // only those which must be rendered }; diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 162f9a81335..1dfcb0c512d 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -91,7 +91,7 @@ struct RAS_MeshObject::fronttoback STR_String RAS_MeshObject::s_emptyname = ""; RAS_MeshObject::RAS_MeshObject(Mesh* mesh, int lightlayer) - : m_lightlayer(lightlayer), + : //m_lightlayer(lightlayer), m_bModified(true), m_bMeshModified(true), m_mesh(mesh), @@ -112,10 +112,10 @@ bool RAS_MeshObject::MeshModified() return m_bMeshModified; } -unsigned int RAS_MeshObject::GetLightLayer() -{ - return m_lightlayer; -} +//unsigned int RAS_MeshObject::GetLightLayer() +//{ +// return m_lightlayer; +//} @@ -179,14 +179,14 @@ list<RAS_MeshMaterial>::iterator RAS_MeshObject::GetLastMaterial() -void RAS_MeshObject::SetName(STR_String name) +void RAS_MeshObject::SetName(const char *name) { m_name = name; } -const STR_String& RAS_MeshObject::GetName() +STR_String& RAS_MeshObject::GetName() { return m_name; } @@ -215,6 +215,19 @@ RAS_MeshMaterial *RAS_MeshObject::GetMeshMaterial(RAS_IPolyMaterial *mat) return NULL; } +int RAS_MeshObject::GetMaterialId(RAS_IPolyMaterial *mat) +{ + list<RAS_MeshMaterial>::iterator mit; + int imat; + + /* find a mesh material */ + for(imat=0, mit = m_materials.begin(); mit != m_materials.end(); mit++, imat++) + if(mit->m_bucket->GetPolyMaterial() == mat) + return imat; + + return -1; +} + RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts) { RAS_MeshMaterial *mmat; @@ -229,6 +242,7 @@ RAS_Polygon* RAS_MeshObject::AddPolygon(RAS_MaterialBucket *bucket, int numverts RAS_MeshMaterial meshmat; meshmat.m_bucket = bucket; meshmat.m_baseslot = meshmat.m_bucket->AddMesh(numverts); + meshmat.m_baseslot->m_mesh = this; m_materials.push_back(meshmat); mmat = &m_materials.back(); } @@ -291,7 +305,7 @@ void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i, slot = mmat->m_baseslot; darray = slot->CurrentDisplayArray(); - if(!flat) { + { /* Shared Vertex! */ /* find vertices shared between faces, with the restriction * that they exist in the same display array, and have the * same uv coordinate etc */ @@ -319,7 +333,7 @@ void RAS_MeshObject::AddVertex(RAS_Polygon *poly, int i, slot->AddPolygonVertex(offset); poly->SetVertexOffset(i, offset); - if(!flat) { + { /* Shared Vertex! */ SharedVertex shared; shared.m_darray = darray; shared.m_offset = offset; @@ -368,16 +382,41 @@ RAS_TexVert* RAS_MeshObject::GetVertex(unsigned int matid, return NULL; } -void RAS_MeshObject::AddMeshUser(void *clientobj) +void RAS_MeshObject::AddMeshUser(void *clientobj, SG_QList *head, RAS_Deformer* deformer) { list<RAS_MeshMaterial>::iterator it; + list<RAS_MeshMaterial>::iterator mit; for(it = m_materials.begin();it!=m_materials.end();++it) { /* always copy from the base slot, which is never removed * since new objects can be created with the same mesh data */ + if (deformer && !deformer->UseVertexArray()) + { + // HACK! + // this deformer doesn't use vertex array => derive mesh + // we must keep only the mesh slots that have unique material id + // this is to match the derived mesh drawing function + // Need a better solution in the future: scan the derive mesh and create vertex array + RAS_IPolyMaterial* curmat = it->m_bucket->GetPolyMaterial(); + if (curmat->GetFlag() & RAS_BLENDERGLSL) + { + for(mit = m_materials.begin(); mit != it; ++mit) + { + RAS_IPolyMaterial* mat = mit->m_bucket->GetPolyMaterial(); + if ((mat->GetFlag() & RAS_BLENDERGLSL) && + mat->GetMaterialIndex() == curmat->GetMaterialIndex()) + // no need to convert current mesh slot + break; + } + if (mit != it) + continue; + } + } RAS_MeshSlot *ms = it->m_bucket->CopyMesh(it->m_baseslot); ms->m_clientObj = clientobj; + ms->SetDeformer(deformer); it->m_slots.insert(clientobj, ms); + head->QAddBack(ms); } } @@ -389,7 +428,7 @@ void RAS_MeshObject::UpdateBuckets(void* clientobj, bool culled) { list<RAS_MeshMaterial>::iterator it; - + for(it = m_materials.begin();it!=m_materials.end();++it) { RAS_MeshSlot **msp = it->m_slots[clientobj]; @@ -404,6 +443,8 @@ void RAS_MeshObject::UpdateBuckets(void* clientobj, ms->m_RGBAcolor = rgbavec; ms->m_bVisible = visible; ms->m_bCulled = culled || !visible; + if (!ms->m_bCulled) + ms->m_bucket->ActivateMesh(ms); /* split if necessary */ #ifdef USE_SPLIT diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index 404b7f16a59..e763d6e7c7f 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -45,6 +45,7 @@ #include "GEN_HashedPtr.h" struct Mesh; +class RAS_Deformer; /* RAS_MeshObject is a mesh used for rendering. It stores polygons, * but the actual vertices and index arrays are stored in material @@ -54,7 +55,7 @@ class RAS_MeshObject { private: unsigned int m_debugcolor; - int m_lightlayer; + //int m_lightlayer; bool m_bModified; bool m_bMeshModified; @@ -89,15 +90,16 @@ public: RAS_MeshMaterial* GetMeshMaterial(unsigned int matid); RAS_MeshMaterial* GetMeshMaterial(RAS_IPolyMaterial *mat); + int GetMaterialId(RAS_IPolyMaterial *mat); list<RAS_MeshMaterial>::iterator GetFirstMaterial(); list<RAS_MeshMaterial>::iterator GetLastMaterial(); - unsigned int GetLightLayer(); + //unsigned int GetLightLayer(); /* name */ - void SetName(STR_String name); - const STR_String& GetName(); + void SetName(const char *name); + STR_String& GetName(); /* modification state */ bool MeshModified(); @@ -129,7 +131,7 @@ public: RAS_Polygon* GetPolygon(int num) const; /* buckets */ - virtual void AddMeshUser(void *clientobj); + virtual void AddMeshUser(void *clientobj, SG_QList *head, RAS_Deformer* deformer); virtual void UpdateBuckets( void* clientobj, double* oglmatrix, diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt index e4403ace69f..fe3d0f6aeea 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt @@ -31,8 +31,14 @@ SET(INC ../../../../intern/string ../../../../intern/moto/include ../../../../source/gameengine/Rasterizer + ../../../../source/gameengine/Ketsji + ../../../../source/gameengine/SceneGraph ../../../../extern/glew/include ../../../../source/blender/gpu + ../../../../source/blender/makesdna + ../../../../source/blender/blenkernel + ../../../../source/blender/blenlib + ../../../../source/blender/blenloader ) BLENDERLIB(bf_oglrasterizer "${SRC}" "${INC}") diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile index aee485a22be..0327714dc5f 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/Makefile @@ -42,8 +42,14 @@ CPPFLAGS += -I$(NAN_STRING)/include CPPFLAGS += -I$(NAN_MOTO)/include CPPFLAGS += -I../../../kernel/gen_system CPPFLAGS += -I../../../blender/gpu +CPPFLAGS += -I../../../blender/makesdna +CPPFLAGS += -I../../../blender/blenlib +CPPFLAGS += -I../../../blender/blenkernel CPPFLAGS += -I../../BlenderRoutines +CPPFLAGS += -I../../Ketsji +CPPFLAGS += -I../../SceneGraph CPPFLAGS += -I.. +CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include ifeq ($(OS),darwin) CPPFLAGS += -fpascal-strings diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index 65aadd63a40..014169f8838 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -104,9 +104,11 @@ bool RAS_ListSlot::End() RAS_ListRasterizer::RAS_ListRasterizer(RAS_ICanvas* canvas, bool useVertexArrays, bool lock) : RAS_VAOpenGLRasterizer(canvas, lock), - mUseVertexArrays(useVertexArrays) + mUseVertexArrays(useVertexArrays), + mATI(false) { - // -- + if (!strcmp((const char*)glGetString(GL_VENDOR), "ATI Technologies Inc.")) + mATI = true; } RAS_ListRasterizer::~RAS_ListRasterizer() @@ -116,13 +118,24 @@ RAS_ListRasterizer::~RAS_ListRasterizer() void RAS_ListRasterizer::RemoveListSlot(RAS_ListSlot* list) { - RAS_Lists::iterator it = mLists.begin(); - while(it != mLists.end()) { - if (it->second == list) { - mLists.erase(it); - break; + if (list->m_flag & LIST_DERIVEDMESH) { + RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.begin(); + while(it != mDerivedMeshLists.end()) { + if (it->second == list) { + mDerivedMeshLists.erase(it); + break; + } + it++; + } + } else { + RAS_ArrayLists::iterator it = mArrayLists.begin(); + while(it != mArrayLists.end()) { + if (it->second == list) { + mArrayLists.erase(it); + break; + } + it++; } - it++; } } @@ -136,12 +149,25 @@ RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms) */ RAS_ListSlot* localSlot = (RAS_ListSlot*)ms.m_DisplayList; if(!localSlot) { - RAS_Lists::iterator it = mLists.find(ms.m_displayArrays); - if(it == mLists.end()) { - localSlot = new RAS_ListSlot(this); - mLists.insert(std::pair<RAS_DisplayArrayList, RAS_ListSlot*>(ms.m_displayArrays, localSlot)); + if (ms.m_pDerivedMesh) { + // that means that we draw based on derived mesh, a display list is possible + // Note that we come here only for static derived mesh + RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.find(ms.m_pDerivedMesh); + if(it == mDerivedMeshLists.end()) { + localSlot = new RAS_ListSlot(this); + localSlot->m_flag |= LIST_DERIVEDMESH; + mDerivedMeshLists.insert(std::pair<DerivedMesh*, RAS_ListSlot*>(ms.m_pDerivedMesh, localSlot)); + } else { + localSlot = static_cast<RAS_ListSlot*>(it->second->AddRef()); + } } else { - localSlot = static_cast<RAS_ListSlot*>(it->second->AddRef()); + RAS_ArrayLists::iterator it = mArrayLists.find(ms.m_displayArrays); + if(it == mArrayLists.end()) { + localSlot = new RAS_ListSlot(this); + mArrayLists.insert(std::pair<RAS_DisplayArrayList, RAS_ListSlot*>(ms.m_displayArrays, localSlot)); + } else { + localSlot = static_cast<RAS_ListSlot*>(it->second->AddRef()); + } } } MT_assert(localSlot); @@ -150,12 +176,12 @@ RAS_ListSlot* RAS_ListRasterizer::FindOrAdd(RAS_MeshSlot& ms) void RAS_ListRasterizer::ReleaseAlloc() { - RAS_Lists::iterator it = mLists.begin(); - while(it != mLists.end()) { + for(RAS_ArrayLists::iterator it = mArrayLists.begin();it != mArrayLists.end();++it) delete it->second; - it++; - } - mLists.clear(); + mArrayLists.clear(); + for (RAS_DerivedMeshLists::iterator it = mDerivedMeshLists.begin();it != mDerivedMeshLists.end();++it) + delete it->second; + mDerivedMeshLists.clear(); } void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms) @@ -172,8 +198,8 @@ void RAS_ListRasterizer::IndexPrimitives(RAS_MeshSlot& ms) return; } } - - if (mUseVertexArrays) + // derived mesh cannot use vertex array + if (mUseVertexArrays && !ms.m_pDerivedMesh) RAS_VAOpenGLRasterizer::IndexPrimitives(ms); else RAS_OpenGLRasterizer::IndexPrimitives(ms); @@ -204,7 +230,7 @@ void RAS_ListRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) // workaround: note how we do not use vertex arrays for making display // lists, since glVertexAttribPointerARB doesn't seem to work correct // in display lists on ATI? either a bug in the driver or in Blender .. - if (mUseVertexArrays && !localSlot) + if (mUseVertexArrays && !mATI && !ms.m_pDerivedMesh) RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(ms); else RAS_OpenGLRasterizer::IndexPrimitivesMulti(ms); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index 653bb43e534..fe358808e4a 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -9,6 +9,7 @@ class RAS_ListRasterizer; class RAS_ListSlot : public KX_ListSlot { + friend class RAS_ListRasterizer; unsigned int m_list; unsigned int m_flag; RAS_ListRasterizer* m_rasty; @@ -32,15 +33,21 @@ enum RAS_ListSlotFlags { LIST_NOCREATE =8, LIST_BEGIN =16, LIST_END =32, - LIST_REGEN =64 + LIST_REGEN =64, + LIST_DERIVEDMESH=128, }; -typedef std::map<RAS_DisplayArrayList, RAS_ListSlot*> RAS_Lists; +struct DerivedMesh; + +typedef std::map<RAS_DisplayArrayList, RAS_ListSlot*> RAS_ArrayLists; +typedef std::map<DerivedMesh*, RAS_ListSlot*> RAS_DerivedMeshLists; class RAS_ListRasterizer : public RAS_VAOpenGLRasterizer { bool mUseVertexArrays; - RAS_Lists mLists; + bool mATI; + RAS_ArrayLists mArrayLists; + RAS_DerivedMeshLists mDerivedMeshLists; RAS_ListSlot* FindOrAdd(class RAS_MeshSlot& ms); void ReleaseAlloc(); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 1a9a28916de..83ba2778ad6 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -35,11 +35,20 @@ #include "RAS_Rect.h" #include "RAS_TexVert.h" +#include "RAS_MeshObject.h" #include "MT_CmMatrix4x4.h" #include "RAS_IRenderTools.h" // rendering text #include "GPU_draw.h" #include "GPU_material.h" +#include "GPU_extensions.h" + +#include "DNA_image_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_material_types.h" +#include "DNA_scene_types.h" + +#include "BKE_DerivedMesh.h" /** * 32x32 bit masks for vinterlace stereo mode @@ -72,7 +81,7 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas) m_motionblurvalue(-1.0), m_texco_num(0), m_attrib_num(0), - m_last_blendmode(GPU_BLEND_SOLID), + //m_last_blendmode(GPU_BLEND_SOLID), m_last_frontface(true), m_materialCachingInfo(0) { @@ -109,7 +118,8 @@ bool RAS_OpenGLRasterizer::Init() glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); - m_last_blendmode = GPU_BLEND_SOLID; + //m_last_blendmode = GPU_BLEND_SOLID; + GPU_set_material_blend_mode(GPU_BLEND_SOLID); glFrontFace(GL_CCW); m_last_frontface = true; @@ -201,6 +211,10 @@ void RAS_OpenGLRasterizer::DisableFog() m_fogenabled = false; } +bool RAS_OpenGLRasterizer::IsFogEnabled() +{ + return m_fogenabled; +} void RAS_OpenGLRasterizer::DisplayFog() @@ -275,7 +289,8 @@ bool RAS_OpenGLRasterizer::BeginFrame(int drawingmode, double time) glDisable(GL_BLEND); glDisable(GL_ALPHA_TEST); - m_last_blendmode = GPU_BLEND_SOLID; + //m_last_blendmode = GPU_BLEND_SOLID; + GPU_set_material_blend_mode(GPU_BLEND_SOLID); glFrontFace(GL_CCW); m_last_frontface = true; @@ -703,6 +718,51 @@ void RAS_OpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) IndexPrimitivesInternal(ms, true); } +static bool current_wireframe; +static RAS_MaterialBucket *current_bucket; +static RAS_IPolyMaterial *current_polymat; +static RAS_MeshSlot *current_ms; +static RAS_MeshObject *current_mesh; +static int current_blmat_nr; +static GPUVertexAttribs current_gpu_attribs; +static int CheckMaterialDM(int matnr, void *attribs) +{ + // only draw the current material + if (matnr != current_blmat_nr) + return 0; + GPUVertexAttribs *gattribs = (GPUVertexAttribs *)attribs; + if (gattribs) + memcpy(gattribs, ¤t_gpu_attribs, sizeof(GPUVertexAttribs)); + return 1; +} +static int CheckTexfaceDM(void *mcol, int index) +{ + + // index is the original face index, retrieve the polygon + RAS_Polygon* polygon = (index >= 0 && index < current_mesh->NumPolygons()) ? + current_mesh->GetPolygon(index) : NULL; + if (polygon && polygon->GetMaterial() == current_bucket) { + // must handle color. + if (current_wireframe) + return 2; + if (current_ms->m_bObjectColor) { + MT_Vector4& rgba = current_ms->m_RGBAcolor; + glColor4d(rgba[0], rgba[1], rgba[2], rgba[3]); + // don't use mcol + return 2; + } + if (!mcol) { + // we have to set the color from the material + unsigned char rgba[4]; + current_polymat->GetMaterialRGBAColor(rgba); + glColor4ubv((const GLubyte *)rgba); + return 2; + } + return 1; + } + return 0; +} + void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) { bool obcolor = ms.m_bObjectColor; @@ -710,6 +770,34 @@ void RAS_OpenGLRasterizer::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) MT_Vector4& rgba = ms.m_RGBAcolor; RAS_MeshSlot::iterator it; + if (ms.m_pDerivedMesh) { + // mesh data is in derived mesh, + current_bucket = ms.m_bucket; + current_polymat = current_bucket->GetPolyMaterial(); + current_ms = &ms; + current_mesh = ms.m_mesh; + current_wireframe = wireframe; + MCol *mcol = (MCol*)ms.m_pDerivedMesh->getFaceDataArray(ms.m_pDerivedMesh, CD_MCOL); + if (current_polymat->GetFlag() & RAS_BLENDERGLSL) { + // GetMaterialIndex return the original mface material index, + // increment by 1 to match what derived mesh is doing + current_blmat_nr = current_polymat->GetMaterialIndex()+1; + // For GLSL we need to retrieve the GPU material attribute + Material* blmat = current_polymat->GetBlenderMaterial(); + Scene* blscene = current_polymat->GetBlenderScene(); + if (!wireframe && blscene && blmat) + GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat), ¤t_gpu_attribs); + else + memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs)); + // DM draw can mess up blending mode, restore at the end + int current_blend_mode = GPU_get_material_blend_mode(); + ms.m_pDerivedMesh->drawFacesGLSL(ms.m_pDerivedMesh, CheckMaterialDM); + GPU_set_material_blend_mode(current_blend_mode); + } else { + ms.m_pDerivedMesh->drawMappedFacesTex(ms.m_pDerivedMesh, CheckTexfaceDM, mcol); + } + return; + } // iterate over display arrays, each containing an index + vertex array for(ms.begin(it); !ms.end(it); ms.next(it)) { RAS_TexVert *vertex; @@ -838,17 +926,40 @@ MT_Matrix4x4 RAS_OpenGLRasterizer::GetFrustumMatrix( return result; } +MT_Matrix4x4 RAS_OpenGLRasterizer::GetOrthoMatrix( + float left, + float right, + float bottom, + float top, + float frustnear, + float frustfar +){ + MT_Matrix4x4 result; + double mat[16]; + + // stereo is meaning less for orthographic, disable it + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(left, right, bottom, top, frustnear, frustfar); + + glGetDoublev(GL_PROJECTION_MATRIX, mat); + result.setValue(mat); + + return result; +} + // next arguments probably contain redundant info, for later... -void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vector3& campos, - const MT_Point3 &, const MT_Quaternion &camOrientQuat) +void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, + const MT_Matrix3x3 & camOrientMat3x3, + const MT_Point3 & pos, + bool perspective) { m_viewmatrix = mat; // correction for stereo - if(Stereo()) + if(Stereo() && perspective) { - MT_Matrix3x3 camOrientMat3x3(camOrientQuat); MT_Vector3 unitViewDir(0.0, -1.0, 0.0); // minus y direction, Blender convention MT_Vector3 unitViewupVec(0.0, 0.0, 1.0); MT_Vector3 viewDir, viewupVec; @@ -894,7 +1005,7 @@ void RAS_OpenGLRasterizer::SetViewMatrix(const MT_Matrix4x4 &mat, const MT_Vecto glMatrixMode(GL_MODELVIEW); glLoadMatrixd(glviewmat); - m_campos = campos; + m_campos = pos; } @@ -990,6 +1101,8 @@ void RAS_OpenGLRasterizer::DisableMotionBlur() void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) { + GPU_set_material_blend_mode(blendmode); +/* if(blendmode == m_last_blendmode) return; @@ -1016,6 +1129,7 @@ void RAS_OpenGLRasterizer::SetBlendingMode(int blendmode) } m_last_blendmode = blendmode; +*/ } void RAS_OpenGLRasterizer::SetFrontFace(bool ccw) diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 83a9f759a8b..e3422394e9e 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -100,7 +100,7 @@ protected: TexCoGen m_attrib[RAS_MAX_ATTRIB]; int m_texco_num; int m_attrib_num; - int m_last_blendmode; + //int m_last_blendmode; bool m_last_frontface; /** Stores the caching information for the last material activated. */ @@ -163,9 +163,9 @@ public: virtual void SetProjectionMatrix(const MT_Matrix4x4 & mat); virtual void SetViewMatrix( const MT_Matrix4x4 & mat, - const MT_Vector3& campos, - const MT_Point3 &camLoc, - const MT_Quaternion &camOrientQuat + const MT_Matrix3x3 & ori, + const MT_Point3 & pos, + bool perspective ); virtual const MT_Point3& GetCameraPosition(); @@ -190,6 +190,7 @@ public: void DisableFog(); virtual void DisplayFog(); + virtual bool IsFogEnabled(); virtual void SetBackColor( float red, @@ -215,6 +216,15 @@ public: bool perspective ); + virtual MT_Matrix4x4 GetOrthoMatrix( + float left, + float right, + float bottom, + float top, + float frustnear, + float frustfar + ); + virtual void SetSpecularity( float specX, float specY, diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp index 2cb3b52adfb..00f0f27b6c1 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_VAOpenGLRasterizer.cpp @@ -110,6 +110,12 @@ void RAS_VAOpenGLRasterizer::IndexPrimitives(RAS_MeshSlot& ms) RAS_MeshSlot::iterator it; GLenum drawmode; + if (ms.m_pDerivedMesh) { + // cannot be handled here, pass to RAS_OpenGLRasterizer + RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, false); + return; + } + if(!wireframe) glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -167,6 +173,12 @@ void RAS_VAOpenGLRasterizer::IndexPrimitivesMulti(RAS_MeshSlot& ms) RAS_MeshSlot::iterator it; GLenum drawmode; + if (ms.m_pDerivedMesh) { + // cannot be handled here, pass to RAS_OpenGLRasterizer + RAS_OpenGLRasterizer::IndexPrimitivesInternal(ms, true); + return; + } + if(!wireframe) EnableTextures(true); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript index c0b73e7644f..3d605ce12b8 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript @@ -5,6 +5,8 @@ sources = env.Glob('*.cpp') incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/Rasterizer #source/gameengine/BlenderRoutines ' incs += ' #source/blender/gpu #extern/glew/include ' + env['BF_OPENGL_INC'] +incs += ' #source/blender/gameengine/Ketsji #source/gameengine/SceneGraph #source/blender/makesdna #source/blender/blenkernel' +incs += ' #intern/guardedalloc #source/blender/blenlib' cxxflags = [] if env['OURPLATFORM']=='win32-vc': diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index 210addfb927..8eee24ac7f0 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -113,19 +113,20 @@ void RAS_TexVert::SetTangent(const MT_Vector3& tangent) tangent.getValue(m_tangent); } + // compare two vertices, and return TRUE if both are almost identical (they can be shared) -#define _VEC_EQUAL3(_v1, _v2) (_v1[0]==_v2[0] && _v1[1]==_v2[1] && _v1[2]==_v2[2]) -#define _VEC_EQUAL2(_v1, _v2) (_v1[0]==_v2[0] && _v1[1]==_v2[1]) bool RAS_TexVert::closeTo(const RAS_TexVert* other) { - return (m_flag == other->m_flag && + return ( + /* m_flag == other->m_flag && */ + /* at the moment the face only stores the smooth/flat setting so dont bother comparing it */ m_rgba == other->m_rgba && - _VEC_EQUAL3(m_normal, other->m_normal) && - _VEC_EQUAL3(m_tangent, other->m_tangent) && - _VEC_EQUAL2(m_uv1, other->m_uv1) && - _VEC_EQUAL2(m_uv2, other->m_uv2) // p -- - /* we know the verts must be shared so dont need to check this */ - /*&& FAST_MT_fuzzyEqual3(m_localxyz, other->m_localxyz)*/) ; + MT_fuzzyEqual(MT_Vector3(m_normal), MT_Vector3(other->m_normal)) && + MT_fuzzyEqual(MT_Vector3(m_tangent), MT_Vector3(other->m_tangent)) && + MT_fuzzyEqual(MT_Vector2(m_uv1), MT_Vector2(other->m_uv1)) && + MT_fuzzyEqual(MT_Vector2(m_uv2), MT_Vector2(other->m_uv2)) /* && + MT_fuzzyEqual(MT_Vector3(m_localxyz), MT_Vector3(other->m_localxyz))*/) ; + /* dont bother comparing m_localxyz since we know there from the same vert */ } short RAS_TexVert::getFlag() const diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript index 9f4cd61e7bb..018f2ab4d20 100644 --- a/source/gameengine/Rasterizer/SConscript +++ b/source/gameengine/Rasterizer/SConscript @@ -4,7 +4,7 @@ Import ('env') sources = env.Glob('*.cpp') -incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions #source/blender/blenkernel #source/blender/makesdna' +incs = '. #source/kernel/gen_system #intern/string #intern/moto/include #source/gameengine/BlenderRoutines #extern/glew/include #source/gameengine/Expressions #source/gameengine/SceneGraph #source/blender/blenkernel #source/blender/makesdna' incs += ' ' + env['BF_PYTHON_INC'] cxxflags = [] diff --git a/source/gameengine/SceneGraph/SG_DList.h b/source/gameengine/SceneGraph/SG_DList.h new file mode 100644 index 00000000000..7bef13cc9e3 --- /dev/null +++ b/source/gameengine/SceneGraph/SG_DList.h @@ -0,0 +1,161 @@ +/** + * $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 __SG_DLIST +#define __SG_DLIST + +#include <stdlib.h> + +/** + * Double circular linked list + */ +class SG_DList +{ +protected : + SG_DList* m_flink; + SG_DList* m_blink; + +public: + template<typename T> class iterator + { + private: + SG_DList& m_head; + T* m_current; + public: + typedef iterator<T> _myT; + iterator(SG_DList& head) : m_head(head), m_current(NULL) {} + ~iterator() {} + + void begin() + { + m_current = (T*)m_head.Peek(); + } + void back() + { + m_current = (T*)m_head.Back(); + } + bool end() + { + return (m_current == (T*)m_head.Self()); + } + bool add_back(T* item) + { + return m_current->AddBack(item); + } + T* operator*() + { + return m_current; + } + _myT& operator++() + { + // no check of NULL! make sure you don't try to increment beyond end + m_current = (T*)m_current->Peek(); + return *this; + } + _myT& operator--() + { + // no check of NULL! make sure you don't try to increment beyond end + m_current = (T*)m_current->Back(); + return *this; + } + }; + + SG_DList() + { + m_flink = m_blink = this; + } + SG_DList(const SG_DList& other) + { + m_flink = m_blink = this; + } + virtual ~SG_DList() + { + Delink(); + } + + inline bool Empty() // Check for empty queue + { + return ( m_flink == this ); + } + bool AddBack( SG_DList *item ) // Add to the back + { + if (!item->Empty()) + return false; + item->m_blink = m_blink; + item->m_flink = this; + m_blink->m_flink = item; + m_blink = item; + return true; + } + bool AddFront( SG_DList *item ) // Add to the back + { + if (!item->Empty()) + return false; + item->m_flink = m_flink; + item->m_blink = this; + m_flink->m_blink = item; + m_flink = item; + return true; + } + SG_DList *Remove() // Remove from the front + { + if (Empty()) + { + return NULL; + } + SG_DList* item = m_flink; + m_flink = item->m_flink; + m_flink->m_blink = this; + item->m_flink = item->m_blink = item; + return item; + } + bool Delink() // Remove from the middle + { + if (Empty()) + return false; + m_blink->m_flink = m_flink; + m_flink->m_blink = m_blink; + m_flink = m_blink = this; + return true; + } + inline SG_DList *Peek() // Look at front without removing + { + return m_flink; + } + inline SG_DList *Back() // Look at front without removing + { + return m_blink; + } + inline SG_DList *Self() + { + return this; + } +}; + +#endif //__SG_DLIST + diff --git a/source/gameengine/SceneGraph/SG_IObject.cpp b/source/gameengine/SceneGraph/SG_IObject.cpp index fbab4032a10..5795ca57113 100644 --- a/source/gameengine/SceneGraph/SG_IObject.cpp +++ b/source/gameengine/SceneGraph/SG_IObject.cpp @@ -39,19 +39,20 @@ SG_IObject:: SG_IObject( void* clientobj, void* clientinfo, - SG_Callbacks callbacks + SG_Callbacks& callbacks ): + SG_QList(), m_SGclientObject(clientobj), - m_SGclientInfo(clientinfo), - m_callbacks(callbacks) + m_SGclientInfo(clientinfo) { - //nothing to do + m_callbacks = callbacks; } SG_IObject:: SG_IObject( const SG_IObject &other ) : + SG_QList(), m_SGclientObject(other.m_SGclientObject), m_SGclientInfo(other.m_SGclientInfo), m_callbacks(other.m_callbacks) @@ -74,92 +75,17 @@ RemoveAllControllers( m_SGcontrollers.clear(); } -/// Needed for replication - SGControllerList& -SG_IObject:: -GetSGControllerList( -){ - return m_SGcontrollers; -} - - void* -SG_IObject:: -GetSGClientObject( -){ - return m_SGclientObject; -} - -const - void* -SG_IObject:: -GetSGClientObject( -) const { - return m_SGclientObject; -} - - void -SG_IObject:: -SetSGClientObject( - void* clientObject -){ - m_SGclientObject = clientObject; -} - - - bool -SG_IObject:: -ActivateReplicationCallback( - SG_IObject *replica -){ - if (m_callbacks.m_replicafunc) - { - // Call client provided replication func - if (m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo) == NULL) - return false; - } - return true; -}; - - void -SG_IObject:: -ActivateDestructionCallback( -){ - if (m_callbacks.m_destructionfunc) - { - // Call client provided destruction function on this! - m_callbacks.m_destructionfunc(this,m_SGclientObject,m_SGclientInfo); - } - else - { - // no callback but must still destroy the node to avoid memory leak - delete this; - } -} - - void -SG_IObject:: -ActivateUpdateTransformCallback( -){ - if (m_callbacks.m_updatefunc) - { - // Call client provided update func. - m_callbacks.m_updatefunc(this, m_SGclientObject, m_SGclientInfo); - } -} - - void -SG_IObject:: -SetControllerTime( - double time -){ +void SG_IObject::SetControllerTime(double time) +{ SGControllerList::iterator contit; - for (contit = m_SGcontrollers.begin();contit!=m_SGcontrollers.end();++contit) { (*contit)->SetSimulatedTime(time); } } +/// Needed for replication + SG_IObject:: ~SG_IObject() diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h index 9012b532059..8f448a0e890 100644 --- a/source/gameengine/SceneGraph/SG_IObject.h +++ b/source/gameengine/SceneGraph/SG_IObject.h @@ -29,6 +29,7 @@ #ifndef __SG_IOBJECT #define __SG_IOBJECT +#include "SG_QList.h" #include <vector> // used for debugging: stage of the game engine main loop at which a Scenegraph modification is done @@ -84,6 +85,18 @@ typedef void (*SG_UpdateTransformCallback)( void* clientinfo ); +typedef bool (*SG_ScheduleUpdateCallback)( + SG_IObject* sgobject, + void* clientobj, + void* clientinfo +); + +typedef bool (*SG_RescheduleUpdateCallback)( + SG_IObject* sgobject, + void* clientobj, + void* clientinfo +); + /** * SG_Callbacks hold 2 call backs to the outside world. @@ -106,30 +119,38 @@ struct SG_Callbacks ): m_replicafunc(NULL), m_destructionfunc(NULL), - m_updatefunc(NULL) + m_updatefunc(NULL), + m_schedulefunc(NULL), + m_reschedulefunc(NULL) { }; SG_Callbacks( SG_ReplicationNewCallback repfunc, SG_DestructionNewCallback destructfunc, - SG_UpdateTransformCallback updatefunc + SG_UpdateTransformCallback updatefunc, + SG_ScheduleUpdateCallback schedulefunc, + SG_RescheduleUpdateCallback reschedulefunc ): m_replicafunc(repfunc), m_destructionfunc(destructfunc), - m_updatefunc(updatefunc) + m_updatefunc(updatefunc), + m_schedulefunc(schedulefunc), + m_reschedulefunc(reschedulefunc) { }; SG_ReplicationNewCallback m_replicafunc; SG_DestructionNewCallback m_destructionfunc; SG_UpdateTransformCallback m_updatefunc; + SG_ScheduleUpdateCallback m_schedulefunc; + SG_RescheduleUpdateCallback m_reschedulefunc; }; /** base object that can be part of the scenegraph. */ -class SG_IObject +class SG_IObject : public SG_QList { private : @@ -177,10 +198,18 @@ public: * using STL? */ - SGControllerList& - GetSGControllerList( - ); + SGControllerList& GetSGControllerList() + { + return m_SGcontrollers; + } + /** + * + */ + SG_Callbacks& GetCallBackFunctions() + { + return m_callbacks; + } /** * Get the client object associated with this @@ -192,16 +221,16 @@ public: * This may be NULL. */ - void* - GetSGClientObject( - ); + inline const void* GetSGClientObject() const + { + return m_SGclientObject; + } - const - void* - GetSGClientObject( - ) const ; + inline void* GetSGClientObject() + { + return m_SGclientObject; + } - /** * Set the client object for this node. This is just a * pointer to an object allocated that should exist for @@ -209,10 +238,10 @@ public: * this function is called again. */ - void - SetSGClientObject( - void* clientObject - ); + void SetSGClientObject(void* clientObject) + { + m_SGclientObject = clientObject; + } /** * Set the current simulation time for this node. @@ -220,10 +249,7 @@ public: * the nodes list of controllers and calls their SetSimulatedTime methods */ - void - SetControllerTime( - double time - ); + void SetControllerTime(double time); virtual void @@ -235,20 +261,76 @@ protected : bool ActivateReplicationCallback( SG_IObject *replica - ); + ) + { + if (m_callbacks.m_replicafunc) + { + // Call client provided replication func + if (m_callbacks.m_replicafunc(replica,m_SGclientObject,m_SGclientInfo) == NULL) + return false; + } + return true; + } + void ActivateDestructionCallback( - ); + ) + { + if (m_callbacks.m_destructionfunc) + { + // Call client provided destruction function on this! + m_callbacks.m_destructionfunc(this,m_SGclientObject,m_SGclientInfo); + } + else + { + // no callback but must still destroy the node to avoid memory leak + delete this; + } + } void ActivateUpdateTransformCallback( - ); + ) + { + if (m_callbacks.m_updatefunc) + { + // Call client provided update func. + m_callbacks.m_updatefunc(this, m_SGclientObject, m_SGclientInfo); + } + } + + bool + ActivateScheduleUpdateCallback( + ) + { + // HACK, this check assumes that the scheduled nodes are put on a DList (see SG_Node.h) + // The early check on Empty() allows up to avoid calling the callback function + // when the node is already scheduled for update. + if (Empty() && m_callbacks.m_schedulefunc) + { + // Call client provided update func. + return m_callbacks.m_schedulefunc(this, m_SGclientObject, m_SGclientInfo); + } + return false; + } + + void + ActivateRecheduleUpdateCallback( + ) + { + if (m_callbacks.m_reschedulefunc) + { + // Call client provided update func. + m_callbacks.m_reschedulefunc(this, m_SGclientObject, m_SGclientInfo); + } + } + SG_IObject( void* clientobj, void* clientinfo, - SG_Callbacks callbacks + SG_Callbacks& callbacks ); SG_IObject( diff --git a/source/gameengine/SceneGraph/SG_Node.cpp b/source/gameengine/SceneGraph/SG_Node.cpp index 64d9019c86a..4cd43e852b8 100644 --- a/source/gameengine/SceneGraph/SG_Node.cpp +++ b/source/gameengine/SceneGraph/SG_Node.cpp @@ -40,12 +40,13 @@ using namespace std; SG_Node::SG_Node( void* clientobj, void* clientinfo, - SG_Callbacks callbacks + SG_Callbacks& callbacks ) : SG_Spatial(clientobj,clientinfo,callbacks), m_SGparent(NULL) { + m_modified = true; } SG_Node::SG_Node( @@ -55,7 +56,7 @@ SG_Node::SG_Node( m_children(other.m_children), m_SGparent(other.m_SGparent) { - // nothing to do + m_modified = true; } SG_Node::~SG_Node() @@ -141,22 +142,6 @@ Destruct() ActivateDestructionCallback(); } - - SG_Node* -SG_Node:: -GetSGParent( -) const { - return m_SGparent; -} - - void -SG_Node:: -SetSGParent( - SG_Node* parent -){ - m_SGparent = parent; -} - const SG_Node* SG_Node:: @@ -165,28 +150,6 @@ GetRootSGParent( return (m_SGparent ? (const SG_Node*) m_SGparent->GetRootSGParent() : (const SG_Node*) this); } - bool -SG_Node:: -IsVertexParent() -{ - if (m_parent_relation) - { - return m_parent_relation->IsVertexRelation(); - } - return false; -} - - bool -SG_Node:: -IsSlowParent() -{ - if (m_parent_relation) - { - return m_parent_relation->IsSlowRelation(); - } - return false; -} - void SG_Node:: DisconnectFromParent( @@ -199,8 +162,6 @@ DisconnectFromParent( } - - void SG_Node::AddChild(SG_Node* child) { m_children.push_back(child); @@ -228,6 +189,9 @@ void SG_Node::UpdateWorldData(double time, bool parentUpdated) // to update the ActivateUpdateTransformCallback(); + // The node is updated, remove it from the update list + Delink(); + // update children's worlddata for (NodeList::iterator it = m_children.begin();it!=m_children.end();++it) { @@ -236,24 +200,6 @@ void SG_Node::UpdateWorldData(double time, bool parentUpdated) } -NodeList& SG_Node::GetSGChildren() -{ - return this->m_children; -} - - -const NodeList& SG_Node::GetSGChildren() const -{ - return this->m_children; -} - - -void SG_Node::ClearSGChildren() -{ - m_children.clear(); -} - - void SG_Node::SetSimulatedTime(double time,bool recurse) { diff --git a/source/gameengine/SceneGraph/SG_Node.h b/source/gameengine/SceneGraph/SG_Node.h index 29943653a81..7c6ef92f670 100644 --- a/source/gameengine/SceneGraph/SG_Node.h +++ b/source/gameengine/SceneGraph/SG_Node.h @@ -44,7 +44,7 @@ public: SG_Node( void* clientobj, void* clientinfo, - SG_Callbacks callbacks + SG_Callbacks& callbacks ); SG_Node( @@ -85,45 +85,47 @@ public: * @return a reference to the list of children of this node. */ - NodeList& - GetSGChildren( - ); + NodeList& GetSGChildren() + { + return this->m_children; + } /** * Get the current list of children. * @return a const reference to the current list of children of this node. */ - const - NodeList& - GetSGChildren( - ) const; + const NodeList& GetSGChildren() const + { + return this->m_children; + } /** * Clear the list of children associated with this node */ - void - ClearSGChildren( - ); + void ClearSGChildren() + { + m_children.clear(); + } /** * return the parent of this node if it exists. */ - SG_Node* - GetSGParent( - ) const ; - + SG_Node* GetSGParent() const + { + return m_SGparent; + } /** * Set the parent of this node. */ - void - SetSGParent( - SG_Node* parent - ); + void SetSGParent(SG_Node* parent) + { + m_SGparent = parent; + } /** * Return the top node in this node's Scene graph hierarchy @@ -143,30 +145,33 @@ public: ); /** - * Tell this node to treat it's parent as a vertex parent. - */ - - void - SetVertexParent( - bool isvertexparent - ) ; - - - /** * Return vertex parent status. */ + bool IsVertexParent() + { + if (m_parent_relation) + { + return m_parent_relation->IsVertexRelation(); + } + return false; + } + - bool - IsVertexParent( - ) ; - /** * Return slow parent status. */ - bool - IsSlowParent( - ) ; + bool IsSlowParent() + { + if (m_parent_relation) + { + return m_parent_relation->IsSlowRelation(); + } + return false; + } + + + /** * Update the spatial data of this node. Iterate through @@ -191,6 +196,42 @@ public: ); /** + * Schedule this node for update by placing it in head queue + */ + bool Schedule(SG_QList& head) + { + // Put top parent in front of list to make sure they are updated before their + // children => the children will be udpated and removed from the list before + // we get to them, should they be in the list too. + return (m_SGparent)?head.AddBack(this):head.AddFront(this); + } + + /** + * Used during Scenegraph update + */ + static SG_Node* GetNextScheduled(SG_QList& head) + { + return static_cast<SG_Node*>(head.Remove()); + } + + /** + * Make this node ready for schedule on next update. This is needed for nodes + * that must always be updated (slow parent, bone parent) + */ + bool Reschedule(SG_QList& head) + { + return head.QAddBack(this); + } + + /** + * Used during Scenegraph update + */ + static SG_Node* GetNextRescheduled(SG_QList& head) + { + return static_cast<SG_Node*>(head.QRemove()); + } + + /** * Node replication functions. */ diff --git a/source/gameengine/SceneGraph/SG_QList.h b/source/gameengine/SceneGraph/SG_QList.h new file mode 100644 index 00000000000..d8afc33ea4f --- /dev/null +++ b/source/gameengine/SceneGraph/SG_QList.h @@ -0,0 +1,157 @@ +/** + * $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 __SG_QLIST +#define __SG_QLIST + +#include "SG_DList.h" + +/** + * Double-Double circular linked list + * For storing an object is two lists simultaneously + */ +class SG_QList : public SG_DList +{ +protected : + SG_QList* m_fqlink; + SG_QList* m_bqlink; + +public: + template<typename T> class iterator + { + private: + SG_QList& m_head; + T* m_current; + public: + typedef iterator<T> _myT; + iterator(SG_QList& head, SG_QList* current=NULL) : m_head(head) { m_current = (T*)current; } + ~iterator() {} + + void begin() + { + m_current = (T*)m_head.QPeek(); + } + void back() + { + m_current = (T*)m_head.QBack(); + } + bool end() + { + return (m_current == (T*)m_head.Self()); + } + bool add_back(T* item) + { + return m_current->QAddBack(item); + } + T* operator*() + { + return m_current; + } + _myT& operator++() + { + m_current = (T*)m_current->QPeek(); + return *this; + } + _myT& operator--() + { + // no check on NULL! make sure you don't try to increment beyond end + m_current = (T*)m_current->QBack(); + return *this; + } + }; + + SG_QList() : SG_DList() + { + m_fqlink = m_bqlink = this; + } + SG_QList(const SG_QList& other) : SG_DList() + { + m_fqlink = m_bqlink = this; + } + virtual ~SG_QList() + { + QDelink(); + } + + inline bool QEmpty() // Check for empty queue + { + return ( m_fqlink == this ); + } + bool QAddBack( SG_QList *item ) // Add to the back + { + if (!item->QEmpty()) + return false; + item->m_bqlink = m_bqlink; + item->m_fqlink = this; + m_bqlink->m_fqlink = item; + m_bqlink = item; + return true; + } + bool QAddFront( SG_QList *item ) // Add to the back + { + if (!item->Empty()) + return false; + item->m_fqlink = m_fqlink; + item->m_bqlink = this; + m_fqlink->m_bqlink = item; + m_fqlink = item; + return true; + } + SG_QList *QRemove() // Remove from the front + { + if (QEmpty()) + { + return NULL; + } + SG_QList* item = m_fqlink; + m_fqlink = item->m_fqlink; + m_fqlink->m_bqlink = this; + item->m_fqlink = item->m_bqlink = item; + return item; + } + bool QDelink() // Remove from the middle + { + if (QEmpty()) + return false; + m_bqlink->m_fqlink = m_fqlink; + m_fqlink->m_bqlink = m_bqlink; + m_fqlink = m_bqlink = this; + return true; + } + inline SG_QList *QPeek() // Look at front without removing + { + return m_fqlink; + } + inline SG_QList *QBack() // Look at front without removing + { + return m_bqlink; + } +}; + +#endif //__SG_QLIST + diff --git a/source/gameengine/SceneGraph/SG_Spatial.cpp b/source/gameengine/SceneGraph/SG_Spatial.cpp index 2f3176816c6..5a47f07f573 100644 --- a/source/gameengine/SceneGraph/SG_Spatial.cpp +++ b/source/gameengine/SceneGraph/SG_Spatial.cpp @@ -40,7 +40,7 @@ SG_Spatial:: SG_Spatial( void* clientobj, void* clientinfo, - SG_Callbacks callbacks + SG_Callbacks& callbacks ): SG_IObject(clientobj,clientinfo,callbacks), @@ -56,7 +56,8 @@ SG_Spatial( m_bbox(MT_Point3(-1.0, -1.0, -1.0), MT_Point3(1.0, 1.0, 1.0)), m_radius(1.0), - m_modified(true) + m_modified(false), + m_ogldirty(false) { } @@ -76,7 +77,9 @@ SG_Spatial( m_parent_relation(NULL), m_bbox(other.m_bbox), - m_radius(other.m_radius) + m_radius(other.m_radius), + m_modified(false), + m_ogldirty(false) { // duplicate the parent relation for this object m_parent_relation = other.m_parent_relation->NewCopy(); @@ -88,13 +91,6 @@ SG_Spatial:: delete (m_parent_relation); } - SG_ParentRelation * -SG_Spatial:: -GetParentRelation( -){ - return m_parent_relation; -} - void SG_Spatial:: SetParentRelation( @@ -102,7 +98,7 @@ SetParentRelation( ){ delete (m_parent_relation); m_parent_relation = relation; - m_modified = true; + SetModified(); } @@ -143,11 +139,6 @@ UpdateSpatialData( return bComputesWorldTransform; } -bool SG_Spatial::ComputeWorldTransforms(const SG_Spatial *parent, bool& parentUpdated) -{ - return m_parent_relation->UpdateChildCoordinates(this,parent,parentUpdated); -} - /** * Position and translation methods */ @@ -169,56 +160,14 @@ RelativeTranslate( m_localPosition += trans; } } - m_modified = true; + SetModified(); } - void -SG_Spatial:: -SetLocalPosition( - const MT_Point3& trans -){ - m_localPosition = trans; - m_modified = true; -} - - void -SG_Spatial:: -SetWorldPosition( - const MT_Point3& trans -) { - m_worldPosition = trans; -} /** * Scaling methods. */ - void -SG_Spatial:: -RelativeScale( - const MT_Vector3& scale -){ - m_localScaling = m_localScaling * scale; - m_modified = true; -} - - void -SG_Spatial:: -SetLocalScale( - const MT_Vector3& scale -){ - m_localScaling = scale; - m_modified = true; -} - - - void -SG_Spatial:: -SetWorldScale( - const MT_Vector3& scale -){ - m_worldScaling = scale; -} /** * Orientation and rotation methods. @@ -236,93 +185,11 @@ RelativeRotate( rot : (GetWorldOrientation().inverse() * rot * GetWorldOrientation())); - m_modified = true; -} - - void -SG_Spatial:: -SetLocalOrientation(const MT_Matrix3x3& rot) -{ - m_localRotation = rot; - m_modified = true; + SetModified(); } - void -SG_Spatial:: -SetWorldOrientation( - const MT_Matrix3x3& rot -) { - m_worldRotation = rot; -} - -const - MT_Point3& -SG_Spatial:: -GetLocalPosition( -) const { - return m_localPosition; -} - -const - MT_Matrix3x3& -SG_Spatial:: -GetLocalOrientation( -) const { - return m_localRotation; -} - -const - MT_Vector3& -SG_Spatial:: -GetLocalScale( -) const{ - return m_localScaling; -} - - -const - MT_Point3& -SG_Spatial:: -GetWorldPosition( -) const { - return m_worldPosition; -} - -const - MT_Matrix3x3& -SG_Spatial:: -GetWorldOrientation( -) const { - return m_worldRotation; -} - -const - MT_Vector3& -SG_Spatial:: -GetWorldScaling( -) const { - return m_worldScaling; -} - -void SG_Spatial::SetWorldFromLocalTransform() -{ - m_worldPosition= m_localPosition; - m_worldScaling= m_localScaling; - m_worldRotation= m_localRotation; -} - -SG_BBox& SG_Spatial::BBox() -{ - return m_bbox; -} - -void SG_Spatial::SetBBox(SG_BBox& bbox) -{ - m_bbox = bbox; -} - MT_Transform SG_Spatial::GetWorldTransform() const { return MT_Transform(m_worldPosition, diff --git a/source/gameengine/SceneGraph/SG_Spatial.h b/source/gameengine/SceneGraph/SG_Spatial.h index c2ed80d21b2..6e274487c9d 100644 --- a/source/gameengine/SceneGraph/SG_Spatial.h +++ b/source/gameengine/SceneGraph/SG_Spatial.h @@ -35,6 +35,7 @@ #include <MT_Matrix3x3.h> // or Quaternion later ? #include "SG_IObject.h" #include "SG_BBox.h" +#include "SG_ParentRelation.h" class SG_Node; @@ -62,9 +63,24 @@ protected: SG_BBox m_bbox; MT_Scalar m_radius; bool m_modified; + bool m_ogldirty; // true if the openGL matrix for this object must be recomputed public: + inline void ClearModified() + { + m_modified = false; + m_ogldirty = true; + } + inline void SetModified() + { + m_modified = true; + ActivateScheduleUpdateCallback(); + } + inline void ClearDirty() + { + m_ogldirty = false; + } /** * Define the realtionship this node has with it's parent * node. You should pass an unshared instance of an SG_ParentRelation @@ -84,9 +100,12 @@ public: SG_ParentRelation *relation ); - SG_ParentRelation * - GetParentRelation( - ); + SG_ParentRelation * GetParentRelation() + { + return m_parent_relation; + } + + /** @@ -105,15 +124,17 @@ public: bool local ); - void - SetLocalPosition( - const MT_Point3& trans - ); + void SetLocalPosition(const MT_Point3& trans) + { + m_localPosition = trans; + SetModified(); + } + + void SetWorldPosition(const MT_Point3& trans) + { + m_worldPosition = trans; + } - void - SetWorldPosition( - const MT_Point3& trans - ); void RelativeRotate( @@ -121,72 +142,102 @@ public: bool local ); - void - SetLocalOrientation( - const MT_Matrix3x3& rot - ); + void SetLocalOrientation(const MT_Matrix3x3& rot) + { + m_localRotation = rot; + SetModified(); + } + + // rot is arrange like openGL matrix + void SetLocalOrientation(const float* rot) + { + m_localRotation.setValue(rot); + SetModified(); + } + + void SetWorldOrientation(const MT_Matrix3x3& rot) + { + m_worldRotation = rot; + } + + void RelativeScale(const MT_Vector3& scale) + { + m_localScaling = m_localScaling * scale; + SetModified(); + } + + void SetLocalScale(const MT_Vector3& scale) + { + m_localScaling = scale; + SetModified(); + } + + void SetWorldScale(const MT_Vector3& scale) + { + m_worldScaling = scale; + } + + const MT_Point3& GetLocalPosition() const + { + return m_localPosition; + } + + const MT_Matrix3x3& GetLocalOrientation() const + { + return m_localRotation; + } + + const MT_Vector3& GetLocalScale() const + { + return m_localScaling; + } + + const MT_Point3& GetWorldPosition() const + { + return m_worldPosition; + } + + const MT_Matrix3x3& GetWorldOrientation() const + { + return m_worldRotation; + } + + const MT_Vector3& GetWorldScaling() const + { + return m_worldScaling; + } + + void SetWorldFromLocalTransform() + { + m_worldPosition= m_localPosition; + m_worldScaling= m_localScaling; + m_worldRotation= m_localRotation; + } - void - SetWorldOrientation( - const MT_Matrix3x3& rot - ); - void - RelativeScale( - const MT_Vector3& scale - ); - - void - SetLocalScale( - const MT_Vector3& scale - ); - - void - SetWorldScale( - const MT_Vector3& scale - ); - - const - MT_Point3& - GetLocalPosition( - ) const ; - - const - MT_Matrix3x3& - GetLocalOrientation( - ) const ; - - const - MT_Vector3& - GetLocalScale( - ) const; - - const - MT_Point3& - GetWorldPosition( - ) const ; - - const - MT_Matrix3x3& - GetWorldOrientation( - ) const ; - - const - MT_Vector3& - GetWorldScaling( - ) const ; - - void SetWorldFromLocalTransform(); MT_Transform GetWorldTransform() const; - bool ComputeWorldTransforms(const SG_Spatial *parent, bool& parentUpdated); + bool ComputeWorldTransforms(const SG_Spatial *parent, bool& parentUpdated) + { + return m_parent_relation->UpdateChildCoordinates(this,parent,parentUpdated); + } + /** * Bounding box functions. */ - SG_BBox& BBox(); - void SetBBox(SG_BBox & bbox); + SG_BBox& BBox() + { + return m_bbox; + } + + void SetBBox(SG_BBox& bbox) + { + m_bbox = bbox; + } + + bool inside(const MT_Point3 &point) const; void getBBox(MT_Point3 *box) const; void getAABBox(MT_Point3 *box) const; @@ -194,6 +245,7 @@ public: MT_Scalar Radius() const { return m_radius; } void SetRadius(MT_Scalar radius) { m_radius = radius; } bool IsModified() { return m_modified; } + bool IsDirty() { return m_ogldirty; } protected: friend class SG_Controller; @@ -210,7 +262,7 @@ protected: SG_Spatial( void* clientobj, void* clientinfo, - SG_Callbacks callbacks + SG_Callbacks& callbacks ); SG_Spatial( @@ -231,7 +283,6 @@ protected: double time, bool& parentUpdated ); - void SetModified(bool modified) { m_modified = modified; } }; diff --git a/source/gameengine/VideoTexture/BlendType.h b/source/gameengine/VideoTexture/BlendType.h index ac3ed8812a6..8b243c43912 100644 --- a/source/gameengine/VideoTexture/BlendType.h +++ b/source/gameengine/VideoTexture/BlendType.h @@ -25,6 +25,7 @@ http://www.gnu.org/copyleft/lesser.txt. /// class allows check type of blender python object and access its contained object +/// MUST ONLY BE USED FOR KX classes that are descendent of PyObjectPlus template <class PyObj> class BlendType { public: @@ -48,8 +49,9 @@ public: // if pointer to type is set and don't match to type of provided object, return NULL else if (obj->ob_type != m_objType) return NULL; - // return pointer to object - return (PyObj*)obj; + // return pointer to object, this class can only be used for KX object => + // the Py object is actually a proxy + return (PyObj*)BGE_PROXY_REF(obj); } /// parse arguments to get object diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp index 43d7566102a..6b23105a278 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp +++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp @@ -135,8 +135,13 @@ static PyGetSetDef filterBSGetSets[] = // define python type PyTypeObject FilterBlueScreenType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterBlueScreen", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp index 22ee729b200..5ff1f7f11ce 100644 --- a/source/gameengine/VideoTexture/FilterColor.cpp +++ b/source/gameengine/VideoTexture/FilterColor.cpp @@ -41,8 +41,13 @@ static PyGetSetDef filterGrayGetSets[] = // define python type PyTypeObject FilterGrayType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterGray", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -173,8 +178,13 @@ static PyGetSetDef filterColorGetSets[] = // define python type PyTypeObject FilterColorType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterColor", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -307,8 +317,13 @@ static PyGetSetDef filterLevelGetSets[] = // define python type PyTypeObject FilterLevelType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterLevel", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp index a7266967efb..9a2b1e90d5a 100644 --- a/source/gameengine/VideoTexture/FilterNormal.cpp +++ b/source/gameengine/VideoTexture/FilterNormal.cpp @@ -124,8 +124,13 @@ static PyGetSetDef filterNormalGetSets[] = // define python type PyTypeObject FilterNormalType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterNormal", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/FilterSource.cpp b/source/gameengine/VideoTexture/FilterSource.cpp index f3676e93a6d..4c75e14bbac 100644 --- a/source/gameengine/VideoTexture/FilterSource.cpp +++ b/source/gameengine/VideoTexture/FilterSource.cpp @@ -36,8 +36,13 @@ http://www.gnu.org/copyleft/lesser.txt. // define python type PyTypeObject FilterRGB24Type = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterRGB24", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -82,8 +87,13 @@ PyTypeObject FilterRGB24Type = // define python type PyTypeObject FilterRGBA32Type = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterRGBA32", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -128,8 +138,13 @@ PyTypeObject FilterRGBA32Type = // define python type PyTypeObject FilterBGR24Type = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.FilterBGR24", /*tp_name*/ sizeof(PyFilter), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index dcca20de24a..5e2841271a6 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -437,7 +437,9 @@ PyObject * Image_getSource (PyImage * self, PyObject * args) { // get arguments char * id; - if (self->m_image != NULL && PyArg_ParseTuple(args, "s", &id)) + if (!PyArg_ParseTuple(args, "s:getSource", &id)) + return NULL; + if (self->m_image != NULL) { // get source object PyObject * src = reinterpret_cast<PyObject*>(self->m_image->getSource(id)); @@ -460,7 +462,9 @@ PyObject * Image_setSource (PyImage * self, PyObject * args) // get arguments char * id; PyObject * obj; - if (self->m_image != NULL && PyArg_ParseTuple(args, "sO", &id, &obj)) + if (!PyArg_ParseTuple(args, "sO:setSource", &id, &obj)) + return NULL; + if (self->m_image != NULL) { // check type of object if (pyImageTypes.in(obj->ob_type)) diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp index 19ad17ac643..c7185660e83 100644 --- a/source/gameengine/VideoTexture/ImageBuff.cpp +++ b/source/gameengine/VideoTexture/ImageBuff.cpp @@ -71,10 +71,9 @@ static PyObject * load (PyImage * self, PyObject * args) short width; short height; // parse parameters - if (!PyArg_ParseTuple(args, "s#hh", &buff, &buffSize, &width, &height)) + if (!PyArg_ParseTuple(args, "s#hh:load", &buff, &buffSize, &width, &height)) { // report error - PyErr_SetString(PyExc_TypeError, "Parameters are not correct"); return NULL; } // else check buffer size @@ -123,8 +122,13 @@ static PyGetSetDef imageBuffGetSets[] = // define python type PyTypeObject ImageBuffType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageBuff", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp index b07b362818c..067143e57bb 100644 --- a/source/gameengine/VideoTexture/ImageMix.cpp +++ b/source/gameengine/VideoTexture/ImageMix.cpp @@ -109,7 +109,9 @@ PyObject * getWeight (PyImage * self, PyObject * args) short weight = 0; // get arguments char * id; - if (self->m_image != NULL && PyArg_ParseTuple(args, "s", &id)) + if (!PyArg_ParseTuple(args, "s:getWeight", &id)) + return NULL; + if (self->m_image != NULL) // get weight weight = getImageMix(self)->getWeight(id); // return weight @@ -123,7 +125,9 @@ PyObject * setWeight (PyImage * self, PyObject * args) // get arguments char * id; short weight = 0; - if (self->m_image != NULL && PyArg_ParseTuple(args, "sh", &id, &weight)) + if (!PyArg_ParseTuple(args, "sh:setWeight", &id, &weight)) + return NULL; + if (self->m_image != NULL) // set weight if (!getImageMix(self)->setWeight(id, weight)) { @@ -162,8 +166,13 @@ static PyGetSetDef imageMixGetSets[] = // define python type PyTypeObject ImageMixType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageMix", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 09c3c22f258..c4fb1fefd9c 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -181,7 +181,6 @@ void ImageRender::Render() frustrum.camnear = -mirrorOffset[2]; frustrum.camfar = -mirrorOffset[2]+m_clip; } - const float ortho = 100.0; const RAS_IRasterizer::StereoMode stereomode = m_rasterizer->GetStereoMode(); // The screen area that ImageViewport will copy is also the rendering zone @@ -214,44 +213,48 @@ void ImageRender::Render() float farfrust = m_camera->GetCameraFar(); float aspect_ratio = 1.0f; Scene *blenderScene = m_scene->GetBlenderScene(); + MT_Matrix4x4 projmat; - if (orthographic) { - lens *= ortho; - nearfrust = (nearfrust + 1.0)*ortho; - farfrust *= ortho; - } // compute the aspect ratio from frame blender scene settings so that render to texture // works the same in Blender and in Blender player if (blenderScene->r.ysch != 0) - aspect_ratio = float(blenderScene->r.xsch) / float(blenderScene->r.ysch); - - RAS_FramingManager::ComputeDefaultFrustum( - nearfrust, - farfrust, - lens, - aspect_ratio, - frustrum); - - MT_Matrix4x4 projmat = m_rasterizer->GetFrustumMatrix( - frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); - + aspect_ratio = float(blenderScene->r.xsch*blenderScene->r.xasp) / float(blenderScene->r.ysch*blenderScene->r.yasp); + + if (orthographic) { + + RAS_FramingManager::ComputeDefaultOrtho( + nearfrust, + farfrust, + m_camera->GetScale(), + aspect_ratio, + frustrum + ); + + projmat = m_rasterizer->GetOrthoMatrix( + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + } else + { + RAS_FramingManager::ComputeDefaultFrustum( + nearfrust, + farfrust, + lens, + aspect_ratio, + frustrum); + + projmat = m_rasterizer->GetFrustumMatrix( + frustrum.x1, frustrum.x2, frustrum.y1, frustrum.y2, frustrum.camnear, frustrum.camfar); + } m_camera->SetProjectionMatrix(projmat); } MT_Transform camtrans(m_camera->GetWorldToCamera()); - if (!m_camera->GetCameraData()->m_perspective) - camtrans.getOrigin()[2] *= ortho; MT_Matrix4x4 viewmat(camtrans); - m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldPosition(), - m_camera->GetCameraLocation(), m_camera->GetCameraOrientation()); + m_rasterizer->SetViewMatrix(viewmat, m_camera->NodeGetWorldOrientation(), m_camera->NodeGetWorldPosition(), m_camera->GetCameraData()->m_perspective); m_camera->SetModelviewMatrix(viewmat); // restore the stereo mode now that the matrix is computed m_rasterizer->SetStereoMode(stereomode); - // do not update the mesh transform, we don't want to do it more than once per frame - //m_scene->UpdateMeshTransformations(); - m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera); m_scene->RenderBuckets(camtrans, m_rasterizer, m_rendertools); @@ -373,8 +376,13 @@ static PyGetSetDef imageRenderGetSets[] = // define python type PyTypeObject ImageRenderType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageRender", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -553,8 +561,8 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj float yaxis[3] = {0.f, 1.f, 0.f}; float mirrorMat[3][3]; float left, right, top, bottom, back; - - m_camera= new KX_Camera(scene, KX_Scene::m_callbacks, camdata); + // make sure this camera will delete its node + m_camera= new KX_Camera(scene, KX_Scene::m_callbacks, camdata, true, true); m_camera->SetName("__mirror__cam__"); // don't add the camera to the scene object list, it doesn't need to be accessible m_owncamera = true; @@ -707,8 +715,13 @@ ImageRender::ImageRender (KX_Scene * scene, KX_GameObject * observer, KX_GameObj // define python type PyTypeObject ImageMirrorType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageMirror", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index a4e36b5948c..d2c23e758f6 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -289,8 +289,13 @@ static PyGetSetDef imageViewportGetSets[] = // define python type PyTypeObject ImageViewportType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageViewport", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp index 6d2676dce09..2d571675dbd 100644 --- a/source/gameengine/VideoTexture/PyTypeList.cpp +++ b/source/gameengine/VideoTexture/PyTypeList.cpp @@ -45,7 +45,6 @@ bool PyTypeList::in (PyTypeObject * type) /// add type to list void PyTypeList::add (PyTypeObject * type, const char * name) { - PyTypeListItem * typeItem; // if list doesn't exist, create it if (m_list.get() == NULL) m_list.reset(new PyTypeListType()); diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index 3533cee0f7f..f4105652f80 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -50,7 +50,7 @@ http://www.gnu.org/copyleft/lesser.txt. // macro for exception handling and logging #define CATCH_EXCP catch (Exception & exp) \ -{ exp.report(); } +{ exp.report(); return NULL; } // Blender GameObject type @@ -162,11 +162,12 @@ void Texture_dealloc (Texture * self) // release renderer Py_XDECREF(self->m_source); // close texture - Texture_close(self); + PyObject* ret = Texture_close(self); + Py_DECREF(ret); // release scaled image buffer delete [] self->m_scaledImg; // release object - self->ob_type->tp_free((PyObject*)self); + ((PyObject *)self)->ob_type->tp_free((PyObject*)self); } @@ -278,7 +279,7 @@ PyObject * Texture_refresh (Texture * self, PyObject * args) { // get parameter - refresh source PyObject * param; - if (!PyArg_ParseTuple(args, "O", ¶m) || !PyBool_Check(param)) + if (!PyArg_ParseTuple(args, "O:refresh", ¶m) || !PyBool_Check(param)) { // report error PyErr_SetString(PyExc_TypeError, "The value must be a bool"); @@ -433,8 +434,13 @@ static PyGetSetDef textureGetSets[] = // class Texture declaration PyTypeObject TextureType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.Texture", /*tp_name*/ sizeof(Texture), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/VideoBase.cpp b/source/gameengine/VideoTexture/VideoBase.cpp index 3c703d75cda..5d449a158d8 100644 --- a/source/gameengine/VideoTexture/VideoBase.cpp +++ b/source/gameengine/VideoTexture/VideoBase.cpp @@ -113,7 +113,10 @@ void Video_open (VideoBase * self, char * file, short captureID) PyObject * Video_play (PyImage * self) { if (getVideo(self)->play()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } -// stop video +// pause video +PyObject * Video_pause (PyImage * self) +{ if (getVideo(self)->pause()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } + PyObject * Video_stop (PyImage * self) { if (getVideo(self)->stop()) Py_RETURN_TRUE; else Py_RETURN_FALSE; } @@ -146,7 +149,7 @@ int Video_setRange (PyImage * self, PyObject * value, void * closure) || !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 0)) || !PyFloat_Check(PySequence_Fast_GET_ITEM(value, 1))) { - PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 longs"); + PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 2 float"); return -1; } // set range diff --git a/source/gameengine/VideoTexture/VideoBase.h b/source/gameengine/VideoTexture/VideoBase.h index 15ecb7a78f4..0c8668ee0bc 100644 --- a/source/gameengine/VideoTexture/VideoBase.h +++ b/source/gameengine/VideoTexture/VideoBase.h @@ -80,7 +80,17 @@ public: } return false; } - /// stop/pause video + /// pause video + virtual bool pause (void) + { + if (m_status == SourcePlaying) + { + m_status = SourceStopped; + return true; + } + return false; + } + /// stop video virtual bool stop (void) { if (m_status == SourcePlaying) @@ -170,6 +180,7 @@ template <class T> void Video_init (PyImage * self) // video functions void Video_open (VideoBase * self, char * file, short captureID); PyObject * Video_play (PyImage * self); +PyObject * Video_pause (PyImage * self); PyObject * Video_stop (PyImage * self); PyObject * Video_refresh (PyImage * self); PyObject * Video_getStatus (PyImage * self, void * closure); diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index 5265b0ecb93..1a5481488c0 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -117,6 +117,7 @@ bool VideoFFmpeg::release() } m_codec = NULL; m_status = SourceStopped; + m_lastFrame = -1; return true; } @@ -669,12 +670,12 @@ bool VideoFFmpeg::play (void) } -// stop video -bool VideoFFmpeg::stop (void) +// pause video +bool VideoFFmpeg::pause (void) { try { - if (VideoBase::stop()) + if (VideoBase::pause()) { return true; } @@ -683,6 +684,20 @@ bool VideoFFmpeg::stop (void) return false; } +// stop video +bool VideoFFmpeg::stop (void) +{ + try + { + VideoBase::stop(); + // force restart when play + m_lastFrame = -1; + return true; + } + CATCH_EXCP; + return false; +} + // set video range void VideoFFmpeg::setRange (double start, double stop) @@ -721,6 +736,8 @@ void VideoFFmpeg::loadFrame (void) { // get actual time double startTime = PIL_check_seconds_timer(); + if (m_lastFrame == -1 && !m_isFile) + m_startTime = startTime; double actTime = startTime - m_startTime; // if video has ended if (m_isFile && actTime * m_frameRate >= m_range[1]) @@ -886,28 +903,47 @@ AVFrame *VideoFFmpeg::grabFrame(long position) if (position != m_curPosition + 1) { double timeBase = av_q2d(m_formatCtx->streams[m_videoStream]->time_base); - long long pos = (long long) - ((long long) (position - m_preseek) * AV_TIME_BASE / m_baseFrameRate); - long long startTs = m_formatCtx->streams[m_videoStream]->start_time; + int64_t pos = (int64_t)((position - m_preseek) / (m_baseFrameRate*timeBase)); + int64_t startTs = m_formatCtx->streams[m_videoStream]->start_time; + int seekres; if (pos < 0) pos = 0; if (startTs != AV_NOPTS_VALUE) - pos += (long long)(startTs * AV_TIME_BASE * timeBase); + pos += startTs; if (position <= m_curPosition || !m_eof) { - // no need to seek past the end of the file - if (av_seek_frame(m_formatCtx, -1, pos, AVSEEK_FLAG_BACKWARD) >= 0) +#if 0 + // Tried to make this work but couldn't: seeking on byte is ignored by the + // format plugin and it will generally continue to read from last timestamp. + // Too bad because frame seek is not always able to get the first frame + // of the file. + if (position <= m_preseek) + { + // we can safely go the begining of the file + if (av_seek_frame(m_formatCtx, m_videoStream, 0, AVSEEK_FLAG_BYTE) >= 0) + { + // binary seek does not reset the timestamp, must do it now + av_update_cur_dts(m_formatCtx, m_formatCtx->streams[m_videoStream], startTs); + m_curPosition = 0; + } + } + else +#endif { // current position is now lost, guess a value. - // It's not important because it will be set at this end of this function - m_curPosition = position - m_preseek - 1; + if (av_seek_frame(m_formatCtx, m_videoStream, pos, AVSEEK_FLAG_BACKWARD) >= 0) + { + // current position is now lost, guess a value. + // It's not important because it will be set at this end of this function + m_curPosition = position - m_preseek - 1; + } } } // this is the timestamp of the frame we're looking for - targetTs = (long long)(((double) position) / m_baseFrameRate / timeBase); + targetTs = (int64_t)(position / (m_baseFrameRate * timeBase)); if (startTs != AV_NOPTS_VALUE) targetTs += startTs; @@ -1097,8 +1133,9 @@ int VideoFFmpeg_setDeinterlace (PyImage * self, PyObject * value, void * closure // methods structure static PyMethodDef videoMethods[] = { // methods from VideoBase class - {"play", (PyCFunction)Video_play, METH_NOARGS, "Play video"}, - {"stop", (PyCFunction)Video_stop, METH_NOARGS, "Stop (pause) video"}, + {"play", (PyCFunction)Video_play, METH_NOARGS, "Play (restart) video"}, + {"pause", (PyCFunction)Video_pause, METH_NOARGS, "pause video"}, + {"stop", (PyCFunction)Video_stop, METH_NOARGS, "stop video (play will replay it from start)"}, {"refresh", (PyCFunction)Video_refresh, METH_NOARGS, "Refresh video - get its status"}, {NULL} }; @@ -1123,8 +1160,13 @@ static PyGetSetDef videoGetSets[] = // python type declaration PyTypeObject VideoFFmpegType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.VideoFFmpeg", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ @@ -1173,7 +1215,7 @@ static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds char * file = NULL; // get parameters - if (!PyArg_ParseTuple(args, "s", &file)) + if (!PyArg_ParseTuple(args, "s:ImageFFmpeg", &file)) return -1; try @@ -1198,8 +1240,9 @@ static int ImageFFmpeg_init (PyObject * pySelf, PyObject * args, PyObject * kwds PyObject * Image_reload (PyImage * self, PyObject *args) { char * newname = NULL; - - if (self->m_image != NULL && PyArg_ParseTuple(args, "|s", &newname)) + if (!PyArg_ParseTuple(args, "|s:reload", &newname)) + return NULL; + if (self->m_image != NULL) { VideoFFmpeg* video = getFFmpeg(self); // check type of object @@ -1241,8 +1284,13 @@ static PyGetSetDef imageGetSets[] = // python type declaration PyTypeObject ImageFFmpegType = { - PyObject_HEAD_INIT(NULL) +#if (PY_VERSION_HEX >= 0x02060000) + PyVarObject_HEAD_INIT(NULL, 0) +#else + /* python 2.5 and below */ + PyObject_HEAD_INIT( NULL ) /* required py macro */ 0, /*ob_size*/ +#endif "VideoTexture.ImageFFmpeg", /*tp_name*/ sizeof(PyImage), /*tp_basicsize*/ 0, /*tp_itemsize*/ diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h index 51f1067c466..fbd04e7e1fc 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.h +++ b/source/gameengine/VideoTexture/VideoFFmpeg.h @@ -83,9 +83,10 @@ public: /// play video virtual bool play (void); - /// stop/pause video + /// pause video + virtual bool pause (void); + /// stop video virtual bool stop (void); - /// set play range virtual void setRange (double start, double stop); /// set frame rate diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index c11e7fffecd..1dcc72c8f7d 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -74,7 +74,7 @@ static PyObject * getLastError (PyObject *self, PyObject *args) static PyObject * setLogFile (PyObject *self, PyObject *args) { // get parameters - if (!PyArg_ParseTuple(args, "s", &Exception::m_logFile)) + if (!PyArg_ParseTuple(args, "s:setLogFile", &Exception::m_logFile)) return Py_BuildValue("i", -1); // log file was loaded return Py_BuildValue("i", 0); @@ -86,7 +86,7 @@ static PyObject * imageToArray (PyObject * self, PyObject *args) { // parameter is Image object PyObject * pyImg; - if (!PyArg_ParseTuple(args, "O", &pyImg) || !pyImageTypes.in(pyImg->ob_type)) + if (!PyArg_ParseTuple(args, "O:imageToArray", &pyImg) || !pyImageTypes.in(pyImg->ob_type)) { // if object is incorect, report error PyErr_SetString(PyExc_TypeError, "VideoTexture.imageToArray(image): The value must be a image source object"); @@ -159,8 +159,25 @@ static void registerAllTypes(void) pyFilterTypes.add(&FilterBGR24Type, "FilterBGR24"); } + +#if (PY_VERSION_HEX >= 0x03000000) +static struct PyModuleDef VideoTexture_module_def = { + {}, /* m_base */ + "VideoTexture", /* m_name */ + "Module that allows to play video files on textures in GameBlender.", /* m_doc */ + 0, /* m_size */ + moduleMethods, /* m_methods */ + 0, /* m_reload */ + 0, /* m_traverse */ + 0, /* m_clear */ + 0, /* m_free */ +}; +#endif + PyObject* initVideoTexture(void) { + PyObject * m; + // initialize GL extensions //bgl::InitExtensions(0); @@ -175,9 +192,25 @@ PyObject* initVideoTexture(void) if (PyType_Ready(&TextureType) < 0) return NULL; - PyObject * m = Py_InitModule4("VideoTexture", moduleMethods, - "Module that allows to play video files on textures in GameBlender.", - (PyObject*)NULL,PYTHON_API_VERSION); + /* Use existing module where possible + * be careful not to init any runtime vars after this */ + m = PyImport_ImportModule( "VideoTexture" ); + if(m) { + Py_DECREF(m); + return m; + } + else { + PyErr_Clear(); + +#if (PY_VERSION_HEX >= 0x03000000) + m = PyModule_Create(&VideoTexture_module_def); +#else + m = Py_InitModule4("VideoTexture", moduleMethods, + "Module that allows to play video files on textures in GameBlender.", + (PyObject*)NULL,PYTHON_API_VERSION); +#endif + } + if (m == NULL) return NULL; @@ -187,9 +220,10 @@ PyObject* initVideoTexture(void) Py_INCREF(&TextureType); PyModule_AddObject(m, (char*)"Texture", (PyObject*)&TextureType); - + // init last error description Exception::m_lastError[0] = '\0'; + return m; } |