From 0190e31e3f682c0f959e34adf3500d1f6e6ce49e Mon Sep 17 00:00:00 2001 From: codereader Date: Wed, 19 Jul 2017 15:17:11 +0200 Subject: [PATCH] Tweak stuff such that executeString has the darkradiant objects readily imported --- plugins/script/ScriptingSystem.cpp | 47 ++++------ .../script/interfaces/SceneGraphInterface.h | 86 ++++++++++++++----- 2 files changed, 81 insertions(+), 52 deletions(-) diff --git a/plugins/script/ScriptingSystem.cpp b/plugins/script/ScriptingSystem.cpp index 15cbcf2593..a6193c3b40 100644 --- a/plugins/script/ScriptingSystem.cpp +++ b/plugins/script/ScriptingSystem.cpp @@ -94,6 +94,14 @@ class DarkRadiantModule _registrationCallback(GetModule(), GetGlobals()); } + py::object main = py::module::import("__main__"); + py::dict globals = main.attr("__dict__").cast(); + + for (auto& i : globals) + { + GetGlobals()[i.first] = i.second; + } + return _module->ptr(); } catch (py::error_already_set& e) @@ -203,8 +211,11 @@ ExecutionResultPtr ScriptingSystem::executeString(const std::string& scriptStrin try { + std::string fullScript = "import darkradiant as DR\nfrom darkradiant import *\n"; + fullScript.append(scriptString); + // Attempt to run the specified script - py::exec(scriptString); + py::exec(fullScript, DarkRadiantModule::GetGlobals()); } catch (py::error_already_set& ex) { @@ -248,6 +259,9 @@ void ScriptingSystem::initialise() { try { + // Import the darkradiant module + py::module::import("darkradiant"); + // Construct the console writer interface PythonConsoleWriterClass consoleWriter(DarkRadiantModule::GetModule(), "PythonConsoleWriter"); consoleWriter.def(py::init()); @@ -265,37 +279,6 @@ void ScriptingSystem::initialise() } } -#if 0 - // Add the registered interfaces - try { - for (Interfaces::iterator i = _interfaces.begin(); i != _interfaces.end(); ++i) { - // Handle each interface in its own try/catch block - try - { - i->second->registerInterface(_mainObjects->mainNamespace); - } - catch (const boost::python::error_already_set&) - { - rError() << "Error while initialising interface " - << i->first << ": " << std::endl; - - PyErr_Print(); - PyErr_Clear(); - - rMessage() << std::endl; - } - } - } - catch (const boost::python::error_already_set&) { - // Dump the error to the console, this will invoke the PythonConsoleWriter - PyErr_Print(); - PyErr_Clear(); - - // Python is usually not appending line feeds... - rMessage() << std::endl; - } -#endif - _initialised = true; // Start the init script diff --git a/plugins/script/interfaces/SceneGraphInterface.h b/plugins/script/interfaces/SceneGraphInterface.h index 47de454c02..b0e7c77fe8 100644 --- a/plugins/script/interfaces/SceneGraphInterface.h +++ b/plugins/script/interfaces/SceneGraphInterface.h @@ -7,6 +7,7 @@ #include "iselection.h" #include "debugging/ScenegraphUtils.h" +#include #include namespace script { @@ -117,25 +118,27 @@ class SceneNodeVisitorWrapper : public boost::python::wrapper { public: - bool pre(const scene::INodePtr& node) { - // Wrap this method to python - return this->get_override("pre")(ScriptSceneNode(node)); - } + using NodeVisitor::NodeVisitor; - void post(const scene::INodePtr& node) { - if (this->get_override("post")) { - // Call the overriden method - this->get_override("post")(ScriptSceneNode(node)); - } - else { - // No override, call base class default - scene::NodeVisitor::post(node); - } - } - - void post_default(const scene::INodePtr& node) { - // Default method: Just call the base class - scene::NodeVisitor::post(node); + bool pre(const scene::INodePtr& node) override + { + // Wrap this method to python + PYBIND11_OVERLOAD_PURE( + int, /* Return type */ + NodeVisitor, /* Parent class */ + pre, /* Name of function in C++ (must match Python name) */ + ScriptSceneNode(node) /* Argument(s) */ + ); + } + + void post(const scene::INodePtr& node) override + { + PYBIND11_OVERLOAD( + void, /* Return type */ + NodeVisitor, /* Parent class */ + post, /* Name of function in C++ (must match Python name) */ + ScriptSceneNode(node) /* Argument(s) */ + ); } }; @@ -143,12 +146,54 @@ class SceneGraphInterface : public IScriptInterface { public: - ScriptSceneNode root() { + ScriptSceneNode root() + { return ScriptSceneNode(GlobalSceneGraph().root()); } + void registerInterface(py::module& scope, py::dict& globals) override + { + // Expose the scene::Node interface + py::class_ sceneNode(scope, "SceneNode"); + + sceneNode.def(py::init()); + sceneNode.def("addToContainer", &ScriptSceneNode::addToContainer); + sceneNode.def("removeFromParent", &ScriptSceneNode::removeFromParent); + sceneNode.def("getWorldAABB", &ScriptSceneNode::getWorldAABB, py::return_value_policy::reference); + sceneNode.def("isNull", &ScriptSceneNode::isNull); + sceneNode.def("getParent", &ScriptSceneNode::getParent); + sceneNode.def("getNodeType", &ScriptSceneNode::getNodeType); + sceneNode.def("traverse", &ScriptSceneNode::traverse); + sceneNode.def("traverseChildren", &ScriptSceneNode::traverseChildren); + sceneNode.def("setSelected", &ScriptSceneNode::setSelected); + sceneNode.def("invertSelected", &ScriptSceneNode::invertSelected); + sceneNode.def("isSelected", &ScriptSceneNode::isSelected); + + py::class_ visitor(scope, "SceneNodeVisitor"); + visitor.def(py::init<>()); + visitor.def("pre", &scene::NodeVisitor::pre); + visitor.def("post", &scene::NodeVisitor::post); + +#if 0 + // Expose the scene::NodeVisitor interface + nspace["SceneNodeVisitor"] = + boost::python::class_("SceneNodeVisitor") + .def("pre", boost::python::pure_virtual(&scene::NodeVisitor::pre)) + .def("post", &scene::NodeVisitor::post, &SceneNodeVisitorWrapper::post_default) // respect default impl. + ; +#endif + // Add the module declaration to the given python namespace + py::class_ sceneGraphInterface(scope, "SceneGraph"); + sceneGraphInterface.def("root", &SceneGraphInterface::root); + + // Now point the Python variable "GlobalSceneGraph" to this instance + globals["GlobalSceneGraph"] = this; + } + +#if 0 // IScriptInterface implementation - void registerInterface(boost::python::object& nspace) { + void registerInterface(boost::python::object& nspace) + { // Expose the scene::Node interface nspace["SceneNode"] = boost::python::class_( "SceneNode", boost::python::init()) @@ -181,6 +226,7 @@ class SceneGraphInterface : // Now point the Python variable "GlobalSceneGraph" to this instance nspace["GlobalSceneGraph"] = boost::python::ptr(this); } +#endif }; typedef std::shared_ptr SceneGraphInterfacePtr;