3 * ***** BEGIN GPL LICENSE BLOCK *****
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
20 * All rights reserved.
22 * The Original Code is: all of this file.
24 * Contributor(s): none yet.
26 * ***** END GPL LICENSE BLOCK *****
29 #if defined(WIN32) && !defined(FREE_WINDOWS)
30 #pragma warning (disable:4786) // suppress stl-MSVC debug info warning
34 #include "KX_GameObject.h"
35 #include "KX_BlenderSceneConverter.h"
36 #include "KX_IpoConvert.h"
37 #include "RAS_MeshObject.h"
38 #include "KX_PhysicsEngineEnums.h"
39 #include "PHY_IPhysicsEnvironment.h"
40 #include "KX_KetsjiEngine.h"
41 #include "KX_IPhysicsController.h"
42 #include "BL_Material.h"
43 #include "KX_BlenderMaterial.h"
44 #include "KX_PolygonMaterial.h"
47 #include "SYS_System.h"
49 #include "DummyPhysicsEnvironment.h"
51 #include "KX_ConvertPhysicsObject.h"
54 #include "CcdPhysicsEnvironment.h"
57 #include "KX_BlenderSceneConverter.h"
58 #include "KX_BlenderScalarInterpolator.h"
59 #include "BL_BlenderDataConversion.h"
60 #include "BlenderWorldInfo.h"
63 /* This little block needed for linking to Blender... */
65 #include "BLI_winstuff.h"
68 /* This list includes only data type definitions */
69 #include "DNA_scene_types.h"
70 #include "DNA_world_types.h"
77 #include "DNA_object_types.h"
78 #include "DNA_curve_types.h"
79 #include "DNA_mesh_types.h"
80 #include "DNA_material_types.h"
81 #include "BLI_blenlib.h"
82 #include "MEM_guardedalloc.h"
83 #include "BKE_global.h"
84 #include "BKE_animsys.h"
85 #include "BKE_library.h"
86 #include "BKE_material.h" // copy_material
87 #include "BKE_mesh.h" // copy_mesh
88 #include "DNA_space_types.h"
89 #include "DNA_anim_types.h"
90 #include "RNA_define.h"
91 #include "../../blender/editors/include/ED_keyframing.h"
94 /* Only for dynamic loading and merging */
95 #include "RAS_BucketManager.h" // XXX cant stay
96 #include "KX_BlenderSceneConverter.h"
97 #include "BL_BlenderDataConversion.h"
98 #include "KX_MeshProxy.h"
99 #include "RAS_MeshObject.h"
101 #include "BKE_context.h"
102 #include "BLO_readfile.h"
103 #include "BKE_idcode.h"
104 #include "BKE_report.h"
105 #include "DNA_space_types.h"
106 #include "DNA_windowmanager_types.h" /* report api */
107 #include "../../blender/blenlib/BLI_linklist.h"
110 KX_BlenderSceneConverter::KX_BlenderSceneConverter(
112 class KX_KetsjiEngine* engine
115 /*m_maggie_dyn(NULL),*/
116 m_ketsjiEngine(engine),
117 m_alwaysUseExpandFraming(false),
121 tag_main(maggie, 0); /* avoid re-tagging later on */
126 KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
128 // clears meshes, and hashmaps from blender to gameengine data
133 int numAdtLists = m_map_blender_to_gameAdtList.size();
134 for (i=0; i<numAdtLists; i++) {
135 BL_InterpolatorList *adtList= *m_map_blender_to_gameAdtList.at(i);
140 vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itw = m_worldinfos.begin();
141 while (itw != m_worldinfos.end()) {
142 delete (*itw).second;
146 vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
147 while (itp != m_polymaterials.end()) {
148 delete (*itp).second;
152 // delete after RAS_IPolyMaterial
153 vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin();
154 while (itmat != m_materials.end()) {
155 delete (*itmat).second;
160 vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin();
161 while (itm != m_meshobjects.end()) {
162 delete (*itm).second;
167 KX_ClearBulletSharedShapes();
170 /* free any data that was dynamically loaded */
171 for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
176 m_DynamicMaggie.clear();
179 void KX_BlenderSceneConverter::SetNewFileName(const STR_String& filename)
181 m_newfilename = filename;
186 bool KX_BlenderSceneConverter::TryAndLoadNewFile()
195 // if not, clear the newfilename
204 Scene *KX_BlenderSceneConverter::GetBlenderSceneForName(const STR_String& name)
209 * Find the specified scene by name, or the first
210 * scene if nothing matches (shouldn't happen).
212 if((sce= (Scene *)BLI_findstring(&m_maggie->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
215 for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
218 if((sce= (Scene *)BLI_findstring(&main->scene, name.ReadPtr(), offsetof(ID, name) + 2)))
222 return (Scene*)m_maggie->scene.first;
225 #include "KX_PythonInit.h"
229 #include "LinearMath/btIDebugDraw.h"
232 struct BlenderDebugDraw : public btIDebugDraw
234 BlenderDebugDraw () :
241 virtual void drawLine(const btVector3& from,const btVector3& to,const btVector3& color)
245 MT_Vector3 kxfrom(from[0],from[1],from[2]);
246 MT_Vector3 kxto(to[0],to[1],to[2]);
247 MT_Vector3 kxcolor(color[0],color[1],color[2]);
249 KX_RasterizerDrawDebugLine(kxfrom,kxto,kxcolor);
253 virtual void reportErrorWarning(const char* warningString)
258 virtual void drawContactPoint(const btVector3& PointOnB,const btVector3& normalOnB,float distance,int lifeTime,const btVector3& color)
263 virtual void setDebugMode(int debugMode)
265 m_debugMode = debugMode;
267 virtual int getDebugMode() const
271 ///todo: find out if Blender can do this
272 virtual void draw3dText(const btVector3& location,const char* textString)
281 void KX_BlenderSceneConverter::ConvertScene(class KX_Scene* destinationscene,
282 class RAS_IRenderTools* rendertools,
283 class RAS_ICanvas* canvas)
285 //find out which physics engine
286 Scene *blenderscene = destinationscene->GetBlenderScene();
288 e_PhysicsEngine physics_engine = UseBullet;
289 bool useDbvtCulling = false;
290 // hook for registration function during conversion.
291 m_currentScene = destinationscene;
292 destinationscene->SetSceneConverter(this);
293 SG_SetActiveStage(SG_STAGE_CONVERTER);
298 switch (blenderscene->gm.physicsEngine)
302 physics_engine = UseBullet;
303 useDbvtCulling = (blenderscene->gm.mode & WO_DBVT_CULLING) != 0;
309 physics_engine = UseODE;
314 physics_engine = UseDynamo;
319 physics_engine = UseSumo;
324 physics_engine = UseNone;
329 switch (physics_engine)
334 CcdPhysicsEnvironment* ccdPhysEnv = new CcdPhysicsEnvironment(useDbvtCulling);
335 ccdPhysEnv->setDebugDrawer(new BlenderDebugDraw());
336 ccdPhysEnv->setDeactivationLinearTreshold(0.8f); // default, can be overridden by Python
337 ccdPhysEnv->setDeactivationAngularTreshold(1.0f); // default, can be overridden by Python
339 SYS_SystemHandle syshandle = SYS_GetSystem(); /*unused*/
340 int visualizePhysics = SYS_GetCommandLineInt(syshandle,"show_physics",0);
341 if (visualizePhysics)
342 ccdPhysEnv->setDebugMode(btIDebugDraw::DBG_DrawWireframe|btIDebugDraw::DBG_DrawAabb|btIDebugDraw::DBG_DrawContactPoints|btIDebugDraw::DBG_DrawText|btIDebugDraw::DBG_DrawConstraintLimits|btIDebugDraw::DBG_DrawConstraints);
344 //todo: get a button in blender ?
345 //disable / enable debug drawing (contact points, aabb's etc)
346 //ccdPhysEnv->setDebugMode(1);
347 destinationscene->SetPhysicsEnvironment(ccdPhysEnv);
357 physics_engine = UseNone;
358 destinationscene ->SetPhysicsEnvironment(new DummyPhysicsEnvironment());
362 BL_ConvertBlenderObjects(m_maggie,
369 m_alwaysUseExpandFraming
372 //These lookup are not needed during game
373 m_map_blender_to_gameactuator.clear();
374 m_map_blender_to_gamecontroller.clear();
375 m_map_blender_to_gameobject.clear();
377 //Clearing this lookup table has the effect of disabling the cache of meshes
378 //between scenes, even if they are shared in the blend file.
379 //This cache mecanism is buggy so I leave it disable and the memory leak
380 //that would result from this is fixed in RemoveScene()
381 m_map_mesh_to_gamemesh.clear();
384 // This function removes all entities stored in the converter for that scene
385 // It should be used instead of direct delete scene
386 // Note that there was some provision for sharing entities (meshes...) between
387 // scenes but that is now disabled so all scene will have their own copy
388 // and we can delete them here. If the sharing is reactivated, change this code too..
389 // (see KX_BlenderSceneConverter::ConvertScene)
390 void KX_BlenderSceneConverter::RemoveScene(KX_Scene *scene)
393 // delete the scene first as it will stop the use of entities
395 // delete the entities of this scene
396 vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
397 size = m_worldinfos.size();
398 for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
399 if ((*worldit).first == scene) {
400 delete (*worldit).second;
401 *worldit = m_worldinfos.back();
402 m_worldinfos.pop_back();
410 vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
411 size = m_polymaterials.size();
412 for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
413 if ((*polymit).first == scene) {
414 delete (*polymit).second;
415 *polymit = m_polymaterials.back();
416 m_polymaterials.pop_back();
424 vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
425 size = m_materials.size();
426 for (i=0, matit=m_materials.begin(); i<size; ) {
427 if ((*matit).first == scene) {
428 delete (*matit).second;
429 *matit = m_materials.back();
430 m_materials.pop_back();
438 vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
439 size = m_meshobjects.size();
440 for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
441 if ((*meshit).first == scene) {
442 delete (*meshit).second;
443 *meshit = m_meshobjects.back();
444 m_meshobjects.pop_back();
453 // use blender materials
454 void KX_BlenderSceneConverter::SetMaterials(bool val)
457 m_useglslmat = false;
460 void KX_BlenderSceneConverter::SetGLSLMaterials(bool val)
466 bool KX_BlenderSceneConverter::GetMaterials()
471 bool KX_BlenderSceneConverter::GetGLSLMaterials()
476 void KX_BlenderSceneConverter::RegisterBlenderMaterial(BL_Material *mat)
478 m_materials.push_back(pair<KX_Scene*,BL_Material *>(m_currentScene,mat));
483 void KX_BlenderSceneConverter::SetAlwaysUseExpandFraming(
486 m_alwaysUseExpandFraming= to_what;
491 void KX_BlenderSceneConverter::RegisterGameObject(
492 KX_GameObject *gameobject,
493 struct Object *for_blenderobject)
495 /* only maintained while converting, freed during game runtime */
496 m_map_blender_to_gameobject.insert(CHashedPtr(for_blenderobject),gameobject);
499 /* only need to run this during conversion since
500 * m_map_blender_to_gameobject is freed after conversion */
501 void KX_BlenderSceneConverter::UnregisterGameObject(
502 KX_GameObject *gameobject)
504 struct Object *bobp= gameobject->GetBlenderObject();
506 CHashedPtr bptr(bobp);
507 KX_GameObject **gobp= m_map_blender_to_gameobject[bptr];
508 if (gobp && *gobp == gameobject)
510 // also maintain m_map_blender_to_gameobject if the gameobject
511 // being removed is matching the blender object
512 m_map_blender_to_gameobject.remove(bptr);
517 KX_GameObject *KX_BlenderSceneConverter::FindGameObject(
518 struct Object *for_blenderobject)
520 KX_GameObject **obp= m_map_blender_to_gameobject[CHashedPtr(for_blenderobject)];
522 return obp?*obp:NULL;
525 void KX_BlenderSceneConverter::RegisterGameMesh(
526 RAS_MeshObject *gamemesh,
527 struct Mesh *for_blendermesh)
529 if(for_blendermesh) { /* dynamically loaded meshes we dont want to keep lookups for */
530 m_map_mesh_to_gamemesh.insert(CHashedPtr(for_blendermesh),gamemesh);
532 m_meshobjects.push_back(pair<KX_Scene*,RAS_MeshObject*>(m_currentScene,gamemesh));
537 RAS_MeshObject *KX_BlenderSceneConverter::FindGameMesh(
538 struct Mesh *for_blendermesh/*,
539 unsigned int onlayer*/)
541 RAS_MeshObject** meshp = m_map_mesh_to_gamemesh[CHashedPtr(for_blendermesh)];
543 if (meshp/* && onlayer==(*meshp)->GetLightLayer()*/) {
555 void KX_BlenderSceneConverter::RegisterPolyMaterial(RAS_IPolyMaterial *polymat)
557 m_polymaterials.push_back(pair<KX_Scene*,RAS_IPolyMaterial*>(m_currentScene,polymat));
562 void KX_BlenderSceneConverter::RegisterInterpolatorList(
563 BL_InterpolatorList *adtList,
564 struct AnimData *for_adt)
566 m_map_blender_to_gameAdtList.insert(CHashedPtr(for_adt), adtList);
571 BL_InterpolatorList *KX_BlenderSceneConverter::FindInterpolatorList(
572 struct AnimData *for_adt)
574 BL_InterpolatorList **listp = m_map_blender_to_gameAdtList[CHashedPtr(for_adt)];
576 return listp?*listp:NULL;
581 void KX_BlenderSceneConverter::RegisterGameActuator(
583 struct bActuator *for_actuator)
585 m_map_blender_to_gameactuator.insert(CHashedPtr(for_actuator), act);
590 SCA_IActuator *KX_BlenderSceneConverter::FindGameActuator(
591 struct bActuator *for_actuator)
593 SCA_IActuator **actp = m_map_blender_to_gameactuator[CHashedPtr(for_actuator)];
595 return actp?*actp:NULL;
600 void KX_BlenderSceneConverter::RegisterGameController(
601 SCA_IController *cont,
602 struct bController *for_controller)
604 m_map_blender_to_gamecontroller.insert(CHashedPtr(for_controller), cont);
609 SCA_IController *KX_BlenderSceneConverter::FindGameController(
610 struct bController *for_controller)
612 SCA_IController **contp = m_map_blender_to_gamecontroller[CHashedPtr(for_controller)];
614 return contp?*contp:NULL;
619 void KX_BlenderSceneConverter::RegisterWorldInfo(
620 KX_WorldInfo *worldinfo)
622 m_worldinfos.push_back(pair<KX_Scene*,KX_WorldInfo*>(m_currentScene,worldinfo));
628 void mat3_to_compatible_eul( float *eul, float *oldrot,float mat[][3]);
631 void KX_BlenderSceneConverter::ResetPhysicsObjectsAnimationIpo(bool clearIpo)
634 KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
635 int numScenes = scenes->size();
637 for (i=0;i<numScenes;i++)
639 KX_Scene* scene = scenes->at(i);
640 //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
641 CListValue* parentList = scene->GetRootParentList();
642 int numObjects = parentList->GetCount();
644 for (g=0;g<numObjects;g++)
646 KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
647 if (gameObj->IsDynamic())
649 //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
651 Object* blenderObject = gameObj->GetBlenderObject();
655 //erase existing ipo's
656 Ipo* ipo = blenderObject->ipo;//findIpoForName(blenderObject->id.name+2);
658 { //clear the curve data
659 if (clearIpo){//rcruiz
663 for( icu1 = (IpoCurve*)ipo->curve.first; icu1; ) {
665 IpoCurve* tmpicu = icu1;
669 for( bezt = tmpicu->bezt, i = 0; i < tmpicu->totvert; i++, bezt++){
670 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]);
676 BLI_remlink( &( blenderObject->ipo->curve ), tmpicu );
678 MEM_freeN( tmpicu->bezt );
680 localDel_ipoCurve( tmpicu );
684 { ipo = NULL; // XXX add_ipo(blenderObject->id.name+2, ID_OB);
685 blenderObject->ipo = ipo;
701 void KX_BlenderSceneConverter::resetNoneDynamicObjectToIpo(){
703 if (addInitFromFrame){
704 KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
705 int numScenes = scenes->size();
707 KX_Scene* scene = scenes->at(0);
708 CListValue* parentList = scene->GetRootParentList();
709 for (int ix=0;ix<parentList->GetCount();ix++){
710 KX_GameObject* gameobj = (KX_GameObject*)parentList->GetValue(ix);
711 if (!gameobj->IsDynamic()){
712 Object* blenderobject = gameobj->GetBlenderObject();
715 if (blenderobject->type==OB_ARMATURE)
718 mat4_to_eul(eu,blenderobject->obmat);
719 MT_Point3 pos = MT_Point3(
720 blenderobject->obmat[3][0],
721 blenderobject->obmat[3][1],
722 blenderobject->obmat[3][2]
724 MT_Vector3 eulxyz = MT_Vector3(
729 MT_Vector3 scale = MT_Vector3(
730 blenderobject->size[0],
731 blenderobject->size[1],
732 blenderobject->size[2]
734 gameobj->NodeSetLocalPosition(pos);
735 gameobj->NodeSetLocalOrientation(MT_Matrix3x3(eulxyz));
736 gameobj->NodeSetLocalScale(scale);
737 gameobj->NodeUpdateGS(0);
745 ///this generates ipo curves for position, rotation, allowing to use game physics in animation
746 void KX_BlenderSceneConverter::WritePhysicsObjectToAnimationIpo(int frameNumber)
749 KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
750 int numScenes = scenes->size();
752 for (i=0;i<numScenes;i++)
754 KX_Scene* scene = scenes->at(i);
755 //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
756 CListValue* parentList = scene->GetObjectList();
757 int numObjects = parentList->GetCount();
759 for (g=0;g<numObjects;g++)
761 KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
762 Object* blenderObject = gameObj->GetBlenderObject();
763 if (blenderObject && blenderObject->parent==NULL && gameObj->GetPhysicsController() != NULL)
765 //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
767 if(blenderObject->adt==NULL)
768 BKE_id_add_animdata(&blenderObject->id);
770 if (blenderObject->adt)
772 const MT_Point3& position = gameObj->NodeGetWorldPosition();
773 //const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
774 const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
776 position.getValue(blenderObject->loc);
779 for (int r=0;r<3;r++)
780 for (int c=0;c<3;c++)
781 tmat[r][c] = orn[c][r];
783 mat3_to_compatible_eul(blenderObject->rot, blenderObject->rot, tmat);
785 insert_keyframe(&blenderObject->id, NULL, NULL, "location", -1, frameNumber, INSERTKEY_FAST);
786 insert_keyframe(&blenderObject->id, NULL, NULL, "rotation_euler", -1, frameNumber, INSERTKEY_FAST);
789 const MT_Point3& position = gameObj->NodeGetWorldPosition();
790 //const MT_Vector3& scale = gameObj->NodeGetWorldScaling();
791 const MT_Matrix3x3& orn = gameObj->NodeGetWorldOrientation();
793 float eulerAngles[3];
794 float eulerAnglesOld[3] = {0.0f, 0.0f, 0.0f};
798 Ipo* ipo = blenderObject->ipo;
800 //create the curves, if not existing, set linear if new
802 IpoCurve *icu_lx = findIpoCurve((IpoCurve *)ipo->curve.first,"LocX");
804 icu_lx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_X, 1);
805 if(icu_lx) icu_lx->ipo = IPO_LIN;
807 IpoCurve *icu_ly = findIpoCurve((IpoCurve *)ipo->curve.first,"LocY");
809 icu_ly = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Y, 1);
810 if(icu_ly) icu_ly->ipo = IPO_LIN;
812 IpoCurve *icu_lz = findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ");
814 icu_lz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_LOC_Z, 1);
815 if(icu_lz) icu_lz->ipo = IPO_LIN;
817 IpoCurve *icu_rx = findIpoCurve((IpoCurve *)ipo->curve.first,"RotX");
819 icu_rx = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_X, 1);
820 if(icu_rx) icu_rx->ipo = IPO_LIN;
822 IpoCurve *icu_ry = findIpoCurve((IpoCurve *)ipo->curve.first,"RotY");
824 icu_ry = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Y, 1);
825 if(icu_ry) icu_ry->ipo = IPO_LIN;
827 IpoCurve *icu_rz = findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ");
829 icu_rz = verify_ipocurve(&blenderObject->id, ipo->blocktype, NULL, NULL, NULL, OB_ROT_Z, 1);
830 if(icu_rz) icu_rz->ipo = IPO_LIN;
833 if(icu_rx) eulerAnglesOld[0]= eval_icu( icu_rx, frameNumber - 1 ) / ((180 / 3.14159265f) / 10);
834 if(icu_ry) eulerAnglesOld[1]= eval_icu( icu_ry, frameNumber - 1 ) / ((180 / 3.14159265f) / 10);
835 if(icu_rz) eulerAnglesOld[2]= eval_icu( icu_rz, frameNumber - 1 ) / ((180 / 3.14159265f) / 10);
837 // orn.getValue((float *)tmat); // uses the wrong ordering, cant use this
838 for (int r=0;r<3;r++)
839 for (int c=0;c<3;c++)
840 tmat[r][c] = orn[c][r];
842 // mat3_to_eul( eulerAngles,tmat); // better to use Mat3ToCompatibleEul
843 mat3_to_compatible_eul( eulerAngles, eulerAnglesOld,tmat);
846 for(int x = 0; x < 3; x++)
847 eulerAngles[x] *= (float) ((180 / 3.14159265f) / 10.0);
849 //fill the curves with data
850 if (icu_lx) insert_vert_icu(icu_lx, frameNumber, position.x(), 1);
851 if (icu_ly) insert_vert_icu(icu_ly, frameNumber, position.y(), 1);
852 if (icu_lz) insert_vert_icu(icu_lz, frameNumber, position.z(), 1);
853 if (icu_rx) insert_vert_icu(icu_rx, frameNumber, eulerAngles[0], 1);
854 if (icu_ry) insert_vert_icu(icu_ry, frameNumber, eulerAngles[1], 1);
855 if (icu_rz) insert_vert_icu(icu_rz, frameNumber, eulerAngles[2], 1);
857 // Handles are corrected at the end, testhandles_ipocurve isnt needed yet
866 void KX_BlenderSceneConverter::TestHandlesPhysicsObjectToAnimationIpo()
869 KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
870 int numScenes = scenes->size();
872 for (i=0;i<numScenes;i++)
874 KX_Scene* scene = scenes->at(i);
875 //PHY_IPhysicsEnvironment* physEnv = scene->GetPhysicsEnvironment();
876 CListValue* parentList = scene->GetRootParentList();
877 int numObjects = parentList->GetCount();
879 for (g=0;g<numObjects;g++)
881 KX_GameObject* gameObj = (KX_GameObject*)parentList->GetValue(g);
882 if (gameObj->IsDynamic())
884 //KX_IPhysicsController* physCtrl = gameObj->GetPhysicsController();
886 Object* blenderObject = gameObj->GetBlenderObject();
887 if (blenderObject && blenderObject->ipo)
891 Ipo* ipo = blenderObject->ipo;
893 //create the curves, if not existing
894 //testhandles_ipocurve checks for NULL
895 testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocX"));
896 testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocY"));
897 testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"LocZ"));
898 testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotX"));
899 testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotY"));
900 testhandles_ipocurve(findIpoCurve((IpoCurve *)ipo->curve.first,"RotZ"));
914 #ifndef DISABLE_PYTHON
915 PyObject *KX_BlenderSceneConverter::GetPyNamespace()
917 return m_ketsjiEngine->GetPyNamespace();
921 vector<Main*> &KX_BlenderSceneConverter::GetMainDynamic()
923 return m_DynamicMaggie;
926 Main* KX_BlenderSceneConverter::GetMainDynamicPath(const char *path)
928 for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++)
929 if(strcmp((*it)->name, path)==0)
935 bool KX_BlenderSceneConverter::LinkBlendFileMemory(void *data, int length, const char *path, char *group, KX_Scene *scene_merge, char **err_str)
937 BlendHandle *bpy_openlib = BLO_blendhandle_from_memory(data, length);
939 // Error checking is done in LinkBlendFile
940 return LinkBlendFile(bpy_openlib, path, group, scene_merge, err_str);
943 bool KX_BlenderSceneConverter::LinkBlendFilePath(const char *path, char *group, KX_Scene *scene_merge, char **err_str)
945 BlendHandle *bpy_openlib = BLO_blendhandle_from_file( (char *)path );
947 // Error checking is done in LinkBlendFile
948 return LinkBlendFile(bpy_openlib, path, group, scene_merge, err_str);
951 bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str)
954 Main *main_newlib; /* stored as a dynamic 'main' until we free it */
955 Main *main_tmp= NULL; /* created only for linking, then freed */
956 LinkNode *names = NULL;
957 int idcode= BKE_idcode_from_name(group);
958 short flag= 0; /* dont need any special options */
960 static char err_local[255];
962 /* only scene and mesh supported right now */
963 if(idcode!=ID_SCE && idcode!=ID_ME) {
964 snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group);
968 if(GetMainDynamicPath(path)) {
969 snprintf(err_local, sizeof(err_local), "blend file already open \"%s\"\n", path);
974 if(bpy_openlib==NULL) {
975 snprintf(err_local, sizeof(err_local), "could not open blendfile \"%s\"\n", path);
980 main_newlib= (Main *)MEM_callocN( sizeof(Main), "BgeMain");
982 CTX_data_main_set(C, main_newlib);
983 BKE_reports_init(&reports, RPT_STORE);
985 /* here appending/linking starts */
986 main_tmp = BLO_library_append_begin(C, &bpy_openlib, (char *)path);
988 names = BLO_blendhandle_get_datablock_names( bpy_openlib, idcode);
993 BLO_library_append_named_part(C, main_tmp, &bpy_openlib, (char *)n->link, idcode, 0);
994 n= (LinkNode *)n->next;
997 BLI_linklist_free(names, free); /* free linklist *and* each node's data */
999 BLO_library_append_end(C, main_tmp, &bpy_openlib, idcode, flag);
1000 BLO_blendhandle_close(bpy_openlib);
1003 BKE_reports_clear(&reports);
1006 /* needed for lookups*/
1007 GetMainDynamic().push_back(main_newlib);
1008 strncpy(main_newlib->name, path, sizeof(main_newlib->name));
1012 /* Convert all new meshes into BGE meshes */
1014 KX_Scene *kx_scene= m_currentScene;
1016 for(mesh= (ID *)main_newlib->mesh.first; mesh; mesh= (ID *)mesh->next ) {
1017 RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)mesh, NULL, scene_merge, this);
1018 kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
1021 else if(idcode==ID_SCE) {
1022 /* Merge all new linked in scene into the existing one */
1024 for(scene= (ID *)main_newlib->scene.first; scene; scene= (ID *)scene->next ) {
1025 printf("SceneName: %s\n", scene->name);
1027 /* merge into the base scene */
1028 KX_Scene* other= m_ketsjiEngine->CreateScene((Scene *)scene);
1029 scene_merge->MergeScene(other);
1031 // RemoveScene(other); // Dont run this, it frees the entire scene converter data, just delete the scene
1039 /* Note m_map_*** are all ok and dont need to be freed
1040 * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */
1041 bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
1049 /* tag all false except the one we remove */
1050 for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
1052 if(main != maggie) {
1061 m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index);
1062 tag_main(maggie, 1);
1065 /* free all tagged objects */
1066 KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
1067 int numScenes = scenes->size();
1070 for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
1072 KX_Scene* scene = scenes->at(scene_idx);
1073 if(IS_TAGGED(scene->GetBlenderScene())) {
1074 RemoveScene(scene); // XXX - not tested yet
1080 /* incase the mesh might be refered to later */
1082 GEN_Map<STR_HashedString,void*> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap();
1084 for(int i=0; i<mapStringToMeshes.size(); i++)
1086 RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i);
1087 if(meshobj && IS_TAGGED(meshobj->GetMesh()))
1089 STR_HashedString mn = meshobj->GetName();
1090 mapStringToMeshes.remove(mn);
1096 //scene->FreeTagged(); /* removed tagged objects and meshes*/
1097 CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL};
1099 for(int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++)
1101 CListValue *obs= obj_lists[ob_ls_idx];
1102 RAS_MeshObject* mesh;
1104 for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++)
1106 KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx);
1107 if(IS_TAGGED(gameobj->GetBlenderObject())) {
1109 int size_before = obs->GetCount();
1111 /* Eventually calls RemoveNodeDestructObject
1112 * frees m_map_gameobject_to_blender from UnregisterGameObject */
1113 scene->RemoveObject(gameobj);
1115 if(size_before != obs->GetCount())
1118 printf("ERROR COULD NOT REMOVE \"%s\"\n", gameobj->GetName().ReadPtr());
1122 /* free the mesh, we could be referecing a linked one! */
1123 int mesh_index= gameobj->GetMeshCount();
1124 while(mesh_index--) {
1125 mesh= gameobj->GetMesh(mesh_index);
1126 if(IS_TAGGED(mesh->GetMesh())) {
1127 gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */
1140 // delete the entities of this scene
1143 vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
1144 size = m_worldinfos.size();
1145 for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
1146 if ((*worldit).second) {
1147 delete (*worldit).second;
1148 *worldit = m_worldinfos.back();
1149 m_worldinfos.pop_back();
1158 /* Worlds dont reference original blender data so we need to make a set from them */
1159 typedef std::set<KX_WorldInfo*> KX_WorldInfoSet;
1160 KX_WorldInfoSet worldset;
1161 for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
1163 KX_Scene* scene = scenes->at(scene_idx);
1164 if(scene->GetWorldInfo())
1165 worldset.insert( scene->GetWorldInfo() );
1168 vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
1169 size = m_worldinfos.size();
1170 for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
1171 if ((*worldit).second && (worldset.count((*worldit).second)) == 0) {
1172 delete (*worldit).second;
1173 *worldit = m_worldinfos.back();
1174 m_worldinfos.pop_back();
1182 /* done freeing the worlds */
1187 vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
1188 size = m_polymaterials.size();
1192 for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
1193 RAS_IPolyMaterial *mat= (*polymit).second;
1194 Material *bmat= NULL;
1196 /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
1197 if(mat->GetFlag() & RAS_BLENDERMAT) {
1198 KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
1199 bmat= bl_mat->GetBlenderMaterial();
1202 KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
1203 bmat= kx_mat->GetBlenderMaterial();
1206 if (IS_TAGGED(bmat)) {
1207 /* only remove from bucket */
1208 ((*polymit).first)->GetBucketManager()->RemoveMaterial(mat);
1217 for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
1218 RAS_IPolyMaterial *mat= (*polymit).second;
1219 Material *bmat= NULL;
1221 /* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
1222 if(mat->GetFlag() & RAS_BLENDERMAT) {
1223 KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
1224 bmat= bl_mat->GetBlenderMaterial();
1227 KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
1228 bmat= kx_mat->GetBlenderMaterial();
1232 //printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2);
1235 //printf("LOST MAT !!!");
1238 if (IS_TAGGED(bmat)) {
1240 delete (*polymit).second;
1241 *polymit = m_polymaterials.back();
1242 m_polymaterials.pop_back();
1244 //printf("tagged !\n");
1248 //printf("(un)tagged !\n");
1252 vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
1253 size = m_materials.size();
1254 for (i=0, matit=m_materials.begin(); i<size; ) {
1255 BL_Material *mat= (*matit).second;
1256 if (IS_TAGGED(mat->material)) {
1257 delete (*matit).second;
1258 *matit = m_materials.back();
1259 m_materials.pop_back();
1267 vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
1268 size = m_meshobjects.size();
1269 for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
1270 RAS_MeshObject *me= (*meshit).second;
1271 if (IS_TAGGED(me->GetMesh())) {
1272 delete (*meshit).second;
1273 *meshit = m_meshobjects.back();
1274 m_meshobjects.pop_back();
1287 bool KX_BlenderSceneConverter::FreeBlendFile(const char *path)
1289 return FreeBlendFile(GetMainDynamicPath(path));
1292 bool KX_BlenderSceneConverter::MergeScene(KX_Scene *to, KX_Scene *from)
1296 vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itp = m_worldinfos.begin();
1297 while (itp != m_worldinfos.end()) {
1298 if ((*itp).first==from)
1305 vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
1306 while (itp != m_polymaterials.end()) {
1307 if ((*itp).first==from) {
1310 /* also switch internal data */
1311 RAS_IPolyMaterial*mat= (*itp).second;
1312 mat->Replace_IScene(to);
1319 vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itp = m_meshobjects.begin();
1320 while (itp != m_meshobjects.end()) {
1321 if ((*itp).first==from)
1328 vector<pair<KX_Scene*,BL_Material*> >::iterator itp = m_materials.begin();
1329 while (itp != m_materials.end()) {
1330 if ((*itp).first==from)
1339 /* This function merges a mesh from the current scene into another main
1340 * it does not convert */
1341 RAS_MeshObject *KX_BlenderSceneConverter::ConvertMeshSpecial(KX_Scene* kx_scene, Main *maggie, const char *name)
1343 /* Find a mesh in the current main */
1344 ID *me= static_cast<ID *>(BLI_findstring(&m_maggie->mesh, name, offsetof(ID, name) + 2));
1347 printf("Could not be found \"%s\"\n", name);
1351 /* Watch this!, if its used in the original scene can cause big troubles */
1353 printf("Mesh has a user \"%s\"\n", name);
1354 me = (ID*)copy_mesh((Mesh*)me);
1357 BLI_remlink(&m_maggie->mesh, me); /* even if we made the copy it needs to be removed */
1358 BLI_addtail(&maggie->mesh, me);
1361 /* Must copy the materials this uses else we cant free them */
1363 Mesh *mesh= (Mesh *)me;
1365 /* ensure all materials are tagged */
1366 for(int i=0; i<mesh->totcol; i++)
1368 mesh->mat[i]->id.flag &= ~LIB_DOIT;
1370 for(int i=0; i<mesh->totcol; i++)
1372 Material *mat_old= mesh->mat[i];
1374 /* if its tagged its a replaced material */
1375 if(mat_old && (mat_old->id.flag & LIB_DOIT)==0)
1377 Material *mat_old= mesh->mat[i];
1378 Material *mat_new= copy_material( mat_old );
1380 mat_new->id.flag |= LIB_DOIT;
1383 BLI_remlink(&m_maggie->mat, mat_new);
1384 BLI_addtail(&maggie->mat, mat_new);
1386 mesh->mat[i]= mat_new;
1388 /* the same material may be used twice */
1389 for(int j=i+1; j<mesh->totcol; j++)
1391 if(mesh->mat[j]==mat_old)
1393 mesh->mat[j]= mat_new;
1402 RAS_MeshObject *meshobj = BL_ConvertMesh((Mesh *)me, NULL, kx_scene, this);
1403 kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(),meshobj);
1404 m_map_mesh_to_gamemesh.clear(); /* This is at runtime so no need to keep this, BL_ConvertMesh adds */