Refactor editor UI architecture
This commit is contained in:
@@ -1,148 +1,155 @@
|
||||
#pragma once
|
||||
|
||||
#include "Core.h"
|
||||
#include <imgui.h>
|
||||
#include <XCEngine/Core/Math/Vector3.h>
|
||||
#include <XCEngine/Core/Math/Vector2.h>
|
||||
#include <string>
|
||||
|
||||
namespace XCEngine {
|
||||
namespace Editor {
|
||||
namespace UI {
|
||||
|
||||
inline bool DrawVec3(
|
||||
const char* label,
|
||||
::XCEngine::Math::Vector3& values,
|
||||
float resetValue = 0.0f,
|
||||
float columnWidth = 100.0f,
|
||||
float dragSpeed = 0.1f
|
||||
struct AxisFloatControlSpec {
|
||||
const char* label = nullptr;
|
||||
float* value = nullptr;
|
||||
};
|
||||
|
||||
inline bool DrawAxisFloatControls(
|
||||
const AxisFloatControlSpec* axes,
|
||||
int axisCount,
|
||||
float dragSpeed,
|
||||
bool useResetButtons,
|
||||
float resetValue,
|
||||
bool* isActive = nullptr
|
||||
) {
|
||||
bool changed = false;
|
||||
ImGui::PushID(label);
|
||||
bool anyItemActive = false;
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{0, 1});
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{4, 1});
|
||||
ImGui::PushStyleVar(
|
||||
ImGuiStyleVar_ItemSpacing,
|
||||
useResetButtons ? VectorAxisControlSpacing() : VectorAxisInputSpacing());
|
||||
|
||||
if (ImGui::BeginTable("##Vec3Table", 2, ImGuiTableFlags_NoSavedSettings)) {
|
||||
ImGui::TableSetupColumn("##label", ImGuiTableColumnFlags_WidthFixed, columnWidth);
|
||||
ImGui::TableSetupColumn("##controls", ImGuiTableColumnFlags_WidthStretch);
|
||||
const float availableWidth = ImGui::GetContentRegionAvail().x;
|
||||
const float spacing = ImGui::GetStyle().ItemSpacing.x;
|
||||
|
||||
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetFontSize() + 2.0f);
|
||||
if (useResetButtons) {
|
||||
const float lineHeight = ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f;
|
||||
const ImVec2 buttonSize(lineHeight + VectorAxisResetButtonExtraWidth(), lineHeight);
|
||||
float itemWidth = (availableWidth - buttonSize.x * static_cast<float>(axisCount)) / static_cast<float>(axisCount);
|
||||
if (itemWidth < 0.0f) {
|
||||
itemWidth = 0.0f;
|
||||
}
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text(label);
|
||||
const ImVec4 buttonColor = VectorAxisButtonColor();
|
||||
const ImVec4 buttonHoverColor = VectorAxisButtonHoveredColor();
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
for (int i = 0; i < axisCount; ++i) {
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoverColor);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, buttonColor);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{0, 0});
|
||||
|
||||
float lineHeight = ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f;
|
||||
ImVec2 buttonSize = {lineHeight + 3.0f, lineHeight};
|
||||
float itemWidth = (ImGui::GetContentRegionAvail().x - buttonSize.x * 3.0f) / 3.0f;
|
||||
|
||||
auto drawAxisControl = [&](const char* axisLabel, float& value, ImVec4 color, ImVec4 colorHovered) {
|
||||
bool axisChanged = false;
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colorHovered);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, color);
|
||||
|
||||
if (ImGui::Button(axisLabel, buttonSize)) {
|
||||
value = resetValue;
|
||||
axisChanged = true;
|
||||
if (ImGui::Button(axes[i].label, buttonSize)) {
|
||||
*axes[i].value = resetValue;
|
||||
changed = true;
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(itemWidth);
|
||||
|
||||
if (ImGui::DragFloat((std::string("##") + axisLabel).c_str(), &value, dragSpeed, 0.0f, 0.0f, "%.2f")) {
|
||||
axisChanged = true;
|
||||
if (ImGui::DragFloat((std::string("##") + axes[i].label).c_str(), axes[i].value, dragSpeed, 0.0f, 0.0f, "%.2f")) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
anyItemActive = anyItemActive || ImGui::IsItemActive();
|
||||
if (i + 1 < axisCount) {
|
||||
ImGui::SameLine();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const float axisLabelWidth = ImGui::CalcTextSize("Z").x;
|
||||
float itemWidth = (availableWidth - axisLabelWidth * static_cast<float>(axisCount) - spacing * static_cast<float>(axisCount * 2 - 1)) / static_cast<float>(axisCount);
|
||||
if (itemWidth < 0.0f) {
|
||||
itemWidth = 0.0f;
|
||||
}
|
||||
|
||||
for (int i = 0; i < axisCount; ++i) {
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::TextDisabled("%s", axes[i].label);
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(itemWidth);
|
||||
if (ImGui::DragFloat((std::string("##") + axes[i].label).c_str(), axes[i].value, dragSpeed, 0.0f, 0.0f, "%.2f")) {
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return axisChanged;
|
||||
};
|
||||
|
||||
changed |= drawAxisControl("X", values.x, ImVec4{0.8f, 0.1f, 0.15f, 1.0f}, ImVec4{0.9f, 0.2f, 0.2f, 1.0f});
|
||||
changed |= drawAxisControl("Y", values.y, ImVec4{0.2f, 0.7f, 0.2f, 1.0f}, ImVec4{0.3f, 0.8f, 0.3f, 1.0f});
|
||||
changed |= drawAxisControl("Z", values.z, ImVec4{0.1f, 0.25f, 0.8f, 1.0f}, ImVec4{0.2f, 0.35f, 0.9f, 1.0f});
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::EndTable();
|
||||
anyItemActive = anyItemActive || ImGui::IsItemActive();
|
||||
if (i + 1 < axisCount) {
|
||||
ImGui::SameLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::PopID();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
if (isActive) {
|
||||
*isActive = anyItemActive;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
inline bool DrawVec3Input(
|
||||
const char* label,
|
||||
::XCEngine::Math::Vector3& values,
|
||||
float columnWidth = DefaultControlLabelWidth(),
|
||||
float dragSpeed = 0.1f,
|
||||
bool* isActive = nullptr
|
||||
) {
|
||||
const AxisFloatControlSpec axes[] = {
|
||||
{ "X", &values.x },
|
||||
{ "Y", &values.y },
|
||||
{ "Z", &values.z }
|
||||
};
|
||||
|
||||
return DrawControlRow(label, columnWidth, [&]() {
|
||||
return DrawAxisFloatControls(axes, 3, dragSpeed, false, 0.0f, isActive);
|
||||
});
|
||||
}
|
||||
|
||||
inline bool DrawVec3(
|
||||
const char* label,
|
||||
::XCEngine::Math::Vector3& values,
|
||||
float resetValue = 0.0f,
|
||||
float columnWidth = DefaultControlLabelWidth(),
|
||||
float dragSpeed = 0.1f,
|
||||
bool* isActive = nullptr
|
||||
) {
|
||||
const AxisFloatControlSpec axes[] = {
|
||||
{ "X", &values.x },
|
||||
{ "Y", &values.y },
|
||||
{ "Z", &values.z }
|
||||
};
|
||||
|
||||
return DrawControlRow(label, columnWidth, [&]() {
|
||||
return DrawAxisFloatControls(axes, 3, dragSpeed, true, resetValue, isActive);
|
||||
});
|
||||
}
|
||||
|
||||
inline bool DrawVec2(
|
||||
const char* label,
|
||||
::XCEngine::Math::Vector2& values,
|
||||
float resetValue = 0.0f,
|
||||
float columnWidth = 100.0f,
|
||||
float columnWidth = DefaultControlLabelWidth(),
|
||||
float dragSpeed = 0.1f
|
||||
) {
|
||||
bool changed = false;
|
||||
ImGui::PushID(label);
|
||||
const AxisFloatControlSpec axes[] = {
|
||||
{ "X", &values.x },
|
||||
{ "Y", &values.y }
|
||||
};
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, ImVec2{0, 1});
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2{4, 1});
|
||||
|
||||
if (ImGui::BeginTable("##Vec2Table", 2, ImGuiTableFlags_NoSavedSettings)) {
|
||||
ImGui::TableSetupColumn("##label", ImGuiTableColumnFlags_WidthFixed, columnWidth);
|
||||
ImGui::TableSetupColumn("##controls", ImGuiTableColumnFlags_WidthStretch);
|
||||
|
||||
ImGui::TableNextRow(ImGuiTableRowFlags_None, ImGui::GetFontSize() + 2.0f);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Text(label);
|
||||
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{0, 0});
|
||||
|
||||
float lineHeight = ImGui::GetFontSize() + ImGui::GetStyle().FramePadding.y * 2.0f;
|
||||
ImVec2 buttonSize = {lineHeight + 3.0f, lineHeight};
|
||||
float itemWidth = (ImGui::GetContentRegionAvail().x - buttonSize.x * 2.0f) / 2.0f;
|
||||
|
||||
auto drawAxisControl = [&](const char* axisLabel, float& value, ImVec4 color, ImVec4 colorHovered) {
|
||||
bool axisChanged = false;
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colorHovered);
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, color);
|
||||
|
||||
if (ImGui::Button(axisLabel, buttonSize)) {
|
||||
value = resetValue;
|
||||
axisChanged = true;
|
||||
}
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(itemWidth);
|
||||
|
||||
if (ImGui::DragFloat((std::string("##") + axisLabel).c_str(), &value, dragSpeed, 0.0f, 0.0f, "%.2f")) {
|
||||
axisChanged = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
||||
return axisChanged;
|
||||
};
|
||||
|
||||
changed |= drawAxisControl("X", values.x, ImVec4{0.8f, 0.1f, 0.15f, 1.0f}, ImVec4{0.9f, 0.2f, 0.2f, 1.0f});
|
||||
changed |= drawAxisControl("Y", values.y, ImVec4{0.2f, 0.7f, 0.2f, 1.0f}, ImVec4{0.3f, 0.8f, 0.3f, 1.0f});
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::EndTable();
|
||||
}
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::PopID();
|
||||
|
||||
return changed;
|
||||
return DrawControlRow(label, columnWidth, [&]() {
|
||||
return DrawAxisFloatControls(axes, 2, dragSpeed, true, resetValue);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user