chore: sync workspace state

This commit is contained in:
2026-03-29 01:36:53 +08:00
parent eb5de3e3d4
commit e5cb79f3ce
4935 changed files with 35593 additions and 360696 deletions

View File

@@ -22,6 +22,8 @@ struct AssetTileResult {
bool hovered = false;
ImVec2 min = ImVec2(0.0f, 0.0f);
ImVec2 max = ImVec2(0.0f, 0.0f);
ImVec2 labelMin = ImVec2(0.0f, 0.0f);
ImVec2 labelMax = ImVec2(0.0f, 0.0f);
};
struct AssetTileOptions {
@@ -30,6 +32,7 @@ struct AssetTileOptions {
ImVec2 iconSize = AssetTileIconSize();
bool drawIdleFrame = true;
bool drawSelectionBorder = true;
bool drawLabel = true;
};
enum class DialogActionResult {
@@ -79,6 +82,77 @@ inline bool DrawMenuScope(const char* label, DrawContentFn&& drawContent) {
return true;
}
template <typename DrawContentFn>
inline bool DrawPopupSubmenuScope(const char* label, DrawContentFn&& drawContent) {
if (!label || label[0] == '\0') {
return false;
}
ImGui::PushID(label);
const char* popupId = "##PopupSubmenu";
const ImVec2 labelSize = ImGui::CalcTextSize(label);
const ImVec2 rowPos = ImGui::GetCursorScreenPos();
const float rowHeight = labelSize.y;
const float rowWidth = ImMax(ImGui::GetContentRegionAvail().x, 1.0f);
const bool popupOpen = ImGui::IsPopupOpen(popupId);
if (ImGui::Selectable(
"##PopupSubmenuRow",
popupOpen,
ImGuiSelectableFlags_NoAutoClosePopups,
ImVec2(rowWidth, rowHeight))) {
ImGui::OpenPopup(popupId);
}
const bool hovered = ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
if (hovered && !popupOpen) {
ImGui::OpenPopup(popupId);
}
const ImVec2 itemMin = ImGui::GetItemRectMin();
const ImVec2 itemMax = ImGui::GetItemRectMax();
const ImVec2 parentWindowPos = ImGui::GetWindowPos();
const ImVec2 parentWindowSize = ImGui::GetWindowSize();
const float parentWindowRight = parentWindowPos.x + parentWindowSize.x;
const float itemHeight = itemMax.y - itemMin.y;
ImDrawList* drawList = ImGui::GetWindowDrawList();
drawList->AddText(
ImVec2(itemMin.x + ImGui::GetStyle().FramePadding.x, itemMin.y + (itemHeight - labelSize.y) * 0.5f),
ImGui::GetColorU32(ImGuiCol_Text),
label);
const float arrowExtent = PopupSubmenuArrowExtent();
const float arrowCenterX = itemMax.x - PopupSubmenuArrowTrailingInset() - arrowExtent * 0.5f;
const float arrowCenterY = (itemMin.y + itemMax.y) * 0.5f;
drawList->AddTriangleFilled(
ImVec2(arrowCenterX - arrowExtent * 0.30f, arrowCenterY - arrowExtent * 0.50f),
ImVec2(arrowCenterX - arrowExtent * 0.30f, arrowCenterY + arrowExtent * 0.50f),
ImVec2(arrowCenterX + arrowExtent * 0.50f, arrowCenterY),
ImGui::GetColorU32(ImGuiCol_Text));
ImGui::SetNextWindowPos(
ImVec2(parentWindowRight + PopupSubmenuOpenOffsetX(), rowPos.y - PopupWindowPadding().y),
ImGuiCond_Always);
const bool open = BeginPopup(
popupId,
ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoSavedSettings);
if (!open) {
ImGui::PopID();
return false;
}
drawContent();
const bool popupHovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
if (!hovered && !popupHovered && !ImGui::IsWindowAppearing()) {
ImGui::CloseCurrentPopup();
}
EndPopup();
ImGui::PopID();
return true;
}
template <typename ExecuteFn>
inline bool DrawMenuCommand(const MenuCommand& command, ExecuteFn&& execute) {
if (command.kind == MenuCommandKind::Separator) {
@@ -285,8 +359,8 @@ inline AssetTileResult DrawAssetTile(
drawList->AddRect(min, max, ImGui::GetColorU32(AssetTileIdleBorderColor()), AssetTileRounding());
}
if (hovered || selected) {
drawList->AddRectFilled(min, max, ImGui::GetColorU32(selected ? AssetTileSelectedFillColor() : AssetTileHoverFillColor()), AssetTileRounding());
if (selected) {
drawList->AddRectFilled(min, max, ImGui::GetColorU32(AssetTileSelectedFillColor()), AssetTileRounding());
}
if (selected && options.drawSelectionBorder) {
drawList->AddRect(min, max, ImGui::GetColorU32(AssetTileSelectedBorderColor()), AssetTileRounding());
@@ -302,14 +376,19 @@ inline AssetTileResult DrawAssetTile(
drawIcon(drawList, iconMin, iconMax);
const ImVec2 textPadding = AssetTileTextPadding();
const float textAreaWidth = tileSize.x - textPadding.x * 2.0f;
const float centeredTextX = min.x + textPadding.x + std::max(0.0f, (textAreaWidth - textSize.x) * 0.5f);
const float textY = max.y - textSize.y - AssetTileTextPadding().y;
ImGui::PushClipRect(ImVec2(min.x + textPadding.x, min.y), ImVec2(max.x - textPadding.x, max.y), true);
drawList->AddText(ImVec2(centeredTextX, textY), ImGui::GetColorU32(AssetTileTextColor(selected)), label);
ImGui::PopClipRect();
const float labelHeight = ImGui::GetFrameHeight();
const ImVec2 labelMin(min.x + textPadding.x, max.y - labelHeight - textPadding.y * 0.5f);
const ImVec2 labelMax(max.x - textPadding.x, labelMin.y + labelHeight);
if (options.drawLabel) {
const float textAreaWidth = labelMax.x - labelMin.x;
const float centeredTextX = labelMin.x + std::max(0.0f, (textAreaWidth - textSize.x) * 0.5f);
const float textY = labelMin.y + (labelHeight - textSize.y) * 0.5f;
ImGui::PushClipRect(labelMin, labelMax, true);
drawList->AddText(ImVec2(centeredTextX, textY), ImGui::GetColorU32(AssetTileTextColor(selected)), label);
ImGui::PopClipRect();
}
return AssetTileResult{ clicked, contextRequested, openRequested, hovered, min, max };
return AssetTileResult{ clicked, contextRequested, openRequested, hovered, min, max, labelMin, labelMax };
}
template <typename DrawMenuFn>