From c6e89dead6aaf3d34a4662df122e9bcffa87934b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Capelle?= Date: Wed, 4 Nov 2020 21:48:22 +0100 Subject: [PATCH 1/5] Add IModInterface::fileTree(). --- src/runner/pythonrunner.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/runner/pythonrunner.cpp b/src/runner/pythonrunner.cpp index fce52e2..85c46dc 100644 --- a/src/runner/pythonrunner.cpp +++ b/src/runner/pythonrunner.cpp @@ -144,7 +144,7 @@ BOOST_PYTHON_MODULE(mobase) utils::register_functor_converter>(); utils::register_functor_converter>(); utils::register_functor_converter(); - utils::register_functor_converter)>(); + utils::register_functor_converter)>(); utils::register_functor_converter(); utils::register_functor_converter const&)>(); utils::register_functor_converter(QString const&)>(); @@ -610,6 +610,7 @@ BOOST_PYTHON_MODULE(mobase) .def("categories", &IModInterface::categories) .def("trackedState", &IModInterface::trackedState) .def("endorsedState", &IModInterface::endorsedState) + .def("fileTree", &IModInterface::fileTree) .def("setVersion", &IModInterface::setVersion, bpy::arg("version")) .def("setNewestVersion", &IModInterface::setNewestVersion, bpy::arg("version")) From 6445f7f47f0878e80f5a85394e604e06675175b3 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Wed, 4 Nov 2020 22:52:56 -0500 Subject: [PATCH 2/5] handle empty variants returned from pluginSetting() can happen when init() is called when MO has no instance set up --- src/proxy/proxypython.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/proxy/proxypython.cpp b/src/proxy/proxypython.cpp index 4f4ae88..15a6ea4 100644 --- a/src/proxy/proxypython.cpp +++ b/src/proxy/proxypython.cpp @@ -116,7 +116,9 @@ typedef IPythonRunner* (*CreatePythonRunner_func)(const MOBase::IOrganizer *moIn bool ProxyPython::init(IOrganizer *moInfo) { m_MOInfo = moInfo; - if (!m_MOInfo->pluginSetting(name(), "enabled").toBool()) { + + const auto enabled = m_MOInfo->pluginSetting(name(), "enabled"); + if (!enabled.isNull() && !enabled.toBool()) { m_LoadFailure = FAIL_NONE; return false; } From 6a73c23a4bd662cfded6975c962e2588f827b614 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 6 Nov 2020 09:06:55 -0500 Subject: [PATCH 3/5] added registered() python wrapper null checks for the IOrganizer, replaced pluginDataPath() by the static version getPluginDataPath() --- src/proxy/proxypython.cpp | 32 ++++++++++----- src/runner/proxypluginwrappers.cpp | 16 ++++++-- src/runner/proxypluginwrappers.h | 4 +- src/runner/pythonrunner.cpp | 63 +++++++++++++++++------------- 4 files changed, 74 insertions(+), 41 deletions(-) diff --git a/src/proxy/proxypython.cpp b/src/proxy/proxypython.cpp index 15a6ea4..fe3886f 100644 --- a/src/proxy/proxypython.cpp +++ b/src/proxy/proxypython.cpp @@ -117,8 +117,7 @@ bool ProxyPython::init(IOrganizer *moInfo) { m_MOInfo = moInfo; - const auto enabled = m_MOInfo->pluginSetting(name(), "enabled"); - if (!enabled.isNull() && !enabled.toBool()) { + if (m_MOInfo && !m_MOInfo->pluginSetting(name(), "enabled").toBool()) { m_LoadFailure = FAIL_NONE; return false; } @@ -129,20 +128,27 @@ bool ProxyPython::init(IOrganizer *moInfo) return true; } - QString pythonPath = m_MOInfo->pluginSetting(name(), "python_dir").toString(); + QString pythonPath; - if (!pythonPath.isEmpty() && !QFile::exists(pythonPath + "/python.exe")) { - m_LoadFailure = FAIL_WRONGPYTHONPATH; - return true; + if (m_MOInfo) { + pythonPath = m_MOInfo->pluginSetting(name(), "python_dir").toString(); + + if (!pythonPath.isEmpty() && !QFile::exists(pythonPath + "/python.exe")) { + m_LoadFailure = FAIL_WRONGPYTHONPATH; + return true; + } } - m_RunnerLib = ::LoadLibraryW(QDir::toNativeSeparators(m_MOInfo->pluginDataPath() + "/pythonRunner.dll").toStdWString().c_str()); + m_RunnerLib = ::LoadLibraryW(QDir::toNativeSeparators( + IOrganizer::getPluginDataPath() + "/pythonRunner.dll").toStdWString().c_str()); + if (m_RunnerLib != nullptr) { CreatePythonRunner_func CreatePythonRunner = (CreatePythonRunner_func)::GetProcAddress(m_RunnerLib, "CreatePythonRunner"); if (CreatePythonRunner == nullptr) { throw MyException("embedded dll is invalid: " + windowsErrorString(::GetLastError())); } - if (m_MOInfo->persistent(name(), "tryInit", false).toBool()) { + + if (m_MOInfo && m_MOInfo->persistent(name(), "tryInit", false).toBool()) { if (pythonPath.isEmpty()) { m_LoadFailure = FAIL_PYTHONDETECTION; } else { @@ -160,9 +166,15 @@ bool ProxyPython::init(IOrganizer *moInfo) } } - m_MOInfo->setPersistent(name(), "tryInit", true); + if (m_MOInfo) { + m_MOInfo->setPersistent(name(), "tryInit", true); + } + m_Runner = CreatePythonRunner(moInfo, pythonPath); - m_MOInfo->setPersistent(name(), "tryInit", false); + + if (m_MOInfo) { + m_MOInfo->setPersistent(name(), "tryInit", false); + } if (m_Runner != nullptr) { m_LoadFailure = FAIL_NONE; diff --git a/src/runner/proxypluginwrappers.cpp b/src/runner/proxypluginwrappers.cpp index 579663c..3aa8072 100644 --- a/src/runner/proxypluginwrappers.cpp +++ b/src/runner/proxypluginwrappers.cpp @@ -28,6 +28,16 @@ using namespace MOBase; #define COMMON_I_PLUGIN_WRAPPER_DEFINITIONS(class_name) \ +void class_name::registered() \ +{ \ + basicWrapperFunctionImplementationWithDefault(this, &class_name::registered_Default, "registered"); \ +} \ +\ +void class_name::registered_Default() \ +{ \ + IPlugin::registered(); \ +} \ +\ bool class_name::init(MOBase::IOrganizer *moInfo) \ { \ return basicWrapperFunctionImplementation(this, "init", boost::python::ptr(moInfo)); \ @@ -306,7 +316,7 @@ void class_name::onInstallationStart(QString const& archive, bool reinstallation basicWrapperFunctionImplementationWithDefault(this, &class_name::onInstallationStart_Default, "onInstallationStart", archive, reinstallation, boost::python::ptr(currentMod)); } \ void class_name::onInstallationEnd(EInstallResult result, MOBase::IModInterface* newMod) { \ basicWrapperFunctionImplementationWithDefault(this, &class_name::onInstallationEnd_Default, "onInstallationEnd", result, boost::python::ptr(newMod)); } \ -bool class_name::isArchiveSupported(std::shared_ptr tree) const { return basicWrapperFunctionImplementation(this, "isArchiveSupported", tree); } +bool class_name::isArchiveSupported(std::shared_ptr tree) const { return basicWrapperFunctionImplementation(this, "isArchiveSupported", tree); } /// end IPluginInstaller macro ///////////////////////////////////// @@ -323,7 +333,7 @@ IPluginInstaller::EInstallResult IPluginInstallerSimpleWrapper::install( using return_type = std::variant< IPluginInstaller::EInstallResult, - std::shared_ptr, + std::shared_ptr, std::tuple, QString, int>> ; auto ret = basicWrapperFunctionImplementation(this, "install", boost::ref(modName), tree, version, nexusID); @@ -364,7 +374,7 @@ std::set IPluginInstallerCustomWrapper::supportedExtensions() const IPluginInstaller::EInstallResult IPluginInstallerCustomWrapper::install( GuessedValue &modName, QString gameName, const QString &archiveName, const QString &version, int modID) { - // Note: This requires far more less trouble than the "Simple" installer version since 1) there is no tree + // Note: This requires far more less trouble than the "Simple" installer version since 1) there is no tree // and 2) there version and modId cannot be modified: return basicWrapperFunctionImplementation( this, "install", boost::ref(modName), gameName, archiveName, version, modID); diff --git a/src/runner/proxypluginwrappers.h b/src/runner/proxypluginwrappers.h index 1d51664..22c3283 100644 --- a/src/runner/proxypluginwrappers.h +++ b/src/runner/proxypluginwrappers.h @@ -17,6 +17,8 @@ #define COMMON_I_PLUGIN_WRAPPER_DECLARATIONS public: \ +virtual void registered() override; \ +void registered_Default(); \ virtual bool init(MOBase::IOrganizer *moInfo) override; \ virtual QString name() const override; \ virtual QString localizedName() const override; \ @@ -146,7 +148,7 @@ void onInstallationStart_Default(QString const& archive, bool reinstallation, MO virtual void onInstallationEnd(EInstallResult result, MOBase::IModInterface* newMod) override; \ void onInstallationEnd_Default(EInstallResult result, MOBase::IModInterface* newMod) { \ return IPluginInstaller::onInstallationEnd(result, newMod); } \ -virtual bool isArchiveSupported(std::shared_ptr tree) const override; +virtual bool isArchiveSupported(std::shared_ptr tree) const override; class IPluginInstallerSimpleWrapper : public MOBase::IPluginInstallerSimple, public boost::python::wrapper diff --git a/src/runner/pythonrunner.cpp b/src/runner/pythonrunner.cpp index fce52e2..5fbe5fb 100644 --- a/src/runner/pythonrunner.cpp +++ b/src/runner/pythonrunner.cpp @@ -109,7 +109,7 @@ BOOST_PYTHON_MODULE(mobase) utils::register_sequence_container>(); utils::register_set_container>(); - + utils::register_associative_container>(); // Required for QVariant since this is QVariantMap. utils::register_associative_container>(); utils::register_associative_container>(); @@ -124,8 +124,8 @@ BOOST_PYTHON_MODULE(mobase) // Variants: bpy::register_variant, + IPluginInstaller::EInstallResult, + std::shared_ptr, std::tuple, QString, int>>>(); bpy::register_variant>(); bpy::register_variant>(); @@ -220,7 +220,7 @@ BOOST_PYTHON_MODULE(mobase) .def_readwrite("description", &PluginSetting::description) .def_readwrite("default_value", &PluginSetting::defaultValue); - bpy::class_("ExecutableInfo", + bpy::class_("ExecutableInfo", bpy::init((bpy::arg("title"), "binary"))) .def("withArgument", &ExecutableInfo::withArgument, bpy::return_self<>(), bpy::arg("argument")) .def("withWorkingDirectory", &ExecutableInfo::withWorkingDirectory, bpy::return_self<>(), bpy::arg("directory")) @@ -235,7 +235,7 @@ BOOST_PYTHON_MODULE(mobase) .def("isCustom", &ExecutableInfo::isCustom) ; - bpy::class_("ExecutableForcedLoadSetting", + bpy::class_("ExecutableForcedLoadSetting", bpy::init((bpy::arg("process"), "library"))) .def("withForced", &ExecutableForcedLoadSetting::withForced, bpy::return_self<>(), bpy::arg("forced")) .def("withEnabled", &ExecutableForcedLoadSetting::withEnabled, bpy::return_self<>(), bpy::arg("enabled")) @@ -293,9 +293,9 @@ BOOST_PYTHON_MODULE(mobase) (bpy::arg("path"), "filter")) // In C++, it is possible to create a QStringList implicitly from a single QString. This is not possible with the current - // converters in python (and I do not think it is a good idea to have it everywhere), but here it is nice to be able to + // converters in python (and I do not think it is a good idea to have it everywhere), but here it is nice to be able to // pass a single string, so we add an extra overload. - // Important: the order matters, because a Python string can be converted to a QStringList since it is a sequence of + // Important: the order matters, because a Python string can be converted to a QStringList since it is a sequence of // single-character strings: .def("findFiles", +[](const IOrganizer* o, QString const& p, const QStringList& gf) { return o->findFiles(p, gf); }, (bpy::arg("path"), "patterns")) @@ -311,11 +311,11 @@ BOOST_PYTHON_MODULE(mobase) // Custom implementation for startApplication and waitForApplication because 1) HANDLE (= void*) is not properly // converted from/to python, and 2) we need to convert the by-ptr argument to a return-tuple for waitForApplication: - .def("startApplication", - +[](IOrganizer* o, const QString& executable, const QStringList& args, const QString& cwd, const QString& profile, + .def("startApplication", + +[](IOrganizer* o, const QString& executable, const QStringList& args, const QString& cwd, const QString& profile, const QString& forcedCustomOverwrite, bool ignoreCustomOverwrite) { return (std::uintptr_t) o->startApplication(executable, args, cwd, profile, forcedCustomOverwrite, ignoreCustomOverwrite); - }, (bpy::arg("executable"), (bpy::arg("args") = QStringList()), (bpy::arg("cwd") = ""), (bpy::arg("profile") = ""), + }, (bpy::arg("executable"), (bpy::arg("args") = QStringList()), (bpy::arg("cwd") = ""), (bpy::arg("profile") = ""), (bpy::arg("forcedCustomOverwrite") = ""), (bpy::arg("ignoreCustomOverwrite") = false)), bpy::return_value_policy()) .def("waitForApplication", +[](IOrganizer *o, std::uintptr_t handle) { DWORD returnCode; @@ -367,9 +367,9 @@ BOOST_PYTHON_MODULE(mobase) // FileTreeEntry Scope: auto fileTreeEntryClass = bpy::class_("FileTreeEntry", bpy::no_init); { - + bpy::scope scope = fileTreeEntryClass; - + bpy::enum_("FileTypes") .value("FILE_OR_DIRECTORY", FileTreeEntry::FILE_OR_DIRECTORY) .value("FILE", FileTreeEntry::FILE) @@ -413,7 +413,7 @@ BOOST_PYTHON_MODULE(mobase) // IFileTree scope: auto iFileTreeClass = bpy::class_, boost::noncopyable>("IFileTree", bpy::no_init); { - + bpy::scope scope = iFileTreeClass; bpy::enum_("InsertPolicy") @@ -463,7 +463,7 @@ BOOST_PYTHON_MODULE(mobase) return result; }, bpy::arg("path")) - // Merge needs custom return types depending if the user wants overrides or not. A failure is translated + // Merge needs custom return types depending if the user wants overrides or not. A failure is translated // into an exception for easier tracing and handling. .def("merge", +[](IFileTree* p, std::shared_ptr other, bool returnOverwrites) -> std::variant { IFileTree::OverwritesType overwrites; @@ -510,7 +510,7 @@ BOOST_PYTHON_MODULE(mobase) .def("__repr__", +[](const IFileTree* entry) { return "IFileTree(\"" + entry->name() + "\")"; }) ; } - + bpy::class_("IProfile", bpy::no_init) .def("name", &IProfile::name) @@ -649,11 +649,11 @@ BOOST_PYTHON_MODULE(mobase) bpy::return_self<>(), (bpy::arg("value"), "quality")) // Methods to simulate the assignment operator: - .def("reset", +[](GuessedValue* gv) { + .def("reset", +[](GuessedValue* gv) { *gv = GuessedValue(); }, bpy::return_self<>()) - .def("reset", +[](GuessedValue* gv, const QString& value, EGuessQuality eq) { + .def("reset", +[](GuessedValue* gv, const QString& value, EGuessQuality eq) { *gv = GuessedValue(value, eq); }, bpy::return_self<>(), (bpy::arg("value"), "quality")) - .def("reset", +[](GuessedValue* gv, const GuessedValue& other) { + .def("reset", +[](GuessedValue* gv, const GuessedValue& other) { *gv = other; }, bpy::return_self<>(), bpy::arg("other")) // Use an intermediate lambda to avoid having to register the std::function conversion: @@ -767,10 +767,11 @@ BOOST_PYTHON_MODULE(mobase) .def("onModMoved", &MOBase::IModList::onModMoved, bpy::arg("callback")) ; - // Note: localizedName() and master() have to go in all the plugin wrappers declaration, + // Note: registered(), localizedName() and master() have to go in all the plugin wrappers declaration, // since the default functions are specific to each wrapper, otherwise in turns into an // infinite recursion mess. bpy::class_("IPlugin") + .def("registered", &MOBase::IPlugin::registered, &IPluginWrapper::registered_Default) .def("init", bpy::pure_virtual(&MOBase::IPlugin::init), bpy::arg("organizer")) .def("name", bpy::pure_virtual(&MOBase::IPlugin::name)) .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginWrapper::localizedName_Default) @@ -783,6 +784,7 @@ BOOST_PYTHON_MODULE(mobase) ; bpy::class_, boost::noncopyable>("IPluginDiagnose") + .def("registered", &MOBase::IPlugin::registered, &IPluginDiagnoseWrapper::registered_Default) .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginDiagnoseWrapper::localizedName_Default) .def("master", &MOBase::IPlugin::master, &IPluginDiagnoseWrapper::master_Default, bpy::return_value_policy()) @@ -809,6 +811,7 @@ BOOST_PYTHON_MODULE(mobase) ; bpy::class_, boost::noncopyable>("IPluginFileMapper") + .def("registered", &MOBase::IPlugin::registered, &IPluginFileMapperWrapper::registered_Default) .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginFileMapperWrapper::localizedName_Default) .def("master", &MOBase::IPlugin::master, &IPluginFileMapperWrapper::master_Default, bpy::return_value_policy()) .def("mappings", bpy::pure_virtual(&MOBase::IPluginFileMapper::mappings)) @@ -843,6 +846,7 @@ BOOST_PYTHON_MODULE(mobase) ; bpy::class_, boost::noncopyable>("IPluginGame") + .def("registered", &MOBase::IPlugin::registered, &IPluginGameWrapper::registered_Default) .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginGameWrapper::localizedName_Default) .def("master", &MOBase::IPlugin::master, &IPluginGameWrapper::master_Default, bpy::return_value_policy()) @@ -940,6 +944,7 @@ BOOST_PYTHON_MODULE(mobase) bpy::class_, boost::noncopyable>("IPluginInstallerSimple") .def("onInstallationStart", &IPluginInstaller::onInstallationStart, (bpy::arg("archive"), bpy::arg("reinstallation"), bpy::arg("current_mod"))) .def("onInstallationEnd", &IPluginInstaller::onInstallationEnd, (bpy::arg("result"), bpy::arg("new_mod"))) + .def("registered", &MOBase::IPlugin::registered, &IPluginInstallerSimpleWrapper::registered_Default) .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginInstallerSimpleWrapper::localizedName_Default) .def("master", &MOBase::IPlugin::master, &IPluginInstallerSimpleWrapper::master_Default, bpy::return_value_policy()) @@ -957,10 +962,11 @@ BOOST_PYTHON_MODULE(mobase) bpy::class_, boost::noncopyable>("IPluginInstallerCustom") .def("onInstallationStart", &IPluginInstaller::onInstallationStart, (bpy::arg("archive"), bpy::arg("reinstallation"), bpy::arg("current_mod"))) .def("onInstallationEnd", &IPluginInstaller::onInstallationEnd, (bpy::arg("result"), bpy::arg("new_mod"))) + .def("registered", &MOBase::IPlugin::registered, &IPluginInstallerCustomWrapper::registered_Default) .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginInstallerCustomWrapper::localizedName_Default) .def("master", &MOBase::IPlugin::master, &IPluginInstallerCustomWrapper::master_Default, bpy::return_value_policy()) - // Needs to add both otherwize boost does not understand: + // Needs to add both otherwize boost does not understand: .def("isArchiveSupported", &IPluginInstaller::isArchiveSupported, bpy::arg("tree")) .def("isArchiveSupported", &IPluginInstallerCustom::isArchiveSupported, bpy::arg("archive_name")) .def("supportedExtensions", &IPluginInstallerCustom::supportedExtensions) @@ -970,6 +976,7 @@ BOOST_PYTHON_MODULE(mobase) ; bpy::class_, boost::noncopyable>("IPluginModPage") + .def("registered", &MOBase::IPlugin::registered, &IPluginModPageWrapper::registered_Default) .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginModPageWrapper::localizedName_Default) .def("master", &MOBase::IPlugin::master, &IPluginModPageWrapper::master_Default, bpy::return_value_policy()) @@ -983,15 +990,17 @@ BOOST_PYTHON_MODULE(mobase) ; bpy::class_, boost::noncopyable>("IPluginPreview") + .def("registered", &MOBase::IPlugin::registered, &IPluginPreviewWrapper::registered_Default) .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginPreviewWrapper::localizedName_Default) .def("master", &MOBase::IPlugin::master, &IPluginPreviewWrapper::master_Default, bpy::return_value_policy()) .def("supportedExtensions", bpy::pure_virtual(&IPluginPreview::supportedExtensions)) - .def("genFilePreview", bpy::pure_virtual(&IPluginPreview::genFilePreview), bpy::return_value_policy(), + .def("genFilePreview", bpy::pure_virtual(&IPluginPreview::genFilePreview), bpy::return_value_policy(), (bpy::arg("filename"), "max_size")) ; bpy::class_, boost::noncopyable>("IPluginTool") + .def("registered", &MOBase::IPlugin::registered, &IPluginToolWrapper::registered_Default) .def("localizedName", &MOBase::IPlugin::localizedName, &IPluginToolWrapper::localizedName_Default) .def("master", &MOBase::IPlugin::master, &IPluginToolWrapper::master_Default, bpy::return_value_policy()) @@ -1009,7 +1018,7 @@ BOOST_PYTHON_MODULE(mobase) bpy::def("getProductVersion", &MOBase::getProductVersion, bpy::arg("executable")); bpy::def("getIconForExecutable", &MOBase::iconForExecutable, bpy::arg("executable")); - // Expose MoVariant: MoVariant is a fake object whose only purpose is to be used as a type-hint + // Expose MoVariant: MoVariant is a fake object whose only purpose is to be used as a type-hint // on the python side (e.g., def foo(x: mobase.MoVariant)). The real MoVariant is defined in the // generated stubs, since it's only relevant when doing type-checking, but this needs to be defined, // otherwise MoVariant is not found when actually running plugins through MO2, making them crash. @@ -1116,7 +1125,7 @@ BOOST_PYTHON_MODULE(moprivate) using callback_t = std::function; - FileTree(std::shared_ptr parent, QString name, callback_t callback) : + FileTree(std::shared_ptr parent, QString name, callback_t callback) : FileTreeEntry(parent, name), IFileTree(), m_Callback(callback){ } std::shared_ptr addFile(QString name, bool) override { @@ -1221,7 +1230,7 @@ void PythonRunner::initPath() static QStringList paths = { QCoreApplication::applicationDirPath() + "/pythoncore.zip", QCoreApplication::applicationDirPath() + "/pythoncore", - m_MOInfo->pluginDataPath() + IOrganizer::getPluginDataPath() }; Py_SetPath(paths.join(';').toStdWString().c_str()); @@ -1255,8 +1264,8 @@ QList PythonRunner::instantiate(const QString &pluginName) // `pluginName` can either be a python file (single-file plugin or a folder (whole module). // - // For whole module, we simply add the parent folder to path, then we load the module with a simple - // bpy::import, and we retrieve the associated __dict__ from which we extract either createPlugin or + // For whole module, we simply add the parent folder to path, then we load the module with a simple + // bpy::import, and we retrieve the associated __dict__ from which we extract either createPlugin or // createPlugins. // // For single file, we need to use bpy::exec_file, and we will use the context (global variables) @@ -1356,7 +1365,7 @@ QList PythonRunner::instantiate(const QString &pluginName) } return allInterfaceList; - } + } catch (const bpy::error_already_set&) { MOBase::log::error("Failed to import plugin from {}.", pluginName); throw pyexcept::PythonError(); From 78e4e5c548a814da6d9f9df779604ccb028d93c8 Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 6 Nov 2020 09:22:23 -0500 Subject: [PATCH 4/5] binding for getPluginDataPath() --- src/runner/pythonrunner.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/runner/pythonrunner.cpp b/src/runner/pythonrunner.cpp index 5fbe5fb..bc733cc 100644 --- a/src/runner/pythonrunner.cpp +++ b/src/runner/pythonrunner.cpp @@ -362,6 +362,9 @@ BOOST_PYTHON_MODULE(mobase) return organizer->modList()->onModInstalled([func](MOBase::IModInterface* m) { func(m->name()); });; }, bpy::arg("callback")) + .def("getPluginDataPath", &IOrganizer::getPluginDataPath) + .staticmethod("getPluginDataPath") + ; // FileTreeEntry Scope: From 86297b11700aa01c759a0004b22738f32dac3c0e Mon Sep 17 00:00:00 2001 From: isanae <14251494+isanae@users.noreply.github.com> Date: Fri, 6 Nov 2020 09:25:01 -0500 Subject: [PATCH 5/5] removed unused IOrganizer from PythonRunner --- src/proxy/proxypython.cpp | 4 ++-- src/runner/pythonrunner.cpp | 10 ++++------ src/runner/pythonrunner.h | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/proxy/proxypython.cpp b/src/proxy/proxypython.cpp index fe3886f..eb9aa90 100644 --- a/src/proxy/proxypython.cpp +++ b/src/proxy/proxypython.cpp @@ -110,7 +110,7 @@ ProxyPython::~ProxyPython() } } -typedef IPythonRunner* (*CreatePythonRunner_func)(const MOBase::IOrganizer *moInfo, const QString &pythonPath); +typedef IPythonRunner* (*CreatePythonRunner_func)(const QString &pythonPath); bool ProxyPython::init(IOrganizer *moInfo) @@ -170,7 +170,7 @@ bool ProxyPython::init(IOrganizer *moInfo) m_MOInfo->setPersistent(name(), "tryInit", true); } - m_Runner = CreatePythonRunner(moInfo, pythonPath); + m_Runner = CreatePythonRunner(pythonPath); if (m_MOInfo) { m_MOInfo->setPersistent(name(), "tryInit", false); diff --git a/src/runner/pythonrunner.cpp b/src/runner/pythonrunner.cpp index bc733cc..0b27d2c 100644 --- a/src/runner/pythonrunner.cpp +++ b/src/runner/pythonrunner.cpp @@ -1035,7 +1035,7 @@ class PythonRunner : public IPythonRunner { public: - PythonRunner(const MOBase::IOrganizer* moInfo); + PythonRunner(); bool initPython(const QString& pythonDir); QList instantiate(const QString& pluginName); bool isPythonInstalled() const; @@ -1066,13 +1066,12 @@ private: // List of python objects representing plugins to keep all the bpy::object "alive" // during the execution. std::vector m_PythonObjects; - const MOBase::IOrganizer* m_MOInfo; wchar_t* m_PythonHome; }; -IPythonRunner* CreatePythonRunner(MOBase::IOrganizer* moInfo, const QString& pythonDir) +IPythonRunner* CreatePythonRunner(const QString& pythonDir) { - PythonRunner* result = new PythonRunner(moInfo); + PythonRunner* result = new PythonRunner; if (result->initPython(pythonDir)) { return result; } @@ -1082,8 +1081,7 @@ IPythonRunner* CreatePythonRunner(MOBase::IOrganizer* moInfo, const QString& pyt } } -PythonRunner::PythonRunner(const MOBase::IOrganizer *moInfo) - : m_MOInfo(moInfo) +PythonRunner::PythonRunner() { m_PythonHome = new wchar_t[MAX_PATH + 1]; } diff --git a/src/runner/pythonrunner.h b/src/runner/pythonrunner.h index ae5d620..73de994 100644 --- a/src/runner/pythonrunner.h +++ b/src/runner/pythonrunner.h @@ -22,7 +22,7 @@ public: #define PYDLLEXPORT Q_DECL_IMPORT #endif // PYTHONRUNNER_LIBRARY -extern "C" PYDLLEXPORT IPythonRunner *CreatePythonRunner(MOBase::IOrganizer *moInfo, const QString &pythonDir); +extern "C" PYDLLEXPORT IPythonRunner *CreatePythonRunner(const QString &pythonDir);