<2021SC@SDUSC>【Overload游戏引擎】OvUI源码模块分析(四)——Modules&Panels

  • 前言
  • Modules
    • Canvas
  • Panels
    • APanel
    • APanelTransformable
    • PanelWindow
  • 总结

前言

本章我们来分析Modules和Panels。Modules中的内容是Canvas的定义和操作, Panels中的内容是 Panels的定义和操作以及和ImGui库的对接。 Panels是Canvas的一个关键组件,它们都用于UI界面的显示。

Modules

Canvas

画布表示可用于UI绘图的整个框架

/**
* @project: Overload
* @author: Overload Tech.
* @licence: MIT
*/#include "OvUI/Modules/Canvas.h"void OvUI::Modules::Canvas::Draw()
{if (!m_panels.empty()){ImGui_ImplOpenGL3_NewFrame();ImGui_ImplGlfw_NewFrame();ImGui::NewFrame();if (m_isDockspace){ImGuiViewport* viewport = ImGui::GetMainViewport();ImGui::SetNextWindowPos(viewport->Pos);ImGui::SetNextWindowSize(viewport->Size);ImGui::SetNextWindowViewport(viewport->ID);ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));ImGui::Begin("##dockspace", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking);ImGuiID dockspace_id = ImGui::GetID("MyDockspace");ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_PassthruCentralNode);ImGui::SetWindowPos({ 0.f, 0.f });ImVec2 displaySize = ImGui::GetIO().DisplaySize;ImGui::SetWindowSize({ (float)displaySize.x, (float)displaySize.y });ImGui::End();ImGui::PopStyleVar(3);}for (auto& panel : m_panels)panel.get().Draw();ImGui::Render();}
}

设置画布的窗口和风格并渲染

void OvUI::Modules::Canvas::AddPanel(Panels::APanel & p_panel)
{m_panels.push_back(std::ref(p_panel));
}

将面板添加到画布

void OvUI::Modules::Canvas::RemovePanel(Panels::APanel & p_panel)
{m_panels.erase(std::remove_if(m_panels.begin(), m_panels.end(), [&p_panel](std::reference_wrapper<Panels::APanel>& p_item){return &p_panel == &p_item.get();}));
}

从画布中删除面板

void OvUI::Modules::Canvas::RemoveAllPanels()
{m_panels.clear();
}

从画布中删除每个面板

void OvUI::Modules::Canvas::MakeDockspace(bool p_state)
{m_isDockspace = p_state;
}

使画布成为停靠空间(可停靠面板将能够将自身连接到画布)

bool OvUI::Modules::Canvas::IsDockspace() const
{return m_isDockspace;
}

绘制画布(绘制每个面板)

Panels

面板是画布的一个组件。它是UI中的一种窗口

APanel

OvUI::Panels::APanel::APanel()
{m_panelID = "##" + std::to_string(__PANEL_ID_INCREMENT++);
}

构造画板

void OvUI::Panels::APanel::Draw()
{if (enabled)_Draw_Impl();
}

绘制画板

const std::string & OvUI::Panels::APanel::GetPanelID() const
{return m_panelID;
}

返回面板标识符

APanelTransformable

在画布中本地化的面板

//APanelTransformable.h
APanelTransformable(const OvMaths::FVector2& p_defaultPosition = OvMaths::FVector2(-1.f, -1.f),const OvMaths::FVector2& p_defaultSize = OvMaths::FVector2(-1.f, -1.f),Settings::EHorizontalAlignment p_defaultHorizontalAlignment = Settings::EHorizontalAlignment::LEFT,Settings::EVerticalAlignment p_defaultVerticalAlignment = Settings::EVerticalAlignment::TOP,bool p_ignoreConfigFile = false);
//APanelTransformable.cpp
OvUI::Panels::APanelTransformable::APanelTransformable
(const OvMaths::FVector2& p_defaultPosition,const OvMaths::FVector2& p_defaultSize,Settings::EHorizontalAlignment p_defaultHorizontalAlignment,Settings::EVerticalAlignment p_defaultVerticalAlignment,bool p_ignoreConfigFile
) :m_defaultPosition(p_defaultPosition),m_defaultSize(p_defaultSize),m_defaultHorizontalAlignment(p_defaultHorizontalAlignment),m_defaultVerticalAlignment(p_defaultVerticalAlignment),m_ignoreConfigFile(p_ignoreConfigFile)
{}

创建可转换的APanel
1.默认位置
2.默认大小
3.默认水平对齐
4.垂直排列
5.配置文件

void OvUI::Panels::APanelTransformable::SetPosition(const OvMaths::FVector2& p_position)
{m_position = p_position;m_positionChanged = true;
}

定义面板的位置

void OvUI::Panels::APanelTransformable::SetSize(const OvMaths::FVector2& p_size)
{m_size = p_size;m_sizeChanged = true;
}

定义面板的大小

void OvUI::Panels::APanelTransformable::SetAlignment(Settings::EHorizontalAlignment p_horizontalAlignment, Settings::EVerticalAlignment p_verticalAligment)
{m_horizontalAlignment = p_horizontalAlignment;m_verticalAlignment = p_verticalAligment;m_alignmentChanged = true;
}

定义面板的对齐方式

void OvUI::Panels::APanelTransformable::UpdatePosition()
{if (m_defaultPosition.x != -1.f && m_defaultPosition.y != 1.f){OvMaths::FVector2 offsettedDefaultPos = m_defaultPosition + CalculatePositionAlignmentOffset(true);ImGui::SetWindowPos(Internal::Converter::ToImVec2(offsettedDefaultPos), m_ignoreConfigFile ? ImGuiCond_Once : ImGuiCond_FirstUseEver);}if (m_positionChanged || m_alignmentChanged){OvMaths::FVector2 offset = CalculatePositionAlignmentOffset(false);OvMaths::FVector2 offsettedPos(m_position.x + offset.x, m_position.y + offset.y);ImGui::SetWindowPos(Internal::Converter::ToImVec2(offsettedPos), ImGuiCond_Always);m_positionChanged = false;m_alignmentChanged = false;}
}

计算位置偏移量,更新位置,要用到OvMath中定义的二维向量

void OvUI::Panels::APanelTransformable::UpdateSize()
{/*if (m_defaultSize.x != -1.f && m_defaultSize.y != 1.f)ImGui::SetWindowSize(Internal::Converter::ToImVec2(m_defaultSize), m_ignoreConfigFile ? ImGuiCond_Once : ImGuiCond_FirstUseEver);*/if (m_sizeChanged){ImGui::SetWindowSize(Internal::Converter::ToImVec2(m_size), ImGuiCond_Always);m_sizeChanged = false;}
}

更新窗口大小

OvMaths::FVector2 OvUI::Panels::APanelTransformable::CalculatePositionAlignmentOffset(bool p_default)
{OvMaths::FVector2 result(0.0f, 0.0f);switch (p_default ? m_defaultHorizontalAlignment : m_horizontalAlignment){case OvUI::Settings::EHorizontalAlignment::CENTER:result.x -= m_size.x / 2.0f;break;case OvUI::Settings::EHorizontalAlignment::RIGHT:result.x -= m_size.x;break;}switch (p_default ? m_defaultVerticalAlignment : m_verticalAlignment){case OvUI::Settings::EVerticalAlignment::MIDDLE:result.y -= m_size.y / 2.0f;break;case OvUI::Settings::EVerticalAlignment::BOTTOM:result.y -= m_size.y;break;}return result;
}

计算位置偏移量,分别计算水平分量和垂直分量,水平分量以中间和右边界为准,垂直分量以中间和底为准。

PanelWindow

本地化面板,其功能类似于窗口,可进行移动、调整大小等操作。

//PanelWindow.h
PanelWindow(const std::string& p_name = "",bool p_opened = true,const Settings::PanelWindowSettings& p_panelSettings = Settings::PanelWindowSettings{});
//PanelWindow.cpp
OvUI::Panels::PanelWindow::PanelWindow(const std::string& p_name, bool p_opened, const Settings::PanelWindowSettings& p_floatingPanelSettings) :name(p_name),resizable(p_floatingPanelSettings.resizable),closable(p_floatingPanelSettings.closable),movable(p_floatingPanelSettings.movable),scrollable(p_floatingPanelSettings.scrollable),dockable(p_floatingPanelSettings.dockable),hideBackground(p_floatingPanelSettings.hideBackground),forceHorizontalScrollbar(p_floatingPanelSettings.forceHorizontalScrollbar),forceVerticalScrollbar(p_floatingPanelSettings.forceVerticalScrollbar),allowHorizontalScrollbar(p_floatingPanelSettings.allowHorizontalScrollbar),bringToFrontOnFocus(p_floatingPanelSettings.bringToFrontOnFocus),collapsable(p_floatingPanelSettings.collapsable),allowInputs(p_floatingPanelSettings.allowInputs),m_opened(p_opened)
{autoSize = p_floatingPanelSettings.autoSize;
}

创建面板窗口,调整参数,并打开面板窗口。

void OvUI::Panels::PanelWindow::SetOpened(bool p_value)
{if (p_value != m_opened){m_opened = p_value;if (m_opened)OpenEvent.Invoke();elseCloseEvent.Invoke();}
}

定义窗口的打开状态

bool OvUI::Panels::PanelWindow::IsAppearing() const
{if (auto window = ImGui::FindWindowByName((name + GetPanelID()).c_str()); window)return window->Appearing;elsereturn false;
}

面板显示状态,如果面板正在显示,则返回true

void OvUI::Panels::PanelWindow::_Draw_Impl()
{if (m_opened){int windowFlags = ImGuiWindowFlags_None;if (!resizable)                 windowFlags |= ImGuiWindowFlags_NoResize;if (!movable)                 windowFlags |= ImGuiWindowFlags_NoMove;if (!dockable)                  windowFlags |= ImGuiWindowFlags_NoDocking;if (hideBackground)              windowFlags |= ImGuiWindowFlags_NoBackground;if (forceHorizontalScrollbar) windowFlags |= ImGuiWindowFlags_AlwaysHorizontalScrollbar;if (forceVerticalScrollbar)      windowFlags |= ImGuiWindowFlags_AlwaysVerticalScrollbar;if (allowHorizontalScrollbar)  windowFlags |= ImGuiWindowFlags_HorizontalScrollbar;if (!bringToFrontOnFocus)      windowFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus;if (!collapsable)                windowFlags |= ImGuiWindowFlags_NoCollapse;if (!allowInputs)               windowFlags |= ImGuiWindowFlags_NoInputs;if (!scrollable)                windowFlags |= ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoScrollbar;if (!titleBar)                  windowFlags |= ImGuiWindowFlags_NoTitleBar;ImVec2 minSizeConstraint = Internal::Converter::ToImVec2(minSize);ImVec2 maxSizeConstraint = Internal::Converter::ToImVec2(maxSize);/* Cancel constraint if x or y is <= 0.f */if (minSizeConstraint.x <= 0.f || minSizeConstraint.y <= 0.f)minSizeConstraint = { 0.0f, 0.0f };if (maxSizeConstraint.x <= 0.f || maxSizeConstraint.y <= 0.f)maxSizeConstraint = { 10000.f, 10000.f };ImGui::SetNextWindowSizeConstraints(minSizeConstraint, maxSizeConstraint);if (ImGui::Begin((name + m_panelID).c_str(), closable ? &m_opened : nullptr, windowFlags)){m_hovered = ImGui::IsWindowHovered();m_focused = ImGui::IsWindowFocused();auto scrollY = ImGui::GetScrollY();m_scrolledToBottom = scrollY == ImGui::GetScrollMaxY();m_scrolledToTop = scrollY == 0.0f;if (!m_opened)CloseEvent.Invoke();Update();if (m_mustScrollToBottom){ImGui::SetScrollY(ImGui::GetScrollMaxY());m_mustScrollToBottom = false;}if (m_mustScrollToTop){ImGui::SetScrollY(0.0f);m_mustScrollToTop = false;}DrawWidgets();}ImGui::End();}
}

与ImGui库的对接,控制窗口大小,背景,滚动条的操作是否开启,以及设置了一些操作的约束条件。

总结

关于Modules和Panels的分析就介绍到这里,Panels中有许多简单的显示和操作函数,在这里就不过多介绍了。界面的难点在于需要调整的参数和函数很多,和ImGui的使用,但理解起来并不困难。

<2021SC@SDUSC>【Overload游戏引擎】OvUI源码模块分析(四)——ModulesPanels相关推荐

  1. <2021SC@SDUSC>【Overload游戏引擎】源码模块简介及项目分工

    <2021SC@SDUSC>[Overload游戏引擎]源码模块简介及项目分工 模块简介 Overload SDK Overload 应用程序 项目分工 模块简介 Overload 由12 ...

  2. <2021SC@SDUSC>【Overload游戏引擎】OvUI源码模块分析(五)——Plugins

    <2021SC@SDUSC>[Overload游戏引擎]OvUI源码模块分析(五)--Plugins 前言 DataDispatcher DDSource DDTarget IPlugin ...

  3. <2021SC@SDUSC>【Overload游戏引擎】OvUI源码模块分析(三)——Internal

    <2021SC@SDUSC>[Overload游戏引擎]OvUI源码模块分析(三)--Internal 前言 Internal 1.Converter 2.EMemoryMode 3.Wi ...

  4. <2021SC@SDUSC>【Overload游戏引擎】OvUI源码模块分析(二)——ImGui

    <2021SC@SDUSC>[Overload游戏引擎]OvUI源码模块分析(二) 前言 案例分析 程序框架 1.基本案例 2.实现定制绑定/定制引擎 渲染函数 总结 前言 本篇我们来分析 ...

  5. <2021SC@SDUSC>【Overload游戏引擎】OvUI源码模块分析(一)——Core

    <2021SC@SDUSC>[Overload游戏引擎]OvUI源码模块分析(一) 文章目录 前言 OvUI的模块结构 源码分析 1.Core模块 (1)UIManger的构造函数和析构函 ...

  6. <2021SC@SDUSC>【Overload游戏引擎】OvUI源码模块分析(六)——Widgets

    <2021SC@SDUSC>[Overload游戏引擎]OvUI源码模块分析(六)--Widgets Button Button namespace OvUI::Widgets::Butt ...

  7. 【Overload游戏引擎】源码分析之十三:OvRendering函数库(十一)

    2021SC@SDUSC 目录 1.Driver 1.1构造函数 1.2InitGlew 1.3GLDebugMessageCallback 2.Renderer 2.1Draw 2.2FetchGL ...

  8. 【Overload游戏引擎】源码分析之五:OvRendering函数库(三)

    2021SC@SDUSC 目录 IMesh.h与Mesh.h 1.CreateBuffers 2.ComputeBoundingSphere 3.其他函数 回顾一下前几篇文章,我们讲到了有关图形学三维 ...

  9. 【Overload游戏引擎】源码分析之六:OvRendering函数库(四)

    2021SC@SDUSC 目录 1.Uniform 1.1UniformType 1.2UniformInfo 2.Shader 2.1SetUniform和GetUniform 2.2GetUnif ...

最新文章

  1. .net操纵xml文件类(c#)
  2. 我崩溃了!月薪30K必须掌握的开源项目Java中SPI机制
  3. Django生命周期与中间件
  4. spark的流失计算模型_使用spark对sparkify的流失预测
  5. PHP、C#、通用的DES加密
  6. 一张图读懂哔哩哔哩2019Q1财报
  7. 学习Jsoup(三)
  8. 17. Element dir 属性
  9. C# OpenCv 证件照换底色
  10. 动手学数据分析(三)- 数据重构
  11. 页面优化之懒加载与预加载
  12. Windows 电脑如何查看已经连接的 Wi-Fi 的密码
  13. 如何用 Python 识别车牌
  14. 【rviz】出现“For frame [laser]: Fixed Frame [map] does not exist”错误
  15. KS检验样本测试集和训练集分布问题
  16. 想去微软工作吗?这些岗位年薪超过1100000元
  17. 网络舆情分析关键词怎么获取的系统平台方法
  18. 数据结构--表达式括号匹配和运算
  19. 佳能mp288打印机连供系统使用
  20. 树莓派Ubuntu 16.04 MATA系统 修改用户文件夹名后,提示configure it with blueman-service...

热门文章

  1. C# 网络斗地主源码开源
  2. Python爬虫01—请求模块
  3. 颜色传感器的工作原理
  4. 绿姿明星慈善签售会,因为爱生日更精彩
  5. java opencv实现扫描图像去底色增强文字
  6. fatal: unable to access ‘https://github.com/nhn/raphael.git/‘: OpenSSL SSL_read: Connection was rese
  7. Idea运行build和writing classes太久
  8. java 通讯机_java 上位机与单片机通过串口485通讯
  9. 【NuxtJs】支付宝PC支付跳转支付页面处理方案
  10. vue2高仿饿了么app