189 lines
5.9 KiB
C++
189 lines
5.9 KiB
C++
#pragma once
|
|
|
|
#include <XCEngine/UI/DrawData.h>
|
|
|
|
#include <imgui.h>
|
|
|
|
#include <algorithm>
|
|
#include <cstddef>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace XCEngine {
|
|
namespace Editor {
|
|
namespace XCUIBackend {
|
|
|
|
class ImGuiTransitionBackend {
|
|
public:
|
|
void BeginFrame() {
|
|
m_lastFlushedDrawListCount = 0;
|
|
m_lastFlushedCommandCount = 0;
|
|
m_pendingCommandCount = 0;
|
|
m_pendingDrawLists.clear();
|
|
}
|
|
|
|
void Submit(const ::XCEngine::UI::UIDrawList& drawList) {
|
|
m_pendingCommandCount += drawList.GetCommandCount();
|
|
m_pendingDrawLists.push_back(drawList);
|
|
}
|
|
|
|
void Submit(::XCEngine::UI::UIDrawList&& drawList) {
|
|
m_pendingCommandCount += drawList.GetCommandCount();
|
|
m_pendingDrawLists.push_back(std::move(drawList));
|
|
}
|
|
|
|
void Submit(const ::XCEngine::UI::UIDrawData& drawData) {
|
|
for (const ::XCEngine::UI::UIDrawList& drawList : drawData.GetDrawLists()) {
|
|
Submit(drawList);
|
|
}
|
|
}
|
|
|
|
bool HasPendingDrawData() const {
|
|
return !m_pendingDrawLists.empty();
|
|
}
|
|
|
|
std::size_t GetPendingDrawListCount() const {
|
|
return m_pendingDrawLists.size();
|
|
}
|
|
|
|
std::size_t GetPendingCommandCount() const {
|
|
return m_pendingCommandCount;
|
|
}
|
|
|
|
std::size_t GetLastFlushedDrawListCount() const {
|
|
return m_lastFlushedDrawListCount;
|
|
}
|
|
|
|
std::size_t GetLastFlushedCommandCount() const {
|
|
return m_lastFlushedCommandCount;
|
|
}
|
|
|
|
bool EndFrame(ImDrawList* targetDrawList = nullptr) {
|
|
ImDrawList* drawList = targetDrawList != nullptr ? targetDrawList : ImGui::GetWindowDrawList();
|
|
if (drawList == nullptr) {
|
|
ClearPendingState();
|
|
return false;
|
|
}
|
|
|
|
std::size_t clipDepth = 0;
|
|
for (const ::XCEngine::UI::UIDrawList& pendingDrawList : m_pendingDrawLists) {
|
|
for (const ::XCEngine::UI::UIDrawCommand& command : pendingDrawList.GetCommands()) {
|
|
RenderCommand(*drawList, command, clipDepth);
|
|
}
|
|
}
|
|
|
|
while (clipDepth > 0) {
|
|
drawList->PopClipRect();
|
|
--clipDepth;
|
|
}
|
|
|
|
m_lastFlushedDrawListCount = m_pendingDrawLists.size();
|
|
m_lastFlushedCommandCount = m_pendingCommandCount;
|
|
ClearPendingState();
|
|
return true;
|
|
}
|
|
|
|
private:
|
|
static ImVec2 ToImVec2(const ::XCEngine::UI::UIPoint& point) {
|
|
return ImVec2(point.x, point.y);
|
|
}
|
|
|
|
static ImVec2 ToImVec2Min(const ::XCEngine::UI::UIRect& rect) {
|
|
return ImVec2(rect.x, rect.y);
|
|
}
|
|
|
|
static ImVec2 ToImVec2Max(const ::XCEngine::UI::UIRect& rect) {
|
|
return ImVec2(rect.x + rect.width, rect.y + rect.height);
|
|
}
|
|
|
|
static ImTextureID ToImTextureId(const ::XCEngine::UI::UITextureHandle& texture) {
|
|
return static_cast<ImTextureID>(texture.nativeHandle);
|
|
}
|
|
|
|
static ImU32 ToImU32(const ::XCEngine::UI::UIColor& color) {
|
|
const float r = (std::max)(0.0f, (std::min)(1.0f, color.r));
|
|
const float g = (std::max)(0.0f, (std::min)(1.0f, color.g));
|
|
const float b = (std::max)(0.0f, (std::min)(1.0f, color.b));
|
|
const float a = (std::max)(0.0f, (std::min)(1.0f, color.a));
|
|
return IM_COL32(
|
|
static_cast<int>(r * 255.0f),
|
|
static_cast<int>(g * 255.0f),
|
|
static_cast<int>(b * 255.0f),
|
|
static_cast<int>(a * 255.0f));
|
|
}
|
|
|
|
static void RenderCommand(
|
|
ImDrawList& drawList,
|
|
const ::XCEngine::UI::UIDrawCommand& command,
|
|
std::size_t& clipDepth) {
|
|
switch (command.type) {
|
|
case ::XCEngine::UI::UIDrawCommandType::FilledRect:
|
|
drawList.AddRectFilled(
|
|
ToImVec2Min(command.rect),
|
|
ToImVec2Max(command.rect),
|
|
ToImU32(command.color),
|
|
command.rounding);
|
|
break;
|
|
case ::XCEngine::UI::UIDrawCommandType::RectOutline:
|
|
drawList.AddRect(
|
|
ToImVec2Min(command.rect),
|
|
ToImVec2Max(command.rect),
|
|
ToImU32(command.color),
|
|
command.rounding,
|
|
0,
|
|
command.thickness > 0.0f ? command.thickness : 1.0f);
|
|
break;
|
|
case ::XCEngine::UI::UIDrawCommandType::Text:
|
|
if (!command.text.empty()) {
|
|
drawList.AddText(
|
|
nullptr,
|
|
command.fontSize > 0.0f ? command.fontSize : ImGui::GetFontSize(),
|
|
ToImVec2(command.position),
|
|
ToImU32(command.color),
|
|
command.text.c_str());
|
|
}
|
|
break;
|
|
case ::XCEngine::UI::UIDrawCommandType::Image:
|
|
if (command.texture.IsValid()) {
|
|
drawList.AddImage(
|
|
ToImTextureId(command.texture),
|
|
ToImVec2Min(command.rect),
|
|
ToImVec2Max(command.rect),
|
|
ImVec2(0.0f, 0.0f),
|
|
ImVec2(1.0f, 1.0f),
|
|
ToImU32(command.color));
|
|
}
|
|
break;
|
|
case ::XCEngine::UI::UIDrawCommandType::PushClipRect:
|
|
drawList.PushClipRect(
|
|
ToImVec2Min(command.rect),
|
|
ToImVec2Max(command.rect),
|
|
command.intersectWithCurrentClip);
|
|
++clipDepth;
|
|
break;
|
|
case ::XCEngine::UI::UIDrawCommandType::PopClipRect:
|
|
if (clipDepth > 0) {
|
|
drawList.PopClipRect();
|
|
--clipDepth;
|
|
}
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void ClearPendingState() {
|
|
m_pendingCommandCount = 0;
|
|
m_pendingDrawLists.clear();
|
|
}
|
|
|
|
std::vector<::XCEngine::UI::UIDrawList> m_pendingDrawLists;
|
|
std::size_t m_pendingCommandCount = 0;
|
|
std::size_t m_lastFlushedDrawListCount = 0;
|
|
std::size_t m_lastFlushedCommandCount = 0;
|
|
};
|
|
|
|
} // namespace XCUIBackend
|
|
} // namespace Editor
|
|
} // namespace XCEngine
|