Compare commits

...
206 Commits
Author SHA1 Message Date
Chris Bessent 67abab0779 Merge pull request #28 from ModOrganizer2/Develop
Stage for release 2.2.2
2020-01-06 05:11:19 -07:00
Silarn b0ef81214a Fix cmakelists and use zip 2019-10-29 01:35:15 -05:00
Silarn b2ae43a0e5 Add lightPluginsAreSupported to the wrapped game plugin functions 2019-10-19 02:28:01 -05:00
LostDragonist 52dd7454be Update version 2019-10-06 17:22:09 -05:00
LostDragonist 059dc8b9d2 Report plugin as active even if failed
This is required for the plugin to report notifications.  This
behavior was changed in the main MO program at some point.
2019-10-06 17:20:53 -05:00
Silarn b8bcecbed4 Update Appveyor to official VS 2019 image 2019-09-28 00:41:47 -05:00
Jeremy Rimpo 42e559b59c Merge pull request #26 from ModOrganizer2/Develop
Stage for release 2.2.1
2019-07-22 01:02:42 -05:00
Jeremy Rimpo b7d343a8dd Merge pull request #27 from AnyOldName3/message-forwarding
Message forwarding
2019-07-22 00:56:29 -05:00
AnyOldName3 63a6c504b0 Restore logging of historically-logged Python exceptions. 2019-07-22 00:08:35 +01:00
AnyOldName3 19dcdd95c0 Prevent PyQt from using its buggy exception logging by making it look like we're using custom exception handling. 2019-07-15 20:04:44 +01:00
AnyOldName3 ac5540ba87 Forward Python stdout and stderr to qDebug and qCritical 2019-07-15 20:02:18 +01:00
Silarn 0708bdedbf Improve error parser for _C_API loader 2019-07-02 12:33:18 -05:00
Silarn 2b6f453fbc Add better error handling when loading the SIP API 2019-07-01 22:19:14 -05:00
Brian Munro 4f86e542cc Merge pull request #25 from AnyOldName3/sip-transfer-fix
Correctly use SIP to transfer ownership of objects from Python to C++
2019-06-01 09:02:05 +02:00
AnyOldName3 e280b07cb6 Correctly use SIP to transfer ownership of objects from Python to C++ 2019-06-01 00:59:39 +01:00
Silarn 0c11e75f0f Set optimization for release builds 2019-05-22 02:04:22 -05:00
Silarn ab72c2f42f Fix artifact paths 2019-05-22 01:07:13 -05:00
Silarn cbe679aad8 Add logs to build artifacts on CI fail, commit translation changes 2019-05-21 23:46:06 -05:00
Silarn 59e5f1acf2 Switch to local build files as appveyor can't use installed files 2019-05-21 02:27:58 -05:00
Silarn d0598cd849 Unify artifacts source path to install path 2019-05-21 01:37:18 -05:00
Silarn 174abb3cea Enable parallel building 2019-05-09 02:10:42 -05:00
Silarn dee8825960 Set appveyor image to VS 2019 Preview 2019-05-08 23:10:34 -05:00
LostDragonist 46a4ee8653 Merge pull request #24 from ModOrganizer2/Develop
Stage for Release 2.2.0
2019-05-03 21:09:18 -05:00
Brian Munro 4721ab35df Merge pull request #23 from ModOrganizer2/Appveyor
Support Appveyor.
2019-04-29 14:18:19 +02:00
LePresidente 352e5c2103 Fixed artifacts for proxy_python. 2019-04-29 14:07:19 +02:00
LePresidente 78278ae57d Support Appveyor. 2019-04-29 10:30:47 +02:00
LostDragonist 3eb85cd17f Update for startApplication 2019-03-24 21:28:13 -05:00
Brian Munro 208965b96d Merge pull request #22 from ModOrganizer2/Appveyor
Removed unneeded cmake variables due to that umbrella handles them co…
2019-03-09 20:20:01 +02:00
LostDragonist c17d703b15 Add function for tracking status 2019-03-07 11:20:59 -06:00
LostDragonist 65eb0c6374 Add function to get configured mods directory 2019-02-23 07:11:19 -06:00
LostDragonist 97a20d522a Add setGameName to the mod interface 2019-02-22 22:16:17 -06:00
Silarn caee1fb7f6 Change to uibase requires Qt5Network linkage 2019-02-18 21:40:12 -06:00
Silarn bab649af43 Update to support API changes to uibase 2019-02-18 21:40:12 -06:00
Brian Munro 30ab7b8e14 Removed unneeded cmake variables due to that umbrella handles them correctly.
Requires testing.
2019-02-12 21:37:41 +02:00
LostDragonist 956d481ca4 Make logs more consistent in format and content 2019-01-30 20:53:48 -06:00
LostDragonist 41a4f273d6 Support for force loading libraries 2019-01-11 01:39:05 -06:00
LostDragonist 66391098b6 Update version to 2.0.1.0 2019-01-05 16:43:30 -06:00
LostDragonist c9d77cf948 Change qPrintable to qUtf8Printable to better support non-ASCII text 2019-01-05 16:34:11 -06:00
LostDragonist b939f7e88e Add enumerations for plugin states and mod states 2018-12-21 02:30:58 -06:00
LostDragonist be6b102599 Merge pull request #21 from ModOrganizer2/Develop
Stage for release 2.1.6
2018-12-20 13:58:41 -06:00
LostDragonist a1bc87e75a Fix the crash in a better, non-leaky way 2018-12-17 17:56:24 -06:00
LostDragonist 4160dea823 Convert a crash when converting strings to QStrings to possibly a memory leak 2018-12-16 18:27:45 -06:00
LostDragonist 1bd5dda7d8 Update version to 2.0.0.0 2018-12-12 02:14:02 -06:00
LostDragonist 9780aeb477 Improve refresh of data when changing profile settings 2018-12-08 00:12:09 -06:00
LostDragonist f6d41a1a81 Update for archive invalidation changes 2018-12-05 06:34:30 -06:00
Al 69ff972b12 Merge pull request #20 from AnyOldName3/settable-plugin-settings
Fix typo preventing IOrganizer::setPluginSetting from being used in P…
2018-09-25 20:28:15 +02:00
Al ada342e818 Merge pull request #19 from AnyOldName3/qvariant-from-unicode
Add missing PyUnicode_Check which prevented QVariants being created f…
2018-09-25 20:27:58 +02:00
AnyOldName3 051c14fe72 Add working version of IOrganizer::waitForApplication (#18) 2018-09-25 20:27:23 +02:00
AnyOldName3 f841a3b13a Add support for the default (invalid) QVariant 2018-09-19 22:52:40 +01:00
AnyOldName3 60701b6ba0 Add forgotten PyDict_Check 2018-09-19 22:36:11 +01:00
AnyOldName3 a8cf8d45f3 Fix typo preventing IOrganizer::setPluginSetting from being used in Python 2018-09-19 22:16:50 +01:00
AnyOldName3 84c04c32dc Add missing PyUnicode_Check which prevented QVariants being created from Python 3 strings 2018-09-19 21:45:42 +01:00
Al 6ce4138b31 Add new function wrapper for archive conflicts (#17) 2018-09-09 23:28:53 +02:00
Silarn d1f6766e16 Allow installs to pass Mod ID through (fixes NCC installs losing ID) 2018-09-09 04:20:21 -05:00
LostDragonist aa2b0744f7 Update for changes to local save game class 2018-08-26 17:55:31 -05:00
Jeremy Rimpo f1997b4788 Merge pull request #15 from ModOrganizer2/python3
Migrate to python 3.7
2018-08-23 11:48:07 -05:00
Brian Munro 423e6f8842 Merge pull request #14 from Modorganizer2/Develop
Stage for 2.1.5 release
2018-08-21 12:11:25 +02:00
Silarn b5b547e041 Changes to compile and run with python3 (WIP) 2018-08-20 19:01:18 -05:00
Silarn 61977d6149 Remove archive conflict code from python 3 branch 2018-08-20 19:00:06 -05:00
Silarn fbf59519c0 Fix to use modularized sip API and embedded python libs 2018-08-20 18:49:15 -05:00
Silarn 08bcebe19c Changes to compile and run with python3 (WIP) 2018-08-20 18:49:15 -05:00
LostDragonist 4900135130 Merge pull request #13 from AnyOldName3/free-plugin-support
Add support for free plugins which don't implement any specialised interface
2018-08-15 15:41:55 -05:00
AnyOldName3 b70fa8174e Add support for free plugins which don't implement any specialised interface 2018-08-15 15:34:08 +01:00
Brian Munro 437d89fc04 Merge pull request #12 from Modorganizer2/Develop
Stage for 2.1.3 release
2018-05-08 12:20:04 +02:00
Silarn 51b59de04d Changes to allow installer_NCC to use the game source set in the DL meta 2018-05-07 01:28:59 -05:00
Silarn 19015289cb Updating gitignore 2018-05-04 00:28:40 -05:00
Silarn e004b56dc9 Fit primarySources to new wrapper method 2018-05-03 22:32:31 -05:00
Jeremy Rimpo fba18c2b96 Merge pull request #11 from AnyOldName3/reusable-wrapper-template
Helpful error message and reduce code duplication
2018-05-03 20:49:05 -05:00
AnyOldName3 00c38f5f03 Remove superfluous template parameter specification to shrink lines to a more readable length. 2018-05-03 22:22:32 +01:00
AnyOldName3 8919fbd351 Use new template for game features wrappers. 2018-05-03 22:19:55 +01:00
Silarn 6a3a257ecd Allow for primary game sources and marking mods as converted/working 2018-05-03 16:17:39 -05:00
AnyOldName3 ec4945db3e Use new template for (non-pointless) uibase wrappers. 2018-05-03 22:02:06 +01:00
AnyOldName3 9f975b92b2 Create template for wrapper functions and add helpful error message. Use this for plugin wrappers. 2018-05-03 21:56:23 +01:00
Jeremy Rimpo 17c86ef540 Merge pull request #10 from AnyOldName3/proxy-multiple-inheritance-support
Return a plugin as multiple (differently-typed) instances to work aro…
2018-05-02 14:02:13 -05:00
AnyOldName3 7ab4b71ed3 Return a plugin as multiple (differently-typed) instances to work around multiple inheritance issues 2018-05-02 17:24:09 +01:00
Jeremy Rimpo 61ecb68918 Merge pull request #9 from AnyOldName3/implement-more-interfaces-2
Implement more interfaces
2018-05-01 18:25:53 -05:00
AnyOldName3 94886104f3 Prevent the C++ part of PyQt objects being deleted while the Python component is still accessible. 2018-05-02 00:19:29 +01:00
AnyOldName3 902024e508 Add Game Features support 2018-04-25 17:25:12 +01:00
AnyOldName3 0a9b4b9fc4 Change the capitalisation of sipapiaccess.h to make it consistent with other files 2018-04-22 15:39:09 +01:00
AnyOldName3 028c14a951 Add missing include guard to sipApiAccess.h 2018-04-22 15:37:29 +01:00
AnyOldName3 bf8f427cd8 Move sipAPI getter function to a shared header so it isn't duplicated. 2018-04-22 00:59:42 +01:00
AnyOldName3 8fe091ab48 Implement IPluginProxy bindings. 2018-04-22 00:34:59 +01:00
AnyOldName3 8877fee4fa Implement IpluginModPage bindings. 2018-04-20 16:40:39 +01:00
AnyOldName3 f13a5961df Align ModRepositoryFileInfo indentation 2018-04-20 16:40:39 +01:00
AnyOldName3 7b6ca76dec Handle conversion for types IPluginModPage depends on 2018-04-20 16:40:39 +01:00
AnyOldName3 a35208d902 Improve QVariant conversion and generalise QMap conversion 2018-04-20 16:40:39 +01:00
AnyOldName3 4feb06a099 Add IPluginFileMapper Wrapper and bindings. 2018-04-20 16:40:39 +01:00
AnyOldName3 0abbab9f8c Add missing parts of IOrganizer bindings 2018-04-20 16:40:39 +01:00
AnyOldName3 86d859d430 Allow anonymous Python functions to return values 2018-04-20 16:40:38 +01:00
AnyOldName3 5a730941db Implement wrapper and bindings for IPluginDiagnose 2018-04-20 16:40:38 +01:00
AnyOldName3 c70f78adfe Reduce code duplication by moving common implementation to macros 2018-04-20 16:40:38 +01:00
AnyOldName3 e8af8819df Add PYCATCH missed when rebasing 2018-04-20 16:40:38 +01:00
AnyOldName3 de809c6d57 Fix simple errors with IPluginGame proxy and add warning when the unimplemented part is encountered 2018-04-20 16:40:38 +01:00
AnyOldName3 01168483c5 handle errors in Python game plugins 2018-04-20 16:40:38 +01:00
AnyOldName3 317f13177e Move IPluginGameWrapper's mentod implementations into the cpp file 2018-04-20 16:40:38 +01:00
AnyOldName3 c47b94d534 Restore indentation which rearraging things broke 2018-04-20 16:40:38 +01:00
AnyOldName3 ca51a53d41 Make IPluginGameWrapper into a class and include the necessary Qt annotations 2018-04-20 16:40:38 +01:00
AnyOldName3 9722d5b093 Move IPluginGameWrapper to proxypluginwrappers.h as it's a wrapper for a plugin. 2018-04-20 16:40:38 +01:00
AnyOldName3 2df983e22c Create ExecutableInfo interface 2018-04-20 16:40:38 +01:00
AnyOldName3 52417d64e4 Implement missing handling for QFileInfo 2018-04-20 16:40:38 +01:00
AnyOldName3 4a558d4caf Implement from_python handling for QStringList 2018-04-20 16:40:38 +01:00
AnyOldName3 8dd9a710b4 Replace wrong QDir converter 2018-04-20 16:40:38 +01:00
AnyOldName3 377199f233 Put plugin wrappers in alphabetical order 2018-04-20 16:40:38 +01:00
Silarn 18a73c2f54 Remove remnants of QtScript and fix some CMake issues 2018-04-19 01:43:57 -05:00
Silarn fba28bb9ab Add SortMechanism check 2018-04-18 03:30:09 -05:00
Silarn cdbc0f3bdb Support for multi-game downloads 2018-04-16 13:07:56 -05:00
Silarn ffbd4e3f11 Support for multi-game downloads 2018-04-16 12:51:40 -05:00
Jeremy Rimpo e1ba01777d Merge pull request #8 from AnyOldName3/version-info-missing-parts
Add missing comparison operators and functions for MOBase::VersionInfo
2018-04-13 12:44:29 -05:00
Jeremy Rimpo 9cbb35d354 Merge pull request #7 from AnyOldName3/cleanup
Cleanup dead code & update .gitignore
2018-04-13 12:43:44 -05:00
Brian Munro abff0e890d Merge pull request #6 from Modorganizer2/Develop
Merge to Master for Release
2018-04-13 08:44:06 +02:00
Jeremy Rimpo c076d7a8bb Remove extraneous search code 2018-04-13 00:38:21 -05:00
AnyOldName3 e277c9b56b Add missing comparison operators and functions for MOBase::VersionInfo 2018-04-12 01:16:27 +01:00
AnyOldName3 d8ad6569ba remove dead include 2018-04-11 17:27:23 +01:00
AnyOldName3 e08b8be570 Remove dead code 2018-04-11 17:12:27 +01:00
AnyOldName3 aca861194d Update .gitignore with msbuild stuff 2018-04-11 17:10:55 +01:00
Silarn fdffe6f277 Prep for Qt 5.11 (backward-compatible) 2018-04-10 23:28:32 -05:00
Silarn 341daf5c5f Fix up CMAKE to use /MP and allow building through umbrella 2018-04-07 17:12:21 -05:00
Jeremy Rimpo b272bd12fe Merge pull request #5 from Modorganizer2/LePresidente-patch-1
Fixed typo causing compilation to fail
2018-03-19 13:33:10 -05:00
Brian Munro d6b673f149 Fixed typo causing compilation to fail
Fixed typo causing compilation to fail
2018-03-19 11:05:00 +02:00
Jeremy Rimpo 81ec421adb Merge pull request #4 from AnyOldName3/better-qflags-support
Better QFlags support
2018-03-17 00:02:12 -05:00
AnyOldName3 f3fa0baa41 Make indentation consistent 2018-03-17 00:35:59 +00:00
AnyOldName3 9a3465cc7a Register converters for all remaining uses of QFlags in the Python wrappers 2018-03-17 00:19:45 +00:00
AnyOldName3 277a2862b1 Make QFlags conversion bidirectional and register the converter for more uses of QFlags 2018-03-17 00:05:17 +00:00
Jeremy Rimpo 046e080943 Merge pull request #3 from AnyOldName3/register-missing-functions
Register some functions which Tannin created wrappers for, but omitte…
2018-03-16 13:28:41 -05:00
AnyOldName3 af7823b920 Register some functions which Tannin created wrappers for, but omitted to make accessible from Python 2018-03-16 17:03:48 +00:00
Jeremy Rimpo d408512a2c Merge pull request #2 from AnyOldName3/full-unicode-support
Allow conversion of any unicode sequence into a QString
2018-03-15 22:25:04 -05:00
AnyOldName3 10437e0aca Allow conversion of any unicode sequence into a QString 2018-03-16 00:32:21 +00:00
Al c6e8a223e1 Merge pull request #1 from AnyOldName3/unicode-support
Add support for converting Python unicode strings to QStrings
2018-03-15 23:26:31 +01:00
AnyOldName3 425ec8df5a Add support for converting Python unicode strings to QStrings 2018-03-15 21:21:23 +00:00
Jeremy Rimpo 39e17ebbe3 Merge pull request #6 from Silarn/mainline_dev
Allow getLauncherName to be overridden
2017-12-12 15:44:01 -06:00
Jeremy Rimpo fc0a257b51 Allow getLauncherName to be overridden 2017-12-12 12:41:28 -06:00
Brian Munro fe87c841a8 Merge pull request #5 from Silarn/mainline_dev
Add QDir and required function to pythonrunner to fix missing definition
2017-12-08 19:40:40 +02:00
Jeremy Rimpo 705d423839 Add QDir and required function to pythonrunner to fix missing definition 2017-12-08 02:41:53 -06:00
Brian Munro 9dff2ab02e Merge pull request #4 from Silarn/mainline_dev
Add CCPlugins support
2017-12-03 07:51:57 +02:00
Jeremy Rimpo 1bc41a72b4 Add CCPlugins support 2017-11-18 12:28:36 -06:00
Brian Munro d212bff9e9 Merge pull request #3 from Silarn/mainline_dev
Fix bind failure due to function overload and move to std bind (MSVC 2017 - Boost 1.65.1)
2017-11-05 17:26:29 +02:00
Jeremy Rimpo 85cb9b18e4 Fix bind failure due to function overload and move to std bind 2017-11-05 03:49:56 -06:00
LePresidente 6a5ab7f747 Updated cmakelists to get the QT5 location from the QT_ROOT variable, instead of expecting it in DEPENDENCIES_DIR. 2017-09-21 16:48:15 +02:00
Brian Munro 539b068b71 Merge pull request #2 from Hugues92/master
Cannot override basePath as it is not present in parent class
2017-03-29 07:35:28 -07:00
Hugues92 96dbb56467 Cannot override basePath as it is not present in parent class 2017-03-22 23:22:38 +01:00
Brian Munro ea408a05af Merge pull request #1 from ZachHaber/master
Adding basePath to python plugins
2017-01-17 20:23:22 -08:00
ZachHaber fa66025024 Adding basePath to python plugins
Adds the virtual function override to the boost python wrapper.
2017-01-17 17:05:22 -06:00
LePresidente 3e61a88abb added if statement to allow to build on msvc2013 2016-12-12 05:13:08 -08:00
lepresidente 828e35a129 changes required by adding gameNexusName to uibase. 2016-12-04 17:52:43 +02:00
lepresidente cc58ccc992 Fixed cmake python location.
Fixed build issue with VS2015.
2016-11-27 16:54:19 +02:00
Tannin aa37f30c68 bugfix: invalid return type in python api 2016-06-06 20:27:29 +02:00
Tannin f9353e4da0 translation 2016-06-04 20:39:14 +02:00
Tannin 9a310229e7 updated wrappers to current api 2016-05-06 22:45:52 +02:00
Tannin a78db4cbdc Merge branch 'ThosRTanner-issue/418' 2016-02-10 18:55:43 +01:00
Tannin 9502ea561e Merge branch 'issue/418' of https://github.com/ThosRTanner/modorganizer-plugin_python into ThosRTanner-issue/418
Conflicts:
	src/runner/uibasewrappers.h
2016-02-10 18:55:18 +01:00
Tannin 179deda6e4 Merge branch 'ThosRTanner-master' 2016-02-10 18:52:48 +01:00
Tannin fa85cc89d3 Merge branch 'master' of https://github.com/ThosRTanner/modorganizer-plugin_python into ThosRTanner-master
Conflicts:
	src/runner/uibasewrappers.h
2016-02-10 18:52:20 +01:00
Tannin ee31647014 minor cleanup 2016-02-09 19:34:09 +01:00
Thomas Tanner 4bb0994d71 Merge branch 'master' into issue/418 2016-01-24 15:57:54 +00:00
Thomas Tanner 4b8b75e641 Removing the 'get' in all function names and making FO4 plugin build
Merge branch 'master' of https://github.com/TanninOne/modorganizer-plugin_python

# Conflicts:
#	src/runner/uibasewrappers.h
2016-01-24 15:23:30 +00:00
Tannin 2fcb932e16 allow for game plugins to be written in python 2016-01-10 19:50:19 +01:00
Tannin 40192cb583 Merge branch 'master' of https://github.com/TanninOne/modorganizer-plugin_python 2015-12-28 14:35:43 +01:00
Tannin 163e3d4544 removed get-prefix from many getters 2015-12-28 14:35:35 +01:00
TanninOne a65763fb58 fixes to build system 2015-12-28 13:46:31 +01:00
Thomas Tanner d144d7c97b Fix const correctness 2015-12-26 15:47:50 +00:00
Thomas Tanner de99a71085 Merge branch 'master' into issue/418 2015-12-26 15:26:41 +00:00
Thomas Tanner 9bdb48c6bc Merge remote-tracking branch 'refs/remotes/TanninOne/master' into issue/418 2015-12-26 15:04:13 +00:00
Thomas Tanner a20b166290 Restore start download file method (3 of 3) 2015-12-20 22:25:45 +00:00
Thomas Tanner d1b2259cc5 For TanninOne/modarganizer#418
Changes to support getting list of mods / esps to activate from game plugin
2015-12-19 20:49:30 +00:00
Tannin 4bb048aa67 Merge branch 'master' of https://github.com/TanninOne/modorganizer-plugin_python
Conflicts:
	src/runner/pythonrunner.cpp
	src/runner/uibasewrappers.h
2015-12-06 20:58:22 +01:00
Tannin 0b53e86e5a updated python api 2015-12-06 20:55:36 +01:00
Thomas Tanner 9077573b9d Merge remote-tracking branch 'refs/remotes/TanninOne/master' 2015-12-06 18:08:43 +00:00
TanninOne 0fa436fc0f Merge pull request #5 from ThosRTanner/issue/344
Issue 344
2015-12-06 18:44:14 +01:00
Thomas Tanner d75eda53fc Merge remote-tracking branch 'TanninOne/master' into issue/344 2015-12-06 17:31:13 +00:00
Thomas Tanner a71566122e Merge remote-tracking branch 'TanninOne/master' into issue/344
# Conflicts:
#	src/runner/pythonrunner.cpp
#	src/runner/uibasewrappers.h
2015-12-06 17:31:02 +00:00
TanninOne 69b988eede Merge pull request #1 from ThosRTanner/issue/308
View web pages from non-nexus installs (3 of 4)
2015-12-06 17:56:42 +01:00
Thomas Tanner c106d6f342 Merge remote-tracking branch 'TanninOne/master' 2015-12-06 16:22:27 +00:00
Thomas Tanner 4a6f8e84f4 work through build issues 2015-12-06 16:13:29 +00:00
TanninOne efc0b1962f Merge branch 'ThosRTanner-issue/344' 2015-12-06 16:24:22 +01:00
TanninOne 8f408a77d2 Merge branch 'issue/344' of https://github.com/ThosRTanner/modorganizer-plugin_python into ThosRTanner-issue/344 2015-12-06 16:23:29 +01:00
Thomas Tanner dccc265364 Merge remote-tracking branch 'TanninOne/master' 2015-12-06 14:56:14 +00:00
TanninOne aa9c6ead94 Merge pull request #4 from ThosRTanner/issue/356
Refactor gameinfo & 'shared' library to use game plugins (7 of 17)
2015-12-06 13:21:25 +01:00
Thomas Tanner f94f37b635 Merge remote-tracking branch 'refs/remotes/TanninOne/master' into issue/356
Conflicts:
	src/runner/pythonrunner.cpp
2015-12-05 12:48:39 +00:00
Thomas Tanner 9fdcde3bd5 Merge remote-tracking branch 'TanninOne/master' into issue/344 2015-12-05 10:33:09 +00:00
Thomas Tanner 11c92e7e96 Merge remote-tracking branch 'refs/remotes/TanninOne/master' 2015-12-05 10:02:16 +00:00
Thomas Tanner 287a82ed48 Most of work for savegame 2015-12-05 06:51:41 +00:00
Thomas Tanner c9299bb623 Addition of directory validity check to IPluginGame API 2015-11-28 14:48:28 +00:00
Tannin 7d6d51b213 fixed build scripts and added fallout 4 support 2015-11-28 10:58:49 +01:00
Thomas Tanner e60121b21f Renamed getNexusName to getGameShortName as previously because it hopefully isn't too nexus related. 2015-11-26 21:17:06 +00:00
Thomas Tanner 7f7a3fb1ca Replaced the IPluginGame getNexusDisplayURL with some APIs in NexusInterface
It makes more sense to have them here as they have very little to do with the game, more to do with the origin of the mod.
2015-11-26 21:03:23 +00:00
Thomas Tanner 9ba337ef17 Remove the getNexusManagementURL as it is a property of how you talk to nexus, not the game 2015-11-26 17:45:30 +00:00
Thomas Tanner 1455bda2f8 Sigh - python wrapper version of the 2 URL fetch functions 2015-11-26 07:40:53 +00:00
Thomas Tanner cc62f15cc8 Replace GameInfo::getNexusModID with IPluginGame::getNexusModOrganizerID()
Also implement IPluginGame::getNexusGameID() but not hooked it in yet.
2015-11-24 16:16:10 +00:00
Thomas Tanner 0b9a56fa7a Replace GameInfo::getLoadorderMechanism with IPluginGame::getLoadOrderMechanism 2015-11-24 14:20:47 +00:00
Thomas Tanner fc8f6c77bc Remove most instances of GameInfo::getname, and transfer getDLCPlugins to the plugingame interface
Also removed startDownloadNextFile as it doesn't appear to be used anywhere
2015-11-23 18:34:04 +00:00
Thomas Tanner 55e9c9c7b6 Final eradication of igameinfo and adding python wrappers for IPluginGame 2015-11-22 21:18:12 +00:00
Thomas Tanner 47e25da95e Removes igameinfo.h from everywhere apart from (sort of) the pythonrunner plugin. 2015-11-22 08:42:42 +00:00
Thomas Tanner cb5d3b4e62 Replace GameInfo::path with iPluginGame::gameDirectory (or dataDirectory where applicable)
Note: this isn''t ideal as it's not backward compatible
2015-11-21 16:41:28 +00:00
Thomas Tanner 542ef73a30 Removal of (get)BinaryName.
Note in pythonrunner this is a bit commented out so I can think about how to deal with it.
2015-11-21 12:28:48 +00:00
Thomas Tanner f6d499e6c6 Merge remote-tracking branch 'refs/remotes/TanninOne/master' 2015-11-18 20:46:19 +00:00
Tannin fe2169650e updated build scripts 2015-11-16 21:39:53 +01:00
Thomas Tanner 07798f2e23 More changes suggested by compiling with clang 2015-11-09 18:14:57 +00:00
Thomas Tanner 86d2ce34f3 Fix compilation issues with clang, requires adding widgets to build 2015-11-08 23:15:55 +00:00
Thomas Tanner 88846e52f5 Add support for version dependency checks 2015-11-01 18:27:03 +00:00
Thomas Tanner 27704407a3 Add the python wrapper changes for the new setURL method 2015-10-15 19:06:04 +01:00
Thomas Tanner 3648690c5e Merge remote-tracking branch 'TanninOne/master' 2015-10-10 14:00:38 +01:00
Tannin 97787553f7 more work on build system 2015-10-09 19:57:45 +02:00
Tannin 10fd3e77d7 more work on build system 2015-10-09 19:57:17 +02:00
convert-repo f806d29a75 update tags 2015-09-07 16:36:52 +00:00
Tom Tanner 25ac05622a Small fix to shut up messages about long boost names 2015-08-20 19:53:39 +01:00
Tannin f29d9ac993 added plugin interface to add/remove/list categories to/from/of mods 2015-06-10 22:09:32 +02:00
33 changed files with 3423 additions and 2357 deletions
+5
View File
@@ -0,0 +1,5 @@
edit
CMakeLists.txt.user
/msbuild.log
/*std*.log
/*build
+25
View File
@@ -0,0 +1,25 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.12)
ADD_COMPILE_OPTIONS($<$<CXX_COMPILER_ID:MSVC>:/MP> $<$<CXX_COMPILER_ID:MSVC>:$<$<CONFIG:RELEASE>:/O2>> $<$<CXX_COMPILER_ID:MSVC>:$<$<CONFIG:RELWITHDEBINFO>:/O2>>)
SET(PROJ_NAME plugin_python)
PROJECT(${PROJ_NAME})
SET(DEPENDENCIES_DIR CACHE PATH "")
# hint to find qt in dependencies path
LIST(APPEND CMAKE_PREFIX_PATH ${QT_ROOT}/lib/cmake)
# need to install python
IF(EXISTS "${PYTHON_ROOT}/PCbuild/python37.dll")
INSTALL(FILES ${PYTHON_ROOT}/PCbuild/python37.dll DESTINATION bin)
INSTALL(FILES ${PYTHON_ROOT}/PCbuild/python37.pdb DESTINATION pdb)
ELSEIF(EXISTS "${PYTHON_ROOT}/PCbuild/amd64/python27.dll")
INSTALL(FILES ${PYTHON_ROOT}/PCbuild/amd64/python37.dll DESTINATION bin)
INSTALL(FILES ${PYTHON_ROOT}/PCbuild/amd64/python37.pdb DESTINATION pdb)
ENDIF()
ADD_SUBDIRECTORY(src/runner)
ADD_SUBDIRECTORY(src/proxy)
+40
View File
@@ -0,0 +1,40 @@
version: 1.0.{build}
skip_branch_with_pr: true
image: Visual Studio 2019
environment:
WEBHOOK_URL:
secure: gOKbXaZM9ImtMD5XrYITvdyZUW/az082G9OIN1EC1Vbg57wBaeLhi49uGjxPw5GVujHku6kxN6ab89zhbS5GVeluR76GM83IbKV4Sh7udXzoYZZdg6YudtYHzdhCgUeiedpswbuczTq9ceIkkfSEWZuh/lMAAVVwvcGsJAnoPFw=
build:
parallel: true
build_script:
- cmd: >-
git clone --depth=1 --branch=%APPVEYOR_REPO_BRANCH% https://github.com/ModOrganizer2/modorganizer-umbrella.git c:\projects\modorganizer-umbrella 2> $null
mkdir c:\projects\modorganizer-build -type directory
cd c:\projects\modorganizer-umbrella
C:\Python37-x64\python.exe unimake.py -d c:\projects\modorganizer-build -s Appveyor_Build=True %APPVEYOR_PROJECT_NAME%
artifacts:
- path: build\src\proxy\plugin_python.dll
name: plugin_python_dll
- path: build\src\proxy\plugin_python.pdb
name: plugin_python_pdb
- path: build\src\proxy\plugin_python.lib
name: plugin_python_lib
- path: build\src\runner\pythonrunner.dll
name: pythonrunner_dll
- path: build\src\runner\pythonrunner.pdb
name: pythonrunner_pdb
- path: build\src\runner\pythonrunner.lib
name: pythonrunner_lib
on_success:
- ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER
- ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1
- ps: ./send.ps1 success $env:WEBHOOK_URL
on_failure:
- ps: Set-Location -Path $env:APPVEYOR_BUILD_FOLDER
- ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stdout.log
- ps: Push-AppveyorArtifact ${env:APPVEYOR_BUILD_FOLDER}\stderr.log
- ps: Invoke-RestMethod https://raw.githubusercontent.com/DiscordHooks/appveyor-discord-webhook/master/send.ps1 -o send.ps1
- ps: ./send.ps1 failure $env:WEBHOOK_URL
+70
View File
@@ -0,0 +1,70 @@
CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11)
CMAKE_POLICY(SET CMP0020 NEW)
CMAKE_POLICY(SET CMP0043 NEW)
SET(${PROJ_NAME}_SRCS proxypython.cpp)
SET(${PROJ_NAME}_HDRS
proxypython.h
resource.h)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
SET(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)
FIND_PACKAGE(Qt5Widgets REQUIRED)
FIND_PACKAGE(Qt5Network REQUIRED)
#QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS})
SET(Boost_USE_STATIC_LIBS ON)
SET(Boost_USE_MULTITHREADED ON)
SET(Boost_USE_STATIC_RUNTIME OFF)
FIND_PACKAGE(Boost)
IF (Boost_FOUND)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
ENDIF (Boost_FOUND)
SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super")
GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH)
SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects")
SET(lib_path "${project_path}/../../install/libs")
ADD_DEFINITIONS(-DUNICODE -D_UNICODE)
INCLUDE_DIRECTORIES(${project_path}/uibase/src
${CMAKE_SOURCE_DIR}/src/runner/
${PYTHON_ROOT}/Include)
LINK_DIRECTORIES(${lib_path})
ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_UIHDRS})
TARGET_LINK_LIBRARIES(${PROJ_NAME}
Qt5::Widgets
Qt5::Network
${Boost_LIBRARIES}
uibase)
IF (MSVC)
SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest")
ENDIF()
IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4)
# 32 bits
SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE")
ENDIF()
IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "")
SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS})
ENDIF()
IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "")
SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS})
ENDIF()
###############
## Installation
INSTALL(TARGETS ${PROJ_NAME}
RUNTIME DESTINATION bin/plugins)
INSTALL(FILES $<TARGET_PDB_FILE:${PROJ_NAME}>
DESTINATION pdb)
+1 -5
View File
@@ -3,9 +3,5 @@
#ifdef SCONS_BUILD
IDR_LOADER_DLL BINARY MOVEABLE PURE pythonRunner.dll
#else
#ifdef _DEBUG
IDR_LOADER_DLL BINARY MOVEABLE PURE "..\\..\\pythonRunner\\debug\\pythonRunner.dll"
#else // _DEBUG
IDR_LOADER_DLL BINARY MOVEABLE PURE "..\\..\\pythonRunner\\release\\pythonRunner.dll"
#endif // _DEBUG
IDR_LOADER_DLL BINARY MOVEABLE PURE "..\\runner\\pythonRunner.dll"
#endif
-213
View File
@@ -1,213 +0,0 @@
#include "proxypluginwrappers.h"
#include <boost/python.hpp>
#include <utility.h>
#include "error.h"
#include "gilock.h"
namespace bpy = boost::python;
using namespace MOBase;
#define PYCATCH catch (const bpy::error_already_set &) { reportPythonError(); throw MyException("unhandled exception"); }\
catch (...) { throw MyException("An unknown exception was thrown in python code"); }
/////////////////////////////
/// IPluginTool Wrapper
bool IPluginToolWrapper::init(MOBase::IOrganizer *moInfo)
{
try {
return this->get_override("init")(bpy::ptr(moInfo));
} PYCATCH;
}
QString IPluginToolWrapper::name() const
{
try {
return this->get_override("name")();
} PYCATCH;
}
QString IPluginToolWrapper::author() const
{
try {
return this->get_override("author")();
} PYCATCH;
}
QString IPluginToolWrapper::description() const
{
try {
return this->get_override("description")();
} PYCATCH;
}
MOBase::VersionInfo IPluginToolWrapper::version() const
{
try {
return this->get_override("version")();
} PYCATCH;
}
bool IPluginToolWrapper::isActive() const
{
try {
return this->get_override("isActive")();
} PYCATCH;
}
QList<MOBase::PluginSetting> IPluginToolWrapper::settings() const
{
try {
return this->get_override("settings")();
} PYCATCH;
}
QString IPluginToolWrapper::displayName() const
{
try {
return this->get_override("displayName")();
} PYCATCH;
}
QString IPluginToolWrapper::tooltip() const
{
try {
return this->get_override("tooltip")();
} PYCATCH;
}
QIcon IPluginToolWrapper::icon() const
{
try {
return this->get_override("icon")();
} PYCATCH;
}
void IPluginToolWrapper::setParentWidget(QWidget *parent)
{
try {
this->get_override("setParentWidget")(parent);
} PYCATCH;
}
void IPluginToolWrapper::display() const
{
try {
GILock lock;
this->get_override("display")();
} PYCATCH;
}
/// end IPluginTool Wrapper
/////////////////////////////////////
/// IPluginInstallerCustom Wrapper
bool IPluginInstallerCustomWrapper::init(MOBase::IOrganizer *moInfo)
{
try {
return this->get_override("init")(bpy::ptr(moInfo));
} PYCATCH;
}
QString IPluginInstallerCustomWrapper::name() const
{
try {
return this->get_override("name")();
} PYCATCH;
}
QString IPluginInstallerCustomWrapper::author() const
{
try {
return this->get_override("author")();
} PYCATCH;
}
QString IPluginInstallerCustomWrapper::description() const
{
try {
return this->get_override("description")();
} PYCATCH;
}
MOBase::VersionInfo IPluginInstallerCustomWrapper::version() const
{
try {
return this->get_override("version")();
} PYCATCH;
}
bool IPluginInstallerCustomWrapper::isActive() const
{
try {
return this->get_override("isActive")();
} PYCATCH;
}
QList<MOBase::PluginSetting> IPluginInstallerCustomWrapper::settings() const
{
try {
return this->get_override("settings")();
} PYCATCH;
}
unsigned int IPluginInstallerCustomWrapper::priority() const
{
try {
return this->get_override("priority")();
} PYCATCH;
}
bool IPluginInstallerCustomWrapper::isManualInstaller() const
{
try {
return this->get_override("isManualInstaller")();
} PYCATCH;
}
bool IPluginInstallerCustomWrapper::isArchiveSupported(const DirectoryTree &tree) const
{
try {
//return this->get_override("isArchiveSupported")(tree);
return false;
} PYCATCH;
}
bool IPluginInstallerCustomWrapper::isArchiveSupported(const QString &archiveName) const
{
try {
return this->get_override("isArchiveSupported")(archiveName);
} PYCATCH;
}
std::set<QString> IPluginInstallerCustomWrapper::supportedExtensions() const
{
try {
return this->get_override("supportedExtensions")();
} PYCATCH;
}
IPluginInstaller::EInstallResult IPluginInstallerCustomWrapper::install(GuessedValue<QString> &modName, const QString &archiveName,
const QString &version, int modID)
{
try {
return this->get_override("install")(modName, archiveName, version, modID);
} PYCATCH;
}
void IPluginInstallerCustomWrapper::setParentWidget(QWidget *parent)
{
try {
this->get_override("setParentWidget")(parent);
} PYCATCH;
}
-80
View File
@@ -1,80 +0,0 @@
#ifndef PROXYPLUGINWRAPPERS_H
#define PROXYPLUGINWRAPPERS_H
#include <iplugintool.h>
#include <iplugininstallersimple.h>
#include <iplugininstallercustom.h>
#include <iplugindiagnose.h>
#ifndef Q_MOC_RUN
#include <boost/python.hpp>
#endif
class IPluginWrapper : public boost::python::wrapper<MOBase::IPlugin>
{
public:
virtual bool init(MOBase::IOrganizer *moInfo);
virtual QString name() const;
virtual QString author() const;
virtual QString description() const;
virtual MOBase::VersionInfo version() const;
virtual bool isActive() const;
virtual QList<MOBase::PluginSetting> settings() const;
};
class IPluginToolWrapper: public MOBase::IPluginTool, public boost::python::wrapper<MOBase::IPluginTool>
{
Q_OBJECT
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginTool)
public:
virtual bool init(MOBase::IOrganizer *moInfo);
virtual QString name() const;
virtual QString author() const;
virtual QString description() const;
virtual MOBase::VersionInfo version() const;
virtual bool isActive() const;
virtual QList<MOBase::PluginSetting> settings() const;
virtual QString displayName() const;
virtual QString tooltip() const;
virtual QIcon icon() const;
virtual void setParentWidget(QWidget *parent);
public slots:
virtual void display() const;
};
class IPluginInstallerCustomWrapper: public MOBase::IPluginInstallerCustom, public boost::python::wrapper<MOBase::IPluginInstallerCustom>
{
Q_OBJECT
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginInstaller MOBase::IPluginInstallerCustom)
public:
virtual bool init(MOBase::IOrganizer *moInfo);
virtual QString name() const;
virtual QString author() const;
virtual QString description() const;
virtual MOBase::VersionInfo version() const;
virtual bool isActive() const;
virtual QList<MOBase::PluginSetting> settings() const;
virtual unsigned int priority() const;
virtual bool isManualInstaller() const;
virtual bool isArchiveSupported(const MOBase::DirectoryTree &tree) const;
virtual bool isArchiveSupported(const QString &archiveName) const;
virtual std::set<QString> supportedExtensions() const;
virtual EInstallResult install(MOBase::GuessedValue<QString> &modName, const QString &archiveName,
const QString &version, int modID);
virtual void setParentWidget(QWidget *parent);
};
#endif // PROXYPLUGINWRAPPERS_H
+6 -13
View File
@@ -135,8 +135,6 @@ bool ProxyPython::init(IOrganizer *moInfo)
return true;
}
//m_TempRunnerFile = ExtractResource(IDR_LOADER_DLL, "__pythonRunner.dll");
//m_RunnerLib = ::LoadLibraryW(ToWString(m_TempRunnerFile).c_str());
m_RunnerLib = ::LoadLibraryW(QDir::toNativeSeparators(m_MOInfo->pluginDataPath() + "/pythonRunner.dll").toStdWString().c_str());
if (m_RunnerLib != nullptr) {
CreatePythonRunner_func CreatePythonRunner = (CreatePythonRunner_func)::GetProcAddress(m_RunnerLib, "CreatePythonRunner");
@@ -173,7 +171,7 @@ bool ProxyPython::init(IOrganizer *moInfo)
return true;
} else {
DWORD error = ::GetLastError();
qCritical("Failed to load python runner (%s): %s", qPrintable(m_TempRunnerFile), qPrintable(windowsErrorString(error)));
qCritical("Failed to load python runner (%s): %s", qUtf8Printable(m_TempRunnerFile), qUtf8Printable(windowsErrorString(error)));
if (error == ERROR_MOD_NOT_FOUND) {
m_LoadFailure = FAIL_MISSINGDEPENDENCIES;
}
@@ -198,12 +196,12 @@ QString ProxyPython::description() const
VersionInfo ProxyPython::version() const
{
return VersionInfo(1, 3, 1, VersionInfo::RELEASE_FINAL);
return VersionInfo(2, 1, 0, VersionInfo::RELEASE_FINAL);
}
bool ProxyPython::isActive() const
{
return m_LoadFailure == FAIL_NONE;
return m_LoadFailure == FAIL_NOTINIT;
}
QList<PluginSetting> ProxyPython::settings() const
@@ -227,13 +225,13 @@ QStringList ProxyPython::pluginList(const QString &pluginPath) const
}
QObject *ProxyPython::instantiate(const QString &pluginName)
QList<QObject*> ProxyPython::instantiate(const QString &pluginName)
{
if (m_Runner != nullptr) {
QObject *result = m_Runner->instantiate(pluginName);
QList<QObject*> result = m_Runner->instantiate(pluginName);
return result;
} else {
return nullptr;
return QList<QObject*>();
}
}
@@ -340,8 +338,3 @@ void ProxyPython::startGuidedFix(unsigned int key) const
::ShellExecuteA(nullptr, "open", s_DownloadPythonURL, nullptr, nullptr, SW_SHOWNORMAL);
}
}
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
Q_EXPORT_PLUGIN2(proxyPython, ProxyPython)
#endif
+1 -1
View File
@@ -49,7 +49,7 @@ public:
virtual QList<MOBase::PluginSetting> settings() const;
QStringList pluginList(const QString &pluginPath) const;
QObject *instantiate(const QString &pluginName);
QList<QObject*> instantiate(const QString &pluginName);
/**
* @return the parent widget for newly created dialogs
-112
View File
@@ -1,112 +0,0 @@
#include "pythonpluginwrapper.h"
using boost::python::extract;
using boost::python::handle_exception;
PythonPluginWrapper::PythonPluginWrapper(const boost::python::object &initFunction,
const boost::python::object &nameFunction,
const boost::python::object &authorFunction,
const boost::python::object &descriptionFunction,
const boost::python::object &versionFunction,
const boost::python::object &isActiveFunction,
const boost::python::object &settingsFunction)
: m_InitFunction(initFunction)
, m_NameFunction(nameFunction)
, m_AuthorFunction(authorFunction)
, m_DescriptionFunction(descriptionFunction)
, m_VersionFunction(versionFunction)
, m_IsActiveFunction(isActiveFunction)
, m_SettingsFunction(settingsFunction)
{
}
void PythonPluginWrapper::reportPythonError() const
{
if (PyErr_Occurred()) {
PyErr_Print();
} else {
qCritical("An unexpected C++ exception was thrown in python code");
}
}
bool PythonPluginWrapper::init(MOBase::IOrganizer *moInfo)
{
try {
return boost::python::extract<bool>(m_InitFunction(boost::python::ptr(moInfo)));
} catch (const boost::python::error_already_set&) {
reportPythonError();
return false;
}
}
QString PythonPluginWrapper::name() const
{
try {
return boost::python::extract<QString>(m_NameFunction());
} catch (const boost::python::error_already_set&) {
reportPythonError();
return QString();
}
}
QString PythonPluginWrapper::author() const
{
try {
return boost::python::extract<QString>(m_AuthorFunction());
} catch (const boost::python::error_already_set&) {
reportPythonError();
return QString();
}
}
QString PythonPluginWrapper::description() const
{
try {
return boost::python::extract<QString>(m_DescriptionFunction());
} catch (const boost::python::error_already_set&) {
reportPythonError();
return QString();
}
}
MOBase::VersionInfo PythonPluginWrapper::version() const
{
try {
return boost::python::extract<MOBase::VersionInfo>(m_VersionFunction());
} catch (const boost::python::error_already_set&) {
reportPythonError();
return MOBase::VersionInfo();
}
}
bool PythonPluginWrapper::isActive() const
{
try {
return boost::python::extract<bool>(m_IsActiveFunction());
} catch (const boost::python::error_already_set&) {
reportPythonError();
return false;
}
}
QList<MOBase::PluginSetting> PythonPluginWrapper::settings() const
{
QList<MOBase::PluginSetting> result;
try {
boost::python::object l = m_SettingsFunction();
if (!l.is_none()) {
// boost::python::list l = extract<boost::python::list>(temp);
for (int i = 0; i < boost::python::len(l); ++i) {
result.append(extract<MOBase::PluginSetting>(l[i]));
}
}
} catch (const boost::python::error_already_set&) {
reportPythonError();
}
return result;
}
-44
View File
@@ -1,44 +0,0 @@
#ifndef PYTHONPLUGINWRAPPER_H
#define PYTHONPLUGINWRAPPER_H
#include <iplugin.h>
#ifndef Q_MOC_RUN
#include <boost/python.hpp>
#endif
class PythonPluginWrapper : public virtual MOBase::IPlugin
{
public:
PythonPluginWrapper(const boost::python::object &initFunction,
const boost::python::object &nameFunction,
const boost::python::object &authorFunction,
const boost::python::object &descriptionFunction,
const boost::python::object &versionFunction,
const boost::python::object &isActiveFunction,
const boost::python::object &settingsFunction);
virtual bool init(MOBase::IOrganizer *moInfo);
virtual QString name() const;
virtual QString author() const;
virtual QString description() const;
virtual MOBase::VersionInfo version() const;
virtual bool isActive() const;
virtual QList<MOBase::PluginSetting> settings() const;
protected:
void reportPythonError() const;
private:
boost::python::object m_InitFunction;
boost::python::object m_NameFunction;
boost::python::object m_AuthorFunction;
boost::python::object m_DescriptionFunction;
boost::python::object m_VersionFunction;
boost::python::object m_IsActiveFunction;
boost::python::object m_SettingsFunction;
};
#endif // PYTHONPLUGINWRAPPER_H
-80
View File
@@ -1,80 +0,0 @@
#include "pythontoolwrapper.h"
#include <QApplication>
#include <QWidget>
using boost::python::extract;
using boost::python::handle_exception;
PythonToolWrapper::PythonToolWrapper(const boost::python::object &initFunction,
const boost::python::object &nameFunction,
const boost::python::object &authorFunction,
const boost::python::object &descriptionFunction,
const boost::python::object &versionFunction,
const boost::python::object &isActiveFunction,
const boost::python::object &settingsFunction,
const boost::python::object &displayNameFunction,
const boost::python::object &tooltipFunction,
const boost::python::object &iconFunction,
const boost::python::object &displayFunction,
const boost::python::object &setParentWidget)
: PythonPluginWrapper(initFunction, nameFunction, authorFunction, descriptionFunction,
versionFunction, isActiveFunction, settingsFunction)
, m_DisplayNameFunction(displayNameFunction)
, m_ToolTipFunction(tooltipFunction)
, m_IconFunction(iconFunction)
, m_DisplayFunction(displayFunction)
, m_SetParentWidget(setParentWidget)
{
}
QString PythonToolWrapper::displayName() const
{
try {
return boost::python::extract<QString>(m_DisplayNameFunction());
} catch (const boost::python::error_already_set&) {
reportPythonError();
return QString();
}
}
QString PythonToolWrapper::tooltip() const
{
try {
return boost::python::extract<QString>(m_ToolTipFunction());
} catch (const boost::python::error_already_set&) {
reportPythonError();
return QString();
}
}
QIcon PythonToolWrapper::icon() const
{
try {
std::vector<const char*> rows;
boost::python::object l = m_IconFunction();
if (!l.is_none()) {
for (int i = 0; i < boost::python::len(l); ++i) {
rows.push_back(extract<const char*>(l[i]));
}
return QIcon(QPixmap(&rows[0]));
} else {
return QIcon();
}
} catch (const boost::python::error_already_set&) {
reportPythonError();
return QIcon();
}
}
void PythonToolWrapper::display() const
{
try {
m_SetParentWidget(parentWidget());
m_DisplayFunction();
} catch (const boost::python::error_already_set&) {
reportPythonError();
}
}
-56
View File
@@ -1,56 +0,0 @@
#ifndef PYTHONTOOLWRAPPER_H
#define PYTHONTOOLWRAPPER_H
#include <iplugintool.h>
#ifndef Q_MOC_RUN
#include <boost/python.hpp>
#endif
#include "pythonpluginwrapper.h"
class PythonToolWrapper : public QObject, public MOBase::IPluginTool, public PythonPluginWrapper
{
Q_OBJECT
Q_INTERFACES(MOBase::IPlugin MOBase::IPluginTool)
public:
PythonToolWrapper(const boost::python::object &initFunction,
const boost::python::object &nameFunction,
const boost::python::object &authorFunction,
const boost::python::object &descriptionFunction,
const boost::python::object &versionFunction,
const boost::python::object &isActiveFunction,
const boost::python::object &settingsFunction,
const boost::python::object &displayNameFunction,
const boost::python::object &tooltipFunction,
const boost::python::object &iconFunction,
const boost::python::object &displayFunction,
const boost::python::object &setParentWidget);
using PythonPluginWrapper::init;
using PythonPluginWrapper::name;
virtual QString displayName() const;
virtual QString tooltip() const;
virtual QIcon icon() const;
public slots:
virtual void display() const;
private:
boost::python::object m_DisplayNameFunction;
boost::python::object m_ToolTipFunction;
boost::python::object m_IconFunction;
boost::python::object m_DisplayFunction;
boost::python::object m_SetParentWidget;
};
#endif // PYTHONTOOLWRAPPER_H
+90
View File
@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_US">
<context>
<name>ProxyPython</name>
<message>
<location filename="proxy/proxypython.cpp" line="150"/>
<source>Python Initialization failed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="151"/>
<source>On a previous start the Python Plugin failed to initialize.
Either the value in Settings-&gt;Plugins-&gt;ProxyPython-&gt;plugin_dir is set incorrectly or it is empty and auto-detection doesn&apos;t work for whatever reason.
Do you want to try initializing python again (at the risk of another crash)?
Suggestion: Select &quot;no&quot;, and click the warning sign for further help. Afterwards you have to re-enable the python plugin.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="194"/>
<source>Proxy Plugin to allow plugins written in python to be loaded</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="269"/>
<source>Python not installed or not found</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="272"/>
<source>Python version is incompatible</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="275"/>
<source>Invalid python path</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="278"/>
<source>Initializing Python failed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="281"/>
<source>Python auto-detection failed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="284"/>
<source>ModOrganizer path contains a semicolon</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="287"/>
<source>invalid problem key %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="296"/>
<source>Some MO plugins require the python interpreter to be installed. These plugins will not even show up in settings-&amp;gt;plugins.&lt;br&gt;If you want to use those plugins, please install the 32-bit version of Python 2.7.x from &lt;a href=&quot;%1&quot;&gt;%1&lt;/a&gt;.&lt;br&gt;This is only required to use some extended functionality in MO, you do not need Python to play the game.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="302"/>
<source>Your installed python version has a different version than 2.7. Some MO plugins may not work.&lt;br&gt;If you have multiple versions of python installed you may have to configure the path to 2.7 (32 bit) in the settings dialog.&lt;br&gt;This is only required to use some extended functionality in MO, you do not need Python to play the game.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="309"/>
<source>Please set python_dir in Settings-&gt;Plugins-&gt;ProxyPython to the path of your python 2.7 (32 bit) installation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="312"/>
<source>The auto-detection of the python path failed. I don&apos;t know why this would happen but you can try to fix it by setting python_dir in Settings-&gt;Plugins-&gt;ProxyPython to the path of your python 2.7 (32 bit) installation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="316"/>
<source>Sorry, I don&apos;t know any details. Most likely your python installation is not supported.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="proxy/proxypython.cpp" line="319"/>
<source>The path to Mod Organizer (%1) contains a semicolon. &lt;br&gt;While this is legal on NTFS drives there is a lot of software that doesn&apos;t handle it correctly.&lt;br&gt;Unfortunately MO depends on libraries that seem to fall into that group.&lt;br&gt;As a result the python plugin can&apos;t be loaded.&lt;br&gt;The only solution I can offer is to remove the semicolon / move MO to a path without a semicolon.</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>
+77
View File
@@ -0,0 +1,77 @@
CMAKE_MINIMUM_REQUIRED (VERSION 2.8.11)
SET(PROJ_NAME pythonrunner)
PROJECT(${PROJ_NAME})
CMAKE_POLICY(SET CMP0020 NEW)
FILE(GLOB ${PROJ_NAME}_SRCS *.cpp)
FILE(GLOB ${PROJ_NAME}_HDRS *.h)
SET(CMAKE_INCLUDE_CURRENT_DIR ON)
SET(CMAKE_AUTOMOC ON)
SET(CMAKE_AUTOUIC ON)
ADD_DEFINITIONS(-DQT_NO_KEYWORDS)
FIND_PACKAGE(Qt5Widgets REQUIRED)
FIND_PACKAGE(Qt5Network REQUIRED)
#QT5_WRAP_UI(${PROJ_NAME}_UIHDRS ${${PROJ_NAME}_FORMS})
FIND_PACKAGE(Qt5LinguistTools)
QT5_CREATE_TRANSLATION(${PROJ_NAME}_translations_qm ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/src/${PROJ_NAME}_en.ts)
SET(Boost_USE_STATIC_LIBS OFF)
SET(Boost_USE_MULTITHREADED ON)
SET(Boost_USE_STATIC_RUNTIME OFF)
FIND_PACKAGE(Boost REQUIRED)
IF (Boost_FOUND)
INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIRS})
ENDIF (Boost_FOUND)
SET(default_project_path "${DEPENDENCIES_DIR}/modorganizer_super")
GET_FILENAME_COMPONENT(${default_project_path} ${default_project_path} REALPATH)
SET(project_path "${default_project_path}" CACHE PATH "path to the other mo projects")
SET(lib_path "${project_path}/../../install/libs")
INCLUDE_DIRECTORIES(${project_path}/uibase/src
${project_path}/game_features/src
${PYTHON_ROOT}/Include
${PYTHON_ROOT}/PC)
LINK_DIRECTORIES(${lib_path}
${PYTHON_ROOT}/PCbuild
${Boost_LIBRARY_DIRS})
ADD_LIBRARY(${PROJ_NAME} SHARED ${${PROJ_NAME}_HDRS} ${${PROJ_NAME}_SRCS} ${${PROJ_NAME}_translations_qm})
TARGET_LINK_LIBRARIES(${PROJ_NAME}
Qt5::Widgets
Qt5::Network
uibase)
ADD_DEFINITIONS(-DPYTHONRUNNER_LIBRARY)
IF (MSVC)
SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS "/std:c++latest")
ENDIF()
IF (MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 4)
# 32 bits
SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS "/LARGEADDRESSAWARE")
ENDIF()
IF (NOT "${OPTIMIZE_COMPILE_FLAGS}" STREQUAL "")
SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES COMPILE_FLAGS_RELWITHDEBINFO ${OPTIMIZE_COMPILE_FLAGS})
ENDIF()
IF (NOT "${OPTIMIZE_LINK_FLAGS}" STREQUAL "")
SET_TARGET_PROPERTIES(${PROJ_NAME} PROPERTIES LINK_FLAGS_RELWITHDEBINFO ${OPTIMIZE_LINK_FLAGS})
ENDIF()
###############
## Installation
INSTALL(TARGETS ${PROJ_NAME}
RUNTIME DESTINATION bin/plugins/data
ARCHIVE DESTINATION libs)
INSTALL(FILES $<TARGET_PDB_FILE:${PROJ_NAME}>
DESTINATION pdb)
+5 -1
View File
@@ -2,7 +2,7 @@ Import('qt_env')
env = qt_env.Clone()
env.EnableQtModules('Core', 'Gui')
env.EnableQtModules('Core', 'Gui', 'Widgets')
env.AppendUnique(CPPDEFINES = 'PYTHONRUNNER_LIBRARY')
@@ -13,6 +13,10 @@ env.AppendUnique(CPPDEFINES = [
'HAVE_ROUND'
])
# Boost produces very long names with msvc truncates. Doesn't seem to cause
# problems.
env.AppendUnique(CPPFLAGS = [ '-wd4503' ])
# QMAKE_CXXFLAGS += /Zi
# QMAKE_LFLAGS += /DEBUG
+47 -8
View File
@@ -1,8 +1,9 @@
#ifndef Q_MOC_RUN
#include <boost/python.hpp>
#endif
#include <QString>
#include <utility.h>
#include <QDebug>
#include "error.h"
using namespace MOBase;
namespace bpy = boost::python;
@@ -10,17 +11,55 @@ namespace bpy = boost::python;
void reportPythonError()
{
if (PyErr_Occurred()) {
// prints to s_ErrIO buffer
ErrWrapper &errWrapper = ErrWrapper::instance();
errWrapper.startRecordingExceptionMessage();
PyErr_Print();
// extract data from python buffer
bpy::object mainModule = bpy::import("__main__");
bpy::object mainNamespace = mainModule.attr("__dict__");
bpy::object errMsgObj = bpy::eval("s_ErrIO.getvalue()", mainNamespace);
QString errMsg = bpy::extract<QString>(errMsgObj.ptr());
bpy::eval("s_ErrIO.truncate(0)", mainNamespace);
errWrapper.stopRecordingExceptionMessage();
QString errMsg = errWrapper.getLastExceptionMessage();
throw MyException(errMsg);
} else {
throw MyException("An unexpected C++ exception was thrown in python code");
}
}
ErrWrapper & ErrWrapper::instance()
{
static ErrWrapper err;
return err;
}
void ErrWrapper::write(const char * message)
{
buffer << message;
if (buffer.tellp() != 0 && buffer.str().back() == '\n')
{
// actually put the string in a variable so it doesn't get destroyed as soon as we get a pointer to its data
std::string string = buffer.str().substr(0, buffer.str().length() - 1);
qCritical().nospace().noquote() << string.c_str();
buffer = std::stringstream();
}
if (recordingExceptionMessage)
{
lastException << message;
}
}
void ErrWrapper::startRecordingExceptionMessage()
{
recordingExceptionMessage = true;
lastException = std::stringstream();
}
void ErrWrapper::stopRecordingExceptionMessage()
{
recordingExceptionMessage = false;
}
QString ErrWrapper::getLastExceptionMessage()
{
return QString::fromStdString(lastException.str());
}
+19
View File
@@ -1,7 +1,26 @@
#ifndef ERROR_H
#define ERROR_H
#include <QString>
#include <sstream>
// turn an error from the python interpreter into an exception
void reportPythonError();
struct ErrWrapper
{
static ErrWrapper & instance();
void write(const char * message);
void startRecordingExceptionMessage();
void stopRecordingExceptionMessage();
QString getLastExceptionMessage();
std::stringstream buffer;
bool recordingExceptionMessage;
std::stringstream lastException;
};
#endif // ERROR_H
+301
View File
@@ -0,0 +1,301 @@
#include "gamefeatureswrappers.h"
#include <boost/any.hpp>
#include <typeindex>
#include <ipluginlist.h>
#include <iprofile.h>
#include <isavegame.h>
#include <isavegameinfowidget.h>
#include "gilock.h"
#include "pythonwrapperutilities.h"
/////////////////////////////
/// BSAInvalidation Wrapper
bool BSAInvalidationWrapper::isInvalidationBSA(const QString &bsaName)
{
return basicWrapperFunctionImplementation<BSAInvalidationWrapper, bool>(this, "isInvalidationBSA", bsaName);
}
void BSAInvalidationWrapper::deactivate(MOBase::IProfile *profile)
{
return basicWrapperFunctionImplementation<BSAInvalidationWrapper, void>(this, "deactivate", boost::python::ptr(profile));
}
void BSAInvalidationWrapper::activate(MOBase::IProfile *profile)
{
return basicWrapperFunctionImplementation<BSAInvalidationWrapper, void>(this, "activate", boost::python::ptr(profile));
}
bool BSAInvalidationWrapper::prepareProfile(MOBase::IProfile *profile)
{
return basicWrapperFunctionImplementation<BSAInvalidationWrapper, bool>(this, "prepareProfile", boost::python::ptr(profile));
}
/// end BSAInvalidation Wrapper
/////////////////////////////
/// DataArchives Wrapper
QStringList DataArchivesWrapper::vanillaArchives() const
{
return basicWrapperFunctionImplementation<DataArchivesWrapper, QStringList>(this, "vanillaArchives");
}
QStringList DataArchivesWrapper::archives(const MOBase::IProfile *profile) const
{
return basicWrapperFunctionImplementation<DataArchivesWrapper, QStringList>(this, "archives", boost::python::ptr(profile));
}
void DataArchivesWrapper::addArchive(MOBase::IProfile *profile, int index, const QString &archiveName)
{
return basicWrapperFunctionImplementation<DataArchivesWrapper, void>(this, "addArchive", boost::python::ptr(profile), index, archiveName);
}
void DataArchivesWrapper::removeArchive(MOBase::IProfile *profile, const QString &archiveName)
{
return basicWrapperFunctionImplementation<DataArchivesWrapper, void>(this, "removeArchive", boost::python::ptr(profile), archiveName);
}
/// end DataArchives Wrapper
/////////////////////////////
/// GamePlugins Wrapper
void GamePluginsWrapper::writePluginLists(const MOBase::IPluginList * pluginList)
{
return basicWrapperFunctionImplementation<GamePluginsWrapper, void>(this, "writePluginLists", boost::python::ptr(pluginList));
}
void GamePluginsWrapper::readPluginLists(MOBase::IPluginList * pluginList)
{
return basicWrapperFunctionImplementation<GamePluginsWrapper, void>(this, "readPluginLists", boost::python::ptr(pluginList));
}
void GamePluginsWrapper::getLoadOrder(QStringList &loadOrder)
{
return basicWrapperFunctionImplementation<GamePluginsWrapper, void>(this, "getLoadOrder", loadOrder);
}
bool GamePluginsWrapper::lightPluginsAreSupported()
{
return basicWrapperFunctionImplementation<GamePluginsWrapper, bool>(this, "lightPluginsAreSupported");
}
/// end GamePlugins Wrapper
/////////////////////////////
/// LocalSavegames Wrapper
MappingType LocalSavegamesWrapper::mappings(const QDir & profileSaveDir) const
{
return basicWrapperFunctionImplementation<LocalSavegamesWrapper, MappingType>(this, "mappings", profileSaveDir);
}
bool LocalSavegamesWrapper::prepareProfile(MOBase::IProfile * profile)
{
return basicWrapperFunctionImplementation<LocalSavegamesWrapper, bool>(this, "prepareProfile", boost::python::ptr(profile));
}
/// end LocalSavegames Wrapper
/////////////////////////////
/// SaveGameInfo Wrapper
MOBase::ISaveGame const * SaveGameInfoWrapper::getSaveGameInfo(QString const & file) const
{
return basicWrapperFunctionImplementation<SaveGameInfoWrapper, MOBase::ISaveGame const *>(this, "getSaveGameInfo", file);
}
SaveGameInfoWrapper::MissingAssets SaveGameInfoWrapper::getMissingAssets(QString const & file) const
{
return basicWrapperFunctionImplementation<SaveGameInfoWrapper, SaveGameInfoWrapper::MissingAssets>(this, "getMissingAssets", file);
}
MOBase::ISaveGameInfoWidget * SaveGameInfoWrapper::getSaveGameWidget(QWidget * parent) const
{
qCritical("Calling method with unimplemented from_python converter.");
return basicWrapperFunctionImplementation<SaveGameInfoWrapper, MOBase::ISaveGameInfoWidget *>(this, "getSaveGameWidget", boost::python::ptr(parent));
}
bool SaveGameInfoWrapper::hasScriptExtenderSave(QString const & file) const
{
return basicWrapperFunctionImplementation<SaveGameInfoWrapper, bool>(this, "hasScriptExtenderSave", file);
}
/// end SaveGameInfo Wrapper
/////////////////////////////
/// ScriptExtender Wrapper
QString ScriptExtenderWrapper::BinaryName() const
{
return basicWrapperFunctionImplementation<ScriptExtenderWrapper, QString>(this, "BinaryName");
}
QString ScriptExtenderWrapper::PluginPath() const
{
return basicWrapperFunctionImplementation<ScriptExtenderWrapper, QString>(this, "PluginPath");
}
QString ScriptExtenderWrapper::loaderName() const
{
return basicWrapperFunctionImplementation<ScriptExtenderWrapper, QString>(this, "loaderName");
}
QString ScriptExtenderWrapper::loaderPath() const
{
return basicWrapperFunctionImplementation<ScriptExtenderWrapper, QString>(this, "loaderPath");
}
QStringList ScriptExtenderWrapper::saveGameAttachmentExtensions() const
{
return basicWrapperFunctionImplementation<ScriptExtenderWrapper, QStringList>(this, "saveGameAttachmentExtensions");
}
bool ScriptExtenderWrapper::isInstalled() const
{
return basicWrapperFunctionImplementation<ScriptExtenderWrapper, bool>(this, "isInstalled");
}
QString ScriptExtenderWrapper::getExtenderVersion() const
{
return basicWrapperFunctionImplementation<ScriptExtenderWrapper, QString>(this, "getExtenderVersion");
}
WORD ScriptExtenderWrapper::getArch() const
{
return basicWrapperFunctionImplementation<ScriptExtenderWrapper, WORD>(this, "getArch");
}
/// end ScriptExtender Wrapper
/////////////////////////////
/// UnmanagedMods Wrapper
QStringList UnmanagedModsWrapper::mods(bool onlyOfficial) const
{
return basicWrapperFunctionImplementation<UnmanagedModsWrapper, QStringList>(this, "mods", onlyOfficial);
}
QString UnmanagedModsWrapper::displayName(const QString & modName) const
{
return basicWrapperFunctionImplementation<UnmanagedModsWrapper, QString>(this, "displayName", modName);
}
QFileInfo UnmanagedModsWrapper::referenceFile(const QString & modName) const
{
return basicWrapperFunctionImplementation<UnmanagedModsWrapper, QFileInfo>(this, "referenceFile", modName);
}
QStringList UnmanagedModsWrapper::secondaryFiles(const QString & modName) const
{
return basicWrapperFunctionImplementation<UnmanagedModsWrapper, QStringList>(this, "secondaryFiles", modName);
}
/// end UnmanagedMods Wrapper
/////////////////////////////
template<typename T>
void insertGameFeature(std::map<std::type_index, boost::any> &map, const boost::python::object &pyObject)
{
map[std::type_index(typeid(T))] = boost::python::extract<T*>(pyObject)();
}
game_features_map_from_python::game_features_map_from_python()
{
boost::python::converter::registry::push_back(&convertible, &construct, boost::python::type_id<std::map<std::type_index, boost::any>>());
}
void * game_features_map_from_python::convertible(PyObject * objPtr)
{
return PyDict_Check(objPtr) ? objPtr : nullptr;
}
void game_features_map_from_python::construct(PyObject * objPtr, boost::python::converter::rvalue_from_python_stage1_data * data)
{
void *storage = ((boost::python::converter::rvalue_from_python_storage<std::map<std::type_index, boost::any>>*)data)->storage.bytes;
std::map<std::type_index, boost::any> *result = new (storage) std::map<std::type_index, boost::any>();
boost::python::dict source(boost::python::handle<>(boost::python::borrowed(objPtr)));
boost::python::list keys = source.keys();
int len = boost::python::len(keys);
for (int i = 0; i < len; ++i)
{
boost::python::object pyKey = keys[i];
// pyKey should be a Boost.Python.class corresponding to a game feature.
std::string className = boost::python::extract<std::string>(pyKey.attr("__name__"))();
if (className == "BSAInvalidation")
insertGameFeature<BSAInvalidation>(*result, source[pyKey]);
else if (className == "DataArchives")
insertGameFeature<DataArchives>(*result, source[pyKey]);
else if (className == "GamePlugins")
insertGameFeature<GamePlugins>(*result, source[pyKey]);
else if (className == "LocalSavegames")
insertGameFeature<LocalSavegames>(*result, source[pyKey]);
else if (className == "SaveGameInfo")
insertGameFeature<SaveGameInfo>(*result, source[pyKey]);
else if (className == "ScriptExtender")
insertGameFeature<ScriptExtender>(*result, source[pyKey]);
else if (className == "UnmanagedMods")
insertGameFeature<UnmanagedMods>(*result, source[pyKey]);
}
data->convertible = storage;
}
void registerGameFeaturesPythonConverters()
{
namespace bpy = boost::python;
game_features_map_from_python();
// Features require defs for all methods as Python can access C++ features
bpy::class_<BSAInvalidationWrapper, boost::noncopyable>("BSAInvalidation")
.def("isInvalidationBSA", bpy::pure_virtual(&BSAInvalidation::isInvalidationBSA))
.def("deactivate", bpy::pure_virtual(&BSAInvalidation::deactivate))
.def("activate", bpy::pure_virtual(&BSAInvalidation::activate))
;
bpy::class_<DataArchivesWrapper, boost::noncopyable>("DataArchives")
.def("vanillaArchives", bpy::pure_virtual(&DataArchives::vanillaArchives))
.def("archives", bpy::pure_virtual(&DataArchives::archives))
.def("addArchive", bpy::pure_virtual(&DataArchives::addArchive))
.def("removeArchive", bpy::pure_virtual(&DataArchives::removeArchive))
;
bpy::class_<GamePluginsWrapper, boost::noncopyable>("GamePlugins")
.def("writePluginLists", bpy::pure_virtual(&GamePlugins::writePluginLists))
.def("readPluginLists", bpy::pure_virtual(&GamePlugins::readPluginLists))
.def("getLoadOrder", bpy::pure_virtual(&GamePlugins::getLoadOrder))
.def("lightPluginsAreSupported", bpy::pure_virtual(&GamePlugins::lightPluginsAreSupported))
;
bpy::class_<LocalSavegamesWrapper, boost::noncopyable>("LocalSavegames")
.def("mappings", bpy::pure_virtual(&LocalSavegames::mappings))
.def("prepareProfile", bpy::pure_virtual(&LocalSavegames::prepareProfile))
;
bpy::class_<SaveGameInfoWrapper, boost::noncopyable>("SaveGameInfo")
.def("getSaveGameInfo", bpy::pure_virtual(&SaveGameInfo::getSaveGameInfo), bpy::return_value_policy<bpy::manage_new_object>())
.def("getMissingAssets", bpy::pure_virtual(&SaveGameInfo::getMissingAssets))
.def("getSaveGameWidget", bpy::pure_virtual(&SaveGameInfo::getSaveGameWidget), bpy::return_value_policy<bpy::manage_new_object>())
.def("hasScriptExtenderSave", bpy::pure_virtual(&SaveGameInfo::hasScriptExtenderSave))
;
bpy::class_<ScriptExtenderWrapper, boost::noncopyable>("ScriptExtender")
.def("BinaryName", bpy::pure_virtual(&ScriptExtender::BinaryName))
.def("PluginPath", bpy::pure_virtual(&ScriptExtender::PluginPath))
.def("loaderName", bpy::pure_virtual(&ScriptExtender::loaderName))
.def("loaderPath", bpy::pure_virtual(&ScriptExtender::loaderPath))
.def("saveGameAttachmentExtensions", bpy::pure_virtual(&ScriptExtender::saveGameAttachmentExtensions))
.def("isInstalled", bpy::pure_virtual(&ScriptExtender::isInstalled))
.def("getExtenderVersion", bpy::pure_virtual(&ScriptExtender::getExtenderVersion))
.def("getArch", bpy::pure_virtual(&ScriptExtender::getArch))
;
bpy::class_<UnmanagedModsWrapper, boost::noncopyable>("UnmanagedMods")
.def("mods", bpy::pure_virtual(&UnmanagedMods::mods))
.def("displayName", bpy::pure_virtual(&UnmanagedMods::displayName))
.def("referenceFile", bpy::pure_virtual(&UnmanagedMods::referenceFile))
.def("secondaryFiles", bpy::pure_virtual(&UnmanagedMods::secondaryFiles))
;
}
+116
View File
@@ -0,0 +1,116 @@
#ifndef GAMEFEATURESWRAPPERS_H
#define GAMEFEATURESWRAPPERS_H
#include <bsainvalidation.h>
#include <dataarchives.h>
#include <gameplugins.h>
#include <localsavegames.h>
#include <savegameinfo.h>
#include <scriptextender.h>
#include <unmanagedmods.h>
// this might need turning off if Q_MOC_RUN is defined
#include <boost/python.hpp>
/////////////////////////////
/// Wrapper declarations
class BSAInvalidationWrapper : public BSAInvalidation, public boost::python::wrapper<BSAInvalidation>
{
public:
static constexpr const char* className = "BSAInvalidationWrapper";
using boost::python::wrapper<BSAInvalidation>::get_override;
virtual bool isInvalidationBSA(const QString &bsaName) override;
virtual void deactivate(MOBase::IProfile *profile) override;
virtual void activate(MOBase::IProfile *profile) override;
virtual bool prepareProfile(MOBase::IProfile *profile) override;
};
class DataArchivesWrapper : public DataArchives, public boost::python::wrapper<DataArchives>
{
public:
static constexpr const char* className = "DataArchivesWrapper";
using boost::python::wrapper<DataArchives>::get_override;
virtual QStringList vanillaArchives() const override;
virtual QStringList archives(const MOBase::IProfile *profile) const override;
virtual void addArchive(MOBase::IProfile *profile, int index, const QString &archiveName) override;
virtual void removeArchive(MOBase::IProfile *profile, const QString &archiveName) override;
};
class GamePluginsWrapper : public GamePlugins, public boost::python::wrapper<GamePlugins>
{
public:
static constexpr const char* className = "GamePluginsWrapper";
using boost::python::wrapper<GamePlugins>::get_override;
virtual void writePluginLists(const MOBase::IPluginList *pluginList) override;
virtual void readPluginLists(MOBase::IPluginList *pluginList) override;
virtual void getLoadOrder(QStringList &loadOrder) override;
virtual bool lightPluginsAreSupported() override;
};
class LocalSavegamesWrapper : public LocalSavegames, public boost::python::wrapper<LocalSavegames>
{
public:
static constexpr const char* className = "LocalSavegamesWrapper";
using boost::python::wrapper<LocalSavegames>::get_override;
virtual MappingType mappings(const QDir &profileSaveDir) const override;
virtual bool prepareProfile(MOBase::IProfile *profile) override;
};
class SaveGameInfoWrapper : public SaveGameInfo, public boost::python::wrapper<SaveGameInfo>
{
public:
static constexpr const char* className = "SaveGameInfoWrapper";
using boost::python::wrapper<SaveGameInfo>::get_override;
virtual MOBase::ISaveGame const *getSaveGameInfo(QString const &file) const override;
virtual MissingAssets getMissingAssets(QString const &file) const override;
virtual MOBase::ISaveGameInfoWidget *getSaveGameWidget(QWidget *parent = 0) const override;
virtual bool hasScriptExtenderSave(QString const &file) const override;
};
class ScriptExtenderWrapper : public ScriptExtender, public boost::python::wrapper<ScriptExtender>
{
public:
static constexpr const char* className = "ScriptExtenderWrapper";
using boost::python::wrapper<ScriptExtender>::get_override;
virtual QString BinaryName() const override;
virtual QString PluginPath() const override;
virtual QString loaderName() const override;
virtual QString loaderPath() const override;
virtual QStringList saveGameAttachmentExtensions() const override;
virtual bool isInstalled() const override;
virtual QString getExtenderVersion() const override;
virtual WORD getArch() const override;
};
class UnmanagedModsWrapper : public UnmanagedMods, public boost::python::wrapper<UnmanagedMods>
{
public:
static constexpr const char* className = "UnmanagedModsWrapper";
using boost::python::wrapper<UnmanagedMods>::get_override;
virtual QStringList mods(bool onlyOfficial) const override;
virtual QString displayName(const QString &modName) const override;
virtual QFileInfo referenceFile(const QString &modName) const override;
virtual QStringList secondaryFiles(const QString &modName) const override;
};
/// end Wrapper declarations
/////////////////////////////
struct game_features_map_from_python
{
game_features_map_from_python();
static void *convertible(PyObject *objPtr);
static void construct(PyObject *objPtr, boost::python::converter::rvalue_from_python_stage1_data *data);
};
void registerGameFeaturesPythonConverters();
#endif // GAMEFEATURESWRAPPERS_H

Some files were not shown because too many files have changed in this diff Show More