This page has been translated automatically.
Видеоуроки
Interface
Essentials
Advanced
Подсказки и советы
Основы
Программирование на C#
Рендеринг
Принципы работы
Свойства (properties)
Компонентная Система
Рендер
Физика
Редактор UnigineEditor
Обзор интерфейса
Работа с ассетами
Настройки и предпочтения
Работа с проектами
Настройка параметров ноды
Setting Up Materials
Настройка свойств
Освещение
Landscape Tool
Sandworm
Использование инструментов редактора для конкретных задач
Extending Editor Functionality
Встроенные объекты
Ноды (Nodes)
Объекты (Objects)
Эффекты
Декали
Источники света
Geodetics
World Nodes
Звуковые объекты
Объекты поиска пути
Players
Программирование
Основы
Настройка среды разработки
Примеры использования
C++
C#
UnigineScript
Унифицированный язык шейдеров UUSL
Плагины
File Formats
Rebuilding the Engine Tools
GUI
Двойная точность координат
API
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Objects-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
IG Plugin
CIGIConnector Plugin
Rendering-Related Classes
Работа с контентом
Оптимизация контента
Материалы
Material Nodes Library
Miscellaneous
Input
Math
Matrix
Textures
Art Samples
Tutorials
Внимание! Эта версия документация УСТАРЕЛА, поскольку относится к более ранней версии SDK! Пожалуйста, переключитесь на самую актуальную документацию для последней версии SDK.
Внимание! Эта версия документации описывает устаревшую версию SDK, которая больше не поддерживается! Пожалуйста, обновитесь до последней версии SDK.

Extending Editor Functionality

Warning
This feature is an experimental one and is not recommended for production use.

UNIGINE enables you to extend the core functionality of the UnigineEditor, e.g., add new menus, windows, tool bar commands, sub-modes, define how properties are displayed, and even create your custom Editor. This is made possible by the UnigineEditor's Plugin System via adding custom user plugins.

UnigineEditor is an application written entirely in C++ relying a lot on the Qt5 framework infrastructure. So, in order to extend its functionality not only C++ programming skills are required, but you should also be familiar with the Qt5 framework, CMake build system.

Notice
Qt Framework version 5.12.3 is required to develop plugins for UnigineEditor. It is not included in UNIGINE SDK, so you'll have to download and install it.

See Also#

Editor's Plugin System#

Plugins are collections of code and data that developers can easily enable or disable within the UnigineEditor on a per-project basis. Each plugin is compiled into a dynamic library that is shipped separately, it is detected and loaded at run time by the UnigineEditor.

Basically the structure of the Plugin System is as follows:

Plugin System

Plugin System

Here is a brief description of the main components:

  • QPluginLoader – is responsible for plugin loading and providing meta data.
  • Editor::PluginInfo – plugin meta data parsing and storage, interaction with plugin interface, it also contains the current plugin state and information on a possible plugin initialization error.
  • Editor::PluginManager – a manager class responsible for locating plugins, building plugin loading queue, as well as loading and removing plugins.
  • Editor::Plugin - the basic class all Editor plugins inherit from, it has the following declaration:

    Editor::Plugin Class Declaration

    Source code (C++)
    namespace Editor
    {
     
    class EDITOR_API Plugin
    {
    public:
        Plugin();
        virtual ~Plugin();
        // Plugin's life cycle.
        virtual bool init()     = 0;
        virtual void shutdown() = 0;
    };
     
    } // namespace Editor
     
    // Associates the given Identifier (a string literal) to the interface class called Editor::Plugin.
    Q_DECLARE_INTERFACE(Editor::Plugin, "com.unigine.EditorPlugin")

    It has two abstract methods defining plugin's life cycle, you should override them for your custom plugin:

    • init() - plugin initialization (returns initialization result)
    • shutdown() - plugin shutdown
    Notice
    The Q_DECLARE_INTERFACE macro adds the interface to Qt's metasystem.

Locating Plugins#

Plugins having their libraries located in the directory given below, are automatically loaded and added to the list of available UnigineEditor plugins, no specific code is required:

  • %project%/bin/editor — for Release build and any SDK build;
  • %project%/bin/editor_debug — for Debug builds on developer's PC.

To see the list of all currently loaded plugins in the UnigineEditor choose Help -> Plugins.

Plugins List

You can view any plugin's description by selecting in in the list and clicking Details.

Plugin Details

If an error has occurred when loading a plugin, a detailed message shall be displayed in the description window.

Plugin Meta Data#

Each plugin must have additional information required by the plugin manager to find your plugin and resolve its dependencies before actually loading your plugin's library file. This information is stored in a meta file in JSON format (myplugin.json file automatically generated when adding an Editor plugin template to your project) and can be obtained at run time from an instance of the Editor::PluginInfo class. This meta file may look as follows:

Source code
{
    "Name" : "MyPlugin",
    "Vendor" : "Unigine",
    "Description" : "The plugin's description text." ,
    "Version" : "@PLUGIN_VERSION@",
    "CompatVersion" : "@PLUGIN_COMPAT_VERSION@"
    "Dependencies" : [
      {
        "Name": "RequiredPlugin",
        "Type": "required",
        "Version" : "2.9.0.0"
      },
      {
        "Name": "OptionalPlugin",
        "Type": "optional",
        "Version" : "2.8.0"
      }

    ]
}

Here is a brief overview of the basic elements:

  • Name – plugin name displayed in the UnigineEditor's Plugins List, and used as reference when describing other plugins dependencies;
  • Vendor, Description – additional information (optional);
  • Version – current plugin version;
  • CompatVersion – last binary compatible plugin version, defines which version of this plugin the current version is binary backward compatible with and is used to resolve dependencies on this plugin.
  • Dependencies – list of objects describing dependencies on other plugins.
  • Name – name of the plugin, on which this plugin relies;
  • Type – dependency type, can be either required or optional;
  • Version – version with which the plugin must be compatible to fill the dependency, in the form x.y.z. Can be empty if the version does not matter.

Actually author creates a .json.in file. which is then used by CMake to generate the actual plugin .json meta data file, replacing variables like EDITOR_VERSION with their actual values.

Plugin Dependencies#

A plugin can rely on other plugins. Such dependencies are specified in the plugin meta data, to ensure that these other plugins are loaded before this one.

Dependencies are declared with the key Dependency, which contains an array of JSON objects with required keys Name and Version, and optional key Type.

The following formulas illustrate how the dependency information is matched. In the formulas the name of the required plugin (as defined in the Name of the dependency object) is denoted as DependencyName and the required version of the plugin is denoted as DependencyVersion. A plugin with given Name, Version, and CompatVersion as defined in the plugin meta data matches the dependency if the following conditions are met:

  • its Name matches DependencyName
  • CompatVersion <= DependencyVersion <= Version

For example a dependency

Source code
{
    "Name" : "SomeOtherPlugin",
    "Version" : "2.4.1"
}

would be matched by a plugin with

Source code
{
    "Name" : "SomeOtherPlugin",
    "Version" : "3.1.0",
    "CompatVersion" : "2.2.0",
    ...
}

since the name matches, and the version 2.4.1 given in the dependency tag lies between 2.2.0 and 3.1.0.

Plugin Life Cycle#

To be able to write Editor plugins, you must understand the steps that the plugin manager takes when you start or shut down UnigineEditor.

When you start UnigineEditor, the plugin manager does the following:

  • Looks in its search paths for all dynamic libraries, and reads their meta data. All libraries without meta data and the ones without the com.unigine.EditorPlugin IID are ignored. The initial state of all plugins is INVALID as this is the first point where loading a plugin can fail in the worst case of malformed meta data.
  • Creates an instance of the Editor::PluginInfo class for each plugin. Being a container for the plugin meta data, this class also tracks the current plugin state. You can get the Editor::PluginInfo instances via the Editor::PluginManager::plugins() function.
  • Sets the plugins to READ state.
  • Verifies that the dependencies of each plugin exist and are compatible.
  • Sets the plugins to RESOLVED state.
  • Sorts all plugins into a list called the "loading queue", where the dependencies of a plugin are positioned after the plugin (but not necessarily directly after it). It ensures that plugins are loaded and initialized in proper order.
  • Loads the plugins' libraries, and creates their Editor::Plugin instances in the order of the loading queue. At this point the plugin constructors are called. Plugins that other plugins depend on are created first.
  • Sets the plugins to LOADED state.
  • Calls the init() functions of all plugins in accordance with the loading queue. In the init() function, a plugin should make sure that all exported interfaces are set up and available to other plugins. As each plugin assumes that plugins it depends on have set up their exported interfaces.
    Notice
    Plugin's init() function is a good place for:
    • creating new objects
    • loading settings
    • adding new menus, and new actions to them
    • connecting to other plugin's signals.
  • Sets the plugins to RUNNING state.

On UnigineEditor shutdown the plugin manager starts its shutdown sequence:

  • Calls the shutdown() functions of all plugins in the order of the loading queue. Plugins should perform measures for speeding up the actual shutdown here, like disconnecting signals that would otherwise needlessly be called.
  • Destroys all plugins by deleting their Editor::Plugin instances in reverse order of the loading queue. At this point the plugin destructors are called. Plugins should clean up after themselves by freeing memory and other resources.

Hot Reload#

Editor plugins support hot reloading, which can be useful in cases, when you need to perform actions like:

  • Unload a plugin
  • Do something
  • Reload the plugin

You can unload and Load your plugin again when necessary via the corresponding button in the HotReload column (accessible via the Editor Plugins window: Help -> Plugins).

You can also do the same via code:

Source code (C++)
Unigine::Vector<Editor::PluginInfo *> plugin_infos = Editor::PluginManager::plugins();

// choose your `PluginInfo*`:
Editor::PluginInfo *required_plugin_info = ..;

// Unload a plugin:
bool unloaded = Editor::PluginManager::unloadPlugin(required_plugin_info);

// Do something
// ...

// Reload the plugin
bool loaded = Editor::PluginManager::loadPlugin(required_plugin_info);
Last update: 18.02.2022
Build: ()