mirror of
https://github.com/ModOrganizer2/modorganizer-plugin_python.git
synced 2026-07-27 14:03:33 -07:00
Fix installers.
This commit is contained in:
@@ -153,7 +153,7 @@ QStringList ProxyPython::pluginList(const QDir& pluginPath) const
|
||||
QString name = iter.next();
|
||||
QFileInfo info = iter.fileInfo();
|
||||
|
||||
if (info.fileName() == "pyCfg.py") {
|
||||
if (info.fileName() == "pyCfg.py" || info.fileName() == "installer_wizard") {
|
||||
result.append(name);
|
||||
}
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <ipluginfilemapper.h>
|
||||
#include <iplugingame.h>
|
||||
#include <iplugininstaller.h>
|
||||
#include <iplugininstallersimple.h>
|
||||
#include <ipluginlist.h>
|
||||
#include <ipluginmodpage.h>
|
||||
#include <ipluginpreview.h>
|
||||
@@ -55,9 +56,12 @@ PYBIND11_MODULE(mobase, m)
|
||||
//
|
||||
mo2::python::add_basic_bindings(m);
|
||||
mo2::python::add_wrapper_bindings(m);
|
||||
mo2::python::add_plugins_bindings(m);
|
||||
|
||||
// game features must be added before plugins
|
||||
mo2::python::add_game_feature_bindings(m);
|
||||
|
||||
mo2::python::add_plugins_bindings(m);
|
||||
|
||||
// widgets
|
||||
//
|
||||
py::module_ widgets(
|
||||
@@ -96,6 +100,12 @@ PYBIND11_MODULE(mobase, m)
|
||||
std::cout << fmt::format(" plugin {}: {} -> {}\n", i, (void*)qobjects[i],
|
||||
(void*)plugin);
|
||||
std::cout << fmt::format(" name: {}\n", plugin->name().toStdString());
|
||||
std::cout << fmt::format(
|
||||
" installer?: {}\n",
|
||||
(void*)qobject_cast<IPluginInstaller*>(qobjects[i]));
|
||||
std::cout << fmt::format(
|
||||
" installer simple?: {}\n",
|
||||
(void*)qobject_cast<IPluginInstallerSimple*>(qobjects[i]));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -8,12 +8,105 @@
|
||||
#include "../pybind11_qt/pybind11_qt.h"
|
||||
|
||||
#include <moddatachecker.h>
|
||||
#include <scriptextender.h>
|
||||
|
||||
#include "pyfiletree.h"
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace MOBase;
|
||||
using namespace pybind11::literals;
|
||||
|
||||
namespace mo2::python {
|
||||
|
||||
void add_game_feature_bindings(pybind11::module_ m) {}
|
||||
class PyModDataChecker : public ModDataChecker {
|
||||
public:
|
||||
CheckReturn
|
||||
dataLooksValid(std::shared_ptr<const MOBase::IFileTree> fileTree) const override
|
||||
{
|
||||
PYBIND11_OVERRIDE_PURE(CheckReturn, ModDataChecker, dataLooksValid,
|
||||
fileTree);
|
||||
}
|
||||
|
||||
std::shared_ptr<MOBase::IFileTree>
|
||||
fix(std::shared_ptr<MOBase::IFileTree> fileTree) const override
|
||||
{
|
||||
PYBIND11_OVERRIDE(std::shared_ptr<MOBase::IFileTree>, ModDataChecker, fix,
|
||||
fileTree);
|
||||
}
|
||||
};
|
||||
|
||||
class PyScriptExtender : public ScriptExtender {
|
||||
public:
|
||||
QString BinaryName() const override
|
||||
{
|
||||
PYBIND11_OVERRIDE_PURE(QString, ScriptExtender, BinaryName, );
|
||||
}
|
||||
|
||||
QString PluginPath() const override
|
||||
{
|
||||
PYBIND11_OVERRIDE_PURE(QString, ScriptExtender, PluginPath, );
|
||||
}
|
||||
|
||||
QString loaderName() const override
|
||||
{
|
||||
PYBIND11_OVERRIDE_PURE(QString, ScriptExtender, loaderName, );
|
||||
}
|
||||
|
||||
QString loaderPath() const override
|
||||
{
|
||||
PYBIND11_OVERRIDE_PURE(QString, ScriptExtender, loaderPath, );
|
||||
}
|
||||
|
||||
QString savegameExtension() const override
|
||||
{
|
||||
PYBIND11_OVERRIDE_PURE(QString, ScriptExtender, savegameExtension, );
|
||||
}
|
||||
|
||||
bool isInstalled() const override
|
||||
{
|
||||
PYBIND11_OVERRIDE_PURE(bool, ScriptExtender, isInstalled, );
|
||||
}
|
||||
|
||||
QString getExtenderVersion() const override
|
||||
{
|
||||
PYBIND11_OVERRIDE_PURE(QString, ScriptExtender, getExtenderVersion, );
|
||||
}
|
||||
|
||||
WORD getArch() const override
|
||||
{
|
||||
PYBIND11_OVERRIDE_PURE(WORD, ScriptExtender, getArch, );
|
||||
}
|
||||
};
|
||||
|
||||
void add_game_feature_bindings(pybind11::module_ m)
|
||||
{
|
||||
// ModDataChecker
|
||||
|
||||
py::class_<ModDataChecker, PyModDataChecker> pyModDataChecker(m,
|
||||
"ModDataChecker");
|
||||
|
||||
py::enum_<ModDataChecker::CheckReturn>(pyModDataChecker, "CheckReturn")
|
||||
.value("INVALID", ModDataChecker::CheckReturn::INVALID)
|
||||
.value("FIXABLE", ModDataChecker::CheckReturn::FIXABLE)
|
||||
.value("VALID", ModDataChecker::CheckReturn::VALID)
|
||||
.export_values();
|
||||
|
||||
pyModDataChecker.def(py::init<>())
|
||||
.def("dataLooksValid", &ModDataChecker::dataLooksValid, "filetree"_a)
|
||||
.def("fix", &ModDataChecker::fix, "filetree"_a);
|
||||
|
||||
// ScriptExtender
|
||||
|
||||
py::class_<ScriptExtender, PyScriptExtender>(m, "ScriptExtender")
|
||||
.def(py::init<>())
|
||||
.def("BinaryName", &ScriptExtender::BinaryName)
|
||||
.def("PluginPath", &ScriptExtender::PluginPath)
|
||||
.def("loaderName", &ScriptExtender::loaderName)
|
||||
.def("loaderPath", &ScriptExtender::loaderPath)
|
||||
.def("savegameExtension", &ScriptExtender::savegameExtension)
|
||||
.def("isInstalled", &ScriptExtender::isInstalled)
|
||||
.def("getExtenderVersion", &ScriptExtender::getExtenderVersion)
|
||||
.def("getArch", &ScriptExtender::getArch);
|
||||
}
|
||||
|
||||
} // namespace mo2::python
|
||||
|
||||
@@ -1,17 +1,53 @@
|
||||
#include "wrappers.h"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
#include "pyplugins.h"
|
||||
|
||||
#include <bsainvalidation.h>
|
||||
#include <dataarchives.h>
|
||||
#include <gameplugins.h>
|
||||
#include <localsavegames.h>
|
||||
#include <moddatachecker.h>
|
||||
#include <moddatacontent.h>
|
||||
#include <savegameinfo.h>
|
||||
#include <scriptextender.h>
|
||||
#include <unmanagedmods.h>
|
||||
|
||||
namespace py = pybind11;
|
||||
using namespace pybind11::literals;
|
||||
using namespace MOBase;
|
||||
|
||||
namespace mo2::python {
|
||||
|
||||
class GameFeaturesHelper {
|
||||
using GameFeatures = std::tuple<
|
||||
// BSAInvalidation, DataArchives, GamePlugins, LocalSavegames,
|
||||
ModDataChecker,
|
||||
// ModDataContent, SaveGameInfo,
|
||||
ScriptExtender
|
||||
// , UnmanagedMods
|
||||
>;
|
||||
|
||||
template <class F, std::size_t... Is>
|
||||
static void helper(F&& f, std::index_sequence<Is...>)
|
||||
{
|
||||
(f(static_cast<std::tuple_element_t<Is, GameFeatures>*>(nullptr)), ...);
|
||||
}
|
||||
|
||||
public:
|
||||
// apply the function f on a null-pointer of type Feature* for each game
|
||||
// feature
|
||||
template <class F>
|
||||
static void apply(F&& f)
|
||||
{
|
||||
helper(f, std::make_index_sequence<std::tuple_size_v<GameFeatures>>{});
|
||||
}
|
||||
};
|
||||
|
||||
// this one is kind of big so it has its own function
|
||||
void add_iplugingame_bindings(pybind11::module_ m)
|
||||
{
|
||||
|
||||
py::enum_<MOBase::IPluginGame::LoadOrderMechanism>(m, "LoadOrderMechanism")
|
||||
.value("FileTime", MOBase::IPluginGame::LoadOrderMechanism::FileTime)
|
||||
.value("PluginsTxt", MOBase::IPluginGame::LoadOrderMechanism::PluginsTxt)
|
||||
@@ -38,125 +74,107 @@ namespace mo2::python {
|
||||
.value("SAVEGAMES", MOBase::IPluginGame::SAVEGAMES)
|
||||
.value("PREFER_DEFAULTS", MOBase::IPluginGame::PREFER_DEFAULTS);
|
||||
|
||||
// py::class_<IPluginGameWrapper, py::bases<IPlugin>,
|
||||
// boost::noncopyable>("IPluginGame")
|
||||
// .def("localizedName", &MOBase::IPlugin::localizedName,
|
||||
// &IPluginGameWrapper::localizedName_Default) .def("master",
|
||||
// &MOBase::IPlugin::master, &IPluginGameWrapper::master_Default)
|
||||
py::class_<IPluginGame, IPlugin, std::unique_ptr<IPluginGame, py::nodelete>>(
|
||||
m, "IPluginGame")
|
||||
|
||||
// .def("detectGame",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::detectGame))
|
||||
// .def("gameName",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameName))
|
||||
// .def("initializeProfile",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::initializeProfile),
|
||||
// (py::arg("directory"), "settings")) .def("listSaves",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::listSaves),
|
||||
// py::arg("folder")) .def("isInstalled",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::isInstalled))
|
||||
// .def("gameIcon",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameIcon))
|
||||
// .def("gameDirectory",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameDirectory))
|
||||
// .def("dataDirectory",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::dataDirectory))
|
||||
// .def("setGamePath",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::setGamePath),
|
||||
// py::arg("path")) .def("documentsDirectory",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::documentsDirectory))
|
||||
// .def("savesDirectory",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::savesDirectory))
|
||||
// .def("executables",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::executables))
|
||||
// .def("executableForcedLoads",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::executableForcedLoads))
|
||||
// .def("steamAPPId",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::steamAPPId))
|
||||
// .def("primaryPlugins",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::primaryPlugins))
|
||||
// .def("gameVariants",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameVariants))
|
||||
// .def("setGameVariant",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::setGameVariant),
|
||||
// py::arg("variant")) .def("binaryName",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::binaryName))
|
||||
// .def("gameShortName",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameShortName))
|
||||
// .def("primarySources",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::primarySources))
|
||||
// .def("validShortNames",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::validShortNames))
|
||||
// .def("gameNexusName",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameNexusName))
|
||||
// .def("iniFiles",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::iniFiles))
|
||||
// .def("DLCPlugins",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::DLCPlugins))
|
||||
// .def("CCPlugins",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::CCPlugins))
|
||||
// .def("loadOrderMechanism",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::loadOrderMechanism))
|
||||
// .def("sortMechanism",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::sortMechanism))
|
||||
// .def("nexusModOrganizerID",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::nexusModOrganizerID))
|
||||
// .def("nexusGameID",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::nexusGameID))
|
||||
// .def("looksValid",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::looksValid),
|
||||
// py::arg("directory")) .def("gameVersion",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameVersion))
|
||||
// .def("getLauncherName",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::getLauncherName))
|
||||
.def("featureList",
|
||||
[](MOBase::IPluginGame* p) {
|
||||
// constructing a dict from class name to actual object
|
||||
py::dict dict;
|
||||
GameFeaturesHelper::apply(
|
||||
[p, &dict]<class Feature>(Feature* feature) {
|
||||
const auto name = py::type::of<Feature>().attr("__name__");
|
||||
dict[name] = py::cast(p->feature<Feature>(),
|
||||
py::return_value_policy::reference);
|
||||
});
|
||||
return dict;
|
||||
})
|
||||
|
||||
// .def("featureList", +[](MOBase::IPluginGame* p) {
|
||||
// // Constructing a dict from class name to actual object:
|
||||
// py::dict dict;
|
||||
// mp11::mp_for_each<
|
||||
// // Must user pointers because mp_for_each construct object:
|
||||
// mp11::mp_transform<std::add_pointer_t, MpGameFeaturesList>
|
||||
// >([&](auto* pt) {
|
||||
// using T = std::remove_pointer_t<decltype(pt)>;
|
||||
// typename py::reference_existing_object::apply<T*>::type
|
||||
// converter;
|
||||
.def(
|
||||
"feature",
|
||||
[](MOBase::IPluginGame* p, py::object clsObj) {
|
||||
py::object py_feature = py::none();
|
||||
|
||||
// // Retrieve the python class object:
|
||||
// const py::converter::registration* registration =
|
||||
// py::converter::registry::query(py::type_id<T>()); py::object
|
||||
// key
|
||||
// =
|
||||
// py::object(py::handle<>(py::borrowed(registration->get_class_object())));
|
||||
GameFeaturesHelper::apply([p, &clsObj, &py_feature]<class Feature>(
|
||||
Feature* feature) {
|
||||
if (py::type::of<Feature>().is(clsObj)) {
|
||||
py_feature = py::cast(p->feature<Feature>(),
|
||||
py::return_value_policy::reference);
|
||||
}
|
||||
});
|
||||
return py_feature;
|
||||
},
|
||||
"feature_type"_a, py::return_value_policy::reference)
|
||||
|
||||
// // Set the object:
|
||||
// dict[key] = py::handle<>(converter(p->feature<T>()));
|
||||
// });
|
||||
// return dict;
|
||||
// })
|
||||
// .def("localizedName", &MOBase::IPlugin::localizedName,
|
||||
// &IPluginGameWrapper::localizedName_Default) .def("master",
|
||||
// &MOBase::IPlugin::master, &IPluginGameWrapper::master_Default)
|
||||
|
||||
// .def("feature", +[](MOBase::IPluginGame* p, py::object clsObj) {
|
||||
// py::object feature;
|
||||
// mp11::mp_for_each<
|
||||
// // Must user pointers because mp_for_each construct object:
|
||||
// mp11::mp_transform<std::add_pointer_t, MpGameFeaturesList>
|
||||
// >([&](auto* pt) {
|
||||
// using T = std::remove_pointer_t<decltype(pt)>;
|
||||
// typename py::reference_existing_object::apply<T*>::type
|
||||
// converter;
|
||||
|
||||
// // Retrieve the python class object:
|
||||
// const py::converter::registration* registration =
|
||||
// py::converter::registry::query(py::type_id<T>());
|
||||
|
||||
// if (clsObj.ptr() == (PyObject*)
|
||||
// registration->get_class_object())
|
||||
// {
|
||||
// feature =
|
||||
// py::object(py::handle<>(converter(p->feature<T>())));
|
||||
// }
|
||||
// });
|
||||
// return feature;
|
||||
// }, py::arg("feature_type"))
|
||||
// ;
|
||||
// .def("detectGame",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::detectGame))
|
||||
// .def("gameName",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameName))
|
||||
// .def("initializeProfile",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::initializeProfile),
|
||||
// (py::arg("directory"), "settings")) .def("listSaves",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::listSaves),
|
||||
// py::arg("folder")) .def("isInstalled",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::isInstalled))
|
||||
// .def("gameIcon",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameIcon))
|
||||
// .def("gameDirectory",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameDirectory))
|
||||
.def("dataDirectory", &MOBase::IPluginGame::dataDirectory)
|
||||
// .def("setGamePath",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::setGamePath),
|
||||
// py::arg("path")) .def("documentsDirectory",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::documentsDirectory))
|
||||
// .def("savesDirectory",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::savesDirectory))
|
||||
// .def("executables",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::executables))
|
||||
// .def("executableForcedLoads",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::executableForcedLoads))
|
||||
// .def("steamAPPId",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::steamAPPId))
|
||||
// .def("primaryPlugins",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::primaryPlugins))
|
||||
// .def("gameVariants",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameVariants))
|
||||
// .def("setGameVariant",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::setGameVariant),
|
||||
// py::arg("variant")) .def("binaryName",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::binaryName))
|
||||
// .def("gameShortName",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameShortName))
|
||||
// .def("primarySources",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::primarySources))
|
||||
// .def("validShortNames",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::validShortNames))
|
||||
// .def("gameNexusName",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameNexusName))
|
||||
// .def("iniFiles",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::iniFiles))
|
||||
// .def("DLCPlugins",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::DLCPlugins))
|
||||
// .def("CCPlugins",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::CCPlugins))
|
||||
// .def("loadOrderMechanism",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::loadOrderMechanism))
|
||||
// .def("sortMechanism",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::sortMechanism))
|
||||
// .def("nexusModOrganizerID",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::nexusModOrganizerID))
|
||||
// .def("nexusGameID",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::nexusGameID))
|
||||
// .def("looksValid",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::looksValid),
|
||||
// py::arg("directory")) .def("gameVersion",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::gameVersion))
|
||||
// .def("getLauncherName",
|
||||
// py::pure_virtual(&MOBase::IPluginGame::getLauncherName))
|
||||
//
|
||||
;
|
||||
}
|
||||
|
||||
// multiple installers
|
||||
|
||||
@@ -262,7 +262,8 @@ namespace mo2::python {
|
||||
class PyPluginInstallerCustom
|
||||
: public PyPluginInstallerBase<IPluginInstallerCustom> {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginInstallerCustom)
|
||||
Q_INTERFACES(
|
||||
MOBase::IPlugin MOBase::IPluginInstaller MOBase::IPluginInstallerCustom)
|
||||
public:
|
||||
bool isArchiveSupported(const QString& archiveName) const
|
||||
{
|
||||
@@ -288,7 +289,8 @@ namespace mo2::python {
|
||||
class PyPluginInstallerSimple
|
||||
: public PyPluginInstallerBase<IPluginInstallerSimple> {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginInstallerSimple)
|
||||
Q_INTERFACES(
|
||||
MOBase::IPlugin MOBase::IPluginInstaller MOBase::IPluginInstallerSimple)
|
||||
public:
|
||||
using py_install_return_type =
|
||||
std::variant<IPluginInstaller::EInstallResult, std::shared_ptr<IFileTree>,
|
||||
|
||||
+1881
-1423
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user