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,然后往里面填一些控件:- class SampleProject_Editor_Plugin final : public QObject, public ::UnigineEditor::Plugin
- {
- Q_OBJECT
- Q_DISABLE_COPY(SampleProject_Editor_Plugin)
- Q_PLUGIN_METADATA(IID UNIGINE_EDITOR_PLUGIN_IID FILE "SampleProject_Editor_Plugin.json")
- Q_INTERFACES(UnigineEditor::Plugin)
- public:
- SampleProject_Editor_Plugin() = default;
- virtual bool init() override;
- virtual void shutdown() override;
- void ShowMainWindow();
- void OnMainButtonClicked();
- private:
- QAction *menuAction{};
- QMainWindow *mainWindow{};
- };
复制代码- bool SampleProject_Editor_Plugin::init()
- {
- auto menu = UnigineEditor::WindowManager::findMenu(UnigineEditor::Constants::MM_TOOLS);
- menu->addSeparator();
- menuAction = menu->addAction("Plugin - SampleProjectEditor", this, &SampleProject_Editor_Plugin::ShowMainWindow);
- mainWindow = new QMainWindow();
- mainWindow->setWindowTitle("Plugin - SampleProject_Editor");
- mainWindow->setObjectName("Plugin_SampleProjectEditor");
- mainWindow->resize(200, 300);
- auto centralWidget = new QWidget(mainWindow);
- mainWindow->setCentralWidget(centralWidget);
- auto layoutWidget = new QWidget(centralWidget);
- layoutWidget->setFixedWidth(200);
- auto vLayout = new QVBoxLayout(layoutWidget);
- vLayout->setSpacing(5);
- vLayout->setContentsMargins(5, 5, 5, 5);
- auto checkBox = new QCheckBox(layoutWidget);
- checkBox->setText("CheckBox");
- vLayout->addWidget(checkBox);
- auto label = new QLabel(layoutWidget);
- label->setText("Some input box");
- vLayout->addWidget(label);
- auto textBox = new QLineEdit(layoutWidget);
- textBox->setPlaceholderText("waiting input...");
- vLayout->addWidget(textBox);
- auto button = new QPushButton(layoutWidget);
- button->setText("This Button");
- vLayout->addWidget(button);
- connect(button, &QPushButton::clicked, this, &SampleProject_Editor_Plugin::OnMainButtonClicked);
- auto radioButton1 = new QRadioButton(layoutWidget);
- radioButton1->setText("radioButton1");
- radioButton1->setChecked(true);
- vLayout->addWidget(radioButton1);
- auto radioButton2 = new QRadioButton(layoutWidget);
- radioButton2->setText("radioButton2");
- vLayout->addWidget(radioButton2);
- return true;
- }
- void SampleProject_Editor_Plugin::shutdown()
- {
- disconnect(UnigineEditor::WindowManager::instance(), nullptr, this, nullptr);
- if (menuAction != nullptr) {
- auto menu = UnigineEditor::WindowManager::findMenu(UnigineEditor::Constants::MM_TOOLS);
- menu->removeAction(menuAction);
- menuAction = nullptr;
- }
- if (mainWindow != nullptr) {
- delete mainWindow;
- mainWindow = nullptr;
- }
- }
- void SampleProject_Editor_Plugin::ShowMainWindow()
- {
- if (mainWindow != nullptr) {
- mainWindow->show();
- }
- }
- void SampleProject_Editor_Plugin::OnMainButtonClicked()
- {
- QMessageBox::information(mainWindow, "Plugin", "Some message");
- }
复制代码 没什么特别的,就是普通的QMainWindow然后里面一个QVBoxLayout,再摆了几个纯演示的控件。一般这类代码都会由QtCreator生成,不过需求没那么复杂的话,手搓问题也不大。
编译,运行,然后点击编辑器的Tools -> Plugin - SampleProjectEditor,就能看见下面这样的窗口:
到这一步,熟悉Qt的就已经懂了。QMainWindow都有了,那接下来想干啥还不是随自己的意了么
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |