找回密码
 立即注册
首页 业界区 安全 Unigine使用QtWidgets制作编辑器扩展(Editor Plugin) ...

Unigine使用QtWidgets制作编辑器扩展(Editor Plugin)的简单随笔

葛雅隽 昨天 15:00
Unigine有一点比较烦,就是不支持用C#写Editor Script。由于Unigine Editor是搭建在Qt框架上的(准确点说,是Qt 5.12.3),所以要写插件也得搭建一套Qt的开发环境出来,同时插件也得用C++来写。
好在Qt本身不难,Unigine也只使用到了最基础的Qt控件。虽然是C++但Qt做了不少简化工作,因此有基本C++基础的都能玩得来。QtWidgets的设计也不复杂,C#下面玩过WinForms的很快就能上手。我原来完全不懂Qt,但看了两天文档后就能做东西了,毕竟要做的只是一些编辑器里用的小工具,而不是什么有着复杂界面的应用程序。能摆几个Button,几个CheckBox,几个输入框,很多时候就够了。
先来做准备工作

首选需要去Qt官网注册一个Qt账号,然后下载5.12.3的离线安装包,地址在这里(可能需要挂梯子):https://download.qt.io/archive/qt/5.12/5.12.3/qt-opensource-windows-x86-5.12.3.exe
接着按照Unigine的教程安装好Qt环境,并配置好“UNIGINE_QTROOT”的环境变量。
下一步为项目添加插件支持。之后会发现,项目里不仅多了刚添加的插件项目,还有几个Unigine的示例插件项目。可以将这几个项目都添加到解决方案里,作为参考例子。
注意这些新增的项目的Platform Toolset编译选项都要选择Visual Studio 2015。没有就去Visual Studio Installer里添加一下“VS 2015 C++ Build Tools”。
有一个细节,就是生成的DLL文件,除了要放到bin\plugins\[组织名称]\文件夹下以外,还必须以一个固定的文件名作为结尾,否则Unigine就不认了。规则也不复杂:
debugreleasefloat[插件名称]_editorplugin_float_x64d.dll[插件名称]_editorplugin_float_x64.dlldouble[插件名称]_editorplugin_double_x64d.dll[插件名称]_editorplugin_double_x64.dllUnigine创建好插件项目后,默认就已经将输出的文件名配置好了。如果要自己改,记得遵循这个规则。
搞成这样是因为Unigine有两种Plugin:可以在运行时加载的插件(比如bin\plugins\Unigine文件夹下的那些),以及只能在编辑器里加载的插件。另外还允许单精度项目和双精度项目共
存。
学QtWidgets可以看:Getting Started Programming with Qt Widgets。这个教程是用QtCreator演示的,Visual Studio可以安装这个插件:Qt Visual Studio Tools。把这个例子搞懂了基本也足够做编辑器Plugin的界面了。
想要进一步了解则可以看:Qt Widgets Examples。
再看看Unigine提供的示例项目

这其中比较容易上手的是AssetsPlugin和MaterialsPlugin这俩。前者是使用Unigine自己的Gui系统绘制了一堆按钮,同时演示了一下各种不同的Asset操作代码。别看AssetsPlugin.cpp好长一串,除去init和shutdown,剩下的基本上都是那一堆Button的事件处理函数。
拆解开来,总共就四步:

  • 在init()里,通过WindowManager::findMenu(Constants::MM_WINDOWS)获取编辑器的菜单栏,并向其中添加一个Action。
  • 在这个Action里,创建Gui窗口并添加事件处理。
  • 回到init(),订阅WindowManager::windowHidden信号,并将窗口删除。
  • shutdown()里,同样执行一遍删除窗口操作,并取消所有信号的订阅。
MaterialsPlugin要复杂一些:在MaterialsPlugin::init()里创建MaterialsView对象,而MaterialsView是一个QWidget,其中包含了一个QTreeView。MaterialsModel则是这个TreeView使用的数据格式。
牵扯到TreeView的代码都不简单,但可以先不管它。要注意的还是MaterialsPlugin::init()函数,和AssetsPlugin不一样,这里直接把QWidget创建了出来,然后在菜单栏的Action里使用WindowManager::show()显示。而删除的部分也是在MaterialsPlugin::shutdown()里面直接删除,没有像AssetsPlugin那边在WindowManager::windowHidden信号里做了一个延后删除的动作。
这就是在Unigine里使用QtWidgets唯一的要点了:在init()里创建。
接着搞个窗口试试

用代码手搓一个QMainWindow,然后往里面填一些控件:
  1. class SampleProject_Editor_Plugin final : public QObject, public ::UnigineEditor::Plugin
  2. {
  3.         Q_OBJECT
  4.         Q_DISABLE_COPY(SampleProject_Editor_Plugin)
  5.         Q_PLUGIN_METADATA(IID UNIGINE_EDITOR_PLUGIN_IID FILE "SampleProject_Editor_Plugin.json")
  6.         Q_INTERFACES(UnigineEditor::Plugin)
  7. public:
  8.         SampleProject_Editor_Plugin() = default;
  9.         virtual bool init() override;
  10.         virtual void shutdown() override;
  11.         void ShowMainWindow();
  12.         void OnMainButtonClicked();
  13. private:
  14.         QAction *menuAction{};
  15.         QMainWindow *mainWindow{};
  16. };
复制代码
  1. bool SampleProject_Editor_Plugin::init()
  2. {
  3.         auto menu = UnigineEditor::WindowManager::findMenu(UnigineEditor::Constants::MM_TOOLS);
  4.         menu->addSeparator();
  5.         menuAction = menu->addAction("Plugin - SampleProjectEditor", this, &SampleProject_Editor_Plugin::ShowMainWindow);
  6.         mainWindow = new QMainWindow();
  7.         mainWindow->setWindowTitle("Plugin - SampleProject_Editor");
  8.         mainWindow->setObjectName("Plugin_SampleProjectEditor");
  9.         mainWindow->resize(200, 300);
  10.         auto centralWidget = new QWidget(mainWindow);
  11.         mainWindow->setCentralWidget(centralWidget);
  12.         auto layoutWidget = new QWidget(centralWidget);
  13.         layoutWidget->setFixedWidth(200);
  14.         auto vLayout = new QVBoxLayout(layoutWidget);
  15.         vLayout->setSpacing(5);
  16.         vLayout->setContentsMargins(5, 5, 5, 5);
  17.         auto checkBox = new QCheckBox(layoutWidget);
  18.         checkBox->setText("CheckBox");
  19.         vLayout->addWidget(checkBox);
  20.         auto label = new QLabel(layoutWidget);
  21.         label->setText("Some input box");
  22.         vLayout->addWidget(label);
  23.         auto textBox = new QLineEdit(layoutWidget);
  24.         textBox->setPlaceholderText("waiting input...");
  25.         vLayout->addWidget(textBox);
  26.         auto button = new QPushButton(layoutWidget);
  27.         button->setText("This Button");
  28.         vLayout->addWidget(button);
  29.         connect(button, &QPushButton::clicked, this, &SampleProject_Editor_Plugin::OnMainButtonClicked);
  30.         auto radioButton1 = new QRadioButton(layoutWidget);
  31.         radioButton1->setText("radioButton1");
  32.         radioButton1->setChecked(true);
  33.         vLayout->addWidget(radioButton1);
  34.         auto radioButton2 = new QRadioButton(layoutWidget);
  35.         radioButton2->setText("radioButton2");
  36.         vLayout->addWidget(radioButton2);
  37.         return true;
  38. }
  39. void SampleProject_Editor_Plugin::shutdown()
  40. {
  41.         disconnect(UnigineEditor::WindowManager::instance(), nullptr, this, nullptr);
  42.         if (menuAction != nullptr) {
  43.                 auto menu = UnigineEditor::WindowManager::findMenu(UnigineEditor::Constants::MM_TOOLS);
  44.                 menu->removeAction(menuAction);
  45.                 menuAction = nullptr;
  46.         }
  47.         if (mainWindow != nullptr) {
  48.                 delete mainWindow;
  49.                 mainWindow = nullptr;
  50.         }
  51. }
  52. void SampleProject_Editor_Plugin::ShowMainWindow()
  53. {
  54.         if (mainWindow != nullptr) {
  55.                 mainWindow->show();
  56.         }
  57. }
  58. void SampleProject_Editor_Plugin::OnMainButtonClicked()
  59. {
  60.         QMessageBox::information(mainWindow, "Plugin", "Some message");
  61. }
复制代码
没什么特别的,就是普通的QMainWindow然后里面一个QVBoxLayout,再摆了几个纯演示的控件。一般这类代码都会由QtCreator生成,不过需求没那么复杂的话,手搓问题也不大。
编译,运行,然后点击编辑器的Tools -> Plugin - SampleProjectEditor,就能看见下面这样的窗口:
1.jpeg


到这一步,熟悉Qt的就已经懂了。QMainWindow都有了,那接下来想干啥还不是随自己的意了么
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册