diff --git a/doc/python_api/rst/bge.logic.rst b/doc/python_api/rst/bge.logic.rst index 3c9e926be8db..0e25122a1fa8 100644 --- a/doc/python_api/rst/bge.logic.rst +++ b/doc/python_api/rst/bge.logic.rst @@ -185,7 +185,7 @@ General functions Restarts the current game by reloading the .blend file (the last saved version, not what is currently running). -.. function:: LibLoad(blend, type, data, load_actions=False, verbose=False, load_scripts=True, async=False) +.. function:: LibLoad(blend, type, data, load_actions=False, verbose=False, load_scripts=True, async=False, scene=None) Converts the all of the datablocks of the given type from the given blend. @@ -203,6 +203,8 @@ General functions :type load_scripts: bool :arg async: Whether or not to do the loading asynchronously (in another thread). Only the "Scene" type is currently supported for this feature. :type async: bool + :arg scene: Scene to merge loaded data to, if `None` use the current scene. + :type scene: :class:`bge.types.KX_Scene` or string :rtype: :class:`bge.types.KX_LibLoadStatus` diff --git a/source/gameengine/Ketsji/KX_PythonInit.cpp b/source/gameengine/Ketsji/KX_PythonInit.cpp index a90ff460cc01..7c0e082b0779 100644 --- a/source/gameengine/Ketsji/KX_PythonInit.cpp +++ b/source/gameengine/Ketsji/KX_PythonInit.cpp @@ -621,7 +621,8 @@ static PyObject *pyPrintExt(PyObject *,PyObject *,PyObject *) static PyObject *gLibLoad(PyObject *, PyObject *args, PyObject *kwds) { - KX_Scene *kx_scene= KX_GetActiveScene(); + KX_Scene *kx_scene = nullptr; + PyObject *pyscene = Py_None; char *path; char *group; Py_buffer py_buffer; @@ -632,11 +633,18 @@ static PyObject *gLibLoad(PyObject *, PyObject *args, PyObject *kwds) short options=0; int load_actions=0, verbose=0, load_scripts=1, async=0; - static const char *kwlist[] = {"path", "group", "buffer", "load_actions", "verbose", "load_scripts", "async", nullptr}; + static const char *kwlist[] = {"path", "group", "buffer", "load_actions", "verbose", "load_scripts", "async", "scene", nullptr}; - if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|y*iiIi:LibLoad", const_cast(kwlist), - &path, &group, &py_buffer, &load_actions, &verbose, &load_scripts, &async)) + if (!PyArg_ParseTupleAndKeywords(args, kwds, "ss|y*iiIiO:LibLoad", const_cast(kwlist), + &path, &group, &py_buffer, &load_actions, &verbose, &load_scripts, &async, &pyscene)) + return nullptr; + + if (!ConvertPythonToScene(pyscene, &kx_scene, true, "invalid scene")) { return nullptr; + } + if (!kx_scene) { + kx_scene = KX_GetActiveScene(); + } /* setup options */ if (load_actions != 0) diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index da4e5d626462..075636222884 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -2497,4 +2497,60 @@ KX_PYMETHODDEF_DOC(KX_Scene, get, "") return def; } +bool ConvertPythonToScene(PyObject *value, KX_Scene **scene, bool py_none_ok, const char *error_prefix) +{ + if (value == nullptr) { + PyErr_Format(PyExc_TypeError, "%s, python pointer nullptr, should never happen", error_prefix); + *scene = nullptr; + return false; + } + + if (value == Py_None) { + *scene = nullptr; + + if (py_none_ok) { + return true; + } + else { + PyErr_Format(PyExc_TypeError, "%s, expected KX_Scene or a KX_Scene name, None is invalid", error_prefix); + return false; + } + } + + if (PyUnicode_Check(value)) { + *scene = (KX_Scene *)KX_GetActiveEngine()->CurrentScenes()->FindValue(std::string(_PyUnicode_AsString(value))); + + if (*scene) { + return true; + } + else { + PyErr_Format(PyExc_ValueError, "%s, requested name \"%s\" did not match any in game", error_prefix, _PyUnicode_AsString(value)); + return false; + } + } + + if (PyObject_TypeCheck(value, &KX_Scene::Type)) { + *scene = static_castBGE_PROXY_REF(value); + + // Sets the error. + if (*scene == nullptr) { + PyErr_Format(PyExc_SystemError, "%s, " BGE_PROXY_ERROR_MSG, error_prefix); + return false; + } + + return true; + } + + *scene = nullptr; + + if (py_none_ok) { + PyErr_Format(PyExc_TypeError, "%s, expect a KX_Scene, a string or None", error_prefix); + } + else { + PyErr_Format(PyExc_TypeError, "%s, expect a KX_Scene or a string", error_prefix); + } + + return false; +} + #endif // WITH_PYTHON diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index 57fd41b3cb9c..a8e785a2602d 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -624,6 +624,10 @@ class KX_Scene : public CValue, public SCA_IScene //} }; +#ifdef WITH_PYTHON +bool ConvertPythonToScene(PyObject *value, KX_Scene **scene, bool py_none_ok, const char *error_prefix); +#endif + typedef std::vector KX_SceneList; #endif /* __KX_SCENE_H__ */