diff options
Diffstat (limited to 'source/gameengine')
271 files changed, 6317 insertions, 4545 deletions
diff --git a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp index c652532895f..91382669d5c 100644 --- a/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp +++ b/source/gameengine/BlenderRoutines/BL_KetsjiEmbedStart.cpp @@ -40,7 +40,7 @@ # pragma warning (disable:4786) #endif -#include "GL/glew.h" +#include "glew-mx.h" #include "KX_BlenderCanvas.h" #include "KX_BlenderKeyboardDevice.h" @@ -63,7 +63,7 @@ #include "BL_System.h" #include "GPU_extensions.h" -#include "Value.h" +#include "EXP_Value.h" extern "C" { @@ -79,6 +79,7 @@ extern "C" { #include "BKE_ipo.h" #include "BKE_main.h" #include "BKE_context.h" + #include "BKE_sound.h" /* avoid c++ conflict with 'new' */ #define new _new @@ -101,9 +102,7 @@ typedef void * wmUIHandlerRemoveFunc; } #ifdef WITH_AUDASPACE -# include "AUD_C-API.h" -# include "AUD_I3DDevice.h" -# include "AUD_IDevice.h" +# include AUD_DEVICE_H #endif static BlendFileData *load_game_data(char *filename) @@ -280,8 +279,8 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 0) != 0); #endif // bool novertexarrays = (SYS_GetCommandLineInt(syshandle, "novertexarrays", 0) != 0); - bool mouse_state = startscene->gm.flag & GAME_SHOW_MOUSE; - bool restrictAnimFPS = startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES; + bool mouse_state = (startscene->gm.flag & GAME_SHOW_MOUSE) != 0; + bool restrictAnimFPS = (startscene->gm.flag & GAME_RESTRICT_ANIM_UPDATES) != 0; short drawtype = v3d->drawtype; @@ -299,7 +298,8 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c canvas->SetMouseState(RAS_ICanvas::MOUSE_INVISIBLE); // Setup vsync - int previous_vsync = canvas->GetSwapInterval(); + int previous_vsync = 0; + canvas->GetSwapInterval(previous_vsync); if (startscene->gm.vsync == VSYNC_ADAPTIVE) canvas->SetSwapInterval(-1); else @@ -445,7 +445,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c rasterizer->SetEyeSeparation(scene->gm.eyeseparation); } - rasterizer->SetBackColor(scene->gm.framing.col[0], scene->gm.framing.col[1], scene->gm.framing.col[2], 0.0f); + rasterizer->SetBackColor(scene->gm.framing.col); } if (exitrequested != KX_EXIT_REQUEST_QUIT_GAME) @@ -456,21 +456,13 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c ketsjiengine->SetCameraOverrideUseOrtho((rv3d->persp == RV3D_ORTHO)); ketsjiengine->SetCameraOverrideProjectionMatrix(MT_CmMatrix4x4(rv3d->winmat)); ketsjiengine->SetCameraOverrideViewMatrix(MT_CmMatrix4x4(rv3d->viewmat)); - if (rv3d->persp == RV3D_ORTHO) - { - ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); - } - else - { - ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); - } + ketsjiengine->SetCameraOverrideClipping(v3d->near, v3d->far); ketsjiengine->SetCameraOverrideLens(v3d->lens); } // create a scene converter, create and convert the startingscene KX_ISceneConverter* sceneconverter = new KX_BlenderSceneConverter(blenderdata, ketsjiengine); ketsjiengine->SetSceneConverter(sceneconverter); - sceneconverter->addInitFromFrame=false; if (always_use_expand_framing) sceneconverter->SetAlwaysUseExpandFraming(true); @@ -509,13 +501,10 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c ketsjiengine->InitDome(scene->gm.dome.res, scene->gm.dome.mode, scene->gm.dome.angle, scene->gm.dome.resbuf, scene->gm.dome.tilt, scene->gm.dome.warptext); // initialize 3D Audio Settings - AUD_I3DDevice* dev = AUD_get3DDevice(); - if (dev) - { - dev->setSpeedOfSound(scene->audio.speed_of_sound); - dev->setDopplerFactor(scene->audio.doppler_factor); - dev->setDistanceModel(AUD_DistanceModel(scene->audio.distance_model)); - } + AUD_Device* device = BKE_sound_get_device(); + AUD_Device_setSpeedOfSound(device, scene->audio.speed_of_sound); + AUD_Device_setDopplerFactor(device, scene->audio.doppler_factor); + AUD_Device_setDistanceModel(device, AUD_DistanceModel(scene->audio.distance_model)); // from see blender.c: // FIXME: this version patching should really be part of the file-reading code, @@ -555,6 +544,10 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c if (python_main) { char *python_code = KX_GetPythonCode(blenderdata, python_main); if (python_code) { + // Set python environement variable. + KX_SetActiveScene(startscene); + PHY_SetActiveEnvironment(startscene->GetPhysicsEnvironment()); + ketsjinextframestate.ketsjiengine = ketsjiengine; ketsjinextframestate.C = C; ketsjinextframestate.win = win; @@ -682,7 +675,7 @@ extern "C" void StartKetsjiShell(struct bContext *C, struct ARegion *ar, rcti *c } // stop all remaining playing sounds - AUD_getDevice()->stopAll(); + AUD_Device_stopAll(BKE_sound_get_device()); } while (exitrequested == KX_EXIT_REQUEST_RESTART_GAME || exitrequested == KX_EXIT_REQUEST_START_OTHER_GAME); diff --git a/source/gameengine/BlenderRoutines/CMakeLists.txt b/source/gameengine/BlenderRoutines/CMakeLists.txt index 73dbe005518..aaeb2e10462 100644 --- a/source/gameengine/BlenderRoutines/CMakeLists.txt +++ b/source/gameengine/BlenderRoutines/CMakeLists.txt @@ -24,6 +24,7 @@ set(INC ../../blender/makesrna ../../blender/windowmanager ../../../intern/container + ../../../intern/glew-mx ../../../intern/guardedalloc ../../../intern/string ) @@ -52,13 +53,14 @@ set(SRC KX_BlenderSystem.h ) -add_definitions(-DGLEW_STATIC) +add_definitions(${GL_DEFINITIONS}) if(WITH_AUDASPACE) - list(APPEND INC - ../../../intern/audaspace/intern + add_definitions(${AUDASPACE_DEFINITIONS}) + + list(APPEND INC_SYS + ${AUDASPACE_C_INCLUDE_DIRS} ) - add_definitions(-DWITH_AUDASPACE) endif() if(WITH_CODEC_FFMPEG) diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp index b3e0b4c3ea6..e37818678d6 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.cpp @@ -29,7 +29,7 @@ * \ingroup blroutines */ -#include <GL/glew.h> +#include "glew-mx.h" #include "MEM_guardedalloc.h" @@ -67,6 +67,7 @@ m_frame_rect(rect) // area boundaries needed for mouse coordinates in Letterbox framing mode m_area_left = ar->winrct.xmin; m_area_top = ar->winrct.ymax; + m_frame = 1; glGetIntegerv(GL_VIEWPORT, (GLint *)m_viewport); } @@ -91,9 +92,14 @@ void KX_BlenderCanvas::SetSwapInterval(int interval) wm_window_set_swap_interval(m_win, interval); } -int KX_BlenderCanvas::GetSwapInterval() +bool KX_BlenderCanvas::GetSwapInterval(int &intervalOut) { - return wm_window_get_swap_interval(m_win); + return wm_window_get_swap_interval(m_win, &intervalOut); +} + +void KX_BlenderCanvas::GetDisplayDimensions(int &width, int &height) +{ + wm_get_screensize(&width, &height); } void KX_BlenderCanvas::ResizeWindow(int width, int height) @@ -350,7 +356,9 @@ void KX_BlenderCanvas::MakeScreenShot(const char *filename) char path[FILE_MAX]; BLI_strncpy(path, filename, sizeof(path)); BLI_path_abs(path, G.main->name); - BKE_add_image_extension_from_type(path, im_format.imtype); + BLI_path_frame(path, m_frame, 0); + m_frame++; + BKE_image_path_ensure_ext_from_imtype(path, im_format.imtype); /* create and save imbuf */ ImBuf *ibuf = IMB_allocImBuf(dumpsx, dumpsy, 24, 0); diff --git a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h index 9ad80cb1737..817a667d783 100644 --- a/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h +++ b/source/gameengine/BlenderRoutines/KX_BlenderCanvas.h @@ -82,10 +82,13 @@ public: int interval ); - int + bool GetSwapInterval( + int &intervalOut ); + void GetDisplayDimensions(int &width, int &height); + void ResizeWindow( int width, @@ -209,6 +212,7 @@ private: RAS_Rect m_area_rect; int m_area_left; int m_area_top; + int m_frame; #ifdef WITH_CXX_GUARDEDALLOC diff --git a/source/gameengine/BlenderRoutines/SConscript b/source/gameengine/BlenderRoutines/SConscript index 62d657189c5..ea14092943a 100644 --- a/source/gameengine/BlenderRoutines/SConscript +++ b/source/gameengine/BlenderRoutines/SConscript @@ -29,9 +29,8 @@ Import ('env') sources = env.Glob('*.cpp') -defs = [ - 'GLEW_STATIC', - ] +defs = [] +defs += env['BF_GL_DEFINITIONS'] incs = [ '.', @@ -39,8 +38,8 @@ incs = [ '#intern/guardedalloc', '#intern/string', '#source/blender', - '#extern/glew/include', - '#intern/audaspace/intern', + env['BF_GLEW_INC'], + '#/intern/glew-mx', '#intern/ghost/include', '#intern/moto/include', '#source/blender/blenfont', @@ -68,6 +67,10 @@ incs = [ ] incs = ' '.join(incs) +if env['WITH_BF_AUDASPACE']: + defs += env['BF_AUDASPACE_DEF'] + incs += ' ' + env['BF_AUDASPACE_C_INC'] + if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') diff --git a/source/gameengine/CMakeLists.txt b/source/gameengine/CMakeLists.txt index cf7895e98ea..62523175f46 100644 --- a/source/gameengine/CMakeLists.txt +++ b/source/gameengine/CMakeLists.txt @@ -23,6 +23,8 @@ # # ***** END GPL LICENSE BLOCK ***** +remove_extra_strict_flags() + # there are too many inter-includes so best define here if(WITH_PYTHON) blender_include_dirs_sys("${PYTHON_INCLUDE_DIRS}") diff --git a/source/gameengine/Converter/BL_ActionActuator.cpp b/source/gameengine/Converter/BL_ActionActuator.cpp index 3dd013dfd63..d4cfeb2201a 100644 --- a/source/gameengine/Converter/BL_ActionActuator.cpp +++ b/source/gameengine/Converter/BL_ActionActuator.cpp @@ -49,8 +49,8 @@ #include "MT_Matrix4x4.h" #include "BKE_action.h" -#include "FloatValue.h" -#include "PyObjectPlus.h" +#include "EXP_FloatValue.h" +#include "EXP_PyObjectPlus.h" #include "KX_PyMath.h" extern "C" { @@ -90,7 +90,7 @@ BL_ActionActuator::BL_ActionActuator(SCA_IObject *gameobj, m_stridelength(stride), m_layer_weight(layer_weight), m_playtype(playtype), - m_blendmode(blend_mode), + m_blendmode(blend_mode), m_priority(priority), m_layer(layer), m_ipo_flags(ipo_flags), @@ -256,12 +256,14 @@ bool BL_ActionActuator::Update(double curtime, bool frame) if ((m_flag & ACT_FLAG_PLAY_END) && (m_flag & ACT_FLAG_ACTIVE) && obj->IsActionDone(m_layer)) { m_flag &= ~ACT_FLAG_ACTIVE; - m_flag &= ~ACT_FLAG_ATTEMPT_PLAY; - if (m_playtype == ACT_ACTION_PINGPONG) + if (m_playtype == ACT_ACTION_PINGPONG) { m_flag ^= ACT_FLAG_REVERSE; - else + } + else { + m_flag &= ~ACT_FLAG_ATTEMPT_PLAY; return false; + } } // If a different action is playing, we've been overruled and are no longer active @@ -320,8 +322,9 @@ bool BL_ActionActuator::Update(double curtime, bool frame) case ACT_ACTION_FLIPPER: // Convert into a play action and play back to the beginning + float temp = end; end = start; - start = obj->GetActionFrame(m_layer); + start = curr_action ? obj->GetActionFrame(m_layer) : temp; obj->PlayAction(m_action->id.name+2, start, end, m_layer, m_priority, 0, BL_Action::ACT_MODE_PLAY, m_layer_weight, m_ipo_flags, 1.f, blendmode); m_flag |= ACT_FLAG_PLAY_END; diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp index cb33ff0e1e3..2b8dfd8f8d1 100644 --- a/source/gameengine/Converter/BL_ArmatureChannel.cpp +++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp @@ -295,7 +295,7 @@ PyObject *BL_ArmatureChannel::py_attr_get_joint_rotation(void *self_v, const str mul_v3_fl(joints,norm); break; } - return Vector_CreatePyObject(joints, 3, Py_NEW, NULL); + return Vector_CreatePyObject(joints, 3, NULL); } int BL_ArmatureChannel::py_attr_set_joint_rotation(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) diff --git a/source/gameengine/Converter/BL_ArmatureChannel.h b/source/gameengine/Converter/BL_ArmatureChannel.h index 51114c5df30..d349e6e9dae 100644 --- a/source/gameengine/Converter/BL_ArmatureChannel.h +++ b/source/gameengine/Converter/BL_ArmatureChannel.h @@ -35,7 +35,7 @@ #include "DNA_action_types.h" #include "CTR_HashedPtr.h" #include "CTR_Map.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" class SCA_IObject; class KX_GameObject; diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp index e515574df8b..88d82e21d61 100644 --- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp +++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp @@ -334,7 +334,7 @@ PyObject *BL_ArmatureConstraint::py_attr_getattr(void *self_v, const struct KX_P } switch (attr_order) { case BCA_IKWEIGHT: - return PyFloat_FromDouble((ikconstraint)?ikconstraint->weight : 0.0f); + return PyFloat_FromDouble(ikconstraint->weight); case BCA_IKTYPE: return PyLong_FromLong(ikconstraint->type); case BCA_IKFLAG: diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.h b/source/gameengine/Converter/BL_ArmatureConstraint.h index 98c2954baf4..1d9f7f0d548 100644 --- a/source/gameengine/Converter/BL_ArmatureConstraint.h +++ b/source/gameengine/Converter/BL_ArmatureConstraint.h @@ -35,7 +35,7 @@ #include "DNA_constraint_types.h" #include "CTR_HashedPtr.h" #include "CTR_Map.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" class SCA_IObject; class KX_GameObject; diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index 8d73e591113..74ebdbcf1b5 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -101,7 +101,7 @@ static void game_copy_pose(bPose **dst, bPose *src, int copy_constraint) out->chanhash = NULL; out->agroups.first= out->agroups.last= NULL; out->ikdata = NULL; - out->ikparam = MEM_dupallocN(src->ikparam); + out->ikparam = MEM_dupallocN(src->ikparam); out->flag |= POSE_GAME_ENGINE; BLI_duplicatelist(&out->chanbase, &src->chanbase); @@ -230,10 +230,15 @@ BL_ArmatureObject::BL_ArmatureObject( m_origObjArma = armature; // Keep a copy of the original armature so we can fix drivers later m_objArma = BKE_object_copy(armature); m_objArma->data = BKE_armature_copy((bArmature *)armature->data); + // During object replication ob->data is increase, we decrease it now because we get a copy. + id_us_min(&((bArmature *)m_origObjArma->data)->id); m_pose = m_objArma->pose; - // need this to get iTaSC working ok in the BGE - m_pose->flag |= POSE_GAME_ENGINE; + // need this to get iTaSC working ok in the BGE + m_pose->flag |= POSE_GAME_ENGINE; memcpy(m_obmat, m_objArma->obmat, sizeof(m_obmat)); + + // The side-effect of this method registers this object as "animatable" with the KX_Scene. + GetActionManager(); } BL_ArmatureObject::~BL_ArmatureObject() @@ -247,8 +252,10 @@ BL_ArmatureObject::~BL_ArmatureObject() delete channel; } - if (m_objArma) + if (m_objArma) { + BKE_libblock_free(G.main, m_objArma->data); BKE_libblock_free(G.main, m_objArma); + } } @@ -265,7 +272,7 @@ void BL_ArmatureObject::LoadConstraints(KX_BlenderSceneConverter* converter) // get the persistent pose structure bPoseChannel* pchan; bConstraint* pcon; - bConstraintTypeInfo* cti; + const bConstraintTypeInfo* cti; Object* blendtarget; KX_GameObject* gametarget; KX_GameObject* gamesubtarget; diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 87b64582e11..c74fd82a9f6 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -52,23 +52,13 @@ #include <algorithm> #include "BL_BlenderDataConversion.h" -#include "KX_BlenderScalarInterpolator.h" -#include "RAS_IPolygonMaterial.h" - -// Expressions -#include "ListValue.h" -#include "IntValue.h" -// Collision & Fuzzics LTD +#include "MT_Transform.h" +#include "MT_MinMax.h" #include "PHY_Pro.h" #include "PHY_IPhysicsEnvironment.h" -#include "PHY_DynamicTypes.h" - -#include "KX_Scene.h" -#include "KX_GameObject.h" -#include "RAS_FramingManager.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" #include "RAS_ILightObject.h" @@ -76,31 +66,27 @@ #include "KX_ConvertActuators.h" #include "KX_ConvertControllers.h" #include "KX_ConvertSensors.h" - #include "SCA_LogicManager.h" -#include "SCA_EventManager.h" #include "SCA_TimeEventManager.h" + +#include "KX_ClientObjectInfo.h" +#include "KX_Scene.h" +#include "KX_GameObject.h" #include "KX_Light.h" #include "KX_Camera.h" -#include "KX_ClientObjectInfo.h" #include "KX_EmptyObject.h" #include "KX_FontObject.h" -#include "MT_Point3.h" -#include "MT_Transform.h" -#include "MT_MinMax.h" -#include "SCA_IInputDevice.h" + #include "RAS_TexMatrix.h" #include "RAS_ICanvas.h" -#include "RAS_MaterialBucket.h" -//#include "KX_BlenderPolyMaterial.h" #include "RAS_Polygon.h" #include "RAS_TexVert.h" #include "RAS_BucketManager.h" +#include "RAS_IPolygonMaterial.h" #include "BL_Material.h" #include "KX_BlenderMaterial.h" #include "BL_Texture.h" -#include "DNA_action_types.h" #include "BKE_main.h" #include "BKE_global.h" #include "BKE_object.h" @@ -109,10 +95,10 @@ #include "BL_SkinDeformer.h" #include "BL_MeshDeformer.h" #include "KX_SoftBodyDeformer.h" -//#include "BL_ArmatureController.h" #include "BLI_utildefines.h" #include "BLI_listbase.h" -#include "BlenderWorldInfo.h" + +#include "KX_WorldInfo.h" #include "KX_KetsjiEngine.h" #include "KX_BlenderSceneConverter.h" @@ -143,13 +129,14 @@ #include "DNA_sound_types.h" #include "DNA_key_types.h" #include "DNA_armature_types.h" +#include "DNA_action_types.h" #include "DNA_object_force.h" +#include "DNA_constraint_types.h" #include "MEM_guardedalloc.h" #include "BKE_key.h" #include "BKE_mesh.h" -#include "MT_Point3.h" #include "BLI_math.h" @@ -170,29 +157,19 @@ extern Material defmaterial; /* material.c */ #include "KX_BlenderInputDevice.h" #include "KX_ConvertProperties.h" -#include "KX_HashedPtr.h" - - -#include "KX_ScalarInterpolator.h" - -#include "KX_IpoConvert.h" -#include "BL_System.h" #include "SG_Node.h" #include "SG_BBox.h" #include "SG_Tree.h" +#include "KX_SG_NodeRelationships.h" +#include "KX_SG_BoneParentNodeRelationship.h" #ifdef WITH_BULLET #include "CcdPhysicsEnvironment.h" #include "CcdGraphicController.h" #endif -#include "KX_MotionState.h" - -// This file defines relationships between parents and children -// in the game engine. -#include "KX_SG_NodeRelationships.h" -#include "KX_SG_BoneParentNodeRelationship.h" +#include "KX_MotionState.h" #include "BL_ArmatureObject.h" #include "BL_DeformableGameObject.h" @@ -200,18 +177,9 @@ extern Material defmaterial; /* material.c */ #include "KX_NavMeshObject.h" #include "KX_ObstacleSimulation.h" -#ifdef __cplusplus -extern "C" { -#endif -//XXX void update_for_newframe(); -//void BKE_scene_update_for_newframe(struct Scene *sce, unsigned int lay); -//void do_all_data_ipos(void); -#ifdef __cplusplus -} -#endif - #include "BLI_threads.h" + static bool default_light_mode = 0; static std::map<int, SCA_IInputDevice::KX_EnumInputs> create_translate_table() @@ -389,6 +357,11 @@ static std::map<int, SCA_IInputDevice::KX_EnumInputs> create_translate_table() static std::map<int, SCA_IInputDevice::KX_EnumInputs> gReverseKeyTranslateTable = create_translate_table(); +SCA_IInputDevice::KX_EnumInputs ConvertKeyCode(int key_code) +{ + return gReverseKeyTranslateTable[key_code]; +} + static unsigned int KX_rgbaint2uint_new(unsigned int icol) { union @@ -889,20 +862,20 @@ static bool ConvertMaterial( // swap the material color, so MCol on bitmap font works if (validmat && (use_vcol == false) && (mat->game.flag & GEMAT_TEXT)) { - rgb[0] = KX_rgbaint2uint_new(rgb[0]); - rgb[1] = KX_rgbaint2uint_new(rgb[1]); - rgb[2] = KX_rgbaint2uint_new(rgb[2]); - rgb[3] = KX_rgbaint2uint_new(rgb[3]); + material->rgb[0] = KX_rgbaint2uint_new(rgb[0]); + material->rgb[1] = KX_rgbaint2uint_new(rgb[1]); + material->rgb[2] = KX_rgbaint2uint_new(rgb[2]); + material->rgb[3] = KX_rgbaint2uint_new(rgb[3]); } if (validmat) material->matname =(mat->id.name); if (tface) { - material->tface = *tface; + ME_MTEXFACE_CPY(&material->mtexpoly, tface); } else { - memset(&material->tface, 0, sizeof(material->tface)); + memset(&material->mtexpoly, 0, sizeof(material->mtexpoly)); } material->material = mat; return true; @@ -986,8 +959,16 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, int totface = dm->getNumTessFaces(dm); const char *tfaceName = ""; + /* needs to be rewritten for loopdata */ if (tface) { - DM_add_tangent_layer(dm); + if (CustomData_get_layer_index(&dm->faceData, CD_TANGENT) == -1) { + bool generate_data = false; + if (CustomData_get_layer_index(&dm->loopData, CD_TANGENT) == -1) { + DM_calc_loop_tangents(dm); + generate_data = true; + } + DM_generate_tangent_tessface_data(dm, generate_data); + } tangent = (float(*)[4])dm->getTessFaceDataArray(dm, CD_TANGENT); } @@ -1022,7 +1003,6 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, meshobj->m_sharedvertex_map.resize(totvert); Material* ma = 0; - bool collider = true; MT_Point2 uvs[4][RAS_TexVert::MAX_UNIT]; unsigned int rgb[4] = {0}; @@ -1092,29 +1072,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, else ma = mesh->mat ? mesh->mat[mface->mat_nr]:NULL; - /* ckeck for texface since texface _only_ is used as a fallback */ - if (ma == NULL && tface == NULL) { + // Check for blender material + if (ma == NULL) { ma= &defmaterial; } { - bool visible = true; - bool twoside = false; RAS_MaterialBucket* bucket = material_from_mesh(ma, mface, tface, mcol, layers, lightlayer, rgb, uvs, tfaceName, scene, converter); // set render flags - if (ma) - { - visible = ((ma->game.flag & GEMAT_INVISIBLE)==0); - twoside = ((ma->game.flag & GEMAT_BACKCULL)==0); - collider = ((ma->game.flag & GEMAT_NOPHYSICS)==0); - } - else { - visible = true; - twoside = false; - collider = true; - } + bool visible = ((ma->game.flag & GEMAT_INVISIBLE)==0); + bool twoside = ((ma->game.flag & GEMAT_BACKCULL)==0); + bool collider = ((ma->game.flag & GEMAT_NOPHYSICS)==0); /* mark face as flat, so vertices are split */ bool flat = (mface->flag & ME_SMOOTH) == 0; @@ -1238,7 +1208,9 @@ static PHY_ShapeProps *CreateShapePropsFromBlenderObject(struct Object* blendero // velocity clamping XXX shapeProps->m_clamp_vel_min = blenderobject->min_vel; shapeProps->m_clamp_vel_max = blenderobject->max_vel; - + shapeProps->m_clamp_angvel_min = blenderobject->min_angvel; + shapeProps->m_clamp_angvel_max = blenderobject->max_angvel; + // Character physics properties shapeProps->m_step_height = blenderobject->step_height; shapeProps->m_jump_speed = blenderobject->jump_speed; @@ -1374,8 +1346,8 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, if (!(blenderobject->gameflag & OB_COLLISION)) { // Respond to all collisions so that Near sensors work on No Collision // objects. - gameobj->SetUserCollisionGroup(0xff); - gameobj->SetUserCollisionMask(0xff); + gameobj->SetUserCollisionGroup(0xffff); + gameobj->SetUserCollisionMask(0xffff); return; } @@ -1389,16 +1361,14 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, } bool isCompoundChild = false; - bool hasCompoundChildren = !parent && (blenderobject->gameflag & OB_CHILD); + bool hasCompoundChildren = !parent && (blenderobject->gameflag & OB_CHILD) && !(blenderobject->gameflag & OB_SOFT_BODY); /* When the parent is not OB_DYNAMIC and has no OB_COLLISION then it gets no bullet controller - * and cant be apart of the parents compound shape */ + * and cant be apart of the parents compound shape, same goes for OB_SOFT_BODY */ if (parent && (parent->gameflag & (OB_DYNAMIC | OB_COLLISION))) { - - if ((parent->gameflag & OB_CHILD) != 0 && (blenderobject->gameflag & OB_CHILD)) - { + if( (parent->gameflag & OB_CHILD)!=0 && (blenderobject->gameflag & OB_CHILD) && !(parent->gameflag & OB_SOFT_BODY)) { isCompoundChild = true; - } + } } if (processCompoundChildren != isCompoundChild) return; @@ -1429,16 +1399,6 @@ static void BL_CreatePhysicsObjectNew(KX_GameObject* gameobj, if ((blenderobject->gameflag & OB_RECORD_ANIMATION) != 0) gameobj->SetRecordAnimation(true); - // store materialname in auxinfo, needed for touchsensors - if (meshobj) - { - const STR_String& matname=meshobj->GetMaterialName(0); - gameobj->getClientInfo()->m_auxilary_info = (matname.Length() ? (void*)(matname.ReadPtr()+2) : NULL); - } else - { - gameobj->getClientInfo()->m_auxilary_info = 0; - } - delete shapeprops; delete smmaterial; if (dm) { @@ -1499,7 +1459,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->ortho_scale, ca->sensor_x, ca->sensor_y, ca->sensor_fit, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, ca->YF_dofdist); + RAS_CameraData camdata(ca->lens, ca->ortho_scale, ca->sensor_x, ca->sensor_y, ca->sensor_fit, ca->shiftx, ca->shifty, ca->clipsta, ca->clipend, ca->type == CAM_PERSP, ca->YF_dofdist); KX_Camera *gamecamera; gamecamera= new KX_Camera(kxscene, KX_Scene::m_callbacks, camdata); @@ -1568,7 +1528,7 @@ static KX_GameObject *gameobject_from_blenderobject( gameobj->AddMesh(meshobj); // gather levels of detail - if (BLI_countlist(&ob->lodlevels) > 1) { + if (BLI_listbase_count_ex(&ob->lodlevels, 2) > 1) { LodLevel *lod = ((LodLevel*)ob->lodlevels.first)->next; Mesh* lodmesh = mesh; Object* lodmatob = ob; @@ -1583,6 +1543,10 @@ static KX_GameObject *gameobject_from_blenderobject( } gameobj->AddLodMesh(BL_ConvertMesh(lodmesh, lodmatob, kxscene, converter, libloading)); } + if (blenderscene->gm.lodflag & SCE_LOD_USE_HYST) { + kxscene->SetLodHysteresis(true); + kxscene->SetLodHysteresisValue(blenderscene->gm.scehysteresis); + } } // for all objects: check whether they want to @@ -1676,7 +1640,7 @@ static KX_GameObject *gameobject_from_blenderobject( case OB_FONT: { - bool do_color_management = !(blenderscene->gm.flag & GAME_GLSL_NO_COLOR_MANAGEMENT); + bool do_color_management = BKE_scene_check_color_management_enabled(blenderscene); /* font objects have no bounding box */ gameobj = new KX_FontObject(kxscene,KX_Scene::m_callbacks, rendertools, ob, do_color_management); @@ -1711,9 +1675,6 @@ struct parentChildLink { SG_Node* m_gamechildnode; }; -#include "DNA_constraint_types.h" -//XXX #include "BIF_editconstraint.h" - static bPoseChannel *get_active_posechannel2(Object *ob) { bArmature *arm= (bArmature*)ob->data; @@ -1747,20 +1708,27 @@ static ListBase *get_active_constraints2(Object *ob) return NULL; } -static void UNUSED_FUNCTION(RBJconstraints)(Object *ob)//not used +static void UNUSED_FUNCTION(print_active_constraints2)(Object *ob) //not used, use to debug { - ListBase *conlist; - bConstraint *curcon; - - conlist = get_active_constraints2(ob); + bConstraint* curcon; + ListBase* conlist = get_active_constraints2(ob); if (conlist) { for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) { - printf("%i\n",curcon->type); } + } +} +// Copy base layer to object layer like in BKE_scene_set_background +static void blenderSceneSetBackground(Scene *blenderscene) +{ + Scene *it; + Base *base; + for (SETLOOPER(blenderscene, it, base)) { + base->object->lay = base->lay; + base->object->flag = base->flag; } } @@ -1778,12 +1746,21 @@ static KX_GameObject* getGameOb(STR_String busc,CListValue* sumolist) } +static bool bl_isConstraintInList(KX_GameObject *gameobj, set<KX_GameObject*> convertedlist) +{ + set<KX_GameObject*>::iterator gobit; + for (gobit = convertedlist.begin(); gobit != convertedlist.end(); gobit++) { + if ((*gobit)->GetName() == gameobj->GetName()) + return true; + } + return false; +} + /* helper for BL_ConvertBlenderObjects, avoids code duplication * note: all var names match args are passed from the caller */ static void bl_ConvertBlenderObject_Single( KX_BlenderSceneConverter *converter, - Scene *blenderscene, Object *blenderobject, - vector<MT_Vector3> &inivel, vector<MT_Vector3> &iniang, + Object *blenderobject, vector<parentChildLink> &vec_parent_child, CListValue* logicbrick_conversionlist, CListValue* objectlist, CListValue* inactivelist, CListValue* sumolist, @@ -1792,10 +1769,6 @@ static void bl_ConvertBlenderObject_Single( bool isInActiveLayer ) { - MT_Point3 posPrev; - MT_Matrix3x3 angor; - if (converter->addInitFromFrame) blenderscene->r.cfra=blenderscene->r.sfra; - MT_Point3 pos( blenderobject->loc[0]+blenderobject->dloc[0], blenderobject->loc[1]+blenderobject->dloc[1], @@ -1809,35 +1782,6 @@ static void bl_ConvertBlenderObject_Single( MT_Vector3 scale(blenderobject->size); - if (converter->addInitFromFrame) {//rcruiz - blenderscene->r.cfra=blenderscene->r.sfra-1; - //XXX update_for_newframe(); - MT_Vector3 tmp=pos-MT_Point3(blenderobject->loc[0]+blenderobject->dloc[0], - blenderobject->loc[1]+blenderobject->dloc[1], - blenderobject->loc[2]+blenderobject->dloc[2] - ); - - float rotmatPrev[3][3]; - BKE_object_rot_to_mat3(blenderobject, rotmatPrev, false); - - float eulxyz[3], eulxyzPrev[3]; - mat3_to_eul(eulxyz, rotmat); - mat3_to_eul(eulxyzPrev, rotmatPrev); - - double fps = (double) blenderscene->r.frs_sec/ - (double) blenderscene->r.frs_sec_base; - - tmp.scale(fps, fps, fps); - inivel.push_back(tmp); - tmp[0]=eulxyz[0]-eulxyzPrev[0]; - tmp[1]=eulxyz[1]-eulxyzPrev[1]; - tmp[2]=eulxyz[2]-eulxyzPrev[2]; - tmp.scale(fps, fps, fps); - iniang.push_back(tmp); - blenderscene->r.cfra=blenderscene->r.sfra; - //XXX update_for_newframe(); - } - gameobj->NodeSetLocalPosition(pos); gameobj->NodeSetLocalOrientation(rotation); gameobj->NodeSetLocalScale(scale); @@ -1850,7 +1794,7 @@ static void bl_ConvertBlenderObject_Single( gameobj->SetName(blenderobject->id.name + 2); // update children/parent hierarchy - if ((blenderobject->parent != 0)&&(!converter->addInitFromFrame)) + if (blenderobject->parent != 0) { // blender has an additional 'parentinverse' offset in each object SG_Callbacks callback(NULL,NULL,NULL,KX_Scene::KX_ScenegraphUpdateFunc,KX_Scene::KX_ScenegraphRescheduleFunc); @@ -1909,10 +1853,6 @@ static void bl_ConvertBlenderObject_Single( logicbrick_conversionlist->Add(gameobj->AddRef()); - if (converter->addInitFromFrame) { - posPrev=gameobj->NodeGetWorldPosition(); - angor=gameobj->NodeGetWorldOrientation(); - } if (isInActiveLayer) { objectlist->Add(gameobj->AddRef()); @@ -1920,7 +1860,6 @@ static void bl_ConvertBlenderObject_Single( gameobj->NodeUpdateGS(0); gameobj->AddMeshUser(); - } else { @@ -1928,11 +1867,6 @@ static void bl_ConvertBlenderObject_Single( //at the end of this function if it is not a root object inactivelist->Add(gameobj->AddRef()); } - - if (converter->addInitFromFrame) { - gameobj->NodeSetLocalPosition(posPrev); - gameobj->NodeSetLocalOrientation(angor); - } } @@ -1951,8 +1885,7 @@ void BL_ConvertBlenderObjects(struct Main* maggie, #define BL_CONVERTBLENDEROBJECT_SINGLE \ bl_ConvertBlenderObject_Single(converter, \ - blenderscene, blenderobject, \ - inivel, iniang, \ + blenderobject, \ vec_parent_child, \ logicbrick_conversionlist, \ objectlist, inactivelist, sumolist, \ @@ -1974,7 +1907,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, RAS_FrameSettings::RAS_FrameType frame_type; int aspect_width; int aspect_height; - vector<MT_Vector3> inivel,iniang; set<Group*> grouplist; // list of groups to be converted set<Object*> allblobj; // all objects converted set<Object*> groupobj; // objects from groups (never in active layer) @@ -1983,6 +1915,12 @@ void BL_ConvertBlenderObjects(struct Main* maggie, // is not in a separate thread. BL_Texture::GetMaxUnits(); + /* We have to ensure that group definitions are only converted once + * push all converted group members to this set. + * This will happen when a group instance is made from a linked group instance + * and both are on the active layer. */ + set<KX_GameObject*> convertedlist; + if (alwaysUseExpandFraming) { frame_type = RAS_FrameSettings::e_frame_extend; aspect_width = canvas->GetWidth(); @@ -2046,6 +1984,9 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } SetDefaultLightMode(blenderscene); + + blenderSceneSetBackground(blenderscene); + // Let's support scene set. // Beware of name conflict in linked data, it will not crash but will create confusion // in Python scripting and in certain actuators (replace mesh). Linked scene *should* have @@ -2061,23 +2002,15 @@ void BL_ConvertBlenderObjects(struct Main* maggie, rendertools, converter, libloading); - - bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0; - bool addobj=true; - - if (converter->addInitFromFrame) - if (!isInActiveLayer) - addobj=false; + bool isInActiveLayer = (blenderobject->lay & activeLayerBitInfo) !=0; if (gameobj) { - if (addobj) - { /* macro calls object conversion funcs */ - BL_CONVERTBLENDEROBJECT_SINGLE; + /* macro calls object conversion funcs */ + BL_CONVERTBLENDEROBJECT_SINGLE; - if (gameobj->IsDupliGroup()) { - grouplist.insert(blenderobject->dup_group); - } + if (gameobj->IsDupliGroup()) { + grouplist.insert(blenderobject->dup_group); } /* Note about memory leak issues: @@ -2121,22 +2054,16 @@ void BL_ConvertBlenderObjects(struct Main* maggie, rendertools, converter, libloading); - - // this code is copied from above except that - // object from groups are never in active layer + bool isInActiveLayer = false; - bool addobj=true; - - if (converter->addInitFromFrame) - if (!isInActiveLayer) - addobj=false; - - if (gameobj) - { - if (addobj) - { /* macro calls object conversion funcs */ - BL_CONVERTBLENDEROBJECT_SINGLE; - } + if (gameobj) { + /* Insert object to the constraint game object list + * so we can check later if there is a instance in the scene or + * an instance and its actual group definition. */ + convertedlist.insert((KX_GameObject*)gameobj->AddRef()); + + /* macro calls object conversion funcs */ + BL_CONVERTBLENDEROBJECT_SINGLE; if (gameobj->IsDupliGroup()) { @@ -2146,7 +2073,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } } - /* see comment above re: mem leaks */ gameobj->Release(); } @@ -2260,8 +2186,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, case PARSKEL: // skinned - ignore break; case PAROBJECT: - case PARCURVE: - case PARKEY: case PARVERT3: default: // unhandled @@ -2338,7 +2262,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } bool processCompoundChildren = false; - // create physics information for (i=0;i<sumolist->GetCount();i++) { @@ -2369,131 +2292,64 @@ void BL_ConvertBlenderObjects(struct Main* maggie, int layerMask = (groupobj.find(blenderobject) == groupobj.end()) ? activeLayerBitInfo : 0; BL_CreatePhysicsObjectNew(gameobj,blenderobject,meshobj,kxscene,layerMask,converter,processCompoundChildren); } - - //set ini linearVel and int angularVel //rcruiz - if (converter->addInitFromFrame) - for (i=0;i<sumolist->GetCount();i++) - { - KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); - if (gameobj->IsDynamic()) { - gameobj->setLinearVelocity(inivel[i],false); - gameobj->setAngularVelocity(iniang[i],false); - } - - - } - // create physics joints + // create physics joints for (i=0;i<sumolist->GetCount();i++) { - KX_GameObject* gameobj = (KX_GameObject*) sumolist->GetValue(i); - struct Object* blenderobject = gameobj->GetBlenderObject(); - ListBase *conlist; + PHY_IPhysicsEnvironment *physEnv = kxscene->GetPhysicsEnvironment(); + KX_GameObject *gameobj = (KX_GameObject *)sumolist->GetValue(i); + struct Object *blenderobject = gameobj->GetBlenderObject(); + ListBase *conlist = get_active_constraints2(blenderobject); bConstraint *curcon; - conlist = get_active_constraints2(blenderobject); - if ((gameobj->GetLayer()&activeLayerBitInfo)==0) + if (!conlist) continue; - if (conlist) { - for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) { - if (curcon->type==CONSTRAINT_TYPE_RIGIDBODYJOINT) { + for (curcon = (bConstraint *)conlist->first; curcon; curcon = (bConstraint *)curcon->next) { + if (curcon->type != CONSTRAINT_TYPE_RIGIDBODYJOINT) + continue; - bRigidBodyJointConstraint *dat=(bRigidBodyJointConstraint *)curcon->data; + bRigidBodyJointConstraint *dat = (bRigidBodyJointConstraint *)curcon->data; + + /* Skip if no target or a child object is selected or constraints are deactivated */ + if (!dat->tar || dat->child || (curcon->flag & CONSTRAINT_OFF)) + continue; - if (!dat->child && !(curcon->flag & CONSTRAINT_OFF)) { + /* Store constraints of grouped and instanced objects for all layers */ + gameobj->AddConstraint(dat); - PHY_IPhysicsController* physctr2 = 0; + /** if it's during libload we only add constraints in the object but + * doesn't create it. Constraint will be replicated later in scene->MergeScene + */ + if (libloading) + continue; - if (dat->tar) - { - KX_GameObject *gotar=getGameOb(dat->tar->id.name+2,sumolist); - if (gotar && ((gotar->GetLayer()&activeLayerBitInfo)!=0) && gotar->GetPhysicsController()) - physctr2 = gotar->GetPhysicsController(); - } + /* Skipped already converted constraints. + * This will happen when a group instance is made from a linked group instance + * and both are on the active layer. */ + if (bl_isConstraintInList(gameobj, convertedlist)) + continue; - if (gameobj->GetPhysicsController()) - { - PHY_IPhysicsController* physctrl = gameobj->GetPhysicsController(); - //we need to pass a full constraint frame, not just axis - - //localConstraintFrameBasis - MT_Matrix3x3 localCFrame(MT_Vector3(dat->axX,dat->axY,dat->axZ)); - MT_Vector3 axis0 = localCFrame.getColumn(0); - MT_Vector3 axis1 = localCFrame.getColumn(1); - MT_Vector3 axis2 = localCFrame.getColumn(2); - - int constraintId = kxscene->GetPhysicsEnvironment()->CreateConstraint(physctrl,physctr2,(PHY_ConstraintType)dat->type,(float)dat->pivX, - (float)dat->pivY,(float)dat->pivZ, - (float)axis0.x(),(float)axis0.y(),(float)axis0.z(), - (float)axis1.x(),(float)axis1.y(),(float)axis1.z(), - (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),dat->flag); - if (constraintId) - { - //if it is a generic 6DOF constraint, set all the limits accordingly - if (dat->type == PHY_GENERIC_6DOF_CONSTRAINT) - { - int dof; - int dofbit=1; - for (dof=0;dof<6;dof++) - { - if (dat->flag & dofbit) - { - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,dat->minLimit[dof],dat->maxLimit[dof]); - } else - { - //minLimit > maxLimit means free(disabled limit) for this degree of freedom - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1); - } - dofbit<<=1; - } - } - else if (dat->type == PHY_CONE_TWIST_CONSTRAINT) - { - int dof; - int dofbit = 1<<3; // bitflag use_angular_limit_x - - for (dof=3;dof<6;dof++) - { - if (dat->flag & dofbit) - { - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,dat->minLimit[dof],dat->maxLimit[dof]); - } - else - { - //maxLimit < 0 means free(disabled limit) for this degree of freedom - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1); - } - dofbit<<=1; - } - } - else if (dat->type == PHY_LINEHINGE_CONSTRAINT) - { - int dof = 3; // dof for angular x - int dofbit = 1<<3; // bitflag use_angular_limit_x - - if (dat->flag & dofbit) - { - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof, - dat->minLimit[dof],dat->maxLimit[dof]); - } else - { - //minLimit > maxLimit means free(disabled limit) for this degree of freedom - kxscene->GetPhysicsEnvironment()->SetConstraintParam(constraintId,dof,1,-1); - } - } - } - } - } - } + KX_GameObject *gotar = getGameOb(dat->tar->id.name + 2, sumolist); + + if (gotar && (gotar->GetLayer()&activeLayerBitInfo) && gotar->GetPhysicsController() && + (gameobj->GetLayer()&activeLayerBitInfo) && gameobj->GetPhysicsController()) + { + physEnv->SetupObjectConstraints(gameobj, gotar, dat); } } } + /* cleanup converted set of group objects */ + set<KX_GameObject*>::iterator gobit; + for (gobit = convertedlist.begin(); gobit != convertedlist.end(); gobit++) + (*gobit)->Release(); + + convertedlist.clear(); sumolist->Release(); // convert world - KX_WorldInfo* worldinfo = new BlenderWorldInfo(blenderscene, blenderscene->world); + KX_WorldInfo* worldinfo = new KX_WorldInfo(blenderscene, blenderscene->world); converter->RegisterWorldInfo(worldinfo); kxscene->SetWorldInfo(worldinfo); @@ -2537,8 +2393,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, } } -#define CONVERT_LOGIC -#ifdef CONVERT_LOGIC // convert logic bricks, sensors, controllers and actuators for (i=0;i<logicbrick_conversionlist->GetCount();i++) { @@ -2573,8 +2427,6 @@ void BL_ConvertBlenderObjects(struct Main* maggie, gameobj->ResetState(); } -#endif //CONVERT_LOGIC - logicbrick_conversionlist->Release(); // Calculate the scene btree - @@ -2601,7 +2453,3 @@ void BL_ConvertBlenderObjects(struct Main* maggie, bucketmanager->OptimizeBuckets(distance); } -SCA_IInputDevice::KX_EnumInputs ConvertKeyCode(int key_code) -{ - return gReverseKeyTranslateTable[key_code]; -} diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.h b/source/gameengine/Converter/BL_BlenderDataConversion.h index 6bd77954b88..22210cc6035 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.h +++ b/source/gameengine/Converter/BL_BlenderDataConversion.h @@ -34,7 +34,7 @@ #include "CTR_HashedPtr.h" #include "STR_String.h" -#include "KX_Python.h" +#include "EXP_Python.h" #include "KX_PhysicsEngineEnums.h" #include "SCA_IInputDevice.h" diff --git a/source/gameengine/Converter/BL_ModifierDeformer.cpp b/source/gameengine/Converter/BL_ModifierDeformer.cpp index 71dc1bdec87..3bc07113ff6 100644 --- a/source/gameengine/Converter/BL_ModifierDeformer.cpp +++ b/source/gameengine/Converter/BL_ModifierDeformer.cpp @@ -186,6 +186,7 @@ bool BL_ModifierDeformer::Update(void) m_dm->release(m_dm); // HACK! use deformedOnly as a user counter m_dm->deformedOnly = 1; + DM_update_materials(m_dm, blendobj); /* update the graphic controller */ PHY_IGraphicController *ctrl = m_gameobj->GetGraphicController(); if (ctrl) { diff --git a/source/gameengine/Converter/BL_ShapeActionActuator.cpp b/source/gameengine/Converter/BL_ShapeActionActuator.cpp index 67712c683f9..e8f451213f5 100644 --- a/source/gameengine/Converter/BL_ShapeActionActuator.cpp +++ b/source/gameengine/Converter/BL_ShapeActionActuator.cpp @@ -48,8 +48,8 @@ #include "BLI_math.h" #include "MT_Matrix4x4.h" -#include "FloatValue.h" -#include "PyObjectPlus.h" +#include "EXP_FloatValue.h" +#include "EXP_PyObjectPlus.h" extern "C" { #include "BKE_animsys.h" diff --git a/source/gameengine/Converter/BL_SkinDeformer.cpp b/source/gameengine/Converter/BL_SkinDeformer.cpp index e7137a5c379..950c1dcad11 100644 --- a/source/gameengine/Converter/BL_SkinDeformer.cpp +++ b/source/gameengine/Converter/BL_SkinDeformer.cpp @@ -200,12 +200,14 @@ void BL_SkinDeformer::BGEDeformVerts() Object *par_arma = m_armobj->GetArmatureObject(); MDeformVert *dverts = m_bmesh->dvert; bDeformGroup *dg; - int defbase_tot = BLI_countlist(&m_objMesh->defbase); + int defbase_tot; Eigen::Matrix4f pre_mat, post_mat, chan_mat, norm_chan_mat; if (!dverts) return; + defbase_tot = BLI_listbase_count(&m_objMesh->defbase); + if (m_dfnrToPC == NULL) { m_dfnrToPC = new bPoseChannel*[defbase_tot]; diff --git a/source/gameengine/Converter/BlenderWorldInfo.cpp b/source/gameengine/Converter/BlenderWorldInfo.cpp deleted file mode 100644 index 75beb5d0e0e..00000000000 --- a/source/gameengine/Converter/BlenderWorldInfo.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can [0]istribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file gameengine/Converter/BlenderWorldInfo.cpp - * \ingroup bgeconv - */ - - -#include <stdio.h> // printf() - -#include "BlenderWorldInfo.h" - -/* This little block needed for linking to Blender... */ -#ifdef WIN32 -#include "BLI_winstuff.h" -#endif - -/* This list includes only data type definitions */ -#include "DNA_object_types.h" -#include "DNA_material_types.h" -#include "DNA_image_types.h" -#include "DNA_lamp_types.h" -#include "DNA_group_types.h" -#include "DNA_scene_types.h" -#include "DNA_camera_types.h" -#include "DNA_property_types.h" -#include "DNA_text_types.h" -#include "DNA_sensor_types.h" -#include "DNA_controller_types.h" -#include "DNA_actuator_types.h" -#include "DNA_mesh_types.h" -#include "DNA_meshdata_types.h" -#include "DNA_view3d_types.h" -#include "DNA_world_types.h" -#include "DNA_screen_types.h" - -#include "BLI_math.h" - -#include "BKE_global.h" -#include "BKE_scene.h" -/* end of blender include block */ - - -BlenderWorldInfo::BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld) -{ - if (blenderworld) { - m_hasworld = true; - - // do we have mist? - if ((blenderworld->mode) & WO_MIST) { - m_hasmist = true; - m_miststart = blenderworld->miststa; - m_mistdistance = blenderworld->mistdist; - copy_v3_v3(m_mistcolor, &blenderworld->horr); - } - else { - m_hasmist = false; - m_miststart = 0.0; - m_mistdistance = 0.0; - zero_v3(m_mistcolor); - } - - copy_v3_v3(m_backgroundcolor, &blenderworld->horr); - copy_v3_v3(m_ambientcolor, &blenderworld->ambr); - - if (BKE_scene_check_color_management_enabled(blenderscene)) { - linearrgb_to_srgb_v3_v3(m_mistcolor, m_mistcolor); - linearrgb_to_srgb_v3_v3(m_backgroundcolor, m_backgroundcolor); - linearrgb_to_srgb_v3_v3(m_ambientcolor, m_ambientcolor); - } - } - else { - m_hasworld = false; - } -} - -BlenderWorldInfo::~BlenderWorldInfo() -{ -} - -bool BlenderWorldInfo::hasWorld() -{ - return m_hasworld; -} - -bool BlenderWorldInfo::hasMist() -{ - return m_hasmist; -} - -float BlenderWorldInfo::getBackColorRed() -{ - return m_backgroundcolor[0]; -} - -float BlenderWorldInfo::getBackColorGreen() -{ - return m_backgroundcolor[1]; -} - -float BlenderWorldInfo::getBackColorBlue() -{ - return m_backgroundcolor[2]; -} - -float BlenderWorldInfo::getAmbientColorRed() -{ - return m_ambientcolor[0]; -} - -float BlenderWorldInfo::getAmbientColorGreen() -{ - return m_ambientcolor[1]; -} - -float BlenderWorldInfo::getAmbientColorBlue() -{ - return m_ambientcolor[2]; -} - -float BlenderWorldInfo::getMistStart() -{ - return m_miststart; -} - -float BlenderWorldInfo::getMistDistance() -{ - return m_mistdistance; -} - -float BlenderWorldInfo::getMistColorRed() -{ - return m_mistcolor[0]; -} - -float BlenderWorldInfo::getMistColorGreen() -{ - return m_mistcolor[1]; -} - -float BlenderWorldInfo::getMistColorBlue() -{ - return m_mistcolor[2]; -} - -void BlenderWorldInfo::setBackColor(float r, float g, float b) -{ - m_backgroundcolor[0] = r; - m_backgroundcolor[1] = g; - m_backgroundcolor[2] = b; -} - -void BlenderWorldInfo::setMistStart(float d) -{ - m_miststart = d; -} - -void BlenderWorldInfo::setMistDistance(float d) -{ - m_mistdistance = d; -} - -void BlenderWorldInfo::setMistColorRed(float d) -{ - m_mistcolor[0] = d; -} - -void BlenderWorldInfo::setMistColorGreen(float d) -{ - m_mistcolor[1] = d; -} - -void BlenderWorldInfo::setMistColorBlue(float d) -{ - m_mistcolor[2] = d; -} diff --git a/source/gameengine/Converter/BlenderWorldInfo.h b/source/gameengine/Converter/BlenderWorldInfo.h deleted file mode 100644 index 2ac2d70b5d1..00000000000 --- a/source/gameengine/Converter/BlenderWorldInfo.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file BlenderWorldInfo.h - * \ingroup bgeconv - */ - -#ifndef __BLENDERWORLDINFO_H__ -#define __BLENDERWORLDINFO_H__ -#include "MT_CmMatrix4x4.h" -#include "KX_WorldInfo.h" - -class BlenderWorldInfo : public KX_WorldInfo -{ - bool m_hasworld; - float m_backgroundcolor[3]; - - bool m_hasmist; - float m_miststart; - float m_mistdistance; - float m_mistcolor[3]; - - float m_ambientcolor[3]; - -public: - BlenderWorldInfo(struct Scene *blenderscene, struct World *blenderworld); - ~BlenderWorldInfo(); - - bool hasWorld(); - bool hasMist(); - float getBackColorRed(); - float getBackColorGreen(); - float getBackColorBlue(); - - float getAmbientColorRed(); - float getAmbientColorGreen(); - float getAmbientColorBlue(); - - float getMistStart(); - float getMistDistance(); - float getMistColorRed(); - float getMistColorGreen(); - float getMistColorBlue(); - - void setBackColor(float r, float g, float b); - void setMistStart(float d); - void setMistDistance(float d); - void setMistColorRed(float d); - void setMistColorGreen(float d); - void setMistColorBlue(float d); - - -#ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("GE:BlenderWorldInfo") -#endif -}; - -#endif /* __BLENDERWORLDINFO_H__ */ diff --git a/source/gameengine/Converter/CMakeLists.txt b/source/gameengine/Converter/CMakeLists.txt index 9c0d25e56ff..4db9fcebd06 100644 --- a/source/gameengine/Converter/CMakeLists.txt +++ b/source/gameengine/Converter/CMakeLists.txt @@ -56,7 +56,7 @@ set(INC set(INC_SYS ../../../intern/moto/include ../../../extern/recastnavigation/Detour/Include - ../../../extern/Eigen3 + ${EIGEN3_INCLUDE_DIRS} ${PTHREADS_INCLUDE_DIRS} ${BOOST_INCLUDE_DIR} ) @@ -74,7 +74,6 @@ set(SRC BL_ShapeActionActuator.cpp BL_ShapeDeformer.cpp BL_SkinDeformer.cpp - BlenderWorldInfo.cpp KX_BlenderScalarInterpolator.cpp KX_BlenderSceneConverter.cpp KX_ConvertActuators.cpp @@ -96,7 +95,6 @@ set(SRC BL_ShapeActionActuator.h BL_ShapeDeformer.h BL_SkinDeformer.h - BlenderWorldInfo.h KX_BlenderScalarInterpolator.h KX_BlenderSceneConverter.h KX_ConvertActuators.h @@ -115,10 +113,11 @@ if(WITH_BULLET) endif() if(WITH_AUDASPACE) - list(APPEND INC - ../../../intern/audaspace/intern + add_definitions(${AUDASPACE_DEFINITIONS}) + + list(APPEND INC_SYS + ${AUDASPACE_C_INCLUDE_DIRS} ) - add_definitions(-DWITH_AUDASPACE) endif() blender_add_lib(ge_converter "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index a20ebb3a081..9d01d3d5a39 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -58,7 +58,7 @@ #include "KX_LibLoadStatus.h" #include "KX_BlenderScalarInterpolator.h" #include "BL_BlenderDataConversion.h" -#include "BlenderWorldInfo.h" +#include "KX_WorldInfo.h" /* This little block needed for linking to Blender... */ #ifdef WIN32 @@ -69,6 +69,7 @@ #include "DNA_scene_types.h" #include "DNA_world_types.h" #include "BKE_main.h" +#include "BKE_fcurve.h" #include "BLI_math.h" @@ -87,6 +88,7 @@ extern "C" #include "BKE_mesh.h" // BKE_mesh_copy #include "DNA_space_types.h" #include "DNA_anim_types.h" +#include "DNA_action_types.h" #include "RNA_define.h" #include "../../blender/editors/include/ED_keyframing.h" } @@ -115,11 +117,9 @@ typedef struct ThreadInfo { } ThreadInfo; KX_BlenderSceneConverter::KX_BlenderSceneConverter( - struct Main* maggie, - class KX_KetsjiEngine* engine - ) - : m_maggie(maggie), - /*m_maggie_dyn(NULL),*/ + Main *maggie, + KX_KetsjiEngine *engine) + :m_maggie(maggie), m_ketsjiEngine(engine), m_alwaysUseExpandFraming(false), m_usemat(false), @@ -132,13 +132,11 @@ KX_BlenderSceneConverter::KX_BlenderSceneConverter( pthread_mutex_init(&m_threadinfo->merge_lock, NULL); } - KX_BlenderSceneConverter::~KX_BlenderSceneConverter() { // clears meshes, and hashmaps from blender to gameengine data - int i; // delete sumoshapes - + if (m_threadinfo) { vector<pthread_t>::iterator pit = m_threadinfo->threads.begin(); while (pit != m_threadinfo->threads.end()) { @@ -151,104 +149,83 @@ KX_BlenderSceneConverter::~KX_BlenderSceneConverter() } int numAdtLists = m_map_blender_to_gameAdtList.size(); - for (i=0; i<numAdtLists; i++) { - BL_InterpolatorList *adtList= *m_map_blender_to_gameAdtList.at(i); + for (int i = 0; i < numAdtLists; i++) { + BL_InterpolatorList *adtList = *m_map_blender_to_gameAdtList.at(i); delete (adtList); } - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itw = m_worldinfos.begin(); + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itw = m_worldinfos.begin(); while (itw != m_worldinfos.end()) { - delete (*itw).second; + delete itw->second; itw++; } m_worldinfos.clear(); - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin(); + vector<pair<KX_Scene *,RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin(); while (itp != m_polymaterials.end()) { - //m_polymat_cache.erase((*itp).second->GetBlenderMaterial()); - delete (*itp).second; + delete itp->second; itp++; } m_polymaterials.clear(); // delete after RAS_IPolyMaterial - vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin(); + vector<pair<KX_Scene *,BL_Material *> >::iterator itmat = m_materials.begin(); while (itmat != m_materials.end()) { - //m_mat_cache.erase((*itmat).second->material); - delete (*itmat).second; + delete itmat->second; itmat++; } m_materials.clear(); - - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin(); + vector<pair<KX_Scene *,RAS_MeshObject *> >::iterator itm = m_meshobjects.begin(); while (itm != m_meshobjects.end()) { - delete (*itm).second; + delete itm->second; itm++; } m_meshobjects.clear(); - /* free any data that was dynamically loaded */ - while (m_DynamicMaggie.size() != 0) - { + while (m_DynamicMaggie.size() != 0) { FreeBlendFile(m_DynamicMaggie[0]); } m_DynamicMaggie.clear(); } -void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename) +void KX_BlenderSceneConverter::SetNewFileName(const STR_String &filename) { m_newfilename = filename; } - - bool KX_BlenderSceneConverter::TryAndLoadNewFile() { bool result = false; - // find the file -/* if () - { - result = true; - } - // if not, clear the newfilename - else - { - m_newfilename = ""; - } -*/ return result; } -Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name) +Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String &name) { Scene *sce; /** * Find the specified scene by name, or NULL if nothing matches. */ - if ((sce= (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2))) + if ((sce = (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2))) return sce; - for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) { - Main *main= *it; + for (vector<Main *>::iterator it=m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { + Main *main = *it; if ((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2))) return sce; } return NULL; - } -void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, - class RAS_IRasterizer* rendertools, - class RAS_ICanvas* canvas, - bool libloading) +void KX_BlenderSceneConverter::ConvertScene(KX_Scene *destinationscene, RAS_IRasterizer *rendertools, + RAS_ICanvas *canvas, bool libloading) { //find out which physics engine Scene *blenderscene = destinationscene->GetBlenderScene(); @@ -264,13 +241,12 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, // when doing threaded conversion, so it's disabled for now. // SG_SetActiveStage(SG_STAGE_CONVERTER); - switch (blenderscene->gm.physicsEngine) - { + switch (blenderscene->gm.physicsEngine) { #ifdef WITH_BULLET case WOPHY_BULLET: { SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/ - int visualizePhysics = SYS_GetCommandLineInt(syshandle,"show_physics",0); + int visualizePhysics = SYS_GetCommandLineInt(syshandle, "show_physics", 0); phy_env = CcdPhysicsEnvironment::Create(blenderscene, visualizePhysics); physics_engine = UseBullet; @@ -289,7 +265,8 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, destinationscene->SetPhysicsEnvironment(phy_env); - BL_ConvertBlenderObjects(m_maggie, + BL_ConvertBlenderObjects( + m_maggie, destinationscene, m_ketsjiEngine, physics_engine, @@ -297,8 +274,7 @@ void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene, canvas, this, m_alwaysUseExpandFraming, - libloading - ); + libloading); //These lookup are not needed during game m_map_blender_to_gameactuator.clear(); @@ -324,30 +300,32 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) // delete the scene first as it will stop the use of entities delete scene; // delete the entities of this scene - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit; + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit; size = m_worldinfos.size(); - for (i=0, worldit=m_worldinfos.begin(); i<size; ) { - if ((*worldit).first == scene) { - delete (*worldit).second; + for (i = 0, worldit = m_worldinfos.begin(); i < size; ) { + if (worldit->first == scene) { + delete worldit->second; *worldit = m_worldinfos.back(); m_worldinfos.pop_back(); size--; - } else { + } + else { i++; worldit++; } } - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit; + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit; size = m_polymaterials.size(); - for (i=0, polymit=m_polymaterials.begin(); i<size; ) { - if ((*polymit).first == scene) { - m_polymat_cache[scene].erase((*polymit).second->GetBlenderMaterial()); - delete (*polymit).second; + for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { + if (polymit->first == scene) { + m_polymat_cache[scene].erase(polymit->second->GetBlenderMaterial()); + delete polymit->second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); size--; - } else { + } + else { i++; polymit++; } @@ -355,16 +333,17 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) m_polymat_cache.erase(scene); - vector<pair<KX_Scene*,BL_Material*> >::iterator matit; + vector<pair<KX_Scene *, BL_Material *> >::iterator matit; size = m_materials.size(); - for (i=0, matit=m_materials.begin(); i<size; ) { - if ((*matit).first == scene) { - m_mat_cache[scene].erase((*matit).second->material); - delete (*matit).second; + for (i = 0, matit = m_materials.begin(); i < size; ) { + if (matit->first == scene) { + m_mat_cache[scene].erase(matit->second->material); + delete matit->second; *matit = m_materials.back(); m_materials.pop_back(); size--; - } else { + } + else { i++; matit++; } @@ -372,15 +351,16 @@ void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene) m_mat_cache.erase(scene); - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit; + vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit; size = m_meshobjects.size(); - for (i=0, meshit=m_meshobjects.begin(); i<size; ) { - if ((*meshit).first == scene) { - delete (*meshit).second; + for (i = 0, meshit = m_meshobjects.begin(); i < size; ) { + if (meshit->first == scene) { + delete meshit->second; *meshit = m_meshobjects.back(); m_meshobjects.pop_back(); size--; - } else { + } + else { i++; meshit++; } @@ -423,43 +403,34 @@ bool KX_BlenderSceneConverter::GetCacheMaterials() void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat) { // First make sure we don't register the material twice - vector<pair<KX_Scene*,BL_Material*> >::iterator it; + vector<pair<KX_Scene *, BL_Material *> >::iterator it; for (it = m_materials.begin(); it != m_materials.end(); ++it) if (it->second == mat) return; - m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat)); + m_materials.push_back(pair<KX_Scene *, BL_Material *> (m_currentScene, mat)); } - - -void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming( - bool to_what) +void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(bool to_what) { m_alwaysUseExpandFraming= to_what; } - - -void KX_BlenderSceneConverter::RegisterGameObject( - KX_GameObject *gameobject, - struct Object *for_blenderobject) +void KX_BlenderSceneConverter::RegisterGameObject(KX_GameObject *gameobject, Object *for_blenderobject) { /* only maintained while converting, freed during game runtime */ - m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject); + m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject), gameobject); } /* only need to run this during conversion since * m_map_blender_to_gameobject is freed after conversion */ -void KX_BlenderSceneConverter::UnregisterGameObject( - KX_GameObject *gameobject) +void KX_BlenderSceneConverter::UnregisterGameObject(KX_GameObject *gameobject) { - struct Object *bobp= gameobject->GetBlenderObject(); + Object *bobp = gameobject->GetBlenderObject(); if (bobp) { CHashedPtr bptr(bobp); - KX_GameObject **gobp= m_map_blender_to_gameobject[bptr]; - if (gobp && *gobp == gameobject) - { + KX_GameObject **gobp = m_map_blender_to_gameobject[bptr]; + if (gobp && *gobp == gameobject) { // also maintain m_map_blender_to_gameobject if the gameobject // being removed is matching the blender object m_map_blender_to_gameobject.remove(bptr); @@ -467,47 +438,41 @@ void KX_BlenderSceneConverter::UnregisterGameObject( } } -KX_GameObject *KX_BlenderSceneConverter::FindGameObject( - struct Object *for_blenderobject) +KX_GameObject *KX_BlenderSceneConverter::FindGameObject(Object *for_blenderobject) { - KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)]; - - return obp?*obp:NULL; + KX_GameObject **obp = m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)]; + + return obp ? *obp : NULL; } -void KX_BlenderSceneConverter::RegisterGameMesh( - RAS_MeshObject *gamemesh, - struct Mesh *for_blendermesh) +void KX_BlenderSceneConverter::RegisterGameMesh(RAS_MeshObject *gamemesh, Mesh *for_blendermesh) { if (for_blendermesh) { /* dynamically loaded meshes we don't want to keep lookups for */ m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh); } - m_meshobjects.push_back(pair<KX_Scene*,RAS_MeshObject*>(m_currentScene,gamemesh)); + m_meshobjects.push_back(pair<KX_Scene *, RAS_MeshObject *> (m_currentScene,gamemesh)); } - - -RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh( - struct Mesh *for_blendermesh/*, - unsigned int onlayer*/) +RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(Mesh *for_blendermesh) { - RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)]; - - if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) { + RAS_MeshObject **meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)]; + + if (meshp) { return *meshp; - } else { + } + else { return NULL; } -} +} void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat) { // First make sure we don't register the material twice - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator it; + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator it; for (it = m_polymaterials.begin(); it != m_polymaterials.end(); ++it) if (it->second == polymat) return; - m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat)); + m_polymaterials.push_back(pair<KX_Scene *, RAS_IPolyMaterial *> (m_currentScene, polymat)); } void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, RAS_IPolyMaterial *polymat) @@ -516,128 +481,99 @@ void KX_BlenderSceneConverter::CachePolyMaterial(KX_Scene *scene, Material *mat, m_polymat_cache[scene][mat] = polymat; } -RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, struct Material *mat) +RAS_IPolyMaterial *KX_BlenderSceneConverter::FindCachedPolyMaterial(KX_Scene *scene, Material *mat) { return (m_use_mat_cache) ? m_polymat_cache[scene][mat] : NULL; } -void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, struct Material *mat, BL_Material *blmat) +void KX_BlenderSceneConverter::CacheBlenderMaterial(KX_Scene *scene, Material *mat, BL_Material *blmat) { if (m_use_mat_cache && mat) m_mat_cache[scene][mat] = blmat; } -BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, struct Material *mat) +BL_Material *KX_BlenderSceneConverter::FindCachedBlenderMaterial(KX_Scene *scene, Material *mat) { return (m_use_mat_cache) ? m_mat_cache[scene][mat] : NULL; } -void KX_BlenderSceneConverter::RegisterInterpolatorList( - BL_InterpolatorList *actList, - struct bAction *for_act) +void KX_BlenderSceneConverter::RegisterInterpolatorList(BL_InterpolatorList *actList, bAction *for_act) { m_map_blender_to_gameAdtList.insert(CHashedPtr(for_act), actList); } - - -BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList( - struct bAction *for_act) +BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(bAction *for_act) { BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_act)]; - - return listp?*listp:NULL; + return listp ? *listp : NULL; } - - -void KX_BlenderSceneConverter::RegisterGameActuator( - SCA_IActuator *act, - struct bActuator *for_actuator) +void KX_BlenderSceneConverter::RegisterGameActuator(SCA_IActuator *act, bActuator *for_actuator) { m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act); } - - -SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator( - struct bActuator *for_actuator) +SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(bActuator *for_actuator) { SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)]; - - return actp?*actp:NULL; + return actp ? *actp : NULL; } - - -void KX_BlenderSceneConverter::RegisterGameController( - SCA_IController *cont, - struct bController *for_controller) +void KX_BlenderSceneConverter::RegisterGameController(SCA_IController *cont, bController *for_controller) { m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont); } - - -SCA_IController *KX_BlenderSceneConverter::FindGameController( - struct bController *for_controller) +SCA_IController *KX_BlenderSceneConverter::FindGameController(bController *for_controller) { SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)]; - - return contp?*contp:NULL; + return contp ? *contp : NULL; } - - -void KX_BlenderSceneConverter::RegisterWorldInfo( - KX_WorldInfo *worldinfo) +void KX_BlenderSceneConverter::RegisterWorldInfo(KX_WorldInfo *worldinfo) { - m_worldinfos.push_back(pair<KX_Scene*,KX_WorldInfo*>(m_currentScene,worldinfo)); + m_worldinfos.push_back(pair<KX_Scene *, KX_WorldInfo *> (m_currentScene, worldinfo)); } -void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) +void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) { + //TODO this entire function is deprecated, written for 2.4x + //the functionality should be rewritten, currently it does nothing - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;i<numScenes;i++) - { - KX_Scene* scene = scenes->at(i); - //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetRootParentList(); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); + CListValue *parentList = scene->GetRootParentList(); int numObjects = parentList->GetCount(); int g; - for (g=0;g<numObjects;g++) - { - KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); if (gameObj->IsRecordAnimation()) { - - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject) - { + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject) { #if 0 //erase existing ipo's Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2); - if (ipo) - { //clear the curve data + if (ipo) { //clear the curve data if (clearIpo) {//rcruiz IpoCurve *icu1; - + int numCurves = 0; for ( icu1 = (IpoCurve*)ipo->curve.first; icu1; ) { - + IpoCurve* tmpicu = icu1; - + /*int i; BezTriple *bezt; for ( bezt = tmpicu->bezt, i = 0; i < tmpicu->totvert; i++, bezt++) { printf("(%f,%f,%f),(%f,%f,%f),(%f,%f,%f)\n",bezt->vec[0][0],bezt->vec[0][1],bezt->vec[0][2],bezt->vec[1][0],bezt->vec[1][1],bezt->vec[1][2],bezt->vec[2][0],bezt->vec[2][1],bezt->vec[2][2]); }*/ - + icu1 = icu1->next; numCurves++; - + BLI_remlink( &( blenderObject->ipo->curve ), tmpicu ); if ( tmpicu->bezt ) MEM_freeN( tmpicu->bezt ); @@ -645,102 +581,52 @@ void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo) localDel_ipoCurve( tmpicu ); } } - } else - { ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB); + } + else { + ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB); blenderObject->ipo = ipo; - } #endif } } - } - - } - - - } -void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() +void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo() { - if (addInitFromFrame) { - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); - int numScenes = scenes->size(); - if (numScenes>=0) { - KX_Scene* scene = scenes->at(0); - CListValue* parentList = scene->GetRootParentList(); - for (int ix=0;ix<parentList->GetCount();ix++) { - KX_GameObject* gameobj = (KX_GameObject*)parentList->GetValue(ix); - if (!gameobj->IsRecordAnimation()) { - Object* blenderobject = gameobj->GetBlenderObject(); - if (!blenderobject) - continue; - if (blenderobject->type==OB_ARMATURE) - continue; - float eu[3]; - mat4_to_eul(eu,blenderobject->obmat); - MT_Point3 pos = MT_Point3( - blenderobject->obmat[3][0], - blenderobject->obmat[3][1], - blenderobject->obmat[3][2] - ); - MT_Vector3 eulxyz = MT_Vector3( - eu[0], - eu[1], - eu[2] - ); - MT_Vector3 scale = MT_Vector3( - blenderobject->size[0], - blenderobject->size[1], - blenderobject->size[2] - ); - gameobj->NodeSetLocalPosition(pos); - gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz)); - gameobj->NodeSetLocalScale(scale); - gameobj->NodeUpdateGS(0); - } - } - } - } + //TODO the functionality should be rewritten } - - ///this generates ipo curves for position, rotation, allowing to use game physics in animation -void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) +// this generates ipo curves for position, rotation, allowing to use game physics in animation +void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) { - - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;i<numScenes;i++) - { - KX_Scene* scene = scenes->at(i); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetObjectList(); + CListValue *parentList = scene->GetObjectList(); int numObjects = parentList->GetCount(); int g; - for (g=0;g<numObjects;g++) - { - KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject && blenderObject->parent==NULL && gameObj->IsRecordAnimation()) { - - if (blenderObject->adt==NULL) - BKE_id_add_animdata(&blenderObject->id); - - if (blenderObject->adt) - { - const MT_Point3& position = gameObj->NodeGetWorldPosition(); + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject && blenderObject->parent == NULL && gameObj->IsRecordAnimation()) { + if (blenderObject->adt == NULL) + BKE_animdata_add_id(&blenderObject->id); + + if (blenderObject->adt) { + const MT_Point3 &position = gameObj->NodeGetWorldPosition(); //const MT_Vector3& scale = gameObj->NodeGetWorldScaling(); - const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation(); + const MT_Matrix3x3 &orn = gameObj->NodeGetWorldOrientation(); position.getValue(blenderObject->loc); float tmat[3][3]; - for (int r=0;r<3;r++) - for (int c=0;c<3;c++) + for (int r = 0; r < 3; r++) + for (int c = 0; c < 3; c++) tmat[r][c] = (float)orn[c][r]; mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat); @@ -825,31 +711,39 @@ void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber) } } - -void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() +void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() { - - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); int i; - for (i=0;i<numScenes;i++) - { - KX_Scene* scene = scenes->at(i); + for (i = 0; i < numScenes; i++) { + KX_Scene *scene = scenes->at(i); //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment(); - CListValue* parentList = scene->GetRootParentList(); + CListValue *parentList = scene->GetRootParentList(); int numObjects = parentList->GetCount(); int g; - for (g=0;g<numObjects;g++) - { - KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g); + for (g = 0; g < numObjects; g++) { + KX_GameObject *gameObj = (KX_GameObject *)parentList->GetValue(g); if (gameObj->IsRecordAnimation()) { + Object *blenderObject = gameObj->GetBlenderObject(); + if (blenderObject && blenderObject->adt) { + bAction *act = verify_adt_action(&blenderObject->id, false); + FCurve *fcu; + + if (!act) { + continue; + } + + /* for now, not much choice but to run this on all curves... */ + for (fcu = (FCurve *)act->curves.first; fcu; fcu = fcu->next) { + /* Note: calling `sort_time_fcurve()` here is not needed, since + * all keys have been added in 'right' order. */ + calchandles_fcurve(fcu); + } #if 0 - Object* blenderObject = gameObj->GetBlenderObject(); - if (blenderObject && blenderObject->ipo) - { // XXX animato Ipo* ipo = blenderObject->ipo; - + //create the curves, if not existing //testhandles_ipocurve checks for NULL testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocX")); @@ -858,8 +752,8 @@ void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo() 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 + } } } } @@ -872,14 +766,14 @@ PyObject *KX_BlenderSceneConverter::GetPyNamespace() } #endif -vector<Main*> &KX_BlenderSceneConverter::GetMainDynamic() +vector<Main *> &KX_BlenderSceneConverter::GetMainDynamic() { return m_DynamicMaggie; } -Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) +Main *KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) { - for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) + for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) if (BLI_path_cmp((*it)->name, path) == 0) return *it; @@ -888,22 +782,21 @@ Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path) void KX_BlenderSceneConverter::MergeAsyncLoads() { - vector<KX_Scene*> *merge_scenes; + vector<KX_Scene *> *merge_scenes; - vector<KX_LibLoadStatus*>::iterator mit; - vector<KX_Scene*>::iterator sit; + vector<KX_LibLoadStatus *>::iterator mit; + vector<KX_Scene *>::iterator sit; pthread_mutex_lock(&m_threadinfo->merge_lock); - for (mit=m_mergequeue.begin(); mit!=m_mergequeue.end(); ++mit) { - merge_scenes = (vector<KX_Scene*>*)(*mit)->GetData(); + for (mit = m_mergequeue.begin(); mit != m_mergequeue.end(); ++mit) { + merge_scenes = (vector<KX_Scene *> *)(*mit)->GetData(); for (sit=merge_scenes->begin(); sit!=merge_scenes->end(); ++sit) { (*mit)->GetMergeScene()->MergeScene(*sit); delete (*sit); } - delete merge_scenes; (*mit)->SetData(NULL); @@ -925,17 +818,17 @@ void KX_BlenderSceneConverter::AddScenesToMergeQueue(KX_LibLoadStatus *status) static void *async_convert(void *ptr) { KX_Scene *new_scene = NULL; - KX_LibLoadStatus *status = (KX_LibLoadStatus*)ptr; - vector<Scene*> *scenes = (vector<Scene*>*)status->GetData(); - vector<KX_Scene*> *merge_scenes = new vector<KX_Scene*>(); // Deleted in MergeAsyncLoads + KX_LibLoadStatus *status = (KX_LibLoadStatus *)ptr; + vector<Scene *> *scenes = (vector<Scene *> *)status->GetData(); + vector<KX_Scene *> *merge_scenes = new vector<KX_Scene *>(); // Deleted in MergeAsyncLoads - for (unsigned int i=0; i<scenes->size(); ++i) { + for (unsigned int i = 0; i < scenes->size(); ++i) { new_scene = status->GetEngine()->CreateScene((*scenes)[i], true); if (new_scene) merge_scenes->push_back(new_scene); - status->AddProgress((1.f/scenes->size())*0.9f); // We'll call conversion 90% and merging 10% for now + status->AddProgress((1.0f / scenes->size()) * 0.9f); // We'll call conversion 90% and merging 10% for now } delete scenes; @@ -962,28 +855,21 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFilePath(const char *filepa return LinkBlendFile(bpy_openlib, filepath, group, scene_merge, err_str, options); } -static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const char *path, int idcode) +static void load_datablocks(Main *main_tmp, BlendHandle *bpy_openlib, const char *path, int idcode) { - Main *main_tmp= NULL; /* created only for linking, then freed */ LinkNode *names = NULL; - short flag= 0; /* don't need any special options */ - - /* here appending/linking starts */ - main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); int totnames_dummy; - names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode, &totnames_dummy); + names = BLO_blendhandle_get_datablock_names(bpy_openlib, idcode, &totnames_dummy); - int i=0; - LinkNode *n= names; + int i = 0; + LinkNode *n = names; while (n) { BLO_library_append_named_part(main_tmp, &bpy_openlib, (char *)n->link, idcode); - n= (LinkNode *)n->next; + n = (LinkNode *)n->next; i++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ - - BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); } KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) @@ -996,42 +882,48 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl // TIMEIT_START(bge_link_blend_file); KX_LibLoadStatus *status; - + /* only scene and mesh supported right now */ - if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) { + if (idcode != ID_SCE && idcode != ID_ME && idcode != ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); - *err_str= err_local; + *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } if (GetMainDynamicPath(path)) { snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path); - *err_str= err_local; + *err_str = err_local; BLO_blendhandle_close(bpy_openlib); return NULL; } - if (bpy_openlib==NULL) { + if (bpy_openlib == NULL) { snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path); - *err_str= err_local; + *err_str = err_local; return NULL; } - + main_newlib = BKE_main_new(); BKE_reports_init(&reports, RPT_STORE); - load_datablocks(main_newlib, bpy_openlib, path, idcode); + short flag = 0; /* don't need any special options */ + /* created only for linking, then freed */ + Main *main_tmp = BLO_library_append_begin(main_newlib, &bpy_openlib, (char *)path); - if (idcode==ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { - load_datablocks(main_newlib, bpy_openlib, path, ID_TXT); + load_datablocks(main_tmp, bpy_openlib, path, idcode); + + if (idcode == ID_SCE && options & LIB_LOAD_LOAD_SCRIPTS) { + load_datablocks(main_tmp, bpy_openlib, path, ID_TXT); } /* now do another round of linking for Scenes so all actions are properly loaded */ - if (idcode==ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { - load_datablocks(main_newlib, bpy_openlib, path, ID_AC); + if (idcode == ID_SCE && options & LIB_LOAD_LOAD_ACTIONS) { + load_datablocks(main_tmp, bpy_openlib, path, ID_AC); } - + + BLO_library_append_end(NULL, main_tmp, &bpy_openlib, idcode, flag); + BLO_blendhandle_close(bpy_openlib); BKE_reports_clear(&reports); @@ -1044,42 +936,43 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl status = new KX_LibLoadStatus(this, m_ketsjiEngine, scene_merge, path); - if (idcode==ID_ME) { + if (idcode == ID_ME) { /* Convert all new meshes into BGE meshes */ - ID* mesh; + ID *mesh; - for (mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) { + for (mesh = (ID *)main_newlib->mesh.first; mesh; mesh = (ID *)mesh->next ) { if (options & LIB_LOAD_VERBOSE) - printf("MeshName: %s\n", mesh->name+2); + printf("MeshName: %s\n", mesh->name + 2); RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this, false); // For now only use the libloading option for scenes, which need to handle materials/shaders - scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj); + scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj); } } - else if (idcode==ID_AC) { + else if (idcode == ID_AC) { /* Convert all actions */ ID *action; - for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { + for (action= (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) - printf("ActionName: %s\n", action->name+2); - scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); + printf("ActionName: %s\n", action->name + 2); + scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } - else if (idcode==ID_SCE) { + else if (idcode == ID_SCE) { /* Merge all new linked in scene into the existing one */ ID *scene; // scenes gets deleted by the thread when it's done using it (look in async_convert()) - vector<Scene*> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene*>() : NULL; + vector<Scene *> *scenes = (options & LIB_LOAD_ASYNC) ? new vector<Scene *>() : NULL; - for (scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) { + for (scene = (ID *)main_newlib->scene.first; scene; scene = (ID *)scene->next ) { if (options & LIB_LOAD_VERBOSE) - printf("SceneName: %s\n", scene->name+2); + printf("SceneName: %s\n", scene->name + 2); if (options & LIB_LOAD_ASYNC) { - scenes->push_back((Scene*)scene); - } else { + scenes->push_back((Scene *)scene); + } + else { /* merge into the base scene */ - KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene, true); + KX_Scene* other = m_ketsjiEngine->CreateScene((Scene *)scene, true); scene_merge->MergeScene(other); // RemoveScene(other); // Don't run this, it frees the entire scene converter data, just delete the scene @@ -1090,7 +983,7 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl if (options & LIB_LOAD_ASYNC) { pthread_t id; status->SetData(scenes); - pthread_create(&id, NULL, &async_convert, (void*)status); + pthread_create(&id, NULL, &async_convert, (void *)status); m_threadinfo->threads.push_back(id); } @@ -1104,17 +997,16 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl if (options & LIB_LOAD_LOAD_ACTIONS) { ID *action; - for (action= (ID *)main_newlib->action.first; action; action= (ID *)action->next) { + for (action = (ID *)main_newlib->action.first; action; action = (ID *)action->next) { if (options & LIB_LOAD_VERBOSE) - printf("ActionName: %s\n", action->name+2); - scene_merge->GetLogicManager()->RegisterActionName(action->name+2, action); + printf("ActionName: %s\n", action->name + 2); + scene_merge->GetLogicManager()->RegisterActionName(action->name + 2, action); } } } if (!(options & LIB_LOAD_ASYNC)) status->Finish(); - // TIMEIT_END(bge_link_blend_file); @@ -1124,22 +1016,22 @@ KX_LibLoadStatus *KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openl /* Note m_map_*** are all ok and don't need to be freed * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */ -bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) +bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie) { - int maggie_index= -1; - int i=0; + int maggie_index = -1; + int i = 0; - if (maggie==NULL) + if (maggie == NULL) return false; /* tag all false except the one we remove */ - for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) { - Main *main= *it; + for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { + Main *main = *it; if (main != maggie) { BKE_main_id_tag_all(main, false); } else { - maggie_index= i; + maggie_index = i; } i++; } @@ -1151,15 +1043,12 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index); BKE_main_id_tag_all(maggie, true); - /* free all tagged objects */ - KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes(); + KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); - - for (int scene_idx=0;scene_idx<numScenes;scene_idx++) - { - KX_Scene* scene = scenes->at(scene_idx); + for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { + KX_Scene *scene = scenes->at(scene_idx); if (IS_TAGGED(scene->GetBlenderScene())) { m_ketsjiEngine->RemoveScene(scene->GetName()); m_mat_cache.erase(scene); @@ -1168,16 +1057,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) numScenes--; } else { - /* in case the mesh might be refered to later */ { - CTR_Map<STR_HashedString,void*> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap(); + CTR_Map<STR_HashedString, void *> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap(); - for (int i=0; i<mapStringToMeshes.size(); i++) - { - RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i); - if (meshobj && IS_TAGGED(meshobj->GetMesh())) - { + for (int i = 0; i < mapStringToMeshes.size(); i++) { + RAS_MeshObject *meshobj = (RAS_MeshObject *) *mapStringToMeshes.at(i); + if (meshobj && IS_TAGGED(meshobj->GetMesh())) { STR_HashedString mn = meshobj->GetName(); mapStringToMeshes.remove(mn); m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh())); @@ -1188,16 +1074,15 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) /* Now unregister actions */ { - CTR_Map<STR_HashedString,void*> &mapStringToActions = scene->GetLogicManager()->GetActionMap(); + CTR_Map<STR_HashedString, void *> &mapStringToActions = scene->GetLogicManager()->GetActionMap(); - for (int i=0; i<mapStringToActions.size(); i++) - { - ID *action= (ID*) *mapStringToActions.at(i); + for (int i = 0; i < mapStringToActions.size(); i++) { + ID *action = (ID*) *mapStringToActions.at(i); - if (IS_TAGGED(action)) - { - STR_HashedString an = action->name+2; + if (IS_TAGGED(action)) { + STR_HashedString an = action->name + 2; mapStringToActions.remove(an); + m_map_blender_to_gameAdtList.remove(CHashedPtr(action)); i--; } } @@ -1206,16 +1091,13 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) //scene->FreeTagged(); /* removed tagged objects and meshes*/ CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL}; - for (int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++) - { - CListValue *obs= obj_lists[ob_ls_idx]; - RAS_MeshObject* mesh; + for (int ob_ls_idx = 0; obj_lists[ob_ls_idx]; ob_ls_idx++) { + CListValue *obs = obj_lists[ob_ls_idx]; + RAS_MeshObject *mesh; - for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) - { - KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx); + for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) { + KX_GameObject *gameobj = (KX_GameObject*)obs->GetValue(ob_idx); if (IS_TAGGED(gameobj->GetBlenderObject())) { - int size_before = obs->GetCount(); /* Eventually calls RemoveNodeDestructObject @@ -1229,10 +1111,11 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } } else { + gameobj->RemoveTaggedActions(); /* free the mesh, we could be referecing a linked one! */ - int mesh_index= gameobj->GetMeshCount(); + int mesh_index = gameobj->GetMeshCount(); while (mesh_index--) { - mesh= gameobj->GetMesh(mesh_index); + mesh = gameobj->GetMesh(mesh_index); if (IS_TAGGED(mesh->GetMesh())) { gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */ break; @@ -1250,11 +1133,9 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } /* make sure action actuators are not referencing tagged actions */ - for (unsigned int act_idx=0; act_idx<gameobj->GetActuators().size(); act_idx++) - { - if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) - { - BL_ActionActuator *act = (BL_ActionActuator*)gameobj->GetActuators()[act_idx]; + for (unsigned int act_idx = 0; act_idx < gameobj->GetActuators().size(); act_idx++) { + if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) { + BL_ActionActuator *act = (BL_ActionActuator *)gameobj->GetActuators()[act_idx]; if (IS_TAGGED(act->GetAction())) act->SetAction(NULL); } @@ -1265,7 +1146,6 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } } - int size; // delete the entities of this scene @@ -1288,24 +1168,24 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) /* Worlds don't reference original blender data so we need to make a set from them */ - typedef std::set<KX_WorldInfo*> KX_WorldInfoSet; + typedef std::set<KX_WorldInfo *> KX_WorldInfoSet; KX_WorldInfoSet worldset; - for (int scene_idx=0;scene_idx<numScenes;scene_idx++) - { - KX_Scene* scene = scenes->at(scene_idx); + for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { + KX_Scene *scene = scenes->at(scene_idx); if (scene->GetWorldInfo()) - worldset.insert( scene->GetWorldInfo() ); + worldset.insert(scene->GetWorldInfo()); } - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit; + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit; size = m_worldinfos.size(); - for (i=0, worldit=m_worldinfos.begin(); i<size; ) { - if ((*worldit).second && (worldset.count((*worldit).second)) == 0) { - delete (*worldit).second; + for (i = 0, worldit = m_worldinfos.begin(); i < size;) { + if (worldit->second && (worldset.count(worldit->second)) == 0) { + delete worldit->second; *worldit = m_worldinfos.back(); m_worldinfos.pop_back(); size--; - } else { + } + else { i++; worldit++; } @@ -1313,87 +1193,76 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) worldset.clear(); /* done freeing the worlds */ - - - - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit; + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit; size = m_polymaterials.size(); + for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { + RAS_IPolyMaterial *mat = polymit->second; + Material *bmat = NULL; - - for (i=0, polymit=m_polymaterials.begin(); i<size; ) { - RAS_IPolyMaterial *mat= (*polymit).second; - Material *bmat= NULL; - - KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat); - bmat= bl_mat->GetBlenderMaterial(); + KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial *>(mat); + bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { /* only remove from bucket */ - ((*polymit).first)->GetBucketManager()->RemoveMaterial(mat); + polymit->first->GetBucketManager()->RemoveMaterial(mat); } i++; polymit++; } - - - for (i=0, polymit=m_polymaterials.begin(); i<size; ) { - RAS_IPolyMaterial *mat= (*polymit).second; - Material *bmat= NULL; + for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { + RAS_IPolyMaterial *mat = polymit->second; + Material *bmat = NULL; KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat); - bmat= bl_mat->GetBlenderMaterial(); - - if (bmat) { - //printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2); - } - else { - //printf("LOST MAT !!!"); - } + bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { - delete (*polymit).second; + // Remove the poly material coresponding to this Blender Material. + m_polymat_cache[polymit->first].erase(bmat); + delete polymit->second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); size--; - //printf("tagged !\n"); } else { i++; polymit++; - //printf("(un)tagged !\n"); } } - vector<pair<KX_Scene*,BL_Material*> >::iterator matit; + vector<pair<KX_Scene *, BL_Material *> >::iterator matit; size = m_materials.size(); - for (i=0, matit=m_materials.begin(); i<size; ) { - BL_Material *mat= (*matit).second; + for (i = 0, matit = m_materials.begin(); i < size; ) { + BL_Material *mat = matit->second; if (IS_TAGGED(mat->material)) { - delete (*matit).second; + // Remove the bl material coresponding to this Blender Material. + m_mat_cache[matit->first].erase(mat->material); + delete matit->second; *matit = m_materials.back(); m_materials.pop_back(); size--; - } else { + } + else { i++; matit++; } } - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit; + vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit; RAS_BucketManager::BucketList::iterator bit; list<RAS_MeshSlot>::iterator msit; RAS_BucketManager::BucketList buckets; size = m_meshobjects.size(); - for (i=0, meshit=m_meshobjects.begin(); i<size; ) { - RAS_MeshObject *me= (*meshit).second; + for (i = 0, meshit = m_meshobjects.begin(); i < size;) { + RAS_MeshObject *me = meshit->second; if (IS_TAGGED(me->GetMesh())) { // Before deleting the mesh object, make sure the rasterizer is // no longer referencing it. buckets = meshit->first->GetBucketManager()->GetSolidBuckets(); - for (bit=buckets.begin(); bit!=buckets.end(); bit++) { + for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { @@ -1406,7 +1275,7 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) // And now the alpha buckets buckets = meshit->first->GetBucketManager()->GetAlphaBuckets(); - for (bit=buckets.begin(); bit!=buckets.end(); bit++) { + for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { @@ -1418,11 +1287,12 @@ bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie) } // Now it should be safe to delete - delete (*meshit).second; + delete meshit->second; *meshit = m_meshobjects.back(); m_meshobjects.pop_back(); size--; - } else { + } + else { i++; meshit++; } @@ -1449,24 +1319,23 @@ bool KX_BlenderSceneConverter::FreeBlendFile(const char *path) bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from) { - { - vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itp = m_worldinfos.begin(); + vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator itp = m_worldinfos.begin(); while (itp != m_worldinfos.end()) { - if ((*itp).first==from) - (*itp).first= to; + if (itp->first == from) + itp->first = to; itp++; } } { - vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin(); + vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator itp = m_polymaterials.begin(); while (itp != m_polymaterials.end()) { - if ((*itp).first==from) { - (*itp).first= to; + if (itp->first == from) { + itp->first = to; /* also switch internal data */ - RAS_IPolyMaterial*mat= (*itp).second; + RAS_IPolyMaterial *mat = itp->second; mat->Replace_IScene(to); } itp++; @@ -1474,29 +1343,43 @@ bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from) } { - vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itp = m_meshobjects.begin(); + vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator itp = m_meshobjects.begin(); while (itp != m_meshobjects.end()) { - if ((*itp).first==from) - (*itp).first= to; + if (itp->first == from) + itp->first = to; itp++; } } { - vector<pair<KX_Scene*,BL_Material*> >::iterator itp = m_materials.begin(); + vector<pair<KX_Scene *, BL_Material *> >::iterator itp = m_materials.begin(); while (itp != m_materials.end()) { - if ((*itp).first==from) - (*itp).first= to; + if (itp->first == from) + itp->first = to; itp++; } } - + + MaterialCache::iterator matcacheit = m_mat_cache.find(from); + if (matcacheit != m_mat_cache.end()) { + // Merge cached BL_Material map. + m_mat_cache[to].insert(matcacheit->second.begin(), matcacheit->second.end()); + m_mat_cache.erase(matcacheit); + } + + PolyMaterialCache::iterator polymatcacheit = m_polymat_cache.find(from); + if (polymatcacheit != m_polymat_cache.end()) { + // Merge cached RAS_IPolyMaterial map. + m_polymat_cache[to].insert(polymatcacheit->second.begin(), polymatcacheit->second.end()); + m_polymat_cache.erase(polymatcacheit); + } + return true; } /* This function merges a mesh from the current scene into another main * it does not convert */ -RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name) +RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, const char *name) { /* Find a mesh in the current main */ ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2)); @@ -1504,7 +1387,7 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, if (me == NULL) { // The mesh wasn't in the current main, try any dynamic (i.e., LibLoaded) ones - vector<Main*>::iterator it; + vector<Main *>::iterator it; for (it = GetMainDynamic().begin(); it != GetMainDynamic().end(); it++) { me = static_cast<ID *>(BLI_findstring(&(*it)->mesh, name, offsetof(ID, name) + 2)); @@ -1514,12 +1397,12 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, break; } } - - if (me==NULL) { + + if (me == NULL) { printf("Could not be found \"%s\"\n", name); return NULL; } - + /* Watch this!, if its used in the original scene can cause big troubles */ if (me->us > 0) { #ifdef DEBUG @@ -1531,34 +1414,32 @@ RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, BLI_remlink(&from_maggie->mesh, me); /* even if we made the copy it needs to be removed */ BLI_addtail(&maggie->mesh, me); - /* Must copy the materials this uses else we cant free them */ { - Mesh *mesh= (Mesh *)me; - + Mesh *mesh = (Mesh *)me; + /* ensure all materials are tagged */ - for (int i=0; i<mesh->totcol; i++) + for (int i = 0; i < mesh->totcol; i++) { if (mesh->mat[i]) mesh->mat[i]->id.flag &= ~LIB_DOIT; - - for (int i=0; i<mesh->totcol; i++) - { - Material *mat_old= mesh->mat[i]; - + } + + for (int i = 0; i < mesh->totcol; i++) { + Material *mat_old = mesh->mat[i]; + /* if its tagged its a replaced material */ - if (mat_old && (mat_old->id.flag & LIB_DOIT)==0) - { - Material *mat_old= mesh->mat[i]; - Material *mat_new= BKE_material_copy( mat_old ); - + if (mat_old && (mat_old->id.flag & LIB_DOIT) == 0) { + Material *mat_old = mesh->mat[i]; + Material *mat_new = BKE_material_copy(mat_old); + mat_new->id.flag |= LIB_DOIT; mat_old->id.us--; - + BLI_remlink(&G.main->mat, mat_new); // BKE_material_copy uses G.main, and there is no BKE_material_copy_ex BLI_addtail(&maggie->mat, mat_new); - + mesh->mat[i] = mat_new; - + /* the same material may be used twice */ for (int j = i + 1; j < mesh->totcol; j++) { if (mesh->mat[j] == mat_old) { diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.h b/source/gameengine/Converter/KX_BlenderSceneConverter.h index 3ae90301553..a40188d197d 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.h +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.h @@ -32,7 +32,7 @@ #ifndef __KX_BLENDERSCENECONVERTER_H__ #define __KX_BLENDERSCENECONVERTER_H__ -#include "KX_HashedPtr.h" +#include "EXP_HashedPtr.h" #include "CTR_Map.h" #include <stdio.h> diff --git a/source/gameengine/Converter/KX_ConvertActuators.cpp b/source/gameengine/Converter/KX_ConvertActuators.cpp index f6ed3366625..3b36e094a75 100644 --- a/source/gameengine/Converter/KX_ConvertActuators.cpp +++ b/source/gameengine/Converter/KX_ConvertActuators.cpp @@ -42,8 +42,7 @@ #include "KX_ConvertActuators.h" #ifdef WITH_AUDASPACE -# include "AUD_C-API.h" -# include "AUD_ChannelMapperFactory.h" +# include AUD_SOUND_H #endif // Actuators @@ -75,7 +74,7 @@ #include "KX_Scene.h" #include "KX_KetsjiEngine.h" -#include "IntValue.h" +#include "EXP_IntValue.h" #include "KX_GameObject.h" /* This little block needed for linking to Blender... */ @@ -385,7 +384,7 @@ void BL_ConvertActuators(const char* maggiename, { bSound* sound = soundact->sound; bool is3d = soundact->flag & ACT_SND_3D_SOUND ? true : false; - boost::shared_ptr<AUD_IFactory> snd_sound; + AUD_Sound* snd_sound = NULL; KX_3DSoundSettings settings; settings.cone_inner_angle = RAD2DEGF(soundact->sound3D.cone_inner_angle); settings.cone_outer_angle = RAD2DEGF(soundact->sound3D.cone_outer_angle); @@ -404,27 +403,12 @@ void BL_ConvertActuators(const char* maggiename, } else { - snd_sound = *reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(sound->playback_handle); + snd_sound = sound->playback_handle; // if sound shall be 3D but isn't mono, we have to make it mono! if (is3d) { - try - { - boost::shared_ptr<AUD_IReader> reader = snd_sound->createReader(); - if (reader->getSpecs().channels != AUD_CHANNELS_MONO) - { - AUD_DeviceSpecs specs; - specs.channels = AUD_CHANNELS_MONO; - specs.rate = AUD_RATE_INVALID; - specs.format = AUD_FORMAT_INVALID; - snd_sound = boost::shared_ptr<AUD_IFactory>(new AUD_ChannelMapperFactory(snd_sound, specs)); - } - } - catch(AUD_Exception&) - { - // sound cannot be played... ignore - } + snd_sound = AUD_Sound_rechannel(snd_sound, AUD_CHANNELS_MONO); } } KX_SoundActuator* tmpsoundact = @@ -436,6 +420,10 @@ void BL_ConvertActuators(const char* maggiename, settings, soundActuatorType); + // if we made it mono, we have to free it + if(snd_sound != sound->playback_handle && snd_sound != NULL) + AUD_Sound_free(snd_sound); + tmpsoundact->SetName(bact->name); baseact = tmpsoundact; } @@ -1087,11 +1075,12 @@ void BL_ConvertActuators(const char* maggiename, bool enableVisualization = (stAct->flag & ACT_STEERING_ENABLEVISUALIZATION) !=0; short facingMode = (stAct->flag & ACT_STEERING_AUTOMATICFACING) ? stAct->facingaxis : 0; bool normalup = (stAct->flag & ACT_STEERING_NORMALUP) !=0; + bool lockzvel = (stAct->flag & ACT_STEERING_LOCKZVEL) !=0; KX_SteeringActuator *tmpstact = new KX_SteeringActuator(gameobj, mode, targetob, navmeshob,stAct->dist, stAct->velocity, stAct->acceleration, stAct->turnspeed, selfTerminated, stAct->updateTime, - scene->GetObstacleSimulation(), facingMode, normalup, enableVisualization); + scene->GetObstacleSimulation(), facingMode, normalup, enableVisualization, lockzvel); baseact = tmpstact; break; } diff --git a/source/gameengine/Converter/KX_ConvertControllers.cpp b/source/gameengine/Converter/KX_ConvertControllers.cpp index 0215b604fdd..e3697087ea9 100644 --- a/source/gameengine/Converter/KX_ConvertControllers.cpp +++ b/source/gameengine/Converter/KX_ConvertControllers.cpp @@ -34,7 +34,7 @@ #include "KX_BlenderSceneConverter.h" #include "KX_ConvertControllers.h" -#include "KX_Python.h" +#include "EXP_Python.h" // Controller #include "SCA_ANDController.h" @@ -48,7 +48,7 @@ #include "SCA_LogicManager.h" #include "KX_GameObject.h" -#include "IntValue.h" +#include "EXP_IntValue.h" /* This little block needed for linking to Blender... */ #ifdef WIN32 diff --git a/source/gameengine/Converter/KX_ConvertControllers.h b/source/gameengine/Converter/KX_ConvertControllers.h index babe3e2e73f..2f93d70a6f9 100644 --- a/source/gameengine/Converter/KX_ConvertControllers.h +++ b/source/gameengine/Converter/KX_ConvertControllers.h @@ -32,7 +32,7 @@ #ifndef __KX_CONVERTCONTROLLERS_H__ #define __KX_CONVERTCONTROLLERS_H__ -#include "KX_Python.h" +#include "EXP_Python.h" void BL_ConvertControllers( struct Object* blenderobject, @@ -41,7 +41,7 @@ void BL_ConvertControllers( int activeLayerBitInfo, bool isInActiveLayer, class KX_BlenderSceneConverter* converter, - bool libloading + bool libloading ); #endif /* __KX_CONVERTCONTROLLERS_H__ */ diff --git a/source/gameengine/Converter/KX_ConvertProperties.cpp b/source/gameengine/Converter/KX_ConvertProperties.cpp index 3b4ba6886cb..2cb61207fb5 100644 --- a/source/gameengine/Converter/KX_ConvertProperties.cpp +++ b/source/gameengine/Converter/KX_ConvertProperties.cpp @@ -38,13 +38,13 @@ /* end of blender include block */ -#include "Value.h" -#include "VectorValue.h" -#include "BoolValue.h" -#include "StringValue.h" -#include "FloatValue.h" +#include "EXP_Value.h" +#include "EXP_VectorValue.h" +#include "EXP_BoolValue.h" +#include "EXP_StringValue.h" +#include "EXP_FloatValue.h" #include "KX_GameObject.h" -#include "IntValue.h" +#include "EXP_IntValue.h" #include "SCA_TimeEventManager.h" #include "SCA_IScene.h" diff --git a/source/gameengine/Converter/KX_ConvertSensors.cpp b/source/gameengine/Converter/KX_ConvertSensors.cpp index 0d706fcd924..79fd9cb9254 100644 --- a/source/gameengine/Converter/KX_ConvertSensors.cpp +++ b/source/gameengine/Converter/KX_ConvertSensors.cpp @@ -79,7 +79,7 @@ #include "SCA_LogicManager.h" #include "KX_BlenderInputDevice.h" #include "KX_Scene.h" -#include "IntValue.h" +#include "EXP_IntValue.h" #include "KX_BlenderKeyboardDevice.h" #include "RAS_ICanvas.h" #include "PHY_IPhysicsEnvironment.h" @@ -105,7 +105,7 @@ void BL_ConvertSensors(struct Object* blenderobject, bSensor* sens = (bSensor*)blenderobject->sensors.first; bool pos_pulsemode = false; bool neg_pulsemode = false; - int frequency = 0; + int skipped_ticks = 0; bool invert = false; bool level = false; bool tap = false; @@ -119,542 +119,542 @@ void BL_ConvertSensors(struct Object* blenderobject, sens = (bSensor*)blenderobject->sensors.first; while (sens) { - SCA_ISensor* gamesensor=NULL; - /* All sensors have a pulse toggle, frequency, and invert field. */ - /* These are extracted here, and set when the sensor is added to the */ - /* list. */ - pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0; - neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0; - - frequency = sens->freq; - invert = !(sens->invert == 0); - level = !(sens->level == 0); - tap = !(sens->tap == 0); - - switch (sens->type) - { - case SENS_ALWAYS: - { - - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) - { - gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj); - } - - break; - } - - case SENS_DELAY: + if (!(sens->flag & SENS_DEACTIVATE)) { + SCA_ISensor* gamesensor=NULL; + /* All sensors have a pulse toggle, skipped ticks parameter, and invert field. */ + /* These are extracted here, and set when the sensor is added to the */ + /* list. */ + pos_pulsemode = (sens->pulse & SENS_PULSE_REPEAT)!=0; + neg_pulsemode = (sens->pulse & SENS_NEG_PULSE_MODE)!=0; + + skipped_ticks = sens->freq; + invert = !(sens->invert == 0); + level = !(sens->level == 0); + tap = !(sens->tap == 0); + + switch (sens->type) { - // we can reuse the Always event manager for the delay sensor - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + case SENS_ALWAYS: { - bDelaySensor* delaysensor = (bDelaySensor*)sens->data; - gamesensor = new SCA_DelaySensor(eventmgr, - gameobj, - delaysensor->delay, - delaysensor->duration, - (delaysensor->flag & SENS_DELAY_REPEAT) != 0); + + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) + { + gamesensor = new SCA_AlwaysSensor(eventmgr, gameobj); + } + + break; } - break; - } - case SENS_COLLISION: - { - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - if (eventmgr) + case SENS_DELAY: { - // collision sensor can sense both materials and properties. - - bool bFindMaterial = false, bTouchPulse = false; - - bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data; - - bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL); - bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE); - - - const STR_String touchPropOrMatName = bFindMaterial ? - blendertouchsensor->materialName : blendertouchsensor->name; - - - if (gameobj->GetPhysicsController()) + // we can reuse the Always event manager for the delay sensor + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) { - gamesensor = new KX_TouchSensor(eventmgr, + bDelaySensor* delaysensor = (bDelaySensor*)sens->data; + gamesensor = new SCA_DelaySensor(eventmgr, gameobj, - bFindMaterial, - bTouchPulse, - touchPropOrMatName); + delaysensor->delay, + delaysensor->duration, + (delaysensor->flag & SENS_DELAY_REPEAT) != 0); } - - } - - break; - } - case SENS_MESSAGE: - { - KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*) - logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR); - if (eventmgr) { - bMessageSensor* msgSens = (bMessageSensor*) sens->data; - - /* Get our NetworkScene */ - NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene(); - /* filter on the incoming subjects, might be empty */ - const STR_String subject = msgSens->subject; - - gamesensor = new KX_NetworkMessageSensor( - eventmgr, // our eventmanager - NetworkScene, // our NetworkScene - gameobj, // the sensor controlling object - subject); // subject to filter on + break; } - break; - } - case SENS_NEAR: - { - - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - if (eventmgr) + + case SENS_COLLISION: { - bNearSensor* blendernearsensor = (bNearSensor*)sens->data; - const STR_String nearpropertyname = (char *)blendernearsensor->name; - - //DT_ShapeHandle shape = DT_Sphere(0.0); - - // this sumoObject is not deleted by a gameobj, so delete it ourself - // later (memleaks)! - float radius = blendernearsensor->dist; - const MT_Vector3& wpos = gameobj->NodeGetWorldPosition(); - bool bFindMaterial = false; - PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,wpos); - - //will be done in KX_TouchEventManager::RegisterSensor() - //if (isInActiveLayer) - // kxscene->GetPhysicsEnvironment()->addSensor(physCtrl); - - - - gamesensor = new KX_NearSensor(eventmgr,gameobj, - blendernearsensor->dist, - blendernearsensor->resetdist, - bFindMaterial, - nearpropertyname, - physCtrl); - + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); + if (eventmgr) + { + // collision sensor can sense both materials and properties. + + bool bFindMaterial = false, bTouchPulse = false; + + bCollisionSensor* blendertouchsensor = (bCollisionSensor*)sens->data; + + bFindMaterial = (blendertouchsensor->mode & SENS_COLLISION_MATERIAL); + bTouchPulse = (blendertouchsensor->mode & SENS_COLLISION_PULSE); + + + const STR_String touchPropOrMatName = bFindMaterial ? + blendertouchsensor->materialName : blendertouchsensor->name; + + + if (gameobj->GetPhysicsController()) + { + gamesensor = new KX_TouchSensor(eventmgr, + gameobj, + bFindMaterial, + bTouchPulse, + touchPropOrMatName); + } + + } + + break; } - break; - } - - - case SENS_KEYBOARD: - { - /* temporary input device, for converting the code for the keyboard sensor */ - - bKeyboardSensor* blenderkeybdsensor = (bKeyboardSensor*)sens->data; - SCA_KeyboardManager* eventmgr = (SCA_KeyboardManager*) logicmgr->FindEventManager(SCA_EventManager::KEYBOARD_EVENTMGR); - if (eventmgr) + case SENS_MESSAGE: { - gamesensor = new SCA_KeyboardSensor(eventmgr, - ConvertKeyCode(blenderkeybdsensor->key), - ConvertKeyCode(blenderkeybdsensor->qual), - ConvertKeyCode(blenderkeybdsensor->qual2), - (blenderkeybdsensor->type == SENS_ALL_KEYS), - blenderkeybdsensor->targetName, - blenderkeybdsensor->toggleName, - gameobj, - KX_KetsjiEngine::GetExitKey()); // blenderkeybdsensor->pad); - - } - - break; - } - case SENS_MOUSE: - { - int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF; - int trackfocus = 0; - bMouseSensor *bmouse = (bMouseSensor *)sens->data; - - /* There are two main types of mouse sensors. If there is - * no focus-related behavior requested, we can make do - * with a basic sensor. This cuts down memory usage and - * gives a slight performance gain. */ - - SCA_MouseManager *eventmgr - = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR); - if (eventmgr) { - - /* Determine key mode. There is at most one active mode. */ - switch (bmouse->type) { - case BL_SENS_MOUSE_LEFT_BUTTON: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_LEFTBUTTON; - break; - case BL_SENS_MOUSE_MIDDLE_BUTTON: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MIDDLEBUTTON; - break; - case BL_SENS_MOUSE_RIGHT_BUTTON: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_RIGHTBUTTON; - break; - case BL_SENS_MOUSE_WHEEL_UP: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELUP; - break; - case BL_SENS_MOUSE_WHEEL_DOWN: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELDOWN; - break; - case BL_SENS_MOUSE_MOVEMENT: - keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MOVEMENT; - break; - case BL_SENS_MOUSE_MOUSEOVER: - trackfocus = 1; - break; - case BL_SENS_MOUSE_MOUSEOVER_ANY: - trackfocus = 2; - break; - - default: - ; /* error */ + KX_NetworkEventManager* eventmgr = (KX_NetworkEventManager*) + logicmgr->FindEventManager(SCA_EventManager::NETWORK_EVENTMGR); + if (eventmgr) { + bMessageSensor* msgSens = (bMessageSensor*) sens->data; + + /* Get our NetworkScene */ + NG_NetworkScene *NetworkScene = kxscene->GetNetworkScene(); + /* filter on the incoming subjects, might be empty */ + const STR_String subject = msgSens->subject; + + gamesensor = new KX_NetworkMessageSensor( + eventmgr, // our eventmanager + NetworkScene, // our NetworkScene + gameobj, // the sensor controlling object + subject); // subject to filter on } - - /* initial mouse position */ - int startx = canvas->GetWidth()/2; - int starty = canvas->GetHeight()/2; - - if (!trackfocus) { - /* plain, simple mouse sensor */ - gamesensor = new SCA_MouseSensor(eventmgr, - startx,starty, - keytype, - gameobj); - } else { - /* give us a focus-aware sensor */ - bool bFindMaterial = (bmouse->mode & SENS_COLLISION_MATERIAL); - bool bXRay = (bmouse->flag & SENS_RAY_XRAY); - STR_String checkname = (bFindMaterial? bmouse->matname : bmouse->propname); - - gamesensor = new KX_MouseFocusSensor(eventmgr, - startx, - starty, - keytype, - trackfocus, - (bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false, - checkname, + break; + } + case SENS_NEAR: + { + + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); + if (eventmgr) + { + bNearSensor* blendernearsensor = (bNearSensor*)sens->data; + const STR_String nearpropertyname = (char *)blendernearsensor->name; + + //DT_ShapeHandle shape = DT_Sphere(0.0); + + // this sumoObject is not deleted by a gameobj, so delete it ourself + // later (memleaks)! + float radius = blendernearsensor->dist; + const MT_Vector3& wpos = gameobj->NodeGetWorldPosition(); + bool bFindMaterial = false; + PHY_IPhysicsController* physCtrl = kxscene->GetPhysicsEnvironment()->CreateSphereController(radius,wpos); + + //will be done in KX_TouchEventManager::RegisterSensor() + //if (isInActiveLayer) + // kxscene->GetPhysicsEnvironment()->addSensor(physCtrl); + + + + gamesensor = new KX_NearSensor(eventmgr,gameobj, + blendernearsensor->dist, + blendernearsensor->resetdist, bFindMaterial, - bXRay, - kxscene, - kxengine, - gameobj); + nearpropertyname, + physCtrl); + } - } else { - // cout << "\n Could't find mouse event manager..."; - should throw an error here... + break; } - break; - } - case SENS_PROPERTY: - { - bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data; - SCA_EventManager* eventmgr - = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + + + case SENS_KEYBOARD: { - STR_String propname=blenderpropsensor->name; - STR_String propval=blenderpropsensor->value; - STR_String propmaxval=blenderpropsensor->maxvalue; - - SCA_PropertySensor::KX_PROPSENSOR_TYPE - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NODEF; - - /* Better do an explicit conversion here! (was implicit */ - /* before...) */ - switch (blenderpropsensor->type) { - case SENS_PROP_EQUAL: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL; - break; - case SENS_PROP_NEQUAL: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL; - break; - case SENS_PROP_INTERVAL: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_INTERVAL; - break; - case SENS_PROP_CHANGED: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_CHANGED; - break; - case SENS_PROP_EXPRESSION: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION; - /* error */ - break; - case SENS_PROP_LESSTHAN: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_LESSTHAN; - break; - case SENS_PROP_GREATERTHAN: - propchecktype = SCA_PropertySensor::KX_PROPSENSOR_GREATERTHAN; - break; - default: - ; /* error */ + /* temporary input device, for converting the code for the keyboard sensor */ + + bKeyboardSensor* blenderkeybdsensor = (bKeyboardSensor*)sens->data; + SCA_KeyboardManager* eventmgr = (SCA_KeyboardManager*) logicmgr->FindEventManager(SCA_EventManager::KEYBOARD_EVENTMGR); + if (eventmgr) + { + gamesensor = new SCA_KeyboardSensor(eventmgr, + ConvertKeyCode(blenderkeybdsensor->key), + ConvertKeyCode(blenderkeybdsensor->qual), + ConvertKeyCode(blenderkeybdsensor->qual2), + (blenderkeybdsensor->type == SENS_ALL_KEYS), + blenderkeybdsensor->targetName, + blenderkeybdsensor->toggleName, + gameobj, + KX_KetsjiEngine::GetExitKey()); // blenderkeybdsensor->pad); + } - gamesensor = new SCA_PropertySensor(eventmgr,gameobj,propname,propval,propmaxval,propchecktype); + + break; } - - break; - } - case SENS_ACTUATOR: - { - bActuatorSensor* blenderactsensor = (bActuatorSensor*) sens->data; - // we will reuse the property event manager, there is nothing special with this sensor - SCA_EventManager* eventmgr - = logicmgr->FindEventManager(SCA_EventManager::ACTUATOR_EVENTMGR); - if (eventmgr) + case SENS_MOUSE: + { + int keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_NODEF; + int trackfocus = 0; + bMouseSensor *bmouse = (bMouseSensor *)sens->data; + + /* There are two main types of mouse sensors. If there is + * no focus-related behavior requested, we can make do + * with a basic sensor. This cuts down memory usage and + * gives a slight performance gain. */ + + SCA_MouseManager *eventmgr + = (SCA_MouseManager*) logicmgr->FindEventManager(SCA_EventManager::MOUSE_EVENTMGR); + if (eventmgr) { + + /* Determine key mode. There is at most one active mode. */ + switch (bmouse->type) { + case BL_SENS_MOUSE_LEFT_BUTTON: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_LEFTBUTTON; + break; + case BL_SENS_MOUSE_MIDDLE_BUTTON: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MIDDLEBUTTON; + break; + case BL_SENS_MOUSE_RIGHT_BUTTON: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_RIGHTBUTTON; + break; + case BL_SENS_MOUSE_WHEEL_UP: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELUP; + break; + case BL_SENS_MOUSE_WHEEL_DOWN: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_WHEELDOWN; + break; + case BL_SENS_MOUSE_MOVEMENT: + keytype = SCA_MouseSensor::KX_MOUSESENSORMODE_MOVEMENT; + break; + case BL_SENS_MOUSE_MOUSEOVER: + trackfocus = 1; + break; + case BL_SENS_MOUSE_MOUSEOVER_ANY: + trackfocus = 2; + break; + + default: + ; /* error */ + } + + /* initial mouse position */ + int startx = canvas->GetWidth()/2; + int starty = canvas->GetHeight()/2; + + if (!trackfocus) { + /* plain, simple mouse sensor */ + gamesensor = new SCA_MouseSensor(eventmgr, + startx,starty, + keytype, + gameobj); + } else { + /* give us a focus-aware sensor */ + bool bFindMaterial = (bmouse->mode & SENS_COLLISION_MATERIAL); + bool bXRay = (bmouse->flag & SENS_RAY_XRAY); + STR_String checkname = (bFindMaterial? bmouse->matname : bmouse->propname); + + gamesensor = new KX_MouseFocusSensor(eventmgr, + startx, + starty, + keytype, + trackfocus, + (bmouse->flag & SENS_MOUSE_FOCUS_PULSE) ? true:false, + checkname, + bFindMaterial, + bXRay, + kxscene, + kxengine, + gameobj); + } + } else { + // cout << "\n Could't find mouse event manager..."; - should throw an error here... + } + break; + } + case SENS_PROPERTY: { - STR_String propname=blenderactsensor->name; - gamesensor = new SCA_ActuatorSensor(eventmgr,gameobj,propname); + bPropertySensor* blenderpropsensor = (bPropertySensor*) sens->data; + SCA_EventManager* eventmgr + = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) + { + STR_String propname=blenderpropsensor->name; + STR_String propval=blenderpropsensor->value; + STR_String propmaxval=blenderpropsensor->maxvalue; + + SCA_PropertySensor::KX_PROPSENSOR_TYPE + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NODEF; + + /* Better do an explicit conversion here! (was implicit */ + /* before...) */ + switch (blenderpropsensor->type) { + case SENS_PROP_EQUAL: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EQUAL; + break; + case SENS_PROP_NEQUAL: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_NOTEQUAL; + break; + case SENS_PROP_INTERVAL: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_INTERVAL; + break; + case SENS_PROP_CHANGED: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_CHANGED; + break; + case SENS_PROP_EXPRESSION: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_EXPRESSION; + /* error */ + break; + case SENS_PROP_LESSTHAN: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_LESSTHAN; + break; + case SENS_PROP_GREATERTHAN: + propchecktype = SCA_PropertySensor::KX_PROPSENSOR_GREATERTHAN; + break; + default: + ; /* error */ + } + gamesensor = new SCA_PropertySensor(eventmgr,gameobj,propname,propval,propmaxval,propchecktype); + } + + break; } - break; - } - - case SENS_ARMATURE: - { - bArmatureSensor* blenderarmsensor = (bArmatureSensor*) sens->data; - // we will reuse the property event manager, there is nothing special with this sensor - SCA_EventManager* eventmgr - = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + case SENS_ACTUATOR: { - STR_String bonename=blenderarmsensor->posechannel; - STR_String constraintname=blenderarmsensor->constraint; - gamesensor = new KX_ArmatureSensor(eventmgr,gameobj,bonename,constraintname, blenderarmsensor->type, blenderarmsensor->value); + bActuatorSensor* blenderactsensor = (bActuatorSensor*) sens->data; + // we will reuse the property event manager, there is nothing special with this sensor + SCA_EventManager* eventmgr + = logicmgr->FindEventManager(SCA_EventManager::ACTUATOR_EVENTMGR); + if (eventmgr) + { + STR_String propname=blenderactsensor->name; + gamesensor = new SCA_ActuatorSensor(eventmgr,gameobj,propname); + } + break; } - break; - } - case SENS_RADAR: - { - - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - if (eventmgr) + case SENS_ARMATURE: { - bRadarSensor* blenderradarsensor = (bRadarSensor*) sens->data; - const STR_String radarpropertyname = blenderradarsensor->name; - - int radaraxis = blenderradarsensor->axis; - - MT_Scalar coneheight = blenderradarsensor->range; - - // janco: the angle was doubled, so should I divide the factor in 2 - // or the blenderradarsensor->angle? - // nzc: the angle is the opening angle. We need to init with - // the axis-hull angle,so /2.0. - MT_Scalar factor = tan(blenderradarsensor->angle * 0.5f); - //MT_Scalar coneradius = coneheight * (factor / 2); - MT_Scalar coneradius = coneheight * factor; - - - // this sumoObject is not deleted by a gameobj, so delete it ourself - // later (memleaks)! - MT_Scalar smallmargin = 0.0; - MT_Scalar largemargin = 0.0; - - bool bFindMaterial = false; - PHY_IPhysicsController* ctrl = kxscene->GetPhysicsEnvironment()->CreateConeController((float)coneradius, (float)coneheight); - - gamesensor = new KX_RadarSensor( - eventmgr, - gameobj, - ctrl, - coneradius, - coneheight, - radaraxis, - smallmargin, - largemargin, - bFindMaterial, - radarpropertyname); - + bArmatureSensor* blenderarmsensor = (bArmatureSensor*) sens->data; + // we will reuse the property event manager, there is nothing special with this sensor + SCA_EventManager* eventmgr + = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) + { + STR_String bonename=blenderarmsensor->posechannel; + STR_String constraintname=blenderarmsensor->constraint; + gamesensor = new KX_ArmatureSensor(eventmgr,gameobj,bonename,constraintname, blenderarmsensor->type, blenderarmsensor->value); + } + break; } - - break; - } - case SENS_RAY: - { - bRaySensor* blenderraysensor = (bRaySensor*) sens->data; - - //blenderradarsensor->angle; - SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); - if (eventmgr) + + case SENS_RADAR: { - bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL); - bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY); - - STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname); - - // don't want to get rays of length 0.0 or so - double distance = (blenderraysensor->range < 0.01f ? 0.01f : blenderraysensor->range); - int axis = blenderraysensor->axisflag; - - - gamesensor = new KX_RaySensor(eventmgr, - gameobj, - checkname, - bFindMaterial, - bXRay, - distance, - axis, - kxscene); + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); + if (eventmgr) + { + bRadarSensor* blenderradarsensor = (bRadarSensor*) sens->data; + const STR_String radarpropertyname = blenderradarsensor->name; + + int radaraxis = blenderradarsensor->axis; + + MT_Scalar coneheight = blenderradarsensor->range; + + // janco: the angle was doubled, so should I divide the factor in 2 + // or the blenderradarsensor->angle? + // nzc: the angle is the opening angle. We need to init with + // the axis-hull angle,so /2.0. + MT_Scalar factor = tan(blenderradarsensor->angle * 0.5f); + //MT_Scalar coneradius = coneheight * (factor / 2); + MT_Scalar coneradius = coneheight * factor; + + + // this sumoObject is not deleted by a gameobj, so delete it ourself + // later (memleaks)! + MT_Scalar smallmargin = 0.0; + MT_Scalar largemargin = 0.0; + + bool bFindMaterial = false; + PHY_IPhysicsController* ctrl = kxscene->GetPhysicsEnvironment()->CreateConeController((float)coneradius, (float)coneheight); + + gamesensor = new KX_RadarSensor( + eventmgr, + gameobj, + ctrl, + coneradius, + coneheight, + radaraxis, + smallmargin, + largemargin, + bFindMaterial, + radarpropertyname); + + } + + break; } - break; - } - - case SENS_RANDOM: - { - bRandomSensor* blenderrndsensor = (bRandomSensor*) sens->data; - // some files didn't write randomsensor, avoid crash now for NULL ptr's - if (blenderrndsensor) + case SENS_RAY: { + bRaySensor* blenderraysensor = (bRaySensor*) sens->data; + + //blenderradarsensor->angle; SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); if (eventmgr) { - int randomSeed = blenderrndsensor->seed; - if (randomSeed == 0) + bool bFindMaterial = (blenderraysensor->mode & SENS_COLLISION_MATERIAL); + bool bXRay = (blenderraysensor->mode & SENS_RAY_XRAY); + + STR_String checkname = (bFindMaterial? blenderraysensor->matname : blenderraysensor->propname); + + // don't want to get rays of length 0.0 or so + double distance = (blenderraysensor->range < 0.01f ? 0.01f : blenderraysensor->range); + int axis = blenderraysensor->axisflag; + + + gamesensor = new KX_RaySensor(eventmgr, + gameobj, + checkname, + bFindMaterial, + bXRay, + distance, + axis, + kxscene); + + } + break; + } + + case SENS_RANDOM: + { + bRandomSensor* blenderrndsensor = (bRandomSensor*) sens->data; + // some files didn't write randomsensor, avoid crash now for NULL ptr's + if (blenderrndsensor) + { + SCA_EventManager* eventmgr = logicmgr->FindEventManager(SCA_EventManager::BASIC_EVENTMGR); + if (eventmgr) { - randomSeed = (int)(kxengine->GetRealTime()*100000.0); - randomSeed ^= (intptr_t)blenderrndsensor; + int randomSeed = blenderrndsensor->seed; + if (randomSeed == 0) + { + randomSeed = (int)(kxengine->GetRealTime()*100000.0); + randomSeed ^= (intptr_t)blenderrndsensor; + } + gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed); } - gamesensor = new SCA_RandomSensor(eventmgr, gameobj, randomSeed); } + break; } - break; - } - case SENS_JOYSTICK: - { - int joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_NODEF; - - bJoystickSensor* bjoy = (bJoystickSensor*) sens->data; - - SCA_JoystickManager *eventmgr - = (SCA_JoystickManager*) logicmgr->FindEventManager(SCA_EventManager::JOY_EVENTMGR); - if (eventmgr) + case SENS_JOYSTICK: { - int axis =0; - int axisf =0; - int button =0; - int hat =0; - int hatf =0; - int prec =0; - - switch (bjoy->type) { - case SENS_JOY_AXIS: - axis = bjoy->axis; - axisf = bjoy->axisf; - prec = bjoy->precision; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS; - break; - case SENS_JOY_BUTTON: - button = bjoy->button; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_BUTTON; - break; - case SENS_JOY_HAT: - hat = bjoy->hat; - hatf = bjoy->hatf; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_HAT; - break; - case SENS_JOY_AXIS_SINGLE: - axis = bjoy->axis_single; - prec = bjoy->precision; - joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS_SINGLE; - break; - default: - printf("Error: bad case statement\n"); - break; + int joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_NODEF; + + bJoystickSensor* bjoy = (bJoystickSensor*) sens->data; + + SCA_JoystickManager *eventmgr + = (SCA_JoystickManager*) logicmgr->FindEventManager(SCA_EventManager::JOY_EVENTMGR); + if (eventmgr) + { + int axis =0; + int axisf =0; + int button =0; + int hat =0; + int hatf =0; + int prec =0; + + switch (bjoy->type) { + case SENS_JOY_AXIS: + axis = bjoy->axis; + axisf = bjoy->axisf; + prec = bjoy->precision; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS; + break; + case SENS_JOY_BUTTON: + button = bjoy->button; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_BUTTON; + break; + case SENS_JOY_HAT: + hat = bjoy->hat; + hatf = bjoy->hatf; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_HAT; + break; + case SENS_JOY_AXIS_SINGLE: + axis = bjoy->axis_single; + prec = bjoy->precision; + joysticktype = SCA_JoystickSensor::KX_JOYSENSORMODE_AXIS_SINGLE; + break; + default: + printf("Error: bad case statement\n"); + break; + } + gamesensor = new SCA_JoystickSensor( + eventmgr, + gameobj, + bjoy->joyindex, + joysticktype, + axis,axisf, + prec, + button, + hat,hatf, + (bjoy->flag & SENS_JOY_ANY_EVENT)); } - gamesensor = new SCA_JoystickSensor( - eventmgr, - gameobj, - bjoy->joyindex, - joysticktype, - axis,axisf, - prec, - button, - hat,hatf, - (bjoy->flag & SENS_JOY_ANY_EVENT)); - } - else + else + { + printf("Error there was a problem finding the event manager\n"); + } + + break; + } + default: { - printf("Error there was a problem finding the event manager\n"); } - - break; } - default: - { - } - } - if (gamesensor && !(sens->flag & SENS_DEACTIVATE)) - { - gamesensor->SetExecutePriority(executePriority++); - STR_String uniquename = sens->name; - uniquename += "#SENS#"; - uniqueint++; - CIntValue* uniqueval = new CIntValue(uniqueint); - uniquename += uniqueval->GetText(); - uniqueval->Release(); - - /* Conversion succeeded, so we can set the generic props here. */ - gamesensor->SetPulseMode(pos_pulsemode, - neg_pulsemode, - frequency); - gamesensor->SetInvert(invert); - gamesensor->SetLevel(level); - gamesensor->SetTap(tap); - gamesensor->SetName(sens->name); - - gameobj->AddSensor(gamesensor); - - // only register to manager if it's in an active layer - // Make registration dynamic: only when sensor is activated - //if (isInActiveLayer) - // gamesensor->RegisterToManager(); - - gamesensor->ReserveController(sens->totlinks); - for (int i=0;i<sens->totlinks;i++) + if (gamesensor) { - bController* linkedcont = (bController*) sens->links[i]; - if (linkedcont) { - // If the controller is deactived doesn't register it - if (!(linkedcont->flag & CONT_DEACTIVATE)) { - SCA_IController* gamecont = converter->FindGameController(linkedcont); - - if (gamecont) { - logicmgr->RegisterToSensor(gamecont,gamesensor); - } - else { - printf("Warning, sensor \"%s\" could not find its controller " - "(link %d of %d) from object \"%s\"\n" - "\tthere has been an error converting the blender controller for the game engine," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + gamesensor->SetExecutePriority(executePriority++); + STR_String uniquename = sens->name; + uniquename += "#SENS#"; + uniqueint++; + CIntValue* uniqueval = new CIntValue(uniqueint); + uniquename += uniqueval->GetText(); + uniqueval->Release(); + + /* Conversion succeeded, so we can set the generic props here. */ + gamesensor->SetPulseMode(pos_pulsemode, + neg_pulsemode, + skipped_ticks); + gamesensor->SetInvert(invert); + gamesensor->SetLevel(level); + gamesensor->SetTap(tap); + gamesensor->SetName(sens->name); + + gameobj->AddSensor(gamesensor); + + // only register to manager if it's in an active layer + // Make registration dynamic: only when sensor is activated + //if (isInActiveLayer) + // gamesensor->RegisterToManager(); + + gamesensor->ReserveController(sens->totlinks); + for (int i=0;i<sens->totlinks;i++) + { + bController* linkedcont = (bController*) sens->links[i]; + if (linkedcont) { + // If the controller is deactived doesn't register it + if (!(linkedcont->flag & CONT_DEACTIVATE)) { + SCA_IController* gamecont = converter->FindGameController(linkedcont); + + if (gamecont) { + logicmgr->RegisterToSensor(gamecont,gamesensor); + } + else { + printf("Warning, sensor \"%s\" could not find its controller " + "(link %d of %d) from object \"%s\"\n" + "\tthere has been an error converting the blender controller for the game engine," + "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + } } } + else { + printf("Warning, sensor \"%s\" has lost a link to a controller " + "(link %d of %d) from object \"%s\"\n" + "\tpossible causes are partially appended objects or an error reading the file," + "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + } } - else { - printf("Warning, sensor \"%s\" has lost a link to a controller " - "(link %d of %d) from object \"%s\"\n" - "\tpossible causes are partially appended objects or an error reading the file," - "logic may be incorrect\n", sens->name, i+1, sens->totlinks, blenderobject->id.name+2); + // special case: Keyboard sensor with no link + // this combination is usually used for key logging. + if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { + // Force the registration so that the sensor runs + gamesensor->IncLink(); } + + // done with gamesensor + gamesensor->Release(); + } - // special case: Keyboard sensor with no link - // this combination is usually used for key logging. - if (sens->type == SENS_KEYBOARD && sens->totlinks == 0) { - // Force the registration so that the sensor runs - gamesensor->IncLink(); - } - - // done with gamesensor - gamesensor->Release(); - } - else if (gamesensor) - gamesensor->Release(); sens=sens->next; } diff --git a/source/gameengine/Converter/KX_LibLoadStatus.h b/source/gameengine/Converter/KX_LibLoadStatus.h index 3da7329213b..bedf4498c96 100644 --- a/source/gameengine/Converter/KX_LibLoadStatus.h +++ b/source/gameengine/Converter/KX_LibLoadStatus.h @@ -27,7 +27,7 @@ #ifndef __KX_LIBLOADSTATUS_H__ #define __KX_LIBLOADSTATUS_H__ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" class KX_LibLoadStatus : public PyObjectPlus { diff --git a/source/gameengine/Converter/SConscript b/source/gameengine/Converter/SConscript index affd4c94ed8..6336fcd3906 100644 --- a/source/gameengine/Converter/SConscript +++ b/source/gameengine/Converter/SConscript @@ -37,7 +37,6 @@ incs = [ '#intern/guardedalloc', '#intern/string', '#source/blender', - '#intern/audaspace/intern', '#intern/moto/include', '#source/blender/blenkernel', '#source/blender/blenlib', @@ -79,6 +78,10 @@ if env['WITH_BF_PYTHON']: incs += ' ' + env['BF_PYTHON_INC'] defs.append('WITH_PYTHON') +if env['WITH_BF_AUDASPACE']: + defs += env['BF_AUDASPACE_DEF'] + incs += ' ' + env['BF_AUDASPACE_C_INC'] + if env['WITH_BF_CXX_GUARDEDALLOC']: defs.append('WITH_CXX_GUARDEDALLOC') diff --git a/source/gameengine/Expressions/CMakeLists.txt b/source/gameengine/Expressions/CMakeLists.txt index 6907f314503..6ab4d3fdacc 100644 --- a/source/gameengine/Expressions/CMakeLists.txt +++ b/source/gameengine/Expressions/CMakeLists.txt @@ -36,47 +36,53 @@ set(INC_SYS ) set(SRC - BoolValue.cpp - ConstExpr.cpp - EXP_C-Api.cpp - EmptyValue.cpp - ErrorValue.cpp - Expression.cpp - FloatValue.cpp - IdentifierExpr.cpp - IfExpr.cpp - InputParser.cpp - IntValue.cpp - KX_HashedPtr.cpp - ListValue.cpp - Operator1Expr.cpp - Operator2Expr.cpp - PyObjectPlus.cpp - StringValue.cpp - Value.cpp - VectorValue.cpp + intern/BoolValue.cpp + intern/ConstExpr.cpp + intern/EmptyValue.cpp + intern/ErrorValue.cpp + intern/Expression.cpp + intern/FloatValue.cpp + intern/IdentifierExpr.cpp + intern/IfExpr.cpp + intern/InputParser.cpp + intern/IntValue.cpp + intern/HashedPtr.cpp + intern/ListValue.cpp + intern/Operator1Expr.cpp + intern/Operator2Expr.cpp + intern/PyObjectPlus.cpp + intern/StringValue.cpp + intern/Value.cpp + intern/VectorValue.cpp - BoolValue.h - ConstExpr.h - EXP_C-Api.h - EmptyValue.h - ErrorValue.h - Expression.h - FloatValue.h - IdentifierExpr.h - IfExpr.h - InputParser.h - IntValue.h - KX_HashedPtr.h - KX_Python.h - ListValue.h - Operator1Expr.h - Operator2Expr.h - PyObjectPlus.h - StringValue.h - Value.h - VectorValue.h - VoidValue.h + EXP_BoolValue.h + EXP_ConstExpr.h + EXP_EmptyValue.h + EXP_ErrorValue.h + EXP_Expression.h + EXP_FloatValue.h + EXP_HashedPtr.h + EXP_IdentifierExpr.h + EXP_IfExpr.h + EXP_InputParser.h + EXP_IntValue.h + EXP_ListValue.h + EXP_Operator1Expr.h + EXP_Operator2Expr.h + EXP_PyObjectPlus.h + EXP_Python.h + EXP_StringValue.h + EXP_Value.h + EXP_VectorValue.h + EXP_VoidValue.h ) +if(WITH_PYTHON) + list(APPEND SRC + intern/PythonCallBack.cpp + + EXP_PythonCallBack.h + ) +endif() + blender_add_lib(ge_logic_expressions "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/Expressions/BoolValue.h b/source/gameengine/Expressions/EXP_BoolValue.h index 161d6112f68..98ba1d75e52 100644 --- a/source/gameengine/Expressions/BoolValue.h +++ b/source/gameengine/Expressions/EXP_BoolValue.h @@ -12,14 +12,14 @@ * */ -/** \file BoolValue.h +/** \file EXP_BoolValue.h * \ingroup expressions */ -#ifndef __BOOLVALUE_H__ -#define __BOOLVALUE_H__ +#ifndef __EXP_BOOLVALUE_H__ +#define __EXP_BOOLVALUE_H__ -#include "Value.h" +#include "EXP_Value.h" /** * Smart Boolean Value class. @@ -62,4 +62,4 @@ private: #endif }; -#endif /* __BOOLVALUE_H__ */ +#endif /* __EXP_BOOLVALUE_H__ */ diff --git a/source/gameengine/Expressions/EXP_C-Api.cpp b/source/gameengine/Expressions/EXP_C-Api.cpp deleted file mode 100644 index 2822fd8f6de..00000000000 --- a/source/gameengine/Expressions/EXP_C-Api.cpp +++ /dev/null @@ -1,123 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file gameengine/Expressions/EXP_C-Api.cpp - * \ingroup expressions - */ - -#include "EXP_C-Api.h" -#include "IntValue.h" -#include "BoolValue.h" -#include "StringValue.h" -#include "ErrorValue.h" -#include "InputParser.h" - -EXP_ValueHandle EXP_CreateInt(int innie) -{ - return (EXP_ValueHandle) new CIntValue(innie); -} - - - -EXP_ValueHandle EXP_CreateBool(int innie) -{ - return (EXP_ValueHandle) new CBoolValue(innie!=0); -} - - - -EXP_ValueHandle EXP_CreateString(const char* str) -{ - - return (EXP_ValueHandle) new CStringValue(str,""); -} - - - -void EXP_SetName(EXP_ValueHandle inval,const char* newname) -{ - ((CValue*) inval)->SetName(newname); -} - - - -/* calculate expression from inputtext */ -EXP_ValueHandle EXP_ParseInput(const char* inputtext) -{ - CValue* resultval=NULL; - CParser parser; - CExpression* expr = parser.ProcessText(inputtext); - if (expr) - { - resultval = expr->Calculate(); - expr->Release(); - } - else - { - resultval = new CErrorValue("couldn't parsetext"); - } - - return (EXP_ValueHandle) resultval; -} - - - -void EXP_ReleaseValue(EXP_ValueHandle inval) -{ - ((CValue*) inval)->Release(); -} - - - -int EXP_IsValid(EXP_ValueHandle inval) -{ - return !((CValue*) inval)->IsError(); -} - - - -/* assign property 'propval' to 'destinationval' */ -void EXP_SetProperty(EXP_ValueHandle destinationval, - const char *propname, - EXP_ValueHandle propval) -{ - ((CValue*) destinationval)->SetProperty(propname,(CValue*)propval); -} - - - -const char* EXP_GetText(EXP_ValueHandle inval) -{ - return ((CValue*) inval)->GetText(); -} - - - -EXP_ValueHandle EXP_GetProperty(EXP_ValueHandle inval,const char* propname) -{ - return (EXP_ValueHandle) ((CValue*)inval)->GetProperty(propname); -} diff --git a/source/gameengine/Expressions/EXP_C-Api.h b/source/gameengine/Expressions/EXP_C-Api.h deleted file mode 100644 index d73b0a209d4..00000000000 --- a/source/gameengine/Expressions/EXP_C-Api.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * ***** BEGIN GPL LICENSE BLOCK ***** - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file EXP_C-Api.h - * \ingroup expressions - */ - -#ifndef __EXP_C_API_H__ -#define __EXP_C_API_H__ - -#define EXP_DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name - -EXP_DECLARE_HANDLE(EXP_ValueHandle); -EXP_DECLARE_HANDLE(EXP_ExpressionHandle); - - -#ifdef __cplusplus -extern "C" { -#endif - -extern EXP_ValueHandle EXP_CreateInt(int innie); -extern EXP_ValueHandle EXP_CreateBool(int innie); -extern EXP_ValueHandle EXP_CreateString(const char* str); -extern void EXP_SetName(EXP_ValueHandle,const char* newname); - -/* calculate expression from inputtext */ -extern EXP_ValueHandle EXP_ParseInput(const char* inputtext); -extern void EXP_ReleaseValue(EXP_ValueHandle); -extern int EXP_IsValid(EXP_ValueHandle); - -/* assign property 'propval' to 'destinationval' */ -extern void EXP_SetProperty(EXP_ValueHandle destinationval, const char *propname, EXP_ValueHandle propval); - -/* returns NULL if property doesn't exist */ -extern EXP_ValueHandle EXP_GetProperty(EXP_ValueHandle inval,const char* propname); - -const char* EXP_GetText(EXP_ValueHandle); - -#ifdef __cplusplus -} -#endif - -#endif /* __EXP_C_API_H__ */ diff --git a/source/gameengine/Expressions/ConstExpr.h b/source/gameengine/Expressions/EXP_ConstExpr.h index 768f2bbd10e..b4456dacdf3 100644 --- a/source/gameengine/Expressions/ConstExpr.h +++ b/source/gameengine/Expressions/EXP_ConstExpr.h @@ -12,15 +12,15 @@ * */ -/** \file ConstExpr.h +/** \file EXP_ConstExpr.h * \ingroup expressions */ -#ifndef __CONSTEXPR_H__ -#define __CONSTEXPR_H__ +#ifndef __EXP_CONSTEXPR_H__ +#define __EXP_CONSTEXPR_H__ -#include "Expression.h" -#include "Value.h" // Added by ClassView +#include "EXP_Expression.h" +#include "EXP_Value.h" // Added by ClassView class CConstExpr : public CExpression { @@ -51,4 +51,4 @@ private: #endif }; -#endif /* __CONSTEXPR_H__ */ +#endif /* __EXP_CONSTEXPR_H__ */ diff --git a/source/gameengine/Expressions/EmptyValue.h b/source/gameengine/Expressions/EXP_EmptyValue.h index 88ef206f0f0..d23addb9f9f 100644 --- a/source/gameengine/Expressions/EmptyValue.h +++ b/source/gameengine/Expressions/EXP_EmptyValue.h @@ -12,14 +12,14 @@ * */ -/** \file EmptyValue.h +/** \file EXP_EmptyValue.h * \ingroup expressions */ -#ifndef __EMPTYVALUE_H__ -#define __EMPTYVALUE_H__ +#ifndef __EXP_EMPTYVALUE_H__ +#define __EXP_EMPTYVALUE_H__ -#include "Value.h" +#include "EXP_Value.h" class CListValue; @@ -46,4 +46,4 @@ public: #endif }; -#endif /* __EMPTYVALUE_H__ */ +#endif /* __EXP_EMPTYVALUE_H__ */ diff --git a/source/gameengine/Expressions/ErrorValue.h b/source/gameengine/Expressions/EXP_ErrorValue.h index 61c72151f40..a6f91ca200a 100644 --- a/source/gameengine/Expressions/ErrorValue.h +++ b/source/gameengine/Expressions/EXP_ErrorValue.h @@ -12,14 +12,14 @@ * */ -/** \file ErrorValue.h +/** \file EXP_ErrorValue.h * \ingroup expressions */ -#ifndef __ERRORVALUE_H__ -#define __ERRORVALUE_H__ +#ifndef __EXP_ERRORVALUE_H__ +#define __EXP_ERRORVALUE_H__ -#include "Value.h" +#include "EXP_Value.h" class CErrorValue : public CPropValue { @@ -44,4 +44,4 @@ private: #endif }; -#endif /* __ERRORVALUE_H__ */ +#endif /* __EXP_ERRORVALUE_H__ */ diff --git a/source/gameengine/Expressions/Expression.h b/source/gameengine/Expressions/EXP_Expression.h index 9a4f1f93284..66a6e9476ff 100644 --- a/source/gameengine/Expressions/Expression.h +++ b/source/gameengine/Expressions/EXP_Expression.h @@ -12,14 +12,14 @@ * */ -/** \file Expression.h +/** \file EXP_Expression.h * \ingroup expressions */ -#ifndef __EXPRESSION_H__ -#define __EXPRESSION_H__ +#ifndef __EXP_EXPRESSION_H__ +#define __EXP_EXPRESSION_H__ -#include "Value.h" +#include "EXP_Value.h" //extern int gRefCountExpr; // only for debugging purposes (detect mem.leaks) @@ -146,4 +146,4 @@ protected: #endif }; -#endif /* __EXPRESSION_H__ */ +#endif /* __EXP_EXPRESSION_H__ */ diff --git a/source/gameengine/Expressions/FloatValue.h b/source/gameengine/Expressions/EXP_FloatValue.h index 379c3e951bc..3c16c57d16d 100644 --- a/source/gameengine/Expressions/FloatValue.h +++ b/source/gameengine/Expressions/EXP_FloatValue.h @@ -12,14 +12,14 @@ * */ -/** \file FloatValue.h +/** \file EXP_FloatValue.h * \ingroup expressions */ -#ifndef __FLOATVALUE_H__ -#define __FLOATVALUE_H__ +#ifndef __EXP_FLOATVALUE_H__ +#define __EXP_FLOATVALUE_H__ -#include "Value.h" +#include "EXP_Value.h" class CFloatValue : public CPropValue { @@ -55,4 +55,4 @@ protected: #endif }; -#endif /* __FLOATVALUE_H__ */ +#endif /* __EXP_FLOATVALUE_H__ */ diff --git a/source/gameengine/Expressions/KX_HashedPtr.h b/source/gameengine/Expressions/EXP_HashedPtr.h index acd9d4daafa..7c7c5f6e5ec 100644 --- a/source/gameengine/Expressions/KX_HashedPtr.h +++ b/source/gameengine/Expressions/EXP_HashedPtr.h @@ -25,19 +25,17 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file KX_HashedPtr.h +/** \file EXP_HashedPtr.h * \ingroup expressions */ -#ifndef __KX_HASHEDPTR_H__ -#define __KX_HASHEDPTR_H__ +#ifndef __EXP_HASHEDPTR_H__ +#define __EXP_HASHEDPTR_H__ #ifdef WITH_CXX_GUARDEDALLOC #include "MEM_guardedalloc.h" #endif -unsigned int KX_Hash(void *inDWord); - class CHashedPtr { void* m_valptr; @@ -58,4 +56,4 @@ public: #endif }; -#endif /* __KX_HASHEDPTR_H__ */ +#endif /* __EXP_HASHEDPTR_H__ */ diff --git a/source/gameengine/Expressions/IdentifierExpr.h b/source/gameengine/Expressions/EXP_IdentifierExpr.h index 26eb3691378..96ef3677cf3 100644 --- a/source/gameengine/Expressions/IdentifierExpr.h +++ b/source/gameengine/Expressions/EXP_IdentifierExpr.h @@ -25,14 +25,14 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file IdentifierExpr.h +/** \file EXP_IdentifierExpr.h * \ingroup expressions */ -#ifndef __IDENTIFIEREXPR_H__ -#define __IDENTIFIEREXPR_H__ +#ifndef __EXP_IDENTIFIEREXPR_H__ +#define __EXP_IDENTIFIEREXPR_H__ -#include "Expression.h" +#include "EXP_Expression.h" class CIdentifierExpr : public CExpression { @@ -56,4 +56,4 @@ public: #endif }; -#endif /* __IDENTIFIEREXPR_H__ */ +#endif /* __EXP_IDENTIFIEREXPR_H__ */ diff --git a/source/gameengine/Expressions/IfExpr.h b/source/gameengine/Expressions/EXP_IfExpr.h index 80e35471d82..43b4b8faf53 100644 --- a/source/gameengine/Expressions/IfExpr.h +++ b/source/gameengine/Expressions/EXP_IfExpr.h @@ -12,14 +12,14 @@ * */ -/** \file IfExpr.h +/** \file EXP_IfExpr.h * \ingroup expressions */ -#ifndef __IFEXPR_H__ -#define __IFEXPR_H__ +#ifndef __EXP_IFEXPR_H__ +#define __EXP_IFEXPR_H__ -#include "Expression.h" +#include "EXP_Expression.h" class CIfExpr : public CExpression { @@ -51,4 +51,4 @@ public: #endif }; -#endif /* __IFEXPR_H__ */ +#endif /* __EXP_IFEXPR_H__ */ diff --git a/source/gameengine/Expressions/InputParser.h b/source/gameengine/Expressions/EXP_InputParser.h index 50bb1ae2f6e..80471009a16 100644 --- a/source/gameengine/Expressions/InputParser.h +++ b/source/gameengine/Expressions/EXP_InputParser.h @@ -14,15 +14,15 @@ * */ -/** \file InputParser.h +/** \file EXP_InputParser.h * \ingroup expressions */ -#ifndef __INPUTPARSER_H__ -#define __INPUTPARSER_H__ +#ifndef __EXP_INPUTPARSER_H__ +#define __EXP_INPUTPARSER_H__ class CParser; -#include "Expression.h" +#include "EXP_Expression.h" class CParser @@ -114,5 +114,5 @@ private: #endif }; -#endif +#endif /* __EXP_INPUTPARSER_H__ */ diff --git a/source/gameengine/Expressions/IntValue.h b/source/gameengine/Expressions/EXP_IntValue.h index 6da975f4f7f..a1cd96a888e 100644 --- a/source/gameengine/Expressions/IntValue.h +++ b/source/gameengine/Expressions/EXP_IntValue.h @@ -12,15 +12,15 @@ * */ -/** \file IntValue.h +/** \file EXP_IntValue.h * \ingroup expressions */ -#ifndef __INTVALUE_H__ -#define __INTVALUE_H__ +#ifndef __EXP_INTVALUE_H__ +#define __EXP_INTVALUE_H__ -#include "Value.h" +#include "EXP_Value.h" typedef long long cInt; @@ -70,4 +70,4 @@ private: #endif }; -#endif /* __INTVALUE_H__ */ +#endif /* __EXP_INTVALUE_H__ */ diff --git a/source/gameengine/Expressions/ListValue.h b/source/gameengine/Expressions/EXP_ListValue.h index bb188179836..f5421066f62 100644 --- a/source/gameengine/Expressions/ListValue.h +++ b/source/gameengine/Expressions/EXP_ListValue.h @@ -12,14 +12,14 @@ * */ -/** \file ListValue.h +/** \file EXP_ListValue.h * \ingroup expressions */ -#ifndef __LISTVALUE_H__ -#define __LISTVALUE_H__ +#ifndef __EXP_LISTVALUE_H__ +#define __EXP_LISTVALUE_H__ -#include "Value.h" +#include "EXP_Value.h" class CListValue : public CPropValue { @@ -88,5 +88,5 @@ private: bool m_bReleaseContents; }; -#endif /* __LISTVALUE_H__ */ +#endif /* __EXP_LISTVALUE_H__ */ diff --git a/source/gameengine/Expressions/Operator1Expr.h b/source/gameengine/Expressions/EXP_Operator1Expr.h index 3dd76f773f2..9a05ce9c0c4 100644 --- a/source/gameengine/Expressions/Operator1Expr.h +++ b/source/gameengine/Expressions/EXP_Operator1Expr.h @@ -12,14 +12,14 @@ * */ -/** \file Operator1Expr.h +/** \file EXP_Operator1Expr.h * \ingroup expressions */ -#ifndef __OPERATOR1EXPR_H__ -#define __OPERATOR1EXPR_H__ +#ifndef __EXP_OPERATOR1EXPR_H__ +#define __EXP_OPERATOR1EXPR_H__ -#include "Expression.h" +#include "EXP_Expression.h" class COperator1Expr : public CExpression { @@ -56,4 +56,4 @@ private: #endif }; -#endif /* __OPERATOR1EXPR_H__ */ +#endif /* __EXP_OPERATOR1EXPR_H__ */ diff --git a/source/gameengine/Expressions/Operator2Expr.h b/source/gameengine/Expressions/EXP_Operator2Expr.h index 8c30b7cd634..cd7a492fde0 100644 --- a/source/gameengine/Expressions/Operator2Expr.h +++ b/source/gameengine/Expressions/EXP_Operator2Expr.h @@ -12,16 +12,16 @@ * */ -/** \file Operator2Expr.h +/** \file EXP_Operator2Expr.h * \ingroup expressions */ -#ifndef __OPERATOR2EXPR_H__ -#define __OPERATOR2EXPR_H__ +#ifndef __EXP_OPERATOR2EXPR_H__ +#define __EXP_OPERATOR2EXPR_H__ -#include "Expression.h" -#include "Value.h" // Added by ClassView +#include "EXP_Expression.h" +#include "EXP_Value.h" // Added by ClassView class COperator2Expr : public CExpression { @@ -62,5 +62,5 @@ private: #endif }; -#endif /* __OPERATOR2EXPR_H__ */ +#endif /* __EXP_OPERATOR2EXPR_H__ */ diff --git a/source/gameengine/Expressions/PyObjectPlus.h b/source/gameengine/Expressions/EXP_PyObjectPlus.h index e2e7c248795..dd612a08494 100644 --- a/source/gameengine/Expressions/PyObjectPlus.h +++ b/source/gameengine/Expressions/EXP_PyObjectPlus.h @@ -25,12 +25,12 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file PyObjectPlus.h +/** \file EXP_PyObjectPlus.h * \ingroup expressions */ -#ifndef __PYOBJECTPLUS_H__ -#define __PYOBJECTPLUS_H__ +#ifndef __EXP_PYOBJECTPLUS_H__ +#define __EXP_PYOBJECTPLUS_H__ /* for now keep weakrefs optional */ #define USE_WEAKREFS @@ -40,7 +40,7 @@ #error Must be compiled with C++ #endif -#include "KX_Python.h" +#include "EXP_Python.h" #include "STR_String.h" #include "MT_Vector3.h" #include "SG_QList.h" @@ -65,21 +65,21 @@ typedef struct { #define ShowDeprecationWarning(old_way, new_way) \ { \ static WarnLink wlink = {false, NULL}; \ - if ((m_ignore_deprecation_warnings || wlink.warn_done)==0) \ + if ((PyObjectPlus::m_ignore_deprecation_warnings || wlink.warn_done)==0) \ { \ - ShowDeprecationWarning_func(old_way, new_way); \ + PyObjectPlus::ShowDeprecationWarning_func(old_way, new_way); \ \ - WarnLink *wlink_last= GetDeprecationWarningLinkLast(); \ + WarnLink *wlink_last= PyObjectPlus::GetDeprecationWarningLinkLast(); \ wlink.warn_done = true; \ wlink.link = NULL; \ \ if(wlink_last) { \ wlink_last->link= (void *)&(wlink); \ - SetDeprecationWarningLinkLast(&(wlink)); \ + PyObjectPlus::SetDeprecationWarningLinkLast(&(wlink)); \ } \ else { \ - SetDeprecationWarningFirst(&(wlink)); \ - SetDeprecationWarningLinkLast(&(wlink)); \ + PyObjectPlus::SetDeprecationWarningFirst(&(wlink)); \ + PyObjectPlus::SetDeprecationWarningLinkLast(&(wlink)); \ } \ } \ } \ @@ -111,6 +111,8 @@ typedef struct PyObjectPlus_Proxy { /* Opposite of BGE_PROXY_REF */ #define BGE_PROXY_FROM_REF(_self) (((PyObjectPlus *)_self)->GetProxy()) +/* Same as 'BGE_PROXY_REF' but doesn't incref. */ +#define BGE_PROXY_FROM_REF_BORROW(_self) _bge_proxy_from_ref_borrow((void *)_self) // This must be the first line of each @@ -631,6 +633,16 @@ public: #ifdef WITH_PYTHON PyObject *PyUnicode_From_STR_String(const STR_String& str); + +inline PyObject *_bge_proxy_from_ref_borrow(void *self_v) +{ + PyObject *self_proxy = BGE_PROXY_FROM_REF(self_v); + /* this is typically _very_ bad practice, + * however we know the proxy is owned by 'self_v' */ + self_proxy->ob_refcnt--; + return self_proxy; +} + #endif -#endif /* __PYOBJECTPLUS_H__ */ +#endif /* __EXP_PYOBJECTPLUS_H__ */ diff --git a/source/gameengine/Expressions/KX_Python.h b/source/gameengine/Expressions/EXP_Python.h index 62dd9a13dd4..f904151085e 100644 --- a/source/gameengine/Expressions/KX_Python.h +++ b/source/gameengine/Expressions/EXP_Python.h @@ -25,12 +25,12 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file KX_Python.h +/** \file EXP_Python.h * \ingroup expressions */ -#ifndef __KX_PYTHON_H__ -#define __KX_PYTHON_H__ +#ifndef __EXP_PYTHON_H__ +#define __EXP_PYTHON_H__ //#define USE_DL_EXPORT @@ -79,4 +79,4 @@ #undef toupper #endif -#endif /* __KX_PYTHON_H__ */ +#endif /* __EXP_PYTHON_H__ */ diff --git a/source/gameengine/Expressions/EXP_PythonCallBack.h b/source/gameengine/Expressions/EXP_PythonCallBack.h new file mode 100644 index 00000000000..f0cbcac0c6f --- /dev/null +++ b/source/gameengine/Expressions/EXP_PythonCallBack.h @@ -0,0 +1,40 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Porteries Tristan. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file EXP_PythonCallBack.h + * \ingroup expressions + */ + +#ifndef __EXP_PYTHON_CALLBACK_H__ +#define __EXP_PYTHON_CALLBACK_H__ + +#include "EXP_Python.h" + +/** Execute each functions with at least one argument + * \param functionlist The python list which contains callbacks. + * \param arglist The first item in the tuple to execute callbacks (can be NULL for no arguments). + * \param minargcount The minimum of quantity of arguments possible. + * \param maxargcount The maximum of quantity of arguments possible. + */ +void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount); + +#endif // __EXP_PYTHON_CALLBACK_H__ diff --git a/source/gameengine/Expressions/StringValue.h b/source/gameengine/Expressions/EXP_StringValue.h index cb60600ad88..ca59ebf1f82 100644 --- a/source/gameengine/Expressions/StringValue.h +++ b/source/gameengine/Expressions/EXP_StringValue.h @@ -12,14 +12,14 @@ * */ -/** \file StringValue.h +/** \file EXP_StringValue.h * \ingroup expressions */ -#ifndef __STRINGVALUE_H__ -#define __STRINGVALUE_H__ +#ifndef __EXP_STRINGVALUE_H__ +#define __EXP_STRINGVALUE_H__ -#include "Value.h" +#include "EXP_Value.h" class CStringValue : public CPropValue { @@ -58,4 +58,4 @@ private: #endif }; -#endif /* __STRINGVALUE_H__ */ +#endif /* __EXP_STRINGVALUE_H__ */ diff --git a/source/gameengine/Expressions/Value.h b/source/gameengine/Expressions/EXP_Value.h index c7e9a40a059..014fc59405f 100644 --- a/source/gameengine/Expressions/Value.h +++ b/source/gameengine/Expressions/EXP_Value.h @@ -12,12 +12,12 @@ * */ -/** \file Value.h +/** \file EXP_Value.h * \ingroup expressions */ -#ifndef __VALUE_H__ -#define __VALUE_H__ +#ifndef __EXP_VALUE_H__ +#define __EXP_VALUE_H__ #ifdef _MSC_VER # pragma warning (disable:4786) @@ -159,7 +159,7 @@ public: }; -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #ifdef WITH_PYTHON #include "object.h" #endif @@ -429,4 +429,4 @@ protected: #endif }; -#endif /* __VALUE_H__ */ +#endif /* __EXP_VALUE_H__ */ diff --git a/source/gameengine/Expressions/VectorValue.h b/source/gameengine/Expressions/EXP_VectorValue.h index 717fa68f6dc..d87d5097156 100644 --- a/source/gameengine/Expressions/VectorValue.h +++ b/source/gameengine/Expressions/EXP_VectorValue.h @@ -12,14 +12,14 @@ * */ -/** \file VectorValue.h +/** \file EXP_VectorValue.h * \ingroup expressions */ -#ifndef __VECTORVALUE_H__ -#define __VECTORVALUE_H__ +#ifndef __EXP_VECTORVALUE_H__ +#define __EXP_VECTORVALUE_H__ -#include "Value.h" +#include "EXP_Value.h" #define KX_X 0 #define KX_Y 1 @@ -91,4 +91,4 @@ protected: #endif }; -#endif /* __VECTORVALUE_H__ */ +#endif /* __EXP_VECTORVALUE_H__ */ diff --git a/source/gameengine/Expressions/VoidValue.h b/source/gameengine/Expressions/EXP_VoidValue.h index 4f74910dd8a..8b2c29488d7 100644 --- a/source/gameengine/Expressions/VoidValue.h +++ b/source/gameengine/Expressions/EXP_VoidValue.h @@ -27,14 +27,14 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file VoidValue.h +/** \file EXP_VoidValue.h * \ingroup expressions */ -#ifndef __VOIDVALUE_H__ -#define __VOIDVALUE_H__ +#ifndef __EXP_VOIDVALUE_H__ +#define __EXP_VOIDVALUE_H__ -#include "Value.h" +#include "EXP_Value.h" // // Void value, used to transport *any* type of data @@ -78,4 +78,4 @@ public: #endif }; -#endif /* __VOIDVALUE_H__ */ +#endif /* __EXP_VOIDVALUE_H__ */ diff --git a/source/gameengine/Expressions/SConscript b/source/gameengine/Expressions/SConscript index 48102e5ba3c..b66d36c2080 100644 --- a/source/gameengine/Expressions/SConscript +++ b/source/gameengine/Expressions/SConscript @@ -27,7 +27,7 @@ Import ('env') -sources = env.Glob('*.cpp') +sources = env.Glob('intern/*.cpp') incs = [ '.', diff --git a/source/gameengine/Expressions/BoolValue.cpp b/source/gameengine/Expressions/intern/BoolValue.cpp index 9ff53395056..1523a9212ba 100644 --- a/source/gameengine/Expressions/BoolValue.cpp +++ b/source/gameengine/Expressions/intern/BoolValue.cpp @@ -16,10 +16,10 @@ * */ -#include "BoolValue.h" -#include "StringValue.h" -#include "ErrorValue.h" -#include "VoidValue.h" +#include "EXP_BoolValue.h" +#include "EXP_StringValue.h" +#include "EXP_ErrorValue.h" +#include "EXP_VoidValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/ConstExpr.cpp b/source/gameengine/Expressions/intern/ConstExpr.cpp index c41cf5a54f5..597427ecfe5 100644 --- a/source/gameengine/Expressions/ConstExpr.cpp +++ b/source/gameengine/Expressions/intern/ConstExpr.cpp @@ -16,9 +16,9 @@ * */ -#include "Value.h" // for precompiled header -#include "ConstExpr.h" -#include "VectorValue.h" +#include "EXP_Value.h" // for precompiled header +#include "EXP_ConstExpr.h" +#include "EXP_VectorValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/EmptyValue.cpp b/source/gameengine/Expressions/intern/EmptyValue.cpp index f8e72181ed7..9227626777d 100644 --- a/source/gameengine/Expressions/EmptyValue.cpp +++ b/source/gameengine/Expressions/intern/EmptyValue.cpp @@ -16,13 +16,13 @@ * */ -#include "EmptyValue.h" -#include "IntValue.h" -#include "FloatValue.h" -#include "StringValue.h" -#include "ErrorValue.h" -#include "ListValue.h" -#include "VoidValue.h" +#include "EXP_EmptyValue.h" +#include "EXP_IntValue.h" +#include "EXP_FloatValue.h" +#include "EXP_StringValue.h" +#include "EXP_ErrorValue.h" +#include "EXP_ListValue.h" +#include "EXP_VoidValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/ErrorValue.cpp b/source/gameengine/Expressions/intern/ErrorValue.cpp index 46e09b9073f..c03ceb88073 100644 --- a/source/gameengine/Expressions/ErrorValue.cpp +++ b/source/gameengine/Expressions/intern/ErrorValue.cpp @@ -15,7 +15,7 @@ * */ -#include "ErrorValue.h" +#include "EXP_ErrorValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/Expression.cpp b/source/gameengine/Expressions/intern/Expression.cpp index 2428df977d3..6a98a15aa12 100644 --- a/source/gameengine/Expressions/Expression.cpp +++ b/source/gameengine/Expressions/intern/Expression.cpp @@ -15,8 +15,8 @@ * */ -#include "Expression.h" -#include "ErrorValue.h" +#include "EXP_Expression.h" +#include "EXP_ErrorValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/FloatValue.cpp b/source/gameengine/Expressions/intern/FloatValue.cpp index 4d6f3f467eb..0f86a429d81 100644 --- a/source/gameengine/Expressions/FloatValue.cpp +++ b/source/gameengine/Expressions/intern/FloatValue.cpp @@ -15,12 +15,12 @@ * */ -#include "FloatValue.h" -#include "IntValue.h" -#include "StringValue.h" -#include "BoolValue.h" -#include "ErrorValue.h" -#include "VoidValue.h" +#include "EXP_FloatValue.h" +#include "EXP_IntValue.h" +#include "EXP_StringValue.h" +#include "EXP_BoolValue.h" +#include "EXP_ErrorValue.h" +#include "EXP_VoidValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/KX_HashedPtr.cpp b/source/gameengine/Expressions/intern/HashedPtr.cpp index bd42892cc8d..005ac16b231 100644 --- a/source/gameengine/Expressions/KX_HashedPtr.cpp +++ b/source/gameengine/Expressions/intern/HashedPtr.cpp @@ -30,16 +30,22 @@ */ -#include "KX_HashedPtr.h" +#include "EXP_HashedPtr.h" -unsigned int KX_Hash(void *inDWord) + +CHashedPtr::CHashedPtr(void* val) : m_valptr(val) +{ +} + + +unsigned int CHashedPtr::hash() const { #if defined(_WIN64) && !defined(FREE_WINDOWS64) - unsigned __int64 key = (unsigned __int64)inDWord; + unsigned __int64 key = (unsigned __int64)m_valptr; #elif defined(FREE_WINDOWS64) - unsigned long long key = (unsigned long long)inDWord; + unsigned long long key = (unsigned long long)m_valptr; #else - unsigned long key = (unsigned long)inDWord; + unsigned long key = (unsigned long)m_valptr; #endif key += ~(key << 16); @@ -51,15 +57,3 @@ unsigned int KX_Hash(void *inDWord) return (unsigned int)(key & 0xffffffff); } - - -CHashedPtr::CHashedPtr(void* val) : m_valptr(val) -{ -} - - - -unsigned int CHashedPtr::hash() const -{ - return KX_Hash(m_valptr); -} diff --git a/source/gameengine/Expressions/IdentifierExpr.cpp b/source/gameengine/Expressions/intern/IdentifierExpr.cpp index c9e053574cd..8fbbf41cd63 100644 --- a/source/gameengine/Expressions/IdentifierExpr.cpp +++ b/source/gameengine/Expressions/intern/IdentifierExpr.cpp @@ -30,7 +30,7 @@ */ -#include "IdentifierExpr.h" +#include "EXP_IdentifierExpr.h" CIdentifierExpr::CIdentifierExpr(const STR_String& identifier,CValue* id_context) :m_identifier(identifier) diff --git a/source/gameengine/Expressions/IfExpr.cpp b/source/gameengine/Expressions/intern/IfExpr.cpp index 152ca8704ce..b4e2fe7315b 100644 --- a/source/gameengine/Expressions/IfExpr.cpp +++ b/source/gameengine/Expressions/intern/IfExpr.cpp @@ -15,10 +15,10 @@ * */ -#include "IfExpr.h" -#include "EmptyValue.h" -#include "ErrorValue.h" -#include "BoolValue.h" +#include "EXP_IfExpr.h" +#include "EXP_EmptyValue.h" +#include "EXP_ErrorValue.h" +#include "EXP_BoolValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/InputParser.cpp b/source/gameengine/Expressions/intern/InputParser.cpp index 4ba3585455b..e8cc7fba284 100644 --- a/source/gameengine/Expressions/InputParser.cpp +++ b/source/gameengine/Expressions/intern/InputParser.cpp @@ -19,23 +19,23 @@ #include "MT_assert.h" -#include "Value.h" -#include "InputParser.h" -#include "ErrorValue.h" -#include "IntValue.h" -#include "StringValue.h" -#include "FloatValue.h" -#include "BoolValue.h" -#include "EmptyValue.h" -#include "ConstExpr.h" -#include "Operator2Expr.h" -#include "Operator1Expr.h" -#include "IdentifierExpr.h" +#include "EXP_Value.h" +#include "EXP_InputParser.h" +#include "EXP_ErrorValue.h" +#include "EXP_IntValue.h" +#include "EXP_StringValue.h" +#include "EXP_FloatValue.h" +#include "EXP_BoolValue.h" +#include "EXP_EmptyValue.h" +#include "EXP_ConstExpr.h" +#include "EXP_Operator2Expr.h" +#include "EXP_Operator1Expr.h" +#include "EXP_IdentifierExpr.h" // this is disable at the moment, I expected a memleak from it, but the error-cleanup was the reason // well, looks we don't need it anyway, until maybe the Curved Surfaces are integrated into CSG // cool things like (IF(LOD==1,CCurvedValue,IF(LOD==2,CCurvedValue2)) etc... -#include "IfExpr.h" +#include "EXP_IfExpr.h" #if (defined(WIN32) || defined(WIN64)) && !defined(FREE_WINDOWS) #define strcasecmp _stricmp diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/intern/IntValue.cpp index 82d2e94dbb0..25aff5b32ab 100644 --- a/source/gameengine/Expressions/IntValue.cpp +++ b/source/gameengine/Expressions/intern/IntValue.cpp @@ -17,12 +17,12 @@ #include <stdio.h> -#include "IntValue.h" -#include "ErrorValue.h" -#include "FloatValue.h" -#include "BoolValue.h" -#include "StringValue.h" -#include "VoidValue.h" +#include "EXP_IntValue.h" +#include "EXP_ErrorValue.h" +#include "EXP_FloatValue.h" +#include "EXP_BoolValue.h" +#include "EXP_StringValue.h" +#include "EXP_VoidValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/ListValue.cpp b/source/gameengine/Expressions/intern/ListValue.cpp index 75e3b490505..557ce7be300 100644 --- a/source/gameengine/Expressions/ListValue.cpp +++ b/source/gameengine/Expressions/intern/ListValue.cpp @@ -19,11 +19,11 @@ #include <stdio.h> -#include "ListValue.h" -#include "StringValue.h" -#include "VoidValue.h" +#include "EXP_ListValue.h" +#include "EXP_StringValue.h" +#include "EXP_VoidValue.h" #include <algorithm> -#include "BoolValue.h" +#include "EXP_BoolValue.h" #include "BLI_sys_types.h" /* for intptr_t support */ @@ -432,7 +432,7 @@ static PyObject *listvalue_buffer_concat(PyObject *self, PyObject *other) for (i=0;i<numitems;i++) { - listitemval = listval->ConvertPythonToValue(PyList_GetItem(other,i), true, "cList + pyList: CListValue, "); + listitemval = listval->ConvertPythonToValue(PyList_GET_ITEM(other, i), true, "cList + pyList: CListValue, "); if (listitemval) { listval_new->SetValue(i+numitems_orig, listitemval); @@ -583,7 +583,8 @@ PyObject *CListValue::Pyappend(PyObject *value) 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"); + PyErr_SetString(PyExc_TypeError, + "CList.append(i): internal values can't be modified"); return NULL; } @@ -594,6 +595,12 @@ PyObject *CListValue::Pyappend(PyObject *value) PyObject *CListValue::Pyreverse() { + if (!BGE_PROXY_PYOWNS(m_proxy)) { + PyErr_SetString(PyExc_TypeError, + "CList.reverse(): internal values can't be modified"); + return NULL; + } + std::reverse(m_pValueArray.begin(),m_pValueArray.end()); Py_RETURN_NONE; } diff --git a/source/gameengine/Expressions/Operator1Expr.cpp b/source/gameengine/Expressions/intern/Operator1Expr.cpp index b985f76825d..add0376f487 100644 --- a/source/gameengine/Expressions/Operator1Expr.cpp +++ b/source/gameengine/Expressions/intern/Operator1Expr.cpp @@ -15,8 +15,8 @@ * */ -#include "Operator1Expr.h" -#include "EmptyValue.h" +#include "EXP_Operator1Expr.h" +#include "EXP_EmptyValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/Operator2Expr.cpp b/source/gameengine/Expressions/intern/Operator2Expr.cpp index b03d00e7f77..0a7f30b8cc8 100644 --- a/source/gameengine/Expressions/Operator2Expr.cpp +++ b/source/gameengine/Expressions/intern/Operator2Expr.cpp @@ -19,9 +19,9 @@ // have to do the trick // when expression is cached, there will be a call to UpdateCalc() instead of Calc() -#include "Operator2Expr.h" -#include "StringValue.h" -#include "VoidValue.h" +#include "EXP_Operator2Expr.h" +#include "EXP_StringValue.h" +#include "EXP_VoidValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/intern/PyObjectPlus.cpp index c025d439fc0..de45bee76a7 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/intern/PyObjectPlus.cpp @@ -47,7 +47,7 @@ #include <stdlib.h> #include <stddef.h> -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "STR_String.h" #include "MT_Vector3.h" #include "MEM_guardedalloc.h" @@ -80,7 +80,7 @@ void PyObjectPlus::ProcessReplica() } /* 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 + * it hasn't 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, @@ -148,12 +148,18 @@ PyObject *PyObjectPlus::py_base_repr(PyObject *self) // This should be the ent PyObject *PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { PyTypeObject *base_type; - PyObjectPlus_Proxy *base = NULL; - if (!PyArg_ParseTuple(args, "O:Base PyObjectPlus", &base)) + /* one or more args is needed */ + if (!PyTuple_GET_SIZE(args)) { + PyErr_SetString(PyExc_TypeError, + "Expected at least one argument"); return NULL; + } + + PyObjectPlus_Proxy *base = (PyObjectPlus_Proxy *)PyTuple_GET_ITEM(args, 0); - /* the 'base' PyObject may be subclassed (multiple times even) + /** + * the 'base' PyObject may be subclassed (multiple times even) * we need to find the first C++ defined class to check 'type' * is a subclass of the base arguments type. * @@ -162,12 +168,13 @@ PyObject *PyObjectPlus::py_base_new(PyTypeObject *type, PyObject *args, PyObject * eg. * * # CustomOb is called 'type' in this C code + * \code{.py} * class CustomOb(GameTypes.KX_GameObject): * pass * * # this calls py_base_new(...), the type of 'CustomOb' is checked to be a subclass of the 'cont.owner' type * ob = CustomOb(cont.owner) - * + * \endcode * */ base_type= Py_TYPE(base); while (base_type && !BGE_PROXY_CHECK_TYPE(base_type)) @@ -418,7 +425,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * return NULL; } #ifdef USE_MATHUTILS - return Vector_CreatePyObject(val, attrdef->m_imax, Py_NEW, NULL); + return Vector_CreatePyObject(val, attrdef->m_imax, NULL); #else PyObject *resultlist = PyList_New(attrdef->m_imax); for (unsigned int i=0; i<attrdef->m_imax; i++) @@ -435,7 +442,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * return NULL; } #ifdef USE_MATHUTILS - return Matrix_CreatePyObject(val, attrdef->m_imin, attrdef->m_imax, Py_WRAP, NULL); + return Matrix_CreatePyObject_wrap(val, attrdef->m_imin, attrdef->m_imax, NULL); #else PyObject *collist = PyList_New(attrdef->m_imin); for (unsigned int i=0; i<attrdef->m_imin; i++) @@ -458,7 +465,7 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * #ifdef USE_MATHUTILS float fval[3]; val->getValue(fval); - return Vector_CreatePyObject(fval, 3, Py_NEW, NULL); + return Vector_CreatePyObject(fval, 3, NULL); #else PyObject *resultlist = PyList_New(3); for (unsigned int i=0; i<3; i++) diff --git a/source/gameengine/Expressions/intern/PythonCallBack.cpp b/source/gameengine/Expressions/intern/PythonCallBack.cpp new file mode 100644 index 00000000000..3fb84569eca --- /dev/null +++ b/source/gameengine/Expressions/intern/PythonCallBack.cpp @@ -0,0 +1,119 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Porteries Tristan. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file gameengine/Expressions/intern/PythonCallBack.cpp + * \ingroup expressions + */ + +#include "EXP_PythonCallBack.h" +#include <iostream> +#include <stdarg.h> + +#include "BLI_alloca.h" + +/** Check if a python value is a function and have the correct number of arguments. + * \param value The python value to check. + * \param minargcount The minimum of arguments possible. + * \param maxargcount The maximum of arguments possible. + * \param r_argcount The number of argument of this function, this variable will be + * changed in the function. + */ +static PyObject *CheckPythonFunction(PyObject *value, unsigned int minargcount, unsigned int maxargcount, unsigned int &r_argcount) +{ + if (PyMethod_Check(value)) { + PyCodeObject *code = ((PyCodeObject *)PyFunction_GET_CODE(PyMethod_GET_FUNCTION(value))); + // *args support + r_argcount = (code->co_flags & CO_VARARGS) ? maxargcount : (code->co_argcount - 1); + } + else if (PyFunction_Check(value)) { + PyCodeObject *code = ((PyCodeObject *)PyFunction_GET_CODE(value)); + // *args support + r_argcount = (code->co_flags & CO_VARARGS) ? maxargcount : code->co_argcount; + } + else { // is not a methode or a function + PyErr_Format(PyExc_TypeError, "items must be functions or methodes, not %s", + Py_TYPE(value)->tp_name); + return NULL; + } + + if (r_argcount < minargcount || r_argcount > maxargcount) { + // wrong number of arguments + PyErr_Format(PyExc_TypeError, "methode or function (%s) has invalid number of arguments (%i) must be between %i and %i", + Py_TYPE(value)->tp_name, r_argcount, minargcount, maxargcount); + return NULL; + } + + return value; +} + +/** Create a python tuple to call a python function + * \param argcount The lenght of the tuple. + * \param arglist The fully list of python arguments [size >= argcount]. + */ +static PyObject *CreatePythonTuple(unsigned int argcount, PyObject **arglist) +{ + PyObject *tuple = PyTuple_New(argcount); + + for (unsigned int i = 0; i < argcount; ++i) { + PyObject *item = arglist[i]; + // increment reference and copy it in a new tuple + Py_INCREF(item); + PyTuple_SET_ITEM(tuple, i, item); + } + + return tuple; +} + +void RunPythonCallBackList(PyObject *functionlist, PyObject **arglist, unsigned int minargcount, unsigned int maxargcount) +{ + unsigned int size = PyList_Size(functionlist); + PyObject **argTuples = (PyObject **)BLI_array_alloca(argTuples, maxargcount - minargcount + 1); + memset(argTuples, 0, sizeof(PyObject *) * (maxargcount - minargcount + 1)); + + for (unsigned int i = 0; i < size; ++i) { + unsigned int funcargcount = 0; + + PyObject *item = PyList_GET_ITEM(functionlist, i); + PyObject *func = CheckPythonFunction(item, minargcount, maxargcount, funcargcount); + if (!func) { // this item fails the check + PyErr_Print(); + PyErr_Clear(); + continue; + } + + // get correct argument tuple. + PyObject *tuple = argTuples[funcargcount - minargcount]; + if (!tuple) + argTuples[funcargcount - minargcount] = tuple = CreatePythonTuple(funcargcount, arglist); + + PyObject *ret = PyObject_Call(func, tuple, NULL); + if (!ret) { // if ret is NULL this seems that the function doesn't work ! + PyErr_Print(); + PyErr_Clear(); + } + else + Py_DECREF(ret); + } + + for (unsigned int i = 0; i <= (maxargcount - minargcount); ++i) + Py_XDECREF(argTuples[i]); +} diff --git a/source/gameengine/Expressions/StringValue.cpp b/source/gameengine/Expressions/intern/StringValue.cpp index 098949c9d7b..ddf61dc441c 100644 --- a/source/gameengine/Expressions/StringValue.cpp +++ b/source/gameengine/Expressions/intern/StringValue.cpp @@ -15,10 +15,10 @@ * */ -#include "StringValue.h" -#include "BoolValue.h" -#include "ErrorValue.h" -#include "VoidValue.h" +#include "EXP_StringValue.h" +#include "EXP_BoolValue.h" +#include "EXP_ErrorValue.h" +#include "EXP_VoidValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction diff --git a/source/gameengine/Expressions/Value.cpp b/source/gameengine/Expressions/intern/Value.cpp index bdef2dbd5b0..f8796a76e76 100644 --- a/source/gameengine/Expressions/Value.cpp +++ b/source/gameengine/Expressions/intern/Value.cpp @@ -17,15 +17,15 @@ * purpose. It is provided "as is" without express or implied warranty. * */ -#include "Value.h" -#include "BoolValue.h" -#include "FloatValue.h" -#include "IntValue.h" -#include "VectorValue.h" -#include "VoidValue.h" -#include "StringValue.h" -#include "ErrorValue.h" -#include "ListValue.h" +#include "EXP_Value.h" +#include "EXP_BoolValue.h" +#include "EXP_FloatValue.h" +#include "EXP_IntValue.h" +#include "EXP_VectorValue.h" +#include "EXP_VoidValue.h" +#include "EXP_StringValue.h" +#include "EXP_ErrorValue.h" +#include "EXP_ListValue.h" ////////////////////////////////////////////////////////////////////// // Construction/Destruction @@ -568,7 +568,7 @@ CValue *CValue::ConvertPythonToValue(PyObject *pyobj, const bool do_type_excepti Py_ssize_t numitems = PyList_GET_SIZE(pyobj); for (i=0;i<numitems;i++) { - PyObject *listitem = PyList_GetItem(pyobj,i); /* borrowed ref */ + PyObject *listitem = PyList_GET_ITEM(pyobj,i); /* borrowed ref */ CValue* listitemval = ConvertPythonToValue(listitem, error_prefix); if (listitemval) { diff --git a/source/gameengine/Expressions/VectorValue.cpp b/source/gameengine/Expressions/intern/VectorValue.cpp index 6931ba2aa76..a3d44116317 100644 --- a/source/gameengine/Expressions/VectorValue.cpp +++ b/source/gameengine/Expressions/intern/VectorValue.cpp @@ -19,12 +19,12 @@ # pragma warning (disable:4786) #endif -#include "Value.h" -#include "VectorValue.h" -#include "ErrorValue.h" +#include "EXP_Value.h" +#include "EXP_VectorValue.h" +#include "EXP_ErrorValue.h" //#include "MatrixValue.h" -#include "VoidValue.h" -#include "StringValue.h" +#include "EXP_VoidValue.h" +#include "EXP_StringValue.h" //#include "FactoryManager.h" diff --git a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp index 6e379c91d0c..b03570e3c28 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp @@ -41,6 +41,10 @@ #include "BLI_path_util.h" +#ifdef WITH_SDL +# define SDL_CHECK(x) ((x) != (void *)0) +#endif + SCA_Joystick::SCA_Joystick(short int index) : m_joyindex(index), @@ -82,6 +86,9 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) #ifndef WITH_SDL return NULL; #else /* WITH_SDL */ + if (!SDL_CHECK(SDL_InitSubSystem)) { + return NULL; + } if (joyindex < 0 || joyindex >= JOYINDEX_MAX) { JOYSTICK_ECHO("Error-invalid joystick index: " << joyindex); return NULL; @@ -104,7 +111,11 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) char *videodriver = getenv("SDL_VIDEODRIVER"); BLI_setenv("SDL_VIDEODRIVER", "dummy"); +#if SDL_VERSION_ATLEAST(2, 0, 0) + int success = (SDL_InitSubSystem(SDL_INIT_JOYSTICK) != -1 ); +#else int success = (SDL_InitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO) != -1 ); +#endif BLI_setenv("SDL_VIDEODRIVER", videodriver); # endif @@ -116,7 +127,7 @@ SCA_Joystick *SCA_Joystick::GetInstance( short int joyindex ) m_joynum = SDL_NumJoysticks(); - for (i=0; i<JOYINDEX_MAX; i++) { + for (i = 0; i < m_joynum; i++) { m_instance[i] = new SCA_Joystick(i); m_instance[i]->CreateJoystickDevice(); } @@ -135,8 +146,10 @@ void SCA_Joystick::ReleaseInstance() if (--m_refCount == 0) { #ifdef WITH_SDL - int i; - for (i=0; i<JOYINDEX_MAX; i++) { + if (!SDL_CHECK(SDL_QuitSubSystem)) { + return; + } + for (int i = 0; i < m_joynum; i++) { if (m_instance[i]) { m_instance[i]->DestroyJoystickDevice(); delete m_instance[i]; @@ -147,11 +160,11 @@ void SCA_Joystick::ReleaseInstance() /* The video subsystem is required for joystick input to work. However, * when GHOST is running under SDL, video is freed elsewhere. * Do this once only. */ -# ifdef WITH_GHOST_SDL +#if SDL_VERSION_ATLEAST(2, 0, 0) SDL_QuitSubSystem(SDL_INIT_JOYSTICK); -# else +#else SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_VIDEO); -# endif +#endif #endif /* WITH_SDL */ } } @@ -191,6 +204,9 @@ bool SCA_Joystick::aAxisIsPositive(int axis_single) bool SCA_Joystick::aAnyButtonPressIsPositive(void) { #ifdef WITH_SDL + if (!SDL_CHECK(SDL_JoystickGetButton)) { + return 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++) @@ -206,7 +222,7 @@ bool SCA_Joystick::aButtonPressIsPositive(int button) return false; #else bool result; - SDL_JoystickGetButton(m_private->m_joystick, button)? result = true:result = false; + result = SDL_CHECK(SDL_JoystickGetButton) && SDL_JoystickGetButton(m_private->m_joystick, button); return result; #endif } @@ -218,7 +234,7 @@ bool SCA_Joystick::aButtonReleaseIsPositive(int button) return false; #else bool result; - SDL_JoystickGetButton(m_private->m_joystick, button)? result = false : result = true; + result = !(SDL_CHECK(SDL_JoystickGetButton) && SDL_JoystickGetButton(m_private->m_joystick, button)); return result; #endif } @@ -253,7 +269,7 @@ bool SCA_Joystick::CreateJoystickDevice(void) m_axismax = m_buttonmax = m_hatmax = 0; return false; #else /* WITH_SDL */ - if (m_isinit == false) { + if (m_isinit == false && SDL_CHECK(SDL_JoystickOpen)) { if (m_joyindex>=m_joynum) { /* don't print a message, because this is done anyway */ //JOYSTICK_ECHO("Joystick-Error: " << SDL_NumJoysticks() << " avaiable joystick(s)"); @@ -293,9 +309,9 @@ void SCA_Joystick::DestroyJoystickDevice(void) #ifdef WITH_SDL if (m_isinit) { #if SDL_VERSION_ATLEAST(2, 0, 0) - if (SDL_JoystickGetAttached(m_private->m_joystick)) + if (SDL_CHECK(SDL_JoystickGetAttached) && SDL_JoystickGetAttached(m_private->m_joystick)) #else - if (SDL_JoystickOpened(m_joyindex)) + if (SDL_CHECK(SDL_JoystickOpened) && SDL_JoystickOpened(m_joyindex)) #endif { JOYSTICK_ECHO("Closing-joystick " << m_joyindex); @@ -309,13 +325,16 @@ void SCA_Joystick::DestroyJoystickDevice(void) int SCA_Joystick::Connected(void) { #ifdef WITH_SDL - if (m_isinit + if (m_isinit && #if SDL_VERSION_ATLEAST(2, 0, 0) - && SDL_JoystickGetAttached(m_private->m_joystick)) + SDL_CHECK(SDL_JoystickGetAttached) && SDL_JoystickGetAttached(m_private->m_joystick) #else - && SDL_JoystickOpened(m_joyindex)) + SDL_CHECK(SDL_JoystickOpened) && SDL_JoystickOpened(m_joyindex) #endif + ) + { return 1; + } #endif return 0; } @@ -353,9 +372,9 @@ const char *SCA_Joystick::GetName() { #ifdef WITH_SDL #if SDL_VERSION_ATLEAST(2, 0, 0) - return SDL_JoystickName(m_private->m_joystick); + return (SDL_CHECK(SDL_JoystickName)) ? SDL_JoystickName(m_private->m_joystick) : ""; #else - return SDL_JoystickName(m_joyindex); + return (SDL_CHECK(SDL_JoystickName)) ? SDL_JoystickName(m_joyindex) : ""; #endif #else /* WITH_SDL */ return ""; diff --git a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp index 2911b3b1a14..0033c137eb6 100644 --- a/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp +++ b/source/gameengine/GameLogic/Joystick/SCA_JoystickEvents.cpp @@ -36,6 +36,9 @@ #include "SCA_Joystick.h" #include "SCA_JoystickPrivate.h" +#ifdef _MSC_VER +# include <cstdio> /* printf */ +#endif #ifdef WITH_SDL void SCA_Joystick::OnAxisMotion(SDL_Event* sdl_event) @@ -82,7 +85,11 @@ void SCA_Joystick::OnNothing(SDL_Event* sdl_event) void SCA_Joystick::HandleEvents(void) { SDL_Event sdl_event; - + + if (SDL_PollEvent == (void*)0) { + return; + } + int i; for (i=0; i<m_joynum; i++) { /* could use JOYINDEX_MAX but no reason to */ if (SCA_Joystick::m_instance[i]) @@ -117,6 +124,12 @@ void SCA_Joystick::HandleEvents(void) SCA_Joystick::m_instance[sdl_event.jball.which]->OnBallMotion(&sdl_event); break; #endif +#if SDL_VERSION_ATLEAST(2, 0, 0) + case SDL_JOYDEVICEADDED: + case SDL_JOYDEVICEREMOVED: + /* pass */ + break; +#endif default: printf("SCA_Joystick::HandleEvents, Unknown SDL event (%d), this should not happen\n", sdl_event.type); break; diff --git a/source/gameengine/GameLogic/SCA_ANDController.cpp b/source/gameengine/GameLogic/SCA_ANDController.cpp index 3c60f2b8847..2cb7406779c 100644 --- a/source/gameengine/GameLogic/SCA_ANDController.cpp +++ b/source/gameengine/GameLogic/SCA_ANDController.cpp @@ -36,7 +36,7 @@ #include "SCA_ANDController.h" #include "SCA_ISensor.h" #include "SCA_LogicManager.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" /* ------------------------------------------------------------------------- */ /* Native functions */ diff --git a/source/gameengine/GameLogic/SCA_ExpressionController.cpp b/source/gameengine/GameLogic/SCA_ExpressionController.cpp index d1c7b58a52c..ef058e215d6 100644 --- a/source/gameengine/GameLogic/SCA_ExpressionController.cpp +++ b/source/gameengine/GameLogic/SCA_ExpressionController.cpp @@ -36,8 +36,8 @@ #include "SCA_ExpressionController.h" #include "SCA_ISensor.h" #include "SCA_LogicManager.h" -#include "BoolValue.h" -#include "InputParser.h" +#include "EXP_BoolValue.h" +#include "EXP_InputParser.h" #include "MT_Transform.h" // for fuzzyZero #include <stdio.h> diff --git a/source/gameengine/GameLogic/SCA_IController.cpp b/source/gameengine/GameLogic/SCA_IController.cpp index f922e617367..2bb04fe7be0 100644 --- a/source/gameengine/GameLogic/SCA_IController.cpp +++ b/source/gameengine/GameLogic/SCA_IController.cpp @@ -36,7 +36,7 @@ #include "SCA_LogicManager.h" #include "SCA_IActuator.h" #include "SCA_ISensor.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "../Ketsji/KX_PythonSeq.h" /* not nice, only need for KX_PythonSeq_CreatePyObject */ #include <stdio.h> diff --git a/source/gameengine/GameLogic/SCA_IController.h b/source/gameengine/GameLogic/SCA_IController.h index 1bc6b60bf1e..4ec872c2316 100644 --- a/source/gameengine/GameLogic/SCA_IController.h +++ b/source/gameengine/GameLogic/SCA_IController.h @@ -33,7 +33,7 @@ #define __SCA_ICONTROLLER_H__ #include "SCA_ILogicBrick.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" /** * Use of SG_DList element: none diff --git a/source/gameengine/GameLogic/SCA_IInputDevice.h b/source/gameengine/GameLogic/SCA_IInputDevice.h index 23346c29601..d4cd66fb564 100644 --- a/source/gameengine/GameLogic/SCA_IInputDevice.h +++ b/source/gameengine/GameLogic/SCA_IInputDevice.h @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file SCA_IController.h +/** \file SCA_IInputDevice.h * \ingroup gamelogic * \brief Interface for input devices. The defines for keyboard/system/mouse events * here are for internal use in the KX module. diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index 34fa1c98a73..72a0b392447 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -33,7 +33,7 @@ #include <stddef.h> #include "SCA_ILogicBrick.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" SCA_LogicManager* SCA_ILogicBrick::m_sCurrentLogicManager = NULL; diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.h b/source/gameengine/GameLogic/SCA_ILogicBrick.h index dc0aa4ce331..a3725789227 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.h +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.h @@ -32,9 +32,9 @@ #ifndef __SCA_ILOGICBRICK_H__ #define __SCA_ILOGICBRICK_H__ -#include "Value.h" +#include "EXP_Value.h" #include "SCA_IObject.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" #include "CTR_Map.h" #include "CTR_HashedPtr.h" diff --git a/source/gameengine/GameLogic/SCA_IObject.cpp b/source/gameengine/GameLogic/SCA_IObject.cpp index ab9e2781001..526e695e792 100644 --- a/source/gameengine/GameLogic/SCA_IObject.cpp +++ b/source/gameengine/GameLogic/SCA_IObject.cpp @@ -37,7 +37,7 @@ #include "SCA_IController.h" #include "SCA_IActuator.h" #include "MT_Point3.h" -#include "ListValue.h" +#include "EXP_ListValue.h" MT_Point3 SCA_IObject::m_sDummy=MT_Point3(0,0,0); SG_QList SCA_IObject::m_activeBookmarkedControllers; diff --git a/source/gameengine/GameLogic/SCA_IObject.h b/source/gameengine/GameLogic/SCA_IObject.h index 365e2b0c853..29a21fd8708 100644 --- a/source/gameengine/GameLogic/SCA_IObject.h +++ b/source/gameengine/GameLogic/SCA_IObject.h @@ -24,7 +24,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ -/** \file SCA_IController.h +/** \file SCA_IObject.h * \ingroup gamelogic * \brief An abstract object that has some logic, python scripting and * reference counting Note: transformation stuff has been moved to @@ -34,7 +34,7 @@ #ifndef __SCA_IOBJECT_H__ #define __SCA_IOBJECT_H__ -#include "Value.h" +#include "EXP_Value.h" #include <vector> class SCA_IObject; @@ -221,6 +221,7 @@ public: OBJ_ARMATURE=0, OBJ_CAMERA=1, OBJ_LIGHT=2, + OBJ_TEXT=3 } ObjectTypes; }; diff --git a/source/gameengine/GameLogic/SCA_IScene.cpp b/source/gameengine/GameLogic/SCA_IScene.cpp index 3ca4b6607b3..a4c905096d7 100644 --- a/source/gameengine/GameLogic/SCA_IScene.cpp +++ b/source/gameengine/GameLogic/SCA_IScene.cpp @@ -31,7 +31,7 @@ #include "SCA_IScene.h" -#include "Value.h" +#include "EXP_Value.h" SCA_DebugProp::SCA_DebugProp(): m_obj(NULL) { @@ -114,7 +114,7 @@ void SCA_IScene::RemoveDebugProperty(class CValue *gameobj, const STR_String &name) { vector<SCA_DebugProp*>::iterator it = m_debugList.begin(); - while(it != m_debugList.end()) { + while (it != m_debugList.end()) { STR_String debugname = (*it)->m_name; CValue *debugobj = (*it)->m_obj; diff --git a/source/gameengine/GameLogic/SCA_ISensor.cpp b/source/gameengine/GameLogic/SCA_ISensor.cpp index 1cb17af8325..66dd69f93c4 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.cpp +++ b/source/gameengine/GameLogic/SCA_ISensor.cpp @@ -67,7 +67,7 @@ SCA_ISensor::SCA_ISensor(SCA_IObject* gameobj, m_neg_ticks = 0; m_pos_pulsemode = false; m_neg_pulsemode = false; - m_pulse_frequency = 0; + m_skipped_ticks = 0; m_state = false; m_prev_state = false; @@ -102,11 +102,11 @@ bool SCA_ISensor::IsPositiveTrigger() void SCA_ISensor::SetPulseMode(bool posmode, bool negmode, - int freq) + int skippedticks) { m_pos_pulsemode = posmode; m_neg_pulsemode = negmode; - m_pulse_frequency = freq; + m_skipped_ticks = skippedticks; } void SCA_ISensor::SetInvert(bool inv) @@ -263,7 +263,7 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr) * not set :( */ if (m_pos_pulsemode) { m_pos_ticks++; - if (m_pos_ticks > m_pulse_frequency) { + if (m_pos_ticks > m_skipped_ticks) { if ( m_state ) { ActivateControllers(logicmgr); @@ -276,7 +276,7 @@ void SCA_ISensor::Activate(class SCA_LogicManager* logicmgr) if (m_neg_pulsemode && !m_tap) { m_neg_ticks++; - if (m_neg_ticks > m_pulse_frequency) { + if (m_neg_ticks > m_skipped_ticks) { if (!m_state ) { ActivateControllers(logicmgr); @@ -367,7 +367,7 @@ PyMethodDef SCA_ISensor::Methods[] = { PyAttributeDef SCA_ISensor::Attributes[] = { KX_PYATTRIBUTE_BOOL_RW("usePosPulseMode",SCA_ISensor,m_pos_pulsemode), KX_PYATTRIBUTE_BOOL_RW("useNegPulseMode",SCA_ISensor,m_neg_pulsemode), - KX_PYATTRIBUTE_INT_RW("frequency",0,100000,true,SCA_ISensor,m_pulse_frequency), + KX_PYATTRIBUTE_INT_RW("skippedTicks",0,100000,true,SCA_ISensor,m_skipped_ticks), KX_PYATTRIBUTE_BOOL_RW("invert",SCA_ISensor,m_invert), KX_PYATTRIBUTE_BOOL_RW_CHECK("level",SCA_ISensor,m_level,pyattr_check_level), KX_PYATTRIBUTE_BOOL_RW_CHECK("tap",SCA_ISensor,m_tap,pyattr_check_tap), @@ -376,6 +376,7 @@ PyAttributeDef SCA_ISensor::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("status", SCA_ISensor, pyattr_get_status), KX_PYATTRIBUTE_RO_FUNCTION("pos_ticks", SCA_ISensor, pyattr_get_posTicks), KX_PYATTRIBUTE_RO_FUNCTION("neg_ticks", SCA_ISensor, pyattr_get_negTicks), + KX_PYATTRIBUTE_RW_FUNCTION("frequency", SCA_ISensor, pyattr_get_frequency, pyattr_set_frequency), { NULL } //Sentinel }; @@ -444,6 +445,27 @@ int SCA_ISensor::pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrde self->m_level = false; return 0; } + +PyObject *SCA_ISensor::pyattr_get_frequency(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + SCA_ISensor *self = static_cast<SCA_ISensor*>(self_v); + ShowDeprecationWarning("SCA_ISensor.frequency", "SCA_ISensor.skippedTicks"); + return PyLong_FromLong(self->m_skipped_ticks); +} + +int SCA_ISensor::pyattr_set_frequency(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + SCA_ISensor *self = static_cast<SCA_ISensor*>(self_v); + ShowDeprecationWarning("SCA_ISensor.frequency", "SCA_ISensor.skippedTicks"); + if (PyLong_Check(value)) { + self->m_skipped_ticks = PyLong_AsLong(value); + return PY_SET_ATTR_SUCCESS; + } + else { + PyErr_SetString(PyExc_TypeError, "sensor.frequency = int: Sensor, expected an integer"); + return PY_SET_ATTR_FAIL; + } +} #endif // WITH_PYTHON /* eof */ diff --git a/source/gameengine/GameLogic/SCA_ISensor.h b/source/gameengine/GameLogic/SCA_ISensor.h index 091aa675741..1e82f3ab11f 100644 --- a/source/gameengine/GameLogic/SCA_ISensor.h +++ b/source/gameengine/GameLogic/SCA_ISensor.h @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file SCA_IController.h +/** \file SCA_ISensor.h * \ingroup gamelogic * \brief Interface Class for all logic Sensors. Implements * pulsemode and pulsefrequency, and event suppression. @@ -57,8 +57,8 @@ protected: /** Pulse negative pulses? */ bool m_neg_pulsemode; - /** Repeat frequency in pulse mode. */ - int m_pulse_frequency; + /** Number of skipped ticks between two active pulses. */ + int m_skipped_ticks; /** Number of ticks since the last positive pulse. */ int m_pos_ticks; @@ -125,7 +125,7 @@ public: */ void SetPulseMode(bool posmode, bool negmode, - int freq); + int skippedticks); /** Set inversion of pulses on or off. */ void SetInvert(bool inv); @@ -201,6 +201,8 @@ public: static PyObject* pyattr_get_status(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_posTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_negTicks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_frequency(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_frequency(void *self_v, const struct KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static int pyattr_check_level(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_check_tap(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp index 3cae3bcf160..56df9692e72 100644 --- a/source/gameengine/GameLogic/SCA_JoystickSensor.cpp +++ b/source/gameengine/GameLogic/SCA_JoystickSensor.cpp @@ -35,7 +35,7 @@ #include "SCA_EventManager.h" #include "SCA_LogicManager.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <stdio.h> #include <stddef.h> @@ -351,8 +351,8 @@ PyObject *SCA_JoystickSensor::pyattr_get_axis_values(void *self_v, const KX_PYAT SCA_JoystickSensor* self = static_cast<SCA_JoystickSensor*>(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - int axis_index= joy->GetNumberOfAxes(); - PyObject *list= PyList_New(axis_index); + int axis_index = (joy ? joy->GetNumberOfAxes() : 0); + PyObject *list = PyList_New(axis_index); while (axis_index--) { PyList_SET_ITEM(list, axis_index, PyLong_FromLong(joy->GetAxisPosition(axis_index))); @@ -371,7 +371,7 @@ PyObject *SCA_JoystickSensor::pyattr_get_axis_single(void *self_v, const KX_PYAT return NULL; } - return PyLong_FromLong(joy->GetAxisPosition(self->m_axis-1)); + return PyLong_FromLong(joy ? joy->GetAxisPosition(self->m_axis - 1) : 0); } PyObject *SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -379,8 +379,8 @@ PyObject *SCA_JoystickSensor::pyattr_get_hat_values(void *self_v, const KX_PYATT SCA_JoystickSensor* self = static_cast<SCA_JoystickSensor*>(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - int hat_index= joy->GetNumberOfHats(); - PyObject *list= PyList_New(hat_index); + int hat_index = (joy ? joy->GetNumberOfHats() : 0); + PyObject *list = PyList_New(hat_index); while (hat_index--) { PyList_SET_ITEM(list, hat_index, PyLong_FromLong(joy->GetHat(hat_index))); @@ -394,7 +394,7 @@ PyObject *SCA_JoystickSensor::pyattr_get_hat_single(void *self_v, const KX_PYATT SCA_JoystickSensor* self = static_cast<SCA_JoystickSensor*>(self_v); SCA_Joystick *joy = ((SCA_JoystickManager *)self->m_eventmgr)->GetJoystickDevice(self->m_joyindex); - return PyLong_FromLong(joy->GetHat(self->m_hat-1)); + return PyLong_FromLong(joy ? joy->GetHat(self->m_hat - 1) : 0); } PyObject *SCA_JoystickSensor::pyattr_get_num_axis(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp index edf1f300fba..778ba9e9a2c 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardManager.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardManager.cpp @@ -33,10 +33,10 @@ */ -#include "BoolValue.h" +#include "EXP_BoolValue.h" #include "SCA_KeyboardManager.h" #include "SCA_KeyboardSensor.h" -#include "IntValue.h" +#include "EXP_IntValue.h" #include <vector> SCA_KeyboardManager::SCA_KeyboardManager(SCA_LogicManager* logicmgr, diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp index cc203880f94..414a685d358 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.cpp @@ -36,7 +36,7 @@ #include "SCA_KeyboardSensor.h" #include "SCA_KeyboardManager.h" #include "SCA_LogicManager.h" -#include "StringValue.h" +#include "EXP_StringValue.h" #include "SCA_IInputDevice.h" extern "C" { @@ -511,6 +511,7 @@ PyObject *SCA_KeyboardSensor::pyattr_get_events(void *self_v, const KX_PYATTRIBU PyList_SET_ITEM(keypair,0,PyLong_FromLong(i)); PyList_SET_ITEM(keypair,1,PyLong_FromLong(inevent.m_status)); PyList_Append(resultlist,keypair); + Py_DECREF(keypair); } } return resultlist; diff --git a/source/gameengine/GameLogic/SCA_KeyboardSensor.h b/source/gameengine/GameLogic/SCA_KeyboardSensor.h index c9d55280fb7..51d7756bd1f 100644 --- a/source/gameengine/GameLogic/SCA_KeyboardSensor.h +++ b/source/gameengine/GameLogic/SCA_KeyboardSensor.h @@ -34,7 +34,7 @@ #define __SCA_KEYBOARDSENSOR_H__ #include "SCA_ISensor.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" #include <list> /** diff --git a/source/gameengine/GameLogic/SCA_LogicManager.cpp b/source/gameengine/GameLogic/SCA_LogicManager.cpp index adf57dec278..978f6d6b836 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.cpp +++ b/source/gameengine/GameLogic/SCA_LogicManager.cpp @@ -30,7 +30,7 @@ * \ingroup gamelogic */ -#include "Value.h" +#include "EXP_Value.h" #include "SCA_LogicManager.h" #include "SCA_ISensor.h" #include "SCA_IController.h" diff --git a/source/gameengine/GameLogic/SCA_LogicManager.h b/source/gameengine/GameLogic/SCA_LogicManager.h index 4d8c20065b5..7319bb537dd 100644 --- a/source/gameengine/GameLogic/SCA_LogicManager.h +++ b/source/gameengine/GameLogic/SCA_LogicManager.h @@ -24,7 +24,7 @@ * * ***** END GPL LICENSE BLOCK ***** */ -/** \file SCA_IController.h +/** \file SCA_LogicManager.h * \ingroup gamelogic * \brief Regulates the top-level logic behavior for one scene. */ @@ -43,10 +43,10 @@ #include "CTR_Map.h" #include "STR_HashedString.h" -#include "Value.h" +#include "EXP_Value.h" #include "SG_QList.h" -#include "KX_HashedPtr.h" +#include "EXP_HashedPtr.h" using namespace std; typedef std::list<class SCA_IController*> controllerlist; diff --git a/source/gameengine/GameLogic/SCA_MouseManager.cpp b/source/gameengine/GameLogic/SCA_MouseManager.cpp index 6d05b862c2d..51c03d1e350 100644 --- a/source/gameengine/GameLogic/SCA_MouseManager.cpp +++ b/source/gameengine/GameLogic/SCA_MouseManager.cpp @@ -40,10 +40,10 @@ # pragma warning( disable:4786 ) #endif -#include "BoolValue.h" +#include "EXP_BoolValue.h" #include "SCA_MouseManager.h" #include "SCA_MouseSensor.h" -#include "IntValue.h" +#include "EXP_IntValue.h" #include "RAS_ICanvas.h" diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.cpp b/source/gameengine/GameLogic/SCA_MouseSensor.cpp index a7cf4963f04..2479e859dea 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.cpp +++ b/source/gameengine/GameLogic/SCA_MouseSensor.cpp @@ -41,7 +41,7 @@ #include "SCA_MouseManager.h" #include "SCA_LogicManager.h" #include "SCA_IInputDevice.h" -#include "ConstExpr.h" +#include "EXP_ConstExpr.h" #include <iostream> /* ------------------------------------------------------------------------- */ diff --git a/source/gameengine/GameLogic/SCA_MouseSensor.h b/source/gameengine/GameLogic/SCA_MouseSensor.h index 8d05a548681..2660aaeacb5 100644 --- a/source/gameengine/GameLogic/SCA_MouseSensor.h +++ b/source/gameengine/GameLogic/SCA_MouseSensor.h @@ -34,7 +34,7 @@ #define __SCA_MOUSESENSOR_H__ #include "SCA_ISensor.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" #include "SCA_IInputDevice.h" class SCA_MouseSensor : public SCA_ISensor diff --git a/source/gameengine/GameLogic/SCA_NANDController.cpp b/source/gameengine/GameLogic/SCA_NANDController.cpp index c78ce77f9fb..6a00c110e2b 100644 --- a/source/gameengine/GameLogic/SCA_NANDController.cpp +++ b/source/gameengine/GameLogic/SCA_NANDController.cpp @@ -36,7 +36,7 @@ #include "SCA_NANDController.h" #include "SCA_ISensor.h" #include "SCA_LogicManager.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" /* ------------------------------------------------------------------------- */ /* Native functions */ diff --git a/source/gameengine/GameLogic/SCA_NORController.cpp b/source/gameengine/GameLogic/SCA_NORController.cpp index e7fb6437feb..fb09617e060 100644 --- a/source/gameengine/GameLogic/SCA_NORController.cpp +++ b/source/gameengine/GameLogic/SCA_NORController.cpp @@ -36,7 +36,7 @@ #include "SCA_NORController.h" #include "SCA_ISensor.h" #include "SCA_LogicManager.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" /* ------------------------------------------------------------------------- */ /* Native functions */ diff --git a/source/gameengine/GameLogic/SCA_ORController.cpp b/source/gameengine/GameLogic/SCA_ORController.cpp index b147f8e6bf6..8a59bdf1b89 100644 --- a/source/gameengine/GameLogic/SCA_ORController.cpp +++ b/source/gameengine/GameLogic/SCA_ORController.cpp @@ -36,7 +36,7 @@ #include "SCA_ORController.h" #include "SCA_ISensor.h" #include "SCA_LogicManager.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" /* ------------------------------------------------------------------------- */ /* Native functions */ diff --git a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp index ea1b2a2bce3..f2907ca6361 100644 --- a/source/gameengine/GameLogic/SCA_PropertyActuator.cpp +++ b/source/gameengine/GameLogic/SCA_PropertyActuator.cpp @@ -36,9 +36,9 @@ #include <stddef.h> #include "SCA_PropertyActuator.h" -#include "InputParser.h" -#include "Operator2Expr.h" -#include "ConstExpr.h" +#include "EXP_InputParser.h" +#include "EXP_Operator2Expr.h" +#include "EXP_ConstExpr.h" /* ------------------------------------------------------------------------- */ /* Native functions */ diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 6f34f8710c1..82f3bee86b2 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -37,14 +37,14 @@ #include <iostream> #include "SCA_PropertySensor.h" -#include "Operator2Expr.h" -#include "ConstExpr.h" -#include "InputParser.h" -#include "StringValue.h" +#include "EXP_Operator2Expr.h" +#include "EXP_ConstExpr.h" +#include "EXP_InputParser.h" +#include "EXP_StringValue.h" #include "SCA_EventManager.h" #include "SCA_LogicManager.h" -#include "BoolValue.h" -#include "FloatValue.h" +#include "EXP_BoolValue.h" +#include "EXP_FloatValue.h" #include <stdio.h> SCA_PropertySensor::SCA_PropertySensor(SCA_EventManager* eventmgr, @@ -265,13 +265,8 @@ bool SCA_PropertySensor::CheckPropertyCondition() //the concept of Edge and Level triggering has unwanted effect for KX_PROPSENSOR_CHANGED //see Game Engine bugtracker [ #3809 ] - if (m_checktype != KX_PROPSENSOR_CHANGED) - { - m_recentresult=result; - } else - { - m_recentresult=result;//true; - } + m_recentresult = result; + return result; } diff --git a/source/gameengine/GameLogic/SCA_PythonController.cpp b/source/gameengine/GameLogic/SCA_PythonController.cpp index 8c3ce38276e..fa30e3a5caf 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.cpp +++ b/source/gameengine/GameLogic/SCA_PythonController.cpp @@ -39,7 +39,7 @@ #include "SCA_LogicManager.h" #include "SCA_ISensor.h" #include "SCA_IActuator.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #ifdef WITH_PYTHON #include "compile.h" @@ -470,7 +470,7 @@ void SCA_PythonController::Trigger(SCA_LogicManager* logicmgr) PyObject *SCA_PythonController::PyActivate(PyObject *value) { if (m_sCurrentController != this) { - PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller"); + PyErr_SetString(PyExc_SystemError, "Cannot activate an actuator from a non-active controller"); return NULL; } @@ -485,7 +485,7 @@ PyObject *SCA_PythonController::PyActivate(PyObject *value) PyObject *SCA_PythonController::PyDeActivate(PyObject *value) { if (m_sCurrentController != this) { - PyErr_SetString(PyExc_SystemError, "Cannot add an actuator from a non-active controller"); + PyErr_SetString(PyExc_SystemError, "Cannot deactivate an actuator from a non-active controller"); return NULL; } diff --git a/source/gameengine/GameLogic/SCA_PythonController.h b/source/gameengine/GameLogic/SCA_PythonController.h index d2549318c2e..11241da9117 100644 --- a/source/gameengine/GameLogic/SCA_PythonController.h +++ b/source/gameengine/GameLogic/SCA_PythonController.h @@ -35,7 +35,7 @@ #include "SCA_IController.h" #include "SCA_LogicManager.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" #include <vector> diff --git a/source/gameengine/GameLogic/SCA_PythonJoystick.h b/source/gameengine/GameLogic/SCA_PythonJoystick.h index 15c6285aed5..ecde00d28b9 100644 --- a/source/gameengine/GameLogic/SCA_PythonJoystick.h +++ b/source/gameengine/GameLogic/SCA_PythonJoystick.h @@ -27,7 +27,7 @@ #ifndef __SCA_PYTHONJOYSTICK_H__ #define __SCA_PYTHONJOYSTICK_H__ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" class SCA_PythonJoystick : public PyObjectPlus { diff --git a/source/gameengine/GameLogic/SCA_PythonKeyboard.h b/source/gameengine/GameLogic/SCA_PythonKeyboard.h index 53068f38e6a..3cbe250378c 100644 --- a/source/gameengine/GameLogic/SCA_PythonKeyboard.h +++ b/source/gameengine/GameLogic/SCA_PythonKeyboard.h @@ -27,7 +27,7 @@ #ifndef __SCA_PYTHONKEYBOARD_H__ #define __SCA_PYTHONKEYBOARD_H__ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" class SCA_PythonKeyboard : public PyObjectPlus { diff --git a/source/gameengine/GameLogic/SCA_PythonMouse.h b/source/gameengine/GameLogic/SCA_PythonMouse.h index bc6e65f07a8..6dde90b3482 100644 --- a/source/gameengine/GameLogic/SCA_PythonMouse.h +++ b/source/gameengine/GameLogic/SCA_PythonMouse.h @@ -27,7 +27,7 @@ #ifndef __SCA_PYTHONMOUSE_H__ #define __SCA_PYTHONMOUSE_H__ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" class SCA_PythonMouse : public PyObjectPlus { diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index db6b4a63423..8d75be9089d 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -36,9 +36,9 @@ #include <stddef.h> #include <math.h> -#include "BoolValue.h" -#include "IntValue.h" -#include "FloatValue.h" +#include "EXP_BoolValue.h" +#include "EXP_IntValue.h" +#include "EXP_FloatValue.h" #include "SCA_IActuator.h" #include "SCA_RandomActuator.h" #include "MT_Transform.h" diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.cpp b/source/gameengine/GameLogic/SCA_RandomSensor.cpp index 4e93556453a..8f2dc8d80f5 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.cpp +++ b/source/gameengine/GameLogic/SCA_RandomSensor.cpp @@ -39,7 +39,7 @@ #include "SCA_EventManager.h" #include "SCA_RandomEventManager.h" #include "SCA_LogicManager.h" -#include "ConstExpr.h" +#include "EXP_ConstExpr.h" #include <iostream> /* ------------------------------------------------------------------------- */ @@ -107,7 +107,7 @@ bool SCA_RandomSensor::Evaluate() bool evaluateResult = false; - if (++m_interval > m_pulse_frequency) { + if (++m_interval > m_skipped_ticks) { bool drawResult = false; m_interval = 0; if (m_iteration > 31) { diff --git a/source/gameengine/GameLogic/SCA_RandomSensor.h b/source/gameengine/GameLogic/SCA_RandomSensor.h index 628562b77e6..66107b7b74b 100644 --- a/source/gameengine/GameLogic/SCA_RandomSensor.h +++ b/source/gameengine/GameLogic/SCA_RandomSensor.h @@ -34,7 +34,7 @@ #define __SCA_RANDOMSENSOR_H__ #include "SCA_ISensor.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" #include "SCA_RandomNumberGenerator.h" class SCA_RandomSensor : public SCA_ISensor diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp index 5aa6fdc8625..c56a1496823 100644 --- a/source/gameengine/GameLogic/SCA_TimeEventManager.cpp +++ b/source/gameengine/GameLogic/SCA_TimeEventManager.cpp @@ -38,7 +38,7 @@ #include "SCA_TimeEventManager.h" #include "SCA_LogicManager.h" -#include "FloatValue.h" +#include "EXP_FloatValue.h" SCA_TimeEventManager::SCA_TimeEventManager(SCA_LogicManager* logicmgr) : SCA_EventManager(NULL, TIME_EVENTMGR) diff --git a/source/gameengine/GameLogic/SCA_TimeEventManager.h b/source/gameengine/GameLogic/SCA_TimeEventManager.h index 4c929dca23c..38d7e3fc4d4 100644 --- a/source/gameengine/GameLogic/SCA_TimeEventManager.h +++ b/source/gameengine/GameLogic/SCA_TimeEventManager.h @@ -33,7 +33,7 @@ #define __SCA_TIMEEVENTMANAGER_H__ #include "SCA_EventManager.h" -#include "Value.h" +#include "EXP_Value.h" #include <vector> using namespace std; diff --git a/source/gameengine/GameLogic/SCA_XNORController.cpp b/source/gameengine/GameLogic/SCA_XNORController.cpp index 2cfc32a6d40..f97d11cabf3 100644 --- a/source/gameengine/GameLogic/SCA_XNORController.cpp +++ b/source/gameengine/GameLogic/SCA_XNORController.cpp @@ -36,7 +36,7 @@ #include "SCA_XNORController.h" #include "SCA_ISensor.h" #include "SCA_LogicManager.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" /* ------------------------------------------------------------------------- */ /* Native functions */ diff --git a/source/gameengine/GameLogic/SCA_XORController.cpp b/source/gameengine/GameLogic/SCA_XORController.cpp index eaa1825e5b6..bb1ea822bd8 100644 --- a/source/gameengine/GameLogic/SCA_XORController.cpp +++ b/source/gameengine/GameLogic/SCA_XORController.cpp @@ -36,7 +36,7 @@ #include "SCA_XORController.h" #include "SCA_ISensor.h" #include "SCA_LogicManager.h" -#include "BoolValue.h" +#include "EXP_BoolValue.h" /* ------------------------------------------------------------------------- */ /* Native functions */ diff --git a/source/gameengine/GamePlayer/common/CMakeLists.txt b/source/gameengine/GamePlayer/common/CMakeLists.txt index fd73b4efb53..e6c980de566 100644 --- a/source/gameengine/GamePlayer/common/CMakeLists.txt +++ b/source/gameengine/GamePlayer/common/CMakeLists.txt @@ -47,6 +47,7 @@ set(INC ../../../blender/makesdna ../../../../intern/container ../../../../intern/ghost + ../../../../intern/glew-mx ../../../../intern/guardedalloc ../../../../intern/string ) @@ -69,6 +70,6 @@ set(SRC GPC_MouseDevice.h ) -add_definitions(-DGLEW_STATIC) +add_definitions(${GL_DEFINITIONS}) blender_add_lib_nolist(ge_player_common "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp index be7cf6629f0..52c4d13c638 100644 --- a/source/gameengine/GamePlayer/common/GPC_Canvas.cpp +++ b/source/gameengine/GamePlayer/common/GPC_Canvas.cpp @@ -69,6 +69,7 @@ GPC_Canvas::GPC_Canvas( m_displayarea.m_y1 = 0; m_displayarea.m_x2 = width; m_displayarea.m_y2 = height; + m_frame = 1; glGetIntegerv(GL_VIEWPORT, (GLint*)m_viewport); } @@ -180,7 +181,9 @@ MakeScreenShot( char path[FILE_MAX]; BLI_strncpy(path, filename, sizeof(path)); BLI_path_abs(path, G.main->name); - BKE_add_image_extension_from_type(path, im_format.imtype); + BLI_path_frame(path, m_frame, 0); + m_frame++; + BKE_image_path_ensure_ext_from_imtype(path, im_format.imtype); // create and save imbuf ImBuf *ibuf = IMB_allocImBuf(GetWidth(), GetHeight(), 24, 0); diff --git a/source/gameengine/GamePlayer/common/GPC_Canvas.h b/source/gameengine/GamePlayer/common/GPC_Canvas.h index bd50066a212..34cc9759a08 100644 --- a/source/gameengine/GamePlayer/common/GPC_Canvas.h +++ b/source/gameengine/GamePlayer/common/GPC_Canvas.h @@ -40,7 +40,7 @@ # include <windows.h> #endif /* WIN32 */ -#include "GL/glew.h" +#include "glew-mx.h" #include <map> @@ -56,6 +56,8 @@ protected: /** Rect that defines the area used for rendering, * relative to the context */ RAS_Rect m_displayarea; + /** Frame counter for screenshots */ + int m_frame; int m_viewport[4]; @@ -69,6 +71,8 @@ public: virtual void ResizeWindow(int width, int height) {} + virtual void GetDisplayDimensions(int &width, int &height) {} + /** * \section Methods inherited from abstract base class RAS_ICanvas. */ diff --git a/source/gameengine/GamePlayer/common/SConscript b/source/gameengine/GamePlayer/common/SConscript index e30c2eb5859..dc105491c98 100644 --- a/source/gameengine/GamePlayer/common/SConscript +++ b/source/gameengine/GamePlayer/common/SConscript @@ -64,12 +64,12 @@ incs = [ '#source/blender/misc', '#source/blender/blenloader', '#source/blender/gpu', - '#extern/glew/include', + env['BF_GLEW_INC'], + '#/intern/glew-mx', ] -defs = [ - 'GLEW_STATIC', - ] +defs = [] +defs += env['BF_GL_DEFINITIONS'] if env['WITH_BF_PYTHON']: incs.extend(Split(env['BF_PYTHON_INC'])) diff --git a/source/gameengine/GamePlayer/ghost/CMakeLists.txt b/source/gameengine/GamePlayer/ghost/CMakeLists.txt index df752799c2c..283f222115c 100644 --- a/source/gameengine/GamePlayer/ghost/CMakeLists.txt +++ b/source/gameengine/GamePlayer/ghost/CMakeLists.txt @@ -42,12 +42,14 @@ set(INC ../../../blender/blenkernel ../../../blender/blenlib ../../../blender/blenloader + ../../../blender/blentranslation ../../../blender/gpu ../../../blender/imbuf ../../../blender/makesdna ../../../blender/makesrna ../../../../intern/container ../../../../intern/ghost + ../../../../intern/glew-mx ../../../../intern/guardedalloc ../../../../intern/string ../../../../intern/memutil @@ -73,7 +75,7 @@ set(SRC GPG_System.h ) -add_definitions(-DGLEW_STATIC) +add_definitions(${GL_DEFINITIONS}) if(WITH_CODEC_FFMPEG) add_definitions(-DWITH_FFMPEG) @@ -84,10 +86,18 @@ if(WITH_INTERNATIONAL) endif() if(WITH_AUDASPACE) + add_definitions(${AUDASPACE_DEFINITIONS}) + + list(APPEND INC_SYS + ${AUDASPACE_C_INCLUDE_DIRS} + ) +endif() + +if(WITH_SDL AND WITH_SDL_DYNLOAD) list(APPEND INC - ../../../../intern/audaspace/intern + ../../../../extern/sdlew/include ) - add_definitions(-DWITH_AUDASPACE) + add_definitions(-DWITH_SDL_DYNLOAD) endif() blender_add_lib_nolist(ge_player_ghost "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp index b85d4b40ca8..2b357f43031 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.cpp @@ -36,8 +36,9 @@ # include <windows.h> #endif -#include "GL/glew.h" +#include "glew-mx.h" #include "GPU_extensions.h" +#include "GPU_init_exit.h" #include "GPG_Application.h" #include "BL_BlenderDataConversion.h" @@ -99,9 +100,7 @@ extern "C" #include "GHOST_Rect.h" #ifdef WITH_AUDASPACE -# include "AUD_C-API.h" -# include "AUD_I3DDevice.h" -# include "AUD_IDevice.h" +# include AUD_DEVICE_H #endif static void frameTimerProc(GHOST_ITimerTask* task, GHOST_TUns64 time); @@ -113,6 +112,7 @@ GPG_Application::GPG_Application(GHOST_ISystem* system) : m_startSceneName(""), m_startScene(0), m_maggie(0), + m_kxStartScene(NULL), m_exitRequested(0), m_system(system), m_mainWindow(0), @@ -249,9 +249,15 @@ bool GPG_Application::startScreenSaverPreview( int windowWidth = rc.right - rc.left; int windowHeight = rc.bottom - rc.top; STR_String title = ""; - + GHOST_GLSettings glSettings = {0}; + + if (stereoVisual) { + glSettings.flags |= GHOST_glStereoVisual; + } + glSettings.numOfAASamples = samples; + m_mainWindow = fSystem->createWindow(title, 0, 0, windowWidth, windowHeight, GHOST_kWindowStateMinimized, - GHOST_kDrawingContextTypeOpenGL, stereoVisual, samples); + GHOST_kDrawingContextTypeOpenGL, glSettings); if (!m_mainWindow) { printf("error: could not create main window\n"); exit(-1); @@ -322,11 +328,16 @@ bool GPG_Application::startWindow( const int stereoMode, const GHOST_TUns16 samples) { + GHOST_GLSettings glSettings = {0}; bool success; // Create the main window //STR_String title ("Blender Player - GHOST"); + if (stereoVisual) + glSettings.flags |= GHOST_glStereoVisual; + glSettings.numOfAASamples = samples; + m_mainWindow = fSystem->createWindow(title, windowLeft, windowTop, windowWidth, windowHeight, GHOST_kWindowStateNormal, - GHOST_kDrawingContextTypeOpenGL, stereoVisual, false, samples); + GHOST_kDrawingContextTypeOpenGL, glSettings); if (!m_mainWindow) { printf("error: could not create main window\n"); exit(-1); @@ -353,10 +364,16 @@ bool GPG_Application::startEmbeddedWindow( const GHOST_TUns16 samples) { GHOST_TWindowState state = GHOST_kWindowStateNormal; + GHOST_GLSettings glSettings = {0}; + + if (stereoVisual) + glSettings.flags |= GHOST_glStereoVisual; + glSettings.numOfAASamples = samples; + if (parentWindow != 0) state = GHOST_kWindowStateEmbedded; m_mainWindow = fSystem->createWindow(title, 0, 0, 0, 0, state, - GHOST_kDrawingContextTypeOpenGL, stereoVisual, false, samples, parentWindow); + GHOST_kDrawingContextTypeOpenGL, glSettings, parentWindow); if (!m_mainWindow) { printf("error: could not create main window\n"); @@ -545,7 +562,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) { if (!m_engineInitialized) { - GPU_extensions_init(); + GPU_init(); bgl::InitExtensions(true); // get and set the preferences @@ -566,7 +583,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) bool frameRate = (SYS_GetCommandLineInt(syshandle, "show_framerate", 0) != 0); bool useLists = (SYS_GetCommandLineInt(syshandle, "displaylists", gm->flag & GAME_DISPLAY_LISTS) != 0) && GPU_display_list_support(); bool nodepwarnings = (SYS_GetCommandLineInt(syshandle, "ignore_deprecation_warnings", 1) != 0); - bool restrictAnimFPS = gm->flag & GAME_RESTRICT_ANIM_UPDATES; + bool restrictAnimFPS = (gm->flag & GAME_RESTRICT_ANIM_UPDATES) != 0; if (GLEW_ARB_multitexture && GLEW_VERSION_1_1) m_blendermat = (SYS_GetCommandLineInt(syshandle, "blender_material", 1) != 0); @@ -618,7 +635,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) if (!m_networkdevice) goto initFailed; - sound_init(m_maggie); + BKE_sound_init(m_maggie); // create a ketsjisystem (only needed for timing and stuff) m_kxsystem = new GPG_System (m_system); @@ -654,7 +671,7 @@ bool GPG_Application::initEngine(GHOST_IWindow* window, const int stereoMode) return m_engineInitialized; initFailed: - sound_exit(); + BKE_sound_exit(); delete m_kxsystem; delete m_networkdevice; delete m_mouse; @@ -698,7 +715,7 @@ bool GPG_Application::startEngine(void) m_sceneconverter = new KX_BlenderSceneConverter(m_maggie, m_ketsjiengine); if (m_sceneconverter) { - STR_String startscenename = m_startSceneName.Ptr(); + STR_String m_kxStartScenename = m_startSceneName.Ptr(); m_ketsjiengine->SetSceneConverter(m_sceneconverter); // if (always_use_expand_framing) @@ -710,17 +727,17 @@ bool GPG_Application::startEngine(void) if (m_startScene->gm.flag & GAME_NO_MATERIAL_CACHING) m_sceneconverter->SetCacheMaterials(false); - KX_Scene* startscene = new KX_Scene(m_keyboard, + m_kxStartScene = new KX_Scene(m_keyboard, m_mouse, m_networkdevice, - startscenename, + m_kxStartScenename, m_startScene, m_canvas); #ifdef WITH_PYTHON // some python things PyObject *gameLogic, *gameLogic_keys; - setupGamePython(m_ketsjiengine, startscene, m_maggie, NULL, &gameLogic, &gameLogic_keys, m_argc, m_argv); + setupGamePython(m_ketsjiengine, m_kxStartScene, m_maggie, NULL, &gameLogic, &gameLogic_keys, m_argc, m_argv); #endif // WITH_PYTHON //initialize Dome Settings @@ -728,13 +745,10 @@ bool GPG_Application::startEngine(void) m_ketsjiengine->InitDome(m_startScene->gm.dome.res, m_startScene->gm.dome.mode, m_startScene->gm.dome.angle, m_startScene->gm.dome.resbuf, m_startScene->gm.dome.tilt, m_startScene->gm.dome.warptext); // initialize 3D Audio Settings - AUD_I3DDevice* dev = AUD_get3DDevice(); - if (dev) - { - dev->setSpeedOfSound(m_startScene->audio.speed_of_sound); - dev->setDopplerFactor(m_startScene->audio.doppler_factor); - dev->setDistanceModel(AUD_DistanceModel(m_startScene->audio.distance_model)); - } + AUD_Device* device = BKE_sound_get_device(); + AUD_Device_setSpeedOfSound(device, m_startScene->audio.speed_of_sound); + AUD_Device_setDopplerFactor(device, m_startScene->audio.doppler_factor); + AUD_Device_setDistanceModel(device, AUD_DistanceModel(m_startScene->audio.distance_model)); #ifdef WITH_PYTHON // Set the GameLogic.globalDict from marshal'd data, so we can @@ -742,10 +756,10 @@ bool GPG_Application::startEngine(void) loadGamePythonConfig(m_pyGlobalDictString, m_pyGlobalDictString_Length); #endif m_sceneconverter->ConvertScene( - startscene, + m_kxStartScene, m_rasterizer, m_canvas); - m_ketsjiengine->AddScene(startscene); + m_ketsjiengine->AddScene(m_kxStartScene); // Create a timer that is used to kick the engine if (!m_frameTimer) { @@ -758,7 +772,7 @@ bool GPG_Application::startEngine(void) // Set the animation playback rate for ipo's and actions // the framerate below should patch with FPS macro defined in blendef.h // Could be in StartEngine set the framerate, we need the scene to do this - Scene *scene= startscene->GetBlenderScene(); // needed for macro + Scene *scene= m_kxStartScene->GetBlenderScene(); // needed for macro m_ketsjiengine->SetAnimFrameRate(FPS); } @@ -829,7 +843,7 @@ void GPG_Application::exitEngine() if (!m_engineInitialized) return; - sound_exit(); + BKE_sound_exit(); if (m_ketsjiengine) { stopEngine(); @@ -867,7 +881,7 @@ void GPG_Application::exitEngine() m_canvas = 0; } - GPU_extensions_exit(); + GPU_exit(); #ifdef WITH_PYTHON // Call this after we're sure nothing needs Python anymore (e.g., destructors) diff --git a/source/gameengine/GamePlayer/ghost/GPG_Application.h b/source/gameengine/GamePlayer/ghost/GPG_Application.h index 2d21b50e664..b6f545c2de8 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Application.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Application.h @@ -40,6 +40,7 @@ #include "KX_KetsjiEngine.h" class KX_KetsjiEngine; +class KX_Scene; class KX_ISceneConverter; class NG_LoopBackNetworkDeviceInterface; class RAS_IRasterizer; @@ -83,6 +84,12 @@ public: int getExitRequested(void); const STR_String& getExitString(void); GlobalSettings* getGlobalSettings(void); + + inline KX_Scene *GetStartScene() const + { + return m_kxStartScene; + } + bool StartGameEngine(int stereoMode); void StopGameEngine(); void EngineNextFrame(); @@ -118,6 +125,7 @@ protected: STR_String m_startSceneName; struct Scene* m_startScene; struct Main* m_maggie; + KX_Scene *m_kxStartScene; /* Exit state. */ int m_exitRequested; diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp b/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp index 35c7c62a67d..09eb1691dae 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.cpp @@ -113,12 +113,24 @@ void GPG_Canvas::SetSwapInterval(int interval) m_window->setSwapInterval(interval); } -int GPG_Canvas::GetSwapInterval() +bool GPG_Canvas::GetSwapInterval(int& intervalOut) { if (m_window) - return m_window->getSwapInterval(); + return (bool)m_window->getSwapInterval(intervalOut); - return 0; + return false; +} + +void GPG_Canvas::GetDisplayDimensions(int &width, int &height) + { + unsigned int uiwidth; + unsigned int uiheight; + + GHOST_ISystem *system = GHOST_ISystem::getSystem(); + system->getMainDisplayDimensions(uiwidth, uiheight); + + width = uiwidth; + height = uiheight; } void GPG_Canvas::ResizeWindow(int width, int height) diff --git a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h index 6e1f86cac0e..18afbf6cd9e 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_Canvas.h +++ b/source/gameengine/GamePlayer/ghost/GPG_Canvas.h @@ -56,13 +56,15 @@ public: virtual void SetMouseState(RAS_MouseState mousestate); virtual void SwapBuffers(); virtual void SetSwapInterval(int interval); - virtual int GetSwapInterval(); + virtual bool GetSwapInterval(int& intervalOut); virtual int GetMouseX(int x) { return x; } virtual int GetMouseY(int y) { return y; } virtual float GetMouseNormalizedX(int x); virtual float GetMouseNormalizedY(int y); + virtual void GetDisplayDimensions(int &width, int &height); + virtual void ResizeWindow(int width, int height); virtual void SetFullScreen(bool enable); virtual bool GetFullScreen(); diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index b6456b105c8..23d5b89f140 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -43,6 +43,7 @@ #include "KX_KetsjiEngine.h" #include "KX_PythonInit.h" #include "KX_PythonMain.h" +#include "KX_PyConstraintBinding.h" // for PHY_SetActiveEnvironment /********************************** * Begin Blender include block @@ -64,6 +65,7 @@ extern "C" #include "BLO_readfile.h" #include "BLO_runtime.h" +#include "BKE_appdir.h" #include "BKE_blender.h" #include "BKE_depsgraph.h" #include "BKE_global.h" @@ -73,17 +75,21 @@ extern "C" #include "BKE_report.h" #include "BKE_library.h" #include "BKE_modifier.h" +#include "BKE_material.h" #include "BKE_text.h" #include "BKE_sound.h" #include "IMB_imbuf.h" #include "IMB_moviecache.h" +#ifdef __APPLE__ int GHOST_HACK_getFirstFile(char buf[]); +#endif // For BLF #include "BLF_api.h" -#include "BLF_translation.h" +#include "BLT_translation.h" +#include "BLT_lang.h" extern int datatoc_bfont_ttf_size; extern char datatoc_bfont_ttf[]; extern int datatoc_bmonofont_ttf_size; @@ -116,6 +122,10 @@ extern char datatoc_bmonofont_ttf[]; #endif // !defined(DEBUG) #endif // WIN32 +#ifdef WITH_SDL_DYNLOAD +# include "sdlew.h" +#endif + const int kMinWindowWidth = 100; const int kMinWindowHeight = 100; @@ -299,7 +309,7 @@ static void get_filename(int argc, char **argv, char *filename) if (GHOST_HACK_getFirstFile(firstfilebuf)) { BLI_strncpy(filename, firstfilebuf, FILE_MAX); } - } + } } srclen -= ::strlen("MacOS/blenderplayer"); @@ -429,8 +439,13 @@ int main(int argc, char** argv) signal (SIGFPE, SIG_IGN); #endif /* __alpha__ */ #endif /* __linux__ */ - BLI_init_program_path(argv[0]); - BLI_temp_dir_init(NULL); + +#ifdef WITH_SDL_DYNLOAD + sdlewInit(); +#endif + + BKE_appdir_program_path_init(argv[0]); + BKE_tempdir_init(NULL); // We don't use threads directly in the BGE, but we need to call this so things like // freeing up GPU_Textures works correctly. @@ -459,8 +474,8 @@ int main(int argc, char** argv) // Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c) BLF_init(11, U.dpi); - BLF_lang_init(); - BLF_lang_set(""); + BLT_lang_init(); + BLT_lang_set(""); BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); if (blf_mono_font == -1) @@ -505,9 +520,12 @@ int main(int argc, char** argv) // enable fast mipmap generation U.use_gpu_mipmap = 1; - sound_init_once(); + BKE_sound_init_once(); + + // Initialize a default material for meshes without materials. + init_def_material(); - set_free_windowmanager_cb(wm_free); + BKE_library_callback_free_window_manager_set(wm_free); /* if running blenderplayer the last argument can't be parsed since it has to be the filename. else it is bundled */ isBlenderPlayer = !BLO_is_a_runtime(argv[0]); @@ -583,7 +601,7 @@ int main(int argc, char** argv) i++; G.debug |= G_DEBUG; MEM_set_memory_debug(); -#ifdef DEBUG +#ifndef NDEBUG BLI_mempool_set_memory_debug(); #endif break; @@ -811,14 +829,6 @@ int main(int argc, char** argv) if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION) #endif { - - if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) { - GPU_set_mipmap(0); - } - - GPU_set_anisotropic(U.anisotropic_filter); - GPU_set_gpu_mipmapping(U.use_gpu_mipmap); - // Create the system if (GHOST_ISystem::createSystem() == GHOST_kSuccess) { GHOST_ISystem* system = GHOST_ISystem::getSystem(); @@ -877,7 +887,7 @@ int main(int argc, char** argv) } } else { - bfd = load_game_data(BLI_program_path(), filename[0]? filename: NULL); + bfd = load_game_data(BKE_appdir_program_path(), filename[0]? filename: NULL); } #if defined(DEBUG) @@ -1041,6 +1051,13 @@ int main(int argc, char** argv) else app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight, stereoWindow, stereomode, aasamples); + + if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) { + GPU_set_mipmap(0); + } + + GPU_set_anisotropic(U.anisotropic_filter); + GPU_set_gpu_mipmapping(U.use_gpu_mipmap); } } } @@ -1064,6 +1081,11 @@ int main(int argc, char** argv) char *python_code = KX_GetPythonCode(maggie, python_main); if (python_code) { #ifdef WITH_PYTHON + // Set python environement variable. + KX_Scene *startscene = app.GetStartScene(); + KX_SetActiveScene(startscene); + PHY_SetActiveEnvironment(startscene->GetPhysicsEnvironment()); + gpg_nextframestate.system = system; gpg_nextframestate.app = &app; gpg_nextframestate.gs = &gs; @@ -1125,7 +1147,7 @@ int main(int argc, char** argv) #ifdef WITH_INTERNATIONAL BLF_free_unifont(); BLF_free_unifont_mono(); - BLF_lang_free(); + BLT_lang_free(); #endif IMB_exit(); @@ -1142,7 +1164,7 @@ int main(int argc, char** argv) MEM_printmemlist(); } - BLI_temp_dir_session_purge(); + BKE_tempdir_session_purge(); return error ? -1 : 0; } diff --git a/source/gameengine/GamePlayer/ghost/SConscript b/source/gameengine/GamePlayer/ghost/SConscript index 3e8ab3d0dd7..be9f50f40fb 100644 --- a/source/gameengine/GamePlayer/ghost/SConscript +++ b/source/gameengine/GamePlayer/ghost/SConscript @@ -44,7 +44,6 @@ incs = [ '#intern/memutil', '#intern/moto/include', '#intern/container', - '#intern/audaspace/intern', '#source/gameengine/Rasterizer/RAS_OpenGLRasterizer', '#source/gameengine/BlenderRoutines', '#source/gameengine/Converter', @@ -53,6 +52,7 @@ incs = [ '#source/blender/blenfont', '#source/blender/blenlib', '#source/blender/blenkernel', + '#source/blender/blentranslation', '#source/blender', '#source/blender/include', '#source/blender/makesdna', @@ -68,24 +68,32 @@ incs = [ '#source/blender/misc', '#source/blender/blenloader', '#source/blender/gpu', - '#extern/glew/include', + env['BF_GLEW_INC'], + '#/intern/glew-mx', ] incs.append(env['BF_PTHREADS_INC']) incs.append(env['BF_BOOST_INC']) -defs = [ - 'GLEW_STATIC', - ] +defs = [] +defs += env['BF_GL_DEFINITIONS'] if env['WITH_BF_PYTHON']: incs += Split(env['BF_PYTHON_INC']) defs.append('WITH_PYTHON') +if env['WITH_BF_AUDASPACE']: + defs += env['BF_AUDASPACE_DEF'] + incs.append(env['BF_AUDASPACE_C_INC']) + if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') if env['WITH_BF_INTERNATIONAL']: defs.append('WITH_INTERNATIONAL') +if env['WITH_BF_SDL'] and env['WITH_BF_SDL_DYNLOAD']: + defs.append('WITH_SDL_DYNLOAD') + incs += ['#extern/sdlew/include'] + env.BlenderLib (libname='ge_player_ghost', sources=source_files, includes = incs, defines = defs, libtype=['player'],priority=[0], cxx_compileflags=env['BGE_CXXFLAGS']) diff --git a/source/gameengine/Ketsji/BL_Action.cpp b/source/gameengine/Ketsji/BL_Action.cpp index a50c07a486a..12a1caee221 100644 --- a/source/gameengine/Ketsji/BL_Action.cpp +++ b/source/gameengine/Ketsji/BL_Action.cpp @@ -49,6 +49,7 @@ extern "C" { // Needed for material IPOs #include "BKE_material.h" #include "DNA_material_types.h" +#include "DNA_scene_types.h" } #include "MEM_guardedalloc.h" @@ -162,6 +163,14 @@ bool BL_Action::Play(const char* name, m_obj->GetSGNode()->AddSGController(sg_contr); sg_contr->SetObject(m_obj->GetSGNode()); + // World + sg_contr = BL_CreateWorldIPO(m_action, kxscene->GetBlenderScene()->world, kxscene->GetSceneConverter()); + if (sg_contr) { + m_sg_contr_list.push_back(sg_contr); + m_obj->GetSGNode()->AddSGController(sg_contr); + sg_contr->SetObject(m_obj->GetSGNode()); + } + // Try obcolor sg_contr = BL_CreateObColorIPO(m_action, m_obj, kxscene->GetSceneConverter()); if (sg_contr) { @@ -292,6 +301,18 @@ float BL_Action::GetFrame() return m_localtime; } +const char *BL_Action::GetName() +{ + if (m_action != NULL) { + return m_action->id.name + 2; + } + else { + return ""; + } + + +} + void BL_Action::SetFrame(float frame) { // Clamp the frame to the start and end frame diff --git a/source/gameengine/Ketsji/BL_Action.h b/source/gameengine/Ketsji/BL_Action.h index dd1cd1f69ff..379dd52df5b 100644 --- a/source/gameengine/Ketsji/BL_Action.h +++ b/source/gameengine/Ketsji/BL_Action.h @@ -112,6 +112,8 @@ public: // Accessors float GetFrame(); + const char *GetName(); + struct bAction *GetAction(); // Mutators diff --git a/source/gameengine/Ketsji/BL_ActionManager.cpp b/source/gameengine/Ketsji/BL_ActionManager.cpp index 07adce73b4a..9e4690548d3 100644 --- a/source/gameengine/Ketsji/BL_ActionManager.cpp +++ b/source/gameengine/Ketsji/BL_ActionManager.cpp @@ -26,9 +26,13 @@ #include "BL_Action.h" #include "BL_ActionManager.h" +#include "DNA_ID.h" + +#define IS_TAGGED(_id) ((_id) && (((ID *)_id)->flag & LIB_DOIT)) BL_ActionManager::BL_ActionManager(class KX_GameObject *obj): - m_obj(obj) + m_obj(obj), + m_prevUpdate(-1.0f) { } @@ -64,6 +68,12 @@ float BL_ActionManager::GetActionFrame(short layer) return action ? action->GetFrame() : 0.f; } +const char *BL_ActionManager::GetActionName(short layer) +{ + BL_Action *action = GetAction(layer); + return action ? action->GetName() : ""; +} + void BL_ActionManager::SetActionFrame(short layer, float frame) { BL_Action *action = GetAction(layer); @@ -122,6 +132,18 @@ void BL_ActionManager::StopAction(short layer) if (action) action->Stop(); } +void BL_ActionManager::RemoveTaggedActions() +{ + for (BL_ActionMap::iterator it = m_layers.begin(); it != m_layers.end();) { + if (IS_TAGGED(it->second->GetAction())) { + delete it->second; + m_layers.erase(it++); + } + else + ++it; + } +} + bool BL_ActionManager::IsActionDone(short layer) { BL_Action *action = GetAction(layer); @@ -131,6 +153,10 @@ bool BL_ActionManager::IsActionDone(short layer) void BL_ActionManager::Update(float curtime) { + if (m_prevUpdate == curtime) + return; + m_prevUpdate = curtime; + BL_ActionMap::iterator it; for (it = m_layers.begin(); it != m_layers.end(); ) { diff --git a/source/gameengine/Ketsji/BL_ActionManager.h b/source/gameengine/Ketsji/BL_ActionManager.h index 5b340257881..97d6d88cf22 100644 --- a/source/gameengine/Ketsji/BL_ActionManager.h +++ b/source/gameengine/Ketsji/BL_ActionManager.h @@ -20,7 +20,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file BL_ActionManager.cpp +/** \file BL_ActionManager.h * \ingroup ketsji */ @@ -51,6 +51,9 @@ private: class KX_GameObject* m_obj; BL_ActionMap m_layers; + // The last update time to avoid double animation update. + float m_prevUpdate; + /** * Check if an action exists */ @@ -82,6 +85,11 @@ public: float GetActionFrame(short layer); /** + * Gets the name of the current action + */ + const char *GetActionName(short layer); + + /** * Sets the current frame of an action */ void SetActionFrame(short layer, float frame); @@ -107,6 +115,11 @@ public: void StopAction(short layer); /** + * Remove playing tagged actions. + */ + void RemoveTaggedActions(); + + /** * Check if an action has finished playing */ bool IsActionDone(short layer); diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index bcdef85bc8a..b5151615f3b 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -62,7 +62,7 @@ BL_BlenderShader::~BL_BlenderShader() void BL_BlenderShader::ReloadMaterial() { - mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat) : NULL; + mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat, false) : NULL; } void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty) @@ -77,7 +77,7 @@ void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty) view.getValue((float*)viewmat); viewinv.getValue((float*)viewinvmat); - GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat, false); + GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat, NULL, false); } else GPU_material_unbind(mGPUMat); @@ -168,7 +168,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) obcol[0] = obcol[1] = obcol[2] = obcol[3] = 1.0f; float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f; - GPU_material_bind_uniforms(gpumat, obmat, obcol, auto_bump_scale); + GPU_material_bind_uniforms(gpumat, obmat, obcol, auto_bump_scale, NULL); mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol); } diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp index 006c1f7202c..4f707e6267f 100644 --- a/source/gameengine/Ketsji/BL_Material.cpp +++ b/source/gameengine/Ketsji/BL_Material.cpp @@ -47,10 +47,10 @@ BL_Material::BL_Material() void BL_Material::Initialize() { - rgb[0] = 0; - rgb[1] = 0; - rgb[2] = 0; - rgb[3] = 0; + rgb[0] = 0xFFFFFFFFL; + rgb[1] = 0xFFFFFFFFL; + rgb[2] = 0xFFFFFFFFL; + rgb[3] = 0xFFFFFFFFL; IdMode = 0; ras_mode = 0; glslmat = 0; @@ -69,7 +69,7 @@ void BL_Material::Initialize() alpha = 1.f; emit = 0.f; material = 0; - memset(&tface, 0, sizeof(tface)); + memset(&mtexpoly, 0, sizeof(mtexpoly)); materialindex = 0; amb=0.5f; num_enabled = 0; diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index 83f9b601e0d..9207a41f56d 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -84,7 +84,7 @@ public: Material* material; - MTFace tface; /* copy of the derived meshes tface */ + MTexPoly mtexpoly; /* copy of the derived meshes tface */ Image* img[MAXTEX]; EnvMap* cubemap[MAXTEX]; diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index 872ac19351d..a59c3686a18 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -22,7 +22,7 @@ * \ingroup ketsji */ -#include "GL/glew.h" +#include "glew-mx.h" #include <iostream> #include "BL_Shader.h" diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index 4c671d0c9a3..e3dc4b19773 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -6,7 +6,7 @@ #ifndef __BL_SHADER_H__ #define __BL_SHADER_H__ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "BL_Material.h" #include "BL_Texture.h" // -- diff --git a/source/gameengine/Ketsji/BL_Texture.cpp b/source/gameengine/Ketsji/BL_Texture.cpp index 1578c745b9f..8f717c05c0f 100644 --- a/source/gameengine/Ketsji/BL_Texture.cpp +++ b/source/gameengine/Ketsji/BL_Texture.cpp @@ -22,7 +22,7 @@ * \ingroup ketsji */ -#include "GL/glew.h" +#include "glew-mx.h" #include <iostream> #include <map> @@ -170,7 +170,7 @@ bool BL_Texture::InitFromImage(int unit, Image *img, bool mipmap) glGenTextures(1, (GLuint*)&mTexture); #ifdef WITH_DDS - if (ibuf->ftype & DDS) + if (ibuf->ftype == IMB_FTYPE_DDS) InitGLCompressedTex(ibuf, mipmap); else InitGLTex(ibuf->rect, ibuf->x, ibuf->y, mipmap); @@ -203,9 +203,21 @@ void BL_Texture::InitGLTex(unsigned int *pix,int x,int y,bool mipmap) glBindTexture(GL_TEXTURE_2D, mTexture ); if ( mipmap ) { + int i; + ImBuf *ibuf; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, x, y, GL_RGBA, GL_UNSIGNED_BYTE, pix ); + + ibuf = IMB_allocFromBuffer(pix, NULL, x, y); + + IMB_makemipmap(ibuf, true); + + for (i = 0; i < ibuf->miptot; i++) { + ImBuf *mip = IMB_getmipmap(ibuf, i); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } + IMB_freeImBuf(ibuf); } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -239,26 +251,34 @@ void BL_Texture::InitNonPow2Tex(unsigned int *pix,int x,int y,bool mipmap) int nx= power_of_2_min_i(x); int ny= power_of_2_min_i(y); - unsigned int *newPixels = (unsigned int *)malloc(nx*ny*sizeof(unsigned int)); - - gluScaleImage(GL_RGBA, x, y, GL_UNSIGNED_BYTE, pix, nx,ny, GL_UNSIGNED_BYTE, newPixels); + ImBuf *ibuf = IMB_allocFromBuffer(pix, NULL, x, y); + IMB_scaleImBuf(ibuf, nx, ny); + glBindTexture(GL_TEXTURE_2D, mTexture ); if ( mipmap ) { + int i; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluBuild2DMipmaps( GL_TEXTURE_2D, GL_RGBA, nx, ny, GL_RGBA, GL_UNSIGNED_BYTE, newPixels ); + + IMB_makemipmap(ibuf, true); + + for (i = 0; i < ibuf->miptot; i++) { + ImBuf *mip = IMB_getmipmap(ibuf, i); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, newPixels ); + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, nx, ny, 0, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect ); } if (GLEW_EXT_texture_filter_anisotropic) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic()); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - free(newPixels); + IMB_freeImBuf(ibuf); } @@ -400,13 +420,16 @@ unsigned int BL_Texture::GetTextureType() const int BL_Texture::GetMaxUnits() { if (g_max_units < 0) { - GLint unit; - if (GLEW_ARB_multitexture) { + GLint unit = 0; + + if (GPU_glsl_support()) { + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &unit); + } + else if (GLEW_ARB_multitexture) { glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &unit); - g_max_units = (MAXTEX>=unit)?unit:MAXTEX; - } else { - g_max_units = 0; } + + g_max_units = (MAXTEX >= unit) ? unit : MAXTEX; } return g_max_units; diff --git a/source/gameengine/Ketsji/CMakeLists.txt b/source/gameengine/Ketsji/CMakeLists.txt index 03d1524b310..2607e2bb4b7 100644 --- a/source/gameengine/Ketsji/CMakeLists.txt +++ b/source/gameengine/Ketsji/CMakeLists.txt @@ -49,6 +49,7 @@ set(INC ../../blender/python/generic ../../blender/python/mathutils ../../../intern/container + ../../../intern/glew-mx ../../../intern/guardedalloc ../../../intern/string ) @@ -229,7 +230,7 @@ set(SRC ) -add_definitions(-DGLEW_STATIC) +add_definitions(${GL_DEFINITIONS}) if(WITH_IMAGE_DDS) add_definitions(-DWITH_DDS) @@ -247,11 +248,12 @@ if(WITH_CODEC_FFMPEG) endif() if(WITH_AUDASPACE) - list(APPEND INC - ../../../intern/audaspace/intern - ../../../intern/audaspace/FX + add_definitions(${AUDASPACE_DEFINITIONS}) + + list(APPEND INC_SYS + ${AUDASPACE_C_INCLUDE_DIRS} + ${AUDASPACE_PY_INCLUDE_DIRS} ) - add_definitions(-DWITH_AUDASPACE) endif() if(WITH_BULLET) diff --git a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt index 0c661cf2c87..cfc6ded4e65 100644 --- a/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt +++ b/source/gameengine/Ketsji/KXNetwork/CMakeLists.txt @@ -30,6 +30,7 @@ set(INC ../../GameLogic ../../Network ../../SceneGraph + ../../../blender/blenlib ../../../../intern/container ../../../../intern/string ) diff --git a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp index 6260596159d..1fadd9382e0 100644 --- a/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp +++ b/source/gameengine/Ketsji/KXNetwork/KX_NetworkMessageSensor.cpp @@ -39,9 +39,9 @@ #include "NG_NetworkScene.h" #include "NG_NetworkObject.h" #include "SCA_IObject.h" -#include "InputParser.h" -#include "ListValue.h" -#include "StringValue.h" +#include "EXP_InputParser.h" +#include "EXP_ListValue.h" +#include "EXP_StringValue.h" #ifdef NAN_NET_DEBUG #include <iostream> diff --git a/source/gameengine/Ketsji/KXNetwork/SConscript b/source/gameengine/Ketsji/KXNetwork/SConscript index 355dcc4f78f..ab03e03e74d 100644 --- a/source/gameengine/Ketsji/KXNetwork/SConscript +++ b/source/gameengine/Ketsji/KXNetwork/SConscript @@ -39,6 +39,7 @@ incs = [ '#source/gameengine/Ketsji', '#source/gameengine/Network', '#source/gameengine/SceneGraph', + '../../../blender/blenlib', ] incs = ' '.join(incs) diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 9ebdfea6156..d85d33d9834 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -22,7 +22,7 @@ * \ingroup ketsji */ -#include "GL/glew.h" +#include "glew-mx.h" #include "KX_BlenderMaterial.h" #include "BL_Material.h" @@ -30,6 +30,7 @@ #include "KX_Light.h" #include "KX_GameObject.h" #include "KX_MeshProxy.h" +#include "KX_PyMath.h" #include "MT_Vector3.h" #include "MT_Vector4.h" @@ -52,6 +53,7 @@ #include "BKE_mesh.h" // ------------------------------------ #include "BLI_utildefines.h" +#include "BLI_math.h" #define spit(x) std::cout << x << std::endl; @@ -94,6 +96,21 @@ void KX_BlenderMaterial::Initialize( ((data->ras_mode &TEX)), game ); + Material *ma = data->material; + + // Save material data to restore on exit + mSavedData.r = ma->r; + mSavedData.g = ma->g; + mSavedData.b = ma->b; + mSavedData.a = ma->alpha; + mSavedData.specr = ma->specr; + mSavedData.specg = ma->specg; + mSavedData.specb = ma->specb; + mSavedData.spec = ma->spec; + mSavedData.ref = ma->ref; + mSavedData.hardness = ma->har; + mSavedData.emit = ma->emit; + mMaterial = data; mShader = 0; mBlenderShader = 0; @@ -124,16 +141,30 @@ void KX_BlenderMaterial::Initialize( KX_BlenderMaterial::~KX_BlenderMaterial() { + Material *ma = mMaterial->material; + // Restore Blender material data + ma->r = mSavedData.r; + ma->g = mSavedData.g; + ma->b = mSavedData.b; + ma->alpha = mSavedData.a; + ma->specr = mSavedData.specr; + ma->specg = mSavedData.specg; + ma->specb = mSavedData.specb; + ma->spec = mSavedData.spec; + ma->ref = mSavedData.ref; + ma->har = mSavedData.hardness; + ma->emit = mSavedData.emit; + // cleanup work if (mConstructed) // clean only if material was actually used OnExit(); } -MTFace* KX_BlenderMaterial::GetMTFace() const +MTexPoly *KX_BlenderMaterial::GetMTexPoly() const { // fonts on polys - return &mMaterial->tface; + return &mMaterial->mtexpoly; } unsigned int* KX_BlenderMaterial::GetMCol() const @@ -160,7 +191,7 @@ Material *KX_BlenderMaterial::GetBlenderMaterial() const Image *KX_BlenderMaterial::GetBlenderImage() const { - return mMaterial->tface.tpage; + return mMaterial->mtexpoly.tpage; } Scene* KX_BlenderMaterial::GetBlenderScene() const @@ -793,17 +824,19 @@ void KX_BlenderMaterial::UpdateIPO( ) { // only works one deep now - mMaterial->speccolor[0] = (float)(specrgb)[0]; - mMaterial->speccolor[1] = (float)(specrgb)[1]; - mMaterial->speccolor[2] = (float)(specrgb)[2]; - mMaterial->matcolor[0] = (float)(rgba[0]); - mMaterial->matcolor[1] = (float)(rgba[1]); - mMaterial->matcolor[2] = (float)(rgba[2]); - mMaterial->alpha = (float)(alpha); - mMaterial->hard = (float)(hard); - mMaterial->emit = (float)(emit); - mMaterial->spec_f = (float)(spec); - mMaterial->ref = (float)(ref); + + // GLSL Multitexture Input + mMaterial->material->specr = mMaterial->speccolor[0] = (float)(specrgb)[0]; + mMaterial->material->specg = mMaterial->speccolor[1] = (float)(specrgb)[1]; + mMaterial->material->specb = mMaterial->speccolor[2] = (float)(specrgb)[2]; + mMaterial->material->r = mMaterial->matcolor[0] = (float)(rgba[0]); + mMaterial->material->g = mMaterial->matcolor[1] = (float)(rgba[1]); + mMaterial->material->b = mMaterial->matcolor[2] = (float)(rgba[2]); + mMaterial->material->alpha = mMaterial->alpha = (float)(rgba[3]); + mMaterial->material->har = mMaterial->hard = (float)(hard); + mMaterial->material->emit = mMaterial->emit = (float)(emit); + mMaterial->material->spec = mMaterial->spec_f = (float)(spec); + mMaterial->material->ref = mMaterial->ref = (float)(ref); } void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) @@ -813,6 +846,11 @@ void KX_BlenderMaterial::Replace_IScene(SCA_IScene *val) OnConstruction(); } +BL_Material *KX_BlenderMaterial::GetBLMaterial() +{ + return mMaterial; +} + void KX_BlenderMaterial::SetBlenderGLSLShader() { if (!mBlenderShader) @@ -824,6 +862,111 @@ void KX_BlenderMaterial::SetBlenderGLSLShader() } } +#ifdef USE_MATHUTILS + +#define MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR 1 +#define MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR 2 + +static unsigned char mathutils_kxblendermaterial_color_cb_index = -1; /* index for our callbacks */ + +static int mathutils_kxblendermaterial_generic_check(BaseMathObject *bmo) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user); + if (!self) + return -1; + + return 0; +} + +static int mathutils_kxblendermaterial_color_get(BaseMathObject *bmo, int subtype) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial*>BGE_PROXY_REF(bmo->cb_user); + if (!self) + return -1; + + switch (subtype) { + case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR: + { + copy_v3_v3(bmo->data, self->GetBLMaterial()->matcolor); + break; + } + case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR: + { + copy_v3_v3(bmo->data, self->GetBLMaterial()->speccolor); + break; + } + } + + return 0; +} + +static int mathutils_kxblendermaterial_color_set(BaseMathObject *bmo, int subtype) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>BGE_PROXY_REF(bmo->cb_user); + if (!self) + return -1; + + switch (subtype) { + case MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR: + { + BL_Material *mat = self->GetBLMaterial(); + copy_v3_v3(mat->matcolor, bmo->data); + mat->material->r = bmo->data[0]; + mat->material->g = bmo->data[1]; + mat->material->b = bmo->data[2]; + break; + } + case MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR: + { + BL_Material *mat = self->GetBLMaterial(); + copy_v3_v3(mat->speccolor, bmo->data); + mat->material->specr = bmo->data[0]; + mat->material->specg = bmo->data[1]; + mat->material->specb = bmo->data[2]; + break; + } + } + + return 0; +} + +static int mathutils_kxblendermaterial_color_get_index(BaseMathObject *bmo, int subtype, int index) +{ + /* lazy, avoid repeteing the case statement */ + if (mathutils_kxblendermaterial_color_get(bmo, subtype) == -1) + return -1; + return 0; +} + +static int mathutils_kxblendermaterial_color_set_index(BaseMathObject *bmo, int subtype, int index) +{ + float f = bmo->data[index]; + + /* lazy, avoid repeateing the case statement */ + if (mathutils_kxblendermaterial_color_get(bmo, subtype) == -1) + return -1; + + bmo->data[index] = f; + return mathutils_kxblendermaterial_color_set(bmo, subtype); +} + +static Mathutils_Callback mathutils_kxblendermaterial_color_cb = { + mathutils_kxblendermaterial_generic_check, + mathutils_kxblendermaterial_color_get, + mathutils_kxblendermaterial_color_set, + mathutils_kxblendermaterial_color_get_index, + mathutils_kxblendermaterial_color_set_index +}; + + +void KX_BlenderMaterial_Mathutils_Callback_Init() +{ + // register mathutils callbacks, ok to run more than once. + mathutils_kxblendermaterial_color_cb_index = Mathutils_RegisterCallback(&mathutils_kxblendermaterial_color_cb); +} + +#endif // USE_MATHUTILS + #ifdef WITH_PYTHON PyMethodDef KX_BlenderMaterial::Methods[] = @@ -838,6 +981,14 @@ PyAttributeDef KX_BlenderMaterial::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("shader", KX_BlenderMaterial, pyattr_get_shader), KX_PYATTRIBUTE_RO_FUNCTION("material_index", KX_BlenderMaterial, pyattr_get_materialIndex), KX_PYATTRIBUTE_RW_FUNCTION("blending", KX_BlenderMaterial, pyattr_get_blending, pyattr_set_blending), + KX_PYATTRIBUTE_RW_FUNCTION("alpha", KX_BlenderMaterial, pyattr_get_alpha, pyattr_set_alpha), + KX_PYATTRIBUTE_RW_FUNCTION("hardness", KX_BlenderMaterial, pyattr_get_hardness, pyattr_set_hardness), + KX_PYATTRIBUTE_RW_FUNCTION("specularIntensity", KX_BlenderMaterial, pyattr_get_specular_intensity, pyattr_set_specular_intensity), + KX_PYATTRIBUTE_RW_FUNCTION("specularColor", KX_BlenderMaterial, pyattr_get_specular_color, pyattr_set_specular_color), + KX_PYATTRIBUTE_RW_FUNCTION("diffuseIntensity", KX_BlenderMaterial, pyattr_get_diffuse_intensity, pyattr_set_diffuse_intensity), + KX_PYATTRIBUTE_RW_FUNCTION("diffuseColor", KX_BlenderMaterial, pyattr_get_diffuse_color, pyattr_set_diffuse_color), + KX_PYATTRIBUTE_RW_FUNCTION("emit", KX_BlenderMaterial, pyattr_get_emit, pyattr_set_emit), + { NULL } //Sentinel }; @@ -882,6 +1033,170 @@ PyObject *KX_BlenderMaterial::pyattr_get_blending(void *self_v, const KX_PYATTRI return Py_BuildValue("(ll)", (long int)bfunc[0], (long int)bfunc[1]); } +PyObject *KX_BlenderMaterial::pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + return PyFloat_FromDouble(self->GetBLMaterial()->alpha); +} + +int KX_BlenderMaterial::pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + float val = PyFloat_AsDouble(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } + + CLAMP(val, 0.0f, 1.0f); + + BL_Material *mat = self->GetBLMaterial(); + mat->alpha = mat->material->alpha = val; + return PY_SET_ATTR_SUCCESS; +} +PyObject *KX_BlenderMaterial::pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + return PyLong_FromLong(self->GetBLMaterial()->hard); +} + +int KX_BlenderMaterial::pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + int val = PyLong_AsLong(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "material.%s = int: KX_BlenderMaterial, expected a int", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } + + CLAMP(val, 1, 511); + + BL_Material *mat = self->GetBLMaterial(); + mat->hard = mat->material->har = val; + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_BlenderMaterial::pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + return PyFloat_FromDouble(self->GetBLMaterial()->spec_f); +} + +int KX_BlenderMaterial::pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + float val = PyFloat_AsDouble(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } + + CLAMP(val, 0.0f, 1.0f); + + BL_Material *mat = self->GetBLMaterial(); + mat->spec_f = mat->material->spec = val; + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_BlenderMaterial::pyattr_get_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ +#ifdef USE_MATHUTILS + return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_SPECULAR_COLOR); +#else + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->speccolor)); +#endif +} + +int KX_BlenderMaterial::pyattr_set_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + MT_Vector3 color; + if (!PyVecTo(value, color)) + return PY_SET_ATTR_FAIL; + + BL_Material *mat = self->GetBLMaterial(); + color.getValue(mat->speccolor); + mat->material->specr = color[0]; + mat->material->specg = color[1]; + mat->material->specb = color[2]; + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_BlenderMaterial::pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + return PyFloat_FromDouble(self->GetBLMaterial()->ref); +} + +int KX_BlenderMaterial::pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + float val = PyFloat_AsDouble(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } + + CLAMP(val, 0.0f, 1.0f); + + BL_Material *mat = self->GetBLMaterial(); + mat->ref = mat->material->ref = val; + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_BlenderMaterial::pyattr_get_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ +#ifdef USE_MATHUTILS + return Color_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), mathutils_kxblendermaterial_color_cb_index, MATHUTILS_COL_CB_MATERIAL_DIFFUSE_COLOR); +#else + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + return PyColorFromVector(MT_Vector3(self->GetBLMaterial()->matcolor)); +#endif +} + +int KX_BlenderMaterial::pyattr_set_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + MT_Vector3 color; + if (!PyVecTo(value, color)) + return PY_SET_ATTR_FAIL; + + BL_Material *mat = self->GetBLMaterial(); + color.getValue(mat->matcolor); + mat->material->r = color[0]; + mat->material->g = color[1]; + mat->material->b = color[2]; + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_BlenderMaterial::pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + return PyFloat_FromDouble(self->GetBLMaterial()->emit); +} + +int KX_BlenderMaterial::pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_BlenderMaterial *self = static_cast<KX_BlenderMaterial *>(self_v); + float val = PyFloat_AsDouble(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "material.%s = float: KX_BlenderMaterial, expected a float", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } + + CLAMP(val, 0.0f, 2.0f); + + BL_Material *mat = self->GetBLMaterial(); + mat->emit = mat->material->emit = val; + return PY_SET_ATTR_SUCCESS; +} + int KX_BlenderMaterial::pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_BlenderMaterial* self = static_cast<KX_BlenderMaterial*>(self_v); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index b7c64215eaf..df089cb7f99 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -15,7 +15,7 @@ #include "BL_Shader.h" #include "BL_BlenderShader.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "MT_Vector3.h" #include "MT_Vector4.h" @@ -30,6 +30,11 @@ struct MTFace; class KX_Scene; + +#ifdef USE_MATHUTILS +void KX_BlenderMaterial_Mathutils_Callback_Init(void); +#endif + class KX_BlenderMaterial : public PyObjectPlus, public RAS_IPolyMaterial { Py_Header @@ -79,7 +84,7 @@ public: Material* GetBlenderMaterial() const; Image* GetBlenderImage() const; - MTFace* GetMTFace() const; + MTexPoly *GetMTexPoly() const; unsigned int* GetMCol() const; BL_Texture * getTex (unsigned int idx) { return (idx < MAXTEX) ? mTextures + idx : NULL; @@ -99,6 +104,8 @@ public: virtual void Replace_IScene(SCA_IScene *val); + BL_Material *GetBLMaterial(); + #ifdef WITH_PYTHON // -------------------------------- virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(mMaterial->matname); } @@ -107,6 +114,20 @@ public: static PyObject *pyattr_get_materialIndex(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject *pyattr_get_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_blending(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_alpha(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_hardness(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_specular_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_specular_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_diffuse_intensity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_diffuse_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_emit(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); KX_PYMETHOD_DOC(KX_BlenderMaterial, getShader); KX_PYMETHOD_DOC(KX_BlenderMaterial, getMaterialIndex); @@ -134,6 +155,15 @@ private: bool mConstructed; // if false, don't clean on exit int mLightLayer; + struct { + float r, g, b, a; + float specr, specg, specb; + float spec; + float ref; + float hardness; + float emit; + } mSavedData; + void InitTextures(); void SetBlenderGLSLShader(); diff --git a/source/gameengine/Ketsji/KX_Camera.cpp b/source/gameengine/Ketsji/KX_Camera.cpp index 4ab768e4240..644c71a68e4 100644 --- a/source/gameengine/Ketsji/KX_Camera.cpp +++ b/source/gameengine/Ketsji/KX_Camera.cpp @@ -31,11 +31,11 @@ */ -#include "GL/glew.h" +#include "glew-mx.h" #include "KX_Camera.h" #include "KX_Scene.h" #include "KX_PythonInit.h" -#include "KX_Python.h" +#include "EXP_Python.h" #include "KX_PyMath.h" #include "RAS_ICanvas.h" @@ -224,6 +224,22 @@ short KX_Camera::GetSensorFit() const return m_camdata.m_sensor_fit; } +/** + * Gets the horizontal shift of the sensor - for camera matching. + */ +float KX_Camera::GetShiftHorizontal() const +{ + return m_camdata.m_shift_x; +} + +/** + * Gets the vertical shift of the sensor - for camera matching. + */ +float KX_Camera::GetShiftVertical() const +{ + return m_camdata.m_shift_y; +} + float KX_Camera::GetCameraNear() const { return m_camdata.m_clipstart; @@ -463,6 +479,7 @@ bool KX_Camera::GetFrustumCulling() const void KX_Camera::EnableViewport(bool viewport) { + InvalidateProjectionMatrix(false); // We need to reset projection matrix m_camdata.m_viewport = viewport; } @@ -528,7 +545,9 @@ PyAttributeDef KX_Camera::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("ortho_scale", KX_Camera, pyattr_get_ortho_scale, pyattr_set_ortho_scale), KX_PYATTRIBUTE_RW_FUNCTION("near", KX_Camera, pyattr_get_near, pyattr_set_near), KX_PYATTRIBUTE_RW_FUNCTION("far", KX_Camera, pyattr_get_far, pyattr_set_far), - + KX_PYATTRIBUTE_RW_FUNCTION("shift_x", KX_Camera, pyattr_get_shift_x, pyattr_set_shift_x), + KX_PYATTRIBUTE_RW_FUNCTION("shift_y", KX_Camera, pyattr_get_shift_y, pyattr_set_shift_y), + KX_PYATTRIBUTE_RW_FUNCTION("useViewport", KX_Camera, pyattr_get_use_viewport, pyattr_set_use_viewport), KX_PYATTRIBUTE_RW_FUNCTION("projection_matrix", KX_Camera, pyattr_get_projection_matrix, pyattr_set_projection_matrix), @@ -747,7 +766,7 @@ int KX_Camera::pyattr_set_lens(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, KX_Camera* self = static_cast<KX_Camera*>(self_v); float param = PyFloat_AsDouble(value); if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater then zero"); + PyErr_SetString(PyExc_AttributeError, "camera.lens = float: KX_Camera, expected a float greater than zero"); return PY_SET_ATTR_FAIL; } @@ -772,7 +791,7 @@ int KX_Camera::pyattr_set_fov(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P KX_Camera* self = static_cast<KX_Camera*>(self_v); float fov = PyFloat_AsDouble(value); if (fov <= 0.0) { - PyErr_SetString(PyExc_AttributeError, "camera.fov = float: KX_Camera, expected a float greater then zero"); + PyErr_SetString(PyExc_AttributeError, "camera.fov = float: KX_Camera, expected a float greater than zero"); return PY_SET_ATTR_FAIL; } @@ -796,7 +815,7 @@ int KX_Camera::pyattr_set_ortho_scale(void *self_v, const KX_PYATTRIBUTE_DEF *at KX_Camera* self = static_cast<KX_Camera*>(self_v); float param = PyFloat_AsDouble(value); if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater then zero"); + PyErr_SetString(PyExc_AttributeError, "camera.ortho_scale = float: KX_Camera, expected a float greater than zero"); return PY_SET_ATTR_FAIL; } @@ -816,7 +835,7 @@ int KX_Camera::pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, KX_Camera* self = static_cast<KX_Camera*>(self_v); float param = PyFloat_AsDouble(value); if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater then zero"); + PyErr_SetString(PyExc_AttributeError, "camera.near = float: KX_Camera, expected a float greater than zero"); return PY_SET_ATTR_FAIL; } @@ -836,7 +855,7 @@ int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P KX_Camera* self = static_cast<KX_Camera*>(self_v); float param = PyFloat_AsDouble(value); if (param == -1) { - PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater then zero"); + PyErr_SetString(PyExc_AttributeError, "camera.far = float: KX_Camera, expected a float greater than zero"); return PY_SET_ATTR_FAIL; } @@ -845,6 +864,45 @@ int KX_Camera::pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, P return PY_SET_ATTR_SUCCESS; } +PyObject *KX_Camera::pyattr_get_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self = static_cast<KX_Camera*>(self_v); + return PyFloat_FromDouble(self->m_camdata.m_shift_x); +} + +int KX_Camera::pyattr_set_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Camera* self = static_cast<KX_Camera*>(self_v); + float param = PyFloat_AsDouble(value); + if (param == -1) { + PyErr_SetString(PyExc_AttributeError, "camera.shift_x = float: KX_Camera, expected a float greater than zero"); + return PY_SET_ATTR_FAIL; + } + + self->m_camdata.m_shift_x = param; + self->m_set_projection_matrix = false; + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_Camera::pyattr_get_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Camera* self = static_cast<KX_Camera*>(self_v); + return PyFloat_FromDouble(self->m_camdata.m_shift_y); +} + +int KX_Camera::pyattr_set_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Camera* self = static_cast<KX_Camera*>(self_v); + float param = PyFloat_AsDouble(value); + if (param == -1) { + PyErr_SetString(PyExc_AttributeError, "camera.shift_y = float: KX_Camera, expected a float greater than zero"); + return PY_SET_ATTR_FAIL; + } + + self->m_camdata.m_shift_y = param; + self->m_set_projection_matrix = false; + return PY_SET_ATTR_SUCCESS; +} PyObject *KX_Camera::pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { @@ -885,7 +943,7 @@ int KX_Camera::pyattr_set_projection_matrix(void *self_v, const KX_PYATTRIBUTE_D PyObject *KX_Camera::pyattr_get_modelview_matrix(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Camera* self = static_cast<KX_Camera*>(self_v); - return PyObjectFrom(self->GetModelviewMatrix()); + return PyObjectFrom(self->GetWorldToCamera()); } PyObject *KX_Camera::pyattr_get_camera_to_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -994,7 +1052,7 @@ KX_PYMETHODDEF_DOC_O(KX_Camera, getScreenPosition, GLdouble modelmatrix[16]; GLdouble projmatrix[16]; - MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); m_modelmatrix.getValue(modelmatrix); @@ -1037,7 +1095,7 @@ KX_PYMETHODDEF_DOC_VARARGS(KX_Camera, getScreenVect, GLdouble modelmatrix[16]; GLdouble projmatrix[16]; - MT_Matrix4x4 m_modelmatrix = this->GetModelviewMatrix(); + MT_Matrix4x4 m_modelmatrix = this->GetWorldToCamera(); MT_Matrix4x4 m_projmatrix = this->GetProjectionMatrix(); m_modelmatrix.getValue(modelmatrix); diff --git a/source/gameengine/Ketsji/KX_Camera.h b/source/gameengine/Ketsji/KX_Camera.h index 454c4a54ec1..8addf0b7aed 100644 --- a/source/gameengine/Ketsji/KX_Camera.h +++ b/source/gameengine/Ketsji/KX_Camera.h @@ -40,7 +40,7 @@ #include "MT_Vector3.h" #include "MT_Point3.h" #include "KX_GameObject.h" -#include "IntValue.h" +#include "EXP_IntValue.h" #include "RAS_CameraData.h" #ifdef WITH_PYTHON @@ -192,7 +192,7 @@ public: void InvalidateProjectionMatrix(bool valid = false); /** Gets the modelview matrix that is used by the rasterizer. - * \warning If the Camera is a dynamic object then this method may return garbage. Use GetCameraToWorld() instead. + * \warning If the Camera is a dynamic object then this method may return garbage. Use GetWorldToCamera() instead. */ const MT_Matrix4x4& GetModelviewMatrix() const; @@ -206,6 +206,10 @@ public: float GetSensorHeight() const; /** Gets the mode FOV is calculating from sensor dimensions */ short GetSensorFit() const; + /** Gets the horizontal shift of the sensor - for camera matching */ + float GetShiftHorizontal() const; + /** Gets the vertical shift of the sensor - for camera matching */ + float GetShiftVertical() const; /** Gets the near clip distance. */ float GetCameraNear() const; /** Gets the far clip distance. */ @@ -306,7 +310,11 @@ public: static int pyattr_set_near(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_far(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); - + static PyObject* pyattr_get_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_shift_x(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_shift_y(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_use_viewport(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); diff --git a/source/gameengine/Ketsji/KX_CameraActuator.cpp b/source/gameengine/Ketsji/KX_CameraActuator.cpp index acf30b4866c..f065e3f0001 100644 --- a/source/gameengine/Ketsji/KX_CameraActuator.cpp +++ b/source/gameengine/Ketsji/KX_CameraActuator.cpp @@ -40,7 +40,7 @@ #include <float.h> #include "KX_GameObject.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" /* ------------------------------------------------------------------------- */ /* Native functions */ @@ -288,19 +288,23 @@ bool KX_CameraActuator::Update(double curtime, bool frame) from[1] += fac * fp1[1]; from[2] += fac * fp1[2]; - /* alleen alstie ervoor ligt: cross testen en loodrechte bijtellen */ + /* only for it lies: cross test and perpendicular bites up */ if (inp < 0.0f) { - if (fp1[0] * fp2[1] - fp1[1] * fp2[0] > 0.0f) { + /* Don't do anything if the cross product is too small. + * The camera up-axis becomes unstable and starts to oscillate. + * The 0.01f threshold is arbitrary but seems to work well in practice. */ + float cross = fp1[0] * fp2[1] - fp1[1] * fp2[0]; + if (cross > 0.01f) { from[0] -= fac * fp1[1]; from[1] += fac * fp1[0]; } - else { + else if (cross < -0.01f) { from[0] += fac * fp1[1]; from[1] -= fac * fp1[0]; } } - /* CONSTRAINT 5: minimum / maximum afstand */ + /* CONSTRAINT 5: minimum / maximum distance */ rc[0] = (lookat[0]-from[0]); rc[1] = (lookat[1]-from[1]); @@ -323,7 +327,7 @@ bool KX_CameraActuator::Update(double curtime, bool frame) } - /* CONSTRAINT 7: track to schaduw */ + /* CONSTRAINT 7: track to floor below actor */ rc[0] = (lookat[0]-from[0]); rc[1] = (lookat[1]-from[1]); rc[2] = (lookat[2]-from[2]); diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h index d4d8f195102..dd7ba680ec7 100644 --- a/source/gameengine/Ketsji/KX_CharacterWrapper.h +++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h @@ -6,7 +6,7 @@ #ifndef __KX_CHARACTERWRAPPER_H__ #define __KX_CHARACTERWRAPPER_H__ -#include "Value.h" +#include "EXP_Value.h" #include "PHY_DynamicTypes.h" class PHY_ICharacter; diff --git a/source/gameengine/Ketsji/KX_ClientObjectInfo.h b/source/gameengine/Ketsji/KX_ClientObjectInfo.h index e947eb4be6d..81ae5b58009 100644 --- a/source/gameengine/Ketsji/KX_ClientObjectInfo.h +++ b/source/gameengine/Ketsji/KX_ClientObjectInfo.h @@ -52,19 +52,16 @@ struct KX_ClientObjectInfo OBACTORSENSOR } m_type; KX_GameObject* m_gameobject; - void* m_auxilary_info; std::list<SCA_ISensor*> m_sensors; public: - KX_ClientObjectInfo(KX_GameObject *gameobject, clienttype type = STATIC, void *auxilary_info = NULL) : + KX_ClientObjectInfo(KX_GameObject *gameobject, clienttype type = STATIC) : m_type(type), - m_gameobject(gameobject), - m_auxilary_info(auxilary_info) + m_gameobject(gameobject) {} KX_ClientObjectInfo(const KX_ClientObjectInfo ©) : m_type(copy.m_type), - m_gameobject(copy.m_gameobject), - m_auxilary_info(copy.m_auxilary_info) + m_gameobject(copy.m_gameobject) { } diff --git a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp index e5662b54b83..e07660cef72 100644 --- a/source/gameengine/Ketsji/KX_ConstraintActuator.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintActuator.cpp @@ -41,6 +41,7 @@ #include "KX_GameObject.h" #include "KX_RayCast.h" #include "KX_PythonInit.h" // KX_GetActiveScene +#include "RAS_MeshObject.h" #include <stdio.h> @@ -129,15 +130,17 @@ bool KX_ConstraintActuator::RayHit(KX_ClientObjectInfo *client, KX_RayCast *resu } else { - if (m_option & KX_ACT_CONSTRAINT_MATERIAL) - { - if (client->m_auxilary_info) - { - bFound = !strcmp(m_property.Ptr(), ((char*)client->m_auxilary_info)); + if (m_option & KX_ACT_CONSTRAINT_MATERIAL) { + for (unsigned int i = 0; i < m_hitObject->GetMeshCount(); ++i) { + RAS_MeshObject *meshObj = m_hitObject->GetMesh(i); + for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { + bFound = strcmp(m_property.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0; + if (bFound) + break; + } } } - else - { + else { bFound = m_hitObject->GetProperty(m_property) != NULL; } } diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp index 29d92762285..2f32b5e3216 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.cpp @@ -30,7 +30,7 @@ */ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "KX_ConstraintWrapper.h" #include "PHY_IPhysicsEnvironment.h" diff --git a/source/gameengine/Ketsji/KX_ConstraintWrapper.h b/source/gameengine/Ketsji/KX_ConstraintWrapper.h index b7124c76439..5e20b7a9aca 100644 --- a/source/gameengine/Ketsji/KX_ConstraintWrapper.h +++ b/source/gameengine/Ketsji/KX_ConstraintWrapper.h @@ -32,7 +32,7 @@ #ifndef __KX_CONSTRAINTWRAPPER_H__ #define __KX_CONSTRAINTWRAPPER_H__ -#include "Value.h" +#include "EXP_Value.h" #include "PHY_DynamicTypes.h" class KX_ConstraintWrapper : public PyObjectPlus diff --git a/source/gameengine/Ketsji/KX_Dome.cpp b/source/gameengine/Ketsji/KX_Dome.cpp index c7f7f586865..07bed647b29 100644 --- a/source/gameengine/Ketsji/KX_Dome.cpp +++ b/source/gameengine/Ketsji/KX_Dome.cpp @@ -41,7 +41,7 @@ #include "RAS_CameraData.h" #include "BLI_math.h" -#include "GL/glew.h" +#include "glew-mx.h" // constructor KX_Dome::KX_Dome ( @@ -2044,7 +2044,9 @@ void KX_Dome::RenderDomeFrame(KX_Scene* scene, KX_Camera* cam, int i) cam->NodeUpdateGS(0.f); scene->CalculateVisibleMeshes(m_rasterizer,cam); - scene->UpdateAnimations(m_engine->GetFrameTime()); + + m_engine->UpdateAnimations(scene); + scene->RenderBuckets(camtrans, m_rasterizer); } diff --git a/source/gameengine/Ketsji/KX_Dome.h b/source/gameengine/Ketsji/KX_Dome.h index a7e798a3944..420565e62f6 100644 --- a/source/gameengine/Ketsji/KX_Dome.h +++ b/source/gameengine/Ketsji/KX_Dome.h @@ -38,7 +38,7 @@ #include "RAS_IRasterizer.h" #include "KX_KetsjiEngine.h" -#include "GL/glew.h" +#include "glew-mx.h" #include <vector> #include "MEM_guardedalloc.h" diff --git a/source/gameengine/Ketsji/KX_FontObject.cpp b/source/gameengine/Ketsji/KX_FontObject.cpp index 9789a8294ee..420f1f7eb98 100644 --- a/source/gameengine/Ketsji/KX_FontObject.cpp +++ b/source/gameengine/Ketsji/KX_FontObject.cpp @@ -35,7 +35,7 @@ #include "KX_Scene.h" #include "KX_PythonInit.h" #include "BLI_math.h" -#include "StringValue.h" +#include "EXP_StringValue.h" #include "RAS_IRasterizer.h" /* paths needed for font load */ @@ -118,7 +118,6 @@ CValue* KX_FontObject::GetReplica() void KX_FontObject::ProcessReplica() { KX_GameObject::ProcessReplica(); - KX_GetActiveScene()->AddFont(this); } int GetFontId(VFont *vfont) diff --git a/source/gameengine/Ketsji/KX_FontObject.h b/source/gameengine/Ketsji/KX_FontObject.h index 209ab6ca69f..bf70eedfde6 100644 --- a/source/gameengine/Ketsji/KX_FontObject.h +++ b/source/gameengine/Ketsji/KX_FontObject.h @@ -54,6 +54,7 @@ public: */ virtual CValue* GetReplica(); virtual void ProcessReplica(); + virtual int GetGameObjectType() { return OBJ_TEXT; } protected: std::vector<STR_String> m_text; diff --git a/source/gameengine/Ketsji/KX_GameActuator.cpp b/source/gameengine/Ketsji/KX_GameActuator.cpp index c6087ac676d..a23af680104 100644 --- a/source/gameengine/Ketsji/KX_GameActuator.cpp +++ b/source/gameengine/Ketsji/KX_GameActuator.cpp @@ -178,6 +178,11 @@ bool KX_GameActuator::Update() // obtain file size: fseek (fp , 0 , SEEK_END); marshal_length = ftell(fp); + if (marshal_length == -1) { + printf("warning: could not read position of '%s'\n", mashal_path); + fclose(fp); + break; + } rewind(fp); marshal_buffer = (char*) malloc (sizeof(char)*marshal_length); diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index c681e0842c4..c3da80bc14f 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -36,14 +36,6 @@ # pragma warning( disable:4786 ) #endif -#if defined(_WIN64) && !defined(FREE_WINDOWS64) -typedef unsigned __int64 uint_ptr; -#elif defined(FREE_WINDOWS64) -typedef unsigned long long uint_ptr; -#else -typedef unsigned long uint_ptr; -#endif - #include "RAS_IPolygonMaterial.h" #include "KX_BlenderMaterial.h" #include "KX_GameObject.h" @@ -55,6 +47,7 @@ typedef unsigned long uint_ptr; #include "KX_MeshProxy.h" #include "KX_PolyProxy.h" #include <stdio.h> // printf +#include <climits> // USHRT_MAX #include "SG_Controller.h" #include "PHY_IGraphicController.h" #include "SG_Node.h" @@ -76,7 +69,13 @@ typedef unsigned long uint_ptr; #include "BL_ActionManager.h" #include "BL_Action.h" -#include "PyObjectPlus.h" /* python stuff */ +#include "EXP_PyObjectPlus.h" /* python stuff */ +#include "BLI_utildefines.h" + +#ifdef WITH_PYTHON +# include "EXP_PythonCallBack.h" +# include "python_utildefines.h" +#endif // This file defines relationships between parents and children // in the game engine. @@ -97,9 +96,10 @@ KX_GameObject::KX_GameObject( : SCA_IObject(), m_bDyna(false), m_layer(0), + m_currentLodLevel(0), + m_previousLodLevel(0), m_pBlenderObject(NULL), m_pBlenderGroupObject(NULL), - m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), m_objectColor(1.0, 1.0, 1.0, 1.0), @@ -297,6 +297,21 @@ void KX_GameObject::SetDupliGroupObject(KX_GameObject* obj) m_pDupliGroupObject = obj; } +void KX_GameObject::AddConstraint(bRigidBodyJointConstraint *cons) +{ + m_constraints.push_back(cons); +} + +std::vector<bRigidBodyJointConstraint*> KX_GameObject::GetConstraints() +{ + return m_constraints; +} + +void KX_GameObject::ClearConstraints() +{ + m_constraints.clear(); +} + KX_GameObject* KX_GameObject::GetParent() { KX_GameObject* result = NULL; @@ -454,6 +469,11 @@ void KX_GameObject::StopAction(short layer) GetActionManager()->StopAction(layer); } +void KX_GameObject::RemoveTaggedActions() +{ + GetActionManager()->RemoveTaggedActions(); +} + bool KX_GameObject::IsActionDone(short layer) { return GetActionManager()->IsActionDone(layer); @@ -474,6 +494,11 @@ float KX_GameObject::GetActionFrame(short layer) return GetActionManager()->GetActionFrame(layer); } +const char *KX_GameObject::GetActionName(short layer) +{ + return GetActionManager()->GetActionName(layer); +} + void KX_GameObject::SetActionFrame(short layer, float frame) { GetActionManager()->SetActionFrame(layer, frame); @@ -551,13 +576,26 @@ void KX_GameObject::ActivateGraphicController(bool recurse) } } -void KX_GameObject::SetUserCollisionGroup(short group) +void KX_GameObject::SetUserCollisionGroup(unsigned short group) { m_userCollisionGroup = group; + if (m_pPhysicsController) + m_pPhysicsController->RefreshCollisions(); } -void KX_GameObject::SetUserCollisionMask(short mask) +void KX_GameObject::SetUserCollisionMask(unsigned short mask) { m_userCollisionMask = mask; + if (m_pPhysicsController) + m_pPhysicsController->RefreshCollisions(); +} + +unsigned short KX_GameObject::GetUserCollisionGroup() +{ + return m_userCollisionGroup; +} +unsigned short KX_GameObject::GetUserCollisionMask() +{ + return m_userCollisionMask; } bool KX_GameObject::CheckCollision(KX_GameObject* other) @@ -575,6 +613,46 @@ CValue* KX_GameObject::GetReplica() return replica; } +bool KX_GameObject::IsDynamicsSuspended() const +{ + if (m_pPhysicsController) + return m_pPhysicsController->IsSuspended(); + return false; +} + +float KX_GameObject::getLinearDamping() const +{ + if (m_pPhysicsController) + return m_pPhysicsController->GetLinearDamping(); + return 0; +} + +float KX_GameObject::getAngularDamping() const +{ + if (m_pPhysicsController) + return m_pPhysicsController->GetAngularDamping(); + return 0; +} + +void KX_GameObject::setLinearDamping(float damping) +{ + if (m_pPhysicsController) + m_pPhysicsController->SetLinearDamping(damping); +} + + +void KX_GameObject::setAngularDamping(float damping) +{ + if (m_pPhysicsController) + m_pPhysicsController->SetAngularDamping(damping); +} + + +void KX_GameObject::setDamping(float linear, float angular) +{ + if (m_pPhysicsController) + m_pPhysicsController->SetDamping(linear, angular); +} void KX_GameObject::ApplyForce(const MT_Vector3& force,bool local) @@ -741,35 +819,74 @@ void KX_GameObject::AddLodMesh(RAS_MeshObject* mesh) m_lodmeshes.push_back(mesh); } + +static float calcHysteresis(KX_Scene *kxscene, LodLevel *lod) +{ + float hystvariance = 0.0f; + + if (!kxscene->IsActivedLodHysteresis()) + return hystvariance; + + short hysteresis = 0; + // if exists, LoD level hysteresis will override scene hysteresis + if (lod->next->flags & OB_LOD_USE_HYST) + hysteresis = lod->next->obhysteresis; + else + hysteresis = kxscene->GetLodHysteresisValue(); + + return hystvariance = MT_abs(lod->next->distance - lod->distance) * hysteresis / 100; +} + void KX_GameObject::UpdateLod(MT_Vector3 &cam_pos) { // Handle dupligroups - if (this->m_pInstanceObjects) { - KX_GameObject * instob; - int count = this->m_pInstanceObjects->GetCount(); + if (m_pInstanceObjects) { + KX_GameObject *instob; + int count = m_pInstanceObjects->GetCount(); for (int i = 0; i < count; i++) { - instob = (KX_GameObject*)this->m_pInstanceObjects->GetValue(i); + instob = (KX_GameObject*)m_pInstanceObjects->GetValue(i); instob->UpdateLod(cam_pos); } } - if (this->m_lodmeshes.empty()) return; + if (m_lodmeshes.empty()) + return; - MT_Vector3 delta = this->NodeGetWorldPosition() - cam_pos; + MT_Vector3 delta = NodeGetWorldPosition() - cam_pos; float distance2 = delta.length2(); int level = 0; - Object *bob = this->GetBlenderObject(); - LodLevel *lod = (LodLevel*) bob->lodlevels.first; + float hystvariance = 0.0f; + Object *bob = GetBlenderObject(); + LodLevel *lod = (LodLevel *)bob->lodlevels.first; + KX_Scene *kxscene = GetScene(); + for (; lod; lod = lod->next, level++) { - if (!lod->source || lod->source->type != OB_MESH) level--; - if (!lod->next || lod->next->distance * lod->next->distance > distance2) break; - } + if (!lod->source || lod->source->type != OB_MESH) + level--; - RAS_MeshObject *mesh = this->m_lodmeshes[level]; + if (!lod->next) + break; + + if (level == m_previousLodLevel || level == (m_previousLodLevel + 1)) { + hystvariance = calcHysteresis(kxscene, lod); + float newdistance = lod->next->distance + hystvariance; + if (newdistance * newdistance > distance2) + break; + } + else if (level == (m_previousLodLevel - 1)) { + hystvariance = calcHysteresis(kxscene, lod); + float newdistance = lod->next->distance - hystvariance; + if (newdistance * newdistance > distance2) + break; + } + } - if (mesh != this->m_meshes[0]) { - this->GetScene()->ReplaceMesh(this, mesh, true, false); + RAS_MeshObject *mesh = m_lodmeshes[level]; + m_currentLodLevel = level; + if (mesh != m_meshes[0]) { + m_previousLodLevel = level; + GetScene()->ReplaceMesh(this, mesh, true, false); } } @@ -930,27 +1047,6 @@ KX_GameObject::SetVisible( } } -bool KX_GameObject::GetCulled() -{ - // If we're set to not cull, double-check with - // the mesh slots first. This is kind of nasty, but - // it allows us to get proper culling information. - if (!m_bCulled) - { - SG_QList::iterator<RAS_MeshSlot> mit(m_meshSlots); - for (mit.begin(); !mit.end(); ++mit) - { - if ((*mit)->m_bCulled) - { - m_bCulled = true; - break; - } - } - } - - return m_bCulled; -} - static void setOccluder_recursive(SG_Node* node, bool v) { NodeList& children = node->GetSGChildren(); @@ -1486,36 +1582,27 @@ void KX_GameObject::RegisterCollisionCallbacks() pe->AddSensor(spc); } } -void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider) +void KX_GameObject::RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal) { - #ifdef WITH_PYTHON - Py_ssize_t len; - PyObject* collision_callbacks = m_collisionCallbacks; - - if (collision_callbacks && (len=PyList_GET_SIZE(collision_callbacks))) - { - PyObject* args = Py_BuildValue("(O)", collider->GetProxy()); // save python creating each call - PyObject *func; - PyObject *ret; +#ifdef WITH_PYTHON + if (!m_collisionCallbacks || PyList_GET_SIZE(m_collisionCallbacks) == 0) + return; - // Iterate the list and run the callbacks - for (Py_ssize_t pos=0; pos < len; pos++) - { - func = PyList_GET_ITEM(collision_callbacks, pos); - ret = PyObject_Call(func, args, NULL); + /** Current logic controller is set by each python logic bricks before run, + * but if no python logic brick ran the logic manager can be wrong + * (if the user use muti scenes) and it will cause problems with function + * ConvertPythonToGameObject which use the current logic manager for object's name. + * Note: the scene is already set in logic frame loop. + */ + SCA_ILogicBrick::m_sCurrentLogicManager = GetScene()->GetLogicManager(); - if (ret == NULL) { - PyErr_Print(); - PyErr_Clear(); - } - else { - Py_DECREF(ret); - } - } + PyObject *args[] = {collider->GetProxy(), PyObjectFrom(point), PyObjectFrom(normal)}; + RunPythonCallBackList(m_collisionCallbacks, args, 1, ARRAY_SIZE(args)); - Py_DECREF(args); + for (unsigned int i = 0; i < ARRAY_SIZE(args); ++i) { + Py_DECREF(args[i]); } - #endif +#endif } /* Suspend/ resume: for the dynamic behavior, there is a simple @@ -1529,7 +1616,8 @@ void KX_GameObject::Resume(void) { if (m_suspended) { SCA_IObject::Resume(); - if (GetPhysicsController()) + // Child objects must be static, so we block changing to dynamic + if (GetPhysicsController() && !GetParent()) GetPhysicsController()->RestoreDynamics(); m_suspended = false; @@ -1587,9 +1675,11 @@ CListValue* KX_GameObject::GetChildrenRecursive() KX_Scene* KX_GameObject::GetScene() { SG_Node* node = this->GetSGNode(); - KX_Scene* scene = static_cast<KX_Scene*>(node->GetSGClientInfo()); - - return scene; + if (node == NULL) { + // this happens for object in non active layers, rely on static scene then + return KX_GetActiveScene(); + } + return static_cast<KX_Scene*>(node->GetSGClientInfo()); } /* --------------------------------------------------------------------- @@ -1823,7 +1913,7 @@ static Mathutils_Callback mathutils_kxgameob_matrix_cb = { void KX_GameObject_Mathutils_Callback_Init(void) { - // register mathutils callbacks, ok to run more then once. + // register mathutils callbacks, ok to run more than once. mathutils_kxgameob_vector_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_vector_cb); mathutils_kxgameob_matrix_cb_index= Mathutils_RegisterCallback(&mathutils_kxgameob_matrix_cb); } @@ -1842,10 +1932,11 @@ PyMethodDef KX_GameObject::Methods[] = { {"getAngularVelocity", (PyCFunction) KX_GameObject::sPyGetAngularVelocity, METH_VARARGS}, {"setAngularVelocity", (PyCFunction) KX_GameObject::sPySetAngularVelocity, METH_VARARGS}, {"getVelocity", (PyCFunction) KX_GameObject::sPyGetVelocity, METH_VARARGS}, + {"setDamping", (PyCFunction) KX_GameObject::sPySetDamping, METH_VARARGS}, {"getReactionForce", (PyCFunction) KX_GameObject::sPyGetReactionForce, METH_NOARGS}, {"alignAxisToVect",(PyCFunction) KX_GameObject::sPyAlignAxisToVect, METH_VARARGS}, {"getAxisVect",(PyCFunction) KX_GameObject::sPyGetAxisVect, METH_O}, - {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics,METH_NOARGS}, + {"suspendDynamics", (PyCFunction)KX_GameObject::sPySuspendDynamics, METH_VARARGS}, {"restoreDynamics", (PyCFunction)KX_GameObject::sPyRestoreDynamics,METH_NOARGS}, {"enableRigidBody", (PyCFunction)KX_GameObject::sPyEnableRigidBody,METH_NOARGS}, {"disableRigidBody", (PyCFunction)KX_GameObject::sPyDisableRigidBody,METH_NOARGS}, @@ -1873,6 +1964,7 @@ PyMethodDef KX_GameObject::Methods[] = { KX_PYMETHODTABLE_KEYWORDS(KX_GameObject, playAction), KX_PYMETHODTABLE(KX_GameObject, stopAction), KX_PYMETHODTABLE(KX_GameObject, getActionFrame), + KX_PYMETHODTABLE(KX_GameObject, getActionName), KX_PYMETHODTABLE(KX_GameObject, setActionFrame), KX_PYMETHODTABLE(KX_GameObject, isPlayingAction), @@ -1883,6 +1975,7 @@ PyMethodDef KX_GameObject::Methods[] = { }; PyAttributeDef KX_GameObject::Attributes[] = { + KX_PYATTRIBUTE_INT_RO("currentLodLevel", KX_GameObject, m_currentLodLevel), KX_PYATTRIBUTE_RO_FUNCTION("name", KX_GameObject, pyattr_get_name), KX_PYATTRIBUTE_RO_FUNCTION("parent", KX_GameObject, pyattr_get_parent), KX_PYATTRIBUTE_RO_FUNCTION("groupMembers", KX_GameObject, pyattr_get_group_members), @@ -1890,8 +1983,11 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("scene", KX_GameObject, pyattr_get_scene), KX_PYATTRIBUTE_RO_FUNCTION("life", KX_GameObject, pyattr_get_life), KX_PYATTRIBUTE_RW_FUNCTION("mass", KX_GameObject, pyattr_get_mass, pyattr_set_mass), + KX_PYATTRIBUTE_RO_FUNCTION("isSuspendDynamics", KX_GameObject, pyattr_get_is_suspend_dynamics), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMin", KX_GameObject, pyattr_get_lin_vel_min, pyattr_set_lin_vel_min), KX_PYATTRIBUTE_RW_FUNCTION("linVelocityMax", KX_GameObject, pyattr_get_lin_vel_max, pyattr_set_lin_vel_max), + KX_PYATTRIBUTE_RW_FUNCTION("angularVelocityMin", KX_GameObject, pyattr_get_ang_vel_min, pyattr_set_ang_vel_min), + KX_PYATTRIBUTE_RW_FUNCTION("angularVelocityMax", KX_GameObject, pyattr_get_ang_vel_max, pyattr_set_ang_vel_max), KX_PYATTRIBUTE_RW_FUNCTION("visible", KX_GameObject, pyattr_get_visible, pyattr_set_visible), KX_PYATTRIBUTE_RW_FUNCTION("record_animation", KX_GameObject, pyattr_get_record_animation, pyattr_set_record_animation), KX_PYATTRIBUTE_BOOL_RW ("occlusion", KX_GameObject, m_bOccluder), @@ -1901,6 +1997,8 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("scaling", KX_GameObject, pyattr_get_worldScaling, pyattr_set_localScaling), KX_PYATTRIBUTE_RW_FUNCTION("timeOffset",KX_GameObject, pyattr_get_timeOffset,pyattr_set_timeOffset), KX_PYATTRIBUTE_RW_FUNCTION("collisionCallbacks", KX_GameObject, pyattr_get_collisionCallbacks, pyattr_set_collisionCallbacks), + KX_PYATTRIBUTE_RW_FUNCTION("collisionGroup", KX_GameObject, pyattr_get_collisionGroup, pyattr_set_collisionGroup), + KX_PYATTRIBUTE_RW_FUNCTION("collisionMask", KX_GameObject, pyattr_get_collisionMask, pyattr_set_collisionMask), KX_PYATTRIBUTE_RW_FUNCTION("state", KX_GameObject, pyattr_get_state, pyattr_set_state), KX_PYATTRIBUTE_RO_FUNCTION("meshes", KX_GameObject, pyattr_get_meshes), KX_PYATTRIBUTE_RW_FUNCTION("localOrientation",KX_GameObject,pyattr_get_localOrientation,pyattr_set_localOrientation), @@ -1917,6 +2015,8 @@ PyAttributeDef KX_GameObject::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("angularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_worldAngularVelocity), KX_PYATTRIBUTE_RW_FUNCTION("localAngularVelocity", KX_GameObject, pyattr_get_localAngularVelocity, pyattr_set_localAngularVelocity), KX_PYATTRIBUTE_RW_FUNCTION("worldAngularVelocity", KX_GameObject, pyattr_get_worldAngularVelocity, pyattr_set_worldAngularVelocity), + KX_PYATTRIBUTE_RW_FUNCTION("linearDamping", KX_GameObject, pyattr_get_linearDamping, pyattr_set_linearDamping), + KX_PYATTRIBUTE_RW_FUNCTION("angularDamping", KX_GameObject, pyattr_get_angularDamping, pyattr_set_angularDamping), KX_PYATTRIBUTE_RO_FUNCTION("children", KX_GameObject, pyattr_get_children), KX_PYATTRIBUTE_RO_FUNCTION("childrenRecursive", KX_GameObject, pyattr_get_children_recursive), KX_PYATTRIBUTE_RO_FUNCTION("attrDict", KX_GameObject, pyattr_get_attrDict), @@ -2245,6 +2345,56 @@ int KX_GameObject::pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIB return PY_SET_ATTR_SUCCESS; } +PyObject *KX_GameObject::pyattr_get_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + return PyLong_FromLong(self->GetUserCollisionGroup()); +} + +int KX_GameObject::pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + int val = PyLong_AsLong(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "gameOb.collisionGroup = int: KX_GameObject, expected an int bit field"); + return PY_SET_ATTR_FAIL; + } + + if (val < 0 || val > USHRT_MAX) { + PyErr_Format(PyExc_AttributeError, "gameOb.collisionGroup = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX); + return PY_SET_ATTR_FAIL; + } + + self->SetUserCollisionGroup(val); + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_GameObject::pyattr_get_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + return PyLong_FromLong(self->GetUserCollisionMask()); +} + +int KX_GameObject::pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + int val = PyLong_AsLong(value); + + if (val == -1 && PyErr_Occurred()) { + PyErr_SetString(PyExc_TypeError, "gameOb.collisionMask = int: KX_GameObject, expected an int bit field"); + return PY_SET_ATTR_FAIL; + } + + if (val < 0 || val > USHRT_MAX) { + PyErr_Format(PyExc_AttributeError, "gameOb.collisionMask = int: KX_GameObject, expected a int bit field between 0 and %i", USHRT_MAX); + return PY_SET_ATTR_FAIL; + } + + self->SetUserCollisionMask(val); + return PY_SET_ATTR_SUCCESS; +} + PyObject* KX_GameObject::pyattr_get_scene(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject *self = static_cast<KX_GameObject*>(self_v); @@ -2301,6 +2451,19 @@ int KX_GameObject::pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrd return PY_SET_ATTR_SUCCESS; } +PyObject *KX_GameObject::pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + + // Only objects with a physics controller can be suspended + if (!self->GetPhysicsController()) { + PyErr_SetString(PyExc_AttributeError, "This object has not Physics Controller"); + return NULL; + } + + return PyBool_FromLong(self->IsDynamicsSuspended()); +} + PyObject *KX_GameObject::pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_GameObject* self = static_cast<KX_GameObject*>(self_v); @@ -2347,6 +2510,54 @@ int KX_GameObject::pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF return PY_SET_ATTR_SUCCESS; } +PyObject *KX_GameObject::pyattr_get_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject *self = static_cast<KX_GameObject*>(self_v); + PHY_IPhysicsController *spc = self->GetPhysicsController(); + return PyFloat_FromDouble(spc ? spc->GetAngularVelocityMin() : 0.0f); +} + +int KX_GameObject::pyattr_set_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject *self = static_cast<KX_GameObject*>(self_v); + PHY_IPhysicsController *spc = self->GetPhysicsController(); + MT_Scalar val = PyFloat_AsDouble(value); + if (val < 0.0f) { /* also accounts for non float */ + PyErr_SetString(PyExc_AttributeError, + "gameOb.angularVelocityMin = float: KX_GameObject, expected a nonnegative float"); + return PY_SET_ATTR_FAIL; + } + + if (spc) + spc->SetAngularVelocityMin(val); + + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_GameObject::pyattr_get_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject *self = static_cast<KX_GameObject*>(self_v); + PHY_IPhysicsController *spc = self->GetPhysicsController(); + return PyFloat_FromDouble(spc ? spc->GetAngularVelocityMax() : 0.0f); +} + +int KX_GameObject::pyattr_set_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject *self = static_cast<KX_GameObject*>(self_v); + PHY_IPhysicsController *spc = self->GetPhysicsController(); + MT_Scalar val = PyFloat_AsDouble(value); + if (val < 0.0f) { /* also accounts for non float */ + PyErr_SetString(PyExc_AttributeError, + "gameOb.angularVelocityMax = float: KX_GameObject, expected a nonnegative float"); + return PY_SET_ATTR_FAIL; + } + + if (spc) + spc->SetAngularVelocityMax(val); + + return PY_SET_ATTR_SUCCESS; +} + PyObject *KX_GameObject::pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { @@ -2393,7 +2604,9 @@ int KX_GameObject::pyattr_set_record_animation(void *self_v, const KX_PYATTRIBUT PyObject *KX_GameObject::pyattr_get_worldPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetWorldPosition()); @@ -2415,7 +2628,9 @@ int KX_GameObject::pyattr_set_worldPosition(void *self_v, const KX_PYATTRIBUTE_D PyObject *KX_GameObject::pyattr_get_localPosition(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_POS_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetLocalPosition()); @@ -2437,7 +2652,9 @@ int KX_GameObject::pyattr_set_localPosition(void *self_v, const KX_PYATTRIBUTE_D PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_INERTIA_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); if (self->GetPhysicsController1()) @@ -2449,7 +2666,9 @@ PyObject *KX_GameObject::pyattr_get_localInertia(void *self_v, const KX_PYATTRIB PyObject *KX_GameObject::pyattr_get_worldOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL); + return Matrix_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, 3, + mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetWorldOrientation()); @@ -2474,7 +2693,9 @@ int KX_GameObject::pyattr_set_worldOrientation(void *self_v, const KX_PYATTRIBUT PyObject *KX_GameObject::pyattr_get_localOrientation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Matrix_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, 3, mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL); + return Matrix_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, 3, + mathutils_kxgameob_matrix_cb_index, MATHUTILS_MAT_CB_ORI_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetLocalOrientation()); @@ -2498,7 +2719,9 @@ int KX_GameObject::pyattr_set_localOrientation(void *self_v, const KX_PYATTRIBUT PyObject *KX_GameObject::pyattr_get_worldScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetWorldScaling()); @@ -2520,7 +2743,9 @@ int KX_GameObject::pyattr_set_worldScaling(void *self_v, const KX_PYATTRIBUTE_DE PyObject *KX_GameObject::pyattr_get_localScaling(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_SCALE_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->NodeGetLocalScaling()); @@ -2622,7 +2847,9 @@ int KX_GameObject::pyattr_set_worldTransform(void *self_v, const KX_PYATTRIBUTE_ PyObject *KX_GameObject::pyattr_get_worldLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetLinearVelocity(false)); @@ -2644,7 +2871,9 @@ int KX_GameObject::pyattr_set_worldLinearVelocity(void *self_v, const KX_PYATTRI PyObject *KX_GameObject::pyattr_get_localLinearVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_LINVEL_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetLinearVelocity(true)); @@ -2666,7 +2895,9 @@ int KX_GameObject::pyattr_set_localLinearVelocity(void *self_v, const KX_PYATTRI PyObject *KX_GameObject::pyattr_get_worldAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_GLOBAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetAngularVelocity(false)); @@ -2688,7 +2919,9 @@ int KX_GameObject::pyattr_set_worldAngularVelocity(void *self_v, const KX_PYATTR PyObject *KX_GameObject::pyattr_get_localAngularVelocity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_ANGVEL_LOCAL); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(GetAngularVelocity(true)); @@ -2707,6 +2940,34 @@ int KX_GameObject::pyattr_set_localAngularVelocity(void *self_v, const KX_PYATTR return PY_SET_ATTR_SUCCESS; } +PyObject *KX_GameObject::pyattr_get_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + return PyFloat_FromDouble(self->getLinearDamping()); +} + +int KX_GameObject::pyattr_set_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + float val = PyFloat_AsDouble(value); + self->setLinearDamping(val); + return PY_SET_ATTR_SUCCESS; +} + +PyObject *KX_GameObject::pyattr_get_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + return PyFloat_FromDouble(self->getAngularDamping()); +} + +int KX_GameObject::pyattr_set_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_GameObject* self = static_cast<KX_GameObject*>(self_v); + float val = PyFloat_AsDouble(value); + self->setAngularDamping(val); + return PY_SET_ATTR_SUCCESS; +} + PyObject *KX_GameObject::pyattr_get_timeOffset(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { @@ -2781,7 +3042,9 @@ PyObject *KX_GameObject::pyattr_get_meshes(void *self_v, const KX_PYATTRIBUTE_DE PyObject *KX_GameObject::pyattr_get_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { #ifdef USE_MATHUTILS - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 4, mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 4, + mathutils_kxgameob_vector_cb_index, MATHUTILS_VEC_CB_OBJECT_COLOR); #else KX_GameObject* self = static_cast<KX_GameObject*>(self_v); return PyObjectFrom(self->GetObjectColor()); @@ -3003,6 +3266,18 @@ PyObject *KX_GameObject::PySetAngularVelocity(PyObject *args) return NULL; } +PyObject *KX_GameObject::PySetDamping(PyObject *args) +{ + float linear; + float angular; + + if (!PyArg_ParseTuple(args,"ff|i:setDamping", &linear, &angular)) + return NULL; + + setDamping(linear, angular); + Py_RETURN_NONE; +} + PyObject *KX_GameObject::PySetVisible(PyObject *args) { int visible, recursive = 0; @@ -3147,10 +3422,16 @@ PyObject *KX_GameObject::PyApplyImpulse(PyObject *args) -PyObject *KX_GameObject::PySuspendDynamics() +PyObject *KX_GameObject::PySuspendDynamics(PyObject *args) { + bool ghost = false; + + if (!PyArg_ParseTuple(args, "|b", &ghost)) + return NULL; + if (GetPhysicsController()) - GetPhysicsController()->SuspendDynamics(); + GetPhysicsController()->SuspendDynamics(ghost); + Py_RETURN_NONE; } @@ -3158,7 +3439,8 @@ PyObject *KX_GameObject::PySuspendDynamics() PyObject *KX_GameObject::PyRestoreDynamics() { - if (GetPhysicsController()) + // Child objects must be static, so we block changing to dynamic + if (GetPhysicsController() && !GetParent()) GetPhysicsController()->RestoreDynamics(); Py_RETURN_NONE; } @@ -3200,12 +3482,12 @@ PyObject *KX_GameObject::PyGetAxisVect(PyObject *value) PyObject *KX_GameObject::PyGetPhysicsId() { PHY_IPhysicsController* ctrl = GetPhysicsController(); - uint_ptr physid=0; + unsigned long long physid = 0; if (ctrl) { - physid= (uint_ptr)ctrl; + physid = (unsigned long long)ctrl; } - return PyLong_FromLong((long)physid); + return PyLong_FromUnsignedLongLong(physid); } PyObject *KX_GameObject::PyGetPropertyNames() @@ -3648,7 +3930,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, stopAction, "stopAction(layer=0)\n" "Stop playing the action on the given layer\n") { - short layer=0; + short layer = 0; if (!PyArg_ParseTuple(args, "|h:stopAction", &layer)) return NULL; @@ -3664,7 +3946,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getActionFrame, "getActionFrame(layer=0)\n" "Gets the current frame of the action playing in the supplied layer\n") { - short layer=0; + short layer = 0; if (!PyArg_ParseTuple(args, "|h:getActionFrame", &layer)) return NULL; @@ -3674,11 +3956,25 @@ KX_PYMETHODDEF_DOC(KX_GameObject, getActionFrame, return PyFloat_FromDouble(GetActionFrame(layer)); } +KX_PYMETHODDEF_DOC(KX_GameObject, getActionName, + "getActionName(layer=0)\n" + "Gets the name of the current action playing in the supplied layer\n") +{ + short layer = 0; + + if (!PyArg_ParseTuple(args, "|h:getActionName", &layer)) + return NULL; + + layer_check(layer, "getActionName"); + + return PyUnicode_FromString(GetActionName(layer)); +} + KX_PYMETHODDEF_DOC(KX_GameObject, setActionFrame, "setActionFrame(frame, layer=0)\n" "Set the current frame of the action playing in the supplied layer\n") { - short layer=0; + short layer = 0; float frame; if (!PyArg_ParseTuple(args, "f|h:setActionFrame", &frame, &layer)) @@ -3695,7 +3991,7 @@ KX_PYMETHODDEF_DOC(KX_GameObject, isPlayingAction, "isPlayingAction(layer=0)\n" "Checks to see if there is an action playing in the given layer\n") { - short layer=0; + short layer = 0; if (!PyArg_ParseTuple(args, "|h:isPlayingAction", &layer)) return NULL; @@ -3793,11 +4089,11 @@ bool ConvertPythonToGameObject(PyObject *value, KX_GameObject **object, bool py_ } } - if ( PyObject_TypeCheck(value, &KX_GameObject::Type) || - PyObject_TypeCheck(value, &KX_LightObject::Type) || - PyObject_TypeCheck(value, &KX_Camera::Type) || - PyObject_TypeCheck(value, &KX_FontObject::Type) || - PyObject_TypeCheck(value, &KX_NavMeshObject::Type)) + if (PyObject_TypeCheck(value, &KX_GameObject::Type) || + PyObject_TypeCheck(value, &KX_LightObject::Type) || + PyObject_TypeCheck(value, &KX_Camera::Type) || + PyObject_TypeCheck(value, &KX_FontObject::Type) || + PyObject_TypeCheck(value, &KX_NavMeshObject::Type)) { *object = static_cast<KX_GameObject*>BGE_PROXY_REF(value); diff --git a/source/gameengine/Ketsji/KX_GameObject.h b/source/gameengine/Ketsji/KX_GameObject.h index d4fa4851696..c10802a83b2 100644 --- a/source/gameengine/Ketsji/KX_GameObject.h +++ b/source/gameengine/Ketsji/KX_GameObject.h @@ -40,7 +40,7 @@ #include <stddef.h> -#include "ListValue.h" +#include "EXP_ListValue.h" #include "SCA_IObject.h" #include "SG_Node.h" #include "MT_Transform.h" @@ -49,6 +49,7 @@ #include "CTR_HashedPtr.h" #include "KX_Scene.h" #include "KX_KetsjiEngine.h" /* for m_anim_framerate */ +#include "DNA_constraint_types.h" /* for constraint replication */ #include "DNA_object_types.h" #include "SCA_LogicManager.h" /* for ConvertPythonToGameObject to search object names */ @@ -88,18 +89,19 @@ protected: int m_layer; std::vector<RAS_MeshObject*> m_meshes; std::vector<RAS_MeshObject*> m_lodmeshes; + int m_currentLodLevel; + short m_previousLodLevel; SG_QList m_meshSlots; // head of mesh slots of this struct Object* m_pBlenderObject; struct Object* m_pBlenderGroupObject; - bool m_bSuspendDynamics; bool m_bUseObjectColor; bool m_bIsNegativeScaling; MT_Vector4 m_objectColor; // Bit fields for user control over physics collisions - short m_userCollisionGroup; - short m_userCollisionMask; + unsigned short m_userCollisionGroup; + unsigned short m_userCollisionMask; // visible = user setting // culled = while rendering, depending on camera @@ -116,6 +118,7 @@ protected: SG_Node* m_pSGNode; MT_CmMatrix4x4 m_OpenGL_4x4Matrix; + std::vector<bRigidBodyJointConstraint*> m_constraints; KX_ObstacleSimulation* m_pObstacleSimulation; @@ -192,6 +195,14 @@ public: void UpdateBlenderObjectMatrix(Object* blendobj=NULL); + /** + * Used for constraint replication for group instances. + * The list of constraints is filled during data conversion. + */ + void AddConstraint(bRigidBodyJointConstraint *cons); + std::vector<bRigidBodyJointConstraint*> GetConstraints(); + void ClearConstraints(); + /** * Get a pointer to the game object that is the parent of * this object. Or NULL if there is no parent. The returned @@ -266,6 +277,11 @@ public: float GetActionFrame(short layer); /** + * Gets the name of the current action + */ + const char *GetActionName(short layer); + + /** * Sets the current frame of an action */ void SetActionFrame(short layer, float frame); @@ -291,6 +307,11 @@ public: void StopAction(short layer); /** + * Remove playing tagged actions. + */ + void RemoveTaggedActions(); + + /** * Check if an action has finished playing */ bool IsActionDone(short layer); @@ -506,8 +527,17 @@ public: */ void ActivateGraphicController(bool recurse); - void SetUserCollisionGroup(short filter); - void SetUserCollisionMask(short mask); + /** Set the object's collison group + * \param filter The group bitfield + */ + void SetUserCollisionGroup(unsigned short filter); + + /** Set the object's collison mask + * \param filter The mask bitfield + */ + void SetUserCollisionMask(unsigned short mask); + unsigned short GetUserCollisionGroup(); + unsigned short GetUserCollisionMask(); /** * Extra broadphase check for user controllable collisions */ @@ -607,6 +637,8 @@ public: return m_bDyna; } + bool IsDynamicsSuspended() const; + /** * Should we record animation for this object? */ @@ -684,6 +716,12 @@ public: bool local ); + virtual float getLinearDamping() const; + virtual float getAngularDamping() const; + virtual void setLinearDamping(float damping); + virtual void setAngularDamping(float damping); + virtual void setDamping(float linear, float angular); + /** * Update the physics object transform based upon the current SG_Node * position. @@ -852,10 +890,10 @@ public: /** * Was this object culled? */ - bool + inline bool GetCulled( void - ); + ) { return m_bCulled; } /** * Set culled flag of this object @@ -886,7 +924,7 @@ public: * Change the layer of the object (when it is added in another layer * than the original layer) */ - void + virtual void SetLayer( int l ); @@ -913,7 +951,7 @@ public: void RegisterCollisionCallbacks(); void UnregisterCollisionCallbacks(); - void RunCollisionCallbacks(KX_GameObject *collider); + void RunCollisionCallbacks(KX_GameObject *collider, const MT_Vector3 &point, const MT_Vector3 &normal); /** * Stop making progress */ @@ -965,6 +1003,7 @@ public: KX_PYMETHOD_VARARGS(KX_GameObject,GetAngularVelocity); KX_PYMETHOD_VARARGS(KX_GameObject,SetAngularVelocity); KX_PYMETHOD_VARARGS(KX_GameObject,GetVelocity); + KX_PYMETHOD_VARARGS(KX_GameObject,SetDamping); KX_PYMETHOD_NOARGS(KX_GameObject,GetReactionForce); @@ -976,7 +1015,7 @@ public: KX_PYMETHOD_O(KX_GameObject,SetState); KX_PYMETHOD_VARARGS(KX_GameObject,AlignAxisToVect); KX_PYMETHOD_O(KX_GameObject,GetAxisVect); - KX_PYMETHOD_NOARGS(KX_GameObject,SuspendDynamics); + KX_PYMETHOD_VARARGS(KX_GameObject,SuspendDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,RestoreDynamics); KX_PYMETHOD_NOARGS(KX_GameObject,EnableRigidBody); KX_PYMETHOD_NOARGS(KX_GameObject,DisableRigidBody); @@ -1003,6 +1042,7 @@ public: KX_PYMETHOD_DOC(KX_GameObject, playAction); KX_PYMETHOD_DOC(KX_GameObject, stopAction); KX_PYMETHOD_DOC(KX_GameObject, getActionFrame); + KX_PYMETHOD_DOC(KX_GameObject, getActionName); KX_PYMETHOD_DOC(KX_GameObject, setActionFrame); KX_PYMETHOD_DOC(KX_GameObject, isPlayingAction); @@ -1020,10 +1060,15 @@ public: static PyObject* pyattr_get_life(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_mass(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_is_suspend_dynamics(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_lin_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_lin_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_ang_vel_min(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_ang_vel_max(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_visible(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_record_animation(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); @@ -1066,10 +1111,18 @@ public: static int pyattr_set_obcolor(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_collisionCallbacks(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_collisionCallbacks(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_collisionGroup(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_collisionGroup(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_collisionMask(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_collisionMask(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_debug(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_debugRecursive(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_linearDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_angularDamping(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); /* Experimental! */ static PyObject* pyattr_get_sensors(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); diff --git a/source/gameengine/Ketsji/KX_ISceneConverter.h b/source/gameengine/Ketsji/KX_ISceneConverter.h index a07d4b2195c..2e1c16c6e32 100644 --- a/source/gameengine/Ketsji/KX_ISceneConverter.h +++ b/source/gameengine/Ketsji/KX_ISceneConverter.h @@ -33,7 +33,7 @@ #define __KX_ISCENECONVERTER_H__ #include "STR_String.h" -#include "KX_Python.h" +#include "EXP_Python.h" #ifdef WITH_CXX_GUARDEDALLOC #include "MEM_guardedalloc.h" @@ -45,8 +45,8 @@ class KX_ISceneConverter { public: - KX_ISceneConverter() :addInitFromFrame(false) {}//this addInitFromFrame is a back hack, todo remove - virtual ~KX_ISceneConverter () {}; + KX_ISceneConverter() {} + virtual ~KX_ISceneConverter () {} /* * scenename: name of the scene to be converted, @@ -59,7 +59,7 @@ public: class RAS_IRasterizer* rendertools, class RAS_ICanvas* canvas, bool libloading=false)=0; - + virtual void RemoveScene(class KX_Scene *scene)=0; // handle any pending merges from asynchronous loads @@ -69,11 +69,9 @@ public: virtual void SetNewFileName(const STR_String& filename) = 0; virtual bool TryAndLoadNewFile() = 0; - bool addInitFromFrame;//rcruiz virtual void ResetPhysicsObjectsAnimationIpo(bool clearIpo) = 0; - ///this generates ipo curves for position, rotation, allowing to use game physics in animation virtual void WritePhysicsObjectToAnimationIpo(int frameNumber) = 0; virtual void TestHandlesPhysicsObjectToAnimationIpo() = 0; diff --git a/source/gameengine/Ketsji/KX_IpoActuator.cpp b/source/gameengine/Ketsji/KX_IpoActuator.cpp index 1597d7f8809..ec7a4146b7d 100644 --- a/source/gameengine/Ketsji/KX_IpoActuator.cpp +++ b/source/gameengine/Ketsji/KX_IpoActuator.cpp @@ -36,7 +36,7 @@ #include "KX_IpoActuator.h" #include "KX_GameObject.h" -#include "FloatValue.h" +#include "EXP_FloatValue.h" #include "KX_KetsjiEngine.h" diff --git a/source/gameengine/Ketsji/KX_IpoConvert.cpp b/source/gameengine/Ketsji/KX_IpoConvert.cpp index 57130bf57b2..7b00760ee7b 100644 --- a/source/gameengine/Ketsji/KX_IpoConvert.cpp +++ b/source/gameengine/Ketsji/KX_IpoConvert.cpp @@ -269,52 +269,80 @@ SG_Controller *BL_CreateCameraIPO(struct bAction *action, KX_GameObject* camera return ipocontr; } -void BL_ConvertWorldIpos(struct World* blenderworld,KX_BlenderSceneConverter *converter) -{ - - if (blenderworld->adt) { - KX_WorldIpoController* ipocontr = new KX_WorldIpoController(); - -// Erwin, hook up the world ipo controller here -// Gino: hook it up to what ? -// is there a userinterface element for that ? -// for now, we have some new python hooks to access the data, for a work-around - - ipocontr->m_mist_start = blenderworld->miststa; - ipocontr->m_mist_dist = blenderworld->mistdist; - ipocontr->m_mist_rgb[0] = blenderworld->horr; - ipocontr->m_mist_rgb[1] = blenderworld->horg; - ipocontr->m_mist_rgb[2] = blenderworld->horb; +SG_Controller * BL_CreateWorldIPO( bAction *action, struct World *blenderworld, KX_BlenderSceneConverter *converter ) +{ + KX_WorldIpoController *ipocontr = NULL; - BL_InterpolatorList *adtList= GetAdtList(blenderworld->adt->action, converter); + if (blenderworld) { + BL_InterpolatorList *adtList = GetAdtList(action, converter); - // For each active channel in the adtList add an - // interpolator to the game object. - + // For each active channel in the adtList add an interpolator to the game object. KX_IInterpolator *interpolator; KX_IScalarInterpolator *interp; - + + for (int i=0; i<3; i++) { + if ((interp = adtList->GetScalarInterpolator("ambient_color", i))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_ambi_rgb[i], interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyAmbientColor(true); + } + } + for (int i=0; i<3; i++) { if ((interp = adtList->GetScalarInterpolator("horizon_color", i))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_rgb[i], interp); + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_hori_rgb[i], interp); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyMistColor(true); + ipocontr->SetModifyHorizonColor(true); } } - if ((interp = adtList->GetScalarInterpolator("mist.depth", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp); + if ((interp = adtList->GetScalarInterpolator("mist_settings.start", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp); + ipocontr->AddInterpolator(interpolator); + ipocontr->SetModifyMistStart(true); + } + + if ((interp = adtList->GetScalarInterpolator("mist_settings.depth", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_dist, interp); ipocontr->AddInterpolator(interpolator); ipocontr->SetModifyMistDist(true); } - if ((interp = adtList->GetScalarInterpolator("mist.start", 0))) { - interpolator= new KX_ScalarInterpolator(&ipocontr->m_mist_start, interp); + if ((interp = adtList->GetScalarInterpolator("mist_settings.intensity", 0))) { + if (!ipocontr) { + ipocontr = new KX_WorldIpoController(); + } + interpolator = new KX_ScalarInterpolator(&ipocontr->m_mist_intensity, interp); ipocontr->AddInterpolator(interpolator); - ipocontr->SetModifyMistStart(true); + ipocontr->SetModifyMistIntensity(true); + } + + if (ipocontr) { + ipocontr->m_mist_start = blenderworld->miststa; + ipocontr->m_mist_dist = blenderworld->mistdist; + ipocontr->m_mist_intensity = blenderworld->misi; + ipocontr->m_hori_rgb[0] = blenderworld->horr; + ipocontr->m_hori_rgb[1] = blenderworld->horg; + ipocontr->m_hori_rgb[2] = blenderworld->horb; + ipocontr->m_ambi_rgb[0] = blenderworld->ambr; + ipocontr->m_ambi_rgb[1] = blenderworld->ambg; + ipocontr->m_ambi_rgb[2] = blenderworld->ambb; } } + return ipocontr; } SG_Controller *BL_CreateMaterialIpo( @@ -368,7 +396,7 @@ SG_Controller *BL_CreateMaterialIpo( ipocontr->AddInterpolator(interpolator); } - if ((sinterp = adtList->GetScalarInterpolator("specularity", 0))) { + if ((sinterp = adtList->GetScalarInterpolator("specular_intensity", 0))) { if (!ipocontr) { ipocontr = new KX_MaterialIpoController(matname_hash); } @@ -376,7 +404,7 @@ SG_Controller *BL_CreateMaterialIpo( ipocontr->AddInterpolator(interpolator); } - if ((sinterp = adtList->GetScalarInterpolator("diffuse_reflection", 0))) { + if ((sinterp = adtList->GetScalarInterpolator("diffuse_intensity", 0))) { if (!ipocontr) { ipocontr = new KX_MaterialIpoController(matname_hash); } diff --git a/source/gameengine/Ketsji/KX_IpoConvert.h b/source/gameengine/Ketsji/KX_IpoConvert.h index a653e4e110b..6db43552811 100644 --- a/source/gameengine/Ketsji/KX_IpoConvert.h +++ b/source/gameengine/Ketsji/KX_IpoConvert.h @@ -50,7 +50,8 @@ SG_Controller *BL_CreateLampIPO(bAction *action, KX_GameObject* lightobj, KX_BlenderSceneConverter *converter); -void BL_ConvertWorldIpos(struct World* blenderworld, +SG_Controller *BL_CreateWorldIPO(bAction *action, + struct World *blenderworld, KX_BlenderSceneConverter *converter); SG_Controller *BL_CreateCameraIPO(bAction *action, diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 14772cda113..72c512589a4 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -41,11 +41,11 @@ #include "KX_KetsjiEngine.h" -#include "ListValue.h" -#include "IntValue.h" -#include "VectorValue.h" -#include "BoolValue.h" -#include "FloatValue.h" +#include "EXP_ListValue.h" +#include "EXP_IntValue.h" +#include "EXP_VectorValue.h" +#include "EXP_BoolValue.h" +#include "EXP_FloatValue.h" #include "RAS_BucketManager.h" #include "RAS_Rect.h" @@ -62,11 +62,6 @@ #include "KX_PyConstraintBinding.h" #include "PHY_IPhysicsEnvironment.h" -#ifdef WITH_AUDASPACE -# include "AUD_C-API.h" -# include "AUD_I3DDevice.h" -#endif - #include "NG_NetworkScene.h" #include "NG_NetworkDeviceInterface.h" @@ -80,9 +75,6 @@ #include "KX_NavMeshObject.h" -// If define: little test for Nzc: guarded drawing. If the canvas is -// not valid, skip rendering this frame. -//#define NZC_GUARDED_OUTPUT #define DEFAULT_LOGIC_TIC_RATE 60.0 //#define DEFAULT_PHYSICS_TIC_RATE 60.0 @@ -140,6 +132,7 @@ KX_KetsjiEngine::KX_KetsjiEngine(KX_ISystem* system) m_frameTime(0.f), m_clockTime(0.f), m_previousClockTime(0.f), + m_previousAnimTime(0.f), m_exitcode(KX_EXIT_REQUEST_NO_REQUEST), @@ -314,10 +307,11 @@ void KX_KetsjiEngine::RenderDome() // for each scene, call the proceed functions { scene = *sceneit; + KX_SetActiveScene(scene); KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); // shadow buffers if (i == 0) { @@ -391,8 +385,10 @@ void KX_KetsjiEngine::RenderDome() ); } m_dome->Draw(); + // Draw Callback for the last scene #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); scene->RunDrawingCallbacks(scene->GetPostDrawCB()); #endif EndFrame(); @@ -477,7 +473,7 @@ void KX_KetsjiEngine::ClearFrame() if (doclear) { KX_Scene* firstscene = *m_scenes.begin(); - SetBackGround(firstscene->GetWorldInfo()); + firstscene->GetWorldInfo()->UpdateBackGround(); m_canvas->SetViewPort(clearvp.GetLeft(), clearvp.GetBottom(), clearvp.GetRight(), clearvp.GetTop()); @@ -686,6 +682,9 @@ bool KX_KetsjiEngine::NextFrame() SG_SetActiveStage(SG_STAGE_ACTUATOR_UPDATE); scene->UpdateParents(m_frameTime); + // update levels of detail + scene->UpdateObjectLods(); + m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_PHYSICS2); scene->GetPhysicsEnvironment()->BeginFrame(); @@ -730,64 +729,6 @@ bool KX_KetsjiEngine::NextFrame() frames--; } - bool bUseAsyncLogicBricks= false;//true; - - if (bUseAsyncLogicBricks) - { - // Logic update sub frame: this will let some logic bricks run at the - // full frame rate. - for (sceneit = m_scenes.begin();sceneit != m_scenes.end(); ++sceneit) - // for each scene, call the proceed functions - { - KX_Scene* scene = *sceneit; - - if (!scene->IsSuspended()) - { - // if the scene was suspended recalcutlate the delta tu "curtime" - m_suspendedtime = scene->getSuspendedTime(); - if (scene->getSuspendedTime()!=0.0) - scene->setSuspendedDelta(scene->getSuspendedDelta()+m_clockTime-scene->getSuspendedTime()); - m_suspendeddelta = scene->getSuspendedDelta(); - - // set Python hooks for each scene -#ifdef WITH_PYTHON - PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); -#endif - KX_SetActiveScene(scene); - - m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); - SG_SetActiveStage(SG_STAGE_PHYSICS1); - scene->UpdateParents(m_clockTime); - - // Perform physics calculations on the scene. This can involve - // many iterations of the physics solver. - m_logger->StartLog(tc_physics, m_kxsystem->GetTimeInSeconds(), true); - scene->GetPhysicsEnvironment()->ProceedDeltaTime(m_clockTime,timestep,timestep); - // Update scenegraph after physics step. This maps physics calculations - // into node positions. - m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); - SG_SetActiveStage(SG_STAGE_PHYSICS2); - scene->UpdateParents(m_clockTime); - - // Do some cleanup work for this logic frame - m_logger->StartLog(tc_logic, m_kxsystem->GetTimeInSeconds(), true); - scene->LogicUpdateFrame(m_clockTime, false); - - // Actuators can affect the scenegraph - m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); - SG_SetActiveStage(SG_STAGE_ACTUATOR); - scene->UpdateParents(m_clockTime); - - scene->setSuspendedTime(0.0); - } // suspended - else - if (scene->getSuspendedTime()==0.0) - scene->setSuspendedTime(m_clockTime); - - m_logger->StartLog(tc_services, m_kxsystem->GetTimeInSeconds(), true); - } - } - // Start logging time spend outside main loop m_logger->StartLog(tc_outside, m_kxsystem->GetTimeInSeconds(), true); @@ -855,7 +796,7 @@ void KX_KetsjiEngine::Render() KX_Scene* scene = *sceneit; KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); // this is now done incrementatlly in KX_Scene::CalculateVisibleMeshes //scene->UpdateMeshTransformations(); @@ -912,7 +853,7 @@ void KX_KetsjiEngine::Render() KX_Camera* cam = scene->GetActiveCamera(); // pass the scene's worldsettings to the rasterizer - SetWorldSettings(scene->GetWorldInfo()); + scene->GetWorldInfo()->UpdateWorldSettings(); if (scene->IsClearingZBuffer()) m_rasterizer->ClearDepthBuffer(); @@ -992,54 +933,6 @@ const STR_String& KX_KetsjiEngine::GetExitString() return m_exitstring; } - -void KX_KetsjiEngine::SetBackGround(KX_WorldInfo* wi) -{ - if (wi->hasWorld()) - { - if (m_rasterizer->GetDrawingMode() == RAS_IRasterizer::KX_TEXTURED) - { - m_rasterizer->SetBackColor( - wi->getBackColorRed(), - wi->getBackColorGreen(), - wi->getBackColorBlue(), - 0.0 - ); - } - } -} - - - -void KX_KetsjiEngine::SetWorldSettings(KX_WorldInfo* wi) -{ - if (wi->hasWorld()) - { - // ... - m_rasterizer->SetAmbientColor( - wi->getAmbientColorRed(), - wi->getAmbientColorGreen(), - wi->getAmbientColorBlue() - ); - - if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) - { - if (wi->hasMist()) - { - m_rasterizer->SetFog( - wi->getMistStart(), - wi->getMistDistance(), - wi->getMistColorRed(), - wi->getMistColorGreen(), - wi->getMistColorBlue() - ); - } - } - } -} - - - void KX_KetsjiEngine::EnableCameraOverride(const STR_String& forscene) { m_overrideCam = true; @@ -1124,6 +1017,23 @@ void KX_KetsjiEngine::GetSceneViewport(KX_Scene *scene, KX_Camera* cam, RAS_Rect } } +void KX_KetsjiEngine::UpdateAnimations(KX_Scene *scene) +{ + // Handle the animations independently of the logic time step + if (GetRestrictAnimationFPS()) { + double anim_timestep = 1.0 / KX_GetActiveScene()->GetAnimationFPS(); + if (m_frameTime - m_previousAnimTime > anim_timestep || m_frameTime == m_previousAnimTime) { + // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep) + // printf("Anim fps: %f\n", 1.0/(m_frameTime - m_previousAnimTime)); + m_previousAnimTime = m_frameTime; + for (KX_SceneList::iterator sceneit = m_scenes.begin(); sceneit != m_scenes.end(); ++sceneit) + (*sceneit)->UpdateAnimations(m_frameTime); + } + } + else + scene->UpdateAnimations(m_frameTime); +} + void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) { CListValue *lightlist = scene->GetLightList(); @@ -1155,14 +1065,13 @@ void KX_KetsjiEngine::RenderShadowBuffers(KX_Scene *scene) raslight->BindShadowBuffer(m_canvas, cam, camtrans); /* update scene */ - m_logger->StartLog(tc_scenegraph, m_kxsystem->GetTimeInSeconds(), true); scene->CalculateVisibleMeshes(m_rasterizer, cam, raslight->GetShadowLayer()); m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true); - scene->UpdateAnimations(GetFrameTime()); - + SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE); + UpdateAnimations(scene); m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true); - + SG_SetActiveStage(SG_STAGE_RENDER); /* render */ m_rasterizer->ClearDepthBuffer(); @@ -1187,6 +1096,13 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) if (!cam) return; + + KX_SetActiveScene(scene); + +#ifdef WITH_PYTHON + scene->RunDrawingCallbacks(scene->GetPreDrawSetupCB()); +#endif + GetSceneViewport(scene, cam, area, viewport); // store the computed viewport in the scene @@ -1238,6 +1154,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) nearfrust, farfrust, cam->GetSensorFit(), + cam->GetShiftHorizontal(), + cam->GetShiftVertical(), frustum ); if (!cam->GetViewport()) { @@ -1258,6 +1176,8 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) cam->GetSensorWidth(), cam->GetSensorHeight(), cam->GetSensorFit(), + cam->GetShiftHorizontal(), + cam->GetShiftVertical(), nearfrust, farfrust, frustum @@ -1297,13 +1217,13 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) m_logger->StartLog(tc_animations, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_ANIMATION_UPDATE); - - scene->UpdateAnimations(GetFrameTime()); + UpdateAnimations(scene); m_logger->StartLog(tc_rasterizer, m_kxsystem->GetTimeInSeconds(), true); SG_SetActiveStage(SG_STAGE_RENDER); #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); // Run any pre-drawing python callbacks scene->RunDrawingCallbacks(scene->GetPreDrawCB()); #endif @@ -1322,13 +1242,20 @@ void KX_KetsjiEngine::RenderFrame(KX_Scene* scene, KX_Camera* cam) */ void KX_KetsjiEngine::PostRenderScene(KX_Scene* scene) { + KX_SetActiveScene(scene); + // We need to first make sure our viewport is correct (enabling multiple viewports can mess this up) m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), m_canvas->GetHeight()); - m_rasterizer->FlushDebugShapes(); + m_rasterizer->FlushDebugShapes(scene); scene->Render2DFilters(m_canvas); + #ifdef WITH_PYTHON + PHY_SetActiveEnvironment(scene->GetPhysicsEnvironment()); scene->RunDrawingCallbacks(scene->GetPostDrawCB()); + + // Python draw callback can also call debug draw functions, so we have to clear debug shapes. + m_rasterizer->FlushDebugShapes(scene); #endif } @@ -1734,18 +1661,17 @@ void KX_KetsjiEngine::AddScheduledScenes() bool KX_KetsjiEngine::ReplaceScene(const STR_String& oldscene,const STR_String& newscene) { - // Don't allow replacement if the new scene doesn't exists. - // Allows smarter game design (used to have no check here). - // Note that it creates a small backward compatbility issue - // for a game that did a replace followed by a lib load with the - // new scene in the lib => it won't work anymore, the lib - // must be loaded before doing the replace. - if (m_sceneconverter->GetBlenderSceneForName(newscene) != NULL) - { - m_replace_scenes.push_back(std::make_pair(oldscene,newscene)); - return true; - } - return false; + // Don't allow replacement if the new scene doesn't exists. + // Allows smarter game design (used to have no check here). + // Note that it creates a small backward compatbility issue + // for a game that did a replace followed by a lib load with the + // new scene in the lib => it won't work anymore, the lib + // must be loaded before doing the replace. + if (m_sceneconverter->GetBlenderSceneForName(newscene) != NULL) { + m_replace_scenes.push_back(std::make_pair(oldscene,newscene)); + return true; + } + return false; } // replace scene is not the same as removing and adding because the @@ -1767,21 +1693,20 @@ void KX_KetsjiEngine::ReplaceScheduledScenes() int i=0; /* Scenes are not supposed to be included twice... I think */ KX_SceneList::iterator sceneit; - for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++) - { - KX_Scene* scene = *sceneit; - if (scene->GetName() == oldscenename) - { - // avoid crash if the new scene doesn't exist, just do nothing - Scene *blScene = m_sceneconverter->GetBlenderSceneForName(newscenename); - if (blScene) { - m_sceneconverter->RemoveScene(scene); - KX_Scene* tmpscene = CreateScene(blScene); - m_scenes[i]=tmpscene; - PostProcessScene(tmpscene); - } else { - printf("warning: scene %s could not be found, not replaced!\n",newscenename.ReadPtr()); - } + for (sceneit = m_scenes.begin();sceneit != m_scenes.end() ; sceneit++) { + KX_Scene* scene = *sceneit; + if (scene->GetName() == oldscenename) { + // avoid crash if the new scene doesn't exist, just do nothing + Scene *blScene = m_sceneconverter->GetBlenderSceneForName(newscenename); + if (blScene) { + m_sceneconverter->RemoveScene(scene); + KX_Scene* tmpscene = CreateScene(blScene); + m_scenes[i]=tmpscene; + PostProcessScene(tmpscene); + } + else { + printf("warning: scene %s could not be found, not replaced!\n",newscenename.ReadPtr()); + } } i++; } @@ -1825,6 +1750,16 @@ void KX_KetsjiEngine::SetAnimRecordMode(bool animation_record, int startFrame) m_currentFrame = startFrame; } +int KX_KetsjiEngine::getAnimRecordFrame() const +{ + return m_currentFrame; +} + +void KX_KetsjiEngine::setAnimRecordFrame(int framenr) +{ + m_currentFrame = framenr; +} + bool KX_KetsjiEngine::GetUseFixedTime(void) const { return m_bFixedTime; diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.h b/source/gameengine/Ketsji/KX_KetsjiEngine.h index 2b80e3bd69a..04e09c8db15 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.h +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.h @@ -38,7 +38,7 @@ #include "STR_String.h" #include "KX_ISystem.h" #include "KX_Scene.h" -#include "KX_Python.h" +#include "EXP_Python.h" #include "KX_WorldInfo.h" #include <vector> @@ -111,6 +111,7 @@ private: double m_frameTime;//discrete timestamp of the 'game logic frame' double m_clockTime;//current time double m_previousClockTime;//previous clock time + double m_previousAnimTime; //the last time animations were updated double m_remainingTime; static int m_maxLogicFrame; /* maximum number of consecutive logic frame */ @@ -204,14 +205,12 @@ private: void PostRenderScene(KX_Scene* scene); void RenderDebugProperties(); void RenderShadowBuffers(KX_Scene *scene); - void SetBackGround(KX_WorldInfo* worldinfo); public: KX_KetsjiEngine(class KX_ISystem* system); virtual ~KX_KetsjiEngine(); // set the devices and stuff. the client must take care of creating these - void SetWorldSettings(KX_WorldInfo* worldinfo); void SetKeyboardDevice(SCA_IInputDevice* keyboarddevice); void SetMouseDevice(SCA_IInputDevice* mousedevice); void SetNetworkDevice(NG_NetworkDeviceInterface* networkdevice); @@ -226,6 +225,9 @@ public: KX_ISceneConverter* GetSceneConverter() { return m_sceneconverter; } void SetAnimRecordMode(bool animation_record, int startFrame); + int getAnimRecordFrame() const; + void setAnimRecordFrame(int framenr); + RAS_IRasterizer* GetRasterizer() { return m_rasterizer; } RAS_ICanvas* GetCanvas() { return m_canvas; } SCA_IInputDevice* GetKeyboardDevice() { return m_keyboarddevice; } @@ -258,7 +260,7 @@ public: void ConvertAndAddScene(const STR_String& scenename,bool overlay); void RemoveScene(const STR_String& scenename); - bool ReplaceScene(const STR_String& oldscene,const STR_String& newscene); + bool ReplaceScene(const STR_String& oldscene,const STR_String& newscene); void SuspendScene(const STR_String& scenename); void ResumeScene(const STR_String& scenename); @@ -273,6 +275,9 @@ public: void SetCameraOverrideViewMatrix(const MT_CmMatrix4x4& mat); void SetCameraOverrideClipping(float near, float far); void SetCameraOverrideLens(float lens); + + // Update animations for object in this scene + void UpdateAnimations(KX_Scene *scene); /** * Sets display of all frames. diff --git a/source/gameengine/Ketsji/KX_Light.cpp b/source/gameengine/Ketsji/KX_Light.cpp index 33cfec57fc0..0dec5715588 100644 --- a/source/gameengine/Ketsji/KX_Light.cpp +++ b/source/gameengine/Ketsji/KX_Light.cpp @@ -108,6 +108,7 @@ void KX_LightObject::UpdateScene(KX_Scene *kxscene) void KX_LightObject::SetLayer(int layer) { + KX_GameObject::SetLayer(layer); m_lightobj->m_layer = layer; } @@ -166,27 +167,31 @@ PyAttributeDef KX_LightObject::Attributes[] = { PyObject *KX_LightObject::pyattr_get_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - KX_LightObject* self = static_cast<KX_LightObject*>(self_v); + KX_LightObject *self = static_cast<KX_LightObject *>(self_v); return PyLong_FromLong(self->m_lightobj->m_layer); } int KX_LightObject::pyattr_set_layer(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { - KX_LightObject* self = static_cast<KX_LightObject*>(self_v); + KX_LightObject *self = static_cast<KX_LightObject *>(self_v); + int layer = PyLong_AsLong(value); - if (PyLong_Check(value)) { - int val = PyLong_AsLong(value); - if (val < 1) - val = 1; - else if (val > 20) - val = 20; + if (layer == -1 && PyErr_Occurred()) { + PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } - self->m_lightobj->m_layer = val; - return PY_SET_ATTR_SUCCESS; + if (layer < 1) { + PyErr_Format(PyExc_TypeError, "expected an integer greater than 1 for attribute \"%s\"", attrdef->m_name); + return PY_SET_ATTR_FAIL; + } + else if(layer > MAX_LIGHT_LAYERS) { + PyErr_Format(PyExc_TypeError, "expected an integer less than %i for attribute \"%s\"", MAX_LIGHT_LAYERS, attrdef->m_name); + return PY_SET_ATTR_FAIL; } - PyErr_Format(PyExc_TypeError, "expected an integer for attribute \"%s\"", attrdef->m_name); - return PY_SET_ATTR_FAIL; + self->SetLayer(layer); + return PY_SET_ATTR_SUCCESS; } PyObject *KX_LightObject::pyattr_get_energy(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) diff --git a/source/gameengine/Ketsji/KX_Light.h b/source/gameengine/Ketsji/KX_Light.h index 503ed7411e9..3a58584223d 100644 --- a/source/gameengine/Ketsji/KX_Light.h +++ b/source/gameengine/Ketsji/KX_Light.h @@ -34,6 +34,8 @@ #include "KX_GameObject.h" +#define MAX_LIGHT_LAYERS ((1 << 20) - 1) + struct GPULamp; struct Scene; struct Base; @@ -58,7 +60,7 @@ public: RAS_ILightObject* GetLightData() { return m_lightobj;} void UpdateScene(class KX_Scene *kxscene); - void SetLayer(int layer); + virtual void SetLayer(int layer); virtual int GetGameObjectType() { return OBJ_LIGHT; } diff --git a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp index a9617aa47b8..1faf8f17d54 100644 --- a/source/gameengine/Ketsji/KX_MaterialIpoController.cpp +++ b/source/gameengine/Ketsji/KX_MaterialIpoController.cpp @@ -32,21 +32,6 @@ bool KX_MaterialIpoController::Update(double currentTime) { if (m_modified) { - m_rgba[0]=0; - m_rgba[1]=0; - m_rgba[2]=0; - m_rgba[3]=0; - - m_specrgb[0] =0; - m_specrgb[1] =0; - m_specrgb[2] =0; - m_hard =0; - m_spec=0; - m_ref=0; - m_emit=0; - m_alpha = 0; - - T_InterpolatorList::iterator i; for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { (*i)->Execute(m_ipotime); diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index a6f2f728674..c98766c9c81 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -43,7 +43,7 @@ #include "KX_PyMath.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" PyTypeObject KX_MeshProxy::Type = { PyVarObject_HEAD_INIT(NULL, 0) diff --git a/source/gameengine/Ketsji/KX_MouseActuator.cpp b/source/gameengine/Ketsji/KX_MouseActuator.cpp index aae5d18189a..154ad1da3a1 100644 --- a/source/gameengine/Ketsji/KX_MouseActuator.cpp +++ b/source/gameengine/Ketsji/KX_MouseActuator.cpp @@ -126,24 +126,33 @@ bool KX_MouseActuator::Update() float movement[2]; MT_Vector3 rotation; float setposition[2] = {0.0}; + float center_x = 0.5, center_y = 0.5; getMousePosition(position); movement[0] = position[0]; movement[1] = position[1]; + //preventing undesired drifting when resolution is odd + if ((m_canvas->GetWidth() % 2) != 0) { + center_x = ((m_canvas->GetWidth() - 1.0) / 2.0) / (m_canvas->GetWidth()); + } + if ((m_canvas->GetHeight() % 2) != 0) { + center_y = ((m_canvas->GetHeight() - 1.0) / 2.0) / (m_canvas->GetHeight()); + } + //preventing initial skipping. if ((m_oldposition[0] <= -0.9) && (m_oldposition[1] <= -0.9)) { if (m_reset_x) { - m_oldposition[0] = 0.5; + m_oldposition[0] = center_x; } else { m_oldposition[0] = position[0]; } if (m_reset_y) { - m_oldposition[1] = 0.5; + m_oldposition[1] = center_y; } else { m_oldposition[1] = position[1]; @@ -156,8 +165,8 @@ bool KX_MouseActuator::Update() if (m_use_axis_x) { if (m_reset_x) { - setposition[0] = 0.5; - movement[0] -= 0.5; + setposition[0] = center_x; + movement[0] -= center_x; } else { setposition[0] = position[0]; @@ -166,12 +175,10 @@ bool KX_MouseActuator::Update() movement[0] *= -1.0; - /* Don't apply the rotation when width resolution is odd (+ little movement) to - avoid undesired drifting or when we are under a certain threshold for mouse + /* Don't apply the rotation when we are under a certain threshold for mouse movement */ - if (!((m_canvas->GetWidth() % 2 != 0) && MT_abs(movement[0]) < 0.01) && - ((movement[0] > (m_threshold[0] / 10.0)) || + if (((movement[0] > (m_threshold[0] / 10.0)) || ((movement[0] * (-1.0)) > (m_threshold[0] / 10.0)))) { movement[0] *= m_sensitivity[0]; @@ -209,15 +216,15 @@ bool KX_MouseActuator::Update() } } else { - setposition[0] = 0.5; + setposition[0] = center_x; } //Calculating Y axis. if (m_use_axis_y) { if (m_reset_y) { - setposition[1] = 0.5; - movement[1] -= 0.5; + setposition[1] = center_y; + movement[1] -= center_y; } else { setposition[1] = position[1]; @@ -226,12 +233,10 @@ bool KX_MouseActuator::Update() movement[1] *= -1.0; - /* Don't apply the rotation when height resolution is odd (+ little movement) to - avoid undesired drifting or when we are under a certain threshold for mouse + /* Don't apply the rotation when we are under a certain threshold for mouse movement */ - if (!((m_canvas->GetHeight() % 2 != 0) && MT_abs(movement[1]) < 0.01) && - ((movement[1] > (m_threshold[1] / 10.0)) || + if (((movement[1] > (m_threshold[1] / 10.0)) || ((movement[1] * (-1.0)) > (m_threshold[1] / 10.0)))) { movement[1] *= m_sensitivity[1]; @@ -270,10 +275,13 @@ bool KX_MouseActuator::Update() } } else { - setposition[1] = 0.5; + setposition[1] = center_y; } - setMousePosition(setposition[0], setposition[1]); + // only trigger mouse event when it is necessary + if (m_oldposition[0] != position[0] || m_oldposition[1] != position[1]) { + setMousePosition(setposition[0], setposition[1]); + } m_oldposition[0] = position[0]; m_oldposition[1] = position[1]; @@ -311,7 +319,7 @@ void KX_MouseActuator::ProcessReplica() void KX_MouseActuator::getMousePosition(float* pos) { - MT_assert(!m_mouse); + MT_assert(m_mouse); const SCA_InputEvent & xevent = m_mouse->GetEventValue(SCA_IInputDevice::KX_MOUSEX); const SCA_InputEvent & yevent = m_mouse->GetEventValue(SCA_IInputDevice::KX_MOUSEY); @@ -329,7 +337,7 @@ void KX_MouseActuator::setMousePosition(float fx, float fy) m_canvas->SetMousePosition(x, y); } -#ifndef DISABLE_PYTHON +#ifdef WITH_PYTHON /* ------------------------------------------------------------------------- */ /* Python functions */ @@ -399,8 +407,8 @@ int KX_MouseActuator::pyattr_set_limit_x(void *self_v, const KX_PYATTRIBUTE_DEF if (PyList_Size(value) != 2) return PY_SET_ATTR_FAIL; - item1 = PyList_GetItem(value, 0); - item2 = PyList_GetItem(value, 1); + item1 = PyList_GET_ITEM(value, 0); + item2 = PyList_GET_ITEM(value, 1); if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) { return PY_SET_ATTR_FAIL; @@ -430,8 +438,8 @@ int KX_MouseActuator::pyattr_set_limit_y(void *self_v, const KX_PYATTRIBUTE_DEF if (PyList_Size(value) != 2) return PY_SET_ATTR_FAIL; - item1 = PyList_GetItem(value, 0); - item2 = PyList_GetItem(value, 1); + item1 = PyList_GET_ITEM(value, 0); + item2 = PyList_GET_ITEM(value, 1); if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) { return PY_SET_ATTR_FAIL; @@ -461,8 +469,8 @@ int KX_MouseActuator::pyattr_set_angle(void *self_v, const KX_PYATTRIBUTE_DEF *a if (PyList_Size(value) != 2) return PY_SET_ATTR_FAIL; - item1 = PyList_GetItem(value, 0); - item2 = PyList_GetItem(value, 1); + item1 = PyList_GET_ITEM(value, 0); + item2 = PyList_GET_ITEM(value, 1); if (!(PyFloat_Check(item1)) || !(PyFloat_Check(item2))) { return PY_SET_ATTR_FAIL; @@ -528,4 +536,4 @@ PyObject* KX_MouseActuator::PyReset() Py_RETURN_NONE; } -#endif +#endif /* WITH_PYTHON */ diff --git a/source/gameengine/Ketsji/KX_MouseActuator.h b/source/gameengine/Ketsji/KX_MouseActuator.h index bf90bd21dac..e244e271428 100644 --- a/source/gameengine/Ketsji/KX_MouseActuator.h +++ b/source/gameengine/Ketsji/KX_MouseActuator.h @@ -104,6 +104,9 @@ public: virtual void getMousePosition(float*); virtual void setMousePosition(float, float); + +#ifdef WITH_PYTHON + /* --------------------------------------------------------------------- */ /* Python interface ---------------------------------------------------- */ /* --------------------------------------------------------------------- */ @@ -122,6 +125,8 @@ public: static PyObject* pyattr_get_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_angle(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); +#endif /* WITH_PYTHON */ + }; #endif //__KX_MOUSEACTUATOR_DOC diff --git a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp index a9f6bb0d2ff..46f27e1a2df 100644 --- a/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp +++ b/source/gameengine/Ketsji/KX_MouseFocusSensor.cpp @@ -36,10 +36,13 @@ # pragma warning(disable:4786) #endif +#include <stdio.h> + #include "MT_Point3.h" #include "RAS_FramingManager.h" #include "RAS_ICanvas.h" #include "RAS_IRasterizer.h" +#include "RAS_MeshObject.h" #include "SCA_IScene.h" #include "KX_Scene.h" #include "KX_Camera.h" @@ -163,15 +166,17 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *r } else { - if (m_bFindMaterial) - { - if (client_info->m_auxilary_info) - { - bFound = (m_propertyname== ((char*)client_info->m_auxilary_info)); + if (m_bFindMaterial) { + for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) { + RAS_MeshObject *meshObj = hitKXObj->GetMesh(i); + for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { + bFound = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0; + if (bFound) + break; + } } } - else - { + else { bFound = hitKXObj->GetProperty(m_propertyname) != NULL; } } @@ -195,6 +200,8 @@ bool KX_MouseFocusSensor::RayHit(KX_ClientObjectInfo *client_info, KX_RayCast *r */ bool KX_MouseFocusSensor::NeedRayCast(KX_ClientObjectInfo* client) { + KX_GameObject *hitKXObj = client->m_gameobject; + if (client->m_type > KX_ClientObjectInfo::ACTOR) { // Unknown type of object, skip it. @@ -206,14 +213,21 @@ bool KX_MouseFocusSensor::NeedRayCast(KX_ClientObjectInfo* client) { if (m_bFindMaterial) { - // not quite correct: an object may have multiple material - // should check all the material and not only the first one - if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info))) + bool found = false; + for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) { + RAS_MeshObject *meshObj = hitKXObj->GetMesh(i); + for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { + found = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0; + if (found) + break; + } + } + if (!found) return false; } else { - if (client->m_gameobject->GetProperty(m_propertyname) == NULL) + if (hitKXObj->GetProperty(m_propertyname) == NULL) return false; } } @@ -269,8 +283,8 @@ bool KX_MouseFocusSensor::ParentObjectHasFocusCamera(KX_Camera *cam) m_kxengine->GetSceneViewport(m_kxscene, cam, area, viewport); /* Check if the mouse is in the viewport */ - if (( m_x < viewport.m_x2 && // less then right - m_x > viewport.m_x1 && // more then then left + if (( m_x < viewport.m_x2 && // less than right + m_x > viewport.m_x1 && // more than then left m_y_inv < viewport.m_y2 && // below top m_y_inv > viewport.m_y1) == 0) // above bottom { diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.cpp b/source/gameengine/Ketsji/KX_NavMeshObject.cpp index 8360681759a..b8907ca5c6b 100644 --- a/source/gameengine/Ketsji/KX_NavMeshObject.cpp +++ b/source/gameengine/Ketsji/KX_NavMeshObject.cpp @@ -45,7 +45,7 @@ extern "C" { #include "KX_PythonInit.h" #include "KX_PyMath.h" -#include "Value.h" +#include "EXP_Value.h" #include "Recast.h" #include "DetourStatNavMeshBuilder.h" #include "KX_ObstacleSimulation.h" @@ -98,12 +98,14 @@ void KX_NavMeshObject::ProcessReplica() { KX_GameObject::ProcessReplica(); m_navMesh = NULL; /* without this, building frees the navmesh we copied from */ - BuildNavMesh(); + if (!BuildNavMesh()) { + std::cout << "Error in " << __func__ << ": unable to build navigation mesh" << std::endl; + return; + } KX_Scene* scene = KX_GetActiveScene(); KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation(); if (obssimulation) obssimulation->AddObstaclesForNavMesh(this); - } bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts, @@ -321,7 +323,11 @@ bool KX_NavMeshObject::BuildNavMesh() } } - buildMeshAdjacency(polys, npolys, nverts, vertsPerPoly); + if (!buildMeshAdjacency(polys, npolys, nverts, vertsPerPoly)) { + std::cout << __func__ << ": unable to build mesh adjacency information." << std::endl; + delete[] vertices; + return false; + } float cs = 0.2f; diff --git a/source/gameengine/Ketsji/KX_NavMeshObject.h b/source/gameengine/Ketsji/KX_NavMeshObject.h index 1599361b334..af178f9aaee 100644 --- a/source/gameengine/Ketsji/KX_NavMeshObject.h +++ b/source/gameengine/Ketsji/KX_NavMeshObject.h @@ -28,7 +28,7 @@ #define __KX_NAVMESHOBJECT_H__ #include "DetourStatNavMesh.h" #include "KX_GameObject.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <vector> class RAS_MeshObject; diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.cpp b/source/gameengine/Ketsji/KX_ObjectActuator.cpp index 0eec86987be..12abcb250a7 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_ObjectActuator.cpp @@ -75,7 +75,8 @@ KX_ObjectActuator( m_reference(refobj), m_active_combined_velocity (false), m_linear_damping_active(false), - m_angular_damping_active(false) + m_angular_damping_active(false), + m_jumping(false) { if (m_bitLocalFlag.ServoControl) { @@ -140,6 +141,7 @@ bool KX_ObjectActuator::Update() m_angular_damping_active = false; m_error_accumulator.setValue(0.0,0.0,0.0); m_previous_error.setValue(0.0,0.0,0.0); + m_jumping = false; return false; } else if (parent) @@ -223,6 +225,11 @@ bool KX_ObjectActuator::Update() else if (m_bitLocalFlag.CharacterMotion) { MT_Vector3 dir = m_dloc; + if (m_bitLocalFlag.DLoc) { + MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation(); + dir = basis * dir; + } + if (m_bitLocalFlag.AddOrSetCharLoc) { MT_Vector3 old_dir = character->GetWalkDirection(); @@ -236,21 +243,20 @@ bool KX_ObjectActuator::Update() } // We always want to set the walk direction since a walk direction of (0, 0, 0) should stop the character - if (m_bitLocalFlag.DLoc) - { - MT_Matrix3x3 basis = parent->GetPhysicsController()->GetOrientation(); - dir = basis*dir; - } character->SetWalkDirection(dir/parent->GetScene()->GetPhysicsEnvironment()->GetNumTimeSubSteps()); if (!m_bitLocalFlag.ZeroDRot) { parent->ApplyRotation(m_drot,(m_bitLocalFlag.DRot) != 0); } - if (m_bitLocalFlag.CharacterJump) - { - character->Jump(); + if (m_bitLocalFlag.CharacterJump) { + if (!m_jumping) { + character->Jump(); + m_jumping = true; + } + else if (character->OnGround()) + m_jumping = false; } } else { @@ -516,7 +522,9 @@ static Mathutils_Callback mathutils_obactu_vector_cb = { PyObject *KX_ObjectActuator::pyattr_get_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_LINV); } int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) @@ -532,7 +540,9 @@ int KX_ObjectActuator::pyattr_set_linV(void *self_v, const KX_PYATTRIBUTE_DEF *a PyObject *KX_ObjectActuator::pyattr_get_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { - return Vector_CreatePyObject_cb(BGE_PROXY_FROM_REF(self_v), 3, mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV); + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_kxobactu_vector_cb_index, MATHUTILS_VEC_CB_ANGV); } int KX_ObjectActuator::pyattr_set_angV(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) diff --git a/source/gameengine/Ketsji/KX_ObjectActuator.h b/source/gameengine/Ketsji/KX_ObjectActuator.h index 1f2453e3700..b5622d97611 100644 --- a/source/gameengine/Ketsji/KX_ObjectActuator.h +++ b/source/gameengine/Ketsji/KX_ObjectActuator.h @@ -116,7 +116,8 @@ class KX_ObjectActuator : public SCA_IActuator bool m_active_combined_velocity; bool m_linear_damping_active; bool m_angular_damping_active; - + bool m_jumping; + public: enum KX_OBJECT_ACT_VEC_TYPE { KX_OBJECT_ACT_NODEF = 0, diff --git a/source/gameengine/Ketsji/KX_ParentActuator.cpp b/source/gameengine/Ketsji/KX_ParentActuator.cpp index 6926fdb1d4c..6ffa2593792 100644 --- a/source/gameengine/Ketsji/KX_ParentActuator.cpp +++ b/source/gameengine/Ketsji/KX_ParentActuator.cpp @@ -37,7 +37,7 @@ #include "KX_GameObject.h" #include "KX_PythonInit.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" /* ------------------------------------------------------------------------- */ /* Native functions */ diff --git a/source/gameengine/Ketsji/KX_PolyProxy.cpp b/source/gameengine/Ketsji/KX_PolyProxy.cpp index ccc10eb06e3..4454543161b 100644 --- a/source/gameengine/Ketsji/KX_PolyProxy.cpp +++ b/source/gameengine/Ketsji/KX_PolyProxy.cpp @@ -140,21 +140,21 @@ PyObject *KX_PolyProxy::pyattr_get_v1(void *self_v, const KX_PYATTRIBUTE_DEF *at { KX_PolyProxy* self = static_cast<KX_PolyProxy*>(self_v); - return PyLong_FromLong(self->m_polygon->GetVertexOffset(0)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(0)); } PyObject *KX_PolyProxy::pyattr_get_v2(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolyProxy* self = static_cast<KX_PolyProxy*>(self_v); - return PyLong_FromLong(self->m_polygon->GetVertexOffset(1)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(1)); } PyObject *KX_PolyProxy::pyattr_get_v3(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_PolyProxy* self = static_cast<KX_PolyProxy*>(self_v); - return PyLong_FromLong(self->m_polygon->GetVertexOffset(2)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(2)); } PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) @@ -163,7 +163,7 @@ PyObject *KX_PolyProxy::pyattr_get_v4(void *self_v, const KX_PYATTRIBUTE_DEF *at if (3 < self->m_polygon->VertexCount()) { - return PyLong_FromLong(self->m_polygon->GetVertexOffset(3)); + return PyLong_FromLong(self->m_polygon->GetVertexOffsetAbsolute(3)); } return PyLong_FromLong(0); } @@ -243,7 +243,7 @@ KX_PYMETHODDEF_DOC(KX_PolyProxy, getVertexIndex, } if (index < m_polygon->VertexCount()) { - return PyLong_FromLong(m_polygon->GetVertexOffset(index)); + return PyLong_FromLong(m_polygon->GetVertexOffsetAbsolute(index)); } return PyLong_FromLong(0); } diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp index ebf1b9ec577..a0084662490 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.cpp @@ -41,7 +41,7 @@ #include "KX_GameObject.h" // ConvertPythonToGameObject() -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #ifdef WITH_BULLET # include "LinearMath/btIDebugDraw.h" @@ -56,38 +56,95 @@ // if there is a better way (without global), please do so! static PHY_IPhysicsEnvironment* g_CurrentActivePhysicsEnvironment = NULL; -static char PhysicsConstraints_module_documentation[] = -"This is the Python API for the Physics Constraints"; - - -static char gPySetGravity__doc__[] = "setGravity(float x,float y,float z)"; -static char gPySetDebugMode__doc__[] = "setDebugMode(int mode)"; - -static char gPySetNumIterations__doc__[] = "setNumIterations(int numiter) This sets the number of iterations for an iterative constraint solver"; -static char gPySetNumTimeSubSteps__doc__[] = "setNumTimeSubSteps(int numsubstep) This sets the number of substeps for each physics proceed. Tradeoff quality for performance."; - - -static char gPySetDeactivationTime__doc__[] = "setDeactivationTime(float time) This sets the time after which a resting rigidbody gets deactived"; -static char gPySetDeactivationLinearTreshold__doc__[] = "setDeactivationLinearTreshold(float linearTreshold)"; -static char gPySetDeactivationAngularTreshold__doc__[] = "setDeactivationAngularTreshold(float angularTreshold)"; -static char gPySetContactBreakingTreshold__doc__[] = "setContactBreakingTreshold(float breakingTreshold) Reasonable default is 0.02 (if units are meters)"; - -static char gPySetCcdMode__doc__[] = "setCcdMode(int ccdMode) Very experimental, not recommended"; -static char gPySetSorConstant__doc__[] = "setSorConstant(float sor) Very experimental, not recommended"; -static char gPySetSolverTau__doc__[] = "setTau(float tau) Very experimental, not recommended"; -static char gPySetSolverDamping__doc__[] = "setDamping(float damping) Very experimental, not recommended"; -static char gPySetLinearAirDamping__doc__[] = "setLinearAirDamping(float damping) Very experimental, not recommended"; -static char gPySetUseEpa__doc__[] = "setUseEpa(int epa) Very experimental, not recommended"; -static char gPySetSolverType__doc__[] = "setSolverType(int solverType) Very experimental, not recommended"; - - -static char gPyCreateConstraint__doc__[] = "createConstraint(ob1,ob2,float restLength,float restitution,float damping)"; -static char gPyGetVehicleConstraint__doc__[] = "getVehicleConstraint(int constraintId)"; -static char gPyGetCharacter__doc__[] = "getCharacter(KX_GameObject obj)"; -static char gPyRemoveConstraint__doc__[] = "removeConstraint(int constraintId)"; -static char gPyGetAppliedImpulse__doc__[] = "getAppliedImpulse(int constraintId)"; - +PyDoc_STRVAR(PhysicsConstraints_module_documentation, +"This is the Python API for the Physics Constraints" +); + +PyDoc_STRVAR(gPySetGravity__doc__, +"setGravity(float x,float y,float z)\n" +"" +); +PyDoc_STRVAR(gPySetDebugMode__doc__, +"setDebugMode(int mode)\n" +"" +); + +PyDoc_STRVAR(gPySetNumIterations__doc__, +"setNumIterations(int numiter)\n" +"This sets the number of iterations for an iterative constraint solver" +); +PyDoc_STRVAR(gPySetNumTimeSubSteps__doc__, +"setNumTimeSubSteps(int numsubstep)\n" +"This sets the number of substeps for each physics proceed. Tradeoff quality for performance." +); + +PyDoc_STRVAR(gPySetDeactivationTime__doc__, +"setDeactivationTime(float time)\n" +"This sets the time after which a resting rigidbody gets deactived" +); +PyDoc_STRVAR(gPySetDeactivationLinearTreshold__doc__, +"setDeactivationLinearTreshold(float linearTreshold)\n" +"" +); +PyDoc_STRVAR(gPySetDeactivationAngularTreshold__doc__, +"setDeactivationAngularTreshold(float angularTreshold)\n" +"" +); +PyDoc_STRVAR(gPySetContactBreakingTreshold__doc__, +"setContactBreakingTreshold(float breakingTreshold)\n" +"Reasonable default is 0.02 (if units are meters)" +); + +PyDoc_STRVAR(gPySetCcdMode__doc__, +"setCcdMode(int ccdMode)\n" +"Very experimental, not recommended" +); +PyDoc_STRVAR(gPySetSorConstant__doc__, +"setSorConstant(float sor)\n" +"Very experimental, not recommended" +); +PyDoc_STRVAR(gPySetSolverTau__doc__, +"setTau(float tau)\n" +"Very experimental, not recommended" +); +PyDoc_STRVAR(gPySetSolverDamping__doc__, +"setDamping(float damping)\n" +"Very experimental, not recommended" +); +PyDoc_STRVAR(gPySetLinearAirDamping__doc__, +"setLinearAirDamping(float damping)\n" +"Very experimental, not recommended" +); +PyDoc_STRVAR(gPySetUseEpa__doc__, +"setUseEpa(int epa)\n" +"Very experimental, not recommended" +); +PyDoc_STRVAR(gPySetSolverType__doc__, +"setSolverType(int solverType)\n" +"Very experimental, not recommended" +); + +PyDoc_STRVAR(gPyCreateConstraint__doc__, +"createConstraint(ob1,ob2,float restLength,float restitution,float damping)\n" +"" +); +PyDoc_STRVAR(gPyGetVehicleConstraint__doc__, +"getVehicleConstraint(int constraintId)\n" +"" +); +PyDoc_STRVAR(gPyGetCharacter__doc__, +"getCharacter(KX_GameObject obj)\n" +"" +); +PyDoc_STRVAR(gPyRemoveConstraint__doc__, +"removeConstraint(int constraintId)\n" +"" +); +PyDoc_STRVAR(gPyGetAppliedImpulse__doc__, +"getAppliedImpulse(int constraintId)\n" +"" +); @@ -438,113 +495,47 @@ static PyObject *gPyCreateConstraint(PyObject *self, PyObject *kwds) { /* FIXME - physicsid is a long being cast to a pointer, should at least use PyCapsule */ -#if defined(_WIN64) - __int64 physicsid=0,physicsid2 = 0; -#else - long physicsid=0,physicsid2 = 0; -#endif - int constrainttype=0, extrainfo=0; - int len = PyTuple_Size(args); - int success = 1; + unsigned long long physicsid = 0, physicsid2 = 0; + int constrainttype = 0; int flag = 0; + float pivotX = 0.0f, pivotY = 0.0f, pivotZ = 0.0f, axisX = 0.0f, axisY = 0.0f, axisZ = 0.0f; - float pivotX=1,pivotY=1,pivotZ=1,axisX=0,axisY=0,axisZ=1; - if (len == 3) - { -#if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLi",&physicsid,&physicsid2,&constrainttype); -#else - success = PyArg_ParseTuple(args,"lli",&physicsid,&physicsid2,&constrainttype); -#endif - } - else if (len == 6) - { -#if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLifff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ); -#else - success = PyArg_ParseTuple(args,"llifff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ); -#endif - } - else if (len == 9) - { -#if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLiffffff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); -#else - success = PyArg_ParseTuple(args,"lliffffff",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ); -#endif - } - else if (len == 10) - { -#if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLiffffffi",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); -#else - success = PyArg_ParseTuple(args,"lliffffffi",&physicsid,&physicsid2,&constrainttype, - &pivotX,&pivotY,&pivotZ,&axisX,&axisY,&axisZ,&flag); -#endif - } + static const char *kwlist[] = {"physicsid_1", "physicsid_2", "constraint_type", "pivot_x", "pivot_y", "pivot_z", + "axis_x", "axis_y", "axis_z", "flag", NULL}; - /* XXX extrainfo seems to be nothing implemented. right now it works as a pivot with [X,0,0] */ - else if (len == 4) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "KKi|ffffffi:createConstraint", (char **)kwlist, + &physicsid, &physicsid2, &constrainttype, + &pivotX, &pivotY, &pivotZ, &axisX, &axisY, &axisZ, &flag)) { -#if defined(_WIN64) - success = PyArg_ParseTuple(args,"LLii",&physicsid,&physicsid2,&constrainttype,&extrainfo); -#else - success = PyArg_ParseTuple(args,"llii",&physicsid,&physicsid2,&constrainttype,&extrainfo); -#endif - pivotX=extrainfo; + return NULL; } - if (success) - { - if (PHY_GetActiveEnvironment()) - { - - PHY_IPhysicsController* physctrl = (PHY_IPhysicsController*) physicsid; - PHY_IPhysicsController* physctrl2 = (PHY_IPhysicsController*) physicsid2; - if (physctrl) //TODO:check for existence of this pointer! - { - PHY_ConstraintType ct = (PHY_ConstraintType) constrainttype; - int constraintid =0; - - if (ct == PHY_GENERIC_6DOF_CONSTRAINT) - { - //convert from euler angle into axis - float radsPerDeg = 6.283185307179586232f / 360.f; - - //we need to pass a full constraint frame, not just axis - //localConstraintFrameBasis - MT_Matrix3x3 localCFrame(MT_Vector3(radsPerDeg*axisX,radsPerDeg*axisY,radsPerDeg*axisZ)); - MT_Vector3 axis0 = localCFrame.getColumn(0); - MT_Vector3 axis1 = localCFrame.getColumn(1); - MT_Vector3 axis2 = localCFrame.getColumn(2); - - constraintid = PHY_GetActiveEnvironment()->CreateConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype, - pivotX,pivotY,pivotZ, - (float)axis0.x(),(float)axis0.y(),(float)axis0.z(), - (float)axis1.x(),(float)axis1.y(),(float)axis1.z(), - (float)axis2.x(),(float)axis2.y(),(float)axis2.z(),flag); - } - else { - constraintid = PHY_GetActiveEnvironment()->CreateConstraint(physctrl,physctrl2,(enum PHY_ConstraintType)constrainttype,pivotX,pivotY,pivotZ,axisX,axisY,axisZ,0); - } - - KX_ConstraintWrapper* wrap = new KX_ConstraintWrapper((enum PHY_ConstraintType)constrainttype,constraintid,PHY_GetActiveEnvironment()); - - return wrap->NewProxy(true); - } - - + if (PHY_GetActiveEnvironment()) { + PHY_IPhysicsController *physctrl = (PHY_IPhysicsController*)physicsid; + PHY_IPhysicsController *physctrl2 = (PHY_IPhysicsController*)physicsid2; + if (physctrl) { //TODO:check for existence of this pointer! + //convert from euler angle into axis + const float deg2rad = 0.017453292f; + + //we need to pass a full constraint frame, not just axis + //localConstraintFrameBasis + MT_Matrix3x3 localCFrame(MT_Vector3(deg2rad*axisX, deg2rad*axisY, deg2rad*axisZ)); + MT_Vector3 axis0 = localCFrame.getColumn(0); + MT_Vector3 axis1 = localCFrame.getColumn(1); + MT_Vector3 axis2 = localCFrame.getColumn(2); + + int constraintid = PHY_GetActiveEnvironment()->CreateConstraint( + physctrl, physctrl2, (enum PHY_ConstraintType)constrainttype, pivotX, pivotY, pivotZ, + (float)axis0.x(), (float)axis0.y(), (float)axis0.z(), + (float)axis1.x(), (float)axis1.y(), (float)axis1.z(), + (float)axis2.x(), (float)axis2.y(), (float)axis2.z(), flag); + + KX_ConstraintWrapper *wrap = new KX_ConstraintWrapper( + (enum PHY_ConstraintType)constrainttype, constraintid, PHY_GetActiveEnvironment()); + + return wrap->NewProxy(true); } } - else { - return NULL; - } - Py_RETURN_NONE; } @@ -592,7 +583,7 @@ static PyObject *gPyRemoveConstraint(PyObject *self, { if (PHY_GetActiveEnvironment()) { - PHY_GetActiveEnvironment()->RemoveConstraint(constraintid); + PHY_GetActiveEnvironment()->RemoveConstraintById(constraintid); } } else { @@ -657,7 +648,7 @@ static struct PyMethodDef physicsconstraints_methods[] = { {"createConstraint",(PyCFunction) gPyCreateConstraint, - METH_VARARGS, (const char *)gPyCreateConstraint__doc__}, + METH_VARARGS|METH_KEYWORDS, (const char *)gPyCreateConstraint__doc__}, {"getVehicleConstraint",(PyCFunction) gPyGetVehicleConstraint, METH_VARARGS, (const char *)gPyGetVehicleConstraint__doc__}, @@ -677,7 +668,7 @@ static struct PyMethodDef physicsconstraints_methods[] = { }; static struct PyModuleDef PhysicsConstraints_module_def = { - {}, /* m_base */ + PyModuleDef_HEAD_INIT, "PhysicsConstraints", /* m_name */ PhysicsConstraints_module_documentation, /* m_doc */ 0, /* m_size */ @@ -688,7 +679,7 @@ static struct PyModuleDef PhysicsConstraints_module_def = { 0, /* m_free */ }; -PyObject *initPythonConstraintBinding() +PyMODINIT_FUNC initConstraintPythonBinding() { PyObject *ErrorObject; @@ -696,19 +687,8 @@ PyObject *initPythonConstraintBinding() PyObject *d; PyObject *item; - /* Use existing module where possible - * be careful not to init any runtime vars after this */ - m = PyImport_ImportModule( "PhysicsConstraints" ); - if (m) { - Py_DECREF(m); - return m; - } - else { - PyErr_Clear(); - - m = PyModule_Create(&PhysicsConstraints_module_def); - PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m); - } + m = PyModule_Create(&PhysicsConstraints_module_def); + PyDict_SetItemString(PySys_GetObject("modules"), PhysicsConstraints_module_def.m_name, m); // Add some symbolic constants to the module d = PyModule_GetDict(m); @@ -747,7 +727,7 @@ PyObject *initPythonConstraintBinding() Py_FatalError("can't initialize module PhysicsConstraints"); } - return d; + return m; } #if 0 diff --git a/source/gameengine/Ketsji/KX_PyConstraintBinding.h b/source/gameengine/Ketsji/KX_PyConstraintBinding.h index b4a520ce71b..2bf9f7e197d 100644 --- a/source/gameengine/Ketsji/KX_PyConstraintBinding.h +++ b/source/gameengine/Ketsji/KX_PyConstraintBinding.h @@ -36,7 +36,8 @@ #include <Python.h> -PyObject* initPythonConstraintBinding(); +PyMODINIT_FUNC initConstraintPythonBinding(); + void PHY_SetActiveEnvironment(class PHY_IPhysicsEnvironment* env); PHY_IPhysicsEnvironment* PHY_GetActiveEnvironment(); #endif /* WITH_PYTHON */ diff --git a/source/gameengine/Ketsji/KX_PyMath.cpp b/source/gameengine/Ketsji/KX_PyMath.cpp index 804e8de2ad1..ee05fd442ab 100644 --- a/source/gameengine/Ketsji/KX_PyMath.cpp +++ b/source/gameengine/Ketsji/KX_PyMath.cpp @@ -42,9 +42,9 @@ #include "MT_Matrix4x4.h" #include "MT_Point2.h" -#include "ListValue.h" +#include "EXP_ListValue.h" -#include "KX_Python.h" +#include "EXP_Python.h" #include "KX_PyMath.h" bool PyOrientationTo(PyObject *pyval, MT_Matrix3x3 &rot, const char *error_prefix) @@ -100,7 +100,7 @@ PyObject *PyObjectFrom(const MT_Matrix4x4 &mat) #ifdef USE_MATHUTILS float fmat[16]; mat.getValue(fmat); - return Matrix_CreatePyObject(fmat, 4, 4, Py_NEW, NULL); + return Matrix_CreatePyObject(fmat, 4, 4, NULL); #else PyObject *collist = PyList_New(4); PyObject *col; @@ -124,7 +124,7 @@ PyObject *PyObjectFrom(const MT_Matrix3x3 &mat) #ifdef USE_MATHUTILS float fmat[9]; mat.getValue3x3(fmat); - return Matrix_CreatePyObject(fmat, 3, 3, Py_NEW, NULL); + return Matrix_CreatePyObject(fmat, 3, 3, NULL); #else PyObject *collist = PyList_New(3); PyObject *col; @@ -148,7 +148,7 @@ PyObject *PyObjectFrom(const MT_Quaternion &qrot) /* NOTE, were re-ordering here for Mathutils compat */ float fvec[4]; qrot.getValue(fvec); - return Quaternion_CreatePyObject(fvec, Py_NEW, NULL); + return Quaternion_CreatePyObject(fvec, NULL); } #endif @@ -157,7 +157,7 @@ PyObject *PyObjectFrom(const MT_Tuple4 &vec) #ifdef USE_MATHUTILS float fvec[4]; vec.getValue(fvec); - return Vector_CreatePyObject(fvec, 4, Py_NEW, NULL); + return Vector_CreatePyObject(fvec, 4, NULL); #else PyObject *list = PyList_New(4); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); @@ -173,7 +173,7 @@ PyObject *PyObjectFrom(const MT_Tuple3 &vec) #ifdef USE_MATHUTILS float fvec[3]; vec.getValue(fvec); - return Vector_CreatePyObject(fvec, 3, Py_NEW, NULL); + return Vector_CreatePyObject(fvec, 3, NULL); #else PyObject *list = PyList_New(3); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); @@ -188,7 +188,7 @@ PyObject *PyObjectFrom(const MT_Tuple2 &vec) #ifdef USE_MATHUTILS float fvec[2]; vec.getValue(fvec); - return Vector_CreatePyObject(fvec, 2, Py_NEW, NULL); + return Vector_CreatePyObject(fvec, 2, NULL); #else PyObject *list = PyList_New(2); PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); @@ -197,4 +197,19 @@ PyObject *PyObjectFrom(const MT_Tuple2 &vec) #endif } +PyObject *PyColorFromVector(const MT_Vector3 &vec) +{ +#ifdef USE_MATHUTILS + float fvec[3]; + vec.getValue(fvec); + return Color_CreatePyObject(fvec, NULL); +#else + PyObject *list = PyList_New(3); + PyList_SET_ITEM(list, 0, PyFloat_FromDouble(vec[0])); + PyList_SET_ITEM(list, 1, PyFloat_FromDouble(vec[1])); + PyList_SET_ITEM(list, 2, PyFloat_FromDouble(vec[2])); + return list; +#endif +} + #endif // WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_PyMath.h b/source/gameengine/Ketsji/KX_PyMath.h index 159506946e8..917fd0fcda6 100644 --- a/source/gameengine/Ketsji/KX_PyMath.h +++ b/source/gameengine/Ketsji/KX_PyMath.h @@ -41,8 +41,8 @@ #include "MT_Matrix3x3.h" #include "MT_Matrix4x4.h" -#include "KX_Python.h" -#include "PyObjectPlus.h" +#include "EXP_Python.h" +#include "EXP_PyObjectPlus.h" #ifdef WITH_PYTHON #ifdef USE_MATHUTILS @@ -273,4 +273,9 @@ PyObject *PyObjectFrom(const MT_Tuple4 &pos); #endif +/** + * Converts an MT_Vector3 to a python color object. + */ +PyObject *PyColorFromVector(const MT_Vector3 &vec); + #endif /* WITH_PYTHON */ diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index da8a0c0844e..2fef74ca33d 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -30,7 +30,7 @@ * \ingroup ketsji */ -#include "GL/glew.h" +#include "glew-mx.h" #ifdef _MSC_VER # pragma warning (disable:4786) @@ -51,6 +51,8 @@ # include <Python.h> extern "C" { + # include "BLI_utildefines.h" + # include "python_utildefines.h" # include "bpy_internal_import.h" /* from the blender python api, but we want to import text too! */ # include "py_capi_utils.h" # include "mathutils.h" // 'mathutils' module copied here so the blenderlayer can use. @@ -59,7 +61,7 @@ extern "C" { # include "marshal.h" /* python header for loading/saving dicts */ } -#include "AUD_PyInit.h" +#include "../../../../intern/audaspace/intern/AUD_PyInit.h" #endif /* WITH_PYTHON */ @@ -110,8 +112,8 @@ extern "C" { #include "RAS_2DFilterManager.h" #include "MT_Vector3.h" #include "MT_Point3.h" -#include "ListValue.h" -#include "InputParser.h" +#include "EXP_ListValue.h" +#include "EXP_InputParser.h" #include "KX_Scene.h" #include "NG_NetworkScene.h" //Needed for sendMessage() @@ -121,7 +123,7 @@ extern "C" { #include "KX_PyMath.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "KX_PythonInitTypes.h" @@ -130,12 +132,17 @@ extern "C" { #include "DNA_scene_types.h" #include "PHY_IPhysicsEnvironment.h" + +extern "C" { #include "BKE_main.h" #include "BKE_global.h" #include "BKE_library.h" +#include "BKE_appdir.h" +#include "BKE_blender.h" #include "BLI_blenlib.h" #include "GPU_material.h" #include "MEM_guardedalloc.h" +} /* for converting new scenes */ #include "KX_BlenderSceneConverter.h" @@ -179,17 +186,17 @@ class KX_KetsjiEngine* KX_GetActiveEngine() } /* why is this in python? */ -void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color) +void KX_RasterizerDrawDebugLine(const MT_Vector3& from,const MT_Vector3& to,const MT_Vector3& color) { if (gp_Rasterizer) - gp_Rasterizer->DrawDebugLine(from,to,color); + gp_Rasterizer->DrawDebugLine(gp_KetsjiScene, from, to, color); } void KX_RasterizerDrawDebugCircle(const MT_Vector3& center, const MT_Scalar radius, const MT_Vector3& color, const MT_Vector3& normal, int nsector) { if (gp_Rasterizer) - gp_Rasterizer->DrawDebugCircle(center, radius, color, normal, nsector); + gp_Rasterizer->DrawDebugCircle(gp_KetsjiScene, center, radius, color, normal, nsector); } #ifdef WITH_PYTHON @@ -214,13 +221,16 @@ static void KX_MACRO_addTypesToDict_fn(PyObject *dict, const char *name, long va // temporarily python stuff, will be put in another place later ! -#include "KX_Python.h" +#include "EXP_Python.h" #include "SCA_PythonController.h" // List of methods defined in the module static PyObject *ErrorObject; -static const char *gPyGetRandomFloat_doc="getRandomFloat returns a random floating point value in the range [0..1]"; +PyDoc_STRVAR(gPyGetRandomFloat_doc, +"getRandomFloat()\n" +"returns a random floating point value in the range [0..1]" +); static PyObject *gPyGetRandomFloat(PyObject *) { return PyFloat_FromDouble(MT_random()); @@ -238,15 +248,15 @@ static PyObject *gPySetGravity(PyObject *, PyObject *value) Py_RETURN_NONE; } -static char gPyExpandPath_doc[] = -"(path) - Converts a blender internal path into a proper file system path.\n\ -path - the string path to convert.\n\n\ -Use / as directory separator in path\n\ -You can use '//' at the start of the string to define a relative path;\n\ -Blender replaces that string by the directory of the current .blend or runtime\n\ -file to make a full path name.\n\ -The function also converts the directory separator to the local file system format."; - +PyDoc_STRVAR(gPyExpandPath_doc, +"expandPath(path)\n" +"Converts a blender internal path into a proper file system path.\n" +" path - the string path to convert.\n" +"Use / as directory separator in path\n" +"You can use '//' at the start of the string to define a relative path." +"Blender replaces that string by the directory of the current .blend or runtime file to make a full path name.\n" +"The function also converts the directory separator to the local file system format." +); static PyObject *gPyExpandPath(PyObject *, PyObject *args) { char expanded[FILE_MAX]; @@ -260,10 +270,10 @@ static PyObject *gPyExpandPath(PyObject *, PyObject *args) return PyC_UnicodeFromByte(expanded); } -static char gPyStartGame_doc[] = -"startGame(blend)\n\ -Loads the blend file"; - +PyDoc_STRVAR(gPyStartGame_doc, +"startGame(blend)\n" +"Loads the blend file" +); static PyObject *gPyStartGame(PyObject *, PyObject *args) { char* blendfile; @@ -277,10 +287,10 @@ static PyObject *gPyStartGame(PyObject *, PyObject *args) Py_RETURN_NONE; } -static char gPyEndGame_doc[] = -"endGame()\n\ -Ends the current game"; - +PyDoc_STRVAR(gPyEndGame_doc, +"endGame()\n" +"Ends the current game" +); static PyObject *gPyEndGame(PyObject *) { gp_KetsjiEngine->RequestExit(KX_EXIT_REQUEST_QUIT_GAME); @@ -290,10 +300,10 @@ static PyObject *gPyEndGame(PyObject *) Py_RETURN_NONE; } -static char gPyRestartGame_doc[] = -"restartGame()\n\ -Restarts the current game by reloading the .blend file"; - +PyDoc_STRVAR(gPyRestartGame_doc, +"restartGame()\n" +"Restarts the current game by reloading the .blend file" +); static PyObject *gPyRestartGame(PyObject *) { gp_KetsjiEngine->RequestExit(KX_EXIT_REQUEST_RESTART_GAME); @@ -302,10 +312,10 @@ static PyObject *gPyRestartGame(PyObject *) Py_RETURN_NONE; } -static char gPySaveGlobalDict_doc[] = - "saveGlobalDict()\n" - "Saves bge.logic.globalDict to a file"; - +PyDoc_STRVAR(gPySaveGlobalDict_doc, +"saveGlobalDict()\n" +"Saves bge.logic.globalDict to a file" +); static PyObject *gPySaveGlobalDict(PyObject *) { char marshal_path[512]; @@ -339,15 +349,15 @@ static PyObject *gPySaveGlobalDict(PyObject *) Py_RETURN_NONE; } -static char gPyLoadGlobalDict_doc[] = - "LoadGlobalDict()\n" - "Loads bge.logic.globalDict from a file"; - +PyDoc_STRVAR(gPyLoadGlobalDict_doc, +"LoadGlobalDict()\n" +"Loads bge.logic.globalDict from a file" +); static PyObject *gPyLoadGlobalDict(PyObject *) { char marshal_path[512]; char *marshal_buffer = NULL; - size_t marshal_length; + int marshal_length; FILE *fp = NULL; int result; @@ -358,7 +368,12 @@ static PyObject *gPyLoadGlobalDict(PyObject *) if (fp) { // obtain file size: fseek (fp, 0, SEEK_END); - marshal_length = (size_t)ftell(fp); + marshal_length = ftell(fp); + if (marshal_length == -1) { + printf("Warning: could not read position of '%s'\n", marshal_path); + fclose(fp); + Py_RETURN_NONE; + } rewind(fp); marshal_buffer = (char*)malloc (sizeof(char)*marshal_length); @@ -380,23 +395,23 @@ static PyObject *gPyLoadGlobalDict(PyObject *) Py_RETURN_NONE; } -static char gPyGetProfileInfo_doc[] = +PyDoc_STRVAR(gPyGetProfileInfo_doc, "getProfileInfo()\n" -"returns a dictionary with profiling information"; - +"returns a dictionary with profiling information" +); static PyObject *gPyGetProfileInfo(PyObject *) { return gp_KetsjiEngine->GetPyProfileDict(); } -static char gPySendMessage_doc[] = -"sendMessage(subject, [body, to, from])\n\ -sends a message in same manner as a message actuator\ -subject = Subject of the message\ -body = Message body\ -to = Name of object to send the message to\ -from = Name of object to send the string from"; - +PyDoc_STRVAR(gPySendMessage_doc, +"sendMessage(subject, [body, to, from])\n" +"sends a message in same manner as a message actuator" +" subject = Subject of the message" +" body = Message body" +" to = Name of object to send the message to" +" from = Name of object to send the string from" +); static PyObject *gPySendMessage(PyObject *, PyObject *args) { char* subject; @@ -511,6 +526,27 @@ static PyObject *gPyGetPhysicsTicRate(PyObject *) return PyFloat_FromDouble(PHY_GetActiveEnvironment()->GetFixedTimeStep()); } +static PyObject *gPySetAnimRecordFrame(PyObject *, PyObject *args) +{ + int anim_record_frame; + + if (!PyArg_ParseTuple(args, "i:setAnimRecordFrame", &anim_record_frame)) + return NULL; + + if (anim_record_frame < 0 && (U.flag & USER_NONEGFRAMES)) { + PyErr_Format(PyExc_ValueError, "Frame number must be non-negative (was %i).", anim_record_frame); + return NULL; + } + + gp_KetsjiEngine->setAnimRecordFrame(anim_record_frame); + Py_RETURN_NONE; +} + +static PyObject *gPyGetAnimRecordFrame(PyObject *) +{ + return PyLong_FromLong(gp_KetsjiEngine->getAnimRecordFrame()); +} + static PyObject *gPyGetAverageFrameRate(PyObject *) { return PyFloat_FromDouble(KX_KetsjiEngine::GetAverageFrameRate()); @@ -556,11 +592,12 @@ static PyObject *gPyGetBlendFileList(PyObject *, PyObject *args) return list; } -static char gPyAddScene_doc[] = -"addScene(name, [overlay])\n\ -adds a scene to the game engine\n\ -name = Name of the scene\n\ -overlay = Overlay or underlay"; +PyDoc_STRVAR(gPyAddScene_doc, +"addScene(name, [overlay])\n" +"Adds a scene to the game engine.\n" +" name = Name of the scene\n" +" overlay = Overlay or underlay" +); static PyObject *gPyAddScene(PyObject *, PyObject *args) { char* name; @@ -574,17 +611,19 @@ static PyObject *gPyAddScene(PyObject *, PyObject *args) Py_RETURN_NONE; } -static const char *gPyGetCurrentScene_doc = +PyDoc_STRVAR(gPyGetCurrentScene_doc, "getCurrentScene()\n" -"Gets a reference to the current scene.\n"; +"Gets a reference to the current scene." +); static PyObject *gPyGetCurrentScene(PyObject *self) { return gp_KetsjiScene->GetProxy(); } -static const char *gPyGetSceneList_doc = +PyDoc_STRVAR(gPyGetSceneList_doc, "getSceneList()\n" -"Return a list of converted scenes.\n"; +"Return a list of converted scenes." +); static PyObject *gPyGetSceneList(PyObject *self) { KX_KetsjiEngine* m_engine = KX_GetActiveEngine(); @@ -869,6 +908,8 @@ static struct PyMethodDef game_methods[] = { {"setLogicTicRate", (PyCFunction) gPySetLogicTicRate, METH_VARARGS, (const char *)"Sets the logic tic rate"}, {"getPhysicsTicRate", (PyCFunction) gPyGetPhysicsTicRate, METH_NOARGS, (const char *)"Gets the physics tic rate"}, {"setPhysicsTicRate", (PyCFunction) gPySetPhysicsTicRate, METH_VARARGS, (const char *)"Sets the physics tic rate"}, + {"getAnimRecordFrame", (PyCFunction) gPyGetAnimRecordFrame, METH_NOARGS, (const char *)"Gets the current frame number used for animation recording"}, + {"setAnimRecordFrame", (PyCFunction) gPySetAnimRecordFrame, METH_VARARGS, (const char *)"Sets the current frame number used for animation recording"}, {"getExitKey", (PyCFunction) gPyGetExitKey, METH_NOARGS, (const char *)"Gets the key used to exit the game engine"}, {"setExitKey", (PyCFunction) gPySetExitKey, METH_VARARGS, (const char *)"Sets the key used to exit the game engine"}, {"getAverageFrameRate", (PyCFunction) gPyGetAverageFrameRate, METH_NOARGS, (const char *)"Gets the estimated average frame rate"}, @@ -1002,111 +1043,39 @@ static PyObject *gPyGetFocalLength(PyObject *, PyObject *, PyObject *) Py_RETURN_NONE; } -static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value) +static PyObject *gPyGetStereoEye(PyObject *, PyObject *, PyObject *) { - - MT_Vector4 vec; - if (!PyVecTo(value, vec)) - return NULL; - - if (gp_Canvas) - { - gp_Rasterizer->SetBackColor((float)vec[0], (float)vec[1], (float)vec[2], (float)vec[3]); - } - - KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); - if (wi->hasWorld()) - wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]); + int flag = RAS_IRasterizer::RAS_STEREO_LEFTEYE; - Py_RETURN_NONE; -} - - - -static PyObject *gPySetMistColor(PyObject *, PyObject *value) -{ - - MT_Vector3 vec; - if (!PyVecTo(value, vec)) - return NULL; - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); + PyErr_SetString(PyExc_RuntimeError, "Rasterizer.getStereoEye(), Rasterizer not available"); return NULL; } - gp_Rasterizer->SetFogColor((float)vec[0], (float)vec[1], (float)vec[2]); - - Py_RETURN_NONE; -} -static PyObject *gPyDisableMist(PyObject *) -{ - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistColor(color), Rasterizer not available"); - return NULL; - } - gp_Rasterizer->DisableFog(); - - Py_RETURN_NONE; -} + if (gp_Rasterizer->Stereo()) + flag = gp_Rasterizer->GetEye(); -static PyObject *gPySetMistStart(PyObject *, PyObject *args) -{ - - float miststart; - if (!PyArg_ParseTuple(args,"f:setMistStart",&miststart)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistStart(float), Rasterizer not available"); - return NULL; - } - - gp_Rasterizer->SetFogStart(miststart); - - Py_RETURN_NONE; + return PyLong_FromLong(flag); } - - -static PyObject *gPySetMistEnd(PyObject *, PyObject *args) +static PyObject *gPySetBackgroundColor(PyObject *, PyObject *value) { - - float mistend; - if (!PyArg_ParseTuple(args,"f:setMistEnd",&mistend)) + MT_Vector4 vec; + if (!PyVecTo(value, vec)) return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setMistEnd(float), Rasterizer not available"); + + KX_WorldInfo *wi = gp_KetsjiScene->GetWorldInfo(); + if (!wi->hasWorld()) { + PyErr_SetString(PyExc_RuntimeError, "bge.render.SetBackgroundColor(color), World not available"); return NULL; } - - gp_Rasterizer->SetFogEnd(mistend); - - Py_RETURN_NONE; -} + ShowDeprecationWarning("setBackgroundColor()", "KX_WorldInfo.background_color"); + wi->setBackColor((float)vec[0], (float)vec[1], (float)vec[2]); -static PyObject *gPySetAmbientColor(PyObject *, PyObject *value) -{ - - MT_Vector3 vec; - if (!PyVecTo(value, vec)) - return NULL; - - if (!gp_Rasterizer) { - PyErr_SetString(PyExc_RuntimeError, "Rasterizer.setAmbientColor(color), Rasterizer not available"); - return NULL; - } - gp_Rasterizer->SetAmbientColor((float)vec[0], (float)vec[1], (float)vec[2]); - Py_RETURN_NONE; } - - - static PyObject *gPyMakeScreenshot(PyObject *, PyObject *args) { char* filename; @@ -1192,10 +1161,6 @@ static PyObject *gPySetGLSLMaterialSetting(PyObject *, else gs->glslflag |= flag; - /* temporarily store the glsl settings in the scene for the GLSL materials */ - GameData *gm= &(gp_KetsjiScene->GetBlenderScene()->gm); - gm->flag = gs->glslflag; - /* display lists and GLSL materials need to be remade */ if (sceneflag != gs->glslflag) { GPU_materials_free(); @@ -1203,11 +1168,14 @@ static PyObject *gPySetGLSLMaterialSetting(PyObject *, KX_SceneList *scenes = gp_KetsjiEngine->CurrentScenes(); KX_SceneList::iterator it; - for (it=scenes->begin(); it!=scenes->end(); it++) + for (it=scenes->begin(); it!=scenes->end(); it++) { + // temporarily store the glsl settings in the scene for the GLSL materials + (*it)->GetBlenderScene()->gm.flag = gs->glslflag; if ((*it)->GetBucketManager()) { (*it)->GetBucketManager()->ReleaseDisplayLists(); (*it)->GetBucketManager()->ReleaseMaterials(); } + } } } @@ -1320,7 +1288,7 @@ static PyObject *gPyDrawLine(PyObject *, PyObject *args) if (!PyVecTo(ob_color, color)) return NULL; - gp_Rasterizer->DrawDebugLine(from,to,color); + gp_Rasterizer->DrawDebugLine(gp_KetsjiScene, from, to, color); Py_RETURN_NONE; } @@ -1396,7 +1364,9 @@ static PyObject *gPySetVsync(PyObject *, PyObject *args) static PyObject *gPyGetVsync(PyObject *) { - return PyLong_FromLong(gp_Canvas->GetSwapInterval()); + int interval = 0; + gp_Canvas->GetSwapInterval(interval); + return PyLong_FromLong(interval); } static PyObject *gPyShowFramerate(PyObject *, PyObject *args) @@ -1463,6 +1433,24 @@ static PyObject *gPyClearDebugList(PyObject *) Py_RETURN_NONE; } +static PyObject *gPyGetDisplayDimensions(PyObject *) +{ + PyObject *result; + int width, height; + + gp_Canvas->GetDisplayDimensions(width, height); + + result = PyTuple_New(2); + PyTuple_SET_ITEMS(result, + PyLong_FromLong(width), + PyLong_FromLong(height)); + + return result; +} + +PyDoc_STRVAR(Rasterizer_module_documentation, +"This is the Python API for the game engine of Rasterizer" +); static struct PyMethodDef rasterizer_methods[] = { {"getWindowWidth",(PyCFunction) gPyGetWindowWidth, @@ -1478,11 +1466,6 @@ static struct PyMethodDef rasterizer_methods[] = { {"setMousePosition",(PyCFunction) gPySetMousePosition, METH_VARARGS, "setMousePosition(int x,int y)"}, {"setBackgroundColor",(PyCFunction)gPySetBackgroundColor,METH_O,"set Background Color (rgb)"}, - {"setAmbientColor",(PyCFunction)gPySetAmbientColor,METH_O,"set Ambient Color (rgb)"}, - {"disableMist",(PyCFunction)gPyDisableMist,METH_NOARGS,"turn off mist"}, - {"setMistColor",(PyCFunction)gPySetMistColor,METH_O,"set Mist Color (rgb)"}, - {"setMistStart",(PyCFunction)gPySetMistStart,METH_VARARGS,"set Mist Start(rgb)"}, - {"setMistEnd",(PyCFunction)gPySetMistEnd,METH_VARARGS,"set Mist End(rgb)"}, {"enableMotionBlur",(PyCFunction)gPyEnableMotionBlur,METH_VARARGS,"enable motion blur"}, {"disableMotionBlur",(PyCFunction)gPyDisableMotionBlur,METH_NOARGS,"disable motion blur"}, @@ -1490,6 +1473,7 @@ static struct PyMethodDef rasterizer_methods[] = { {"getEyeSeparation", (PyCFunction) gPyGetEyeSeparation, METH_NOARGS, "get the eye separation for stereo mode"}, {"setFocalLength", (PyCFunction) gPySetFocalLength, METH_VARARGS, "set the focal length for stereo mode"}, {"getFocalLength", (PyCFunction) gPyGetFocalLength, METH_VARARGS, "get the focal length for stereo mode"}, + {"getStereoEye", (PyCFunction) gPyGetStereoEye, METH_VARARGS, "get the current stereoscopy eye being rendered"}, {"setMaterialMode",(PyCFunction) gPySetMaterialType, METH_VARARGS, "set the material mode to use for OpenGL rendering"}, {"getMaterialMode",(PyCFunction) gPyGetMaterialType, @@ -1507,6 +1491,8 @@ static struct PyMethodDef rasterizer_methods[] = { {"setWindowSize", (PyCFunction) gPySetWindowSize, METH_VARARGS, ""}, {"setFullScreen", (PyCFunction) gPySetFullScreen, METH_O, ""}, {"getFullScreen", (PyCFunction) gPyGetFullScreen, METH_NOARGS, ""}, + {"getDisplayDimensions", (PyCFunction) gPyGetDisplayDimensions, METH_NOARGS, + "Get the actual dimensions, in pixels, of the physical display (e.g., the monitor)."}, {"setMipmapping", (PyCFunction) gPySetMipmapping, METH_VARARGS, ""}, {"getMipmapping", (PyCFunction) gPyGetMipmapping, METH_NOARGS, ""}, {"setVsync", (PyCFunction) gPySetVsync, METH_VARARGS, ""}, @@ -1519,15 +1505,11 @@ static struct PyMethodDef rasterizer_methods[] = { { NULL, (PyCFunction) NULL, 0, NULL } }; -// Initialization function for the module (*must* be called initGameLogic) -static char GameLogic_module_documentation[] = -"This is the Python API for the game engine of bge.logic" -; -static char Rasterizer_module_documentation[] = -"This is the Python API for the game engine of Rasterizer" -; +PyDoc_STRVAR(GameLogic_module_documentation, +"This is the Python API for the game engine of bge.logic" +); static struct PyModuleDef GameLogic_module_def = { {}, /* m_base */ @@ -1541,33 +1523,20 @@ static struct PyModuleDef GameLogic_module_def = { 0, /* m_free */ }; -PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack to get gravity hook +PyMODINIT_FUNC initGameLogicPythonBinding() { PyObject *m; PyObject *d; PyObject *item; /* temp PyObject *storage */ - - gp_KetsjiEngine = engine; - gp_KetsjiScene = scene; gUseVisibilityTemp=false; - + PyObjectPlus::ClearDeprecationWarning(); /* Not that nice to call here but makes sure warnings are reset between loading scenes */ - - /* Use existing module where possible - * be careful not to init any runtime vars after this */ - m = PyImport_ImportModule( "GameLogic" ); - if (m) { - Py_DECREF(m); - return m; - } - else { - PyErr_Clear(); - // Create the module and add the functions - m = PyModule_Create(&GameLogic_module_def); - PyDict_SetItemString(PySys_GetObject("modules"), GameLogic_module_def.m_name, m); - } - + + m = PyModule_Create(&GameLogic_module_def); + PyDict_SetItemString(PySys_GetObject("modules"), GameLogic_module_def.m_name, m); + + // Add some symbolic constants to the module d = PyModule_GetDict(m); @@ -1587,17 +1556,22 @@ PyObject *initGameLogic(KX_KetsjiEngine *engine, KX_Scene* scene) // quick hack PyObject* joylist = PyList_New(JOYINDEX_MAX); for (int i=0; i<JOYINDEX_MAX; ++i) { - SCA_Joystick* joy = SCA_Joystick::GetInstance(i); + SCA_Joystick *joy = SCA_Joystick::GetInstance(i); + PyObject *item; + if (joy && joy->Connected()) { gp_PythonJoysticks[i] = new SCA_PythonJoystick(joy); - PyObject* tmp = gp_PythonJoysticks[i]->NewProxy(true); - Py_INCREF(tmp); - PyList_SET_ITEM(joylist, i, tmp); - } else { - joy->ReleaseInstance(); - Py_INCREF(Py_None); - PyList_SET_ITEM(joylist, i, Py_None); + item = gp_PythonJoysticks[i]->NewProxy(true); } + else { + if (joy) { + joy->ReleaseInstance(); + } + item = Py_None; + } + + Py_INCREF(item); + PyList_SET_ITEM(joylist, i, item); } PyDict_SetItemString(d, "joysticks", joylist); @@ -2047,7 +2021,77 @@ void removeImportMain(struct Main *maggie) bpy_import_main_extra_remove(maggie); } -// Copied from bpy_interface.c + +PyDoc_STRVAR(BGE_module_documentation, + "This module contains submodules for the Blender Game Engine.\n" +); + +static struct PyModuleDef BGE_module_def = { + PyModuleDef_HEAD_INIT, + "bge", /* m_name */ + BGE_module_documentation, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + +PyMODINIT_FUNC initBGE(void) +{ + PyObject *mod; + PyObject *submodule; + PyObject *sys_modules = PyThreadState_GET()->interp->modules; + const char *mod_full; + + mod = PyModule_Create(&BGE_module_def); + + /* skip "bge." */ +#define SUBMOD (mod_full + 4) + + mod_full = "bge.app"; + PyModule_AddObject(mod, SUBMOD, (submodule = initApplicationPythonBinding())); + PyDict_SetItemString(sys_modules, mod_full, submodule); + Py_INCREF(submodule); + + mod_full = "bge.constraints"; + PyModule_AddObject(mod, SUBMOD, (submodule = initConstraintPythonBinding())); + PyDict_SetItemString(sys_modules, mod_full, submodule); + Py_INCREF(submodule); + + mod_full = "bge.events"; + PyModule_AddObject(mod, SUBMOD, (submodule = initGameKeysPythonBinding())); + PyDict_SetItemString(sys_modules, mod_full, submodule); + Py_INCREF(submodule); + + mod_full = "bge.logic"; + PyModule_AddObject(mod, SUBMOD, (submodule = initGameLogicPythonBinding())); + PyDict_SetItemString(sys_modules, mod_full, submodule); + Py_INCREF(submodule); + + mod_full = "bge.render"; + PyModule_AddObject(mod, SUBMOD, (submodule = initRasterizerPythonBinding())); + PyDict_SetItemString(sys_modules, mod_full, submodule); + Py_INCREF(submodule); + + mod_full = "bge.texture"; + PyModule_AddObject(mod, SUBMOD, (submodule = initVideoTexturePythonBinding())); + PyDict_SetItemString(sys_modules, mod_full, submodule); + Py_INCREF(submodule); + + mod_full = "bge.types"; + PyModule_AddObject(mod, SUBMOD, (submodule = initGameTypesPythonBinding())); + PyDict_SetItemString(sys_modules, mod_full, submodule); + Py_INCREF(submodule); + +#undef SUBMOD + + return mod; +} + + +/* minimal required blender modules to run blenderplayer */ static struct _inittab bge_internal_modules[] = { {"mathutils", PyInit_mathutils}, {"bgl", BPyInit_bgl}, @@ -2060,7 +2104,7 @@ static struct _inittab bge_internal_modules[] = { * Python is not initialized. * see bpy_interface.c's BPY_python_start() which shares the same functionality in blender. */ -PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie, int argc, char** argv) +PyObject *initGamePlayerPythonScripting(Main *maggie, int argc, char** argv) { /* Yet another gotcha in the py api * Cant run PySys_SetArgv more than once because this adds the @@ -2069,16 +2113,22 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur * somehow it remembers the sys.path - Campbell */ static bool first_time = true; - const char * const py_path_bundle = BLI_get_folder(BLENDER_SYSTEM_PYTHON, NULL); - -#if 0 // TODO - py3 - STR_String pname = progname; - Py_SetProgramName(pname.Ptr()); -#endif - + const char * const py_path_bundle = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, NULL); + + /* not essential but nice to set our name */ + static wchar_t program_path_wchar[FILE_MAX]; /* python holds a reference */ + BLI_strncpy_wchar_from_utf8(program_path_wchar, BKE_appdir_program_path(), ARRAY_SIZE(program_path_wchar)); + Py_SetProgramName(program_path_wchar); + + /* Update, Py3.3 resolves attempting to parse non-existing header */ +#if 0 + /* Python 3.2 now looks for '2.xx/python/include/python3.2d/pyconfig.h' to + * parse from the 'sysconfig' module which is used by 'site', + * so for now disable site. alternatively we could copy the file. */ if (py_path_bundle != NULL) { - Py_NoSiteFlag = 1; + Py_NoSiteFlag = 1; /* inhibits the automatic importing of 'site' */ } +#endif Py_FrozenFlag = 1; @@ -2102,12 +2152,16 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur PySys_SetObject("argv", py_argv); Py_DECREF(py_argv); } - + /* Initialize thread support (also acquires lock) */ PyEval_InitThreads(); bpy_import_init(PyEval_GetBuiltins()); + bpy_import_main_set(maggie); + + initPySysObjects(maggie); + /* mathutils types are used by the BGE even if we don't import them */ { PyObject *mod = PyImport_ImportModuleLevel("mathutils", NULL, NULL, NULL, 0); @@ -2122,12 +2176,8 @@ PyObject *initGamePlayerPythonScripting(const STR_String& progname, TPythonSecur } #endif - initPyTypes(); - - bpy_import_main_set(maggie); - - initPySysObjects(maggie); - + PyDict_SetItemString(PyImport_GetModuleDict(), "bge", initBGE()); + first_time = false; PyObjectPlus::ClearDeprecationWarning(); @@ -2164,12 +2214,13 @@ void exitGamePlayerPythonScripting() /** * Python is already initialized. */ -PyObject *initGamePythonScripting(const STR_String& progname, TPythonSecurityLevel level, Main *maggie) +PyObject *initGamePythonScripting(Main *maggie) { -#if 0 // XXX TODO Py3 - STR_String pname = progname; - Py_SetProgramName(pname.Ptr()); -#endif + /* no need to Py_SetProgramName, it was already taken care of in BPY_python_start */ + + bpy_import_main_set(maggie); + + initPySysObjects(maggie); #ifdef WITH_AUDASPACE /* accessing a SoundActuator's sound results in a crash if aud is not initialized... */ @@ -2179,11 +2230,7 @@ PyObject *initGamePythonScripting(const STR_String& progname, TPythonSecurityLev } #endif - initPyTypes(); - - bpy_import_main_set(maggie); - - initPySysObjects(maggie); + PyDict_SetItemString(PyImport_GetModuleDict(), "bge", initBGE()); PyObjectPlus::NullDeprecationWarning(); @@ -2216,51 +2263,32 @@ void exitGamePythonScripting() void setupGamePython(KX_KetsjiEngine* ketsjiengine, KX_Scene *startscene, Main *blenderdata, PyObject *pyGlobalDict, PyObject **gameLogic, PyObject **gameLogic_keys, int argc, char** argv) { - PyObject *dictionaryobject; + PyObject *modules, *dictionaryobject; + + gp_Canvas = ketsjiengine->GetCanvas(); + gp_Rasterizer = ketsjiengine->GetRasterizer(); + gp_KetsjiEngine = ketsjiengine; + gp_KetsjiScene = startscene; if (argv) /* player only */ - dictionaryobject= initGamePlayerPythonScripting("Ketsji", psl_Lowest, blenderdata, argc, argv); + dictionaryobject= initGamePlayerPythonScripting(blenderdata, argc, argv); else - dictionaryobject= initGamePythonScripting("Ketsji", psl_Lowest, blenderdata); + dictionaryobject= initGamePythonScripting(blenderdata); ketsjiengine->SetPyNamespace(dictionaryobject); - initRasterizer(ketsjiengine->GetRasterizer(), ketsjiengine->GetCanvas()); - *gameLogic = initGameLogic(ketsjiengine, startscene); - /* is set in initGameLogic so only set here if we want it to persist between scenes */ + modules = PyImport_GetModuleDict(); + + *gameLogic = PyDict_GetItemString(modules, "GameLogic"); + /* is set in initGameLogicPythonBinding so only set here if we want it to persist between scenes */ if (pyGlobalDict) PyDict_SetItemString(PyModule_GetDict(*gameLogic), "globalDict", pyGlobalDict); // Same as importing the module. *gameLogic_keys = PyDict_Keys(PyModule_GetDict(*gameLogic)); - - initGameKeys(); - initPythonConstraintBinding(); - initVideoTexture(); - - /* could be done a lot more nicely, but for now a quick way to get bge.* working */ - PyRun_SimpleString("sys = __import__('sys');" - "bge = type(sys)('bge');" - "bge.__dict__.update({'logic':__import__('GameLogic'), " - "'render':__import__('Rasterizer'), " - "'events':__import__('GameKeys'), " - "'constraints':__import__('PhysicsConstraints'), " - "'physics':__import__('PhysicsConstraints')," - "'types':__import__('GameTypes'), " - "'texture':__import__('VideoTexture')});" - /* so we can do 'import bge.foo as bar' */ - "sys.modules.update({'bge': bge, " - "'bge.logic':bge.logic, " - "'bge.render':bge.render, " - "'bge.events':bge.events, " - "'bge.constraints':bge.constraints, " - "'bge.physics':bge.physics," - "'bge.types':bge.types, " - "'bge.texture':bge.texture})" - ); } static struct PyModuleDef Rasterizer_module_def = { - {}, /* m_base */ + PyModuleDef_HEAD_INIT, "Rasterizer", /* m_name */ Rasterizer_module_documentation, /* m_doc */ 0, /* m_size */ @@ -2271,29 +2299,14 @@ static struct PyModuleDef Rasterizer_module_def = { 0, /* m_free */ }; -PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) +PyMODINIT_FUNC initRasterizerPythonBinding() { - gp_Canvas = canvas; - gp_Rasterizer = rasty; - - PyObject *m; PyObject *d; - /* Use existing module where possible - * be careful not to init any runtime vars after this */ - m = PyImport_ImportModule( "Rasterizer" ); - if (m) { - Py_DECREF(m); - return m; - } - else { - PyErr_Clear(); + m = PyModule_Create(&Rasterizer_module_def); + PyDict_SetItemString(PySys_GetObject("modules"), Rasterizer_module_def.m_name, m); - // Create the module and add the functions - m = PyModule_Create(&Rasterizer_module_def); - PyDict_SetItemString(PySys_GetObject("modules"), Rasterizer_module_def.m_name, m); - } // Add some symbolic constants to the module d = PyModule_GetDict(m); @@ -2314,6 +2327,10 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) KX_MACRO_addTypesToDict(d, VSYNC_ON, VSYNC_ON); KX_MACRO_addTypesToDict(d, VSYNC_ADAPTIVE, VSYNC_ADAPTIVE); + /* stereoscopy */ + KX_MACRO_addTypesToDict(d, LEFT_EYE, RAS_IRasterizer::RAS_STEREO_LEFTEYE); + KX_MACRO_addTypesToDict(d, RIGHT_EYE, RAS_IRasterizer::RAS_STEREO_RIGHTEYE); + // XXXX Add constants here // Check for errors @@ -2322,7 +2339,7 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) Py_FatalError("can't initialize module Rasterizer"); } - return d; + return m; } @@ -2331,13 +2348,14 @@ PyObject *initRasterizer(RAS_IRasterizer* rasty,RAS_ICanvas* canvas) /* GameKeys: symbolic constants for key mapping */ /* ------------------------------------------------------------------------- */ -static char GameKeys_module_documentation[] = +PyDoc_STRVAR(GameKeys_module_documentation, "This modules provides defines for key-codes" -; +); -static char gPyEventToString_doc[] = -"EventToString(event) - Take a valid event from the GameKeys module or Keyboard Sensor and return a name" -; +PyDoc_STRVAR(gPyEventToString_doc, +"EventToString(event)\n" +"Take a valid event from the GameKeys module or Keyboard Sensor and return a name" +); static PyObject *gPyEventToString(PyObject *, PyObject *value) { @@ -2365,9 +2383,11 @@ static PyObject *gPyEventToString(PyObject *, PyObject *value) return ret; } -static char gPyEventToCharacter_doc[] = -"EventToCharacter(event, is_shift) - Take a valid event from the GameKeys module or Keyboard Sensor and return a character" -; + +PyDoc_STRVAR(gPyEventToCharacter_doc, +"EventToCharacter(event, is_shift)\n" +"Take a valid event from the GameKeys module or Keyboard Sensor and return a character" +); static PyObject *gPyEventToCharacter(PyObject *, PyObject *args) { @@ -2393,7 +2413,7 @@ static struct PyMethodDef gamekeys_methods[] = { }; static struct PyModuleDef GameKeys_module_def = { - {}, /* m_base */ + PyModuleDef_HEAD_INIT, "GameKeys", /* m_name */ GameKeys_module_documentation, /* m_doc */ 0, /* m_size */ @@ -2404,24 +2424,13 @@ static struct PyModuleDef GameKeys_module_def = { 0, /* m_free */ }; -PyObject *initGameKeys() +PyMODINIT_FUNC initGameKeysPythonBinding() { PyObject *m; PyObject *d; - - /* Use existing module where possible */ - m = PyImport_ImportModule( "GameKeys" ); - if (m) { - Py_DECREF(m); - return m; - } - else { - PyErr_Clear(); - - // Create the module and add the functions - m = PyModule_Create(&GameKeys_module_def); - PyDict_SetItemString(PySys_GetObject("modules"), GameKeys_module_def.m_name, m); - } + + m = PyModule_Create(&GameKeys_module_def); + PyDict_SetItemString(PySys_GetObject("modules"), GameKeys_module_def.m_name, m); // Add some symbolic constants to the module d = PyModule_GetDict(m); @@ -2566,9 +2575,80 @@ PyObject *initGameKeys() Py_FatalError("can't initialize module GameKeys"); } - return d; + return m; +} + + + +/* ------------------------------------------------------------------------- */ +/* Application: application values that remain unchanged during runtime */ +/* ------------------------------------------------------------------------- */ + +PyDoc_STRVAR(Application_module_documentation, + "This module contains application values that remain unchanged during runtime." + ); + +static struct PyModuleDef Application_module_def = { + PyModuleDef_HEAD_INIT, + "bge.app", /* m_name */ + Application_module_documentation, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + 0, /* m_reload */ + 0, /* m_traverse */ + 0, /* m_clear */ + 0, /* m_free */ +}; + +PyMODINIT_FUNC initApplicationPythonBinding() +{ + PyObject *m; + PyObject *d; + + m = PyModule_Create(&Application_module_def); + + // Add some symbolic constants to the module + d = PyModule_GetDict(m); + + PyDict_SetItemString(d, "version", Py_BuildValue("(iii)", + BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION)); + PyDict_SetItemString(d, "version_string", PyUnicode_FromFormat("%d.%02d (sub %d)", + BLENDER_VERSION / 100, BLENDER_VERSION % 100, BLENDER_SUBVERSION)); + PyDict_SetItemString(d, "version_char", PyUnicode_FromString( + STRINGIFY(BLENDER_VERSION_CHAR))); + + PyDict_SetItemString(d, "has_texture_ffmpeg", +#ifdef WITH_FFMPEG + Py_True +#else + Py_False +#endif + ); + PyDict_SetItemString(d, "has_joystick", +#ifdef WITH_SDL + Py_True +#else + Py_False +#endif + ); + PyDict_SetItemString(d, "has_physics", +#ifdef WITH_BULLET + Py_True +#else + Py_False +#endif + ); + + // Check for errors + if (PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + } + + return m; } + // utility function for loading and saving the globalDict int saveGamePythonConfig( char **marshal_buffer) { diff --git a/source/gameengine/Ketsji/KX_PythonInit.h b/source/gameengine/Ketsji/KX_PythonInit.h index 719a74ee219..6550934a916 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.h +++ b/source/gameengine/Ketsji/KX_PythonInit.h @@ -32,10 +32,13 @@ #ifndef __KX_PYTHONINIT_H__ #define __KX_PYTHONINIT_H__ -#include "KX_Python.h" +#include "EXP_Python.h" #include "STR_String.h" #include "MT_Vector3.h" +class KX_KetsjiEngine; +class KX_Scene; + typedef enum { psl_Lowest = 0, psl_Highest, @@ -44,13 +47,14 @@ typedef enum { extern bool gUseVisibilityTemp; #ifdef WITH_PYTHON -PyObject *initGameLogic(class KX_KetsjiEngine *engine, class KX_Scene *ketsjiscene); -PyObject *initGameKeys(); -PyObject *initRasterizer(class RAS_IRasterizer *rasty,class RAS_ICanvas *canvas); -PyObject *initGamePlayerPythonScripting(const STR_String &progname, TPythonSecurityLevel level, - struct Main *maggie, int argc, char **argv); -PyObject *initVideoTexture(void); -PyObject *initGamePythonScripting(const STR_String &progname, TPythonSecurityLevel level, struct Main *maggie); +PyMODINIT_FUNC initBGE(void); +PyMODINIT_FUNC initApplicationPythonBinding(void); +PyMODINIT_FUNC initGameLogicPythonBinding(void); +PyMODINIT_FUNC initGameKeysPythonBinding(void); +PyMODINIT_FUNC initRasterizerPythonBinding(void); +PyMODINIT_FUNC initVideoTexturePythonBinding(void); +PyObject *initGamePlayerPythonScripting(struct Main *maggie, int argc, char **argv); +PyObject *initGamePythonScripting(struct Main *maggie); void exitGamePlayerPythonScripting(); void exitGamePythonScripting(); @@ -69,9 +73,9 @@ void removeImportMain(struct Main *maggie); class KX_KetsjiEngine; class KX_Scene; -void KX_SetActiveScene(class KX_Scene *scene); -class KX_Scene *KX_GetActiveScene(); -class KX_KetsjiEngine *KX_GetActiveEngine(); +void KX_SetActiveScene(KX_Scene *scene); +KX_Scene *KX_GetActiveScene(); +KX_KetsjiEngine *KX_GetActiveEngine(); typedef int (*PyNextFrameFunc)(void *); diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp index 7d38ce58eee..ef6ad4712a5 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.cpp +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.cpp @@ -40,6 +40,7 @@ #include "BL_ArmatureConstraint.h" #include "BL_ArmatureObject.h" #include "BL_ArmatureChannel.h" +#include "KX_WorldInfo.h" #include "KX_ArmatureSensor.h" #include "KX_BlenderMaterial.h" #include "KX_CameraActuator.h" @@ -163,21 +164,34 @@ static void PyType_Ready_ADD(PyObject *dict, PyTypeObject *tp, PyAttributeDef *a #define PyType_Ready_Attr(d, n, i) PyType_Ready_ADD(d, &n::Type, n::Attributes, NULL, i) #define PyType_Ready_AttrPtr(d, n, i) PyType_Ready_ADD(d, &n::Type, n::Attributes, n::AttributesPtr, i) -void initPyTypes(void) + + +PyDoc_STRVAR(GameTypes_module_documentation, +"This module provides access to the game engine data types." +); +static struct PyModuleDef GameTypes_module_def = { + PyModuleDef_HEAD_INIT, + "GameTypes", /* m_name */ + GameTypes_module_documentation, /* m_doc */ + 0, /* m_size */ + NULL, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ +}; + + +PyMODINIT_FUNC initGameTypesPythonBinding(void) { + PyObject *m; + PyObject *dict; -/* - * initPyObjectPlusType(BL_ActionActuator::Parents); - * ..... - */ + m = PyModule_Create(&GameTypes_module_def); + PyDict_SetItemString(PySys_GetObject("modules"), GameTypes_module_def.m_name, m); + + dict = PyModule_GetDict(m); - /* For now just do PyType_Ready */ - PyObject *mod = PyModule_New("GameTypes"); - PyObject *dict = PyModule_GetDict(mod); - PyDict_SetItemString(PySys_GetObject("modules"), "GameTypes", mod); - Py_DECREF(mod); - - for (int init_getset= 1; init_getset > -1; init_getset--) { /* run twice, once to init the getsets another to run PyType_Ready */ PyType_Ready_Attr(dict, BL_ActionActuator, init_getset); PyType_Ready_Attr(dict, BL_Shader, init_getset); @@ -218,6 +232,7 @@ void initPyTypes(void) PyType_Ready_Attr(dict, KX_SCA_EndObjectActuator, init_getset); PyType_Ready_Attr(dict, KX_SCA_ReplaceMeshActuator, init_getset); PyType_Ready_Attr(dict, KX_Scene, init_getset); + PyType_Ready_Attr(dict, KX_WorldInfo, init_getset); PyType_Ready_Attr(dict, KX_NavMeshObject, init_getset); PyType_Ready_Attr(dict, KX_SceneActuator, init_getset); PyType_Ready_Attr(dict, KX_SoundActuator, init_getset); @@ -266,7 +281,11 @@ void initPyTypes(void) /* Init mathutils callbacks */ KX_GameObject_Mathutils_Callback_Init(); KX_ObjectActuator_Mathutils_Callback_Init(); + KX_WorldInfo_Mathutils_Callback_Init(); + KX_BlenderMaterial_Mathutils_Callback_Init(); #endif + + return m; } #endif // WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_PythonInitTypes.h b/source/gameengine/Ketsji/KX_PythonInitTypes.h index d8ee4f75fdd..cfc49a1dc93 100644 --- a/source/gameengine/Ketsji/KX_PythonInitTypes.h +++ b/source/gameengine/Ketsji/KX_PythonInitTypes.h @@ -33,7 +33,8 @@ #define __KX_PYTHON_INIT_TYPES__ #ifdef WITH_PYTHON -void initPyTypes(void); +#include <Python.h> +PyMODINIT_FUNC initGameTypesPythonBinding(void); #endif #endif /* __KX_PYTHON_INIT_TYPES__ */ diff --git a/source/gameengine/Ketsji/KX_PythonSeq.h b/source/gameengine/Ketsji/KX_PythonSeq.h index 568d59119c0..33b5335ddf4 100644 --- a/source/gameengine/Ketsji/KX_PythonSeq.h +++ b/source/gameengine/Ketsji/KX_PythonSeq.h @@ -35,7 +35,7 @@ #ifdef WITH_PYTHON -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" // ------------------------- enum KX_PYGENSEQ_TYPE { diff --git a/source/gameengine/Ketsji/KX_RaySensor.cpp b/source/gameengine/Ketsji/KX_RaySensor.cpp index 0f47dfd922b..c97d233a67b 100644 --- a/source/gameengine/Ketsji/KX_RaySensor.cpp +++ b/source/gameengine/Ketsji/KX_RaySensor.cpp @@ -46,6 +46,7 @@ #include "PHY_IPhysicsEnvironment.h" #include "PHY_IPhysicsController.h" #include "DNA_sensor_types.h" +#include "RAS_MeshObject.h" #include <stdio.h> @@ -111,6 +112,7 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void KX_GameObject* hitKXObj = client->m_gameobject; bool bFound = false; + bool hitMaterial = false; if (m_propertyname.Length() == 0) { @@ -118,15 +120,19 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void } else { - if (m_bFindMaterial) - { - if (client->m_auxilary_info) - { - bFound = (m_propertyname== ((char*)client->m_auxilary_info)); + if (m_bFindMaterial) { + for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) { + RAS_MeshObject *meshObj = hitKXObj->GetMesh(i); + for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { + bFound = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0; + if (bFound) { + hitMaterial = true; + break; + } + } } } - else - { + else { bFound = hitKXObj->GetProperty(m_propertyname) != NULL; } } @@ -143,7 +149,7 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void m_hitNormal[1] = result->m_hitNormal[1]; m_hitNormal[2] = result->m_hitNormal[2]; - m_hitMaterial = (client->m_auxilary_info ? (char*)client->m_auxilary_info : ""); + m_hitMaterial = hitMaterial; } // no multi-hit search yet return true; @@ -154,6 +160,8 @@ bool KX_RaySensor::RayHit(KX_ClientObjectInfo *client, KX_RayCast *result, void */ bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo *client) { + KX_GameObject *hitKXObj = client->m_gameobject; + if (client->m_type > KX_ClientObjectInfo::ACTOR) { // Unknown type of object, skip it. @@ -163,16 +171,21 @@ bool KX_RaySensor::NeedRayCast(KX_ClientObjectInfo *client) } if (m_bXRay && m_propertyname.Length() != 0) { - if (m_bFindMaterial) - { - // not quite correct: an object may have multiple material - // should check all the material and not only the first one - if (!client->m_auxilary_info || (m_propertyname != ((char*)client->m_auxilary_info))) + if (m_bFindMaterial) { + bool found = false; + for (unsigned int i = 0; i < hitKXObj->GetMeshCount(); ++i) { + RAS_MeshObject *meshObj = hitKXObj->GetMesh(i); + for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { + found = strcmp(m_propertyname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0; + if (found) + break; + } + } + if (!found) return false; } - else - { - if (client->m_gameobject->GetProperty(m_propertyname) == NULL) + else { + if (hitKXObj->GetProperty(m_propertyname) == NULL) return false; } } diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index f8f79269eaa..fdcfd22270b 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -38,7 +38,7 @@ #include "KX_SCA_AddObjectActuator.h" #include "SCA_IScene.h" #include "KX_GameObject.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" /* ------------------------------------------------------------------------- */ /* Native functions */ diff --git a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp index e02eca3db63..96e1cc29de3 100644 --- a/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_DynamicActuator.cpp @@ -121,7 +121,9 @@ bool KX_SCA_DynamicActuator::Update() switch (m_dyn_operation) { case 0: - controller->RestoreDynamics(); + // Child objects must be static, so we block changing to dynamic + if (!obj->GetParent()) + controller->RestoreDynamics(); break; case 1: controller->SuspendDynamics(); diff --git a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp index b105256836b..6b6b090c1c4 100644 --- a/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_ReplaceMeshActuator.cpp @@ -43,7 +43,7 @@ #include "KX_SCA_ReplaceMeshActuator.h" #include "KX_MeshProxy.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #ifdef WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index d0eab9de1c1..723736906a9 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -35,6 +35,8 @@ # pragma warning (disable:4786) #endif +#include <stdio.h> + #include "KX_Scene.h" #include "KX_PythonInit.h" #include "MT_assert.h" @@ -42,7 +44,7 @@ #include "KX_BlenderMaterial.h" #include "KX_FontObject.h" #include "RAS_IPolygonMaterial.h" -#include "ListValue.h" +#include "EXP_ListValue.h" #include "SCA_LogicManager.h" #include "SCA_TimeEventManager.h" //#include "SCA_AlwaysEventManager.h" @@ -66,7 +68,7 @@ #include "RAS_ICanvas.h" #include "RAS_BucketManager.h" -#include "FloatValue.h" +#include "EXP_FloatValue.h" #include "SCA_IController.h" #include "SCA_IActuator.h" #include "SG_Node.h" @@ -94,12 +96,14 @@ #include "KX_ObstacleSimulation.h" #ifdef WITH_BULLET -#include "KX_SoftBodyDeformer.h" +# include "KX_SoftBodyDeformer.h" #endif -#include "KX_Light.h" +#ifdef WITH_PYTHON +# include "EXP_PythonCallBack.h" +#endif -#include <stdio.h> +#include "KX_Light.h" #include "BLI_task.h" @@ -156,7 +160,9 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_networkDeviceInterface(ndi), m_active_camera(NULL), m_ueberExecutionPriority(0), - m_blenderScene(scene) + m_blenderScene(scene), + m_isActivedHysteresis(false), + m_lodHysteresisValue(0) { m_suspendedtime = 0.0; m_suspendeddelta = 0.0; @@ -218,7 +224,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_bucketmanager=new RAS_BucketManager(); - bool showObstacleSimulation = scene->gm.flag & GAME_SHOW_OBSTACLE_SIMULATION; + bool showObstacleSimulation = (scene->gm.flag & GAME_SHOW_OBSTACLE_SIMULATION) != 0; switch (scene->gm.obstacleSimulation) { case OBSTSIMULATION_TOI_rays: @@ -235,6 +241,7 @@ KX_Scene::KX_Scene(class SCA_IInputDevice* keyboarddevice, m_attr_dict = NULL; m_draw_call_pre = NULL; m_draw_call_post = NULL; + m_draw_setup_call_pre = NULL; #endif } @@ -532,6 +539,8 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal m_objectlist->Add(newobj->AddRef()); if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) m_lightlist->Add(newobj->AddRef()); + else if (newobj->GetGameObjectType()==SCA_IObject::OBJ_TEXT) + AddFont((KX_FontObject*)newobj); newobj->AddMeshUser(); // logic cannot be replicated, until the whole hierarchy is replicated. @@ -575,6 +584,10 @@ KX_GameObject* KX_Scene::AddNodeReplicaObject(class SG_IObject* node, class CVal newctrl->SetNewClientInfo(newobj->getClientInfo()); newobj->SetPhysicsController(newctrl, newobj->IsDynamic()); newctrl->PostProcessReplica(motionstate, parentctrl); + + // Child objects must be static + if (parent) + newctrl->SuspendDynamics(); } return newobj; @@ -803,13 +816,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // we can now add the graphic controller to the physic engine replica->ActivateGraphicController(true); - // set references for dupli-group - // groupobj holds a list of all objects, that belongs to this group - groupobj->AddInstanceObjects(replica); - - // every object gets the reference to its dupli-group object - replica->SetDupliGroupObject(groupobj); - // done with replica replica->Release(); } @@ -829,12 +835,6 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) (*git)->Relink(&m_map_gameobject_to_replica); // add the object in the layer of the parent (*git)->SetLayer(groupobj->GetLayer()); - // If the object was a light, we need to update it's RAS_LightObject as well - if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) - { - KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git); - lightobj->SetLayer(groupobj->GetLayer()); - } } // replicate crosslinks etc. between logic bricks @@ -846,9 +846,24 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) // now look if object in the hierarchy have dupli group and recurse for (git = m_logicHierarchicalGameObjects.begin();!(git==m_logicHierarchicalGameObjects.end());++git) { + /* Replicate all constraints. */ + if ((*git)->GetPhysicsController()) { + (*git)->GetPhysicsController()->ReplicateConstraints((*git), m_logicHierarchicalGameObjects); + (*git)->ClearConstraints(); + } + if ((*git) != groupobj && (*git)->IsDupliGroup()) // can't instantiate group immediately as it destroys m_logicHierarchicalGameObjects duplilist.push_back((*git)); + + if ((*git)->GetBlenderGroupObject() == blgroupobj) { + // set references for dupli-group + // groupobj holds a list of all objects, that belongs to this group + groupobj->AddInstanceObjects((*git)); + + // every object gets the reference to its dupli-group object + (*git)->SetDupliGroupObject(groupobj); + } } for (git = duplilist.begin(); !(git == duplilist.end()); ++git) @@ -859,7 +874,7 @@ void KX_Scene::DupliGroupRecurse(CValue* obj, int level) SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, - class CValue* parentobject, + class CValue* referenceobject, int lifespan) { @@ -867,19 +882,18 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, m_map_gameobject_to_replica.clear(); m_groupGameObjects.clear(); - // todo: place a timebomb in the object, for temporarily objects :) - // lifespan of zero means 'this object lives forever' KX_GameObject* originalobj = (KX_GameObject*) originalobject; - KX_GameObject* parentobj = (KX_GameObject*) parentobject; + KX_GameObject* referenceobj = (KX_GameObject*) referenceobject; m_ueberExecutionPriority++; // lets create a replica KX_GameObject* replica = (KX_GameObject*) AddNodeReplicaObject(NULL,originalobj); + // add a timebomb to this object + // lifespan of zero means 'this object lives forever' if (lifespan > 0) { - // add a timebomb to this object // for now, convert between so called frames and realtime m_tempObjectList->Add(replica->AddRef()); // this convert the life from frames to sort-of seconds, hard coded 0.02 that assumes we have 50 frames per second @@ -905,19 +919,20 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, replica->GetSGNode()->AddChild(childreplicanode); } - // At this stage all the objects in the hierarchy have been duplicated, - // we can update the scenegraph, we need it for the duplication of logic - MT_Point3 newpos = ((KX_GameObject*) parentobject)->NodeGetWorldPosition(); - replica->NodeSetLocalPosition(newpos); + if (referenceobj) { + // At this stage all the objects in the hierarchy have been duplicated, + // we can update the scenegraph, we need it for the duplication of logic + MT_Point3 newpos = referenceobj->NodeGetWorldPosition(); + replica->NodeSetLocalPosition(newpos); - MT_Matrix3x3 newori = ((KX_GameObject*) parentobject)->NodeGetWorldOrientation(); - replica->NodeSetLocalOrientation(newori); - - // get the rootnode's scale - MT_Vector3 newscale = parentobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); + MT_Matrix3x3 newori = referenceobj->NodeGetWorldOrientation(); + replica->NodeSetLocalOrientation(newori); - // set the replica's relative scale with the rootnode's scale - replica->NodeSetRelativeScale(newscale); + // get the rootnode's scale + MT_Vector3 newscale = referenceobj->GetSGNode()->GetRootSGParent()->GetLocalScale(); + // set the replica's relative scale with the rootnode's scale + replica->NodeSetRelativeScale(newscale); + } replica->GetSGNode()->UpdateWorldData(0); replica->GetSGNode()->SetBBox(originalobj->GetSGNode()->BBox()); @@ -937,13 +952,13 @@ SCA_IObject* KX_Scene::AddReplicaObject(class CValue* originalobject, { // this will also relink the actuators in the hierarchy (*git)->Relink(&m_map_gameobject_to_replica); - // add the object in the layer of the parent - (*git)->SetLayer(parentobj->GetLayer()); - // If the object was a light, we need to update it's RAS_LightObject as well - if ((*git)->GetGameObjectType()==SCA_IObject::OBJ_LIGHT) - { - KX_LightObject* lightobj = static_cast<KX_LightObject*>(*git); - lightobj->SetLayer(parentobj->GetLayer()); + if (referenceobj) { + // add the object in the layer of the reference object + (*git)->SetLayer(referenceobj->GetLayer()); + } + else { + // We don't know what layer set, so we set all visible layers in the blender scene. + (*git)->SetLayer(m_blenderScene->lay); } } @@ -1078,6 +1093,16 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) group->RemoveInstanceObject(newobj); newobj->RemoveMeshes(); + + switch (newobj->GetGameObjectType()) { + case SCA_IObject::OBJ_CAMERA: + m_cameras.remove((KX_Camera *)newobj); + break; + case SCA_IObject::OBJ_TEXT: + m_fonts.remove((KX_FontObject *)newobj); + break; + } + ret = 1; if (newobj->GetGameObjectType()==SCA_IObject::OBJ_LIGHT && m_lightlist->RemoveValue(newobj)) ret = newobj->Release(); @@ -1093,7 +1118,10 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) ret = newobj->Release(); if (m_animatedlist->RemoveValue(newobj)) ret = newobj->Release(); - + + /* Warning 'newobj' maye be freed now, only compare, don't access */ + + if (newobj == m_active_camera) { //no AddRef done on m_active_camera so no Release @@ -1101,12 +1129,6 @@ int KX_Scene::NewRemoveObject(class CValue* gameobj) m_active_camera = NULL; } - // in case this is a camera - m_cameras.remove((KX_Camera*)newobj); - - // in case this is a font - m_fonts.remove((KX_FontObject*)newobj); - /* currently does nothing, keep in case we need to Unregister something */ #if 0 if (m_sceneConverter) @@ -1502,6 +1524,15 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int bool dbvt_culling = false; if (m_dbvt_culling) { + /* Reset KX_GameObject m_bCulled to true before doing culling + * since DBVT culling will only set it to false. + * This is similar to what RAS_BucketManager does for RAS_MeshSlot culling. + */ + for (int i = 0; i < m_objectlist->GetCount(); i++) { + KX_GameObject *gameobj = static_cast<KX_GameObject*>(m_objectlist->GetValue(i)); + gameobj->SetCulled(true); + } + // test culling through Bullet MT_Vector4 planes[6]; // get the clip planes @@ -1531,9 +1562,6 @@ void KX_Scene::CalculateVisibleMeshes(RAS_IRasterizer* rasty,KX_Camera* cam, int MarkVisible(rasty, static_cast<KX_GameObject*>(m_objectlist->GetValue(i)), cam, layer); } } - - // Now that we know visible meshes, update LoDs - UpdateObjectLods(); } // logic stuff @@ -1642,20 +1670,6 @@ static void update_anim_thread_func(TaskPool *pool, void *taskdata, int UNUSED(t void KX_Scene::UpdateAnimations(double curtime) { - KX_KetsjiEngine *engine = KX_GetActiveEngine(); - - if (engine->GetRestrictAnimationFPS()) - { - // Handle the animations independently of the logic time step - double anim_timestep = 1.0 / GetAnimationFPS(); - if (curtime - m_previousAnimTime < anim_timestep) - return; - - // Sanity/debug print to make sure we're actually going at the fps we want (should be close to anim_timestep) - // printf("Anim fps: %f\n", 1.0/(m_clockTime - m_previousAnimTime)); - m_previousAnimTime = curtime; - } - TaskPool *pool = BLI_task_pool_create(KX_GetActiveEngine()->GetTaskScheduler(), &curtime); for (int i=0; i<m_animatedlist->GetCount(); ++i) { @@ -1755,6 +1769,10 @@ void KX_Scene::RenderFonts() void KX_Scene::UpdateObjectLods(void) { KX_GameObject* gameobj; + + if (!this->m_active_camera) + return; + MT_Vector3 cam_pos = this->m_active_camera->NodeGetWorldPosition(); for (int i = 0; i < this->GetObjectList()->GetCount(); i++) { @@ -1765,6 +1783,26 @@ void KX_Scene::UpdateObjectLods(void) } } +void KX_Scene::SetLodHysteresis(bool active) +{ + m_isActivedHysteresis = active; +} + +bool KX_Scene::IsActivedLodHysteresis(void) +{ + return m_isActivedHysteresis; +} + +void KX_Scene::SetLodHysteresisValue(int hysteresisvalue) +{ + m_lodHysteresisValue = hysteresisvalue; +} + +int KX_Scene::GetLodHysteresisValue(void) +{ + return m_lodHysteresisValue; +} + void KX_Scene::UpdateObjectActivity(void) { if (m_activity_culling) { @@ -1881,15 +1919,6 @@ static void MergeScene_LogicBrick(SCA_ILogicBrick* brick, KX_Scene *from, KX_Sce brick->Replace_IScene(to); brick->Replace_NetworkScene(to->GetNetworkScene()); - /* near sensors have physics controllers */ - KX_TouchSensor *touch_sensor = dynamic_cast<class KX_TouchSensor *>(brick); - if (touch_sensor) { - KX_TouchEventManager *tmgr = (KX_TouchEventManager*)from->GetLogicManager()->FindEventManager(SCA_EventManager::TOUCH_EVENTMGR); - touch_sensor->UnregisterSumo(tmgr); - touch_sensor->GetPhysicsController()->SetPhysicsEnvironment(to->GetPhysicsEnvironment()); - touch_sensor->RegisterSumo(tmgr); - } - // If we end up replacing a KX_TouchEventManager, we need to make sure // physics controllers are properly in place. In other words, do this // after merging physics controllers! @@ -1948,17 +1977,6 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene { SCA_IController *cont= *itc; MergeScene_LogicBrick(cont, from, to); - - vector<SCA_ISensor*> linkedsensors = cont->GetLinkedSensors(); - vector<SCA_IActuator*> linkedactuators = cont->GetLinkedActuators(); - - for (vector<SCA_IActuator*>::iterator ita = linkedactuators.begin();!(ita==linkedactuators.end());++ita) { - MergeScene_LogicBrick(*ita, from, to); - } - - for (vector<SCA_ISensor*>::iterator its = linkedsensors.begin();!(its==linkedsensors.end());++its) { - MergeScene_LogicBrick(*its, from, to); - } } } @@ -1993,12 +2011,20 @@ static void MergeScene_GameObject(KX_GameObject* gameobj, KX_Scene *to, KX_Scene if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_CAMERA) to->AddCamera((KX_Camera*)gameobj); + // All armatures should be in the animated object list to be umpdated. + if (gameobj->GetGameObjectType() == SCA_IObject::OBJ_ARMATURE) + to->AddAnimatedObject(gameobj); + /* Add the object to the scene's logic manager */ to->GetLogicManager()->RegisterGameObjectName(gameobj->GetName(), gameobj); to->GetLogicManager()->RegisterGameObj(gameobj->GetBlenderObject(), gameobj); - for (int i=0; i<gameobj->GetMeshCount(); ++i) - to->GetLogicManager()->RegisterGameMeshName(gameobj->GetMesh(i)->GetName(), gameobj->GetBlenderObject()); + for (int i = 0; i < gameobj->GetMeshCount(); ++i) { + RAS_MeshObject *meshobj = gameobj->GetMesh(i); + // Register the mesh object by name and blender object. + to->GetLogicManager()->RegisterGameMeshName(meshobj->GetName(), gameobj->GetBlenderObject()); + to->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj); + } } bool KX_Scene::MergeScene(KX_Scene *other) @@ -2042,6 +2068,28 @@ bool KX_Scene::MergeScene(KX_Scene *other) MergeScene_GameObject(gameobj, this, other); } + if (env) { + env->MergeEnvironment(env_other); + CListValue *otherObjects = other->GetObjectList(); + + // List of all physics objects to merge (needed by ReplicateConstraints). + std::vector<KX_GameObject *> physicsObjects; + for (unsigned int i = 0; i < otherObjects->GetCount(); ++i) { + KX_GameObject *gameobj = (KX_GameObject *)otherObjects->GetValue(i); + if (gameobj->GetPhysicsController()) { + physicsObjects.push_back(gameobj); + } + } + + for (unsigned int i = 0; i < physicsObjects.size(); ++i) { + KX_GameObject *gameobj = physicsObjects[i]; + // Replicate all constraints in the right physics environment. + gameobj->GetPhysicsController()->ReplicateConstraints(gameobj, physicsObjects); + gameobj->ClearConstraints(); + } + } + + GetTempObjectList()->MergeList(other->GetTempObjectList()); other->GetTempObjectList()->ReleaseAndRemoveAll(); @@ -2057,9 +2105,6 @@ bool KX_Scene::MergeScene(KX_Scene *other) GetLightList()->MergeList(other->GetLightList()); other->GetLightList()->ReleaseAndRemoveAll(); - if (env) - env->MergeEnvironment(env_other); - /* move materials across, assume they both use the same scene-converters * Do this after lights are merged so materials can use the lights in shaders */ @@ -2112,30 +2157,10 @@ void KX_Scene::Render2DFilters(RAS_ICanvas* canvas) void KX_Scene::RunDrawingCallbacks(PyObject *cb_list) { - Py_ssize_t len; - - if (cb_list && (len=PyList_GET_SIZE(cb_list))) - { - PyObject *args = PyTuple_New(0); // save python creating each call - PyObject *func; - PyObject *ret; - - // Iterate the list and run the callbacks - for (Py_ssize_t pos=0; pos < len; pos++) - { - func= PyList_GET_ITEM(cb_list, pos); - ret= PyObject_Call(func, args, NULL); - if (ret==NULL) { - PyErr_Print(); - PyErr_Clear(); - } - else { - Py_DECREF(ret); - } - } + if (!cb_list || PyList_GET_SIZE(cb_list) == 0) + return; - Py_DECREF(args); - } + RunPythonCallBackList(cb_list, NULL, 0, 0); } //---------------------------------------------------------------------------- @@ -2321,6 +2346,19 @@ PyObject *KX_Scene::pyattr_get_lights(void *self_v, const KX_PYATTRIBUTE_DEF *at return self->GetLightList()->GetProxy(); } +PyObject *KX_Scene::pyattr_get_world(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + KX_WorldInfo *world = self->GetWorldInfo(); + + if (world->GetName() != "") { + return world->GetProxy(); + } + else { + Py_RETURN_NONE; + } +} + PyObject *KX_Scene::pyattr_get_cameras(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { /* With refcounts in this case... @@ -2385,6 +2423,17 @@ PyObject *KX_Scene::pyattr_get_drawing_callback_post(void *self_v, const KX_PYAT return self->m_draw_call_post; } +PyObject *KX_Scene::pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + + if (self->m_draw_setup_call_pre == NULL) + self->m_draw_setup_call_pre = PyList_New(0); + + Py_INCREF(self->m_draw_setup_call_pre); + return self->m_draw_setup_call_pre; +} + int KX_Scene::pyattr_set_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) { KX_Scene* self = static_cast<KX_Scene*>(self_v); @@ -2419,6 +2468,22 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } +int KX_Scene::pyattr_set_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Scene* self = static_cast<KX_Scene*>(self_v); + + if (!PyList_CheckExact(value)) { + PyErr_SetString(PyExc_ValueError, "Expected a list"); + return PY_SET_ATTR_FAIL; + } + + Py_XDECREF(self->m_draw_setup_call_pre); + Py_INCREF(value); + + self->m_draw_setup_call_pre = value; + return PY_SET_ATTR_SUCCESS; +} + PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_Scene* self = static_cast<KX_Scene*>(self_v); @@ -2444,9 +2509,11 @@ PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("objectsInactive", KX_Scene, pyattr_get_objects_inactive), KX_PYATTRIBUTE_RO_FUNCTION("lights", KX_Scene, pyattr_get_lights), KX_PYATTRIBUTE_RO_FUNCTION("cameras", KX_Scene, pyattr_get_cameras), + KX_PYATTRIBUTE_RO_FUNCTION("world", KX_Scene, pyattr_get_world), KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera), KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post), + KX_PYATTRIBUTE_RW_FUNCTION("pre_draw_setup", KX_Scene, pyattr_get_drawing_setup_callback_pre, pyattr_set_drawing_setup_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity), KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), @@ -2459,23 +2526,23 @@ KX_PYMETHODDEF_DOC(KX_Scene, addObject, "addObject(object, other, time=0)\n" "Returns the added object.\n") { - PyObject *pyob, *pyother; - KX_GameObject *ob, *other; + PyObject *pyob, *pyreference = Py_None; + KX_GameObject *ob, *reference; int time = 0; - if (!PyArg_ParseTuple(args, "OO|i:addObject", &pyob, &pyother, &time)) + if (!PyArg_ParseTuple(args, "O|Oi:addObject", &pyob, &pyreference, &time)) return NULL; - if ( !ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, other, time): KX_Scene (first argument)") || - !ConvertPythonToGameObject(pyother, &other, false, "scene.addObject(object, other, time): KX_Scene (second argument)") ) + if (!ConvertPythonToGameObject(pyob, &ob, false, "scene.addObject(object, reference, time): KX_Scene (first argument)") || + !ConvertPythonToGameObject(pyreference, &reference, true, "scene.addObject(object, reference, time): KX_Scene (second argument)")) return NULL; if (!m_inactivelist->SearchValue(ob)) { - PyErr_Format(PyExc_ValueError, "scene.addObject(object, other, time): KX_Scene (first argument): object must be in an inactive layer"); + PyErr_Format(PyExc_ValueError, "scene.addObject(object, reference, time): KX_Scene (first argument): object must be in an inactive layer"); return NULL; } - SCA_IObject* replica = AddReplicaObject((SCA_IObject*)ob, other, time); + SCA_IObject *replica = AddReplicaObject((SCA_IObject*)ob, reference, time); // release here because AddReplicaObject AddRef's // the object is added to the scene so we don't want python to own a reference diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index c5840c28041..4f7ad98f30d 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -49,7 +49,7 @@ #include "RAS_Rect.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "RAS_2DFilterManager.h" /** @@ -107,6 +107,7 @@ class KX_Scene : public PyObjectPlus, public SCA_IScene PyObject* m_attr_dict; PyObject* m_draw_call_pre; PyObject* m_draw_call_post; + PyObject* m_draw_setup_call_pre; #endif struct CullingInfo { @@ -289,14 +290,18 @@ protected: double m_suspendedtime; double m_suspendeddelta; - double m_previousAnimTime; //the last time animations were updated - struct Scene* m_blenderScene; RAS_2DFilterManager m_filtermanager; KX_ObstacleSimulation* m_obstacleSimulation; + /** + * LOD Hysteresis settings + */ + bool m_isActivedHysteresis; + int m_lodHysteresisValue; + public: KX_Scene(class SCA_IInputDevice* keyboarddevice, class SCA_IInputDevice* mousedevice, @@ -548,6 +553,12 @@ public: // Update the mesh for objects based on level of detail settings void UpdateObjectLods(void); + + // LoD Hysteresis functions + void SetLodHysteresis(bool active); + bool IsActivedLodHysteresis(); + void SetLodHysteresisValue(int hysteresisvalue); + int GetLodHysteresisValue(); // Update the activity box settings for objects in this scene, if needed. void UpdateObjectActivity(void); @@ -614,12 +625,15 @@ public: static PyObject* pyattr_get_objects_inactive(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_lights(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_cameras(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject* pyattr_get_world(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject* pyattr_get_active_camera(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_active_camera(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_drawing_setup_callback_pre(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_drawing_setup_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); @@ -636,6 +650,7 @@ public: PyObject *GetPreDrawCB() { return m_draw_call_pre; } PyObject *GetPostDrawCB() { return m_draw_call_post; } + PyObject *GetPreDrawSetupCB() { return m_draw_setup_call_pre; } #endif /** diff --git a/source/gameengine/Ketsji/KX_SoundActuator.cpp b/source/gameengine/Ketsji/KX_SoundActuator.cpp index 4e5cd0ac5e1..02b1071e267 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.cpp +++ b/source/gameengine/Ketsji/KX_SoundActuator.cpp @@ -37,10 +37,14 @@ #include "KX_SoundActuator.h" #ifdef WITH_AUDASPACE -# include "AUD_C-API.h" -# include "AUD_PingPongFactory.h" -# include "AUD_IDevice.h" -# include "AUD_I3DHandle.h" +# ifdef WITH_SYSTEM_AUDASPACE +typedef float sample_t; +# include AUD_PYTHON_H +# endif +# include AUD_SOUND_H +# include AUD_SPECIAL_H +# include AUD_DEVICE_H +# include AUD_HANDLE_H #endif #include "KX_GameObject.h" @@ -53,7 +57,7 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, - boost::shared_ptr<AUD_IFactory> sound, + AUD_Sound* sound, float volume, float pitch, bool is3d, @@ -61,7 +65,8 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, KX_SOUNDACT_TYPE type)//, : SCA_IActuator(gameobj, KX_ACT_SOUND) { - m_sound = sound; + m_sound = AUD_Sound_copy(sound); + m_handle = NULL; m_volume = volume; m_pitch = pitch; m_is3d = is3d; @@ -74,20 +79,30 @@ KX_SoundActuator::KX_SoundActuator(SCA_IObject* gameobj, KX_SoundActuator::~KX_SoundActuator() { - if (m_handle.get()) - m_handle->stop(); + if(m_handle) + { + AUD_Handle_stop(m_handle); + } + + if(m_sound) + { + AUD_Sound_free(m_sound); + } } void KX_SoundActuator::play() { - if (m_handle.get()) - m_handle->stop(); + if(m_handle) + { + AUD_Handle_stop(m_handle); + m_handle = NULL; + } - if (!m_sound.get()) + if (!m_sound) return; // this is the sound that will be played and not deleted afterwards - boost::shared_ptr<AUD_IFactory> sound = m_sound; + AUD_Sound* sound = m_sound; bool loop = false; @@ -95,7 +110,7 @@ void KX_SoundActuator::play() { case KX_SOUNDACT_LOOPBIDIRECTIONAL: case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: - sound = boost::shared_ptr<AUD_IFactory>(new AUD_PingPongFactory(sound)); + sound = AUD_Sound_pingpong(sound); // fall through case KX_SOUNDACT_LOOPEND: case KX_SOUNDACT_LOOPSTOP: @@ -107,36 +122,33 @@ void KX_SoundActuator::play() break; } - try - { - m_handle = AUD_getDevice()->play(sound); - } - catch(AUD_Exception&) - { - // cannot play back, ignore - return; - } + AUD_Device* device = AUD_Device_getCurrent(); + m_handle = AUD_Device_play(device, sound, false); + AUD_Device_free(device); - boost::shared_ptr<AUD_I3DHandle> handle3d = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle); + // in case of pingpong, we have to free the sound + if(sound != m_sound) + AUD_Sound_free(sound); - if (m_is3d && handle3d.get()) + if (m_handle != NULL) { - handle3d->setRelative(true); - handle3d->setVolumeMaximum(m_3d.max_gain); - handle3d->setVolumeMinimum(m_3d.min_gain); - handle3d->setDistanceReference(m_3d.reference_distance); - handle3d->setDistanceMaximum(m_3d.max_distance); - handle3d->setAttenuation(m_3d.rolloff_factor); - handle3d->setConeAngleInner(m_3d.cone_inner_angle); - handle3d->setConeAngleOuter(m_3d.cone_outer_angle); - handle3d->setConeVolumeOuter(m_3d.cone_outer_gain); - } + if (m_is3d) + { + AUD_Handle_setRelative(m_handle, true); + AUD_Handle_setVolumeMaximum(m_handle, m_3d.max_gain); + AUD_Handle_setVolumeMinimum(m_handle, m_3d.min_gain); + AUD_Handle_setDistanceReference(m_handle, m_3d.reference_distance); + AUD_Handle_setDistanceMaximum(m_handle, m_3d.max_distance); + AUD_Handle_setAttenuation(m_handle, m_3d.rolloff_factor); + AUD_Handle_setConeAngleInner(m_handle, m_3d.cone_inner_angle); + AUD_Handle_setConeAngleOuter(m_handle, m_3d.cone_outer_angle); + AUD_Handle_setConeVolumeOuter(m_handle, m_3d.cone_outer_gain); + } - if (m_handle.get()) { if (loop) - m_handle->setLoopCount(-1); - m_handle->setPitch(m_pitch); - m_handle->setVolume(m_volume); + AUD_Handle_setLoopCount(m_handle, -1); + AUD_Handle_setPitch(m_handle, m_pitch); + AUD_Handle_setVolume(m_handle, m_volume); } m_isplaying = true; @@ -152,7 +164,8 @@ CValue* KX_SoundActuator::GetReplica() void KX_SoundActuator::ProcessReplica() { SCA_IActuator::ProcessReplica(); - m_handle = boost::shared_ptr<AUD_IHandle>(); + m_handle = NULL; + m_sound = AUD_Sound_copy(m_sound); } bool KX_SoundActuator::Update(double curtime, bool frame) @@ -167,11 +180,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame) RemoveAllEvents(); - if (!m_sound.get()) + if (!m_sound) return false; // actual audio device playing state - bool isplaying = m_handle.get() ? (m_handle->getStatus() == AUD_STATUS_PLAYING) : false; + bool isplaying = m_handle ? (AUD_Handle_getStatus(m_handle) == AUD_STATUS_PLAYING) : false; if (bNegativeEvent) { @@ -185,9 +198,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame) case KX_SOUNDACT_LOOPBIDIRECTIONAL_STOP: { // stop immediately - if (m_handle.get()) - m_handle->stop(); - m_handle = boost::shared_ptr<AUD_IHandle>(); + if (m_handle) + { + AUD_Handle_stop(m_handle); + m_handle = NULL; + } break; } case KX_SOUNDACT_PLAYEND: @@ -199,8 +214,8 @@ bool KX_SoundActuator::Update(double curtime, bool frame) case KX_SOUNDACT_LOOPBIDIRECTIONAL: { // stop the looping so that the sound stops when it finished - if (m_handle.get()) - m_handle->setLoopCount(0); + if (m_handle) + AUD_Handle_setLoopCount(m_handle, 0); break; } default: @@ -227,13 +242,11 @@ bool KX_SoundActuator::Update(double curtime, bool frame) play(); } // verify that the sound is still playing - isplaying = m_handle.get() ? (m_handle->getStatus() == AUD_STATUS_PLAYING) : false; + isplaying = m_handle ? (AUD_Handle_getStatus(m_handle) == AUD_STATUS_PLAYING) : false; if (isplaying) { - boost::shared_ptr<AUD_I3DHandle> handle3d = boost::dynamic_pointer_cast<AUD_I3DHandle>(m_handle); - - if (m_is3d && handle3d.get()) + if (m_is3d) { KX_Camera* cam = KX_GetActiveScene()->GetActiveCamera(); if (cam) @@ -241,20 +254,19 @@ bool KX_SoundActuator::Update(double curtime, bool frame) KX_GameObject* obj = (KX_GameObject*)this->GetParent(); MT_Point3 p; MT_Matrix3x3 Mo; - AUD_Vector3 v; - float q[4]; + float data[4]; Mo = cam->NodeGetWorldOrientation().inverse(); p = (obj->NodeGetWorldPosition() - cam->NodeGetWorldPosition()); p = Mo * p; - p.getValue(v.get()); - handle3d->setSourceLocation(v); + p.getValue(data); + AUD_Handle_setLocation(m_handle, data); p = (obj->GetLinearVelocity() - cam->GetLinearVelocity()); p = Mo * p; - p.getValue(v.get()); - handle3d->setSourceVelocity(v); - (Mo * obj->NodeGetWorldOrientation()).getRotation().getValue(q); - handle3d->setSourceOrientation(AUD_Quaternion(q[3], q[0], q[1], q[2])); + p.getValue(data); + AUD_Handle_setVelocity(m_handle, data); + (Mo * obj->NodeGetWorldOrientation()).getRotation().getValue(data); + AUD_Handle_setOrientation(m_handle, data); } } result = true; @@ -329,11 +341,11 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, startSound, "startSound()\n" "\tStarts the sound.\n") { - switch (m_handle.get() ? m_handle->getStatus() : AUD_STATUS_INVALID) { + switch (m_handle ? AUD_Handle_getStatus(m_handle) : AUD_STATUS_INVALID) { case AUD_STATUS_PLAYING: break; case AUD_STATUS_PAUSED: - m_handle->resume(); + AUD_Handle_resume(m_handle); break; default: play(); @@ -345,8 +357,8 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, pauseSound, "pauseSound()\n" "\tPauses the sound.\n") { - if (m_handle.get()) - m_handle->pause(); + if (m_handle) + AUD_Handle_pause(m_handle); Py_RETURN_NONE; } @@ -354,9 +366,11 @@ KX_PYMETHODDEF_DOC_NOARGS(KX_SoundActuator, stopSound, "stopSound()\n" "\tStops the sound.\n") { - if (m_handle.get()) - m_handle->stop(); - m_handle = boost::shared_ptr<AUD_IHandle>(); + if (m_handle) + { + AUD_Handle_stop(m_handle); + m_handle = NULL; + } Py_RETURN_NONE; } @@ -404,8 +418,8 @@ PyObject *KX_SoundActuator::pyattr_get_audposition(void *self, const struct KX_P KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); float position = 0.0; - if (actuator->m_handle.get()) - position = actuator->m_handle->getPosition(); + if (actuator->m_handle) + position = AUD_Handle_getPosition(actuator->m_handle); PyObject *result = PyFloat_FromDouble(position); @@ -435,8 +449,8 @@ PyObject *KX_SoundActuator::pyattr_get_pitch(void *self, const struct KX_PYATTRI PyObject *KX_SoundActuator::pyattr_get_sound(void *self, const struct KX_PYATTRIBUTE_DEF *attrdef) { KX_SoundActuator * actuator = static_cast<KX_SoundActuator *> (self); - if (actuator->m_sound.get()) - return (PyObject *)AUD_getPythonFactory(&actuator->m_sound); + if (actuator->m_sound) + return (PyObject *)AUD_getPythonSound(actuator->m_sound); else Py_RETURN_NONE; } @@ -450,50 +464,49 @@ int KX_SoundActuator::pyattr_set_3d_property(void *self, const struct KX_PYATTRI if (!PyArg_Parse(value, "f", &prop_value)) return PY_SET_ATTR_FAIL; - boost::shared_ptr<AUD_I3DHandle> handle3d = boost::dynamic_pointer_cast<AUD_I3DHandle>(actuator->m_handle); // if sound is working and 3D, set the new setting if (!actuator->m_is3d) return PY_SET_ATTR_FAIL; if (!strcmp(prop, "volume_maximum")) { actuator->m_3d.max_gain = prop_value; - if (handle3d.get()) - handle3d->setVolumeMaximum(prop_value); + if (actuator->m_handle) + AUD_Handle_setVolumeMaximum(actuator->m_handle, prop_value); } else if (!strcmp(prop, "volume_minimum")) { actuator->m_3d.min_gain = prop_value; - if (handle3d.get()) - handle3d->setVolumeMinimum(prop_value); + if (actuator->m_handle) + AUD_Handle_setVolumeMinimum(actuator->m_handle, prop_value); } else if (!strcmp(prop, "distance_reference")) { actuator->m_3d.reference_distance = prop_value; - if (handle3d.get()) - handle3d->setDistanceReference(prop_value); + if (actuator->m_handle) + AUD_Handle_setDistanceReference(actuator->m_handle, prop_value); } else if (!strcmp(prop, "distance_maximum")) { actuator->m_3d.max_distance = prop_value; - if (handle3d.get()) - handle3d->setDistanceMaximum(prop_value); + if (actuator->m_handle) + AUD_Handle_setDistanceMaximum(actuator->m_handle, prop_value); } else if (!strcmp(prop, "attenuation")) { actuator->m_3d.rolloff_factor = prop_value; - if (handle3d.get()) - handle3d->setAttenuation(prop_value); + if (actuator->m_handle) + AUD_Handle_setAttenuation(actuator->m_handle, prop_value); } else if (!!strcmp(prop, "cone_angle_inner")) { actuator->m_3d.cone_inner_angle = prop_value; - if (handle3d.get()) - handle3d->setConeAngleInner(prop_value); + if (actuator->m_handle) + AUD_Handle_setConeAngleInner(actuator->m_handle, prop_value); } else if (!strcmp(prop, "cone_angle_outer")) { actuator->m_3d.cone_outer_angle = prop_value; - if (handle3d.get()) - handle3d->setConeAngleOuter(prop_value); + if (actuator->m_handle) + AUD_Handle_setConeAngleOuter(actuator->m_handle, prop_value); } else if (!strcmp(prop, "cone_volume_outer")) { actuator->m_3d.cone_outer_gain = prop_value; - if (handle3d.get()) - handle3d->setConeVolumeOuter(prop_value); + if (actuator->m_handle) + AUD_Handle_setConeVolumeOuter(actuator->m_handle, prop_value); } else { return PY_SET_ATTR_FAIL; @@ -510,8 +523,8 @@ int KX_SoundActuator::pyattr_set_audposition(void *self, const struct KX_PYATTRI if (!PyArg_Parse(value, "f", &position)) return PY_SET_ATTR_FAIL; - if (actuator->m_handle.get()) - actuator->m_handle->seek(position); + if (actuator->m_handle) + AUD_Handle_setPosition(actuator->m_handle, position); return PY_SET_ATTR_SUCCESS; } @@ -523,8 +536,8 @@ int KX_SoundActuator::pyattr_set_gain(void *self, const struct KX_PYATTRIBUTE_DE return PY_SET_ATTR_FAIL; actuator->m_volume = gain; - if (actuator->m_handle.get()) - actuator->m_handle->setVolume(gain); + if (actuator->m_handle) + AUD_Handle_setVolume(actuator->m_handle, gain); return PY_SET_ATTR_SUCCESS; } @@ -537,8 +550,8 @@ int KX_SoundActuator::pyattr_set_pitch(void *self, const struct KX_PYATTRIBUTE_D return PY_SET_ATTR_FAIL; actuator->m_pitch = pitch; - if (actuator->m_handle.get()) - actuator->m_handle->setPitch(pitch); + if (actuator->m_handle) + AUD_Handle_setPitch(actuator->m_handle, pitch); return PY_SET_ATTR_SUCCESS; } @@ -550,11 +563,12 @@ int KX_SoundActuator::pyattr_set_sound(void *self, const struct KX_PYATTRIBUTE_D if (!PyArg_Parse(value, "O", &sound)) return PY_SET_ATTR_FAIL; - boost::shared_ptr<AUD_IFactory>* snd = reinterpret_cast<boost::shared_ptr<AUD_IFactory>*>(AUD_getPythonSound((void *)sound)); + AUD_Sound *snd = AUD_getSoundFromPython(sound); + if (snd) { - actuator->m_sound = *snd; - delete snd; + AUD_Sound_free(actuator->m_sound); + actuator->m_sound = snd; return PY_SET_ATTR_SUCCESS; } diff --git a/source/gameengine/Ketsji/KX_SoundActuator.h b/source/gameengine/Ketsji/KX_SoundActuator.h index 68eff56797b..5ec2fda722f 100644 --- a/source/gameengine/Ketsji/KX_SoundActuator.h +++ b/source/gameengine/Ketsji/KX_SoundActuator.h @@ -35,10 +35,8 @@ #include "SCA_IActuator.h" #ifdef WITH_AUDASPACE -# include "AUD_C-API.h" -# include "AUD_IFactory.h" -# include "AUD_IHandle.h" -# include <boost/shared_ptr.hpp> +# include AUD_SOUND_H +# include AUD_HANDLE_H #endif #include "BKE_sound.h" @@ -58,12 +56,12 @@ class KX_SoundActuator : public SCA_IActuator { Py_Header bool m_isplaying; - boost::shared_ptr<AUD_IFactory> m_sound; + AUD_Sound* m_sound; float m_volume; float m_pitch; bool m_is3d; KX_3DSoundSettings m_3d; - boost::shared_ptr<AUD_IHandle> m_handle; + AUD_Handle* m_handle; void play(); @@ -84,7 +82,7 @@ public: KX_SOUNDACT_TYPE m_type; KX_SoundActuator(SCA_IObject* gameobj, - boost::shared_ptr<AUD_IFactory> sound, + AUD_Sound *sound, float volume, float pitch, bool is3d, diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.cpp b/source/gameengine/Ketsji/KX_SteeringActuator.cpp index ff192299702..cd2cd2bae0b 100644 --- a/source/gameengine/Ketsji/KX_SteeringActuator.cpp +++ b/source/gameengine/Ketsji/KX_SteeringActuator.cpp @@ -41,7 +41,7 @@ /* Native functions */ /* ------------------------------------------------------------------------- */ -KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj, +KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj, int mode, KX_GameObject *target, KX_GameObject *navmesh, @@ -54,7 +54,8 @@ KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj, KX_ObstacleSimulation* simulation, short facingmode, bool normalup, - bool enableVisualization) + bool enableVisualization, + bool lockzvel) : SCA_IActuator(gameobj, KX_ACT_STEERING), m_target(target), m_mode(mode), @@ -72,6 +73,7 @@ KX_SteeringActuator::KX_SteeringActuator(SCA_IObject *gameobj, m_normalUp(normalup), m_pathLen(0), m_pathUpdatePeriod(pathUpdatePeriod), + m_lockzvel(lockzvel), m_wayPointIdx(-1), m_steerVec(MT_Vector3(0, 0, 0)) { @@ -266,14 +268,14 @@ bool KX_SteeringActuator::Update(double curtime, bool frame) m_steerVec.z() = 0; if (!m_steerVec.fuzzyZero()) m_steerVec.normalize(); - MT_Vector3 newvel = m_velocity*m_steerVec; + MT_Vector3 newvel = m_velocity * m_steerVec; //adjust velocity to avoid obstacles if (m_simulation && m_obstacle /*&& !newvel.fuzzyZero()*/) { if (m_enableVisualization) KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector3(1.0, 0.0, 0.0)); - m_simulation->AdjustObstacleVelocity(m_obstacle, m_mode!=KX_STEERING_PATHFOLLOWING ? m_navmesh : NULL, + m_simulation->AdjustObstacleVelocity(m_obstacle, m_mode!=KX_STEERING_PATHFOLLOWING ? m_navmesh : NULL, newvel, m_acceleration*delta, m_turnspeed/180.0f*M_PI*delta); if (m_enableVisualization) KX_RasterizerDrawDebugLine(mypos, mypos + newvel, MT_Vector3(0.0, 1.0, 0.0)); @@ -285,7 +287,12 @@ bool KX_SteeringActuator::Update(double curtime, bool frame) //temporary solution: set 2D steering velocity directly to obj //correct way is to apply physical force MT_Vector3 curvel = obj->GetLinearVelocity(); - newvel.z() = curvel.z(); + + if (m_lockzvel) + newvel.z() = 0.0f; + else + newvel.z() = curvel.z(); + obj->setLinearVelocity(newvel, false); } else @@ -554,6 +561,7 @@ PyAttributeDef KX_SteeringActuator::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("steeringVec", KX_SteeringActuator, pyattr_get_steeringVec), KX_PYATTRIBUTE_SHORT_RW("facingMode", 0, 6, true, KX_SteeringActuator, m_facingMode), KX_PYATTRIBUTE_INT_RW("pathUpdatePeriod", -1, 100000, true, KX_SteeringActuator, m_pathUpdatePeriod), + KX_PYATTRIBUTE_BOOL_RW("lockZVelocity", KX_SteeringActuator, m_lockzvel), { NULL } //Sentinel }; @@ -602,8 +610,7 @@ int KX_SteeringActuator::pyattr_set_navmesh(void *self, const struct KX_PYATTRIB if (!ConvertPythonToGameObject(value, &gameobj, true, "actuator.object = value: KX_SteeringActuator")) return PY_SET_ATTR_FAIL; // ConvertPythonToGameObject sets the error - if (dynamic_cast<KX_NavMeshObject *>(gameobj) == NULL) - { + if (dynamic_cast<KX_NavMeshObject *>(gameobj) == NULL) { PyErr_Format(PyExc_TypeError, "KX_NavMeshObject is expected"); return PY_SET_ATTR_FAIL; } diff --git a/source/gameengine/Ketsji/KX_SteeringActuator.h b/source/gameengine/Ketsji/KX_SteeringActuator.h index 1e8ac9a54f0..3273471c166 100644 --- a/source/gameengine/Ketsji/KX_SteeringActuator.h +++ b/source/gameengine/Ketsji/KX_SteeringActuator.h @@ -62,6 +62,7 @@ class KX_SteeringActuator : public SCA_IActuator int m_pathLen; int m_pathUpdatePeriod; double m_pathUpdateTime; + bool m_lockzvel; int m_wayPointIdx; MT_Matrix3x3 m_parentlocalmat; MT_Vector3 m_steerVec; @@ -89,7 +90,8 @@ public: KX_ObstacleSimulation* simulation, short facingmode, bool normalup, - bool enableVisualization); + bool enableVisualization, + bool lockzvel); virtual ~KX_SteeringActuator(); virtual bool Update(double curtime, bool frame); diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.cpp b/source/gameengine/Ketsji/KX_TouchEventManager.cpp index 7ec379eec26..eb774960d41 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.cpp +++ b/source/gameengine/Ketsji/KX_TouchEventManager.cpp @@ -60,7 +60,7 @@ bool KX_TouchEventManager::NewHandleCollision(void* object1, void* object2, cons PHY_IPhysicsController* obj1 = static_cast<PHY_IPhysicsController*>(object1); PHY_IPhysicsController* obj2 = static_cast<PHY_IPhysicsController*>(object2); - m_newCollisions.insert(std::pair<PHY_IPhysicsController*, PHY_IPhysicsController*>(obj1, obj2)); + m_newCollisions.insert(NewCollision(obj1, obj2, coll_data)); return false; } @@ -209,9 +209,11 @@ void KX_TouchEventManager::NextFrame() } } // Run python callbacks - kxObj1->RunCollisionCallbacks(kxObj2); - kxObj2->RunCollisionCallbacks(kxObj1); + PHY_CollData *colldata = cit->colldata; + kxObj1->RunCollisionCallbacks(kxObj2, colldata->m_point1, colldata->m_normal); + kxObj2->RunCollisionCallbacks(kxObj1, colldata->m_point2, -colldata->m_normal); + delete cit->colldata; } m_newCollisions.clear(); @@ -219,3 +221,19 @@ void KX_TouchEventManager::NextFrame() for (it.begin();!it.end();++it) (*it)->Activate(m_logicmgr); } + + +KX_TouchEventManager::NewCollision::NewCollision(PHY_IPhysicsController *first, + PHY_IPhysicsController *second, + const PHY_CollData *colldata) + : first(first), second(second), colldata(new PHY_CollData(*colldata)) +{} + +KX_TouchEventManager::NewCollision::NewCollision(const NewCollision &to_copy) + : first(to_copy.first), second(to_copy.second), colldata(to_copy.colldata) +{} + +bool KX_TouchEventManager::NewCollision::operator<(const NewCollision &other) const +{ + return first < other.first || second < other.second || colldata < other.colldata; +} diff --git a/source/gameengine/Ketsji/KX_TouchEventManager.h b/source/gameengine/Ketsji/KX_TouchEventManager.h index bd4903c1545..d9c6fdad307 100644 --- a/source/gameengine/Ketsji/KX_TouchEventManager.h +++ b/source/gameengine/Ketsji/KX_TouchEventManager.h @@ -45,7 +45,29 @@ class PHY_IPhysicsEnvironment; class KX_TouchEventManager : public SCA_EventManager { - typedef std::pair<PHY_IPhysicsController*, PHY_IPhysicsController*> NewCollision; + /** + * Contains two colliding objects and the first contact point. + */ + class NewCollision { + public: + PHY_IPhysicsController *first; + PHY_IPhysicsController *second; + PHY_CollData *colldata; + + /** + * Creates a copy of the given PHY_CollData; freeing that copy should be done by the owner of + * the NewCollision object. + * + * This allows us to efficiently store NewCollision objects in a std::set without creating more + * copies of colldata, as the NewCollision copy constructor reuses the pointer and doesn't clone + * it again. */ + NewCollision(PHY_IPhysicsController *first, + PHY_IPhysicsController *second, + const PHY_CollData *colldata); + NewCollision(const NewCollision &to_copy); + bool operator<(const NewCollision &other) const; + }; + PHY_IPhysicsEnvironment* m_physEnv; std::set<NewCollision> m_newCollisions; diff --git a/source/gameengine/Ketsji/KX_TouchSensor.cpp b/source/gameengine/Ketsji/KX_TouchSensor.cpp index 5cb1d5f3620..593d3e844e8 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.cpp +++ b/source/gameengine/Ketsji/KX_TouchSensor.cpp @@ -41,6 +41,8 @@ #include "PHY_IPhysicsController.h" +#include "RAS_MeshObject.h" + #include <iostream> #include "PHY_IPhysicsEnvironment.h" @@ -219,14 +221,17 @@ bool KX_TouchSensor::BroadPhaseSensorFilterCollision(void*obj1,void*obj2) bool found = m_touchedpropname.IsEmpty(); if (!found) { - if (m_bFindMaterial) - { - if (client_info->m_auxilary_info) - { - found = (!strcmp(m_touchedpropname.Ptr(), (char*)client_info->m_auxilary_info)); + if (m_bFindMaterial) { + for (unsigned int i = 0; i < otherobj->GetMeshCount(); ++i) { + RAS_MeshObject *meshObj = otherobj->GetMesh(i); + for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { + found = strcmp(m_touchedpropname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0; + if (found) + break; + } } - } else - { + } + else { found = (otherobj->GetProperty(m_touchedpropname) != NULL); } } @@ -255,16 +260,22 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll { bool found = m_touchedpropname.IsEmpty(); + bool hitMaterial = false; if (!found) { - if (m_bFindMaterial) - { - if (client_info->m_auxilary_info) - { - found = (!strcmp(m_touchedpropname.Ptr(), (char*)client_info->m_auxilary_info)); + if (m_bFindMaterial) { + for (unsigned int i = 0; i < gameobj->GetMeshCount(); ++i) { + RAS_MeshObject *meshObj = gameobj->GetMesh(i); + for (unsigned int j = 0; j < meshObj->NumMaterials(); ++j) { + found = strcmp(m_touchedpropname.ReadPtr(), meshObj->GetMaterialName(j).ReadPtr() + 2) == 0; + if (found) { + hitMaterial = true; + break; + } + } } - } else - { + } + else { found = (gameobj->GetProperty(m_touchedpropname) != NULL); } } @@ -278,7 +289,7 @@ bool KX_TouchSensor::NewHandleCollision(void*object1,void*object2,const PHY_Coll } m_bTriggered = true; m_hitObject = gameobj; - m_hitMaterial = (client_info->m_auxilary_info ? (char*)client_info->m_auxilary_info : ""); + m_hitMaterial = hitMaterial; //printf("KX_TouchSensor::HandleCollision\n"); } diff --git a/source/gameengine/Ketsji/KX_TouchSensor.h b/source/gameengine/Ketsji/KX_TouchSensor.h index 0edca44296a..e1b5725a32b 100644 --- a/source/gameengine/Ketsji/KX_TouchSensor.h +++ b/source/gameengine/Ketsji/KX_TouchSensor.h @@ -34,7 +34,7 @@ #define __KX_TOUCHSENSOR_H__ #include "SCA_ISensor.h" -#include "ListValue.h" +#include "EXP_ListValue.h" struct PHY_CollData; diff --git a/source/gameengine/Ketsji/KX_TrackToActuator.cpp b/source/gameengine/Ketsji/KX_TrackToActuator.cpp index 75baf5fac1d..3ed8eba759f 100644 --- a/source/gameengine/Ketsji/KX_TrackToActuator.cpp +++ b/source/gameengine/Ketsji/KX_TrackToActuator.cpp @@ -44,7 +44,7 @@ #include <iostream> #include "KX_GameObject.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" /* ------------------------------------------------------------------------- */ /* Native functions */ diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp index 535ed5ed39a..ee791a44782 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.cpp +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.cpp @@ -22,7 +22,7 @@ * \ingroup ketsji */ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "KX_VehicleWrapper.h" #include "PHY_IPhysicsEnvironment.h" @@ -53,6 +53,23 @@ KX_VehicleWrapper::~KX_VehicleWrapper() #ifdef WITH_PYTHON + +static bool raise_exc_wheel(PHY_IVehicle *vehicle, int i, const char *method) +{ + if (i < 0 || i >= vehicle->GetNumWheels()) { + PyErr_Format(PyExc_ValueError, + "%s(...): wheel index %d out of range (0 to %d).", method, i, vehicle->GetNumWheels() - 1); + return true; + } + else { + return false; + } +} + +#define WHEEL_INDEX_CHECK_OR_RETURN(i, method) \ + if (raise_exc_wheel(m_vehicle, i, method)) {return NULL;} (void)0 + + PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) { @@ -67,22 +84,36 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) KX_GameObject *gameOb; if (!ConvertPythonToGameObject(wheelGameObject, &gameOb, false, "vehicle.addWheel(...): KX_VehicleWrapper (first argument)")) return NULL; - if (gameOb->GetSGNode()) { - PHY_IMotionState* motionState = new KX_MotionState(gameOb->GetSGNode()); - - /* TODO - no error checking here! - bad juju */ MT_Vector3 attachPos,attachDir,attachAxle; - PyVecTo(pylistPos,attachPos); - PyVecTo(pylistDir,attachDir); - PyVecTo(pylistAxleDir,attachAxle); + if(!PyVecTo(pylistPos,attachPos)) { + PyErr_SetString(PyExc_AttributeError, + "addWheel(...) Unable to add wheel. attachPos must be a vector with 3 elements."); + return NULL; + } + if(!PyVecTo(pylistDir,attachDir)) { + PyErr_SetString(PyExc_AttributeError, + "addWheel(...) Unable to add wheel. downDir must be a vector with 3 elements."); + return NULL; + } + if(!PyVecTo(pylistAxleDir,attachAxle)) { + PyErr_SetString(PyExc_AttributeError, + "addWheel(...) Unable to add wheel. axleDir must be a vector with 3 elements."); + return NULL; + } //someone reverse some conventions inside Bullet (axle winding) attachAxle = -attachAxle; - printf("attempt for addWheel: suspensionRestLength%f wheelRadius %f, hasSteering:%d\n",suspensionRestLength,wheelRadius,hasSteering); + if(wheelRadius<=0) { + PyErr_SetString(PyExc_AttributeError, + "addWheel(...) Unable to add wheel. wheelRadius must be positive."); + return NULL; + } + + PHY_IMotionState *motionState = new KX_MotionState(gameOb->GetSGNode()); m_vehicle->AddWheel(motionState,attachPos,attachDir,attachAxle,suspensionRestLength,wheelRadius,hasSteering); } @@ -93,8 +124,6 @@ PyObject *KX_VehicleWrapper::PyAddWheel(PyObject *args) } - - PyObject *KX_VehicleWrapper::PyGetWheelPosition(PyObject *args) { @@ -103,6 +132,8 @@ PyObject *KX_VehicleWrapper::PyGetWheelPosition(PyObject *args) if (PyArg_ParseTuple(args,"i:getWheelPosition",&wheelIndex)) { float position[3]; + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelPosition"); + m_vehicle->GetWheelPosition(wheelIndex,position[0],position[1],position[2]); MT_Vector3 pos(position[0],position[1],position[2]); return PyObjectFrom(pos); @@ -115,6 +146,8 @@ PyObject *KX_VehicleWrapper::PyGetWheelRotation(PyObject *args) int wheelIndex; if (PyArg_ParseTuple(args,"i:getWheelRotation",&wheelIndex)) { + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelRotation"); + return PyFloat_FromDouble(m_vehicle->GetWheelRotation(wheelIndex)); } return NULL; @@ -126,6 +159,8 @@ PyObject *KX_VehicleWrapper::PyGetWheelOrientationQuaternion(PyObject *args) if (PyArg_ParseTuple(args,"i:getWheelOrientationQuaternion",&wheelIndex)) { float orn[4]; + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "getWheelOrientationQuaternion"); + m_vehicle->GetWheelOrientationQuaternion(wheelIndex,orn[0],orn[1],orn[2],orn[3]); MT_Quaternion quatorn(orn[0],orn[1],orn[2],orn[3]); MT_Matrix3x3 ornmat(quatorn); @@ -148,7 +183,6 @@ PyObject *KX_VehicleWrapper::PyGetConstraintId(PyObject *args) } - PyObject *KX_VehicleWrapper::PyApplyEngineForce(PyObject *args) { float force; @@ -156,6 +190,8 @@ PyObject *KX_VehicleWrapper::PyApplyEngineForce(PyObject *args) if (PyArg_ParseTuple(args,"fi:applyEngineForce",&force,&wheelIndex)) { + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "applyEngineForce"); + force *= -1.f;//someone reverse some conventions inside Bullet (axle winding) m_vehicle->ApplyEngineForce(force,wheelIndex); } @@ -172,6 +208,8 @@ PyObject *KX_VehicleWrapper::PySetTyreFriction(PyObject *args) if (PyArg_ParseTuple(args,"fi:setTyreFriction",&wheelFriction,&wheelIndex)) { + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setTyreFriction"); + m_vehicle->SetWheelFriction(wheelFriction,wheelIndex); } else { @@ -187,6 +225,8 @@ PyObject *KX_VehicleWrapper::PySetSuspensionStiffness(PyObject *args) if (PyArg_ParseTuple(args,"fi:setSuspensionStiffness",&suspensionStiffness,&wheelIndex)) { + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionStiffness"); + m_vehicle->SetSuspensionStiffness(suspensionStiffness,wheelIndex); } else { @@ -202,6 +242,8 @@ PyObject *KX_VehicleWrapper::PySetSuspensionDamping(PyObject *args) if (PyArg_ParseTuple(args,"fi:setSuspensionDamping",&suspensionDamping,&wheelIndex)) { + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionDamping"); + m_vehicle->SetSuspensionDamping(suspensionDamping,wheelIndex); } else { return NULL; @@ -216,6 +258,8 @@ PyObject *KX_VehicleWrapper::PySetSuspensionCompression(PyObject *args) if (PyArg_ParseTuple(args,"fi:setSuspensionCompression",&suspensionCompression,&wheelIndex)) { + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSuspensionCompression"); + m_vehicle->SetSuspensionCompression(suspensionCompression,wheelIndex); } else { return NULL; @@ -230,6 +274,8 @@ PyObject *KX_VehicleWrapper::PySetRollInfluence(PyObject *args) if (PyArg_ParseTuple(args,"fi:setRollInfluence",&rollInfluence,&wheelIndex)) { + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setRollInfluence"); + m_vehicle->SetRollInfluence(rollInfluence,wheelIndex); } else { @@ -246,6 +292,8 @@ PyObject *KX_VehicleWrapper::PyApplyBraking(PyObject *args) if (PyArg_ParseTuple(args,"fi:applyBraking",&braking,&wheelIndex)) { + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "applyBraking"); + m_vehicle->ApplyBraking(braking,wheelIndex); } else { @@ -255,8 +303,6 @@ PyObject *KX_VehicleWrapper::PyApplyBraking(PyObject *args) } - - PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args) { float steeringValue; @@ -264,6 +310,8 @@ PyObject *KX_VehicleWrapper::PySetSteeringValue(PyObject *args) if (PyArg_ParseTuple(args,"fi:setSteeringValue",&steeringValue,&wheelIndex)) { + WHEEL_INDEX_CHECK_OR_RETURN(wheelIndex, "setSteeringValue"); + m_vehicle->SetSteeringValue(steeringValue,wheelIndex); } else { @@ -316,17 +364,11 @@ PyMethodDef KX_VehicleWrapper::Methods[] = { {"setSteeringValue",(PyCFunction) KX_VehicleWrapper::sPySetSteeringValue, METH_VARARGS}, {"applyEngineForce",(PyCFunction) KX_VehicleWrapper::sPyApplyEngineForce, METH_VARARGS}, {"applyBraking",(PyCFunction) KX_VehicleWrapper::sPyApplyBraking, METH_VARARGS}, - {"setTyreFriction",(PyCFunction) KX_VehicleWrapper::sPySetTyreFriction, METH_VARARGS}, - {"setSuspensionStiffness",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionStiffness, METH_VARARGS}, - {"setSuspensionDamping",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionDamping, METH_VARARGS}, - {"setSuspensionCompression",(PyCFunction) KX_VehicleWrapper::sPySetSuspensionCompression, METH_VARARGS}, - {"setRollInfluence",(PyCFunction) KX_VehicleWrapper::sPySetRollInfluence, METH_VARARGS}, - {NULL,NULL} //Sentinel }; diff --git a/source/gameengine/Ketsji/KX_VehicleWrapper.h b/source/gameengine/Ketsji/KX_VehicleWrapper.h index c38f57d8b9f..22b9591f48b 100644 --- a/source/gameengine/Ketsji/KX_VehicleWrapper.h +++ b/source/gameengine/Ketsji/KX_VehicleWrapper.h @@ -6,7 +6,7 @@ #ifndef __KX_VEHICLEWRAPPER_H__ #define __KX_VEHICLEWRAPPER_H__ -#include "Value.h" +#include "EXP_Value.h" class PHY_IVehicle; class PHY_IMotionState; diff --git a/source/gameengine/Ketsji/KX_WorldInfo.cpp b/source/gameengine/Ketsji/KX_WorldInfo.cpp index 444d6b0771b..111d81cad2e 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.cpp +++ b/source/gameengine/Ketsji/KX_WorldInfo.cpp @@ -31,8 +31,464 @@ #include "KX_WorldInfo.h" +#include "KX_PythonInit.h" +#include "KX_PyMath.h" +#include "RAS_IRasterizer.h" +#include "GPU_material.h" + +/* This little block needed for linking to Blender... */ +#ifdef WIN32 +#include "BLI_winstuff.h" +#endif + +/* This list includes only data type definitions */ +#include "DNA_scene_types.h" +#include "DNA_world_types.h" + +#include "BLI_math.h" + +#include "BKE_global.h" +#include "BKE_scene.h" +/* end of blender include block */ + + +KX_WorldInfo::KX_WorldInfo(Scene *blenderscene, World *blenderworld) +{ + if (blenderworld) { + m_name = blenderworld->id.name + 2; + m_do_color_management = BKE_scene_check_color_management_enabled(blenderscene); + m_hasworld = true; + m_hasmist = ((blenderworld->mode) & WO_MIST ? true : false); + m_misttype = blenderworld->mistype; + m_miststart = blenderworld->miststa; + m_mistdistance = blenderworld->mistdist; + m_mistintensity = blenderworld->misi; + setMistColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); + setBackColor(blenderworld->horr, blenderworld->horg, blenderworld->horb); + setAmbientColor(blenderworld->ambr, blenderworld->ambg, blenderworld->ambb); + } + else { + m_hasworld = false; + } +} KX_WorldInfo::~KX_WorldInfo() { } +const STR_String& KX_WorldInfo::GetName() +{ + return m_name; +} + +bool KX_WorldInfo::hasWorld() +{ + return m_hasworld; +} + +void KX_WorldInfo::setBackColor(float r, float g, float b) +{ + m_backgroundcolor[0] = r; + m_backgroundcolor[1] = g; + m_backgroundcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_backgroundcolor, m_backgroundcolor); + } + else { + copy_v3_v3(m_con_backgroundcolor, m_backgroundcolor); + } +} + +const float *KX_WorldInfo::getBackColorConverted() const +{ + return m_con_backgroundcolor; +} + +void KX_WorldInfo::setMistType(short type) +{ + m_misttype = type; +} + +void KX_WorldInfo::setUseMist(bool enable) +{ + m_hasmist = enable; +} + +void KX_WorldInfo::setMistStart(float d) +{ + m_miststart = d; +} + +void KX_WorldInfo::setMistDistance(float d) +{ + m_mistdistance = d; +} + +void KX_WorldInfo::setMistIntensity(float intensity) +{ + m_mistintensity = intensity; +} +void KX_WorldInfo::setMistColor(float r, float g, float b) +{ + m_mistcolor[0] = r; + m_mistcolor[1] = g; + m_mistcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_mistcolor, m_mistcolor); + } + else { + copy_v3_v3(m_con_mistcolor, m_mistcolor); + } +} + +void KX_WorldInfo::setAmbientColor(float r, float g, float b) +{ + m_ambientcolor[0] = r; + m_ambientcolor[1] = g; + m_ambientcolor[2] = b; + + if (m_do_color_management) { + linearrgb_to_srgb_v3_v3(m_con_ambientcolor, m_ambientcolor); + } + else { + copy_v3_v3(m_con_ambientcolor, m_ambientcolor); + } +} + +void KX_WorldInfo::UpdateBackGround() +{ + if (m_hasworld) { + RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); + + if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetBackColor(m_con_backgroundcolor); + GPU_horizon_update_color(m_backgroundcolor); + } + } +} + +void KX_WorldInfo::UpdateWorldSettings() +{ + if (m_hasworld) { + RAS_IRasterizer *m_rasterizer = KX_GetActiveEngine()->GetRasterizer(); + + if (m_rasterizer->GetDrawingMode() >= RAS_IRasterizer::KX_SOLID) { + m_rasterizer->SetAmbientColor(m_con_ambientcolor); + GPU_ambient_update_color(m_ambientcolor); + + if (m_hasmist) { + m_rasterizer->SetFog(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_con_mistcolor); + GPU_mist_update_values(m_misttype, m_miststart, m_mistdistance, m_mistintensity, m_mistcolor); + m_rasterizer->EnableFog(true); + GPU_mist_update_enable(true); + } + else { + m_rasterizer->EnableFog(false); + GPU_mist_update_enable(false); + } + } + } +} + +#ifdef WITH_PYTHON + +/* ------------------------------------------------------------------------- + * Python functions + * ------------------------------------------------------------------------- */ +PyObject *KX_WorldInfo::py_repr(void) +{ + return PyUnicode_From_STR_String(GetName()); +} + +/* ------------------------------------------------------------------------- + * Python Integration Hooks + * ------------------------------------------------------------------------- */ +PyTypeObject KX_WorldInfo::Type = { + PyVarObject_HEAD_INIT(NULL, 0) + "KX_WorldInfo", + sizeof(PyObjectPlus_Proxy), + 0, + py_base_dealloc, + 0, + 0, + 0, + 0, + py_base_repr, + 0,0,0,0,0,0,0,0,0, + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, + 0,0,0,0,0,0,0, + Methods, + 0, + 0, + &PyObjectPlus::Type, + 0,0,0,0,0,0, + py_base_new +}; + +PyMethodDef KX_WorldInfo::Methods[] = { + {NULL,NULL} /* Sentinel */ +}; + +PyAttributeDef KX_WorldInfo::Attributes[] = { + KX_PYATTRIBUTE_BOOL_RW("mistEnable", KX_WorldInfo, m_hasmist), + KX_PYATTRIBUTE_FLOAT_RW("mistStart", 0.0f, 10000.0f, KX_WorldInfo, m_miststart), + KX_PYATTRIBUTE_FLOAT_RW("mistDistance", 0.001f, 10000.0f, KX_WorldInfo, m_mistdistance), + KX_PYATTRIBUTE_FLOAT_RW("mistIntensity", 0.0f, 1.0f, KX_WorldInfo, m_mistintensity), + KX_PYATTRIBUTE_SHORT_RW("mistType", 0, 2, true, KX_WorldInfo, m_misttype), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_LINEAR", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RO_FUNCTION("KX_MIST_INV_QUADRATIC", KX_WorldInfo, pyattr_get_mist_typeconst), + KX_PYATTRIBUTE_RW_FUNCTION("mistColor", KX_WorldInfo, pyattr_get_mist_color, pyattr_set_mist_color), + KX_PYATTRIBUTE_RW_FUNCTION("backgroundColor", KX_WorldInfo, pyattr_get_back_color, pyattr_set_back_color), + KX_PYATTRIBUTE_RW_FUNCTION("ambientColor", KX_WorldInfo, pyattr_get_ambient_color, pyattr_set_ambient_color), + { NULL } /* Sentinel */ +}; + +/* Attribute get/set functions */ + +#ifdef USE_MATHUTILS + +/*----------------------mathutils callbacks ----------------------------*/ + +/* subtype */ +#define MATHUTILS_VEC_CB_MIST_COLOR 1 +#define MATHUTILS_VEC_CB_BACK_COLOR 2 +#define MATHUTILS_VEC_CB_AMBIENT_COLOR 3 + +static unsigned char mathutils_world_vector_cb_index = -1; /* index for our callbacks */ + +static int mathutils_world_generic_check(BaseMathObject *bmo) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + if (self == NULL) + return -1; + + return 0; +} + +static int mathutils_world_vector_get(BaseMathObject *bmo, int subtype) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + copy_v3_v3(bmo->data, self->m_mistcolor); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + copy_v3_v3(bmo->data, self->m_backgroundcolor); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + copy_v3_v3(bmo->data, self->m_ambientcolor); + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_set(BaseMathObject *bmo, int subtype) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + self->setMistColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + self->setBackColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + self->setAmbientColor(bmo->data[0], bmo->data[1], bmo->data[2]); + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_get_index(BaseMathObject *bmo, int subtype, int index) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + { + const float *color = self->m_mistcolor; + bmo->data[index] = color[index]; + } + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + { + const float *color = self->m_backgroundcolor; + bmo->data[index] = color[index]; + } + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + { + const float *color = self->m_ambientcolor; + bmo->data[index] = color[index]; + } + break; + default: + return -1; + } + return 0; +} + +static int mathutils_world_vector_set_index(BaseMathObject *bmo, int subtype, int index) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>BGE_PROXY_REF(bmo->cb_user); + + if (self == NULL) + return -1; + + float color[4]; + switch (subtype) { + case MATHUTILS_VEC_CB_MIST_COLOR: + copy_v3_v3(color, self->m_mistcolor); + color[index] = bmo->data[index]; + self->setMistColor(color[0], color[1], color[2]); + break; + case MATHUTILS_VEC_CB_BACK_COLOR: + copy_v3_v3(color, self->m_backgroundcolor); + color[index] = bmo->data[index]; + self->setBackColor(color[0], color[1], color[2]); + break; + case MATHUTILS_VEC_CB_AMBIENT_COLOR: + copy_v3_v3(color, self->m_ambientcolor); + color[index] = bmo->data[index]; + self->setAmbientColor(color[0], color[1], color[2]); + break; + default: + return -1; + } + return 0; +} + +static Mathutils_Callback mathutils_world_vector_cb = { + mathutils_world_generic_check, + mathutils_world_vector_get, + mathutils_world_vector_set, + mathutils_world_vector_get_index, + mathutils_world_vector_set_index +}; + +void KX_WorldInfo_Mathutils_Callback_Init() +{ + // register mathutils callbacks, ok to run more than once. + mathutils_world_vector_cb_index = Mathutils_RegisterCallback(&mathutils_world_vector_cb); +} +#endif // USE_MATHUTILS + + +PyObject *KX_WorldInfo::pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + PyObject *retvalue; + + const char* type = attrdef->m_name; + + if (!strcmp(type, "KX_MIST_QUADRATIC")) { + retvalue = PyLong_FromLong(KX_MIST_QUADRATIC); + } + else if (!strcmp(type, "KX_MIST_LINEAR")) { + retvalue = PyLong_FromLong(KX_MIST_LINEAR); + } + else if (!strcmp(type, "KX_MIST_INV_QUADRATIC")) { + retvalue = PyLong_FromLong(KX_MIST_INV_QUADRATIC); + } + else { + /* should never happen */ + PyErr_SetString(PyExc_TypeError, "invalid mist type"); + retvalue = NULL; + } + + return retvalue; +} + +PyObject *KX_WorldInfo::pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_MIST_COLOR); +#else + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + return PyObjectFrom(MT_Vector3(self->m_mistcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setMistColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +PyObject *KX_WorldInfo::pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_BACK_COLOR); +#else + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + return PyObjectFrom(MT_Vector3(self->m_backgroundcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setBackColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +PyObject *KX_WorldInfo::pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ +#ifdef USE_MATHUTILS + return Vector_CreatePyObject_cb( + BGE_PROXY_FROM_REF_BORROW(self_v), 3, + mathutils_world_vector_cb_index, MATHUTILS_VEC_CB_AMBIENT_COLOR); +#else + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + return PyObjectFrom(MT_Vector3(self->m_ambientcolor)); +#endif +} + +int KX_WorldInfo::pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_WorldInfo *self = static_cast<KX_WorldInfo*>(self_v); + + MT_Vector3 color; + if (PyVecTo(value, color)) + { + self->setAmbientColor(color[0], color[1], color[2]); + return PY_SET_ATTR_SUCCESS; + } + return PY_SET_ATTR_FAIL; +} + +#endif /* WITH_PYTHON */ diff --git a/source/gameengine/Ketsji/KX_WorldInfo.h b/source/gameengine/Ketsji/KX_WorldInfo.h index 90b16fe1242..b155faf2837 100644 --- a/source/gameengine/Ketsji/KX_WorldInfo.h +++ b/source/gameengine/Ketsji/KX_WorldInfo.h @@ -33,44 +33,72 @@ #define __KX_WORLDINFO_H__ #include "MT_Scalar.h" +#include "KX_KetsjiEngine.h" +#include "EXP_PyObjectPlus.h" -#ifdef WITH_CXX_GUARDEDALLOC -#include "MEM_guardedalloc.h" +#ifdef USE_MATHUTILS +void KX_WorldInfo_Mathutils_Callback_Init(void); #endif -class MT_CmMatrix4x4; +struct Scene; +struct World; -class KX_WorldInfo +class KX_WorldInfo : public PyObjectPlus { -public: - KX_WorldInfo() {} - virtual ~KX_WorldInfo(); + Py_Header - virtual bool hasWorld() = 0; - virtual bool hasMist() = 0; - virtual float getBackColorRed() = 0; - virtual float getBackColorGreen() = 0; - virtual float getBackColorBlue() = 0; - virtual float getMistStart() = 0; - virtual float getMistDistance() = 0; - virtual float getMistColorRed() = 0; - virtual float getMistColorGreen() = 0; - virtual float getMistColorBlue() = 0; + STR_String m_name; + bool m_do_color_management; + bool m_hasworld; + bool m_hasmist; + short m_misttype; + float m_miststart; + float m_mistdistance; + float m_mistintensity; + float m_mistcolor[3]; + float m_backgroundcolor[3]; + float m_ambientcolor[3]; + float m_con_mistcolor[3]; + float m_con_backgroundcolor[3]; + float m_con_ambientcolor[3]; - virtual float getAmbientColorRed() = 0; - virtual float getAmbientColorGreen() = 0; - virtual float getAmbientColorBlue() = 0; +public: + /** + * Mist options + */ + enum MistType { + KX_MIST_QUADRATIC, + KX_MIST_LINEAR, + KX_MIST_INV_QUADRATIC, + }; - virtual void setBackColor(float, float, float) = 0; - virtual void setMistStart(float) = 0; - virtual void setMistDistance(float) = 0; - virtual void setMistColorRed(float) = 0; - virtual void setMistColorGreen(float) = 0; - virtual void setMistColorBlue(float) = 0; + KX_WorldInfo(Scene *blenderscene, World *blenderworld); + ~KX_WorldInfo(); + const STR_String &GetName(); + bool hasWorld(); + void setUseMist(bool enable); + void setMistType(short type); + void setMistStart(float d); + void setMistDistance(float d); + void setMistIntensity(float intensity); + void setMistColor(float r, float g, float b); + void setBackColor(float r, float g, float b); + const float *getBackColorConverted() const; + void setAmbientColor(float r, float g, float b); + void UpdateBackGround(); + void UpdateWorldSettings(); -#ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_WorldInfo") +#ifdef WITH_PYTHON + /* attributes */ + static PyObject *pyattr_get_mist_typeconst(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_mist_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_back_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject *pyattr_get_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_ambient_color(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + virtual PyObject *py_repr(void); #endif }; diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.cpp b/source/gameengine/Ketsji/KX_WorldIpoController.cpp index 7f83a155643..1123e07ebcc 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.cpp +++ b/source/gameengine/Ketsji/KX_WorldIpoController.cpp @@ -33,6 +33,8 @@ #include "KX_WorldIpoController.h" #include "KX_ScalarInterpolator.h" #include "KX_WorldInfo.h" +#include "KX_PythonInit.h" +#include "KX_Scene.h" #if defined(_WIN64) typedef unsigned __int64 uint_ptr; @@ -42,31 +44,36 @@ typedef unsigned long uint_ptr; bool KX_WorldIpoController::Update(double currentTime) { - if (m_modified) - { + if (m_modified) { T_InterpolatorList::iterator i; for (i = m_interpolators.begin(); !(i == m_interpolators.end()); ++i) { - (*i)->Execute(m_ipotime);//currentTime); + (*i)->Execute(m_ipotime); } - /* TODO, this will crash! */ - KX_WorldInfo *world = NULL; + KX_WorldInfo *world = KX_GetActiveScene()->GetWorldInfo(); if (m_modify_mist_start) { world->setMistStart(m_mist_start); } - if (m_modify_mist_color) { - world->setMistColorRed(m_mist_rgb[0]); - world->setMistColorGreen(m_mist_rgb[1]); - world->setMistColorBlue(m_mist_rgb[2]); - } - if (m_modify_mist_dist) { world->setMistDistance(m_mist_dist); } - m_modified=false; + if (m_modify_mist_intensity) { + world->setMistIntensity(m_mist_intensity); + } + + if (m_modify_horizon_color) { + world->setBackColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]); + world->setMistColor(m_hori_rgb[0], m_hori_rgb[1], m_hori_rgb[2]); + } + + if (m_modify_ambient_color) { + world->setAmbientColor(m_ambi_rgb[0], m_ambi_rgb[1], m_ambi_rgb[2]); + } + + m_modified = false; } return false; } diff --git a/source/gameengine/Ketsji/KX_WorldIpoController.h b/source/gameengine/Ketsji/KX_WorldIpoController.h index 63983b3129b..704f421573e 100644 --- a/source/gameengine/Ketsji/KX_WorldIpoController.h +++ b/source/gameengine/Ketsji/KX_WorldIpoController.h @@ -39,24 +39,30 @@ class KX_WorldIpoController : public SG_Controller { public: - MT_Scalar m_mist_rgb[3]; MT_Scalar m_mist_start; MT_Scalar m_mist_dist; + MT_Scalar m_mist_intensity; + MT_Scalar m_hori_rgb[3]; + MT_Scalar m_ambi_rgb[3]; private: T_InterpolatorList m_interpolators; - unsigned short m_modify_mist_color : 1; unsigned short m_modify_mist_start : 1; unsigned short m_modify_mist_dist : 1; + unsigned short m_modify_mist_intensity : 1; + unsigned short m_modify_horizon_color : 1; + unsigned short m_modify_ambient_color : 1; bool m_modified; double m_ipotime; public: KX_WorldIpoController() : - m_modify_mist_color(false), m_modify_mist_start(false), m_modify_mist_dist(false), + m_modify_mist_intensity(false), + m_modify_horizon_color(false), + m_modify_ambient_color(false), m_modified(true), m_ipotime(0.0) {} @@ -76,14 +82,22 @@ public: m_modify_mist_start = modify; } - void SetModifyMistColor(bool modify) { - m_modify_mist_color = modify; - } - void SetModifyMistDist(bool modify) { m_modify_mist_dist = modify; } + void SetModifyMistIntensity(bool modify) { + m_modify_mist_intensity = modify; + } + + void SetModifyHorizonColor(bool modify) { + m_modify_horizon_color = modify; + } + + void SetModifyAmbientColor(bool modify) { + m_modify_ambient_color = modify; + } + void SetOption( int option, diff --git a/source/gameengine/Ketsji/SConscript b/source/gameengine/Ketsji/SConscript index db5474cf2d7..d8dfd3d9bca 100644 --- a/source/gameengine/Ketsji/SConscript +++ b/source/gameengine/Ketsji/SConscript @@ -30,7 +30,8 @@ import sys Import ('env') sources = env.Glob('*.cpp') -defs = [ 'GLEW_STATIC' ] +defs = [] +defs += env['BF_GL_DEFINITIONS'] incs = [ '.', @@ -38,9 +39,8 @@ incs = [ '#intern/guardedalloc', '#intern/string', '#source/blender', - '#extern/glew/include', - '#intern/audaspace/FX', - '#intern/audaspace/intern', + env['BF_GLEW_INC'], + '#/intern/glew-mx', '#intern/moto/include', '#source/blender/blenfont', '#source/blender/blenkernel', @@ -85,6 +85,11 @@ if env['WITH_BF_PYTHON']: incs += ' ' + env['BF_PYTHON_INC'] defs.append('WITH_PYTHON') +if env['WITH_BF_AUDASPACE']: + defs += env['BF_AUDASPACE_DEF'] + incs += ' ' + env['BF_AUDASPACE_C_INC'] + incs += ' ' + env['BF_AUDASPACE_PY_INC'] + if env['WITH_BF_FFMPEG']: defs.append('WITH_FFMPEG') diff --git a/source/gameengine/Network/CMakeLists.txt b/source/gameengine/Network/CMakeLists.txt index bae00c464f2..019fc3e6032 100644 --- a/source/gameengine/Network/CMakeLists.txt +++ b/source/gameengine/Network/CMakeLists.txt @@ -27,6 +27,7 @@ set(INC . ../../../intern/container ../../../intern/string + ../../blender/blenlib ) set(INC_SYS diff --git a/source/gameengine/Network/SConscript b/source/gameengine/Network/SConscript index 1d78cdba174..feb14e29552 100644 --- a/source/gameengine/Network/SConscript +++ b/source/gameengine/Network/SConscript @@ -31,6 +31,7 @@ sources = env.Glob('*.cpp') #'NG_NetworkMessage.cpp NG_NetworkObject.cpp NG_Netw incs = [ '.', + '../../blender/blenlib', '#intern/container', '#intern/string', '#intern/moto/include', diff --git a/source/gameengine/Physics/Bullet/CMakeLists.txt b/source/gameengine/Physics/Bullet/CMakeLists.txt index fbaa7bb59ba..e52dc1ba052 100644 --- a/source/gameengine/Physics/Bullet/CMakeLists.txt +++ b/source/gameengine/Physics/Bullet/CMakeLists.txt @@ -40,6 +40,7 @@ set(INC ../../../blender/makesdna ../../../../intern/container ../../../../intern/guardedalloc + ../../../../intern/glew-mx ../../../../intern/string ) @@ -66,4 +67,6 @@ if(WITH_BULLET) add_definitions(-DWITH_BULLET) endif() +add_definitions(${GL_DEFINITIONS}) + blender_add_lib(ge_phys_bullet "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp index 72c3b13e301..dbaa925db08 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.cpp @@ -39,7 +39,6 @@ subject to the following restrictions: #include "LinearMath/btConvexHull.h" #include "BulletCollision/Gimpact/btGImpactShape.h" - #include "BulletSoftBody/btSoftRigidDynamicsWorld.h" #include "DNA_mesh_types.h" @@ -65,7 +64,6 @@ extern bool gDisableDeactivation; float gLinearSleepingTreshold; float gAngularSleepingTreshold; - BlenderBulletCharacterController::BlenderBulletCharacterController(btMotionState *motionState, btPairCachingGhostObject *ghost, btConvexShape* shape, float stepHeight) : btKinematicCharacterController(ghost,shape,stepHeight,2), m_motionState(motionState), @@ -118,6 +116,18 @@ const btVector3& BlenderBulletCharacterController::getWalkDirection() return m_walkDirection; } +bool CleanPairCallback::processOverlap(btBroadphasePair &pair) +{ + if ((pair.m_pProxy0 == m_cleanProxy) || (pair.m_pProxy1 == m_cleanProxy)) { + m_pairCache->cleanOverlappingPair(pair, m_dispatcher); + CcdPhysicsController *ctrl0 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy0->m_clientObject)->getUserPointer()); + CcdPhysicsController *ctrl1 = (CcdPhysicsController*)(((btCollisionObject*)pair.m_pProxy1->m_clientObject)->getUserPointer()); + ctrl0->GetCollisionObject()->activate(false); + ctrl1->GetCollisionObject()->activate(false); + } + return false; +} + CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) :m_cci(ci) { @@ -148,11 +158,34 @@ CcdPhysicsController::CcdPhysicsController (const CcdConstructionInfo& ci) m_savedCollisionFilterGroup = 0; m_savedCollisionFilterMask = 0; m_savedMass = 0.0; + m_savedDyna = false; m_suspended = false; CreateRigidbody(); } +void CcdPhysicsController::addCcdConstraintRef(btTypedConstraint* c) +{ + int index = m_ccdConstraintRefs.findLinearSearch(c); + if (index == m_ccdConstraintRefs.size()) + m_ccdConstraintRefs.push_back(c); +} + +void CcdPhysicsController::removeCcdConstraintRef(btTypedConstraint* c) +{ + m_ccdConstraintRefs.remove(c); +} + +btTypedConstraint* CcdPhysicsController::getCcdConstraintRef(int index) +{ + return m_ccdConstraintRefs[index]; +} + +int CcdPhysicsController::getNumCcdConstraintRefs() const +{ + return m_ccdConstraintRefs.size(); +} + btTransform& CcdPhysicsController::GetTransformFromMotionState(PHY_IMotionState* motionState) { static btTransform trans; @@ -207,6 +240,11 @@ btRigidBody* CcdPhysicsController::GetRigidBody() { return btRigidBody::upcast(m_object); } +const btRigidBody* CcdPhysicsController::GetRigidBody() const +{ + return btRigidBody::upcast(m_object); +} + btCollisionObject* CcdPhysicsController::GetCollisionObject() { return m_object; @@ -560,20 +598,13 @@ void CcdPhysicsController::CreateRigidbody() static void DeleteBulletShape(btCollisionShape* shape, bool free) { - if (shape->getShapeType() == TRIANGLE_MESH_SHAPE_PROXYTYPE) - { - // shapes based on meshes use an interface that contains the vertices. - btTriangleMeshShape* meshShape = static_cast<btTriangleMeshShape*>(shape); - btStridingMeshInterface* meshInterface = meshShape->getMeshInterface(); - if (meshInterface) - delete meshInterface; - } - else if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) - { - btGImpactMeshShape* meshShape = static_cast<btGImpactMeshShape*>(shape); - btStridingMeshInterface* meshInterface = meshShape->getMeshInterface(); - if (meshInterface) - delete meshInterface; + if (shape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) { + /* If we use Bullet scaled shape (btScaledBvhTriangleMeshShape) we have to + * free the child of the unscaled shape (btTriangleMeshShape) here. + */ + btTriangleMeshShape *meshShape = ((btScaledBvhTriangleMeshShape *)shape)->getChildShape(); + if (meshShape) + delete meshShape; } if (free) { delete shape; @@ -606,48 +637,41 @@ bool CcdPhysicsController::DeleteControllerShape( ) bool CcdPhysicsController::ReplaceControllerShape(btCollisionShape *newShape) { - - /* Note, deleting the previous collision shape must be done already */ - /* if (m_collisionShape) DeleteControllerShape(); */ + if (m_collisionShape) + DeleteControllerShape(); + + // If newShape is NULL it means to create a new Bullet shape. + if (!newShape) + newShape = m_shapeInfo->CreateBulletShape(m_cci.m_margin, m_cci.m_bGimpact, !m_cci.m_bSoft); m_object->setCollisionShape(newShape); - m_collisionShape= newShape; - m_cci.m_collisionShape= newShape; - - if (GetSoftBody()) { + m_collisionShape = newShape; + m_cci.m_collisionShape = newShape; + + btSoftBody *softBody = GetSoftBody(); + if (softBody) { + btSoftRigidDynamicsWorld *world = GetPhysicsEnvironment()->GetDynamicsWorld(); + // remove the old softBody + world->removeSoftBody(softBody); + // soft body must be recreated - m_cci.m_physicsEnv->RemoveCcdPhysicsController(this); delete m_object; m_object = NULL; // force complete reinitialization m_softbodyMappingDone = false; m_prototypeTransformInitialized = false; m_softBodyTransformInitialized = false; + CreateSoftbody(); assert(m_object); - // reinsert the new body - m_cci.m_physicsEnv->AddCcdPhysicsController(this); - } - - /* Copied from CcdPhysicsEnvironment::addCcdPhysicsController() */ - - /* without this, an object can rest on the old physics mesh - * and not move to account for the physics mesh, even with 'nosleep' */ - btSoftRigidDynamicsWorld* dw= GetPhysicsEnvironment()->GetDynamicsWorld(); - btCollisionObjectArray &obarr= dw->getCollisionObjectArray(); - btCollisionObject *ob; - btBroadphaseProxy* proxy; - - for (int i= 0; i < obarr.size(); i++) { - ob= obarr[i]; - if (ob->getCollisionShape() == newShape) { - proxy = ob->getBroadphaseHandle(); - - if (proxy) - dw->getPairCache()->cleanProxyFromPairs(proxy,dw->getDispatcher()); - } + + btSoftBody *newSoftBody = GetSoftBody(); + // set the user + newSoftBody->setUserPointer(this); + // add the new softbody + world->addSoftBody(newSoftBody); } - + return true; } @@ -673,6 +697,35 @@ CcdPhysicsController::~CcdPhysicsController() } } +void CcdPhysicsController::SimulationTick(float timestep) +{ + btRigidBody *body = GetRigidBody(); + if (!body || body->isStaticObject()) + return; + + // Clamp linear velocity + if (m_cci.m_clamp_vel_max > 0.0f || m_cci.m_clamp_vel_min > 0.0f) { + const btVector3 &linvel = body->getLinearVelocity(); + btScalar len = linvel.length(); + + if (m_cci.m_clamp_vel_max > 0.0f && len > m_cci.m_clamp_vel_max) + body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len)); + else if (m_cci.m_clamp_vel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_vel_min) + body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len)); + } + + // Clamp angular velocity + if (m_cci.m_clamp_angvel_max > 0.0f || m_cci.m_clamp_angvel_min > 0.0f) { + const btVector3 &angvel = body->getAngularVelocity(); + btScalar len = angvel.length(); + + if (m_cci.m_clamp_angvel_max > 0.0f && len > m_cci.m_clamp_angvel_max) + body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_max / len)); + else if (m_cci.m_clamp_angvel_min > 0.0f && !btFuzzyZero(len) && len < m_cci.m_clamp_angvel_min) + body->setAngularVelocity(angvel * (m_cci.m_clamp_angvel_min / len)); + } +} + /** * SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding') @@ -708,19 +761,6 @@ bool CcdPhysicsController::SynchronizeMotionStates(float time) if (body && !body->isStaticObject()) { - - if ((m_cci.m_clamp_vel_max>0.0) || (m_cci.m_clamp_vel_min>0.0)) - { - const btVector3& linvel = body->getLinearVelocity(); - float len= linvel.length(); - - if ((m_cci.m_clamp_vel_max>0.0) && (len > m_cci.m_clamp_vel_max)) - body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_max / len)); - - else if ((m_cci.m_clamp_vel_min>0.0) && btFuzzyZero(len)==0 && (len < m_cci.m_clamp_vel_min)) - body->setLinearVelocity(linvel * (m_cci.m_clamp_vel_min / len)); - } - const btTransform& xform = body->getCenterOfMassTransform(); const btMatrix3x3& worldOri = xform.getBasis(); const btVector3& worldPos = xform.getOrigin(); @@ -780,6 +820,9 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta m_registerCount = 0; m_collisionShape = NULL; + // Clear all old constraints. + m_ccdConstraintRefs.clear(); + // always create a new shape to avoid scaling bug if (m_shapeInfo) { @@ -822,36 +865,6 @@ void CcdPhysicsController::PostProcessReplica(class PHY_IMotionState* motionsta m_cci.m_physicsEnv->AddCcdPhysicsController(this); -/* SM_Object* dynaparent=0; - SumoPhysicsController* sumoparentctrl = (SumoPhysicsController* )parentctrl; - - if (sumoparentctrl) - { - dynaparent = sumoparentctrl->GetSumoObject(); - } - - SM_Object* orgsumoobject = m_sumoObj; - - - m_sumoObj = new SM_Object( - orgsumoobject->getShapeHandle(), - orgsumoobject->getMaterialProps(), - orgsumoobject->getShapeProps(), - dynaparent); - - m_sumoObj->setRigidBody(orgsumoobject->isRigidBody()); - - m_sumoObj->setMargin(orgsumoobject->getMargin()); - m_sumoObj->setPosition(orgsumoobject->getPosition()); - m_sumoObj->setOrientation(orgsumoobject->getOrientation()); - //if it is a dyna, register for a callback - m_sumoObj->registerCallback(*this); - - m_sumoScene->add(* (m_sumoObj)); - */ - - - } void CcdPhysicsController::SetPhysicsEnvironment(class PHY_IPhysicsEnvironment *env) @@ -899,12 +912,6 @@ void CcdPhysicsController::SetCenterOfMassTransform(btTransform& xform) { m_object->setInterpolationWorldTransform(xform); } - if (body) - { - body->setInterpolationLinearVelocity(body->getLinearVelocity()); - body->setInterpolationAngularVelocity(body->getAngularVelocity()); - body->updateInertiaTensor(); - } m_object->setWorldTransform(xform); } } @@ -1054,15 +1061,35 @@ void CcdPhysicsController::ResolveCombinedVelocities(float linvelX,float linvel { } +void CcdPhysicsController::RefreshCollisions() +{ + // the object is in an inactive layer so it's useless to update it and can cause problems + if (!GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this)) + return; + + btSoftRigidDynamicsWorld *dw = GetPhysicsEnvironment()->GetDynamicsWorld(); + btBroadphaseProxy *proxy = m_object->getBroadphaseHandle(); + btDispatcher *dispatcher = dw->getDispatcher(); + btOverlappingPairCache *pairCache = dw->getPairCache(); + + CleanPairCallback cleanPairs(proxy, pairCache, dispatcher); + pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher); + + // Forcibly recreate the physics object + btBroadphaseProxy* handle = m_object->getBroadphaseHandle(); + GetPhysicsEnvironment()->UpdateCcdPhysicsController(this, GetMass(), m_object->getCollisionFlags(), handle->m_collisionFilterGroup, handle->m_collisionFilterMask); +} + void CcdPhysicsController::SuspendDynamics(bool ghost) { btRigidBody *body = GetRigidBody(); - if (body && !m_suspended && !GetConstructionInfo().m_bSensor) + if (body && !m_suspended && !GetConstructionInfo().m_bSensor && GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this)) { btBroadphaseProxy* handle = body->getBroadphaseHandle(); m_savedCollisionFlags = body->getCollisionFlags(); m_savedMass = GetMass(); + m_savedDyna = m_cci.m_bDyna; m_savedCollisionFilterGroup = handle->m_collisionFilterGroup; m_savedCollisionFilterMask = handle->m_collisionFilterMask; m_suspended = true; @@ -1071,13 +1098,14 @@ void CcdPhysicsController::SuspendDynamics(bool ghost) btCollisionObject::CF_STATIC_OBJECT|((ghost)?btCollisionObject::CF_NO_CONTACT_RESPONSE:(m_savedCollisionFlags&btCollisionObject::CF_NO_CONTACT_RESPONSE)), btBroadphaseProxy::StaticFilter, btBroadphaseProxy::AllFilter ^ btBroadphaseProxy::StaticFilter); + m_cci.m_bDyna = false; } } void CcdPhysicsController::RestoreDynamics() { btRigidBody *body = GetRigidBody(); - if (body && m_suspended) + if (body && m_suspended && GetPhysicsEnvironment()->IsActiveCcdPhysicsController(this)) { // before make sure any position change that was done in this logic frame are accounted for SetTransform(); @@ -1087,6 +1115,7 @@ void CcdPhysicsController::RestoreDynamics() m_savedCollisionFilterGroup, m_savedCollisionFilterMask); body->activate(); + m_cci.m_bDyna = m_savedDyna; m_suspended = false; } } @@ -1354,6 +1383,42 @@ void CcdPhysicsController::Jump() void CcdPhysicsController::SetActive(bool active) { } + +float CcdPhysicsController::GetLinearDamping() const +{ + const btRigidBody* body = GetRigidBody(); + if (body) + return body->getLinearDamping(); + return 0; +} + +float CcdPhysicsController::GetAngularDamping() const +{ + const btRigidBody* body = GetRigidBody(); + if (body) + return body->getAngularDamping(); + return 0; +} + +void CcdPhysicsController::SetLinearDamping(float damping) +{ + SetDamping(damping, GetAngularDamping()); +} + +void CcdPhysicsController::SetAngularDamping(float damping) +{ + SetDamping(GetLinearDamping(), damping); +} + +void CcdPhysicsController::SetDamping(float linear, float angular) +{ + btRigidBody* body = GetRigidBody(); + if (!body) return; + + body->setDamping(linear, angular); +} + + // reading out information from physics MT_Vector3 CcdPhysicsController::GetLinearVelocity() { @@ -1479,8 +1544,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child) const btCollisionShape* childShape = childBody->getCollisionShape(); if (!rootShape || !childShape || - rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE || - childShape->getShapeType() == COMPOUND_SHAPE_PROXYTYPE) + rootShape->getShapeType() != COMPOUND_SHAPE_PROXYTYPE) return; btCompoundShape* compoundShape = (btCompoundShape*)rootShape; // compute relative transformation between parent and child @@ -1530,7 +1594,7 @@ void CcdPhysicsController::AddCompoundChild(PHY_IPhysicsController* child) // must update the broadphase cache, GetPhysicsEnvironment()->RefreshCcdPhysicsController(this); // remove the children - GetPhysicsEnvironment()->DisableCcdPhysicsController(childCtrl); + GetPhysicsEnvironment()->RemoveCcdPhysicsController(childCtrl); } /* Reverse function of the above, it will remove a shape from a compound shape @@ -1586,7 +1650,7 @@ void CcdPhysicsController::RemoveCompoundChild(PHY_IPhysicsController* child) // must update the broadphase cache, GetPhysicsEnvironment()->RefreshCcdPhysicsController(this); // reactivate the children - GetPhysicsEnvironment()->EnableCcdPhysicsController(childCtrl); + GetPhysicsEnvironment()->AddCcdPhysicsController(childCtrl); } PHY_IPhysicsController* CcdPhysicsController::GetReplica() @@ -1646,33 +1710,50 @@ PHY_IPhysicsController* CcdPhysicsController::GetReplicaForSensors() * 2) from_gameobj - creates the phys mesh from the DerivedMesh where possible, else the RAS_MeshObject * 3) this - update the phys mesh from DerivedMesh or RAS_MeshObject * - * Most of the logic behind this is in shapeInfo->UpdateMesh(...) + * Most of the logic behind this is in m_shapeInfo->UpdateMesh(...) */ bool CcdPhysicsController::ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject *from_meshobj) { - CcdShapeConstructionInfo *shapeInfo; - - shapeInfo = this->GetShapeInfo(); - - if (shapeInfo->m_shapeType != PHY_SHAPE_MESH/* || spc->GetSoftBody()*/) + if (m_shapeInfo->m_shapeType != PHY_SHAPE_MESH) return false; - this->DeleteControllerShape(); - - if (from_gameobj==NULL && from_meshobj==NULL) - from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)this->GetNewClientInfo()); + if (!from_gameobj && !from_meshobj) + from_gameobj = KX_GameObject::GetClientObject((KX_ClientObjectInfo*)GetNewClientInfo()); /* updates the arrays used for making the new bullet mesh */ - shapeInfo->UpdateMesh(from_gameobj, from_meshobj); + m_shapeInfo->UpdateMesh(from_gameobj, from_meshobj); /* create the new bullet mesh */ - CcdConstructionInfo& cci = this->GetConstructionInfo(); - btCollisionShape* bm= shapeInfo->CreateBulletShape(cci.m_margin, cci.m_bGimpact, !cci.m_bSoft); + GetPhysicsEnvironment()->UpdateCcdPhysicsControllerShape(m_shapeInfo); - this->ReplaceControllerShape(bm); return true; } +void CcdPhysicsController::ReplicateConstraints(KX_GameObject *replica, std::vector<KX_GameObject*> constobj) +{ + if (replica->GetConstraints().size() == 0 || !replica->GetPhysicsController()) + return; + + PHY_IPhysicsEnvironment *physEnv = GetPhysicsEnvironment(); + + vector<bRigidBodyJointConstraint*> constraints = replica->GetConstraints(); + vector<bRigidBodyJointConstraint*>::iterator consit; + + /* Object could have some constraints, iterate over all of theme to ensure that every constraint is recreated. */ + for (consit = constraints.begin(); consit != constraints.end(); ++consit) { + /* Try to find the constraint targets in the list of group objects. */ + bRigidBodyJointConstraint *dat = (*consit); + vector<KX_GameObject*>::iterator memit; + for (memit = constobj.begin(); memit != constobj.end(); ++memit) { + KX_GameObject *member = (*memit); + /* If the group member is the actual target for the constraint. */ + if (dat->tar->id.name + 2 == member->GetName() && member->GetPhysicsController()) + physEnv->SetupObjectConstraints(replica, member, dat); + } + } + +} + /////////////////////////////////////////////////////////// ///A small utility class, DefaultMotionState /// @@ -1754,7 +1835,7 @@ CcdShapeConstructionInfo* CcdShapeConstructionInfo::FindMesh(RAS_MeshObject* mes return NULL; } -bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool polytope) +bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject *meshobj, DerivedMesh *dm, bool polytope) { int numpolys, numverts; @@ -1766,7 +1847,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, bool free_dm = false; // No mesh object or mesh has no polys - if (!meshobj || meshobj->HasColliderPolygon()==false) { + if (!meshobj || !meshobj->HasColliderPolygon()) { m_vertexArray.clear(); m_polygonIndexArray.clear(); m_triFaceArray.clear(); @@ -1789,80 +1870,83 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, /* double lookup */ const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if (index_mf_to_mpoly == NULL) { + if (!index_mf_to_mpoly) { index_mp_to_orig = NULL; } m_shapeType = (polytope) ? PHY_SHAPE_POLYTOPE : PHY_SHAPE_MESH; /* Convert blender geometry into bullet mesh, need these vars for mapping */ - vector<bool> vert_tag_array(numverts, false); - unsigned int tot_bt_verts= 0; + std::vector<bool> vert_tag_array(numverts, false); + unsigned int tot_bt_verts = 0; - if (polytope) - { + if (polytope) { // Tag verts we're using - for (int p2=0; p2<numpolys; p2++) - { - MFace* mf = &mface[p2]; + for (int p2 = 0; p2 < numpolys; p2++) { + MFace *mf = &mface[p2]; const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon* poly = meshobj->GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collision flag set - if (poly->IsCollider()) - { - if (vert_tag_array[mf->v1] == false) {vert_tag_array[mf->v1] = true; tot_bt_verts++;} - if (vert_tag_array[mf->v2] == false) {vert_tag_array[mf->v2] = true; tot_bt_verts++;} - if (vert_tag_array[mf->v3] == false) {vert_tag_array[mf->v3] = true; tot_bt_verts++;} - if (mf->v4 && vert_tag_array[mf->v4] == false) {vert_tag_array[mf->v4] = true; tot_bt_verts++;} + if (poly->IsCollider()) { + if (!vert_tag_array[mf->v1]) { + vert_tag_array[mf->v1] = true; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v2]) { + vert_tag_array[mf->v2] = true; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v3]) { + vert_tag_array[mf->v3] = true; + tot_bt_verts++; + } + if (mf->v4 && !vert_tag_array[mf->v4]) { + vert_tag_array[mf->v4] = true; + tot_bt_verts++; + } } } - + /* Can happen with ngons */ if (!tot_bt_verts) { goto cleanup_empty_mesh; } - m_vertexArray.resize(tot_bt_verts*3); + m_vertexArray.resize(tot_bt_verts * 3); - btScalar *bt= &m_vertexArray[0]; + btScalar *bt = &m_vertexArray[0]; - for (int p2=0; p2<numpolys; p2++) - { - MFace* mf = &mface[p2]; + for (int p2 = 0; p2 < numpolys; p2++) { + MFace *mf = &mface[p2]; const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon* poly= meshobj->GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { - if (vert_tag_array[mf->v1]==true) - { - const float* vtx = mvert[mf->v1].co; + if (poly->IsCollider()) { + if (vert_tag_array[mf->v1]) { + const float *vtx = mvert[mf->v1].co; vert_tag_array[mf->v1] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; } - if (vert_tag_array[mf->v2]==true) - { - const float* vtx = mvert[mf->v2].co; + if (vert_tag_array[mf->v2]) { + const float *vtx = mvert[mf->v2].co; vert_tag_array[mf->v2] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; } - if (vert_tag_array[mf->v3]==true) - { - const float* vtx = mvert[mf->v3].co; + if (vert_tag_array[mf->v3]) { + const float *vtx = mvert[mf->v3].co; vert_tag_array[mf->v3] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; *bt++ = vtx[2]; } - if (mf->v4 && vert_tag_array[mf->v4]==true) - { - const float* vtx = mvert[mf->v4].co; + if (mf->v4 && vert_tag_array[mf->v4]) { + const float *vtx = mvert[mf->v4].co; vert_tag_array[mf->v4] = false; *bt++ = vtx[0]; *bt++ = vtx[1]; @@ -1872,28 +1956,38 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, } } else { - unsigned int tot_bt_tris= 0; - vector<int> vert_remap_array(numverts, 0); - + unsigned int tot_bt_tris = 0; + std::vector<int> vert_remap_array(numverts, 0); + // Tag verts we're using - for (int p2=0; p2<numpolys; p2++) - { - MFace* mf = &mface[p2]; + for (int p2 = 0; p2 < numpolys; p2++) { + MFace *mf = &mface[p2]; const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon* poly= meshobj->GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collision flag set - if (poly->IsCollider()) - { - if (vert_tag_array[mf->v1]==false) - {vert_tag_array[mf->v1] = true;vert_remap_array[mf->v1] = tot_bt_verts;tot_bt_verts++;} - if (vert_tag_array[mf->v2]==false) - {vert_tag_array[mf->v2] = true;vert_remap_array[mf->v2] = tot_bt_verts;tot_bt_verts++;} - if (vert_tag_array[mf->v3]==false) - {vert_tag_array[mf->v3] = true;vert_remap_array[mf->v3] = tot_bt_verts;tot_bt_verts++;} - if (mf->v4 && vert_tag_array[mf->v4]==false) - {vert_tag_array[mf->v4] = true;vert_remap_array[mf->v4] = tot_bt_verts;tot_bt_verts++;} - tot_bt_tris += (mf->v4 ? 2:1); /* a quad or a tri */ + if (poly->IsCollider()) { + if (!vert_tag_array[mf->v1]) { + vert_tag_array[mf->v1] = true; + vert_remap_array[mf->v1] = tot_bt_verts; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v2]) { + vert_tag_array[mf->v2] = true; + vert_remap_array[mf->v2] = tot_bt_verts; + tot_bt_verts++; + } + if (!vert_tag_array[mf->v3]) { + vert_tag_array[mf->v3] = true; + vert_remap_array[mf->v3] = tot_bt_verts; + tot_bt_verts++; + } + if (mf->v4 && !vert_tag_array[mf->v4]) { + vert_tag_array[mf->v4] = true; + vert_remap_array[mf->v4] = tot_bt_verts; + tot_bt_verts++; + } + tot_bt_tris += (mf->v4 ? 2 : 1); /* a quad or a tri */ } } @@ -1902,43 +1996,39 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, goto cleanup_empty_mesh; } - m_vertexArray.resize(tot_bt_verts*3); + m_vertexArray.resize(tot_bt_verts * 3); m_polygonIndexArray.resize(tot_bt_tris); - m_triFaceArray.resize(tot_bt_tris*3); - btScalar *bt= &m_vertexArray[0]; - int *poly_index_pt= &m_polygonIndexArray[0]; - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + btScalar *bt = &m_vertexArray[0]; + int *poly_index_pt = &m_polygonIndexArray[0]; + int *tri_pt = &m_triFaceArray[0]; UVco *uv_pt = NULL; - if (tface) - { - m_triFaceUVcoArray.resize(tot_bt_tris*3); + if (tface) { + m_triFaceUVcoArray.resize(tot_bt_tris * 3); uv_pt = &m_triFaceUVcoArray[0]; - } - else + } + else m_triFaceUVcoArray.clear(); - for (int p2=0; p2<numpolys; p2++) - { - MFace* mf = &mface[p2]; - MTFace* tf = (tface) ? &tface[p2] : NULL; + for (int p2 = 0; p2 < numpolys; p2++) { + MFace *mf = &mface[p2]; + MTFace *tf = (tface) ? &tface[p2] : NULL; const int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, p2) : p2; - RAS_Polygon* poly= meshobj->GetPolygon(origi); + RAS_Polygon *poly = meshobj->GetPolygon(origi); // only add polygons that have the collisionflag set - if (poly->IsCollider()) - { - MVert *v1= &mvert[mf->v1]; - MVert *v2= &mvert[mf->v2]; - MVert *v3= &mvert[mf->v3]; + if (poly->IsCollider()) { + MVert *v1 = &mvert[mf->v1]; + MVert *v2 = &mvert[mf->v2]; + MVert *v3 = &mvert[mf->v3]; // the face indices tri_pt[0] = vert_remap_array[mf->v1]; tri_pt[1] = vert_remap_array[mf->v2]; tri_pt[2] = vert_remap_array[mf->v3]; - tri_pt= tri_pt+3; - if (tf) - { + tri_pt = tri_pt + 3; + if (tf) { uv_pt[0].uv[0] = tf->uv[0][0]; uv_pt[0].uv[1] = tf->uv[0][1]; uv_pt[1].uv[0] = tf->uv[1][0]; @@ -1953,19 +2043,19 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, poly_index_pt++; // the vertex location - if (vert_tag_array[mf->v1]==true) { /* *** v1 *** */ + if (vert_tag_array[mf->v1]) { /* *** v1 *** */ vert_tag_array[mf->v1] = false; *bt++ = v1->co[0]; *bt++ = v1->co[1]; *bt++ = v1->co[2]; } - if (vert_tag_array[mf->v2]==true) { /* *** v2 *** */ + if (vert_tag_array[mf->v2]) { /* *** v2 *** */ vert_tag_array[mf->v2] = false; *bt++ = v2->co[0]; *bt++ = v2->co[1]; *bt++ = v2->co[2]; } - if (vert_tag_array[mf->v3]==true) { /* *** v3 *** */ + if (vert_tag_array[mf->v3]) { /* *** v3 *** */ vert_tag_array[mf->v3] = false; *bt++ = v3->co[0]; *bt++ = v3->co[1]; @@ -1974,12 +2064,12 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, if (mf->v4) { - MVert *v4= &mvert[mf->v4]; + MVert *v4 = &mvert[mf->v4]; tri_pt[0] = vert_remap_array[mf->v1]; tri_pt[1] = vert_remap_array[mf->v3]; tri_pt[2] = vert_remap_array[mf->v4]; - tri_pt= tri_pt+3; + tri_pt = tri_pt + 3; if (tf) { uv_pt[0].uv[0] = tf->uv[0][0]; @@ -1996,7 +2086,7 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, poly_index_pt++; // the vertex location - if (vert_tag_array[mf->v4] == true) { /* *** v4 *** */ + if (vert_tag_array[mf->v4]) { /* *** v4 *** */ vert_tag_array[mf->v4] = false; *bt++ = v4->co[0]; *bt++ = v4->co[1]; @@ -2010,27 +2100,27 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, /* If this ever gets confusing, print out an OBJ file for debugging */ #if 0 printf("# vert count %d\n", m_vertexArray.size()); - for (i=0; i<m_vertexArray.size(); i+=1) { + for (i = 0; i < m_vertexArray.size(); i += 1) { printf("v %.6f %.6f %.6f\n", m_vertexArray[i].x(), m_vertexArray[i].y(), m_vertexArray[i].z()); } printf("# face count %d\n", m_triFaceArray.size()); - for (i=0; i<m_triFaceArray.size(); i+=3) { - printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1); + for (i = 0; i < m_triFaceArray.size(); i += 3) { + printf("f %d %d %d\n", m_triFaceArray[i] + 1, m_triFaceArray[i + 1] + 1, m_triFaceArray[i + 2] + 1); } #endif } #if 0 - if (validpolys==false) + if (validpolys == false) { // should not happen m_shapeType = PHY_SHAPE_NONE; return false; } #endif - + m_meshObject = meshobj; if (free_dm) { dm->release(dm); @@ -2038,10 +2128,9 @@ bool CcdShapeConstructionInfo::SetMesh(RAS_MeshObject* meshobj, DerivedMesh* dm, } // sharing only on static mesh at present, if you change that, you must also change in FindMesh - if (!polytope && !dm) - { + if (!polytope && !dm) { // triangle shape can be shared, store the mesh object in the map - m_meshShapeMap.insert(std::pair<RAS_MeshObject*,CcdShapeConstructionInfo*>(meshobj,this)); + m_meshShapeMap.insert(std::pair<RAS_MeshObject *, CcdShapeConstructionInfo *>(meshobj, this)); } return true; @@ -2064,51 +2153,50 @@ cleanup_empty_mesh: /* Updates the arrays used by CreateBulletShape(), * take care that recalcLocalAabb() runs after CreateBulletShape is called. * */ -bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RAS_MeshObject* meshobj) +bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject *gameobj, class RAS_MeshObject *meshobj) { int numpolys; int numverts; - unsigned int tot_bt_tris= 0; - unsigned int tot_bt_verts= 0; + unsigned int tot_bt_tris = 0; + unsigned int tot_bt_verts = 0; int i, j; int v_orig; /* Use for looping over verts in a face as a try or 2 tris */ - const int quad_verts[7]= {0,1,2, 0,2,3, -1}; - const int tri_verts[4]= {0,1,2, -1}; + const int quad_verts[7] = {0, 1, 2, 0, 2, 3, -1}; + const int tri_verts[4] = {0, 1, 2, -1}; const int *fv_pt; - if (gameobj==NULL && meshobj==NULL) + if (!gameobj && !meshobj) return false; - + if (m_shapeType != PHY_SHAPE_MESH) return false; - RAS_Deformer *deformer= gameobj ? gameobj->GetDeformer():NULL; - DerivedMesh* dm = NULL; + RAS_Deformer *deformer = gameobj ? gameobj->GetDeformer() : NULL; + DerivedMesh *dm = NULL; if (deformer) dm = deformer->GetPhysicsMesh(); - + /* get the mesh from the object if not defined */ - if (meshobj==NULL) { - + if (!meshobj) { /* modifier mesh */ if (dm) - meshobj= deformer->GetRasMesh(); - + meshobj = deformer->GetRasMesh(); + /* game object first mesh */ - if (meshobj==NULL) { + if (!meshobj) { if (gameobj->GetMeshCount() > 0) { - meshobj= gameobj->GetMesh(0); + meshobj = gameobj->GetMesh(0); } } } - - if (dm && deformer->GetRasMesh() == meshobj) - { /* + + if (dm && deformer->GetRasMesh() == meshobj) { + /* * Derived Mesh Update * * */ @@ -2120,41 +2208,38 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA /* double lookup */ const int *index_mf_to_mpoly = (const int *)dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); - if (index_mf_to_mpoly == NULL) { + const int *index_mp_to_orig = (const int *)dm->getPolyDataArray(dm, CD_ORIGINDEX); + if (!index_mf_to_mpoly) { index_mp_to_orig = NULL; } MFace *mf; MVert *mv; - int flen; - - if (CustomData_has_layer(&dm->faceData, CD_MTFACE)) - { + if (CustomData_has_layer(&dm->faceData, CD_MTFACE)) { MTFace *tface = (MTFace *)dm->getTessFaceDataArray(dm, CD_MTFACE); MTFace *tf; - vector<bool> vert_tag_array(numverts, false); - vector<int> vert_remap_array(numverts, 0); + std::vector<bool> vert_tag_array(numverts, false); + std::vector<int> vert_remap_array(numverts, 0); + + for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) { + if (tf->mode & TF_DYNAMIC) { + int flen; - for (mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++) { - if (tf->mode & TF_DYNAMIC) - { if (mf->v4) { - tot_bt_tris+= 2; - flen= 4; - } else { + tot_bt_tris += 2; + flen = 4; + } + else { tot_bt_tris++; - flen= 3; + flen = 3; } - for (j=0; j<flen; j++) - { + for (j = 0; j < flen; j++) { v_orig = (*(&mf->v1 + j)); - if (vert_tag_array[v_orig]==false) - { + if (!vert_tag_array[v_orig]) { vert_tag_array[v_orig] = true; vert_remap_array[v_orig] = tot_bt_verts; tot_bt_verts++; @@ -2163,42 +2248,38 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA } } - m_vertexArray.resize(tot_bt_verts*3); - btScalar *bt= &m_vertexArray[0]; + m_vertexArray.resize(tot_bt_verts * 3); + btScalar *bt = &m_vertexArray[0]; - m_triFaceArray.resize(tot_bt_tris*3); - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + int *tri_pt = &m_triFaceArray[0]; - m_triFaceUVcoArray.resize(tot_bt_tris*3); - UVco *uv_pt= &m_triFaceUVcoArray[0]; + m_triFaceUVcoArray.resize(tot_bt_tris * 3); + UVco *uv_pt = &m_triFaceUVcoArray[0]; m_polygonIndexArray.resize(tot_bt_tris); - int *poly_index_pt= &m_polygonIndexArray[0]; + int *poly_index_pt = &m_polygonIndexArray[0]; - for (mf= mface, tf= tface, i=0; i < numpolys; mf++, tf++, i++) - { - if (tf->mode & TF_DYNAMIC) - { + for (mf = mface, tf = tface, i = 0; i < numpolys; mf++, tf++, i++) { + if (tf->mode & TF_DYNAMIC) { int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; if (mf->v4) { - fv_pt= quad_verts; + fv_pt = quad_verts; *poly_index_pt++ = origi; *poly_index_pt++ = origi; - flen= 4; - } else { - fv_pt= tri_verts; + } + else { + fv_pt = tri_verts; *poly_index_pt++ = origi; - flen= 3; } - for (; *fv_pt > -1; fv_pt++) - { + for (; *fv_pt > -1; fv_pt++) { v_orig = (*(&mf->v1 + (*fv_pt))); if (vert_tag_array[v_orig]) { - mv= mvert + v_orig; + mv = mvert + v_orig; *bt++ = mv->co[0]; *bt++ = mv->co[1]; *bt++ = mv->co[2]; @@ -2216,37 +2297,37 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA else { /* no need for a vertex mapping. simple/fast */ - tot_bt_verts= numverts; + tot_bt_verts = numverts; - for (mf= mface, i=0; i < numpolys; mf++, i++) { - tot_bt_tris += (mf->v4 ? 2:1); + for (mf = mface, i = 0; i < numpolys; mf++, i++) { + tot_bt_tris += (mf->v4 ? 2 : 1); } - m_vertexArray.resize(tot_bt_verts*3); - btScalar *bt= &m_vertexArray[0]; + m_vertexArray.resize(tot_bt_verts * 3); + btScalar *bt = &m_vertexArray[0]; - m_triFaceArray.resize(tot_bt_tris*3); - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + int *tri_pt = &m_triFaceArray[0]; m_polygonIndexArray.resize(tot_bt_tris); - int *poly_index_pt= &m_polygonIndexArray[0]; + int *poly_index_pt = &m_polygonIndexArray[0]; m_triFaceUVcoArray.clear(); - for (mv= mvert, i=0; i < numverts; mv++, i++) { + for (mv = mvert, i = 0; i < numverts; mv++, i++) { *bt++ = mv->co[0]; *bt++ = mv->co[1]; *bt++ = mv->co[2]; } - for (mf= mface, i=0; i < numpolys; mf++, i++) { + for (mf = mface, i = 0; i < numpolys; mf++, i++) { int origi = index_mf_to_mpoly ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i) : i; if (mf->v4) { - fv_pt= quad_verts; + fv_pt = quad_verts; *poly_index_pt++ = origi; *poly_index_pt++ = origi; } else { - fv_pt= tri_verts; + fv_pt = tri_verts; *poly_index_pt++ = origi; } @@ -2255,51 +2336,46 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA } } } - else { /* - * RAS Mesh Update - * - * */ - + else { /* + * RAS Mesh Update + * + * */ /* Note!, gameobj can be NULL here */ /* transverts are only used for deformed RAS_Meshes, the RAS_TexVert data * is too hard to get at, see below for details */ - float (*transverts)[3] = NULL; - int transverts_tot= 0; /* with deformed meshes - should always be greater then the max orginal index, or we get crashes */ + float(*transverts)[3] = NULL; + int transverts_tot = 0; /* with deformed meshes - should always be greater than the max orginal index, or we get crashes */ if (deformer) { /* map locations from the deformed array * * Could call deformer->Update(); but rely on redraw updating. * */ - transverts= deformer->GetTransVerts(&transverts_tot); + transverts = deformer->GetTransVerts(&transverts_tot); } // Tag verts we're using - numpolys= meshobj->NumPolygons(); - numverts= meshobj->m_sharedvertex_map.size(); + numpolys = meshobj->NumPolygons(); + numverts = meshobj->m_sharedvertex_map.size(); const float *xyz; - vector<bool> vert_tag_array(numverts, false); - vector<int> vert_remap_array(numverts, 0); + std::vector<bool> vert_tag_array(numverts, false); + std::vector<int> vert_remap_array(numverts, 0); - for (int p=0; p<numpolys; p++) - { - RAS_Polygon* poly= meshobj->GetPolygon(p); - if (poly->IsCollider()) - { - for (i=0; i < poly->VertexCount(); i++) - { - v_orig= poly->GetVertex(i)->getOrigIndex(); - if (vert_tag_array[v_orig]==false) - { + for (int p = 0; p < numpolys; p++) { + RAS_Polygon *poly = meshobj->GetPolygon(p); + if (poly->IsCollider()) { + for (i = 0; i < poly->VertexCount(); i++) { + v_orig = poly->GetVertex(i)->getOrigIndex(); + if (!vert_tag_array[v_orig]) { vert_tag_array[v_orig] = true; vert_remap_array[v_orig] = tot_bt_verts; tot_bt_verts++; } } - tot_bt_tris += (poly->VertexCount()==4 ? 2:1); + tot_bt_tris += (poly->VertexCount() == 4 ? 2 : 1); } } @@ -2307,32 +2383,29 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA if (tot_bt_tris == 0 || tot_bt_verts == 0) return false; - m_vertexArray.resize(tot_bt_verts*3); - btScalar *bt= &m_vertexArray[0]; + m_vertexArray.resize(tot_bt_verts * 3); + btScalar *bt = &m_vertexArray[0]; - m_triFaceArray.resize(tot_bt_tris*3); - int *tri_pt= &m_triFaceArray[0]; + m_triFaceArray.resize(tot_bt_tris * 3); + int *tri_pt = &m_triFaceArray[0]; /* cant be used for anything useful in this case, since we don't rely on the original mesh * will just be an array like pythons range(tot_bt_tris) */ m_polygonIndexArray.resize(tot_bt_tris); - for (int p=0; p<numpolys; p++) - { - RAS_Polygon* poly= meshobj->GetPolygon(p); + int p = 0; + int t = 0; + while (t < tot_bt_tris) { + RAS_Polygon *poly = meshobj->GetPolygon(p); - if (poly->IsCollider()) - { + if (poly->IsCollider()) { /* quad or tri loop */ - fv_pt= (poly->VertexCount()==3 ? tri_verts:quad_verts); - - for (; *fv_pt > -1; fv_pt++) - { - v_orig= poly->GetVertex(*fv_pt)->getOrigIndex(); + fv_pt = (poly->VertexCount() == 3 ? tri_verts : quad_verts); - if (vert_tag_array[v_orig]) - { + for (; *fv_pt > -1; fv_pt++) { + v_orig = poly->GetVertex(*fv_pt)->getOrigIndex(); + if (vert_tag_array[v_orig]) { if (transverts) { /* deformed mesh, using RAS_TexVert locations would be too troublesome * because they are use the gameob as a hash in the material slot */ @@ -2342,55 +2415,60 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA } else { /* static mesh python may have modified */ - xyz= meshobj->GetVertexLocation( v_orig ); + xyz = meshobj->GetVertexLocation(v_orig); *bt++ = xyz[0]; *bt++ = xyz[1]; *bt++ = xyz[2]; } - vert_tag_array[v_orig] = false; } - *tri_pt++ = vert_remap_array[v_orig]; } } - - m_polygonIndexArray[p] = p; /* dumb counting */ + // first triangle + m_polygonIndexArray[t] = p; + + // if the poly is a quad we transform it in two triangles + if (poly->VertexCount() == 4) { + t++; + // second triangle + m_polygonIndexArray[t] = p; + } + t++; + p++; } } - + #if 0 /* needs #include <cstdio> */ printf("# vert count %d\n", m_vertexArray.size()); - for (int i=0; i<m_vertexArray.size(); i+=3) { - printf("v %.6f %.6f %.6f\n", m_vertexArray[i], m_vertexArray[i+1], m_vertexArray[i+2]); + for (int i = 0; i < m_vertexArray.size(); i += 3) { + printf("v %.6f %.6f %.6f\n", m_vertexArray[i], m_vertexArray[i + 1], m_vertexArray[i + 2]); } printf("# face count %d\n", m_triFaceArray.size()); - for (int i=0; i<m_triFaceArray.size(); i+=3) { - printf("f %d %d %d\n", m_triFaceArray[i]+1, m_triFaceArray[i+1]+1, m_triFaceArray[i+2]+1); + for (int i = 0; i < m_triFaceArray.size(); i += 3) { + printf("f %d %d %d\n", m_triFaceArray[i] + 1, m_triFaceArray[i + 1] + 1, m_triFaceArray[i + 2] + 1); } #endif - /* force recreation of the m_unscaledShape. + /* force recreation of the m_triangleIndexVertexArray. * If this has multiple users we cant delete */ - if (m_unscaledShape) { - // don't free now so it can re-allocate under the same location and not break pointers. - // DeleteBulletShape(m_unscaledShape); - m_forceReInstance= true; + if (m_triangleIndexVertexArray) { + m_forceReInstance = true; } // Make sure to also replace the mesh in the shape map! Otherwise we leave dangling references when we free. // Note, this whole business could cause issues with shared meshes. If we update one mesh, do we replace // them all? - std::map<RAS_MeshObject*,CcdShapeConstructionInfo*>::iterator mit = m_meshShapeMap.find(m_meshObject); + std::map<RAS_MeshObject *, CcdShapeConstructionInfo *>::iterator mit = m_meshShapeMap.find(m_meshObject); if (mit != m_meshShapeMap.end()) { m_meshShapeMap.erase(mit); m_meshShapeMap[meshobj] = this; } - m_meshObject= meshobj; - + m_meshObject = meshobj; + if (dm) { dm->needsFree = 1; dm->release(dm); @@ -2398,8 +2476,6 @@ bool CcdShapeConstructionInfo::UpdateMesh(class KX_GameObject* gameobj, class RA return true; } - - bool CcdShapeConstructionInfo::SetProxy(CcdShapeConstructionInfo* shapeInfo) { if (shapeInfo == NULL) @@ -2462,74 +2538,61 @@ btCollisionShape* CcdShapeConstructionInfo::CreateBulletShape(btScalar margin, b // 9 multiplications/additions and one function call for each triangle that passes the mid phase filtering // One possible optimization is to use directly the btBvhTriangleMeshShape when the scale is 1,1,1 // and btScaledBvhTriangleMeshShape otherwise. - if (useGimpact) - { - btTriangleIndexVertexArray* indexVertexArrays = new btTriangleIndexVertexArray( + if (useGimpact) { + if (!m_triangleIndexVertexArray || m_forceReInstance) { + if (m_triangleIndexVertexArray) + delete m_triangleIndexVertexArray; + + m_triangleIndexVertexArray = new btTriangleIndexVertexArray( m_polygonIndexArray.size(), - &m_triFaceArray[0], - 3*sizeof(int), - m_vertexArray.size()/3, + m_triFaceArray.data(), + 3 * sizeof(int), + m_vertexArray.size() / 3, &m_vertexArray[0], - 3*sizeof(btScalar) - ); - btGImpactMeshShape* gimpactShape = new btGImpactMeshShape(indexVertexArrays); - gimpactShape->setMargin(margin); - gimpactShape->updateBound(); - collisionShape = gimpactShape; - - - } else - { - if (!m_unscaledShape || m_forceReInstance) - { - - btTriangleIndexVertexArray* indexVertexArrays = 0; + 3 * sizeof(btScalar)); + m_forceReInstance = false; + } + btGImpactMeshShape *gimpactShape = new btGImpactMeshShape(m_triangleIndexVertexArray); + gimpactShape->setMargin(margin); + gimpactShape->updateBound(); + collisionShape = gimpactShape; + } + else { + if (!m_triangleIndexVertexArray || m_forceReInstance) { ///enable welding, only for the objects that need it (such as soft bodies) - if (0.f != m_weldingThreshold1) - { - btTriangleMesh* collisionMeshData = new btTriangleMesh(true,false); + if (0.0f != m_weldingThreshold1) { + btTriangleMesh *collisionMeshData = new btTriangleMesh(true, false); collisionMeshData->m_weldingThreshold = m_weldingThreshold1; - bool removeDuplicateVertices=true; + bool removeDuplicateVertices = true; // m_vertexArray not in multiple of 3 anymore, use m_triFaceArray - for (unsigned int i=0; i<m_triFaceArray.size(); i+=3) { - btScalar *bt = &m_vertexArray[3*m_triFaceArray[i]]; + for (unsigned int i = 0; i < m_triFaceArray.size(); i += 3) { + btScalar *bt = &m_vertexArray[3 * m_triFaceArray[i]]; btVector3 v1(bt[0], bt[1], bt[2]); - bt = &m_vertexArray[3*m_triFaceArray[i+1]]; + bt = &m_vertexArray[3 * m_triFaceArray[i + 1]]; btVector3 v2(bt[0], bt[1], bt[2]); - bt = &m_vertexArray[3*m_triFaceArray[i+2]]; + bt = &m_vertexArray[3 * m_triFaceArray[i + 2]]; btVector3 v3(bt[0], bt[1], bt[2]); collisionMeshData->addTriangle(v1, v2, v3, removeDuplicateVertices); } - indexVertexArrays = collisionMeshData; - - } else - { - indexVertexArrays = new btTriangleIndexVertexArray( + m_triangleIndexVertexArray = collisionMeshData; + } + else { + m_triangleIndexVertexArray = new btTriangleIndexVertexArray( m_polygonIndexArray.size(), - &m_triFaceArray[0], - 3*sizeof(int), - m_vertexArray.size()/3, + m_triFaceArray.data(), + 3 * sizeof(int), + m_vertexArray.size() / 3, &m_vertexArray[0], - 3*sizeof(btScalar)); + 3 * sizeof(btScalar)); } - - // this shape will be shared and not deleted until shapeInfo is deleted - - // for UpdateMesh, reuse the last memory location so instancing wont crash. - if (m_unscaledShape) { - DeleteBulletShape(m_unscaledShape, false); - m_unscaledShape->~btBvhTriangleMeshShape(); - m_unscaledShape = new(m_unscaledShape) btBvhTriangleMeshShape( indexVertexArrays, true, useBvh ); - } else { - m_unscaledShape = new btBvhTriangleMeshShape( indexVertexArrays, true, useBvh ); - } - m_forceReInstance= false; - } else if (useBvh && m_unscaledShape->getOptimizedBvh() == NULL) { - // the existing unscaledShape was not build with Bvh, do it now - m_unscaledShape->buildOptimizedBvh(); + + m_forceReInstance = false; } - collisionShape = new btScaledBvhTriangleMeshShape(m_unscaledShape, btVector3(1.0f,1.0f,1.0f)); + + btBvhTriangleMeshShape *unscaledShape = new btBvhTriangleMeshShape(m_triangleIndexVertexArray, true, useBvh); + unscaledShape->setMargin(margin); + collisionShape = new btScaledBvhTriangleMeshShape(unscaledShape, btVector3(1.0f, 1.0f, 1.0f)); collisionShape->setMargin(margin); } break; @@ -2571,10 +2634,9 @@ CcdShapeConstructionInfo::~CcdShapeConstructionInfo() (*sit)->Release(); } m_shapeArray.clear(); - if (m_unscaledShape) - { - DeleteBulletShape(m_unscaledShape, true); - } + + if (m_triangleIndexVertexArray) + delete m_triangleIndexVertexArray; m_vertexArray.clear(); if (m_shapeType == PHY_SHAPE_MESH && m_meshObject != NULL) { diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsController.h b/source/gameengine/Physics/Bullet/CcdPhysicsController.h index 4d0d96e07c6..c49ae8d20e1 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsController.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsController.h @@ -79,7 +79,7 @@ public: m_userData(NULL), m_refCount(1), m_meshObject(NULL), - m_unscaledShape(NULL), + m_triangleIndexVertexArray(NULL), m_forceReInstance(false), m_weldingThreshold1(0.f), m_shapeProxy(NULL) @@ -110,10 +110,11 @@ public: void AddShape(CcdShapeConstructionInfo* shapeInfo); - btTriangleMeshShape* GetMeshShape(void) + btStridingMeshInterface *GetMeshInterface() { - return (m_unscaledShape); + return m_triangleIndexVertexArray; } + CcdShapeConstructionInfo* GetChildShape(int i) { if (i < 0 || i >= (int)m_shapeArray.size()) @@ -195,8 +196,8 @@ protected: int m_refCount; // this class is shared between replicas // keep track of users so that we can release it RAS_MeshObject* m_meshObject; // Keep a pointer to the original mesh - btBvhTriangleMeshShape* m_unscaledShape;// holds the shared unscale BVH mesh shape, - // the actual shape is of type btScaledBvhTriangleMeshShape + // The list of vertexes and indexes for the triangle mesh, shared between Bullet shape. + btTriangleIndexVertexArray *m_triangleIndexVertexArray; std::vector<CcdShapeConstructionInfo*> m_shapeArray; // for compound shapes bool m_forceReInstance; //use gimpact for concave dynamic/moving collision detection float m_weldingThreshold1; //welding closeby vertices together can improve softbody stability etc. @@ -235,6 +236,8 @@ struct CcdConstructionInfo m_mass(0.f), m_clamp_vel_min(-1.f), m_clamp_vel_max(-1.f), + m_clamp_angvel_min(0.0f), + m_clamp_angvel_max(0.0f), m_restitution(0.1f), m_friction(0.5f), m_linearDamping(0.1f), @@ -301,6 +304,8 @@ struct CcdConstructionInfo btScalar m_mass; btScalar m_clamp_vel_min; btScalar m_clamp_vel_max; + btScalar m_clamp_angvel_min; // Minimum angular velocity, in radians/sec. + btScalar m_clamp_angvel_max; // Maximum angular velocity, in radians/sec. btScalar m_restitution; btScalar m_friction; btScalar m_linearDamping; @@ -447,6 +452,23 @@ public: #endif }; +class CleanPairCallback : public btOverlapCallback +{ + btBroadphaseProxy *m_cleanProxy; + btOverlappingPairCache *m_pairCache; + btDispatcher *m_dispatcher; + +public: + CleanPairCallback(btBroadphaseProxy *cleanProxy, btOverlappingPairCache *pairCache, btDispatcher *dispatcher) + :m_cleanProxy(cleanProxy), + m_pairCache(pairCache), + m_dispatcher(dispatcher) + { + } + + virtual bool processOverlap(btBroadphasePair &pair); +}; + ///CcdPhysicsController is a physics object that supports continuous collision detection and time of impact based physics resolution. class CcdPhysicsController : public PHY_IPhysicsController { @@ -461,6 +483,7 @@ protected: class CcdShapeConstructionInfo* m_shapeInfo; btCollisionShape* m_bulletChildShape; + btAlignedObjectArray<btTypedConstraint*> m_ccdConstraintRefs; // keep track of typed constraints referencing this rigid body friend class CcdPhysicsEnvironment; // needed when updating the controller //some book keeping for replication @@ -480,6 +503,7 @@ protected: short m_savedCollisionFilterGroup; short m_savedCollisionFilterMask; MT_Scalar m_savedMass; + bool m_savedDyna; bool m_suspended; @@ -496,6 +520,16 @@ protected: return (--m_registerCount == 0) ? true : false; } + bool Registered() const + { + return (m_registerCount != 0); + } + + void addCcdConstraintRef(btTypedConstraint* c); + void removeCcdConstraintRef(btTypedConstraint* c); + btTypedConstraint* getCcdConstraintRef(int index); + int getNumCcdConstraintRefs() const; + void SetWorldOrientation(const btMatrix3x3& mat); void ForceWorldTransform(const btMatrix3x3& mat, const btVector3& pos); @@ -506,7 +540,15 @@ protected: CcdPhysicsController (const CcdConstructionInfo& ci); + /** + * Delete the current Bullet shape used in the rigid body. + */ bool DeleteControllerShape(); + + /** + * Delete the old Bullet shape and set the new Bullet shape : newShape + * \param newShape The new Bullet shape to set, if is NULL we create a new Bullet shape + */ bool ReplaceControllerShape(btCollisionShape *newShape); virtual ~CcdPhysicsController(); @@ -522,6 +564,7 @@ protected: btRigidBody* GetRigidBody(); + const btRigidBody* GetRigidBody() const; btCollisionObject* GetCollisionObject(); btSoftBody* GetSoftBody(); btKinematicCharacterController* GetCharacterController(); @@ -540,6 +583,13 @@ protected: * SynchronizeMotionStates ynchronizes dynas, kinematic and deformable entities (and do 'late binding') */ virtual bool SynchronizeMotionStates(float time); + + /** + * Called for every physics simulation step. Use this method for + * things like limiting linear and angular velocity. + */ + void SimulationTick(float timestep); + /** * WriteMotionStateToDynamics ynchronizes dynas, kinematic and deformable entities (and do 'late binding') */ @@ -573,6 +623,12 @@ protected: virtual void Jump(); virtual void SetActive(bool active); + virtual float GetLinearDamping() const; + virtual float GetAngularDamping() const; + virtual void SetLinearDamping(float damping); + virtual void SetAngularDamping(float damping); + virtual void SetDamping(float linear, float angular); + // reading out information from physics virtual MT_Vector3 GetLinearVelocity(); virtual MT_Vector3 GetAngularVelocity(); @@ -584,7 +640,7 @@ protected: virtual void ResolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ); - + virtual void RefreshCollisions(); virtual void SuspendDynamics(bool ghost); virtual void RestoreDynamics(); @@ -612,8 +668,12 @@ protected: virtual void CalcXform() {} virtual void SetMargin(float margin) { - if (m_collisionShape) - m_collisionShape->setMargin(btScalar(margin)); + if (m_collisionShape) { + m_collisionShape->setMargin(margin); + // if the shape use a unscaled shape we have also to set the correct margin in it + if (m_collisionShape->getShapeType() == SCALED_TRIANGLE_MESH_SHAPE_PROXYTYPE) + ((btScaledBvhTriangleMeshShape *)m_collisionShape)->getChildShape()->setMargin(margin); + } } virtual float GetMargin() const { @@ -652,6 +712,23 @@ protected: return m_cci.m_clamp_vel_max; } + virtual void SetAngularVelocityMin(float val) + { + m_cci.m_clamp_angvel_min = val; + } + virtual float GetAngularVelocityMin() const + { + return m_cci.m_clamp_angvel_min; + } + virtual void SetAngularVelocityMax(float val) + { + m_cci.m_clamp_angvel_max = val; + } + virtual float GetAngularVelocityMax() const + { + return m_cci.m_clamp_angvel_max; + } + bool WantsSleeping(); void UpdateDeactivation(float timeStep); @@ -698,6 +775,11 @@ protected: return GetConstructionInfo().m_bDyna; } + virtual bool IsSuspended() const + { + return m_suspended; + } + virtual bool IsCompound() { return GetConstructionInfo().m_shapeInfo->m_shapeType == PHY_SHAPE_COMPOUND; @@ -705,6 +787,9 @@ protected: virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj); + /* Method to replicate rigid body joint contraints for group instances. */ + virtual void ReplicateConstraints(KX_GameObject *gameobj, std::vector<KX_GameObject*> constobj); + #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:CcdPhysicsController") #endif diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp index e17d4402556..eec579158cc 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.cpp @@ -174,26 +174,27 @@ public: virtual void GetWheelPosition(int wheelIndex,float& posX,float& posY,float& posZ) const { - btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex); - posX = trans.getOrigin().x(); - posY = trans.getOrigin().y(); - posZ = trans.getOrigin().z(); + if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels())) + { + btVector3 origin = m_vehicle->getWheelTransformWS(wheelIndex).getOrigin(); + + posX = origin.x(); + posY = origin.y(); + posZ = origin.z(); + } } + virtual void GetWheelOrientationQuaternion(int wheelIndex,float& quatX,float& quatY,float& quatZ,float& quatW) const { - btTransform trans = m_vehicle->getWheelTransformWS(wheelIndex); - btQuaternion quat = trans.getRotation(); - btMatrix3x3 orn2(quat); - - quatX = trans.getRotation().x(); - quatY = trans.getRotation().y(); - quatZ = trans.getRotation().z(); - quatW = trans.getRotation()[3]; - - - //printf("test"); - + if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels())) + { + btQuaternion quat = m_vehicle->getWheelTransformWS(wheelIndex).getRotation(); + quatX = quat.x(); + quatY = quat.y(); + quatZ = quat.z(); + quatW = quat.w(); + } } virtual float GetWheelRotation(int wheelIndex) const @@ -205,8 +206,8 @@ public: btWheelInfo& info = m_vehicle->getWheelInfo(wheelIndex); rotation = info.m_rotation; } - return rotation; + return rotation; } @@ -223,12 +224,16 @@ public: virtual void SetSteeringValue(float steering,int wheelIndex) { - m_vehicle->setSteeringValue(steering,wheelIndex); + if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels())) { + m_vehicle->setSteeringValue(steering,wheelIndex); + } } virtual void ApplyEngineForce(float force,int wheelIndex) { - m_vehicle->applyEngineForce(force,wheelIndex); + if ((wheelIndex>=0) && (wheelIndex< m_vehicle->getNumWheels())) { + m_vehicle->applyEngineForce(force,wheelIndex); + } } virtual void ApplyBraking(float braking,int wheelIndex) @@ -405,6 +410,10 @@ m_ccdMode(0), m_solverType(-1), m_profileTimings(0), m_enableSatCollisionDetection(false), +m_deactivationTime(2.0f), +m_linearDeactivationThreshold(0.8f), +m_angularDeactivationThreshold(1.0f), +m_contactBreakingThreshold(0.02f), m_solver(NULL), m_ownPairCache(NULL), m_filterCallback(NULL), @@ -447,6 +456,7 @@ m_scalingPropagated(false) SetSolverType(1);//issues with quickstep and memory allocations // m_dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); m_dynamicsWorld = new btSoftRigidDynamicsWorld(dispatcher,m_broadphase,m_solver,m_collisionConfiguration); + m_dynamicsWorld->setInternalTickCallback(&CcdPhysicsEnvironment::StaticSimulationSubtickCallback, this); //m_dynamicsWorld->getSolverInfo().m_linearSlop = 0.01f; //m_dynamicsWorld->getSolverInfo().m_solverMode= SOLVER_USE_WARMSTARTING + SOLVER_USE_2_FRICTION_DIRECTIONS + SOLVER_RANDMIZE_ORDER + SOLVER_USE_FRICTION_WARMSTARTING; @@ -456,15 +466,20 @@ m_scalingPropagated(false) void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) { + // the controller is already added we do nothing + if (!m_controllers.insert(ctrl).second) { + return; + } + btRigidBody* body = ctrl->GetRigidBody(); btCollisionObject* obj = ctrl->GetCollisionObject(); //this m_userPointer is just used for triggers, see CallbackTriggers obj->setUserPointer(ctrl); - if (body) - body->setGravity( m_gravity ); - - m_controllers.insert(ctrl); + if (body) { + body->setGravity(m_gravity); + body->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold); + } if (body) { @@ -496,20 +511,49 @@ void CcdPhysicsEnvironment::AddCcdPhysicsController(CcdPhysicsController* ctrl) assert(obj->getBroadphaseHandle()); } - +void CcdPhysicsEnvironment::RemoveConstraint(btTypedConstraint *con) +{ + btRigidBody rbA = con->getRigidBodyA(); + btRigidBody rbB = con->getRigidBodyB(); + rbA.activate(); + rbB.activate(); + m_dynamicsWorld->removeConstraint(con); + + if (rbA.getUserPointer()) { + ((CcdPhysicsController *)rbA.getUserPointer())->removeCcdConstraintRef(con); + } + + if (rbB.getUserPointer()) { + ((CcdPhysicsController *)rbB.getUserPointer())->removeCcdConstraintRef(con); + } + + /* Since we remove the constraint in the onwer and the target, we can delete it, + * KX_ConstraintWrapper keep the constraint id not the pointer, so no problems. */ + delete con; +} bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctrl) { + // if the physics controller is already removed we do nothing + if (!m_controllers.erase(ctrl)) { + return false; + } + //also remove constraint btRigidBody* body = ctrl->GetRigidBody(); if (body) { - for (int i=body->getNumConstraintRefs()-1;i>=0;i--) + btBroadphaseProxy *proxy = ctrl->GetCollisionObject()->getBroadphaseHandle(); + btDispatcher *dispatcher = m_dynamicsWorld->getDispatcher(); + btOverlappingPairCache *pairCache = m_dynamicsWorld->getPairCache(); + + CleanPairCallback cleanPairs(proxy, pairCache, dispatcher); + pairCache->processAllOverlappingPairs(&cleanPairs, dispatcher); + + for (int i = ctrl->getNumCcdConstraintRefs() - 1; i >= 0; i--) { - btTypedConstraint* con = body->getConstraintRef(i); - m_dynamicsWorld->removeConstraint(con); - body->removeConstraintRef(con); - //delete con; //might be kept by python KX_ConstraintWrapper + btTypedConstraint* con = ctrl->getCcdConstraintRef(i); + RemoveConstraint(con); } m_dynamicsWorld->removeRigidBody(ctrl->GetRigidBody()); @@ -524,7 +568,7 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr } if (vehicle_constraint > 0) - RemoveConstraint(vehicle_constraint); + RemoveConstraintById(vehicle_constraint); } else { //if a softbody @@ -541,13 +585,8 @@ bool CcdPhysicsEnvironment::RemoveCcdPhysicsController(CcdPhysicsController* ctr } } } - if (ctrl->m_registerCount != 0) - printf("Warning: removing controller with non-zero m_registerCount: %d\n", ctrl->m_registerCount); - //remove it from the triggers - m_triggerControllers.erase(ctrl); - - return (m_controllers.erase(ctrl) != 0); + return true; } void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask) @@ -555,6 +594,7 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr // this function is used when the collisionning group of a controller is changed // remove and add the collistioning object btRigidBody* body = ctrl->GetRigidBody(); + btSoftBody *softBody = ctrl->GetSoftBody(); btCollisionObject* obj = ctrl->GetCollisionObject(); if (obj) { @@ -568,6 +608,9 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr body->setMassProps(newMass, inertia); m_dynamicsWorld->addRigidBody(body, newCollisionGroup, newCollisionMask); } + else if (softBody) { + m_dynamicsWorld->addSoftBody(softBody); + } else { m_dynamicsWorld->addCollisionObject(obj, newCollisionGroup, newCollisionMask); } @@ -579,43 +622,6 @@ void CcdPhysicsEnvironment::UpdateCcdPhysicsController(CcdPhysicsController* ctr ctrl->m_cci.m_collisionFlags = newCollisionFlags; } -void CcdPhysicsEnvironment::EnableCcdPhysicsController(CcdPhysicsController* ctrl) -{ - if (m_controllers.insert(ctrl).second) - { - btCollisionObject* obj = ctrl->GetCollisionObject(); - obj->setUserPointer(ctrl); - // update the position of the object from the user - if (ctrl->GetMotionState()) - { - btTransform xform = CcdPhysicsController::GetTransformFromMotionState(ctrl->GetMotionState()); - ctrl->SetCenterOfMassTransform(xform); - } - m_dynamicsWorld->addCollisionObject(obj, - ctrl->GetCollisionFilterGroup(), ctrl->GetCollisionFilterMask()); - } -} - -void CcdPhysicsEnvironment::DisableCcdPhysicsController(CcdPhysicsController* ctrl) -{ - if (m_controllers.erase(ctrl)) - { - btRigidBody* body = ctrl->GetRigidBody(); - if (body) - { - m_dynamicsWorld->removeRigidBody(body); - } else - { - if (ctrl->GetSoftBody()) - { - } else - { - m_dynamicsWorld->removeCollisionObject(ctrl->GetCollisionObject()); - } - } - } -} - void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ctrl) { btCollisionObject* obj = ctrl->GetCollisionObject(); @@ -629,6 +635,11 @@ void CcdPhysicsEnvironment::RefreshCcdPhysicsController(CcdPhysicsController* ct } } +bool CcdPhysicsEnvironment::IsActiveCcdPhysicsController(CcdPhysicsController *ctrl) +{ + return (m_controllers.find(ctrl) != m_controllers.end()); +} + void CcdPhysicsEnvironment::AddCcdGraphicController(CcdGraphicController* ctrl) { if (m_cullingTree && !ctrl->GetBroadphaseHandle()) @@ -664,6 +675,19 @@ void CcdPhysicsEnvironment::RemoveCcdGraphicController(CcdGraphicController* ctr } } +void CcdPhysicsEnvironment::UpdateCcdPhysicsControllerShape(CcdShapeConstructionInfo *shapeInfo) +{ + for (std::set<CcdPhysicsController *>::iterator it = m_controllers.begin(); it != m_controllers.end(); ++it) { + CcdPhysicsController *ctrl = *it; + + if (ctrl->GetShapeInfo() != shapeInfo) + continue; + + ctrl->ReplaceControllerShape(NULL); + RefreshCcdPhysicsController(ctrl); + } +} + void CcdPhysicsEnvironment::BeginFrame() { @@ -675,11 +699,31 @@ void CcdPhysicsEnvironment::DebugDrawWorld() m_dynamicsWorld->debugDrawWorld(); } +void CcdPhysicsEnvironment::StaticSimulationSubtickCallback(btDynamicsWorld *world, btScalar timeStep) +{ + // Get the pointer to the CcdPhysicsEnvironment associated with this Bullet world. + CcdPhysicsEnvironment *this_ = static_cast<CcdPhysicsEnvironment*>(world->getWorldUserInfo()); + this_->SimulationSubtickCallback(timeStep); +} + +void CcdPhysicsEnvironment::SimulationSubtickCallback(btScalar timeStep) +{ + std::set<CcdPhysicsController*>::iterator it; + + for (it = m_controllers.begin(); it != m_controllers.end(); it++) { + (*it)->SimulationTick(timeStep); + } +} + bool CcdPhysicsEnvironment::ProceedDeltaTime(double curTime,float timeStep,float interval) { std::set<CcdPhysicsController*>::iterator it; int i; + // Update Bullet global variables. + gDeactivationTime = m_deactivationTime; + gContactBreakingThreshold = m_contactBreakingThreshold; + for (it=m_controllers.begin(); it!=m_controllers.end(); it++) { (*it)->SynchronizeMotionStates(timeStep); @@ -745,8 +789,8 @@ public: void CcdPhysicsEnvironment::ProcessFhSprings(double curTime,float interval) { std::set<CcdPhysicsController*>::iterator it; - // dynamic of Fh spring is based on a timestep of 1/60 - int numIter = (int)(interval*60.0001f); + // Add epsilon to the tick rate for numerical stability + int numIter = (int)(interval*(KX_KetsjiEngine::GetTicRate() + 0.001f)); for (it=m_controllers.begin(); it!=m_controllers.end(); it++) { @@ -899,21 +943,32 @@ void CcdPhysicsEnvironment::SetNumIterations(int numIter) } void CcdPhysicsEnvironment::SetDeactivationTime(float dTime) { - gDeactivationTime = dTime; + m_deactivationTime = dTime; } void CcdPhysicsEnvironment::SetDeactivationLinearTreshold(float linTresh) { - gLinearSleepingTreshold = linTresh; + m_linearDeactivationThreshold = linTresh; + + // Update from all controllers. + for (std::set<CcdPhysicsController*>::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) { + if ((*it)->GetRigidBody()) + (*it)->GetRigidBody()->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold); + } } void CcdPhysicsEnvironment::SetDeactivationAngularTreshold(float angTresh) { - gAngularSleepingTreshold = angTresh; + m_angularDeactivationThreshold = angTresh; + + // Update from all controllers. + for (std::set<CcdPhysicsController*>::iterator it = m_controllers.begin(); it != m_controllers.end(); it++) { + if ((*it)->GetRigidBody()) + (*it)->GetRigidBody()->setSleepingThresholds(m_linearDeactivationThreshold, m_angularDeactivationThreshold); + } } void CcdPhysicsEnvironment::SetContactBreakingTreshold(float contactBreakingTreshold) { - gContactBreakingThreshold = contactBreakingTreshold; - + m_contactBreakingThreshold = contactBreakingTreshold; } @@ -1059,11 +1114,12 @@ int CcdPhysicsEnvironment::CreateUniversalD6Constraint( return 0; } - - -void CcdPhysicsEnvironment::RemoveConstraint(int constraintId) +void CcdPhysicsEnvironment::RemoveConstraintById(int constraintId) { - + // For soft body constraints + if (constraintId == 0) + return; + int i; int numConstraints = m_dynamicsWorld->getNumConstraints(); for (i=0;i<numConstraints;i++) @@ -1071,9 +1127,7 @@ void CcdPhysicsEnvironment::RemoveConstraint(int constraintId) btTypedConstraint* constraint = m_dynamicsWorld->getConstraint(i); if (constraint->getUserConstraintId() == constraintId) { - constraint->getRigidBodyA().activate(); - constraint->getRigidBodyB().activate(); - m_dynamicsWorld->removeConstraint(constraint); + RemoveConstraint(constraint); break; } } @@ -1149,17 +1203,8 @@ static bool GetHitTriangle(btCollisionShape* shape, CcdShapeConstructionInfo* sh int indexstride; int numfaces; PHY_ScalarType indicestype; - btStridingMeshInterface* meshInterface = NULL; - btTriangleMeshShape* triangleShape = shapeInfo->GetMeshShape(); + btStridingMeshInterface* meshInterface = shapeInfo->GetMeshInterface(); - if (triangleShape) - meshInterface = triangleShape->getMeshInterface(); - else - { - // other possibility is gImpact - if (shape->getShapeType() == GIMPACT_SHAPE_PROXYTYPE) - meshInterface = (static_cast<btGImpactMeshShape*>(shape))->getMeshInterface(); - } if (!meshInterface) return false; @@ -2016,6 +2061,9 @@ CcdPhysicsEnvironment::~CcdPhysicsEnvironment() float CcdPhysicsEnvironment::GetConstraintParam(int constraintId,int param) { btTypedConstraint* typedConstraint = GetConstraintById(constraintId); + if (!typedConstraint) + return 0.0f; + switch (typedConstraint->getUserConstraintType()) { case PHY_GENERIC_6DOF_CONSTRAINT: @@ -2055,6 +2103,9 @@ float CcdPhysicsEnvironment::GetConstraintParam(int constraintId,int param) void CcdPhysicsEnvironment::SetConstraintParam(int constraintId,int param,float value0,float value1) { btTypedConstraint* typedConstraint = GetConstraintById(constraintId); + if (!typedConstraint) + return; + switch (typedConstraint->getUserConstraintType()) { case PHY_GENERIC_6DOF_CONSTRAINT: @@ -2164,6 +2215,9 @@ void CcdPhysicsEnvironment::SetConstraintParam(int constraintId,int param,float btTypedConstraint* CcdPhysicsEnvironment::GetConstraintById(int constraintId) { + // For soft body constraints + if (constraintId == 0) + return NULL; int numConstraints = m_dynamicsWorld->getNumConstraints(); int i; @@ -2181,30 +2235,20 @@ btTypedConstraint* CcdPhysicsEnvironment::GetConstraintById(int constraintId) void CcdPhysicsEnvironment::AddSensor(PHY_IPhysicsController* ctrl) { - CcdPhysicsController* ctrl1 = (CcdPhysicsController* )ctrl; - // addSensor() is a "light" function for bullet because it is used - // dynamically when the sensor is activated. Use enableCcdPhysicsController() instead - //if (m_controllers.insert(ctrl1).second) - //{ - // addCcdPhysicsController(ctrl1); - //} - EnableCcdPhysicsController(ctrl1); + AddCcdPhysicsController(ctrl1); } bool CcdPhysicsEnvironment::RemoveCollisionCallback(PHY_IPhysicsController* ctrl) { CcdPhysicsController* ccdCtrl = (CcdPhysicsController*)ctrl; - if (!ccdCtrl->Unregister()) - return false; - m_triggerControllers.erase(ccdCtrl); - return true; + return ccdCtrl->Unregister(); } void CcdPhysicsEnvironment::RemoveSensor(PHY_IPhysicsController* ctrl) { - DisableCcdPhysicsController((CcdPhysicsController*)ctrl); + RemoveCcdPhysicsController((CcdPhysicsController*)ctrl); } void CcdPhysicsEnvironment::AddTouchCallback(int response_class, PHY_ResponseCallback callback, void *user) @@ -2242,73 +2286,83 @@ void CcdPhysicsEnvironment::AddTouchCallback(int response_class, PHY_ResponseCal bool CcdPhysicsEnvironment::RequestCollisionCallback(PHY_IPhysicsController* ctrl) { CcdPhysicsController* ccdCtrl = static_cast<CcdPhysicsController*>(ctrl); - - if (!ccdCtrl->Register()) - return false; - m_triggerControllers.insert(ccdCtrl); - return true; + return ccdCtrl->Register(); } void CcdPhysicsEnvironment::CallbackTriggers() { - 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 - btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher(); - int numManifolds = dispatcher->getNumManifolds(); - for (int i=0;i<numManifolds;i++) - { - btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); - int numContacts = manifold->getNumContacts(); - if (numContacts) - { - const btRigidBody* rb0 = static_cast<const btRigidBody*>(manifold->getBody0()); - const btRigidBody* rb1 = static_cast<const btRigidBody*>(manifold->getBody1()); - if (m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints)) - { - for (int j=0;j<numContacts;j++) - { - btVector3 color(1,0,0); - const btManifoldPoint& cp = manifold->getContactPoint(j); - if (m_debugDrawer) - m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.getDistance(),cp.getLifeTime(),color); - } - } - const btRigidBody* obj0 = rb0; - const btRigidBody* obj1 = rb1; + bool draw_contact_points = m_debugDrawer && (m_debugDrawer->getDebugMode() & btIDebugDraw::DBG_DrawContactPoints); - //m_internalOwner is set in 'addPhysicsController' - CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(obj0->getUserPointer()); - CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(obj1->getUserPointer()); + if (!m_triggerCallbacks[PHY_OBJECT_RESPONSE] && !draw_contact_points) + return; - std::set<CcdPhysicsController*>::const_iterator i = m_triggerControllers.find(ctrl0); - if (i == m_triggerControllers.end()) - { - i = m_triggerControllers.find(ctrl1); - } + //walk over all overlapping pairs, and if one of the involved bodies is registered for trigger callback, perform callback + btDispatcher* dispatcher = m_dynamicsWorld->getDispatcher(); + int numManifolds = dispatcher->getNumManifolds(); + for (int i=0;i<numManifolds;i++) + { + bool colliding_ctrl0 = true; + btPersistentManifold* manifold = dispatcher->getManifoldByIndexInternal(i); + int numContacts = manifold->getNumContacts(); + if (!numContacts) continue; - if (!(i == m_triggerControllers.end())) - { - m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE], - ctrl0,ctrl1,0); - } - // Bullet does not refresh the manifold contact point for object without contact response - // may need to remove this when a newer Bullet version is integrated - if (!dispatcher->needsResponse(rb0, rb1)) - { - // Refresh algorithm fails sometimes when there is penetration - // (usuall the case with ghost and sensor objects) - // Let's just clear the manifold, in any case, it is recomputed on each frame. - manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); - } + const btRigidBody* rb0 = static_cast<const btRigidBody*>(manifold->getBody0()); + const btRigidBody* rb1 = static_cast<const btRigidBody*>(manifold->getBody1()); + if (draw_contact_points) + { + for (int j=0;j<numContacts;j++) + { + btVector3 color(1,1,0); + const btManifoldPoint& cp = manifold->getContactPoint(j); + m_debugDrawer->drawContactPoint(cp.m_positionWorldOnB, + cp.m_normalWorldOnB, + cp.getDistance(), + cp.getLifeTime(), + color); } } + //m_internalOwner is set in 'addPhysicsController' + CcdPhysicsController* ctrl0 = static_cast<CcdPhysicsController*>(rb0->getUserPointer()); + CcdPhysicsController* ctrl1 = static_cast<CcdPhysicsController*>(rb1->getUserPointer()); + bool usecallback = false; + // Test if one of the controller is registered and use collision callback. + if (ctrl0->Registered()) + usecallback = true; + else if (ctrl1->Registered()) { + colliding_ctrl0 = false; + usecallback = true; + } - } + if (usecallback) { + static PHY_CollData coll_data; + const btManifoldPoint &cp = manifold->getContactPoint(0); + + /* Make sure that "point1" is always on the object we report on, and + * "point2" on the other object. Also ensure the normal is oriented + * correctly. */ + btVector3 point1 = colliding_ctrl0 ? cp.m_positionWorldOnA : cp.m_positionWorldOnB; + btVector3 point2 = colliding_ctrl0 ? cp.m_positionWorldOnB : cp.m_positionWorldOnA; + btVector3 normal = colliding_ctrl0 ? -cp.m_normalWorldOnB : cp.m_normalWorldOnB; + coll_data.m_point1 = MT_Vector3(point1.m_floats); + coll_data.m_point2 = MT_Vector3(point2.m_floats); + coll_data.m_normal = MT_Vector3(normal.m_floats); + m_triggerCallbacks[PHY_OBJECT_RESPONSE](m_triggerCallbacksUserPtrs[PHY_OBJECT_RESPONSE], + ctrl0, ctrl1, &coll_data); + } + // Bullet does not refresh the manifold contact point for object without contact response + // may need to remove this when a newer Bullet version is integrated + if (!dispatcher->needsResponse(rb0, rb1)) + { + // Refresh algorithm fails sometimes when there is penetration + // (usuall the case with ghost and sensor objects) + // Let's just clear the manifold, in any case, it is recomputed on each frame. + manifold->clearManifold(); //refreshContactPoints(rb0->getCenterOfMassTransform(),rb1->getCenterOfMassTransform()); + } + } } // This call back is called before a pair is added in the cache @@ -2624,7 +2678,6 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl if (!rb0) return 0; - btVector3 pivotInB = rb1 ? rb1->getCenterOfMassTransform().inverse()(rb0->getCenterOfMassTransform()(pivotInA)) : rb0->getCenterOfMassTransform() * pivotInA; btVector3 axisInA(axisX,axisY,axisZ); @@ -2636,6 +2689,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl { case PHY_POINT2POINT_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; btPoint2PointConstraint* p2p = 0; @@ -2649,6 +2704,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl pivotInA); } + c0->addCcdConstraintRef(p2p); + c1->addCcdConstraintRef(p2p); m_dynamicsWorld->addConstraint(p2p,disableCollisionBetweenLinkedBodies); // m_constraints.push_back(p2p); @@ -2662,6 +2719,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl case PHY_GENERIC_6DOF_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; + btGeneric6DofConstraint* genericConstraint = 0; if (rb1) @@ -2715,10 +2775,12 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl *rb0,s_fixedObject2, frameInA,frameInB,useReferenceFrameA); } - + if (genericConstraint) { //m_constraints.push_back(genericConstraint); + c0->addCcdConstraintRef(genericConstraint); + c1->addCcdConstraintRef(genericConstraint); m_dynamicsWorld->addConstraint(genericConstraint,disableCollisionBetweenLinkedBodies); genericConstraint->setUserConstraintId(gConstraintUid++); genericConstraint->setUserConstraintType(type); @@ -2730,6 +2792,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl } case PHY_CONE_TWIST_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; + btConeTwistConstraint* coneTwistContraint = 0; @@ -2781,10 +2846,12 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl *rb0,s_fixedObject2, frameInA,frameInB); } - + if (coneTwistContraint) { //m_constraints.push_back(genericConstraint); + c0->addCcdConstraintRef(coneTwistContraint); + c1->addCcdConstraintRef(coneTwistContraint); m_dynamicsWorld->addConstraint(coneTwistContraint,disableCollisionBetweenLinkedBodies); coneTwistContraint->setUserConstraintId(gConstraintUid++); coneTwistContraint->setUserConstraintType(type); @@ -2802,6 +2869,9 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl case PHY_LINEHINGE_CONSTRAINT: { + // If either of the controllers is missing, we can't do anything. + if (!c0 || !c1) return 0; + btHingeConstraint* hinge = 0; if (rb1) @@ -2858,6 +2928,8 @@ int CcdPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ctrl hinge->setAngularOnly(angularOnly); //m_constraints.push_back(hinge); + c0->addCcdConstraintRef(hinge); + c1->addCcdConstraintRef(hinge); m_dynamicsWorld->addConstraint(hinge,disableCollisionBetweenLinkedBodies); hinge->setUserConstraintId(gConstraintUid++); hinge->setUserConstraintType(type); @@ -2926,6 +2998,10 @@ PHY_IPhysicsController* CcdPhysicsEnvironment::CreateConeController(float conera float CcdPhysicsEnvironment::getAppliedImpulse(int constraintid) { + // For soft body constraints + if (constraintid == 0) + return 0.0f; + int i; int numConstraints = m_dynamicsWorld->getNumConstraints(); for (i=0;i<numConstraints;i++) @@ -2999,7 +3075,8 @@ struct BlenderDebugDraw : public btIDebugDraw virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,float distance,int lifeTime,const btVector3& color) { - //not yet + drawLine(PointOnB, PointOnB + normalOnB, color); + drawSphere(PointOnB, 0.1, color); } virtual void setDebugMode(int debugMode) @@ -3036,7 +3113,7 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject { Object* blenderobject = gameobj->GetBlenderObject(); - bool isbulletdyna = (blenderobject->gameflag & OB_DYNAMIC) != 0;; + bool isbulletdyna = (blenderobject->gameflag & OB_DYNAMIC) != 0; bool isbulletsensor = (blenderobject->gameflag & OB_SENSOR) != 0; bool isbulletchar = (blenderobject->gameflag & OB_CHARACTER) != 0; bool isbulletsoftbody = (blenderobject->gameflag & OB_SOFT_BODY) != 0; @@ -3056,9 +3133,7 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject { KX_BlenderSceneConverter *converter = (KX_BlenderSceneConverter*)KX_GetActiveEngine()->GetSceneConverter(); parent = converter->FindGameObject(blenderparent); - isbulletdyna = false; isbulletsoftbody = false; - shapeprops->m_mass = 0.f; } if (!isbulletdyna) @@ -3082,6 +3157,8 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject ci.m_mass = isbulletdyna ? shapeprops->m_mass : 0.f; ci.m_clamp_vel_min = shapeprops->m_clamp_vel_min; ci.m_clamp_vel_max = shapeprops->m_clamp_vel_max; + ci.m_clamp_angvel_min = shapeprops->m_clamp_angvel_min; + ci.m_clamp_angvel_max = shapeprops->m_clamp_angvel_max; ci.m_stepHeight = isbulletchar ? shapeprops->m_step_height : 0.f; ci.m_jumpSpeed = isbulletchar ? shapeprops->m_jump_speed : 0.f; ci.m_fallSpeed = isbulletchar ? shapeprops->m_fall_speed : 0.f; @@ -3339,46 +3416,50 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject //take relative transform into account! CcdPhysicsController* parentCtrl = (CcdPhysicsController*)parent->GetPhysicsController(); assert(parentCtrl); - CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo(); - btRigidBody* rigidbody = parentCtrl->GetRigidBody(); - btCollisionShape* colShape = rigidbody->getCollisionShape(); - assert(colShape->isCompound()); - btCompoundShape* compoundShape = (btCompoundShape*)colShape; - - // compute the local transform from parent, this may include several node in the chain - SG_Node* gameNode = gameobj->GetSGNode(); - SG_Node* parentNode = 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.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 - if (!rigidbody->isStaticOrKinematicObject()) - { - btVector3 localInertia; - float mass = 1.f/rigidbody->getInvMass(); - compoundShape->calculateLocalInertia(mass,localInertia); - rigidbody->setMassProps(mass,localInertia); + + // only makes compound shape if parent has a physics controller (i.e not an empty, etc) + if (parentCtrl) { + CcdShapeConstructionInfo* parentShapeInfo = parentCtrl->GetShapeInfo(); + btRigidBody* rigidbody = parentCtrl->GetRigidBody(); + btCollisionShape* colShape = rigidbody->getCollisionShape(); + assert(colShape->isCompound()); + btCompoundShape* compoundShape = (btCompoundShape*)colShape; + + // compute the local transform from parent, this may include several node in the chain + SG_Node* gameNode = gameobj->GetSGNode(); + SG_Node* parentNode = 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.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 + if (!rigidbody->isStaticOrKinematicObject()) + { + btVector3 localInertia; + float mass = 1.f/rigidbody->getInvMass(); + compoundShape->calculateLocalInertia(mass,localInertia); + rigidbody->setMassProps(mass,localInertia); + } + shapeInfo->Release(); + // delete motionstate as it's not used + delete motionstate; } - shapeInfo->Release(); - // delete motionstate as it's not used - delete motionstate; return; } @@ -3482,20 +3563,23 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject if (isbulletdyna) gameobj->SetRecordAnimation(true); + physicscontroller->SetNewClientInfo(gameobj->getClientInfo()); + // don't add automatically sensor object, they are added when a collision sensor is registered if (!isbulletsensor && (blenderobject->lay & activeLayerBitInfo) != 0) { this->AddCcdPhysicsController( physicscontroller); } - physicscontroller->SetNewClientInfo(gameobj->getClientInfo()); + { btRigidBody* rbody = physicscontroller->GetRigidBody(); if (rbody) { + rbody->setLinearFactor(ci.m_linearFactor); + if (isbulletrigidbody) { - rbody->setLinearFactor(ci.m_linearFactor); rbody->setAngularFactor(ci.m_angularFactor); } @@ -3506,6 +3590,9 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject } } + if (parent) + physicscontroller->SuspendDynamics(false); + CcdPhysicsController* parentCtrl = parent ? (CcdPhysicsController*)parent->GetPhysicsController() : 0; physicscontroller->SetParentCtrl(parentCtrl); @@ -3556,3 +3643,79 @@ void CcdPhysicsEnvironment::ConvertObject(KX_GameObject *gameobj, RAS_MeshObject } #endif } + + +void CcdPhysicsEnvironment::SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest, + bRigidBodyJointConstraint *dat) +{ + PHY_IPhysicsController *phy_src = obj_src->GetPhysicsController(); + PHY_IPhysicsController *phy_dest = obj_dest->GetPhysicsController(); + PHY_IPhysicsEnvironment *phys_env = obj_src->GetScene()->GetPhysicsEnvironment(); + + /* We need to pass a full constraint frame, not just axis. */ + MT_Matrix3x3 localCFrame(MT_Vector3(dat->axX,dat->axY,dat->axZ)); + MT_Vector3 axis0 = localCFrame.getColumn(0); + MT_Vector3 axis1 = localCFrame.getColumn(1); + MT_Vector3 axis2 = localCFrame.getColumn(2); + MT_Vector3 scale = obj_src->NodeGetWorldScaling(); + + /* Apply not only the pivot and axis values, but also take scale into count + * this is not working well, if only one or two axis are scaled, but works ok on + * homogeneous scaling. */ + int constraintId = phys_env->CreateConstraint( + phy_src, phy_dest, (PHY_ConstraintType)dat->type, + (float)(dat->pivX * scale.x()), (float)(dat->pivY * scale.y()), (float)(dat->pivZ * scale.z()), + (float)(axis0.x() * scale.x()), (float)(axis0.y() * scale.y()), (float)(axis0.z() * scale.z()), + (float)(axis1.x() * scale.x()), (float)(axis1.y() * scale.y()), (float)(axis1.z() * scale.z()), + (float)(axis2.x() * scale.x()), (float)(axis2.y() * scale.y()), (float)(axis2.z() * scale.z()), + dat->flag); + + /* PHY_POINT2POINT_CONSTRAINT = 1, + * PHY_LINEHINGE_CONSTRAINT = 2, + * PHY_ANGULAR_CONSTRAINT = 3, + * PHY_CONE_TWIST_CONSTRAINT = 4, + * PHY_VEHICLE_CONSTRAINT = 11, + * PHY_GENERIC_6DOF_CONSTRAINT = 12 */ + + if (!constraintId) + return; + + int dof = 0; + int dof_max = 0; + int dofbit = 0; + + switch (dat->type) { + /* Set all the limits for generic 6DOF constraint. */ + case PHY_GENERIC_6DOF_CONSTRAINT: + dof_max = 6; + dofbit = 1; + break; + /* Set XYZ angular limits for cone twist constraint. */ + case PHY_CONE_TWIST_CONSTRAINT: + dof = 3; + dof_max = 6; + dofbit = 1 << 3; + break; + /* Set only X angular limits for line hinge and angular constraint. */ + case PHY_LINEHINGE_CONSTRAINT: + case PHY_ANGULAR_CONSTRAINT: + dof = 3; + dof_max = 4; + dofbit = 1 << 3; + break; + default: + break; + } + + for (; dof < dof_max; dof++) { + if (dat->flag & dofbit) { + phys_env->SetConstraintParam(constraintId, dof, dat->minLimit[dof], dat->maxLimit[dof]); + } + else { + /* minLimit > maxLimit means free (no limit) for this degree of freedom. */ + phys_env->SetConstraintParam(constraintId, dof, 1.0f, -1.0f); + } + dofbit <<= 1; + } + +} diff --git a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h index ff8a3f4f9f9..86f663959f1 100644 --- a/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h +++ b/source/gameengine/Physics/Bullet/CcdPhysicsEnvironment.h @@ -22,6 +22,8 @@ subject to the following restrictions: #define __CCDPHYSICSENVIRONMENT_H__ #include "PHY_IPhysicsEnvironment.h" +#include "KX_KetsjiEngine.h" + #include <vector> #include <set> #include <map> @@ -50,8 +52,10 @@ class btBroadphaseInterface; struct btDbvtBroadphase; class btOverlappingPairCache; class btIDebugDraw; +class btDynamicsWorld; class PHY_IVehicle; class CcdOverlapFilterCallBack; +class CcdShapeConstructionInfo; /** CcdPhysicsEnvironment is an experimental mainloop for physics simulation using optional continuous collision detection. * Physics Environment takes care of stepping the simulation and is a container for physics entities. @@ -63,6 +67,9 @@ class CcdPhysicsEnvironment : public PHY_IPhysicsEnvironment friend class CcdOverlapFilterCallBack; btVector3 m_gravity; + // Removes the constraint and his references from the owner and the target. + void RemoveConstraint(btTypedConstraint *con); + protected: btIDebugDraw* m_debugDrawer; @@ -84,6 +91,11 @@ protected: int m_profileTimings; bool m_enableSatCollisionDetection; + float m_deactivationTime; + float m_linearDeactivationThreshold; + float m_angularDeactivationThreshold; + float m_contactBreakingThreshold; + void ProcessFhSprings(double curTime,float timeStep); public: @@ -126,13 +138,20 @@ protected: /// Perform an integration step of duration 'timeStep'. virtual bool ProceedDeltaTime(double curTime,float timeStep,float interval); + /** + * Called by Bullet for every physical simulation (sub)tick. + * Our constructor registers this callback to Bullet, which stores a pointer to 'this' in + * the btDynamicsWorld::getWorldUserInfo() pointer. + */ + static void StaticSimulationSubtickCallback(btDynamicsWorld *world, btScalar timeStep); + void SimulationSubtickCallback(btScalar timeStep); + virtual void DebugDrawWorld(); // virtual bool proceedDeltaTimeOneStep(float timeStep); virtual void SetFixedTimeStep(bool useFixedTimeStep,float fixedTimeStep) { - //based on DEFAULT_PHYSICS_TIC_RATE of 60 hertz - SetNumTimeSubSteps((int)(fixedTimeStep / 60.f)); + SetNumTimeSubSteps((int)(fixedTimeStep / KX_KetsjiEngine::GetTicRate())); } //returns 0.f if no fixed timestep is used @@ -169,7 +188,7 @@ protected: virtual float GetConstraintParam(int constraintId,int param); - virtual void RemoveConstraint(int constraintid); + virtual void RemoveConstraintById(int constraintid); virtual float getAppliedImpulse(int constraintid); @@ -220,16 +239,22 @@ protected: void UpdateCcdPhysicsController(CcdPhysicsController* ctrl, btScalar newMass, int newCollisionFlags, short int newCollisionGroup, short int newCollisionMask); - void DisableCcdPhysicsController(CcdPhysicsController* ctrl); - - void EnableCcdPhysicsController(CcdPhysicsController* ctrl); - void RefreshCcdPhysicsController(CcdPhysicsController* ctrl); + bool IsActiveCcdPhysicsController(CcdPhysicsController *ctrl); + void AddCcdGraphicController(CcdGraphicController* ctrl); void RemoveCcdGraphicController(CcdGraphicController* ctrl); + /** + * Update all physics controllers shape which use the same shape construction info. + * Call RecreateControllerShape on controllers which use the same shape + * construction info that argument shapeInfo. + * You need to call this function when the shape construction info changed. + */ + void UpdateCcdPhysicsControllerShape(CcdShapeConstructionInfo *shapeInfo); + btBroadphaseInterface* GetBroadphase(); btDbvtBroadphase* GetCullingTree() { return m_cullingTree; } @@ -274,12 +299,15 @@ protected: bool isCompoundChild, bool hasCompoundChildren); + /* Set the rigid body joints constraints values for converted objects and replicated group instances. */ + virtual void SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest, + bRigidBodyJointConstraint *dat); + protected: std::set<CcdPhysicsController*> m_controllers; - std::set<CcdPhysicsController*> m_triggerControllers; PHY_ResponseCallback m_triggerCallbacks[PHY_NUM_RESPONSE]; void* m_triggerCallbacksUserPtrs[PHY_NUM_RESPONSE]; diff --git a/source/gameengine/Physics/Bullet/SConscript b/source/gameengine/Physics/Bullet/SConscript index 2a8249b9558..5c5b1fe6ea6 100644 --- a/source/gameengine/Physics/Bullet/SConscript +++ b/source/gameengine/Physics/Bullet/SConscript @@ -34,7 +34,8 @@ incs = [ '#intern/container', '#intern/guardedalloc', '#intern/string', - '#extern/glew/include', + env['BF_GLEW_INC'], + '#/intern/glew-mx', '#intern/moto/include', '#source/blender/blenkernel', '#source/blender/blenlib', @@ -52,6 +53,7 @@ incs = ' '.join(incs) incs += ' ' + env['BF_BULLET_INC'] defs = [] +defs += env['BF_GL_DEFINITIONS'] if env['WITH_BF_PYTHON']: incs += ' ' + env['BF_PYTHON_INC'] diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp index 979128370ee..99db56bfcef 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp @@ -106,7 +106,7 @@ int DummyPhysicsEnvironment::CreateConstraint(class PHY_IPhysicsController* ct } -void DummyPhysicsEnvironment::RemoveConstraint(int constraintid) +void DummyPhysicsEnvironment::RemoveConstraintById(int constraintid) { if (constraintid) { diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index cfc8841cac2..929345d7161 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -68,7 +68,7 @@ public: float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0 ); - virtual void RemoveConstraint(int constraintid); + virtual void RemoveConstraintById(int constraintid); //complex constraint for vehicles virtual PHY_IVehicle* GetVehicleConstraint(int constraintId) diff --git a/source/gameengine/Physics/common/PHY_IPhysicsController.h b/source/gameengine/Physics/common/PHY_IPhysicsController.h index f9975484fa7..62b163536dd 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsController.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsController.h @@ -32,6 +32,7 @@ #ifndef __PHY_IPHYSICSCONTROLLER_H__ #define __PHY_IPHYSICSCONTROLLER_H__ +#include <vector> #include "PHY_IController.h" class PHY_IMotionState; @@ -89,6 +90,13 @@ class PHY_IPhysicsController : public PHY_IController virtual void SetLinearVelocity(const MT_Vector3& lin_vel,bool local)=0; virtual void ResolveCombinedVelocities(float linvelX,float linvelY,float linvelZ,float angVelX,float angVelY,float angVelZ) = 0; + virtual float GetLinearDamping() const=0; + virtual float GetAngularDamping() const=0; + virtual void SetLinearDamping(float damping)=0; + virtual void SetAngularDamping(float damping)=0; + virtual void SetDamping(float linear, float angular)=0; + + virtual void RefreshCollisions() = 0; virtual void SuspendDynamics(bool ghost=false)=0; virtual void RestoreDynamics()=0; @@ -117,6 +125,11 @@ class PHY_IPhysicsController : public PHY_IController virtual float GetLinVelocityMax() const=0; virtual void SetLinVelocityMax(float val) = 0; + virtual void SetAngularVelocityMin(float val) = 0; + virtual float GetAngularVelocityMin() const = 0; + virtual void SetAngularVelocityMax(float val) = 0; + virtual float GetAngularVelocityMax() const = 0; + MT_Vector3 GetWorldPosition(MT_Vector3& localpos); // Shape control @@ -126,9 +139,12 @@ class PHY_IPhysicsController : public PHY_IController virtual bool IsDynamic() = 0; virtual bool IsCompound() = 0; + virtual bool IsSuspended() const = 0; virtual bool ReinstancePhysicsShape(KX_GameObject *from_gameobj, RAS_MeshObject* from_meshobj) = 0; + /* Method to replicate rigid body joint contraints for group instances. */ + virtual void ReplicateConstraints(KX_GameObject *gameobj, std::vector<KX_GameObject*> constobj) = 0; #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_IPhysicsController") diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index dd762b02b4e..4b8d36285be 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -55,6 +55,7 @@ class KX_Scene; struct PHY_ShapeProps; struct PHY_MaterialProps; class PHY_IMotionState; +struct bRigidBodyJointConstraint; /** * pass back information from rayTest @@ -167,7 +168,7 @@ class PHY_IPhysicsEnvironment float axis1X=0,float axis1Y=0,float axis1Z=0, float axis2X=0,float axis2Y=0,float axis2Z=0,int flag=0 )=0; - virtual void RemoveConstraint(int constraintid)=0; + virtual void RemoveConstraintById(int constraintid) = 0; virtual float GetAppliedImpulse(int constraintid) { return 0.0f; } @@ -213,6 +214,9 @@ class PHY_IPhysicsEnvironment bool isCompoundChild, bool hasCompoundChildren) = 0; + /* Set the rigid body joints constraints values for converted objects and replicated group instances. */ + virtual void SetupObjectConstraints(KX_GameObject *obj_src, KX_GameObject *obj_dest, + bRigidBodyJointConstraint *dat) {} #ifdef WITH_CXX_GUARDEDALLOC MEM_CXX_CLASS_ALLOC_FUNCS("GE:PHY_IPhysicsEnvironment") diff --git a/source/gameengine/Physics/common/PHY_Pro.h b/source/gameengine/Physics/common/PHY_Pro.h index 7c5d9c9638e..c9b91b06a3c 100644 --- a/source/gameengine/Physics/common/PHY_Pro.h +++ b/source/gameengine/Physics/common/PHY_Pro.h @@ -43,6 +43,8 @@ struct PHY_ShapeProps { MT_Scalar m_friction_scaling[3]; // Scaling for anisotropic friction. Component in range [0, 1] MT_Scalar m_clamp_vel_min; // Clamp the minimum velocity, this ensures an object moves at a minimum speed unless its stationary MT_Scalar m_clamp_vel_max; // Clamp max velocity + MT_Scalar m_clamp_angvel_min; // Clamp the minimum angular velocity. + MT_Scalar m_clamp_angvel_max; // Clamp the maximum angular velocity. bool m_do_anisotropic; // Should I do anisotropic friction? bool m_do_fh; // Should the object have a linear Fh spring? bool m_do_rot_fh; // Should the object have an angular Fh spring? diff --git a/source/gameengine/Rasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/CMakeLists.txt index e254bf9b1c5..5bc3f22e327 100644 --- a/source/gameengine/Rasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/CMakeLists.txt @@ -32,6 +32,7 @@ set(INC ../../blender/blenlib ../../blender/blenkernel ../../../intern/container + ../../../intern/glew-mx ../../../intern/guardedalloc ../../../intern/string ) @@ -81,6 +82,6 @@ set(SRC RAS_OpenGLFilters/RAS_Sobel2DFilter.h ) -add_definitions(-DGLEW_STATIC) +add_definitions(${GL_DEFINITIONS}) blender_add_lib(ge_rasterizer "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp index abbe65738d4..cedc27c3b92 100644 --- a/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp +++ b/source/gameengine/Rasterizer/RAS_2DFilterManager.cpp @@ -43,11 +43,11 @@ #include "RAS_2DFilterManager.h" #include <iostream> -#include "GL/glew.h" +#include "glew-mx.h" #include <stdio.h> -#include "Value.h" +#include "EXP_Value.h" RAS_2DFilterManager::RAS_2DFilterManager(): texturewidth(-1), textureheight(-1), @@ -75,6 +75,12 @@ texturewidth(-1), textureheight(-1), RAS_2DFilterManager::~RAS_2DFilterManager() { FreeTextures(); + + for (int passindex = 0; passindex < MAX_RENDER_PASS; passindex++) { + if (m_filters[passindex]) { + glDeleteObjectARB(m_filters[passindex]); + } + } } void RAS_2DFilterManager::PrintShaderErrors(unsigned int shader, const char *task, const char *code) @@ -119,11 +125,10 @@ unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource) glGetObjectParameterivARB(fShader, GL_COMPILE_STATUS, &success); - if (!success) - { + if (!success) { /*Shader Comile Error*/ PrintShaderErrors(fShader, "compile", shadersource); - return 0; + goto fail; } program = glCreateProgramObjectARB(); @@ -131,23 +136,37 @@ unsigned int RAS_2DFilterManager::CreateShaderProgram(const char* shadersource) glLinkProgramARB(program); glGetObjectParameterivARB(program, GL_LINK_STATUS, &success); - if (!success) - { + if (!success) { /*Program Link Error*/ PrintShaderErrors(fShader, "link", shadersource); - return 0; + goto fail; } glValidateProgramARB(program); glGetObjectParameterivARB(program, GL_VALIDATE_STATUS, &success); - if (!success) - { + if (!success) { /*Program Validation Error*/ PrintShaderErrors(fShader, "validate", shadersource); - return 0; + goto fail; + } + + /* owned by 'program' */ + if (fShader) { + glDeleteObjectARB(fShader); } return program; + + +fail: + if (fShader) { + glDeleteObjectARB(fShader); + } + + if (program) { + glDeleteObjectARB(program); + } + return 0; } unsigned int RAS_2DFilterManager::CreateShaderProgram(int filtermode) @@ -257,10 +276,24 @@ void RAS_2DFilterManager::StartShaderProgram(int passindex) for (i=0; i<objProperties; i++) { uniformLoc = glGetUniformLocationARB(m_filters[passindex], m_properties[passindex][i]); - if (uniformLoc != -1) - { - float value = ((CValue*)m_gameObjects[passindex])->GetPropertyNumber(m_properties[passindex][i], 0.0); - glUniform1fARB(uniformLoc,value); + + if (uniformLoc == -1) + continue; + + CValue *property = ((CValue *)m_gameObjects[passindex])->GetProperty(m_properties[passindex][i]); + + if (!property) + continue; + + switch (property->GetValueType()) { + case VALUE_INT_TYPE: + glUniform1iARB(uniformLoc, property->GetNumber()); + break; + case VALUE_FLOAT_TYPE: + glUniform1fARB(uniformLoc, property->GetNumber()); + break; + default: + break; } } } diff --git a/source/gameengine/Rasterizer/RAS_CameraData.h b/source/gameengine/Rasterizer/RAS_CameraData.h index 7a6bb541a1a..e2024a4a55d 100644 --- a/source/gameengine/Rasterizer/RAS_CameraData.h +++ b/source/gameengine/Rasterizer/RAS_CameraData.h @@ -39,6 +39,8 @@ struct RAS_CameraData float m_sensor_x; float m_sensor_y; short m_sensor_fit; + float m_shift_x; + float m_shift_y; float m_clipstart; float m_clipend; bool m_perspective; @@ -50,6 +52,7 @@ struct RAS_CameraData float m_focallength; RAS_CameraData(float lens = 35.0, float scale = 6.0, float sensor_x = 32.0, float sensor_y = 18.0, short sensor_fit = 0, + float shift_x = 0.0, float shift_y = 0.0, float clipstart = 0.1, float clipend = 5000.0, bool perspective = true, float focallength = 3.0, bool viewport = false, int viewportleft = 0, int viewportbottom = 0, int viewportright = 0, int viewporttop = 0) : @@ -58,6 +61,8 @@ struct RAS_CameraData m_sensor_x(sensor_x), m_sensor_y(sensor_y), m_sensor_fit(sensor_fit), + m_shift_x(shift_x), + m_shift_y(shift_y), m_clipstart(clipstart), m_clipend(clipend), m_perspective(perspective), diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.cpp b/source/gameengine/Rasterizer/RAS_FramingManager.cpp index d1a801c52f8..c5f15c9ad21 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.cpp +++ b/source/gameengine/Rasterizer/RAS_FramingManager.cpp @@ -41,15 +41,21 @@ ComputeDefaultFrustum( const float lens, const float sensor_x, const float sensor_y, const short sensor_fit, + const float shift_x, + const float shift_y, const float design_aspect_ratio, RAS_FrameFrustum & frustum ) { + float size; float halfSize; float sizeX; float sizeY; + float offsetX; + float offsetY; if (sensor_fit==RAS_SENSORFIT_AUTO) { - halfSize = (sensor_x / 2.f) * camnear / lens; + size = sensor_x * camnear / lens; + halfSize = size * 0.5f; if (design_aspect_ratio > 1.f) { // halfsize defines the width @@ -62,20 +68,25 @@ ComputeDefaultFrustum( } } else if (sensor_fit==RAS_SENSORFIT_HOR) { - halfSize = (sensor_x / 2.f) * camnear / lens; + size = sensor_x * camnear / lens; + halfSize = size * 0.5f; sizeX = halfSize; sizeY = halfSize/design_aspect_ratio; } else { - halfSize = (sensor_y / 2.f) * camnear / lens; + size = sensor_y * camnear / lens; + halfSize = size * 0.5f; sizeX = halfSize * design_aspect_ratio; sizeY = halfSize; } - - frustum.x2 = sizeX; - frustum.x1 = -frustum.x2; - frustum.y2 = sizeY; - frustum.y1 = -frustum.y2; + + offsetX = size * shift_x; + offsetY = size * shift_y; + + frustum.x2 = sizeX + offsetX; + frustum.x1 = -sizeX + offsetX; + frustum.y2 = sizeY + offsetY; + frustum.y1 = -sizeY + offsetY; frustum.camnear = camnear; frustum.camfar = camfar; } @@ -88,12 +99,16 @@ ComputeDefaultOrtho( const float scale, const float design_aspect_ratio, const short sensor_fit, + const float shift_x, + const float shift_y, RAS_FrameFrustum & frustum ) { float halfSize = scale*0.5f; float sizeX; float sizeY; + float offsetX; + float offsetY; if (sensor_fit==RAS_SENSORFIT_AUTO) { if (design_aspect_ratio > 1.f) { @@ -114,11 +129,14 @@ ComputeDefaultOrtho( sizeX = halfSize * design_aspect_ratio; sizeY = halfSize; } - - frustum.x2 = sizeX; - frustum.x1 = -frustum.x2; - frustum.y2 = sizeY; - frustum.y1 = -frustum.y2; + + offsetX = scale * shift_x; + offsetY = scale * shift_y; + + frustum.x2 = sizeX + offsetX; + frustum.x1 = -sizeX + offsetX; + frustum.y2 = sizeY + offsetY; + frustum.y1 = -sizeY + offsetY; frustum.camnear = camnear; frustum.camfar = camfar; } @@ -221,6 +239,8 @@ ComputeFrustum( const RAS_Rect &viewport, const float lens, const float sensor_x, const float sensor_y, const short sensor_fit, + const float shift_x, + const float shift_y, const float camnear, const float camfar, RAS_FrameFrustum &frustum @@ -249,6 +269,8 @@ ComputeFrustum( sensor_x, sensor_y, sensor_fit, + shift_x, + shift_y, design_aspect_ratio, frustum ); @@ -315,6 +337,8 @@ RAS_FramingManager:: const float camnear, const float camfar, const short sensor_fit, + const float shift_x, + const float shift_y, RAS_FrameFrustum &frustum ) { @@ -340,6 +364,8 @@ RAS_FramingManager:: scale, design_aspect_ratio, sensor_fit, + shift_x, + shift_y, frustum ); diff --git a/source/gameengine/Rasterizer/RAS_FramingManager.h b/source/gameengine/Rasterizer/RAS_FramingManager.h index 122f0ca46ec..5741a91939e 100644 --- a/source/gameengine/Rasterizer/RAS_FramingManager.h +++ b/source/gameengine/Rasterizer/RAS_FramingManager.h @@ -236,6 +236,8 @@ public : const float camnear, const float camfar, const short sensor_fit, + const float shift_x, + const float shift_y, RAS_FrameFrustum &frustum ); @@ -247,6 +249,8 @@ public : const RAS_Rect &viewport, const float lens, const float sensor_x, const float sensor_y, const short sensor_fit, + const float shift_x, + const float shift_y, const float camnear, const float camfar, RAS_FrameFrustum &frustum @@ -260,6 +264,8 @@ public : const float lens, const float sensor_x, const float sensor_y, const short sensor_fit, + const float shift_x, + const float shift_y, const float design_aspect_ratio, RAS_FrameFrustum & frustum ); @@ -272,6 +278,8 @@ public : const float scale, const float design_aspect_ratio, const short sensor_fit, + const float shift_x, + const float shift_y, RAS_FrameFrustum & frustum ); diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h index 9e8a6e8ccf6..471c2c97fa1 100644 --- a/source/gameengine/Rasterizer/RAS_ICanvas.h +++ b/source/gameengine/Rasterizer/RAS_ICanvas.h @@ -113,8 +113,9 @@ public: )=0; virtual - int + bool GetSwapInterval( + int& intervalOut )=0; virtual @@ -236,6 +237,8 @@ public: const char* filename )=0; + virtual void GetDisplayDimensions(int &width, int &height) = 0; + virtual void ResizeWindow( diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp index 03f6e567771..d07b4910968 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.cpp @@ -233,7 +233,7 @@ Image *RAS_IPolyMaterial::GetBlenderImage() const { return NULL; } -MTFace *RAS_IPolyMaterial::GetMTFace() const +MTexPoly *RAS_IPolyMaterial::GetMTexPoly() const { return NULL; } diff --git a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h index 14223fc59bd..a34f7a9b390 100644 --- a/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h +++ b/source/gameengine/Rasterizer/RAS_IPolygonMaterial.h @@ -41,7 +41,7 @@ #endif class RAS_IRasterizer; -struct MTFace; +struct MTexPoly; struct Material; struct Image; struct Scene; @@ -167,7 +167,7 @@ public: virtual Material* GetBlenderMaterial() const; virtual Image* GetBlenderImage() const; - virtual MTFace* GetMTFace() const; + virtual MTexPoly* GetMTexPoly() const; virtual unsigned int* GetMCol() const; virtual Scene* GetBlenderScene() const; virtual void ReleaseMaterial(); diff --git a/source/gameengine/Rasterizer/RAS_IRasterizer.h b/source/gameengine/Rasterizer/RAS_IRasterizer.h index d7b52213191..7fbaf076d25 100644 --- a/source/gameengine/Rasterizer/RAS_IRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_IRasterizer.h @@ -54,6 +54,7 @@ class RAS_ICanvas; class RAS_IPolyMaterial; class RAS_MeshSlot; class RAS_ILightObject; +class SCA_IScene; typedef vector<unsigned short> KX_IndexArray; typedef vector<RAS_TexVert> KX_VertexArray; @@ -297,15 +298,11 @@ public: /** * Fog */ - virtual void SetFog(float start, float dist, float r, float g, float b) = 0; - virtual void SetFogColor(float r, float g,float b) = 0; - virtual void SetFogStart(float start) = 0; - virtual void SetFogEnd(float end) = 0; + virtual void SetFog(short type, float start, float dist, float intensity, float color[3]) = 0; virtual void DisplayFog() = 0; - virtual void DisableFog() = 0; - virtual bool IsFogEnabled() = 0; + virtual void EnableFog(bool enable) = 0; - virtual void SetBackColor(float red, float green, float blue, float alpha) = 0; + virtual void SetBackColor(float color[3]) = 0; /** * \param drawingmode = KX_BOUNDINGBOX, KX_WIREFRAME, KX_SOLID, KX_SHADED or KX_TEXTURED. @@ -380,7 +377,7 @@ public: */ virtual void SetEmissive(float eX, float eY, float eZ, float e) = 0; - virtual void SetAmbientColor(float red, float green, float blue) = 0; + virtual void SetAmbientColor(float color[3]) = 0; virtual void SetAmbient(float factor) = 0; /** @@ -388,10 +385,10 @@ public: */ virtual void SetPolygonOffset(float mult, float add) = 0; - virtual void DrawDebugLine(const MT_Vector3 &from, const MT_Vector3 &to, const MT_Vector3& color) = 0; - virtual void DrawDebugCircle(const MT_Vector3 ¢er, const MT_Scalar radius, const MT_Vector3 &color, - const MT_Vector3 &normal, int nsector) = 0; - virtual void FlushDebugShapes() = 0; + virtual void DrawDebugLine(SCA_IScene *scene, const MT_Vector3 &from, const MT_Vector3 &to, const MT_Vector3& color) = 0; + virtual void DrawDebugCircle(SCA_IScene *scene, const MT_Vector3 ¢er, const MT_Scalar radius, + const MT_Vector3 &color, const MT_Vector3 &normal, int nsector) = 0; + virtual void FlushDebugShapes(SCA_IScene *scene) = 0; virtual void SetTexCoordNum(int num) = 0; virtual void SetAttribNum(int num) = 0; diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp index 4b5fc6510e0..2078fc99f2e 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.cpp @@ -287,6 +287,16 @@ void RAS_MeshSlot::AddPolygonVertex(int offset) m_endindex++; } +void RAS_MeshSlot::UpdateDisplayArraysOffset() +{ + unsigned int offset = 0; + for (unsigned short i = 0; i < m_displayArrays.size(); ++i) { + RAS_DisplayArray *darray = m_displayArrays[i]; + darray->m_offset = offset; + offset += darray->m_vertex.size(); + } +} + void RAS_MeshSlot::SetDeformer(RAS_Deformer* deformer) { if (deformer && m_pDeformer != deformer) { diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 007fdf240c4..1eee99f896b 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -80,6 +80,13 @@ public: class RAS_DisplayArray { public: + /** The offset relation to the previous RAS_DisplayArray. + * For the user vertex are one big list but in C++ source + * it's two different lists if we use quads and triangles. + * So to fix that we add an offset. + * This value is set in UpdateDisplayArraysOffset(). + */ + unsigned int m_offset; vector<RAS_TexVert> m_vertex; vector<unsigned short> m_index; /* LINE currently isn't used */ @@ -165,6 +172,9 @@ public: int AddVertex(const RAS_TexVert& tv); void AddPolygonVertex(int offset); + /// Update offset of each display array + void UpdateDisplayArraysOffset(); + /* optimization */ bool Split(bool force=false); bool Join(RAS_MeshSlot *target, MT_Scalar distance); diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.cpp b/source/gameengine/Rasterizer/RAS_MeshObject.cpp index 54b15f07896..4360464ed32 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.cpp +++ b/source/gameengine/Rasterizer/RAS_MeshObject.cpp @@ -465,6 +465,23 @@ void RAS_MeshObject::RemoveFromBuckets(void *clientobj) } } +void RAS_MeshObject::EndConversion() +{ +#if 0 + m_sharedvertex_map.clear(); // SharedVertex + vector<vector<SharedVertex> > shared_null(0); + shared_null.swap( m_sharedvertex_map ); /* really free the memory */ +#endif + + for (std::list<RAS_MeshMaterial>::iterator it = m_materials.begin(); + it != m_materials.end(); + ++it) + { + RAS_MeshSlot *ms = it->m_baseslot; + ms->UpdateDisplayArraysOffset(); + } +} + //void RAS_MeshObject::Transform(const MT_Transform& trans) //{ //m_trans.translate(MT_Vector3(0,0,1));//.operator *=(trans); diff --git a/source/gameengine/Rasterizer/RAS_MeshObject.h b/source/gameengine/Rasterizer/RAS_MeshObject.h index 4f352379d39..a6f1a1cafc6 100644 --- a/source/gameengine/Rasterizer/RAS_MeshObject.h +++ b/source/gameengine/Rasterizer/RAS_MeshObject.h @@ -132,13 +132,7 @@ public: virtual void AddMeshUser(void *clientobj, SG_QList *head, RAS_Deformer* deformer); void RemoveFromBuckets(void *clientobj); - void EndConversion() { -#if 0 - m_sharedvertex_map.clear(); // SharedVertex - vector<vector<SharedVertex> > shared_null(0); - shared_null.swap( m_sharedvertex_map ); /* really free the memory */ -#endif - } + void EndConversion(); /* colors */ void DebugColor(unsigned int abgr); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt index f0410ba891d..888a7114f50 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/CMakeLists.txt @@ -39,6 +39,7 @@ set(INC ../../../blender/gpu ../../../blender/makesdna ../../../../intern/container + ../../../../intern/glew-mx ../../../../intern/string ) @@ -66,6 +67,6 @@ set(SRC RAS_StorageVBO.h ) -add_definitions(-DGLEW_STATIC) +add_definitions(${GL_DEFINITIONS}) blender_add_lib(ge_oglrasterizer "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp index 32cc4ba9fea..bc22d68e218 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_GLExtensionManager.cpp @@ -32,7 +32,7 @@ #include <iostream> -#include "GL/glew.h" +#include "glew-mx.h" #include "RAS_GLExtensionManager.h" diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp index e1dbd6f0a7f..34184f73953 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.cpp @@ -30,7 +30,7 @@ #include <windows.h> #endif // WIN32 -#include "GL/glew.h" +#include "glew-mx.h" #include "RAS_MaterialBucket.h" #include "RAS_TexVert.h" @@ -79,10 +79,6 @@ void RAS_ListSlot::RemoveList() void RAS_ListSlot::DrawList() { - if (m_flag &LIST_STREAM || m_flag& LIST_NOCREATE) { - RemoveList(); - return; - } if (m_flag &LIST_MODIFY) { if (m_flag &LIST_CREATE) { if (m_list == 0) { @@ -115,7 +111,7 @@ void RAS_ListSlot::SetModified(bool mod) if (mod && !(m_flag & LIST_MODIFY)) { spit("Modifying list (" << m_list << ")"); m_flag = m_flag &~ LIST_END; - m_flag |= LIST_STREAM; + m_flag |= LIST_MODIFY; } } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h index d394c72b2a2..5e1c662bc17 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_ListRasterizer.h @@ -35,12 +35,9 @@ public: enum RAS_ListSlotFlags { LIST_CREATE =1, LIST_MODIFY =2, - LIST_STREAM =4, - LIST_NOCREATE =8, - LIST_BEGIN =16, - LIST_END =32, - LIST_REGEN =64, - LIST_DERIVEDMESH=128, + LIST_BEGIN =4, + LIST_END =8, + LIST_DERIVEDMESH=16, }; struct DerivedMesh; diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp index e1b7a2151c5..4ac1c9c4ebb 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLLight.cpp @@ -25,9 +25,10 @@ * ***** END GPL LICENSE BLOCK ***** */ +#include "glew-mx.h" + #include <stdio.h> -#include "GL/glew.h" #include "RAS_OpenGLLight.h" #include "RAS_OpenGLRasterizer.h" diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp index 0960fdaab4f..1758b7abf9f 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.cpp @@ -35,7 +35,7 @@ #include "RAS_OpenGLRasterizer.h" -#include "GL/glew.h" +#include "glew-mx.h" #include "RAS_ICanvas.h" #include "RAS_Rect.h" @@ -60,7 +60,7 @@ extern "C"{ // XXX Clean these up <<< -#include "Value.h" +#include "EXP_Value.h" #include "KX_Scene.h" #include "KX_RayCast.h" #include "KX_GameObject.h" @@ -99,9 +99,9 @@ RAS_OpenGLRasterizer::RAS_OpenGLRasterizer(RAS_ICanvas* canvas, int storage) m_motionblur(0), m_motionblurvalue(-1.0), m_usingoverrideshader(false), - m_clientobject(NULL), - m_auxilaryClientInfo(NULL), - m_drawingmode(KX_TEXTURED), + m_clientobject(NULL), + m_auxilaryClientInfo(NULL), + m_drawingmode(KX_TEXTURED), m_texco_num(0), m_attrib_num(0), //m_last_alphablend(GPU_BLEND_SOLID), @@ -194,113 +194,52 @@ bool RAS_OpenGLRasterizer::Init() } -void RAS_OpenGLRasterizer::SetAmbientColor(float red, float green, float blue) +void RAS_OpenGLRasterizer::SetAmbientColor(float color[3]) { - m_ambr = red; - m_ambg = green; - m_ambb = blue; + m_ambr = color[0]; + m_ambg = color[1]; + m_ambb = color[2]; } - void RAS_OpenGLRasterizer::SetAmbient(float factor) { - float ambient[] = { m_ambr*factor, m_ambg*factor, m_ambb*factor, 1.0f }; + float ambient[] = {m_ambr * factor, m_ambg * factor, m_ambb * factor, 1.0f}; glLightModelfv(GL_LIGHT_MODEL_AMBIENT, ambient); } - -void RAS_OpenGLRasterizer::SetBackColor(float red, - float green, - float blue, - float alpha) -{ - m_redback = red; - m_greenback = green; - m_blueback = blue; - m_alphaback = alpha; -} - - - -void RAS_OpenGLRasterizer::SetFogColor(float r, - float g, - float b) +void RAS_OpenGLRasterizer::SetBackColor(float color[3]) { - m_fogr = r; - m_fogg = g; - m_fogb = b; - m_fogenabled = true; + m_redback = color[0]; + m_greenback = color[1]; + m_blueback = color[2]; + m_alphaback = 1.0f; } - - -void RAS_OpenGLRasterizer::SetFogStart(float start) +void RAS_OpenGLRasterizer::SetFog(short type, float start, float dist, float intensity, float color[3]) { - m_fogstart = start; - m_fogenabled = true; + float params[4] = {color[0], color[1], color[2], 1.0f}; + glFogi(GL_FOG_MODE, GL_LINEAR); + glFogf(GL_FOG_DENSITY, intensity / 10.0f); + glFogf(GL_FOG_START, start); + glFogf(GL_FOG_END, start + dist); + glFogfv(GL_FOG_COLOR, params); } - - -void RAS_OpenGLRasterizer::SetFogEnd(float fogend) +void RAS_OpenGLRasterizer::EnableFog(bool enable) { - m_fogdist = fogend; - m_fogenabled = true; + m_fogenabled = enable; } - - -void RAS_OpenGLRasterizer::SetFog(float start, - float dist, - float r, - float g, - float b) -{ - m_fogstart = start; - m_fogdist = dist; - m_fogr = r; - m_fogg = g; - m_fogb = b; - m_fogenabled = true; -} - - - -void RAS_OpenGLRasterizer::DisableFog() -{ - m_fogenabled = false; -} - -bool RAS_OpenGLRasterizer::IsFogEnabled() -{ - return m_fogenabled; -} - - void RAS_OpenGLRasterizer::DisplayFog() { - if ((m_drawingmode >= KX_SOLID) && m_fogenabled) - { - float params[5]; - glFogi(GL_FOG_MODE, GL_LINEAR); - glFogf(GL_FOG_DENSITY, 0.1f); - glFogf(GL_FOG_START, m_fogstart); - glFogf(GL_FOG_END, m_fogstart + m_fogdist); - params[0] = m_fogr; - params[1] = m_fogg; - params[2] = m_fogb; - params[3] = 0.0; - glFogfv(GL_FOG_COLOR, params); + if ((m_drawingmode >= KX_SOLID) && m_fogenabled) { glEnable(GL_FOG); - } - else - { + } + else { glDisable(GL_FOG); } } - - bool RAS_OpenGLRasterizer::SetMaterial(const RAS_IPolyMaterial& mat) { return mat.Activate(this, m_materialCachingInfo); @@ -417,9 +356,10 @@ void RAS_OpenGLRasterizer::ClearCachingInfo(void) m_materialCachingInfo = 0; } -void RAS_OpenGLRasterizer::FlushDebugShapes() +void RAS_OpenGLRasterizer::FlushDebugShapes(SCA_IScene *scene) { - if (m_debugShapes.empty()) + std::vector<OglDebugShape> &debugShapes = m_debugShapes[scene]; + if (debugShapes.empty()) return; // DrawDebugLines @@ -433,28 +373,26 @@ void RAS_OpenGLRasterizer::FlushDebugShapes() //draw lines glBegin(GL_LINES); - for (unsigned int i=0;i<m_debugShapes.size();i++) - { - if (m_debugShapes[i].m_type != OglDebugShape::LINE) + for (unsigned int i = 0; i < debugShapes.size(); i++) { + if (debugShapes[i].m_type != OglDebugShape::LINE) continue; - glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f); - const MT_Scalar* fromPtr = &m_debugShapes[i].m_pos.x(); - const MT_Scalar* toPtr= &m_debugShapes[i].m_param.x(); + glColor4f(debugShapes[i].m_color[0], debugShapes[i].m_color[1], debugShapes[i].m_color[2], 1.0f); + const MT_Scalar *fromPtr = &debugShapes[i].m_pos.x(); + const MT_Scalar *toPtr= &debugShapes[i].m_param.x(); glVertex3dv(fromPtr); glVertex3dv(toPtr); } glEnd(); //draw circles - for (unsigned int i=0;i<m_debugShapes.size();i++) - { - if (m_debugShapes[i].m_type != OglDebugShape::CIRCLE) + for (unsigned int i = 0; i < debugShapes.size(); i++) { + if (debugShapes[i].m_type != OglDebugShape::CIRCLE) continue; glBegin(GL_LINE_LOOP); - glColor4f(m_debugShapes[i].m_color[0],m_debugShapes[i].m_color[1],m_debugShapes[i].m_color[2],1.f); + glColor4f(debugShapes[i].m_color[0], debugShapes[i].m_color[1], debugShapes[i].m_color[2], 1.0f); static const MT_Vector3 worldUp(0.0, 0.0, 1.0); - MT_Vector3 norm = m_debugShapes[i].m_param; + MT_Vector3 norm = debugShapes[i].m_param; MT_Matrix3x3 tr; if (norm.fuzzyZero() || norm == worldUp) { @@ -469,14 +407,14 @@ void RAS_OpenGLRasterizer::FlushDebugShapes() yaxis.x(), yaxis.y(), yaxis.z(), norm.x(), norm.y(), norm.z()); } - MT_Scalar rad = m_debugShapes[i].m_param2.x(); - int n = (int) m_debugShapes[i].m_param2.y(); + MT_Scalar rad = debugShapes[i].m_param2.x(); + int n = (int)debugShapes[i].m_param2.y(); for (int j = 0; j<n; j++) { MT_Scalar theta = j*M_PI*2/n; MT_Vector3 pos(cos(theta) * rad, sin(theta) * rad, 0.0); pos = pos*tr; - pos += m_debugShapes[i].m_pos; + pos += debugShapes[i].m_pos; const MT_Scalar* posPtr = &pos.x(); glVertex3dv(posPtr); } @@ -486,13 +424,11 @@ void RAS_OpenGLRasterizer::FlushDebugShapes() if (light) glEnable(GL_LIGHTING); if (tex) glEnable(GL_TEXTURE_2D); - m_debugShapes.clear(); + debugShapes.clear(); } void RAS_OpenGLRasterizer::EndFrame() { - FlushDebugShapes(); - glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glDisable(GL_MULTISAMPLE_ARB); @@ -731,7 +667,9 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms, // triangle and quad text drawing for (i=0; i<it.totindex; i+=numvert) { - float v[4][3]; + float v[4][3]; + const float *v_ptr[4] = {NULL}; + const float *uv_ptr[4] = {NULL}; int glattrib, unit; for (j=0; j<numvert; j++) { @@ -740,6 +678,9 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms, v[j][0] = vertex->getXYZ()[0]; v[j][1] = vertex->getXYZ()[1]; v[j][2] = vertex->getXYZ()[2]; + v_ptr[j] = v[j]; + + uv_ptr[j] = vertex->getUV(0); } // find the right opengl attribute @@ -749,7 +690,9 @@ void RAS_OpenGLRasterizer::IndexPrimitives_3DText(RAS_MeshSlot& ms, if (m_attrib[unit] == RAS_TEXCO_UV) glattrib = unit; - GPU_render_text(polymat->GetMTFace(), polymat->GetDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(), v[0], v[1], v[2], v[3], glattrib); + GPU_render_text( + polymat->GetMTexPoly(), polymat->GetDrawingMode(), mytext, mytext.Length(), polymat->GetMCol(), + v_ptr, uv_ptr, glattrib); ClearCachingInfo(); } @@ -1135,12 +1078,17 @@ void RAS_OpenGLRasterizer::SetMipmapping(MipmapOption val) RAS_IRasterizer::MipmapOption RAS_OpenGLRasterizer::GetMipmapping() { - if (GPU_get_linear_mipmap()) - return RAS_IRasterizer::RAS_MIPMAP_LINEAR; - else if (GPU_get_mipmap()) - return RAS_IRasterizer::RAS_MIPMAP_NEAREST; - else + if (GPU_get_mipmap()) { + if (GPU_get_linear_mipmap()) { + return RAS_IRasterizer::RAS_MIPMAP_LINEAR; + } + else { + return RAS_IRasterizer::RAS_MIPMAP_NEAREST; + } + } + else { return RAS_IRasterizer::RAS_MIPMAP_NONE; + } } void RAS_OpenGLRasterizer::SetUsingOverrideShader(bool val) @@ -1269,28 +1217,32 @@ void RAS_OpenGLRasterizer::RemoveLight(RAS_ILightObject* lightobject) bool RAS_OpenGLRasterizer::RayHit(struct KX_ClientObjectInfo *client, KX_RayCast *result, void * const data) { - double* const oglmatrix = (double* const) data; + if (result->m_hitMesh) { + double* const oglmatrix = (double* const) data; - RAS_Polygon* poly = result->m_hitMesh->GetPolygon(result->m_hitPolygon); - if (!poly->IsVisible()) - return false; + RAS_Polygon* poly = result->m_hitMesh->GetPolygon(result->m_hitPolygon); + if (!poly->IsVisible()) + return false; - MT_Point3 resultpoint(result->m_hitPoint); - MT_Vector3 resultnormal(result->m_hitNormal); - MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); - MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); - left = (dir.cross(resultnormal)).safe_normalized(); - // for the up vector, we take the 'resultnormal' returned by the physics - - double maat[16] = {left[0], left[1], left[2], 0, - dir[0], dir[1], dir[2], 0, - resultnormal[0], resultnormal[1], resultnormal[2], 0, - 0, 0, 0, 1}; - - glTranslated(resultpoint[0],resultpoint[1],resultpoint[2]); - //glMultMatrixd(oglmatrix); - glMultMatrixd(maat); - return true; + MT_Vector3 resultnormal(result->m_hitNormal); + MT_Vector3 left(oglmatrix[0],oglmatrix[1],oglmatrix[2]); + MT_Vector3 dir = -(left.cross(resultnormal)).safe_normalized(); + left = (dir.cross(resultnormal)).safe_normalized(); + // for the up vector, we take the 'resultnormal' returned by the physics + + double maat[16] = {left[0], left[1], left[2], 0, + dir[0], dir[1], dir[2], 0, + resultnormal[0], resultnormal[1], resultnormal[2], 0, + 0, 0, 0, 1}; + + glTranslated(oglmatrix[12],oglmatrix[13],oglmatrix[14]); + //glMultMatrixd(oglmatrix); + glMultMatrixd(maat); + return true; + } + else { + return false; + } } void RAS_OpenGLRasterizer::applyTransform(double* oglmatrix,int objectdrawmode ) @@ -1351,7 +1303,7 @@ void RAS_OpenGLRasterizer::applyTransform(double* oglmatrix,int objectdrawmode ) up[0], up[1], up[2], 0, 0, 0, 0, 1}; - glTranslated(objpos[0],objpos[1],objpos[2]); + glTranslatef(objpos[0],objpos[1],objpos[2]); glMultMatrixd(maat); } diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h index 1334ddb2a26..ad49ebe5179 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_OpenGLRasterizer.h @@ -38,6 +38,7 @@ #include "MT_CmMatrix4x4.h" #include <vector> +#include <map> using namespace std; #include "RAS_IRasterizer.h" @@ -80,12 +81,7 @@ class RAS_OpenGLRasterizer : public RAS_IRasterizer /* fogging vars */ bool m_fogenabled; - float m_fogstart; - float m_fogdist; - float m_fogr; - float m_fogg; - float m_fogb; - + float m_redback; float m_greenback; float m_blueback; @@ -198,16 +194,12 @@ public: virtual const MT_Point3& GetCameraPosition(); virtual bool GetCameraOrtho(); - virtual void SetFog(float start, float dist, float r, float g, float b); - virtual void SetFogColor(float r, float g, float b); - virtual void SetFogStart(float fogstart); - virtual void SetFogEnd(float fogend); - void DisableFog(); + virtual void SetFog(short type, float start, float dist, float intensity, float color[3]); + virtual void EnableFog(bool enable); virtual void DisplayFog(); - virtual bool IsFogEnabled(); - virtual void SetBackColor(float red, float green, float blue, float alpha); - + virtual void SetBackColor(float color[3]); + virtual void SetDrawingMode(int drawingmode); virtual int GetDrawingMode(); @@ -227,25 +219,25 @@ public: virtual void SetDiffuse(float difX, float difY, float difZ, float diffuse); virtual void SetEmissive(float eX, float eY, float eZ, float e); - virtual void SetAmbientColor(float red, float green, float blue); + virtual void SetAmbientColor(float color[3]); virtual void SetAmbient(float factor); virtual void SetPolygonOffset(float mult, float add); - virtual void FlushDebugShapes(); + virtual void FlushDebugShapes(SCA_IScene *scene); - virtual void DrawDebugLine(const MT_Vector3 &from,const MT_Vector3 &to, const MT_Vector3 &color) + virtual void DrawDebugLine(SCA_IScene *scene, const MT_Vector3 &from,const MT_Vector3 &to, const MT_Vector3 &color) { OglDebugShape line; line.m_type = OglDebugShape::LINE; line.m_pos= from; line.m_param = to; line.m_color = color; - m_debugShapes.push_back(line); + m_debugShapes[scene].push_back(line); } - virtual void DrawDebugCircle(const MT_Vector3 ¢er, const MT_Scalar radius, const MT_Vector3 &color, - const MT_Vector3 &normal, int nsector) + virtual void DrawDebugCircle(SCA_IScene *scene, const MT_Vector3 ¢er, const MT_Scalar radius, + const MT_Vector3 &color, const MT_Vector3 &normal, int nsector) { OglDebugShape line; line.m_type = OglDebugShape::CIRCLE; @@ -254,10 +246,11 @@ public: line.m_color = color; line.m_param2.x() = radius; line.m_param2.y() = (float) nsector; - m_debugShapes.push_back(line); + m_debugShapes[scene].push_back(line); } - std::vector <OglDebugShape> m_debugShapes; + // We store each debug shape by scene. + std::map<SCA_IScene *, std::vector<OglDebugShape> > m_debugShapes; virtual void SetTexCoordNum(int num); virtual void SetAttribNum(int num); diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp index c8975c245cb..2cf6088629a 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageIM.cpp @@ -29,7 +29,7 @@ #include "RAS_MaterialBucket.h" #include "RAS_IPolygonMaterial.h" -#include "GL/glew.h" +#include "glew-mx.h" #include "GPU_draw.h" #include "GPU_extensions.h" #include "GPU_material.h" @@ -179,12 +179,12 @@ static int CheckTexfaceDM(void *mcol, int index) } */ -static DMDrawOption CheckTexDM(MTFace *tface, const bool has_mcol, int matnr) +static DMDrawOption CheckTexDM(MTexPoly *mtexpoly, const bool has_mcol, int matnr) { // index is the original face index, retrieve the polygon if (matnr == current_blmat_nr && - (tface == NULL || tface->tpage == current_image)) { + (mtexpoly == NULL || mtexpoly->tpage == current_image)) { // must handle color. if (current_wireframe) return DM_DRAW_OPTION_NO_MCOL; @@ -236,7 +236,7 @@ void RAS_StorageIM::IndexPrimitivesInternal(RAS_MeshSlot& ms, bool multi) 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); + GPU_material_vertex_attributes(GPU_material_from_blender(blscene, blmat, false), ¤t_gpu_attribs); else memset(¤t_gpu_attribs, 0, sizeof(current_gpu_attribs)); // DM draw can mess up blending mode, restore at the end diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp index 006c07b0491..c2980a6c15f 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVA.cpp @@ -27,7 +27,7 @@ #include "RAS_StorageVA.h" -#include "GL/glew.h" +#include "glew-mx.h" RAS_StorageVA::RAS_StorageVA(int *texco_num, RAS_IRasterizer::TexCoGen *texco, int *attrib_num, RAS_IRasterizer::TexCoGen *attrib, int *attrib_layer) : m_drawingmode(RAS_IRasterizer::KX_TEXTURED), diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp index 6aa90fbd6ef..58f3d4c05da 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.cpp @@ -28,7 +28,7 @@ #include "RAS_StorageVBO.h" #include "RAS_MeshObject.h" -#include "GL/glew.h" +#include "glew-mx.h" VBO::VBO(RAS_DisplayArray *data, unsigned int indices) { diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h index 2fe0c32f399..f156722247c 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/RAS_StorageVBO.h @@ -29,7 +29,7 @@ #define __KX_VERTEXBUFFEROBJECTSTORAGE #include <map> -#include "GL/glew.h" +#include "glew-mx.h" #include "RAS_IStorage.h" #include "RAS_IRasterizer.h" diff --git a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript index 0a7417656c6..ce520df2a21 100644 --- a/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript +++ b/source/gameengine/Rasterizer/RAS_OpenGLRasterizer/SConscript @@ -3,14 +3,16 @@ Import ('env') sources = env.Glob('*.cpp') -defs = [ 'GLEW_STATIC' ] +defs = [] +defs += env['BF_GL_DEFINITIONS'] incs = [ '.', '#intern/container', '#intern/guardedalloc', '#intern/string', - '#extern/glew/include', + env['BF_GLEW_INC'], + '#/intern/glew-mx', '#intern/moto/include', '#source/blender/blenkernel', '#source/blender/blenfont', diff --git a/source/gameengine/Rasterizer/RAS_Polygon.cpp b/source/gameengine/Rasterizer/RAS_Polygon.cpp index 1f23df90753..3274ded4406 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.cpp +++ b/source/gameengine/Rasterizer/RAS_Polygon.cpp @@ -62,9 +62,9 @@ RAS_TexVert *RAS_Polygon::GetVertex(int i) return &m_darray->m_vertex[m_offset[i]]; } -int RAS_Polygon::GetVertexOffset(int i) +unsigned int RAS_Polygon::GetVertexOffsetAbsolute(unsigned short i) { - return m_offset[i]; + return m_offset[i] + m_darray->m_offset; } /* diff --git a/source/gameengine/Rasterizer/RAS_Polygon.h b/source/gameengine/Rasterizer/RAS_Polygon.h index b18477a72d2..597e80ffdfb 100644 --- a/source/gameengine/Rasterizer/RAS_Polygon.h +++ b/source/gameengine/Rasterizer/RAS_Polygon.h @@ -72,8 +72,8 @@ public: RAS_TexVert* GetVertex(int i); void SetVertexOffset(int i, unsigned short offset); - int GetVertexOffset(int i); - + unsigned int GetVertexOffsetAbsolute(unsigned short i); + // each bit is for a visible edge, starting with bit 1 for the first edge, bit 2 for second etc. // - Not used yet! /* int GetEdgeCode(); diff --git a/source/gameengine/Rasterizer/RAS_texmatrix.cpp b/source/gameengine/Rasterizer/RAS_texmatrix.cpp index 3203fcf9d6b..d30a3d3a75d 100644 --- a/source/gameengine/Rasterizer/RAS_texmatrix.cpp +++ b/source/gameengine/Rasterizer/RAS_texmatrix.cpp @@ -34,7 +34,7 @@ void RAS_CalcTexMatrix(RAS_TexVert p[3],MT_Point3& origin,MT_Vector3& udir,MT_Vector3& vdir) { -// precondition: 3 vertices are non-colinear +// precondition: 3 vertices are non-collinear MT_Vector3 vec1 = p[1].xyz()-p[0].xyz(); MT_Vector3 vec2 = p[2].xyz()-p[0].xyz(); diff --git a/source/gameengine/Rasterizer/SConscript b/source/gameengine/Rasterizer/SConscript index 5c68ce63a3b..a643f46e39a 100644 --- a/source/gameengine/Rasterizer/SConscript +++ b/source/gameengine/Rasterizer/SConscript @@ -36,15 +36,18 @@ incs = [ '#intern/moto/include', '#intern/container', '#source/gameengine/BlenderRoutines', - '#extern/glew/include', + env['BF_GLEW_INC'], + '#/intern/glew-mx', '#source/gameengine/Expressions', '#source/gameengine/SceneGraph', '#source/blender/blenlib', '#source/blender/blenkernel', + '#source/blender/gpu', '#source/blender/makesdna', ] -defs = ['GLEW_STATIC'] +defs = [] +defs += env['BF_GL_DEFINITIONS'] if env['WITH_BF_PYTHON']: incs.extend(Split(env['BF_PYTHON_INC'])) diff --git a/source/gameengine/VideoTexture/CMakeLists.txt b/source/gameengine/VideoTexture/CMakeLists.txt index 3ca3917cf6d..4be9a9abe5c 100644 --- a/source/gameengine/VideoTexture/CMakeLists.txt +++ b/source/gameengine/VideoTexture/CMakeLists.txt @@ -42,6 +42,7 @@ set(INC ../../blender/python/generic ../../../intern/container ../../../intern/ffmpeg + ../../../intern/glew-mx ../../../intern/guardedalloc ../../../intern/string ) @@ -51,7 +52,7 @@ set(INC_SYS ${GLEW_INCLUDE_PATH} ) -add_definitions(-DGLEW_STATIC) +add_definitions(${GL_DEFINITIONS}) set(SRC Exception.cpp diff --git a/source/gameengine/VideoTexture/Exception.cpp b/source/gameengine/VideoTexture/Exception.cpp index 804834af4cd..08616e0c41c 100644 --- a/source/gameengine/VideoTexture/Exception.cpp +++ b/source/gameengine/VideoTexture/Exception.cpp @@ -31,7 +31,7 @@ #include <sstream> #include <fstream> -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "Exception.h" diff --git a/source/gameengine/VideoTexture/FilterBase.cpp b/source/gameengine/VideoTexture/FilterBase.cpp index 97abe36bb81..5717a1edbcb 100644 --- a/source/gameengine/VideoTexture/FilterBase.cpp +++ b/source/gameengine/VideoTexture/FilterBase.cpp @@ -31,7 +31,7 @@ #include "FilterBase.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> diff --git a/source/gameengine/VideoTexture/FilterBase.h b/source/gameengine/VideoTexture/FilterBase.h index a1d199b1851..498917e2375 100644 --- a/source/gameengine/VideoTexture/FilterBase.h +++ b/source/gameengine/VideoTexture/FilterBase.h @@ -33,7 +33,7 @@ #include "Common.h" -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "PyTypeList.h" @@ -116,6 +116,10 @@ protected: // otherwise return converted pixel return m_previous->m_filter->convert(src, x, y, size, pixSize); } + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("GE:FilterBase") +#endif }; diff --git a/source/gameengine/VideoTexture/FilterBlueScreen.cpp b/source/gameengine/VideoTexture/FilterBlueScreen.cpp index 857da12c28d..a25d09e1eee 100644 --- a/source/gameengine/VideoTexture/FilterBlueScreen.cpp +++ b/source/gameengine/VideoTexture/FilterBlueScreen.cpp @@ -28,7 +28,7 @@ * \ingroup bgevideotex */ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> #include "FilterBlueScreen.h" diff --git a/source/gameengine/VideoTexture/FilterColor.cpp b/source/gameengine/VideoTexture/FilterColor.cpp index 26b5303e365..eed84a8580c 100644 --- a/source/gameengine/VideoTexture/FilterColor.cpp +++ b/source/gameengine/VideoTexture/FilterColor.cpp @@ -28,7 +28,7 @@ * \ingroup bgevideotex */ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> #include "FilterColor.h" diff --git a/source/gameengine/VideoTexture/FilterNormal.cpp b/source/gameengine/VideoTexture/FilterNormal.cpp index 78a09f8afac..3a5333710fd 100644 --- a/source/gameengine/VideoTexture/FilterNormal.cpp +++ b/source/gameengine/VideoTexture/FilterNormal.cpp @@ -28,7 +28,7 @@ * \ingroup bgevideotex */ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> #include "FilterNormal.h" diff --git a/source/gameengine/VideoTexture/FilterSource.cpp b/source/gameengine/VideoTexture/FilterSource.cpp index 1fac87f2b04..c8faa1f9f07 100644 --- a/source/gameengine/VideoTexture/FilterSource.cpp +++ b/source/gameengine/VideoTexture/FilterSource.cpp @@ -30,7 +30,7 @@ // implementation -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> #include "FilterSource.h" diff --git a/source/gameengine/VideoTexture/ImageBase.cpp b/source/gameengine/VideoTexture/ImageBase.cpp index 4109981a98c..8be152c7b8e 100644 --- a/source/gameengine/VideoTexture/ImageBase.cpp +++ b/source/gameengine/VideoTexture/ImageBase.cpp @@ -32,12 +32,12 @@ extern "C" { #include "bgl.h" } -#include "GL/glew.h" +#include "glew-mx.h" #include <vector> #include <string.h> -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> #include "FilterBase.h" @@ -713,25 +713,18 @@ static int Image_getbuffer(PyImage *self, Py_buffer *view, int flags) unsigned int * image; int ret; - try - { + try { // can throw in case of resize image = self->m_image->getImage(); } - catch (Exception & exp) - { - // cannot return -1, this creates a crash in Python, for now we will just return an empty buffer + catch (Exception & exp) { exp.report(); - //return -1; - goto error; + return -1; } - if (!image) - { - // same remark, see above - //PyErr_SetString(PyExc_BufferError, "Image buffer is not available"); - //return -1; - goto error; + if (!image) { + PyErr_SetString(PyExc_BufferError, "Image buffer is not available"); + return -1; } if (view == NULL) { @@ -742,17 +735,6 @@ static int Image_getbuffer(PyImage *self, Py_buffer *view, int flags) if (ret >= 0) self->m_image->m_exports++; return ret; - -error: - // Return a empty buffer to avoid a crash in Python 3.1 - // The bug is fixed in Python SVN 77916, as soon as the python revision used by Blender is - // updated, you can simply return -1 and set the error - static char* buf = (char *)""; - ret = PyBuffer_FillInfo(view, (PyObject *)self, buf, 0, 0, flags); - if (ret >= 0) - self->m_image->m_exports++; - return ret; - } static void Image_releaseBuffer(PyImage *self, Py_buffer *buffer) diff --git a/source/gameengine/VideoTexture/ImageBase.h b/source/gameengine/VideoTexture/ImageBase.h index 50dc8c10ec6..f646d145365 100644 --- a/source/gameengine/VideoTexture/ImageBase.h +++ b/source/gameengine/VideoTexture/ImageBase.h @@ -34,7 +34,7 @@ #include "Common.h" #include <vector> -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "PyTypeList.h" diff --git a/source/gameengine/VideoTexture/ImageBuff.cpp b/source/gameengine/VideoTexture/ImageBuff.cpp index 705d9136cbe..77270865b17 100644 --- a/source/gameengine/VideoTexture/ImageBuff.cpp +++ b/source/gameengine/VideoTexture/ImageBuff.cpp @@ -30,7 +30,7 @@ // implementation -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> #include "ImageBuff.h" diff --git a/source/gameengine/VideoTexture/ImageMix.cpp b/source/gameengine/VideoTexture/ImageMix.cpp index dc93bf03423..973be52e0fc 100644 --- a/source/gameengine/VideoTexture/ImageMix.cpp +++ b/source/gameengine/VideoTexture/ImageMix.cpp @@ -31,7 +31,7 @@ // implementation -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> #include "ImageMix.h" diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 8c6dcf45d6f..9086b042537 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -30,13 +30,13 @@ // implementation -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> #include <float.h> #include <math.h> -#include "GL/glew.h" +#include "glew-mx.h" #include "KX_PythonInit.h" #include "DNA_scene_types.h" @@ -75,8 +75,8 @@ ImageRender::ImageRender (KX_Scene *scene, KX_Camera * camera) : m_mirrorHalfWidth(0.f), m_mirrorHalfHeight(0.f) { - // initialize background color - setBackground(0, 0, 255, 255); + // initialize background color to scene background color as default + setBackgroundFromScene(m_scene); // retrieve rendering objects m_engine = KX_GetActiveEngine(); m_rasterizer = m_engine->GetRasterizer(); @@ -90,14 +90,33 @@ ImageRender::~ImageRender (void) m_camera->Release(); } +// get background color +float ImageRender::getBackground (int idx) +{ + return (idx < 0 || idx > 3) ? 0.0f : m_background[idx] * 255.0f; +} // set background color -void ImageRender::setBackground (int red, int green, int blue, int alpha) +void ImageRender::setBackground (float red, float green, float blue, float alpha) +{ + m_background[0] = (red < 0.0f) ? 0.0f : (red > 255.0f) ? 1.0f : red / 255.0f; + m_background[1] = (green < 0.0f) ? 0.0f : (green > 255.0f) ? 1.0f : green / 255.0f; + m_background[2] = (blue < 0.0f) ? 0.0f : (blue > 255.0f) ? 1.0f : blue / 255.0f; + m_background[3] = (alpha < 0.0f) ? 0.0f : (alpha > 255.0f) ? 1.0f : alpha / 255.0f; +} + +// set background color from scene +void ImageRender::setBackgroundFromScene (KX_Scene *scene) { - m_background[0] = (red < 0) ? 0.f : (red > 255) ? 1.f : float(red)/255.f; - m_background[1] = (green < 0) ? 0.f : (green > 255) ? 1.f : float(green)/255.f; - m_background[2] = (blue < 0) ? 0.f : (blue > 255) ? 1.f : float(blue)/255.f; - m_background[3] = (alpha < 0) ? 0.f : (alpha > 255) ? 1.f : float(alpha)/255.f; + if (scene) { + const float *background_color = scene->GetWorldInfo()->getBackColorConverted(); + copy_v3_v3(m_background, background_color); + m_background[3] = 1.0f; + } + else { + const float blue_color[] = {0.0f, 0.0f, 1.0f, 1.0f}; + copy_v4_v4(m_background, blue_color); + } } @@ -200,7 +219,7 @@ void ImageRender::Render() m_canvas->ClearColor(m_background[0], m_background[1], m_background[2], m_background[3]); m_canvas->ClearBuffer(RAS_ICanvas::COLOR_BUFFER|RAS_ICanvas::DEPTH_BUFFER); m_rasterizer->BeginFrame(m_engine->GetClockTime()); - m_engine->SetWorldSettings(m_scene->GetWorldInfo()); + m_scene->GetWorldInfo()->UpdateWorldSettings(); m_rasterizer->SetAuxilaryClientInfo(m_scene); m_rasterizer->DisplayFog(); // matrix calculation, don't apply any of the stereo mode @@ -221,6 +240,8 @@ void ImageRender::Render() float lens = m_camera->GetLens(); float sensor_x = m_camera->GetSensorWidth(); float sensor_y = m_camera->GetSensorHeight(); + float shift_x = m_camera->GetShiftHorizontal(); + float shift_y = m_camera->GetShiftVertical(); bool orthographic = !m_camera->GetCameraData()->m_perspective; float nearfrust = m_camera->GetCameraNear(); float farfrust = m_camera->GetCameraFar(); @@ -241,6 +262,8 @@ void ImageRender::Render() m_camera->GetScale(), aspect_ratio, m_camera->GetSensorFit(), + shift_x, + shift_y, frustrum ); @@ -255,6 +278,8 @@ void ImageRender::Render() sensor_x, sensor_y, RAS_SENSORFIT_AUTO, + shift_x, + shift_y, aspect_ratio, frustrum); @@ -272,9 +297,16 @@ void ImageRender::Render() // restore the stereo mode now that the matrix is computed m_rasterizer->SetStereoMode(stereomode); + if (stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) { + // In QUAD buffer stereo mode, the GE render pass ends with the right eye on the right buffer + // but we need to draw on the left buffer to capture the render + // TODO: implement an explicit function in rasterizer to restore the left buffer. + m_rasterizer->SetEye(RAS_IRasterizer::RAS_STEREO_LEFTEYE); + } + m_scene->CalculateVisibleMeshes(m_rasterizer,m_camera); - m_scene->UpdateAnimations(m_engine->GetFrameTime()); + m_engine->UpdateAnimations(m_scene); m_scene->RenderBuckets(camtrans, m_rasterizer); @@ -344,7 +376,7 @@ static int ImageRender_init(PyObject *pySelf, PyObject *args, PyObject *kwds) // get background color static PyObject *getBackground (PyImage *self, void *closure) { - return Py_BuildValue("[BBBB]", + return Py_BuildValue("[ffff]", getImageRender(self)->getBackground(0), getImageRender(self)->getBackground(1), getImageRender(self)->getBackground(2), @@ -356,20 +388,20 @@ static int setBackground(PyImage *self, PyObject *value, void *closure) { // check validity of parameter if (value == NULL || !PySequence_Check(value) || PySequence_Size(value) != 4 - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2)) - || !PyLong_Check(PySequence_Fast_GET_ITEM(value, 3))) - { - PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 4 integer between 0 and 255"); + || (!PyFloat_Check(PySequence_Fast_GET_ITEM(value, 0)) && !PyLong_Check(PySequence_Fast_GET_ITEM(value, 0))) + || (!PyFloat_Check(PySequence_Fast_GET_ITEM(value, 1)) && !PyLong_Check(PySequence_Fast_GET_ITEM(value, 1))) + || (!PyFloat_Check(PySequence_Fast_GET_ITEM(value, 2)) && !PyLong_Check(PySequence_Fast_GET_ITEM(value, 2))) + || (!PyFloat_Check(PySequence_Fast_GET_ITEM(value, 3)) && !PyLong_Check(PySequence_Fast_GET_ITEM(value, 3)))) { + + PyErr_SetString(PyExc_TypeError, "The value must be a sequence of 4 floats or ints between 0.0 and 255.0"); return -1; } // set background color getImageRender(self)->setBackground( - (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 0))), - (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 1))), - (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 2))), - (unsigned char)(PyLong_AsLong(PySequence_Fast_GET_ITEM(value, 3)))); + PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 0)), + PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 1)), + PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 2)), + PyFloat_AsDouble(PySequence_Fast_GET_ITEM(value, 3))); // success return 0; } @@ -729,7 +761,8 @@ ImageRender::ImageRender (KX_Scene *scene, KX_GameObject *observer, KX_GameObjec m_mirrorX = m_mirrorY.cross(m_mirrorZ); m_render = true; - setBackground(0, 0, 255, 255); + // set mirror background color to scene background color as default + setBackgroundFromScene(m_scene); } diff --git a/source/gameengine/VideoTexture/ImageRender.h b/source/gameengine/VideoTexture/ImageRender.h index 98dceeaafe1..ef55e4dea84 100644 --- a/source/gameengine/VideoTexture/ImageRender.h +++ b/source/gameengine/VideoTexture/ImageRender.h @@ -55,9 +55,9 @@ public: virtual ~ImageRender (void); /// get background color - int getBackground (int idx) { return (idx < 0 || idx > 3) ? 0 : int(m_background[idx]*255.f); } + float getBackground (int idx); /// set background color - void setBackground (int red, int green, int blue, int alpha); + void setBackground (float red, float green, float blue, float alpha); /// clipping distance float getClip (void) { return m_clip; } @@ -100,7 +100,7 @@ protected: void Render(); void SetupRenderFrame(KX_Scene *scene, KX_Camera* cam); void RenderFrame(KX_Scene* scene, KX_Camera* cam); - void SetBackGround(KX_WorldInfo* wi); + void setBackgroundFromScene(KX_Scene *scene); void SetWorldSettings(KX_WorldInfo* wi); }; diff --git a/source/gameengine/VideoTexture/ImageViewport.cpp b/source/gameengine/VideoTexture/ImageViewport.cpp index 789b6006f99..820a019832e 100644 --- a/source/gameengine/VideoTexture/ImageViewport.cpp +++ b/source/gameengine/VideoTexture/ImageViewport.cpp @@ -30,10 +30,10 @@ // implementation -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> -#include "GL/glew.h" +#include "glew-mx.h" #include "KX_PythonInit.h" #include "RAS_ICanvas.h" diff --git a/source/gameengine/VideoTexture/PyTypeList.cpp b/source/gameengine/VideoTexture/PyTypeList.cpp index 588a1257d6a..18f477f6178 100644 --- a/source/gameengine/VideoTexture/PyTypeList.cpp +++ b/source/gameengine/VideoTexture/PyTypeList.cpp @@ -33,7 +33,7 @@ #include <memory> #include <vector> -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" /// destructor PyTypeList::~PyTypeList() diff --git a/source/gameengine/VideoTexture/PyTypeList.h b/source/gameengine/VideoTexture/PyTypeList.h index b36f11ed75a..a8716e72e14 100644 --- a/source/gameengine/VideoTexture/PyTypeList.h +++ b/source/gameengine/VideoTexture/PyTypeList.h @@ -36,7 +36,7 @@ #include <memory> #include <vector> -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" // forward declaration class PyTypeListItem; diff --git a/source/gameengine/VideoTexture/SConscript b/source/gameengine/VideoTexture/SConscript index f7bf6bd93c1..dc708904309 100644 --- a/source/gameengine/VideoTexture/SConscript +++ b/source/gameengine/VideoTexture/SConscript @@ -37,7 +37,8 @@ incs = [ '#intern/ffmpeg', '#intern/guardedalloc', '#intern/string', - '#extern/glew/include', + env['BF_GLEW_INC'], + '#/intern/glew-mx', '#intern/moto/include', '#source/blender/blenkernel', '#source/blender/blenlib', @@ -57,7 +58,9 @@ incs = [ ] incs = ' '.join(incs) -defs = ['GLEW_STATIC'] +defs = [] +defs += env['BF_GL_DEFINITIONS'] + if env['OURPLATFORM'] in ('win32-vc', 'win64-vc','win32-mingw', 'win64-mingw'): if env['BF_DEBUG']: defs.append('_DEBUG') diff --git a/source/gameengine/VideoTexture/Texture.cpp b/source/gameengine/VideoTexture/Texture.cpp index 35a73193a24..cc010f08b17 100644 --- a/source/gameengine/VideoTexture/Texture.cpp +++ b/source/gameengine/VideoTexture/Texture.cpp @@ -30,7 +30,7 @@ // implementation -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> #include "KX_GameObject.h" @@ -41,6 +41,7 @@ #include "DNA_meshdata_types.h" #include "DNA_image_types.h" #include "IMB_imbuf_types.h" +#include "BKE_image.h" #include "MEM_guardedalloc.h" @@ -54,8 +55,11 @@ #include "Exception.h" #include <memory.h> -#include "GL/glew.h" +#include "glew-mx.h" +extern "C" { + #include "IMB_imbuf.h" +} // macro for exception handling and logging #define CATCH_EXCP catch (Exception & exp) \ @@ -75,9 +79,21 @@ void loadTexture(unsigned int texId, unsigned int *texture, short *size, glBindTexture(GL_TEXTURE_2D, texId); if (mipmap) { + int i; + ImBuf *ibuf; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gluBuild2DMipmaps(GL_TEXTURE_2D, GL_RGBA, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, texture); + + ibuf = IMB_allocFromBuffer(texture, NULL, size[0], size[1]); + + IMB_makemipmap(ibuf, true); + + for (i = 0; i < ibuf->miptot; i++) { + ImBuf *mip = IMB_getmipmap(ibuf, i); + + glTexImage2D(GL_TEXTURE_2D, i, GL_RGBA, mip->x, mip->y, 0, GL_RGBA, GL_UNSIGNED_BYTE, mip->rect); + } + IMB_freeImBuf(ibuf); } else { @@ -158,11 +174,11 @@ static PyObject *Texture_new(PyTypeObject *type, PyObject *args, PyObject *kwds) // initialize object structure self->m_actTex = 0; self->m_orgSaved = false; + self->m_imgBuf = NULL; self->m_imgTexture = NULL; self->m_matTexture = NULL; self->m_mipmap = false; - self->m_scaledImg = NULL; - self->m_scaledImgSize = 0; + self->m_scaledImBuf = NULL; self->m_source = NULL; self->m_lastClock = 0.0; // return allocated object @@ -184,7 +200,7 @@ static void Texture_dealloc(Texture *self) PyObject *ret = Texture_close(self); Py_DECREF(ret); // release scaled image buffer - delete [] self->m_scaledImg; + IMB_freeImBuf(self->m_scaledImBuf); // release object Py_TYPE((PyObject *)self)->tp_free((PyObject *)self); } @@ -282,7 +298,11 @@ PyObject *Texture_close(Texture * self) if (self->m_useMatTexture) self->m_matTexture->swapTexture(self->m_orgTex); else + { self->m_imgTexture->bindcode = self->m_orgTex; + BKE_image_release_ibuf(self->m_imgTexture, self->m_imgBuf, NULL); + self->m_imgBuf = NULL; + } // drop actual texture if (self->m_actTex != 0) { @@ -331,6 +351,12 @@ static PyObject *Texture_refresh(Texture *self, PyObject *args) self->m_orgTex = self->m_matTexture->swapTexture(self->m_actTex); else { + // Swapping will work only if the GPU has already loaded the image. + // If not, it will delete and overwrite our texture on next render. + // To avoid that, we acquire the image buffer now. + // WARNING: GPU has a ImageUser to pass, we don't. Using NULL + // works on image file, not necessarily on other type of image. + self->m_imgBuf = BKE_image_acquire_ibuf(self->m_imgTexture, NULL, NULL); self->m_orgTex = self->m_imgTexture->bindcode; self->m_imgTexture->bindcode = self->m_actTex; } @@ -358,20 +384,12 @@ static PyObject *Texture_refresh(Texture *self, PyObject *args) // scale texture if needed if (size[0] != orgSize[0] || size[1] != orgSize[1]) { - // if scaled image buffer is smaller than needed - if (self->m_scaledImgSize < (unsigned int)(size[0] * size[1])) - { - // new size - self->m_scaledImgSize = size[0] * size[1]; - // allocate scaling image - delete [] self->m_scaledImg; - self->m_scaledImg = new unsigned int[self->m_scaledImgSize]; - } - // scale texture - gluScaleImage(GL_RGBA, orgSize[0], orgSize[1], GL_UNSIGNED_BYTE, texture, - size[0], size[1], GL_UNSIGNED_BYTE, self->m_scaledImg); + IMB_freeImBuf(self->m_scaledImBuf); + self->m_scaledImBuf = IMB_allocFromBuffer(texture, NULL, orgSize[0], orgSize[1]); + IMB_scaleImBuf(self->m_scaledImBuf, size[0], size[1]); + // use scaled image instead original - texture = self->m_scaledImg; + texture = self->m_scaledImBuf->rect; } // load texture for rendering loadTexture(self->m_actTex, texture, size, self->m_mipmap); diff --git a/source/gameengine/VideoTexture/Texture.h b/source/gameengine/VideoTexture/Texture.h index c85b1228864..dc38b4181bb 100644 --- a/source/gameengine/VideoTexture/Texture.h +++ b/source/gameengine/VideoTexture/Texture.h @@ -31,7 +31,7 @@ #ifndef __TEXTURE_H__ #define __TEXTURE_H__ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include <structmember.h> #include "DNA_image_types.h" @@ -43,6 +43,8 @@ #include "Exception.h" +struct ImBuf; + // type Texture declaration struct Texture { @@ -58,6 +60,8 @@ struct Texture // original texture saved bool m_orgSaved; + // kernel image buffer, to make sure the image is loaded before we swap the bindcode + struct ImBuf *m_imgBuf; // texture image for game materials Image * m_imgTexture; // texture for blender materials @@ -67,9 +71,7 @@ struct Texture bool m_mipmap; // scaled image buffer - unsigned int * m_scaledImg; - // scaled image buffer size - unsigned int m_scaledImgSize; + ImBuf * m_scaledImBuf; // last refresh double m_lastClock; diff --git a/source/gameengine/VideoTexture/VideoBase.h b/source/gameengine/VideoTexture/VideoBase.h index 51f025909fd..6f35c474300 100644 --- a/source/gameengine/VideoTexture/VideoBase.h +++ b/source/gameengine/VideoTexture/VideoBase.h @@ -32,7 +32,7 @@ #define __VIDEOBASE_H__ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "ImageBase.h" diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.cpp b/source/gameengine/VideoTexture/VideoFFmpeg.cpp index edf3c58bcbe..ffe06cff100 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.cpp +++ b/source/gameengine/VideoTexture/VideoFFmpeg.cpp @@ -86,6 +86,13 @@ VideoFFmpeg::~VideoFFmpeg () { } +void VideoFFmpeg::refresh(void) +{ + // a fixed image will not refresh because it is loaded only once at creation + if (m_isImage) + return; + m_avail = false; +} // release components bool VideoFFmpeg::release() @@ -1016,19 +1023,14 @@ AVFrame *VideoFFmpeg::grabFrame(long position) { if (packet.stream_index == m_videoStream) { - if (m_isImage) - { - // If we're an image, we're probably not going to be here often, - // so we don't want to deal with delayed frames from threading. - // There might be a better way to handle this, but I'll leave that - // for people more knowledgeable with ffmpeg than myself. We don't - // need threading for a single image anyways. - m_codecCtx->thread_count = 1; - } + AVFrame *input = m_frame; + short counter = 0; - avcodec_decode_video2(m_codecCtx, - m_frame, &frameFinished, - &packet); + /* While the data is not read properly (png, tiffs, etc formats may need several pass)*/ + while ((input->data[0] == 0 && input->data[1] == 0 && input->data[2] == 0 && input->data[3] == 0) && counter < 10) { + avcodec_decode_video2(m_codecCtx, m_frame, &frameFinished, &packet); + counter++; + } // remember dts to compute exact frame number dts = packet.dts; diff --git a/source/gameengine/VideoTexture/VideoFFmpeg.h b/source/gameengine/VideoTexture/VideoFFmpeg.h index 4a948fe61de..0a49a0b19bb 100644 --- a/source/gameengine/VideoTexture/VideoFFmpeg.h +++ b/source/gameengine/VideoTexture/VideoFFmpeg.h @@ -85,7 +85,8 @@ public: /// release video source virtual bool release (void); - + /// overwrite base refresh to handle fixed image + virtual void refresh(void); /// play video virtual bool play (void); /// pause video diff --git a/source/gameengine/VideoTexture/blendVideoTex.cpp b/source/gameengine/VideoTexture/blendVideoTex.cpp index ab6dca0958f..30a8107b558 100644 --- a/source/gameengine/VideoTexture/blendVideoTex.cpp +++ b/source/gameengine/VideoTexture/blendVideoTex.cpp @@ -28,7 +28,7 @@ * \ingroup bgevideotex */ -#include "PyObjectPlus.h" +#include "EXP_PyObjectPlus.h" #include "KX_PythonInit.h" @@ -50,6 +50,12 @@ #include "Exception.h" +// access to IMB_BLEND_* constants +extern "C" +{ +#include "IMB_imbuf.h" +}; + // get material id static PyObject *getMaterialID (PyObject *self, PyObject *args) @@ -157,10 +163,14 @@ static void registerAllTypes(void) pyFilterTypes.add(&FilterBGR24Type, "FilterBGR24"); } +PyDoc_STRVAR(VideoTexture_module_documentation, +"Module that allows to play video files on textures in GameBlender." +); + static struct PyModuleDef VideoTexture_module_def = { - {}, /* m_base */ + PyModuleDef_HEAD_INIT, "VideoTexture", /* m_name */ - "Module that allows to play video files on textures in GameBlender.", /* m_doc */ + VideoTexture_module_documentation, /* m_doc */ 0, /* m_size */ moduleMethods, /* m_methods */ 0, /* m_reload */ @@ -169,7 +179,7 @@ static struct PyModuleDef VideoTexture_module_def = { 0, /* m_free */ }; -PyObject *initVideoTexture(void) +PyMODINIT_FUNC initVideoTexturePythonBinding(void) { PyObject *m; @@ -187,20 +197,9 @@ PyObject *initVideoTexture(void) if (PyType_Ready(&TextureType) < 0) return NULL; - /* 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(); - - m = PyModule_Create(&VideoTexture_module_def); - PyDict_SetItemString(PySys_GetObject("modules"), VideoTexture_module_def.m_name, m); - } - + m = PyModule_Create(&VideoTexture_module_def); + PyDict_SetItemString(PySys_GetObject("modules"), VideoTexture_module_def.m_name, m); + if (m == NULL) return NULL; @@ -215,7 +214,36 @@ PyObject *initVideoTexture(void) PyModule_AddIntConstant(m, "SOURCE_READY", SourceReady); PyModule_AddIntConstant(m, "SOURCE_PLAYING", SourcePlaying); PyModule_AddIntConstant(m, "SOURCE_STOPPED", SourceStopped); - + + PyModule_AddIntConstant(m, "IMB_BLEND_MIX", IMB_BLEND_MIX); + PyModule_AddIntConstant(m, "IMB_BLEND_ADD", IMB_BLEND_ADD); + PyModule_AddIntConstant(m, "IMB_BLEND_SUB", IMB_BLEND_SUB); + PyModule_AddIntConstant(m, "IMB_BLEND_MUL", IMB_BLEND_MUL); + PyModule_AddIntConstant(m, "IMB_BLEND_LIGHTEN", IMB_BLEND_LIGHTEN); + PyModule_AddIntConstant(m, "IMB_BLEND_DARKEN", IMB_BLEND_DARKEN); + PyModule_AddIntConstant(m, "IMB_BLEND_ERASE_ALPHA", IMB_BLEND_ERASE_ALPHA); + PyModule_AddIntConstant(m, "IMB_BLEND_ADD_ALPHA", IMB_BLEND_ADD_ALPHA); + PyModule_AddIntConstant(m, "IMB_BLEND_OVERLAY", IMB_BLEND_OVERLAY); + PyModule_AddIntConstant(m, "IMB_BLEND_HARDLIGHT", IMB_BLEND_HARDLIGHT); + PyModule_AddIntConstant(m, "IMB_BLEND_COLORBURN", IMB_BLEND_COLORBURN); + PyModule_AddIntConstant(m, "IMB_BLEND_LINEARBURN", IMB_BLEND_LINEARBURN); + PyModule_AddIntConstant(m, "IMB_BLEND_COLORDODGE", IMB_BLEND_COLORDODGE); + PyModule_AddIntConstant(m, "IMB_BLEND_SCREEN", IMB_BLEND_SCREEN); + PyModule_AddIntConstant(m, "IMB_BLEND_SOFTLIGHT", IMB_BLEND_SOFTLIGHT); + PyModule_AddIntConstant(m, "IMB_BLEND_PINLIGHT", IMB_BLEND_PINLIGHT); + PyModule_AddIntConstant(m, "IMB_BLEND_VIVIDLIGHT", IMB_BLEND_VIVIDLIGHT); + PyModule_AddIntConstant(m, "IMB_BLEND_LINEARLIGHT", IMB_BLEND_LINEARLIGHT); + PyModule_AddIntConstant(m, "IMB_BLEND_DIFFERENCE", IMB_BLEND_DIFFERENCE); + PyModule_AddIntConstant(m, "IMB_BLEND_EXCLUSION", IMB_BLEND_EXCLUSION); + PyModule_AddIntConstant(m, "IMB_BLEND_HUE", IMB_BLEND_HUE); + PyModule_AddIntConstant(m, "IMB_BLEND_SATURATION", IMB_BLEND_SATURATION); + PyModule_AddIntConstant(m, "IMB_BLEND_LUMINOSITY", IMB_BLEND_LUMINOSITY); + PyModule_AddIntConstant(m, "IMB_BLEND_COLOR", IMB_BLEND_COLOR); + + PyModule_AddIntConstant(m, "IMB_BLEND_COPY", IMB_BLEND_COPY); + PyModule_AddIntConstant(m, "IMB_BLEND_COPY_RGB", IMB_BLEND_COPY_RGB); + PyModule_AddIntConstant(m, "IMB_BLEND_COPY_ALPHA", IMB_BLEND_COPY_ALPHA); + // init last error description Exception::m_lastError = ""; |