diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 279a5af69394..e292e758354f 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -434,7 +434,7 @@ static RAS_MaterialBucket *BL_ConvertMaterial(Material *ma, KX_Scene *scene, BL_ name = "MA"; } - mat = new KX_BlenderMaterial(ma, name); + mat = new KX_BlenderMaterial(ma, name, scene); // this is needed to free up memory afterwards. converter.RegisterMaterial(mat, ma); @@ -1195,7 +1195,6 @@ static void bl_ConvertBlenderObject_Single(BL_SceneConverter& converter, std::vector &vec_parent_child, EXP_ListValue *logicbrick_conversionlist, EXP_ListValue *objectlist, EXP_ListValue *inactivelist, - EXP_ListValue *sumolist, KX_Scene *kxscene, KX_GameObject *gameobj, SCA_LogicManager *logicmgr, SCA_TimeEventManager *timemgr, bool isInActiveLayer) @@ -1219,8 +1218,6 @@ static void bl_ConvertBlenderObject_Single(BL_SceneConverter& converter, gameobj->NodeSetLocalScale(scale); gameobj->NodeUpdate(); - sumolist->Add(CM_AddRef(gameobj)); - BL_ConvertProperties(blenderobject, gameobj, timemgr, kxscene, isInActiveLayer); gameobj->SetName(blenderobject->id.name + 2); @@ -1293,7 +1290,7 @@ void BL_ConvertBlenderObjects(struct Main *maggie, blenderobject, \ vec_parent_child, \ logicbrick_conversionlist, \ - objectlist, inactivelist, sumolist, \ + objectlist, inactivelist, \ kxscene, gameobj, \ logicmgr, timemgr, \ isInActiveLayer \ @@ -1417,9 +1414,6 @@ void BL_ConvertBlenderObjects(struct Main *maggie, int activeLayerBitInfo = blenderscene->lay; - // List of all object converted, active and inactive. - EXP_ListValue *sumolist = new EXP_ListValue(); - std::vector vec_parent_child; EXP_ListValue *objectlist = kxscene->GetObjectList(); @@ -1547,9 +1541,6 @@ void BL_ConvertBlenderObjects(struct Main *maggie, // The returned list by GetChildrenRecursive is not owned by anyone and must not own items, so no AddRef(). childrenlist.push_back(childobj); for (KX_GameObject *obj : childrenlist) { - if (sumolist->RemoveValue(obj)) { - obj->Release(); - } if (logicbrick_conversionlist->RemoveValue(obj)) { obj->Release(); } @@ -1603,6 +1594,8 @@ void BL_ConvertBlenderObjects(struct Main *maggie, } vec_parent_child.clear(); + const std::vector& sumolist = converter.GetObjects(); + // Find 'root' parents (object that has not parents in SceneGraph). for (KX_GameObject *gameobj : sumolist) { if (!gameobj->GetNode()->GetParent()) { @@ -1788,11 +1781,14 @@ void BL_ConvertBlenderObjects(struct Main *maggie, continue; } - KX_GameObject *gotar = sumolist->FindValue(dat->tar->id.name + 2); - - if (gotar && (gotar->GetLayer() & activeLayerBitInfo) && gotar->GetPhysicsController() && - (gameobj->GetLayer() & activeLayerBitInfo) && gameobj->GetPhysicsController()) { - physEnv->SetupObjectConstraints(gameobj, gotar, dat); + for (KX_GameObject *gotar : sumolist) { + if (gotar->GetName() == (dat->tar->id.name + 2) && + (gotar->GetLayer() & activeLayerBitInfo) && gotar->GetPhysicsController() && + (gameobj->GetLayer() & activeLayerBitInfo) && gameobj->GetPhysicsController()) + { + physEnv->SetupObjectConstraints(gameobj, gotar, dat); + break; + } } } } @@ -1857,6 +1853,31 @@ void BL_ConvertBlenderObjects(struct Main *maggie, gameobj->ResetState(); } + // Cleanup converted set of group objects. + convertedlist->Release(); + logicbrick_conversionlist->Release(); + + /* Instantiate dupli group, we will loop trough the object + * that are in active layers. Note that duplicating group + * has the effect of adding objects at the end of objectlist. + * Only loop through the first part of the list. + */ + int objcount = objectlist->GetCount(); + for (unsigned int i = 0; i < objcount; ++i) { + KX_GameObject *gameobj = objectlist->GetValue(i); + if (gameobj->IsDupliGroup()) { + kxscene->DupliGroupRecurse(gameobj, 0); + } + } +} + +void BL_PostConvertBlenderObjects(KX_Scene *kxscene, const BL_SceneConverter& sceneconverter) +{ + const std::vector& sumolist = sceneconverter.GetObjects(); + EXP_ListValue *objectlist = kxscene->GetObjectList(); + +#ifdef WITH_PYTHON + // Convert the python components of each object if the component execution is available. if (G.f & G_SCRIPT_AUTOEXEC) { for (KX_GameObject *gameobj : sumolist) { @@ -1875,22 +1896,6 @@ void BL_ConvertBlenderObjects(struct Main *maggie, CM_Warning("Python components auto-execution disabled"); } - // Cleanup converted set of group objects. - convertedlist->Release(); - sumolist->Release(); - logicbrick_conversionlist->Release(); - - /* Instantiate dupli group, we will loop trough the object - * that are in active layers. Note that duplicating group - * has the effect of adding objects at the end of objectlist. - * Only loop through the first part of the list. - */ - int objcount = objectlist->GetCount(); - for (unsigned int i = 0; i < objcount; ++i) { - KX_GameObject *gameobj = objectlist->GetValue(i); - if (gameobj->IsDupliGroup()) { - kxscene->DupliGroupRecurse(gameobj, 0); - } - } +#endif // WITH_PYTHON } diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.h b/source/gameengine/Converter/BL_BlenderDataConversion.h index 724771038464..9fd29c5d19f0 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.h +++ b/source/gameengine/Converter/BL_BlenderDataConversion.h @@ -64,6 +64,8 @@ RAS_Deformer *BL_ConvertDeformer(KX_GameObject *object, KX_Mesh *meshobj); void BL_ConvertBlenderObjects(Main *maggie, KX_Scene *kxscene, KX_KetsjiEngine *ketsjiEngine, RAS_Rasterizer *rendertools, RAS_ICanvas *canvas, BL_SceneConverter& sceneconverter, bool alwaysUseExpandFraming, float camZoom, bool libloading); +// Non-multithreadable conversion. +void BL_PostConvertBlenderObjects(KX_Scene *kxscene, const BL_SceneConverter& sceneconverter); SCA_IInputDevice::SCA_EnumInputs BL_ConvertKeyCode(int key_code); diff --git a/source/gameengine/Converter/BL_Converter.cpp b/source/gameengine/Converter/BL_Converter.cpp index 6ddb0f44cf2c..080028bc01f8 100644 --- a/source/gameengine/Converter/BL_Converter.cpp +++ b/source/gameengine/Converter/BL_Converter.cpp @@ -35,7 +35,6 @@ #include "KX_Scene.h" #include "KX_GameObject.h" -#include "KX_WorldInfo.h" #include "KX_Mesh.h" #include "RAS_BucketManager.h" #include "KX_PhysicsEngineEnums.h" @@ -191,29 +190,15 @@ void BL_Converter::ConvertScene(BL_SceneConverter& converter, bool libloading) m_alwaysUseExpandFraming, m_camZoom, libloading); - - m_sceneSlots.emplace(scene, converter); } -void BL_Converter::FinalizeSceneData(const BL_SceneConverter& converter, KX_Scene *mergeScene) +void BL_Converter::PostConvertScene(const BL_SceneConverter& converter) { - for (KX_Mesh *mesh : converter.m_meshobjects) { - mesh->ReplaceScene(mergeScene); - } - - for (KX_BlenderMaterial *mat : converter.m_materials) { - // Do this after lights are available so materials can use the lights in shaders. - mat->InitScene(mergeScene); - } + BL_PostConvertBlenderObjects(converter.GetScene(), converter); } void BL_Converter::RemoveScene(KX_Scene *scene) { - KX_WorldInfo *world = scene->GetWorldInfo(); - if (world) { - delete world; - } - #ifdef WITH_PYTHON Texture::FreeAllTextures(scene); #endif // WITH_PYTHON @@ -280,11 +265,7 @@ void BL_Converter::MergeAsyncLoads() for (KX_LibLoadStatus *libload : m_mergequeue) { KX_Scene *mergeScene = libload->GetMergeScene(); for (const BL_SceneConverter& converter : libload->GetSceneConverters()) { - KX_Scene *scene = converter.GetScene(); - MergeScene(mergeScene, scene); - // Finalize material and mesh conversion. - FinalizeSceneData(converter, mergeScene); - delete scene; + MergeScene(mergeScene, converter); } libload->Finish(); @@ -313,7 +294,6 @@ void BL_Converter::AddScenesToMergeQueue(KX_LibLoadStatus *status) static void async_convert(TaskPool *pool, void *ptr, int UNUSED(threadid)) { KX_LibLoadStatus *status = static_cast(ptr); - KX_KetsjiEngine *engine = status->GetEngine(); BL_Converter *converter = status->GetConverter(); const std::vector& scenes = status->GetScenes(); @@ -438,9 +418,8 @@ KX_LibLoadStatus *BL_Converter::LinkBlendFile(BlendHandle *blendlib, const char scene_merge->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj); } - // Finalize material and mesh conversion. - FinalizeSceneData(sceneConverter, scene_merge); - m_sceneSlots[scene_merge].Merge(sceneConverter); + MergeSceneData(scene_merge, sceneConverter); + FinalizeSceneData(sceneConverter); } else if (idcode == ID_AC) { // Convert all actions @@ -483,13 +462,7 @@ KX_LibLoadStatus *BL_Converter::LinkBlendFile(BlendHandle *blendlib, const char BL_SceneConverter sceneConverter(other); ConvertScene(sceneConverter, true); - - MergeScene(scene_merge, other); - - // Finalize material and mesh conversion. - FinalizeSceneData(sceneConverter, scene_merge); - - delete other; + MergeScene(scene_merge, sceneConverter); } } @@ -706,16 +679,39 @@ bool BL_Converter::FreeBlendFile(const std::string& path) return FreeBlendFile(GetMainDynamicPath(path)); } -void BL_Converter::MergeScene(KX_Scene *to, KX_Scene *from) +void BL_Converter::MergeSceneData(KX_Scene *to, const BL_SceneConverter& converter) { + for (KX_Mesh *mesh : converter.m_meshobjects) { + mesh->ReplaceScene(to); + } + + // Do this after lights are available (scene merged) so materials can use the lights in shaders. + for (KX_BlenderMaterial *mat : converter.m_materials) { + mat->ReplaceScene(to); + } + + m_sceneSlots[to].Merge(converter); +} + +void BL_Converter::MergeScene(KX_Scene *to, const BL_SceneConverter& converter) +{ + PostConvertScene(converter); + + MergeSceneData(to, converter); + + KX_Scene *from = converter.GetScene(); to->MergeScene(from); - m_sceneSlots[to].Merge(m_sceneSlots[from]); - m_sceneSlots.erase(from); + FinalizeSceneData(converter); + + delete from; +} - // Delete from scene's world info. - delete from->GetWorldInfo(); - from->SetWorldInfo(nullptr); +void BL_Converter::FinalizeSceneData(const BL_SceneConverter& converter) +{ + for (KX_BlenderMaterial *mat : converter.m_materials) { + mat->InitShader(); + } } /** This function merges a mesh from the current scene into another main @@ -797,9 +793,8 @@ KX_Mesh *BL_Converter::ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, cons KX_Mesh *meshobj = BL_ConvertMesh((Mesh *)me, nullptr, kx_scene, sceneConverter); kx_scene->GetLogicManager()->RegisterMeshName(meshobj->GetName(), meshobj); - // Finalize material and mesh conversion. - FinalizeSceneData(sceneConverter, kx_scene); - m_sceneSlots[kx_scene].Merge(sceneConverter); + MergeSceneData(kx_scene, sceneConverter); + FinalizeSceneData(sceneConverter); return meshobj; } diff --git a/source/gameengine/Converter/BL_Converter.h b/source/gameengine/Converter/BL_Converter.h index f229ae485ead..1238d1b78699 100644 --- a/source/gameengine/Converter/BL_Converter.h +++ b/source/gameengine/Converter/BL_Converter.h @@ -106,20 +106,36 @@ class BL_Converter bool m_alwaysUseExpandFraming; float m_camZoom; + /** Merge all data contained in the scene converter to the scene slot of + * the destination scene and update the data to use the destination scene. + * \param to The destination scene. + * \param converter The scene converted of the data to merge. + */ + void MergeSceneData(KX_Scene *to, const BL_SceneConverter& converter); + + /** Complete process of scene merging: + * - post convert + * - merge data + * - merge scene (KX_Scene::MergeScene) + * - finalize data + */ + void MergeScene(KX_Scene *to, const BL_SceneConverter& converter); + public: BL_Converter(Main *maggie, KX_KetsjiEngine *engine, bool alwaysUseExpandFraming, float camZoom); virtual ~BL_Converter(); void ConvertScene(BL_SceneConverter& converter, bool libloading); - /** Generate shaders and mesh attributes depending on. - * This function is separated from ConvertScene to be synchronized when compiling shaders - * and select a scene to generate shaders with. This last point is used for scene libload - * merging. + /** Convert all scene data that can't in a separate thread such as python components. * \param converter The scene convert to finalize. - * \param mergeScene The scene used to generate shaders. */ - void FinalizeSceneData(const BL_SceneConverter& converter, KX_Scene *mergeScene); + void PostConvertScene(const BL_SceneConverter& converter); + + /** Finalize all data depending on scene context after a potential scene merging, + * such as shader creation depending on lights into scene. + */ + void FinalizeSceneData(const BL_SceneConverter& converter); /** This function removes all entities stored in the converter for that scene * It should be used instead of direct delete scene @@ -151,8 +167,6 @@ class BL_Converter KX_Mesh *ConvertMeshSpecial(KX_Scene *kx_scene, Main *maggie, const std::string& name); - void MergeScene(KX_Scene *to, KX_Scene *from); - void MergeAsyncLoads(); void FinalizeAsyncLoads(); void AddScenesToMergeQueue(KX_LibLoadStatus *status); diff --git a/source/gameengine/Converter/BL_SceneConverter.cpp b/source/gameengine/Converter/BL_SceneConverter.cpp index 3a7b1fce7876..50cedc17a4e0 100644 --- a/source/gameengine/Converter/BL_SceneConverter.cpp +++ b/source/gameengine/Converter/BL_SceneConverter.cpp @@ -33,6 +33,8 @@ #include "BL_ConvertObjectInfo.h" #include "KX_GameObject.h" +#include "CM_List.h" + BL_SceneConverter::BL_SceneConverter(KX_Scene *scene) :m_scene(scene) { @@ -43,6 +45,7 @@ BL_SceneConverter::BL_SceneConverter(BL_SceneConverter&& other) m_materials(std::move(other.m_materials)), m_meshobjects(std::move(other.m_meshobjects)), m_objectInfos(std::move(other.m_objectInfos)), + m_objects(std::move(other.m_objects)), m_blenderToObjectInfos(std::move(other.m_blenderToObjectInfos)), m_map_blender_to_gameobject(std::move(other.m_map_blender_to_gameobject)), m_map_mesh_to_gamemesh(std::move(other.m_map_mesh_to_gamemesh)), @@ -61,6 +64,7 @@ void BL_SceneConverter::RegisterGameObject(KX_GameObject *gameobject, Object *fo { // only maintained while converting, freed during game runtime m_map_blender_to_gameobject[for_blenderobject] = gameobject; + m_objects.push_back(gameobject); } /** only need to run this during conversion since @@ -76,6 +80,8 @@ void BL_SceneConverter::UnregisterGameObject(KX_GameObject *gameobject) m_map_blender_to_gameobject.erase(it); } } + + CM_ListRemoveIfFound(m_objects, gameobject); } KX_GameObject *BL_SceneConverter::FindGameObject(Object *for_blenderobject) @@ -140,3 +146,8 @@ BL_ConvertObjectInfo *BL_SceneConverter::GetObjectInfo(Object *blenderobj) return it->second; } + +const std::vector &BL_SceneConverter::GetObjects() const +{ + return m_objects; +} diff --git a/source/gameengine/Converter/BL_SceneConverter.h b/source/gameengine/Converter/BL_SceneConverter.h index f61ba784a646..b19c07a0a74b 100644 --- a/source/gameengine/Converter/BL_SceneConverter.h +++ b/source/gameengine/Converter/BL_SceneConverter.h @@ -65,6 +65,8 @@ class BL_SceneConverter std::vector m_materials; std::vector m_meshobjects; std::vector m_objectInfos; + // List of all object converted, active and inactive. + std::vector m_objects; std::map m_blenderToObjectInfos; std::map m_map_blender_to_gameobject; @@ -101,6 +103,8 @@ class BL_SceneConverter SCA_IController *FindGameController(bController *for_controller); BL_ConvertObjectInfo *GetObjectInfo(Object *blenderobj); + + const std::vector& GetObjects() const; }; #endif // __KX_BLENDERSCENECONVERTER_H__ diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index b999876ef8c4..87a8b9785816 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -41,12 +41,12 @@ #include "DNA_material_types.h" #include "DNA_scene_types.h" -KX_BlenderMaterial::KX_BlenderMaterial(Material *mat, const std::string& name) +KX_BlenderMaterial::KX_BlenderMaterial(Material *mat, const std::string& name, KX_Scene *scene) :RAS_IPolyMaterial(name), m_material(mat), m_shader(nullptr), m_blenderShader(nullptr), - m_scene(nullptr), + m_scene(scene), m_userDefBlend(false) { // Save material data to restore on exit @@ -198,6 +198,11 @@ void KX_BlenderMaterial::ReloadMaterial() } } +void KX_BlenderMaterial::ReplaceScene(KX_Scene *scene) +{ + m_scene = scene; +} + void KX_BlenderMaterial::InitTextures() { // for each unique material... @@ -211,13 +216,12 @@ void KX_BlenderMaterial::InitTextures() } } -void KX_BlenderMaterial::InitScene(KX_Scene *scene) +void KX_BlenderMaterial::InitShader() { - m_scene = scene; + BLI_assert(!m_blenderShader); + BLI_assert(m_scene); - if (!m_blenderShader) { - m_blenderShader = new BL_BlenderShader(m_scene, m_material, this); - } + m_blenderShader = new BL_BlenderShader(m_scene, m_material, this); if (!m_blenderShader->Ok()) { delete m_blenderShader; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index d29a67407e56..264661502367 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -26,7 +26,7 @@ class KX_BlenderMaterial : public EXP_Value, public RAS_IPolyMaterial Py_Header public: - KX_BlenderMaterial(Material *mat, const std::string& name); + KX_BlenderMaterial(Material *mat, const std::string& name, KX_Scene *scene); virtual ~KX_BlenderMaterial(); @@ -52,11 +52,8 @@ class KX_BlenderMaterial : public EXP_Value, public RAS_IPolyMaterial virtual SCA_IScene *GetScene() const; virtual void ReloadMaterial(); - /** Set scene owning this material and generate blender shader using - * scene lights. - * \param scene The scene material owner. - */ - void InitScene(KX_Scene *scene); + void ReplaceScene(KX_Scene *scene); + void InitShader(); static void EndFrame(RAS_Rasterizer *rasty); diff --git a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp index 8e82db4c3c08..883c90b02a1c 100644 --- a/source/gameengine/Ketsji/KX_KetsjiEngine.cpp +++ b/source/gameengine/Ketsji/KX_KetsjiEngine.cpp @@ -1317,8 +1317,8 @@ void KX_KetsjiEngine::ConvertScene(KX_Scene *scene) { BL_SceneConverter sceneConverter(scene); m_converter->ConvertScene(sceneConverter, false); - // Finalize material and mesh conversion. - m_converter->FinalizeSceneData(sceneConverter, scene); + m_converter->PostConvertScene(sceneConverter); + m_converter->FinalizeSceneData(sceneConverter); } void KX_KetsjiEngine::AddScheduledScenes() diff --git a/source/gameengine/Ketsji/KX_PythonComponentManager.cpp b/source/gameengine/Ketsji/KX_PythonComponentManager.cpp index e5b3ef1a65ff..7fbb006e244f 100644 --- a/source/gameengine/Ketsji/KX_PythonComponentManager.cpp +++ b/source/gameengine/Ketsji/KX_PythonComponentManager.cpp @@ -34,3 +34,9 @@ void KX_PythonComponentManager::UpdateComponents() gameobj->UpdateComponents(); } } + +void KX_PythonComponentManager::Merge(KX_PythonComponentManager& other) +{ + m_objects.insert(m_objects.end(), other.m_objects.begin(), other.m_objects.end()); + other.m_objects.clear(); +} diff --git a/source/gameengine/Ketsji/KX_PythonComponentManager.h b/source/gameengine/Ketsji/KX_PythonComponentManager.h index 6c0b18c904f2..41b2faee70bf 100644 --- a/source/gameengine/Ketsji/KX_PythonComponentManager.h +++ b/source/gameengine/Ketsji/KX_PythonComponentManager.h @@ -18,6 +18,8 @@ class KX_PythonComponentManager void UnregisterObject(KX_GameObject *gameobj); void UpdateComponents(); + + void Merge(KX_PythonComponentManager& other); }; #endif // __KX_PYTHON_COMPONENT_H__ diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index 31d746770ccd..87c6599b205b 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -2060,9 +2060,6 @@ void initPlayerPython(int argc, char **argv) PySys_SetObject("argv", py_argv); Py_DECREF(py_argv); - // Initialize thread support (also acquires lock). - PyEval_InitThreads(); - bpy_import_init(PyEval_GetBuiltins()); /* The modules are imported to call their init functions to ensure the types they own are ready diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 6ea6b403868d..75145f03cd4c 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -276,6 +276,10 @@ KX_Scene::~KX_Scene() delete m_boundingBoxManager; } + if (m_worldinfo) { + delete m_worldinfo; + } + #ifdef WITH_PYTHON if (m_attrDict) { PyDict_Clear(m_attrDict); @@ -1644,6 +1648,7 @@ bool KX_Scene::MergeScene(KX_Scene *other) m_bucketmanager->Merge(other->GetBucketManager(), this); m_boundingBoxManager->Merge(other->GetBoundingBoxManager()); m_rendererManager->Merge(other->GetTextureRendererManager()); + m_componentManager.Merge(other->GetPythonComponentManager()); for (KX_GameObject *gameobj : *other->GetObjectList()) { MergeScene_GameObject(gameobj, this, other);