Files
python-plugins-doc/writing-plugins.html
T

580 lines
39 KiB
HTML

<!DOCTYPE html>
<html class="writer-html5" lang="en" >
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Writing Plugins &mdash; MO2 Python Plugin API 2.3rc1 documentation</title>
<link rel="stylesheet" href="_static/css/theme.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="_static/graphviz.css" type="text/css" />
<link rel="shortcut icon" href="_static/mo2.ico"/>
<!--[if lt IE 9]>
<script src="_static/js/html5shiv.min.js"></script>
<![endif]-->
<script type="text/javascript" id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/language_data.js"></script>
<script type="text/javascript" src="_static/js/theme.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="FAQ" href="faq.html" />
<link rel="prev" title="Type of Plugins" href="plugin-types.html" />
</head>
<body class="wy-body-for-nav">
<div class="wy-grid-for-nav">
<nav data-toggle="wy-nav-shift" class="wy-nav-side">
<div class="wy-side-scroll">
<div class="wy-side-nav-search" >
<a href="index.html" class="icon icon-home"> MO2 Python Plugin API
</a>
<div role="search">
<form id="rtd-search-form" class="wy-form" action="search.html" method="get">
<input type="text" name="q" placeholder="Search docs" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="wy-menu wy-menu-vertical" data-spy="affix" role="navigation" aria-label="main navigation">
<p class="caption"><span class="caption-text">Contents:</span></p>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="setup-tools.html">Setting up the environment</a><ul>
<li class="toctree-l2"><a class="reference internal" href="setup-tools.html#required-tools">Required tools</a></li>
<li class="toctree-l2"><a class="reference internal" href="setup-tools.html#preparation">Preparation</a><ul>
<li class="toctree-l3"><a class="reference internal" href="setup-tools.html#get-the-mobase-stubs">1. Get the <code class="docutils literal notranslate"><span class="pre">mobase</span></code> stubs</a></li>
<li class="toctree-l3"><a class="reference internal" href="setup-tools.html#configure-visual-studio-code-for-mobase">2. Configure Visual Studio Code for <code class="docutils literal notranslate"><span class="pre">mobase</span></code></a></li>
<li class="toctree-l3"><a class="reference internal" href="setup-tools.html#configure-mypy-to-find-the-mobase-stubs">3. Configure <code class="docutils literal notranslate"><span class="pre">mypy</span></code> to find the <code class="docutils literal notranslate"><span class="pre">mobase</span></code> stubs</a></li>
<li class="toctree-l3"><a class="reference internal" href="setup-tools.html#optional-automatically-reload-plugins-during-development">4. [Optional] Automatically reload plugins during development</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="setup-tools.html#testing-the-setup">Testing the setup</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="plugin-types.html">Type of Plugins</a><ul>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#installers">Installers</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#previewers">Previewers</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#mod-page">Mod Page</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#game">Game</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#tool">Tool</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#proxies">Proxies</a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#free-plugins"><em>Free Plugins</em></a></li>
<li class="toctree-l2"><a class="reference internal" href="plugin-types.html#extension-interfaces">Extension Interfaces</a><ul>
<li class="toctree-l3"><a class="reference internal" href="plugin-types.html#diagnose">Diagnose</a></li>
<li class="toctree-l3"><a class="reference internal" href="plugin-types.html#file-mappings">File Mappings</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Writing Plugins</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#getting-started">Getting started</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#single-file-plugins">Single file plugins</a></li>
<li class="toctree-l3"><a class="reference internal" href="#module-plugins">Module Plugins</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#writing-the-plugin">Writing the plugin</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#iplugin-interface"><code class="docutils literal notranslate"><span class="pre">IPlugin</span></code> interface</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#examples">Examples</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#tutorial-plugins">Tutorial Plugins</a></li>
<li class="toctree-l3"><a class="reference internal" href="#official-plugins">Official Plugins</a></li>
<li class="toctree-l3"><a class="reference internal" href="#unofficial-plugins">Unofficial Plugins</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="faq.html">FAQ</a><ul>
<li class="toctree-l2"><a class="reference internal" href="faq.html#why-is-mo2-throwing-an-exception-when-i-try-to-create-a-type-inheriting-one-of-mo2-class">1. Why is MO2 throwing an exception when I try to create a type inheriting one of MO2 class?</a></li>
<li class="toctree-l2"><a class="reference internal" href="faq.html#how-can-i-be-sure-to-implement-all-the-required-methods-when-creating-a-plugin">2. How can I be sure to implement all the required methods when creating a plugin?</a></li>
<li class="toctree-l2"><a class="reference internal" href="faq.html#why-are-my-isinstance-x-qobject-and-isinstance-y-qwidget-not-working">3. Why are my <code class="docutils literal notranslate"><span class="pre">isinstance(x,</span> <span class="pre">QObject)</span></code> and <code class="docutils literal notranslate"><span class="pre">isinstance(y,</span> <span class="pre">QWidget)</span></code> not working?</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="mobase.html"><code class="docutils literal notranslate"><span class="pre">mobase</span></code> API</a><ul>
<li class="toctree-l2"><a class="reference internal" href="mobase.html#functions">Functions</a><ul>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.getFileVersion.html">getFileVersion</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.getIconForExecutable.html">getIconForExecutable</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.getProductVersion.html">getProductVersion</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="mobase.html#classes">Classes</a><ul>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.BSAInvalidation.html">BSAInvalidation</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.DataArchives.html">DataArchives</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.EndorsedState.html">EndorsedState</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ExecutableForcedLoadSetting.html">ExecutableForcedLoadSetting</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ExecutableInfo.html">ExecutableInfo</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.FileInfo.html">FileInfo</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.FileTreeEntry.html">FileTreeEntry</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.GamePlugins.html">GamePlugins</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.GuessQuality.html">GuessQuality</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.GuessedString.html">GuessedString</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IDownloadManager.html">IDownloadManager</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IFileTree.html">IFileTree</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IInstallationManager.html">IInstallationManager</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IModInterface.html">IModInterface</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IModList.html">IModList</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IModRepositoryBridge.html">IModRepositoryBridge</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IOrganizer.html">IOrganizer</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPlugin.html">IPlugin</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginDiagnose.html">IPluginDiagnose</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginFileMapper.html">IPluginFileMapper</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginGame.html">IPluginGame</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginInstaller.html">IPluginInstaller</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginInstallerCustom.html">IPluginInstallerCustom</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginInstallerSimple.html">IPluginInstallerSimple</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginList.html">IPluginList</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginModPage.html">IPluginModPage</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginPreview.html">IPluginPreview</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginRequirement.html">IPluginRequirement</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IPluginTool.html">IPluginTool</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.IProfile.html">IProfile</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ISaveGame.html">ISaveGame</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ISaveGameInfoWidget.html">ISaveGameInfoWidget</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.InstallResult.html">InstallResult</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.InterfaceNotImplemented.html">InterfaceNotImplemented</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.LoadOrderMechanism.html">LoadOrderMechanism</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.LocalSavegames.html">LocalSavegames</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.Mapping.html">Mapping</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ModDataChecker.html">ModDataChecker</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ModDataContent.html">ModDataContent</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ModRepositoryFileInfo.html">ModRepositoryFileInfo</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ModState.html">ModState</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.PluginRequirementFactory.html">PluginRequirementFactory</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.PluginSetting.html">PluginSetting</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.PluginState.html">PluginState</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ProfileSetting.html">ProfileSetting</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ReleaseType.html">ReleaseType</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.SaveGameInfo.html">SaveGameInfo</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.ScriptExtender.html">ScriptExtender</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.SortMechanism.html">SortMechanism</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.TrackedState.html">TrackedState</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.UnmanagedMods.html">UnmanagedMods</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.VersionInfo.html">VersionInfo</a></li>
<li class="toctree-l3"><a class="reference internal" href="api/mobase.VersionScheme.html">VersionScheme</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<section data-toggle="wy-nav-shift" class="wy-nav-content-wrap">
<nav class="wy-nav-top" aria-label="top navigation">
<i data-toggle="wy-nav-top" class="fa fa-bars"></i>
<a href="index.html">MO2 Python Plugin API</a>
</nav>
<div class="wy-nav-content">
<div class="rst-content">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="index.html" class="icon icon-home"></a> &raquo;</li>
<li>Writing Plugins</li>
<li class="wy-breadcrumbs-aside">
<a href="_sources/writing-plugins.rst.txt" rel="nofollow"> View page source</a>
</li>
</ul>
<hr/>
</div>
<div role="main" class="document" itemscope="itemscope" itemtype="http://schema.org/Article">
<div itemprop="articleBody">
<div class="section" id="writing-plugins">
<h1>Writing Plugins<a class="headerlink" href="#writing-plugins" title="Permalink to this headline">¶</a></h1>
<div class="section" id="getting-started">
<h2>Getting started<a class="headerlink" href="#getting-started" title="Permalink to this headline">¶</a></h2>
<p>Now that you know which type of plugin you need, you can start writing your own plugin.
There is two way to write a Python plugin:</p>
<ul class="simple">
<li><p><a class="reference internal" href="#single-file-plugin"><span class="std std-ref">Single file plugins</span></a>: You use a single <code class="docutils literal notranslate"><span class="pre">.py</span></code> file that you put directly in the <code class="docutils literal notranslate"><span class="pre">plugins</span></code>
folder of the MO2 installation.</p></li>
<li><p><a class="reference internal" href="#module-plugin"><span class="std std-ref">Module Plugins</span></a>: You create a Python package (folder) with a <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code> file that you
put in the <code class="docutils literal notranslate"><span class="pre">plugins</span></code> folder of the MO2 installation.</p></li>
</ul>
<p>Most examples of plugins will be module plugins.</p>
<div class="section" id="single-file-plugins">
<span id="single-file-plugin"></span><h3>Single file plugins<a class="headerlink" href="#single-file-plugins" title="Permalink to this headline">¶</a></h3>
<p>Prior to version 2.3, this was the only way of creating a Python plugin. You simply need
to create a <code class="docutils literal notranslate"><span class="pre">myplugin.py</span></code> file in the <code class="docutils literal notranslate"><span class="pre">plugins</span></code> folder of Mod Organizer 2 with a content
similar to:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">mobase</span>
<span class="k">class</span> <span class="nc">MyPlugin</span><span class="p">(</span><span class="o">...</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">createPlugin</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">mobase</span><span class="o">.</span><span class="n">IPlugin</span><span class="p">:</span>
<span class="k">return</span> <span class="n">MyPlugin</span><span class="p">()</span>
</pre></div>
</div>
<p>We will see later on how to create the actual <code class="docutils literal notranslate"><span class="pre">MyPlugin</span></code> class.
The <code class="docutils literal notranslate"><span class="pre">createPlugin</span></code> function is the function that is called by Mod Organizer 2 to instantiate
the plugin.</p>
<p>You can also provide multiple plugins by using <code class="docutils literal notranslate"><span class="pre">createPlugins</span></code> instead of <code class="docutils literal notranslate"><span class="pre">createPlugin</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span>
<span class="kn">import</span> <span class="nn">mobase</span>
<span class="k">class</span> <span class="nc">MyPlugin1</span><span class="p">(</span><span class="o">...</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">MyPlugin2</span><span class="p">(</span><span class="o">...</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">def</span> <span class="nf">createPlugins</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">mobase</span><span class="o">.</span><span class="n">IPlugin</span><span class="p">]:</span>
<span class="k">return</span> <span class="p">[</span><span class="n">MyPlugin1</span><span class="p">(),</span> <span class="n">MyPlugin2</span><span class="p">()]</span>
</pre></div>
</div>
<p><strong>Note:</strong> If you provide neither <code class="docutils literal notranslate"><span class="pre">createPlugin()</span></code> nor <code class="docutils literal notranslate"><span class="pre">createPlugins</span></code>, MO2 will display
an error message in the logs.</p>
<p><strong>Note:</strong> If you add a return type-hint to <code class="docutils literal notranslate"><span class="pre">createPlugin()</span></code> or <code class="docutils literal notranslate"><span class="pre">createPlugins</span></code> (<code class="docutils literal notranslate"><span class="pre">-&gt;</span></code>), <code class="docutils literal notranslate"><span class="pre">mypy</span></code>
will type-check the function and warn you if one of your plugins is invalid, e.g. if you
forgot to implement a required method.</p>
<p>If you need to provide other files with your <code class="docutils literal notranslate"><span class="pre">.py</span></code> (assets or other Python files), you can
put them in the <code class="docutils literal notranslate"><span class="pre">plugins/data</span></code>, but this is deprecated since MO2 2.3, and you should instead
create a Python module plugin.</p>
</div>
<div class="section" id="module-plugins">
<span id="module-plugin"></span><h3>Module Plugins<a class="headerlink" href="#module-plugins" title="Permalink to this headline">¶</a></h3>
<p>Module plugins were introduced in MO2 2.3 and are shipped as whole folder containg a python module.
The minimum content of the folder is a <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code> file with <code class="docutils literal notranslate"><span class="pre">createPlugin</span></code> or <code class="docutils literal notranslate"><span class="pre">createPlugins</span></code>
function.</p>
<p>A minimal module plugin could be as follows:</p>
<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>plugins/ <span class="c1"># MO2 plugins folder</span>
myplugin/
__init__.py
plugin.py
</pre></div>
</div>
<p>In <code class="docutils literal notranslate"><span class="pre">plugin.py</span></code>, you could define your plugin:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># plugin.py</span>
<span class="kn">import</span> <span class="nn">mobase</span>
<span class="k">class</span> <span class="nc">MyPlugin</span><span class="p">(</span><span class="o">...</span><span class="p">):</span>
<span class="o">...</span>
</pre></div>
</div>
<p>And in <code class="docutils literal notranslate"><span class="pre">__init__.py</span></code>, you should write <code class="docutils literal notranslate"><span class="pre">createPlugin</span></code>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="c1"># __init__.py</span>
<span class="kn">import</span> <span class="nn">mobase</span> <span class="c1"># For type-checking createPlugin().</span>
<span class="kn">from</span> <span class="nn">.plugin</span> <span class="kn">import</span> <span class="n">MyPlugin</span> <span class="c1"># Always use relative import:</span>
<span class="k">def</span> <span class="nf">createPlugin</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">mobase</span><span class="o">.</span><span class="n">IPlugin</span><span class="p">:</span>
<span class="k">return</span> <span class="n">MyPlugin</span><span class="p">()</span>
</pre></div>
</div>
<p>Similar to single-file plugins, you can expose <code class="docutils literal notranslate"><span class="pre">createPlugins</span></code> instead of <code class="docutils literal notranslate"><span class="pre">createPlugin</span></code>
to instantiate multiple plugins.</p>
<p><strong>Note:</strong> The name of the folder does not have to be a valid python package, and you should
always use relative imports within the module (<code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">.xxx</span></code>) instead of absolute ones.</p>
</div>
</div>
<div class="section" id="writing-the-plugin">
<h2>Writing the plugin<a class="headerlink" href="#writing-the-plugin" title="Permalink to this headline">¶</a></h2>
<div class="section" id="iplugin-interface">
<h3><code class="docutils literal notranslate"><span class="pre">IPlugin</span></code> interface<a class="headerlink" href="#iplugin-interface" title="Permalink to this headline">¶</a></h3>
<p>In the code snippets above, the <code class="docutils literal notranslate"><span class="pre">MyPlugin</span></code> class was not implemented.
Depending on the <a class="reference internal" href="plugin-types.html#type-of-plugins"><span class="std std-ref">type of plugins</span></a> that you want to create, you will
need to extend a different class.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyTool</span><span class="p">(</span><span class="n">mobase</span><span class="o">.</span><span class="n">IPluginTool</span><span class="p">):</span> <span class="c1"># Create a Tool plugin</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">MyPreview</span><span class="p">(</span><span class="n">mobase</span><span class="o">.</span><span class="n">IPluginPreview</span><span class="p">):</span> <span class="c1"># Create a preview plugin</span>
<span class="o">...</span>
</pre></div>
</div>
<p>Each plugin class has its own abstract methods that you need to implement but all the classes
also extend <code class="docutils literal notranslate"><span class="pre">IPlugin</span></code>, so you need to implement the methods from <a class="reference internal" href="api/mobase.IPlugin.html#mobase.IPlugin" title="mobase.IPlugin"><code class="xref py py-class docutils literal notranslate"><span class="pre">IPlugin</span></code></a>:</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span>
<span class="kn">import</span> <span class="nn">mobase</span>
<span class="k">class</span> <span class="nc">MyPlugin</span><span class="p">(</span><span class="o">...</span><span class="p">):</span> <span class="c1"># The base class depends on the actual type of plugin</span>
<span class="n">_organizer</span><span class="p">:</span> <span class="n">mobase</span><span class="o">.</span><span class="n">IOrganizer</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">super</span><span class="p">()</span><span class="o">.</span><span class="fm">__init__</span><span class="p">()</span> <span class="c1"># You need to call this manually.</span>
<span class="k">def</span> <span class="nf">init</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">organizer</span><span class="p">:</span> <span class="n">mobase</span><span class="o">.</span><span class="n">IOrganizer</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_organizer</span> <span class="o">=</span> <span class="n">organizer</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="k">def</span> <span class="nf">name</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">&quot;&quot;</span>
<span class="k">def</span> <span class="nf">author</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="s2">&quot;Tannin&quot;</span>
<span class="k">def</span> <span class="nf">description</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_tr</span><span class="p">(</span><span class="s2">&quot;Gives a friendly greeting&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">version</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">mobase</span><span class="o">.</span><span class="n">VersionInfo</span><span class="p">:</span>
<span class="k">return</span> <span class="n">mobase</span><span class="o">.</span><span class="n">VersionInfo</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">mobase</span><span class="o">.</span><span class="n">ReleaseType</span><span class="o">.</span><span class="n">FINAL</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">isActive</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">bool</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_organizer</span><span class="o">.</span><span class="n">pluginSetting</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">name</span><span class="p">(),</span> <span class="s2">&quot;enabled&quot;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">settings</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">mobase</span><span class="o">.</span><span class="n">PluginSetting</span><span class="p">]:</span>
<span class="k">return</span> <span class="p">[</span>
<span class="n">mobase</span><span class="o">.</span><span class="n">PluginSetting</span><span class="p">(</span><span class="s2">&quot;enabled&quot;</span><span class="p">,</span> <span class="s2">&quot;enable this plugin&quot;</span><span class="p">,</span> <span class="kc">True</span><span class="p">)</span>
<span class="p">]</span>
</pre></div>
</div>
<p>Most of these are pretty simple to understand:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">name</span></code>: Returns the name of the plugin. The name of the plugin is used to
fetch settings, and in many places, so this should not change between versions.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">author</span></code>: Returns the name of the plugin author (you!).</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">description</span></code>: Returns the description of the plugin.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">version</span></code>: Returns the version of the plugin. See <a class="reference internal" href="api/mobase.VersionInfo.html#mobase.VersionInfo" title="mobase.VersionInfo"><code class="xref py py-class docutils literal notranslate"><span class="pre">VersionInfo</span></code></a> for
more details.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">isActive</span></code>: Returns <code class="docutils literal notranslate"><span class="pre">True</span></code> if the plugin is active, <code class="docutils literal notranslate"><span class="pre">False</span></code> otherwise. This
usually returns <code class="docutils literal notranslate"><span class="pre">True</span></code>, unless you want to check for something to dynamically
enable the plugin. You can also use a plugin setting to allow users to disable
your plugins.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">settings</span></code>: Returns the list of settings (that user can modify) for this plugin.
Settings can be <code class="docutils literal notranslate"><span class="pre">int</span></code>, <code class="docutils literal notranslate"><span class="pre">bool</span></code>, <code class="docutils literal notranslate"><span class="pre">str</span></code> or list of <code class="docutils literal notranslate"><span class="pre">str</span></code>. Here we indicate
that we have a “enabled” setting that user could use to disable the plugin (and
we use it in <code class="docutils literal notranslate"><span class="pre">isActive</span></code>).</p></li>
</ul>
<p>The <code class="docutils literal notranslate"><span class="pre">__init__</span></code> method is the normal Python constructor for our plugin, called when doing
<code class="docutils literal notranslate"><span class="pre">MyPlugin()</span></code>.
You should always call <code class="docutils literal notranslate"><span class="pre">super().__init__()</span></code> explicitly when extending MO2 classes (due to
a “bug” in <code class="docutils literal notranslate"><span class="pre">boost.python</span></code>).</p>
<p>The <code class="docutils literal notranslate"><span class="pre">init</span></code> method is called by MO2 to initialize the plugin. The given argument, <code class="docutils literal notranslate"><span class="pre">organizer</span></code>,
is an instance of <a class="reference internal" href="api/mobase.IOrganizer.html#mobase.IOrganizer" title="mobase.IOrganizer"><code class="xref py py-class docutils literal notranslate"><span class="pre">IOrganizer</span></code></a> which is the class used to interface with MO2.
Here, we use it in the <code class="docutils literal notranslate"><span class="pre">isActive()</span></code> method to retrieve the “enabled” setting for our plugin.
See <a class="reference internal" href="api/mobase.IOrganizer.html#mobase.IOrganizer" title="mobase.IOrganizer"><code class="xref py py-class docutils literal notranslate"><span class="pre">IOrganizer</span></code></a> for more details.</p>
</div>
</div>
<div class="section" id="examples">
<h2>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h2>
<p>This section contains (links to) examples of MO2 Python plugins.
Some of these plugins have been created for educational purpose and are thus very detailed and
easy to understand or get started from.</p>
<div class="section" id="tutorial-plugins">
<h3>Tutorial Plugins<a class="headerlink" href="#tutorial-plugins" title="Permalink to this headline">¶</a></h3>
<p><a class="reference external" href="https://github.com/Holt59/modorganizer-python_plugins">This repository</a> contains examples of Python
plugins that were written only to help users write their own plugins.
If you want to start somewhere, this is the place to go.</p>
</div>
<div class="section" id="official-plugins">
<h3>Official Plugins<a class="headerlink" href="#official-plugins" title="Permalink to this headline">¶</a></h3>
<p>These plugins are (or will be) included in MO2 releases and are usually maintain by some members of
the MO2 development teams.
These plugins are not as well documented as the ones in the repository above.</p>
<ul class="simple">
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-basic_games">Basic Games</a> [<code class="docutils literal notranslate"><span class="pre">IPluginGame</span></code>]</dt><dd><p>This is the meta-plugin for “basic” games. It is a complex
plugins and should mostly be investigated if you want to add a game to it.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-fnistool">FNIS Tool</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>Plugin to integrate FNIS into MO2.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-preview_dds">Preview DDS</a> [<code class="docutils literal notranslate"><span class="pre">IPluginPreview</span></code>]:</dt><dd><p>Plugin to preview DDS files. Quite complex due to the use
of OpenGL for display.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-form43_checker">Form 43 Checker</a> [<code class="docutils literal notranslate"><span class="pre">IPluginDiagnose</span></code>]:</dt><dd><p>Plugin that warn users if there are form 43 ESPs (Skyrim ESPs)
enabled when managing a Skyrim SE instance.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-tool_configurator">Tool Configurator</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>Plugin that allows easier modifications of game settings.
Mostly contains a complex GUI for managing INI files.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/ModOrganizer2/modorganizer-script_extender_plugin_checker">Script Extender Plugin Checker</a> [<code class="docutils literal notranslate"><span class="pre">IPluginDiagnose</span></code>]:</dt><dd><p>Plugin that checks Script Extender logs to see
if some plugins have failed to load and display information to the user if possible.</p>
</dd>
</dl>
</li>
</ul>
</div>
<div class="section" id="unofficial-plugins">
<h3>Unofficial Plugins<a class="headerlink" href="#unofficial-plugins" title="Permalink to this headline">¶</a></h3>
<p>These plugins have been created by developpers for MO2 and are usually distributed on Nexus.</p>
<ul class="simple">
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/deorder/mo2-plugins">Merge Plugins Hide</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>Hide / unhide plugins that were merged using <code class="docutils literal notranslate"><span class="pre">Merge</span> <span class="pre">Plugins</span></code> or <code class="docutils literal notranslate"><span class="pre">zMerge</span></code>.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/AnyOldName3/ModOrganizer-to-OpenMW">OpenMW Exporter</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>A Mod Organizer plugin to export your VFS, plugin selection and load order to OpenMW.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/AnyOldName3/modorganizer-orphaned_script_extender_save_deleter">Orphaned Script Extender Save Deleter</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>Mod Organizer plugin to delete orphaned script extender co-saves.</p>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference external" href="https://github.com/deorder/mo2-plugins">Sync Mod Order</a> [<code class="docutils literal notranslate"><span class="pre">IPluginTool</span></code>]:</dt><dd><p>Synchronize mod order from current profile to another while keeping the (enabled/disabled) state intact.</p>
</dd>
</dl>
</li>
</ul>
<p><em>Feel free to open an issue or a pull-request if you want to add your own plugin to the list.</em></p>
</div>
</div>
</div>
</div>
</div>
<footer>
<div class="rst-footer-buttons" role="navigation" aria-label="footer navigation">
<a href="faq.html" class="btn btn-neutral float-right" title="FAQ" accesskey="n" rel="next">Next <span class="fa fa-arrow-circle-right" aria-hidden="true"></span></a>
<a href="plugin-types.html" class="btn btn-neutral float-left" title="Type of Plugins" accesskey="p" rel="prev"><span class="fa fa-arrow-circle-left" aria-hidden="true"></span> Previous</a>
</div>
<hr/>
<div role="contentinfo">
<p>
&#169; Copyright 2020, Holt59.
</p>
</div>
Built with <a href="https://www.sphinx-doc.org/">Sphinx</a> using a
<a href="https://github.com/readthedocs/sphinx_rtd_theme">theme</a>
provided by <a href="https://readthedocs.org">Read the Docs</a>.
</footer>
</div>
</div>
</section>
</div>
<script type="text/javascript">
jQuery(function () {
SphinxRtdTheme.Navigation.enable(true);
});
</script>
</body>
</html>