Workbench Plugin Tutorial – Arma Reforger
Lou Montana (talk | contribs) m (Remove after class' semicolons) |
Lou Montana (talk | contribs) m (Some wiki formatting) |
||
Line 118: | Line 118: | ||
=== Workbench Attribute === | === Workbench Attribute === | ||
'''WorkbenchPluginAttribute''' defines how & where the plugin is going to be visible. We already have display name defined via '''name''' attribute & '''wbModules''' parameter to show this plugin only in '''Resource Manager'''. There are few more attributes which are quite handy when developing plugins. | '''WorkbenchPluginAttribute''' defines how & where the plugin is going to be visible. We already have display name defined ''via'' '''name''' attribute & '''wbModules''' parameter to show this plugin only in '''Resource Manager'''. There are few more attributes which are quite handy when developing plugins. | ||
{{Feature|informative| | {{Feature|informative| | ||
Line 231: | Line 231: | ||
* Space is added after each capital letter | * Space is added after each capital letter | ||
{{hl|m_bCopyToClipboard}} will then be displayed as {{hl|Copy | {{hl|m_bCopyToClipboard}} will then be displayed as {{hl|Copy To Clipboard}}. | ||
}} | }} | ||
Line 446: | Line 446: | ||
O:\PathToReforger\ArmaReforgerWorkbenchSteam.exe -wbmodule=ResourceManager -plugin=SampleResourceManagerPlugin | O:\PathToReforger\ArmaReforgerWorkbenchSteam.exe -wbmodule=ResourceManager -plugin=SampleResourceManagerPlugin | ||
Furthermore, you can also read custom command line parameters which are passed to the Workbench via '''GetCmdLine''' method! To do so, add additional parameter in your shortcut after '''-plugin=SampleResourceManagerPlugin''' (see [[Arma Reforger:Startup Parameters|Startup Parameters]]). | Furthermore, you can also read custom command line parameters which are passed to the Workbench ''via'' '''GetCmdLine''' method! To do so, add additional parameter in your shortcut after '''-plugin=SampleResourceManagerPlugin''' (see [[Arma Reforger:Startup Parameters|Startup Parameters]]). | ||
O:\PathToReforger\ArmaReforgerWorkbenchSteam.exe -wbmodule=ResourceManager -plugin=SampleResourceManagerPlugin -myParameter="$ArmaReforger:Prefabs\Vehicles" | O:\PathToReforger\ArmaReforgerWorkbenchSteam.exe -wbmodule=ResourceManager -plugin=SampleResourceManagerPlugin -myParameter="$ArmaReforger:Prefabs\Vehicles" | ||
Line 766: | Line 766: | ||
* Usage of '''WorkbenchToolAttribute''' (which shares available parameters with plugin - see Workbench Attribute) to expose it to '''World Editor''' | * Usage of '''WorkbenchToolAttribute''' (which shares available parameters with plugin - see Workbench Attribute) to expose it to '''World Editor''' | ||
* Inheritance from '''WorldEditorTool''' class, which has different pool of methods available compared to plugins | * Inheritance from '''WorldEditorTool''' class, which has different pool of methods available compared to plugins | ||
* They cannot be launched via CLI parameter | * They cannot be launched ''via'' CLI parameter | ||
* They can use description parameter '''(2)''' | * They can use description parameter '''(2)''' | ||
* They are not grouped in categories like plugins, therefore category parameter is not relevant for them | * They are not grouped in categories like plugins, therefore category parameter is not relevant for them | ||
Line 785: | Line 785: | ||
=== Using World Editor API === | === Using World Editor API === | ||
When performing any operations to entities, you need to call '''BeginEntityAction''', which marks start of logical edit actions. Use m_API.'''EndEntityAction'''(); to mark end of edit actions. All transformations between '''BeginEntityAction & EndEntityAction''' are used by '''World Editor''' history stack - such actions can be reverted by user either via '''Undo last action''' button or shortcut (Ctrl | When performing any operations to entities, you need to call '''BeginEntityAction''', which marks start of logical edit actions. Use m_API.'''EndEntityAction'''(); to mark end of edit actions. | ||
All transformations between '''BeginEntityAction & EndEntityAction''' are used by '''World Editor''' history stack - such actions can be reverted by user either ''via'' '''Undo last action''' button or shortcut ({{Controls|Ctrl|Z}}). | |||
In below example code is creating a new entity and applies random scale to it. | In below example code is creating a new entity and applies random scale to it. | ||
Line 857: | Line 858: | ||
// Delete all entities created by this tool | // Delete all entities created by this tool | ||
m_API.BeginEntityAction("Changing scale of entities"); | m_API.BeginEntityAction("Changing scale of entities"); | ||
foreach ( | foreach (IEntity entity : m_aEntities) | ||
{ | { | ||
m_API.ModifyEntityKey(entity, "scale", Math.RandomFloat(0.5, 2).ToString()); | m_API.ModifyEntityKey(entity, "scale", Math.RandomFloat(0.5, 2).ToString()); |
Revision as of 17:37, 19 June 2023
Workbench allows to extend its functionality to certain degree. With help of scripts, you can create plugins for Resource Manager, Script Editor, String Editor & World Editor. Furthermore, you can also create additional tools for World Editor.
In general, you can use both plugins & tools for various types of automation like:
- Batch processing files
- Automatic testing of assets
- Generating databases
- Performing automation task on action
Editor Plugins
Plugin can be located in top toolbar in "Plugins" section (1). From there, you can either select one of the already existing plugins (3) or change their settings in Settings sub menu (2). Plugins can be also organized in submenus (4), so you can conveniently gather multiple plugins.
World Editor Tools
By default, World Editor Tools can be found right above the preview window of World Editor.
Some of those tools are part of the engine and some of them are scripted. Once some tool is selected, you can change its properties.
To start using World Editor Tools, make sure that you have enabled Current Tool (2)' window in Windows tab (1). Once you have that completed, you can pick one of the Tools either from the tool bar (3) or from Tools category'. After that, you can go to the Current Tool tab (4) and change parameters of currently selected tool (5).
World Editor Tools are often used to assist with prefab management (like spawning assets) but they can be also used for autotests due to ability to switch to game mode.
It is also possible to drag & drop resources (like prefabs) into current tool properties, which is especially useful when you want to change multiple hand picked prefabs.
Preparing Data Structure
All your new plugins and tools should be located in Scripts/WorkbenchGame folder. It is possible to have them in some sub folder to keep structure bit more clear and in this tutorial SamplePlugins subfolder will collect all new scripts.
In SamplePlugin folder, we will create in total 5 new scripts:
- SampleResourceManagerPlugin.c - containing Resource Manager plugin code
- SampleScriptEditorPlugin.c - containing Script Editor plugin code
- SampleStringEditorPlugin.c - containing String Editor plugin code
- SampleWorldEditorPlugin.c - containing World Editor plugin code
- SampleWorldEditor.c - containing World Editor Tool code
Assuming that you have already created folders in way described above (either through system file explorer or through Workbench context menu available in Resource Browser), you can start creating empty script file by clicking on Resource Browse field (1) with which will invoke context menu. From there, you can select option to create a new empty script file with name of your choice. Alternatively, you can click on Create button (2) which will show you same context menu as previous method.
Creating script file | Resulting file structure |
Resource Manager Plugin
Basic structure
At minimum, new plugin needs to inherit from WorkbenchPlugin class. This class offers you ability to define behaviour of the plugin when it's launched (either by clicking on it or by CLI parameter) or when its settings are being changed.
There are also few more specialized variants of WorkbenchPlugin class, which exposes additional API, like:
- ResourceManagerPlugin
- WorldEditorPlugin
- LocalizationEditorPlugin
Let's start with SampleResourceManagerPlugin.c and try to create some minimum code for new Workbench plugin which is visible in Resource Manager plugins tab.
One of the requirements was already listed above but let's summarize all ingredients necessary to create a new plugin:
- New plugin class needs to inherit from WorkbenchPlugin or its derivatives
- Needs WorkbenchPluginAttribute correctly defined
- Needs some code in Run() method
The above code should result in a new entry in the Resource Manager plugins tab.
Now it is time to test the plugin in action! Clicking on Sample Resource Manager Plugin in the Plugins tab should result in "I'm here!" being printed in the Log Console.
Workbench Attribute
WorkbenchPluginAttribute defines how & where the plugin is going to be visible. We already have display name defined via name attribute & wbModules parameter to show this plugin only in Resource Manager. There are few more attributes which are quite handy when developing plugins.
Attributes
Parameter Name | Description |
---|---|
name |
Name of the plugin/tool |
description |
Description of tool visible in Current Tool panel (only relevant to World Editor Tools) |
shortcut |
Keyboard shortcut in text format - "Ctrl+G" means that plugin will be activated after pressing Ctrl + G on the keyboard. |
icon |
Plugin custom PNG icon - it's recommended to use awesomeFontCode instead! |
wbModules |
List of strings representing Workbench modules where this tool should be avalaible (e.g. {"ResourceManager", "ScriptEditor"}). Leave null or empty array for any module |
category |
Category of the plugin ( see #4 ) - (not relevant to World Editor Tools) |
awesomeFontCode |
Hexadecimal code for Awesome icon.
|
Adding category parameter
Adding a new category is fairly simple as typing category: "Sample Plugins" into WorkbenchPluginAttribute is enough to add your plugin to "Sample Plugins" sub menu in the Plugins tab. Multiple plugins can be collected in one category if they all use same "category" parameter
Adding custom icon
First of all, it's recommended to use awesomeFontCode instead of icon parameter and that's why this paragraph only focus on usage of awesome font.
On https://fontawesome.com/cheatsheet webpage you can try to find suitable icon for you. Let's say you are interested in copy icon. On the right you can see code for that icon - in this case it is F0C5
To use that icon in Workbench, add awesomeFontCode parameter to WorkbenchPluginAttribute with following data - 0xF0C5. 0x is a prefix required by the Workbench.
Custom icon
As result, you should get following thing in Workbench
- Full WorkbenchPluginAttribute code
Expanding plugin functionality
It's time to expand plugin functionality!
In this chapter the Resource Manager plugin will be expanded with following options:
- Getting array of currently selected files in Resource Browser
- Printing array of selected files to Console Log
- Copying content of that array to the clipboard
Settings
If the Configure() method is not empty, plugins settings can be accessed by selecting appropriate entry in Plugins → Settings tab (see #2).
Usually, you are going to use following code to invoke UI window to change plugin settings:
ScriptDialog has 3 parameters which lets you change:
- Title (1) - Title of the UI
- Text (2) - Text that is inside of UI dialog - it's useful to fill there i.e. usage instruction or general description of the plugin
- Data (3) - Data (parameters) that are passed to dialog. All members of the method with [Attribute] are exposed to this script dialog if "this" is used as last parameter.
Furthermore, dialog can be expanded with additional buttons (4), which can execute any code you want. All you have to do is to add [ButtonAttribute()] above the method.
This attribute has two parameters:
- label - string which is used as a display name in UI
- focused - boolean which controls if given button is by default focused. (default: false)
The above code will show simple "OK" button which doesn't do anything.
Below is a bit more advanced example which lets import/export current settings from/to clipboard.
Below is full example which you can test yourself in Resource Manager. Try changing either Copy To Clipboard or Print To Console parameter and check how it behaves in Workbench.
Key shortcuts
Shortcuts can be easily added by changing shortcut parameter in WorkbenchPluginAttribute of plugin.
In this case, adding shortcut: "Ctrl+T" to the attribute will result in the selected keybind to be displayed next to the plugin name.
Running through CLI parameter
Beside launching plugin from the Workbench itself, it is also possible to launch selected plugins through CLI parameter on Workbench shortcut, which is really useful when creating some automation systems.
To do so, first specify in wbModule name of the module which plugin relays on (in this case its ResourceManager) and then type name of the plugin in -plugin parameter.
O:\PathToReforger\ArmaReforgerWorkbenchSteam.exe -wbmodule=ResourceManager -plugin=SampleResourceManagerPlugin
Furthermore, you can also read custom command line parameters which are passed to the Workbench via GetCmdLine method! To do so, add additional parameter in your shortcut after -plugin=SampleResourceManagerPlugin (see Startup Parameters).
O:\PathToReforger\ArmaReforgerWorkbenchSteam.exe -wbmodule=ResourceManager -plugin=SampleResourceManagerPlugin -myParameter="$ArmaReforger:Prefabs\Vehicles"
After that, you can fetch myParameter from the script via the GetCmdLine() method.
Below is bit more advanced example which you can use in SampleResourceManagerPlugin. This code will copy to clipboard total amount of prefabs in selected location. By default code is working without any extra parameters and is looking for prefabs in "$ArmaReforger:". You can change search location through myParameter - example -myParameter="$ArmaReforger:Prefabs\Vehicles"
Optionally, you can also use -autoclose=1 parameter to automatically close Workbench once search for prefabs was completed.
Running plugin on event
Some of the Workbench editors supports additional actions which are executed when some event is triggered. As per info in this paragraph, you can check workbench.c file and look for classes which inherits from WorkbenchPlugin.
In below example, we are going to use OnRegisterResource method located in ResourceManagerPlugin. This method is called every time some resource is registered in Workbench. Whenever it happens, OnRegisterResource is called and you can use two parameters that are exposed there:
- absFileName - which is absolute path + name of newly registered file
- metaFile - link to meta file which was created during that process
You can add that code to SampleResourceManagerPlugin class and try to register a new resource in Workbench. If everything is done correctly, you should see name of newly registered resource in Log Console.
Calling Run command & external executables
Workbench provides API for running Run command & executing external executables. This achieved by two Workbench methods
Method | Description | Parameters | Return |
---|---|---|---|
int RunCmd(string command, bool wait = false); | Run command - https://en.wikipedia.org/wiki/Run_command | string command - command to run
bool wait - tells whether Workbench should wait till command is completed |
If wait is used, exit code represented as integer is returned. Otherwise 0 is returned |
ProcessHandle RunProcess(string command); | Executes selected proccess | string command - process to run | Returns handle to process which can be used to i.e. check if application was launched or to kill it later |
RunCmd allows to execute any Run command available on operating system.
In below example, a new button Ping is added to the plugin settings, which executes RunCmd & pings bohemia.net page. Once pinging is completed, Cmd.exe window will be closed.
RunProcess can be used to any executable on PC. This method returns also handle to the process so you can check whether process was executed successfully or terminate it once some condition is reached.
In this example, Windows notepad is launched after pressing Notepad button in UI. If process was launched sucesfully, notepad will be closed after two seconds.
Below is example code for SampleResourceManagerPluginSettings plugin which inherits from SampleResourceManagerPlugin. Import & Export buttons were removed and instead of them, there is Ping & Notepad button.
Script Editor Plugin
This simple plugin is going to print name of currently selected script & currently selected line in Script Editor. In principle, most of the plugin functionality was already above so this plugin is mainly to showcase possibilities lying in the API that various editors have.
Plugin can be activated either by selecting it in Plugins → Sample Plugins → Sample Script Editor Plugin or through the Ctrl + T shortcut.
String Editor plugin
This String Editor example plugin prints to the Log Console currently opened file & selected rows in this editor. Additionally, the name of the currently selected file is also copied to the user clipboard. This example plugin has no options available.
Creating World Editor Extensions
Compared to all other editors, World Editor is exposing to user much more functions than any other Workbench module. Beside World Editor API in workbench.c file, there is another in worldEditor.c file inside of WorldEditorAPI.
Among things that are possible to do in World Editor:
- Terrain manipulation
- Game mode creation assistance
- Loading scenarios and performing autotests
- Making edits to prefabs or configs
World Editor Plugin
This simple plugin is showing amount of currently selected entities in World Editor. You can invoke it by pressing Ctrl + T or by selecting it from the Plugins tab.
World Editor Tool
Setting up new Tool
As indicated before, World Editor Tools has quite impressive API which can be used in many different ways. There are few subtle differences between World Editor Tools and plugins which are worth to note like:
- Usage of WorkbenchToolAttribute (which shares available parameters with plugin - see Workbench Attribute) to expose it to World Editor
- Inheritance from WorldEditorTool class, which has different pool of methods available compared to plugins
- They cannot be launched via CLI parameter
- They can use description parameter (2)
- They are not grouped in categories like plugins, therefore category parameter is not relevant for them
Beside that, they can have name (1), parameters (3) and buttons (4) as plugin.
Below is the minimal code required to create a new World Editor Tool.
Using World Editor API
When performing any operations to entities, you need to call BeginEntityAction, which marks start of logical edit actions. Use m_API.EndEntityAction(); to mark end of edit actions. All transformations between BeginEntityAction & EndEntityAction are used by World Editor history stack - such actions can be reverted by user either via Undo last action button or shortcut (Ctrl + Z).
In below example code is creating a new entity and applies random scale to it.
Example World Editor Tool code
Below is full World Editor Tool example which utilizes some of the World Editor API. Tool will try to create a random prefab at cursor position from pool of Prefab Variants provided by user (tip: you can drag and drop multiple prefabs there!) and then randomize scale of that new entity.
Entity creation happens on left mouse button press and after that, tool will try to rotate that new entity in direction where mouse button was located when button was released.
All entities created by that tool can be deleted by pressing Escape key or by clicking on Delete all button in Current Tool tab. Additionally you can also use Randomize scale button to randomize scale of all entities created with this tool.