Workbench Plugin – Arma Reforger

From Bohemia Interactive Community
Jump to navigation Jump to search
m (Text replacement - "lang="cpp">" to "lang="C#">")
m (Text replacement - "<syntaxhighlight lang="C#">" to "<enforce>")
Line 35: Line 35:
A plugin inherits from {{hl|WorkbenchPlugin}} and is decorated with a {{hl|WorkbenchPluginAttribute}} attribute which signature is as follow:
A plugin inherits from {{hl|WorkbenchPlugin}} and is decorated with a {{hl|WorkbenchPluginAttribute}} attribute which signature is as follow:


<syntaxhighlight lang="C#">
<enforce>
WorkbenchPluginAttribute(string name, string description = "", string shortcut = "", string icon = "", array<string> wbModules = null, string category = "", int awesomeFontCode = 0)
WorkbenchPluginAttribute(string name, string description = "", string shortcut = "", string icon = "", array<string> wbModules = null, string category = "", int awesomeFontCode = 0)
</syntaxhighlight>
</syntaxhighlight>
Line 64: Line 64:


Each Workbench module (editor) API can be accessed through the following script:
Each Workbench module (editor) API can be accessed through the following script:
<syntaxhighlight lang="C#">
<enforce>
ModuleType moduleType = Workbench.GetModule(ModuleType);
ModuleType moduleType = Workbench.GetModule(ModuleType);
</syntaxhighlight>
</syntaxhighlight>
Line 96: Line 96:
It is linked to the {{Controls|Ctrl|Shift|H}} keyboard shortcut, and applies only to "ScriptEditor" Workbench module (a.k.a Script Editor).
It is linked to the {{Controls|Ctrl|Shift|H}} keyboard shortcut, and applies only to "ScriptEditor" Workbench module (a.k.a Script Editor).


<syntaxhighlight lang="C#">
<enforce>
[WorkbenchPluginAttribute(name: "Tutorial Plugin", description: "This tutorial plugin does something.", shortcut: "Ctrl+Shift+H", wbModules: { "ScriptEditor" }, awesomeFontCode: 0xF188)]
[WorkbenchPluginAttribute(name: "Tutorial Plugin", description: "This tutorial plugin does something.", shortcut: "Ctrl+Shift+H", wbModules: { "ScriptEditor" }, awesomeFontCode: 0xF188)]
class TutorialPlugin : WorkbenchPlugin
class TutorialPlugin : WorkbenchPlugin
Line 109: Line 109:
In the below code, the {{hl|GetCurrentLine}} method is used to get the cursor location's line number. The {{hl|GetLineText}}/{{hl|SetLineText}} methods is used to obtain and change the line's value by adding an inline comment indicating the current line number ("hardcoded" into the comment).
In the below code, the {{hl|GetCurrentLine}} method is used to get the cursor location's line number. The {{hl|GetLineText}}/{{hl|SetLineText}} methods is used to obtain and change the line's value by adding an inline comment indicating the current line number ("hardcoded" into the comment).


<syntaxhighlight lang="C#">
<enforce>
[WorkbenchPluginAttribute(name: "Tutorial Plugin", description: "This tutorial plugin does something.", shortcut: "Ctrl+Shift+H", wbModules: { "ScriptEditor" }, awesomeFontCode: 0xF188)]
[WorkbenchPluginAttribute(name: "Tutorial Plugin", description: "This tutorial plugin does something.", shortcut: "Ctrl+Shift+H", wbModules: { "ScriptEditor" }, awesomeFontCode: 0xF188)]
class TutorialPlugin : WorkbenchPlugin
class TutorialPlugin : WorkbenchPlugin
Line 138: Line 138:
Displayed parameters are declared values decorated with an {{hl|Attribute}}; a full setup is done as follow:
Displayed parameters are declared values decorated with an {{hl|Attribute}}; a full setup is done as follow:


<syntaxhighlight lang="C#">
<enforce>
[WorkbenchPluginAttribute(name: "Tutorial Plugin", description: "This tutorial plugin does something.", shortcut: "Ctrl+Shift+H", wbModules: { "ScriptEditor" }, awesomeFontCode: 0xF188)]
[WorkbenchPluginAttribute(name: "Tutorial Plugin", description: "This tutorial plugin does something.", shortcut: "Ctrl+Shift+H", wbModules: { "ScriptEditor" }, awesomeFontCode: 0xF188)]
class TutorialPlugin : WorkbenchPlugin
class TutorialPlugin : WorkbenchPlugin
Line 176: Line 176:
==== Buttons ====
==== Buttons ====
A button method is decorated with a {{hl|ButtonAttribute}} attribute which signature is as follow:
A button method is decorated with a {{hl|ButtonAttribute}} attribute which signature is as follow:
<syntaxhighlight lang="C#">
<enforce>
ButtonAttribute(string label = "ScriptButton", bool focused = false)
ButtonAttribute(string label = "ScriptButton", bool focused = false)
</syntaxhighlight>
</syntaxhighlight>


A button method's return type can be anything, but the value will be treated as a boolean int (1 = true, 0 = false). A {{hl|void}} method will return 0. An empty string result will convert as a 1.
A button method's return type can be anything, but the value will be treated as a boolean int (1 = true, 0 = false). A {{hl|void}} method will return 0. An empty string result will convert as a 1.
<syntaxhighlight lang="C#">
<enforce>
[ButtonAttribute("OK")]
[ButtonAttribute("OK")]
int ButtonOK()
int ButtonOK()

Revision as of 19:17, 30 July 2022

Workbench Plugins are script files that can be triggered from within any editor (Resource Browser, World Editor, Script Editor, etc).

Existing plugins are listed in scripts > WorkbenchGame and are sorted by directories.

Editor Directory
Common Plugins Editor
Resource Manager ResourceManager
String Editor LocalizationEditor
Script Editor ScriptEditor
World Editor WorldEditor

A Plugin must be named ClassnamePlugin, and its file too.

A Tool must be named ClassnameTool, and its file too.


Anatomy

Type

Plugin

A plugin inherits from WorkbenchPlugin and is decorated with a WorkbenchPluginAttribute attribute which signature is as follow:

<enforce> WorkbenchPluginAttribute(string name, string description = "", string shortcut = "", string icon = "", array<string> wbModules = null, string category = "", int awesomeFontCode = 0) </syntaxhighlight>

  • name is mandatory: it is the plugin's display name
  • description
  • shortcut: none (empty string) can be defined, the plugin will then need to be triggered from the Plugin top menu
  • icon
  • wbModules: to which editors does this plugin apply (e.g wbModules = { "ScriptEditor" })
  • category: the plugins menu entry in which this plugin will find itself (e.g Plugins > Text > TutorialPlugin)
  • awesomeFontCode: the FontAwesome icon associated with the plugin (see FontAwesome's Cheatsheet)

A plugin must also override either or both Run or RunCommandLine methods in order to have an impact. It can also, but is not mandatory, override the Configure method to display a settings entry.

Tool

A tool is a system that allows for direct manipulation with a config panel available on the side.

For now, Tools are only available for the World Editor, and inherit from the WorldEditorTool class.

A tool inherits from the editor-related class (e.g World Editor: WorldEditorTool) in order to be found in said editor's Tools menu.

It is decorated with a WorkbenchToolAttribute attribute which signature is identical to WorkbenchPluginAttribute (see above).

Scripting

A plugin has access to the currently loaded game/project resources, but in order to be as adaptable as possible it should also be generic.

Each Workbench module (editor) API can be accessed through the following script: <enforce> ModuleType moduleType = Workbench.GetModule(ModuleType); </syntaxhighlight>

Where ModuleType can be one of the following classes, all children of the WBModuleDef class):

Editor Class
Resource Manager ResourceManager
String Editor LocalizationEditor
Script Editor ScriptEditor
World Editor WorldEditor

Each module has obviously a different API. This tutorial will work with the Script Editor.


Create a Plugin

Run Method

The following is a very basic plugin that does nothing but print "It works!" in the debug console on trigger. It is linked to the Ctrl + ⇧ Shift + H keyboard shortcut, and applies only to "ScriptEditor" Workbench module (a.k.a Script Editor).

<enforce> [WorkbenchPluginAttribute(name: "Tutorial Plugin", description: "This tutorial plugin does something.", shortcut: "Ctrl+Shift+H", wbModules: { "ScriptEditor" }, awesomeFontCode: 0xF188)] class TutorialPlugin : WorkbenchPlugin { override void Run() { Print("It works!"); } } </syntaxhighlight>

In the below code, the GetCurrentLine method is used to get the cursor location's line number. The GetLineText/SetLineText methods is used to obtain and change the line's value by adding an inline comment indicating the current line number ("hardcoded" into the comment).

<enforce> [WorkbenchPluginAttribute(name: "Tutorial Plugin", description: "This tutorial plugin does something.", shortcut: "Ctrl+Shift+H", wbModules: { "ScriptEditor" }, awesomeFontCode: 0xF188)] class TutorialPlugin : WorkbenchPlugin { override void Run() { ScriptEditor scriptEditor = Workbench.GetModule(ScriptEditor); int lineNumber = scriptEditor.GetCurrentLine(); string lineContent; scriptEditor.GetLineText(lineContent); lineContent += " // current line is " + (lineNumber + 1); scriptEditor.SetLineText(lineContent); } } </syntaxhighlight>

Every operation goes into one Ctrl+Z each, making reverting a multi-line text operation successive Ctrl+Zs.

Configure Method

The Configure method is the one called when clicking Plugins > Settings > Plugin Name. If this method is not overriden with a non-empty code, the option does not appear in this menu.

Dialog

Setup

The Workbench.ScriptDialog methods allows for displaying UI dialogs for the user to confirm an action or set values. It can be used in any method (e.g not only Configure).

Displayed parameters are declared values decorated with an Attribute; a full setup is done as follow:

<enforce> [WorkbenchPluginAttribute(name: "Tutorial Plugin", description: "This tutorial plugin does something.", shortcut: "Ctrl+Shift+H", wbModules: { "ScriptEditor" }, awesomeFontCode: 0xF188)] class TutorialPlugin : WorkbenchPlugin { [Attribute(desc: "Only display the line number without any other text")] protected bool m_bOnlyLineNumber;

override void Run() { ScriptEditor scriptEditor = Workbench.GetModule(ScriptEditor); int lineNumber = scriptEditor.GetCurrentLine(); string lineContent; scriptEditor.GetLineText(lineContent); string lineNumberText = ""; if (!m_bOnlyLineNumber) { lineNumberText = "current line is "; } lineNumberText += (lineNumber + 1).ToString();

lineContent += " // " + lineNumberText; scriptEditor.SetLineText(lineContent); }

override void Configure() { Workbench.ScriptDialog("Tutorial Plugin Configuration", "Usage:\nTick the checkbox or not, depending on if the line number should be hardcoded or not", this); } } </syntaxhighlight>

Think of the plugin's behaviour: should the end user encounter a configuration popup on each tool usage (e.g from the Run method) or can it be configured once, or should some settings be offered on every usage?

Buttons

A button method is decorated with a ButtonAttribute attribute which signature is as follow: <enforce> ButtonAttribute(string label = "ScriptButton", bool focused = false) </syntaxhighlight>

A button method's return type can be anything, but the value will be treated as a boolean int (1 = true, 0 = false). A void method will return 0. An empty string result will convert as a 1. <enforce> [ButtonAttribute("OK")] int ButtonOK() { return 42; // Workbench.ScriptDialog will return 1/true } </syntaxhighlight> The Workbench.ScriptDialog's return value can then be used to know if the user confirmed or cancelled an interface.

By default, a scripted dialog does not have any buttons and clicking on the close button (« × ») will make the Workbench.ScriptDialog method return 0.