Skip to content

Commit

Permalink
#6473: The WIP state of my investigations - leaving this topic for now
Browse files Browse the repository at this point in the history
  • Loading branch information
codereader committed Jan 28, 2024
1 parent 9ac6de8 commit f2dcaa3
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 11 deletions.
22 changes: 17 additions & 5 deletions install/scripts/builtin/brush.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
import dr as darkradiant
import darkradiant as dr
from internal import CommandUtil

# Python commands would be classes with static members
class ResizeSelectedBrushesToBounds:
def execute(self, min: dr.Vector3, max: dr.Vector3, material: str):
# We can use type hints to make it possible to register its Signature in the CommandSystem
@staticmethod
def execute(min: dr.Vector3, max: dr.Vector3, material: str):
print(min)
print(max)
print(material)

import inspect
for name, obj in inspect.getmembers(sys.modules[__name__], inspect.isclass):
print(name)
@staticmethod
def canExecute():
return true

print('We have the module: ' + __name__)

# Proves that it's possible to access previously registered DR interfaces
print(dr.ScriptingSystemInterface)
print(dr.ScriptingSystem)

CommandUtil.registerModule(__name__)
21 changes: 21 additions & 0 deletions install/scripts/builtin/internal.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import darkradiant as dr
import inspect

class CommandUtil:
@staticmethod
def registerModule(moduleName):
for name, obj in inspect.getmembers(sys.modules[moduleName], inspect.isclass):
print(name + ' ' + str(obj))
registerClass(name, obj)

@staticmethod
def registerClass(name, obj):
sig = inspect.signature(obj.execute)
print(sig)

for paramName in sig.parameters:
print("Parameter {0} has type {1}".format(paramName, sig.parameters[paramName].annotation))
# Prove that we can identify DR types in the signature
if sig.parameters[paramName].annotation == dr.Vector3:
print('This parametr is a Vec3')
#dr.ScriptingSystem.registerBuiltinScriptCommand(...)
38 changes: 38 additions & 0 deletions plugins/script/PythonModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ PythonModule::~PythonModule()
{
_namedInterfaces.clear();

for (auto& module : _builtInModules)
{
module.dec_ref();
module.release();
}

_builtInModules.clear();

// Release the references to trigger the internal cleanup before Py_Finalize
_module.dec_ref();
_module.release();
Expand Down Expand Up @@ -324,6 +332,36 @@ ScriptCommand::Ptr PythonModule::createScriptCommand(const std::string& scriptBa
}
}

void PythonModule::registerBuiltInModulePath(const std::string& scriptBasePath)
{
// Import module from the base path
auto sys = py::module::import("sys");
sys.attr("path").attr("insert")(1, os::getDirectory(scriptBasePath));
}

void PythonModule::initialiseBuiltInModule(const std::string& moduleFilename)
{
try
{
auto moduleName = os::removeExtension(os::getFilename(moduleFilename));
auto builtInModule = py::module::import(moduleName.c_str());
_builtInModules.push_back(builtInModule);
}
catch (const py::error_already_set& ex)
{
rError() << "Script file " << moduleFilename << " is not a valid command:" << std::endl;
rError() << ex.what() << std::endl;
}
}

void PythonModule::refreshBuiltInModules()
{
for (auto& module : _builtInModules)
{
module.reload();
}
}

PythonModule* PythonModule::_instance = nullptr;

}
6 changes: 6 additions & 0 deletions plugins/script/PythonModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ class PythonModule final
// List of registered interfaces
NamedInterfaces _namedInterfaces;

std::vector<py::module_> _builtInModules;

PythonModule(const PythonModule& other) = delete;
PythonModule& operator=(const PythonModule& other) = delete;

Expand Down Expand Up @@ -63,6 +65,10 @@ class PythonModule final
// Will return an empty object if the file path is not a valid file
ScriptCommand::Ptr createScriptCommand(const std::string& scriptBasePath, const std::string& relativeScriptPath);

void registerBuiltInModulePath(const std::string& scriptBasePath);
void initialiseBuiltInModule(const std::string& moduleFilename);
void refreshBuiltInModules();

private:
// Register the darkradiant module with the inittab pointing to InitModule
void registerModule();
Expand Down
13 changes: 10 additions & 3 deletions plugins/script/ScriptingSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ void ScriptingSystem::initialise()
// Start the init script
executeScriptFile(INIT_SCRIPT_FILENAME);

// Initialise the python script files containing built-in commands
registerBuiltInCommands();

// Search script folder for commands
reloadScripts();
}
Expand Down Expand Up @@ -221,6 +224,8 @@ void ScriptingSystem::registerBuiltInCommands()
return;
}

_pythonModule->registerBuiltInModulePath(start.string());

for (fs::recursive_directory_iterator it(start); it != fs::recursive_directory_iterator(); ++it)
{
// Get the candidate
Expand All @@ -236,7 +241,7 @@ void ScriptingSystem::registerBuiltInCommands()

void ScriptingSystem::initialiseBuiltInCommandFile(const std::string& scriptFilename)
{
//_pythonModule->createScriptCommand(_scriptPath, scriptFilename);
_pythonModule->initialiseBuiltInModule(scriptFilename);
}

// RegisterableModule implementation
Expand Down Expand Up @@ -315,8 +320,10 @@ void ScriptingSystem::initialiseModule(const IApplicationContext& ctx)
{ cmd::ARGTYPE_STRING }
);

// Initialise the python script files containing built-in commands
registerBuiltInCommands();
GlobalCommandSystem().addCommand(
"RefreshScriptModules",
[this](const auto& args) { _pythonModule->refreshBuiltInModules(); }
);

SceneNodeBuffer::Instance().clear();
}
Expand Down
12 changes: 10 additions & 2 deletions plugins/script/interfaces/ScriptingSystemInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
namespace script
{

void ScriptingSystemInterface::registerBuiltinScriptCommand()
void ScriptingSystemInterface::registerBuiltinScriptCommand(py::object& cls)
{

auto inspect = py::module::import("inspect");

auto execute = cls.attr("execute");

auto result = inspect.attr("signature")(execute);
py::print(result);
}

void ScriptingSystemInterface::registerInterface(py::module& scope, py::dict& globals)
Expand All @@ -17,6 +22,9 @@ void ScriptingSystemInterface::registerInterface(py::module& scope, py::dict& gl

// Now point the Python variable "GlobalScriptingSystem" to this instance
globals["GlobalScriptingSystem"] = this;

// Define a ScriptingSystem property in the darkradiant module
scope.attr("ScriptingSystem") = this;
}

}
3 changes: 2 additions & 1 deletion plugins/script/interfaces/ScriptingSystemInterface.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "iscriptinterface.h"
#include <pybind11/pybind11.h>

namespace script
{
Expand All @@ -21,7 +22,7 @@ class ScriptingSystemInterface :
_scriptingSystem(scriptingSystem)
{}

void registerBuiltinScriptCommand();
void registerBuiltinScriptCommand(py::object& cls);

// IScriptInterface implementation
void registerInterface(py::module& scope, py::dict& globals) override;
Expand Down

0 comments on commit f2dcaa3

Please sign in to comment.