Files
XCEngine/editor/src/UI/VectorControls.h

158 lines
4.6 KiB
C
Raw Normal View History

#pragma once
2026-03-26 21:18:33 +08:00
#include "Core.h"
#include <imgui.h>
#include <XCEngine/Core/Math/Vector3.h>
#include <XCEngine/Core/Math/Vector2.h>
2026-03-26 21:18:33 +08:00
#include <string>
namespace XCEngine {
namespace Editor {
namespace UI {
2026-03-26 21:18:33 +08:00
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;
2026-03-26 21:18:33 +08:00
bool anyItemActive = false;
ImGui::PushStyleVar(
ImGuiStyleVar_ItemSpacing,
useResetButtons ? VectorAxisControlSpacing() : VectorAxisInputSpacing());
const float availableWidth = ImGui::GetContentRegionAvail().x;
const float spacing = ImGui::GetStyle().ItemSpacing.x;
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;
}
const ImVec4 buttonColor = VectorAxisButtonColor();
const ImVec4 buttonHoverColor = VectorAxisButtonHoveredColor();
for (int i = 0; i < axisCount; ++i) {
ImGui::PushStyleColor(ImGuiCol_Button, buttonColor);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, buttonHoverColor);
ImGui::PushStyleColor(ImGuiCol_ButtonActive, buttonColor);
if (ImGui::Button(axes[i].label, buttonSize)) {
*axes[i].value = resetValue;
changed = true;
}
ImGui::PopStyleColor(3);
ImGui::SameLine();
ImGui::SetNextItemWidth(itemWidth);
2026-03-26 21:18:33 +08:00
if (ImGui::DragFloat((std::string("##") + axes[i].label).c_str(), axes[i].value, dragSpeed, 0.0f, 0.0f, "%.2f")) {
changed = true;
}
2026-03-26 21:18:33 +08:00
anyItemActive = anyItemActive || ImGui::IsItemActive();
if (i + 1 < axisCount) {
ImGui::SameLine();
}
2026-03-26 21:18:33 +08:00
}
} 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();
2026-03-26 21:18:33 +08:00
ImGui::SetNextItemWidth(itemWidth);
if (ImGui::DragFloat((std::string("##") + axes[i].label).c_str(), axes[i].value, dragSpeed, 0.0f, 0.0f, "%.2f")) {
changed = true;
}
2026-03-26 21:18:33 +08:00
anyItemActive = anyItemActive || ImGui::IsItemActive();
if (i + 1 < axisCount) {
ImGui::SameLine();
}
}
}
2026-03-26 21:18:33 +08:00
ImGui::PopStyleVar();
2026-03-26 21:18:33 +08:00
if (isActive) {
*isActive = anyItemActive;
}
return changed;
}
2026-03-26 21:18:33 +08:00
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,
2026-03-26 21:18:33 +08:00
float columnWidth = DefaultControlLabelWidth(),
float dragSpeed = 0.1f
) {
2026-03-26 21:18:33 +08:00
const AxisFloatControlSpec axes[] = {
{ "X", &values.x },
{ "Y", &values.y }
};
return DrawControlRow(label, columnWidth, [&]() {
return DrawAxisFloatControls(axes, 2, dragSpeed, true, resetValue);
});
}
}
}
}