关键节点

This commit is contained in:
2026-04-25 16:46:01 +08:00
parent 6002d86a7e
commit ef41c44464
516 changed files with 6175 additions and 12401 deletions

View File

@@ -0,0 +1,32 @@
#pragma once
#include <cstdint>
#include <string_view>
namespace XCEngine::UI::Editor::Widgets {
enum class UIEditorCollectionPrimitiveKind : std::uint8_t {
None = 0,
ScrollView,
TreeView,
TreeItem,
ListView,
ListItem,
PropertySection,
FieldRow
};
UIEditorCollectionPrimitiveKind ClassifyUIEditorCollectionPrimitive(std::string_view tagName);
bool IsUIEditorCollectionPrimitiveContainer(UIEditorCollectionPrimitiveKind kind);
bool UsesUIEditorCollectionPrimitiveColumnLayout(UIEditorCollectionPrimitiveKind kind);
bool IsUIEditorCollectionPrimitiveHoverable(UIEditorCollectionPrimitiveKind kind);
bool DoesUIEditorCollectionPrimitiveClipChildren(UIEditorCollectionPrimitiveKind kind);
float ResolveUIEditorCollectionPrimitivePadding(
UIEditorCollectionPrimitiveKind kind);
float ResolveUIEditorCollectionPrimitiveDefaultHeight(
UIEditorCollectionPrimitiveKind kind);
float ResolveUIEditorCollectionPrimitiveIndent(
UIEditorCollectionPrimitiveKind kind,
float indentLevel);
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,33 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
#include <string>
namespace XCEngine::UI::Editor::Widgets {
struct UIEditorHsvColor {
float hue = 0.0f;
float saturation = 0.0f;
float value = 0.0f;
float alpha = 1.0f;
};
float ClampUIEditorColorUnit(float value);
int ToUIEditorColorByte(float value);
UIEditorHsvColor ConvertUIEditorColorToHsv(
const ::XCEngine::UI::UIColor& color,
float fallbackHue = 0.0f);
::XCEngine::UI::UIColor ConvertUIEditorHsvToColor(const UIEditorHsvColor& hsv);
UIEditorHsvColor ResolveUIEditorDisplayHsv(
const ::XCEngine::UI::UIColor& color,
float rememberedHue,
bool hueValid);
std::string FormatUIEditorColorHex(
const ::XCEngine::UI::UIColor& color,
bool includeAlpha = true);
std::string FormatUIEditorColorChannelsText(
const ::XCEngine::UI::UIColor& color,
bool includeAlpha = true);
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,125 @@
#pragma once
#include <XCEngine/UI/DrawData.h>
namespace XCEngine::UI::Editor::Widgets {
struct UIEditorInspectorFieldStyleTokens {
::XCEngine::UI::UIColor rowHoverColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor rowActiveColor =
::XCEngine::UI::UIColor(0.17f, 0.17f, 0.17f, 1.0f);
::XCEngine::UI::UIColor labelColor =
::XCEngine::UI::UIColor(0.72f, 0.72f, 0.72f, 1.0f);
::XCEngine::UI::UIColor valueColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor readOnlyValueColor =
::XCEngine::UI::UIColor(0.60f, 0.60f, 0.60f, 1.0f);
::XCEngine::UI::UIColor controlColor =
::XCEngine::UI::UIColor(0.12f, 0.12f, 0.12f, 1.0f);
::XCEngine::UI::UIColor controlHoverColor =
::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f);
::XCEngine::UI::UIColor controlEditingColor =
::XCEngine::UI::UIColor(0.18f, 0.18f, 0.18f, 1.0f);
::XCEngine::UI::UIColor controlReadOnlyColor =
::XCEngine::UI::UIColor(0.10f, 0.10f, 0.10f, 1.0f);
::XCEngine::UI::UIColor controlBorderColor =
::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f);
::XCEngine::UI::UIColor controlFocusedBorderColor =
::XCEngine::UI::UIColor(0.19f, 0.19f, 0.19f, 1.0f);
::XCEngine::UI::UIColor prefixColor =
::XCEngine::UI::UIColor(0.13f, 0.13f, 0.13f, 1.0f);
::XCEngine::UI::UIColor prefixBorderColor =
::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f);
::XCEngine::UI::UIColor axisXColor =
::XCEngine::UI::UIColor(0.78f, 0.42f, 0.42f, 1.0f);
::XCEngine::UI::UIColor axisYColor =
::XCEngine::UI::UIColor(0.56f, 0.72f, 0.46f, 1.0f);
::XCEngine::UI::UIColor axisZColor =
::XCEngine::UI::UIColor(0.45f, 0.62f, 0.82f, 1.0f);
::XCEngine::UI::UIColor axisWColor =
::XCEngine::UI::UIColor(0.76f, 0.66f, 0.42f, 1.0f);
::XCEngine::UI::UIColor arrowColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor swatchBorderColor =
::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f);
::XCEngine::UI::UIColor swatchHoverBorderColor =
::XCEngine::UI::UIColor(0.19f, 0.19f, 0.19f, 1.0f);
::XCEngine::UI::UIColor swatchReadOnlyOverlayColor =
::XCEngine::UI::UIColor(0.08f, 0.08f, 0.08f, 0.18f);
::XCEngine::UI::UIColor popupColor =
::XCEngine::UI::UIColor(0.10f, 0.10f, 0.10f, 1.0f);
::XCEngine::UI::UIColor popupBorderColor =
::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f);
::XCEngine::UI::UIColor popupHeaderColor =
::XCEngine::UI::UIColor(0.11f, 0.11f, 0.11f, 1.0f);
::XCEngine::UI::UIColor popupTitleColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor popupTextColor =
::XCEngine::UI::UIColor(0.88f, 0.88f, 0.88f, 1.0f);
::XCEngine::UI::UIColor popupTextMutedColor =
::XCEngine::UI::UIColor(0.66f, 0.66f, 0.66f, 1.0f);
::XCEngine::UI::UIColor previewBorderColor =
::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f);
::XCEngine::UI::UIColor previewBaseColor =
::XCEngine::UI::UIColor(0.12f, 0.12f, 0.12f, 1.0f);
::XCEngine::UI::UIColor checkerLightColor =
::XCEngine::UI::UIColor(0.24f, 0.24f, 0.24f, 1.0f);
::XCEngine::UI::UIColor checkerDarkColor =
::XCEngine::UI::UIColor(0.14f, 0.14f, 0.14f, 1.0f);
::XCEngine::UI::UIColor sliderBorderColor =
::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f);
::XCEngine::UI::UIColor numericBoxColor =
::XCEngine::UI::UIColor(0.12f, 0.12f, 0.12f, 1.0f);
::XCEngine::UI::UIColor numericBoxBorderColor =
::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f);
::XCEngine::UI::UIColor numericBoxTextColor =
::XCEngine::UI::UIColor(0.92f, 0.92f, 0.92f, 1.0f);
::XCEngine::UI::UIColor closeButtonColor =
::XCEngine::UI::UIColor(0.0f, 0.0f, 0.0f, 0.0f);
::XCEngine::UI::UIColor closeButtonHoverColor =
::XCEngine::UI::UIColor(0.15f, 0.15f, 0.15f, 1.0f);
::XCEngine::UI::UIColor closeGlyphColor =
::XCEngine::UI::UIColor(0.86f, 0.86f, 0.86f, 1.0f);
::XCEngine::UI::UIColor handleFillColor =
::XCEngine::UI::UIColor(1.0f, 1.0f, 1.0f, 1.0f);
::XCEngine::UI::UIColor handleStrokeColor =
::XCEngine::UI::UIColor(0.10f, 0.10f, 0.10f, 0.5f);
float controlTrailingInset = 9.0f;
float controlMinWidth = 88.0f;
float dropdownArrowWidth = 14.0f;
float vectorComponentMinWidth = 74.0f;
float vectorPrefixWidth = 18.0f;
float vectorPrefixGap = 5.0f;
};
struct UIEditorFieldRowLayoutMetrics {
float rowHeight = 22.0f;
float horizontalPadding = 12.0f;
float labelControlGap = 20.0f;
float controlColumnStart = 236.0f;
float controlMinWidth = 0.0f;
float controlTrailingInset = 8.0f;
float controlInsetY = 1.0f;
};
struct UIEditorFieldRowLayout {
::XCEngine::UI::UIRect bounds = {};
::XCEngine::UI::UIRect labelRect = {};
::XCEngine::UI::UIRect controlRect = {};
};
const UIEditorInspectorFieldStyleTokens& GetUIEditorInspectorFieldStyleTokens();
bool AreUIEditorFieldMetricsEqual(float lhs, float rhs);
bool AreUIEditorFieldColorsEqual(
const ::XCEngine::UI::UIColor& lhs,
const ::XCEngine::UI::UIColor& rhs);
UIEditorFieldRowLayout BuildUIEditorFieldRowLayout(
const ::XCEngine::UI::UIRect& bounds,
float minimumControlWidth,
const UIEditorFieldRowLayoutMetrics& metrics = {});
} // namespace XCEngine::UI::Editor::Widgets

View File

@@ -0,0 +1,154 @@
#pragma once
#include <XCEditor/Foundation/UIEditorTextMeasurement.h>
#include <XCEngine/UI/Text/UITextEditing.h>
#include <XCEngine/UI/DrawData.h>
#include <algorithm>
#include <chrono>
#include <cmath>
#include <string>
namespace XCEngine::UI::Editor::Widgets {
inline float MeasureUIEditorTextLayoutHeight(float fontSize) {
return (std::max)(0.0f, fontSize * 1.35f);
}
inline float ResolveUIEditorTextTop(
const ::XCEngine::UI::UIRect& rect,
float fontSize,
float offsetY = 0.0f) {
const float textHeight = MeasureUIEditorTextLayoutHeight(fontSize);
const float centeredTop =
rect.y + (std::max)(0.0f, std::floor((rect.height - textHeight) * 0.5f));
return centeredTop - 1.0f + offsetY;
}
inline float ResolveUIEditorControlTextTop(
const ::XCEngine::UI::UIRect& rect,
float fontSize,
float offsetY = 0.0f) {
const float textHeight = MeasureUIEditorTextLayoutHeight(fontSize);
const float centeredTop =
rect.y + (std::max)(0.0f, std::floor((rect.height - textHeight) * 0.5f));
return centeredTop + offsetY;
}
inline ::XCEngine::UI::UIRect ResolveUIEditorTextClipRect(
const ::XCEngine::UI::UIRect& rect,
float fontSize) {
const float extraPadding = (std::max)(2.0f, std::ceil(fontSize * 0.35f));
return ::XCEngine::UI::UIRect(
rect.x,
rect.y - 1.0f,
rect.width,
rect.height + extraPadding + 1.0f);
}
inline float MeasureUIEditorTextWidth(
const std::string& text,
float fontSize,
const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr) {
if (textMeasurer != nullptr &&
!text.empty() &&
fontSize > 0.0f) {
return textMeasurer->MeasureTextWidth(
::XCEngine::UI::Editor::UIEditorTextMeasureRequest{
text,
fontSize
});
}
return fontSize * 0.56f *
static_cast<float>(::XCEngine::UI::Text::CountUtf8Codepoints(text));
}
inline float MeasureUIEditorTextWidthToCaret(
const std::string& text,
std::size_t caretOffset,
float fontSize,
const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr) {
const std::size_t clampedCaretOffset = (std::min)(caretOffset, text.size());
if (textMeasurer != nullptr &&
clampedCaretOffset > 0u &&
fontSize > 0.0f) {
return textMeasurer->MeasureTextAdvance(
::XCEngine::UI::Editor::UIEditorTextMeasureRequest{
std::string_view(text.data(), clampedCaretOffset),
fontSize
});
}
return fontSize * 0.56f *
static_cast<float>(::XCEngine::UI::Text::CountUtf8CodepointsInRange(
text,
0u,
clampedCaretOffset));
}
inline std::uint64_t GetUIEditorTextCaretClockNanoseconds() {
using Clock = std::chrono::steady_clock;
const auto now = Clock::now().time_since_epoch();
return static_cast<std::uint64_t>(
std::chrono::duration_cast<std::chrono::nanoseconds>(now).count());
}
inline bool ShouldBlinkUIEditorTextCaret(std::uint64_t blinkStartNanoseconds) {
constexpr std::uint64_t kInitialVisibleDurationNanoseconds = 500000000ull;
constexpr std::uint64_t kBlinkPhaseDurationNanoseconds = 500000000ull;
if (blinkStartNanoseconds == 0u) {
return true;
}
const std::uint64_t nowNanoseconds = GetUIEditorTextCaretClockNanoseconds();
if (nowNanoseconds <= blinkStartNanoseconds) {
return true;
}
const std::uint64_t elapsedNanoseconds = nowNanoseconds - blinkStartNanoseconds;
if (elapsedNanoseconds < kInitialVisibleDurationNanoseconds) {
return true;
}
const std::uint64_t blinkElapsedNanoseconds =
elapsedNanoseconds - kInitialVisibleDurationNanoseconds;
return ((blinkElapsedNanoseconds / kBlinkPhaseDurationNanoseconds) % 2u) == 0u;
}
inline void AppendUIEditorTextCaret(
::XCEngine::UI::UIDrawList& drawList,
const ::XCEngine::UI::UIRect& rect,
const std::string& text,
std::size_t caretOffset,
std::uint64_t blinkStartNanoseconds,
const ::XCEngine::UI::UIColor& color,
float fontSize,
float insetX,
float insetY = 0.0f,
float thickness = 1.0f,
const ::XCEngine::UI::Editor::UIEditorTextMeasurer* textMeasurer = nullptr) {
if (color.a <= 0.0f || !ShouldBlinkUIEditorTextCaret(blinkStartNanoseconds)) {
return;
}
const float caretX = (std::min)(
rect.x + rect.width - 1.0f,
rect.x + insetX +
MeasureUIEditorTextWidthToCaret(
text,
caretOffset,
fontSize,
textMeasurer));
const float top = ResolveUIEditorControlTextTop(rect, fontSize, insetY);
const float bottom = top + MeasureUIEditorTextLayoutHeight(fontSize);
drawList.AddLine(
::XCEngine::UI::UIPoint(caretX, top),
::XCEngine::UI::UIPoint(caretX, bottom),
color,
thickness);
}
} // namespace XCEngine::UI::Editor::Widgets