diff options
Diffstat (limited to 'core')
-rw-r--r-- | core/src/Locale/zh_CN.h | 9 | ||||
-rw-r--r-- | core/src/Model/Template/TableTemplate.cpp | 4 | ||||
-rw-r--r-- | core/src/Model/Template/Template_Main.cpp | 10 | ||||
-rw-r--r-- | core/src/Model/Workflow/Workflow_Main.cpp | 10 | ||||
-rw-r--r-- | core/src/UI/UI_Templates.cpp | 218 |
5 files changed, 206 insertions, 45 deletions
diff --git a/core/src/Locale/zh_CN.h b/core/src/Locale/zh_CN.h index 478c627..b01017f 100644 --- a/core/src/Locale/zh_CN.h +++ b/core/src/Locale/zh_CN.h @@ -81,3 +81,12 @@ #define L10N_DELETE_ASSET_DIALOG_TITLE "确认删除资源" #define L10N_RENAME_ASSET_DIALOG_TITLE "重命名资源" #define L10N_TEMPLATE_INVALID_TYPE_ERROR "无效的模板类型" + +#define L10N_TABLE_CELL_HORIZONTAL_ALIGNMENT "水平对齐" +#define L10N_TABLE_CELL_VERTICAL_ALIGNMENT "垂直对齐" +#define L10N_TABLE_CELL_ALIGN_LEFT "左对齐" +#define L10N_TABLE_CELL_ALIGN_CENTER "居中" +#define L10N_TABLE_CELL_ALIGN_RIGHT "右对齐" +#define L10N_TABLE_CELL_ALIGN_TOP "顶部对齐" +#define L10N_TABLE_CELL_ALIGN_MIDDLE "居中" +#define L10N_TABLE_CELL_ALIGN_BOTTOM "底部对齐" diff --git a/core/src/Model/Template/TableTemplate.cpp b/core/src/Model/Template/TableTemplate.cpp index f2524a0..be61606 100644 --- a/core/src/Model/Template/TableTemplate.cpp +++ b/core/src/Model/Template/TableTemplate.cpp @@ -107,8 +107,8 @@ void TableTemplate::Resize(int newWidth, int newHeight) } mCells = std::move(cells); - mColumnWidths.resize(newWidth); - mRowHeights.resize(newHeight); + mColumnWidths.resize(newWidth, 80); + mRowHeights.resize(newHeight, 20); } int TableTemplate::GetRowHeight(int row) const diff --git a/core/src/Model/Template/Template_Main.cpp b/core/src/Model/Template/Template_Main.cpp index 8b659cf..a681c4a 100644 --- a/core/src/Model/Template/Template_Main.cpp +++ b/core/src/Model/Template/Template_Main.cpp @@ -8,6 +8,8 @@ #include <imgui.h> #include <imgui_stdlib.h> +#include <algorithm> +#include <cstdint> #include <fstream> using namespace std::literals::string_view_literals; @@ -34,8 +36,13 @@ std::string TemplateAssetList::RetrieveNameFromFile(const fs::path& file) const std::ifstream ifs(file); if (!ifs) return ""; + uint64_t len; + ifs >> len; + std::string name; - ifs >> name; + name.reserve(len); + std::copy_n(std::istreambuf_iterator(ifs), len, std::back_inserter(name)); + return name; } @@ -56,6 +63,7 @@ void TemplateAssetList::SaveEmptyInstance(const SavedAsset& asset) const std::ofstream ofs(path); if (!ofs) return; + ofs << (uint64_t)asset.Name.size(); ofs << asset.Name; ofs << static_cast<Template::Kind>(asset.Payload); } diff --git a/core/src/Model/Workflow/Workflow_Main.cpp b/core/src/Model/Workflow/Workflow_Main.cpp index 77b64d3..af5103d 100644 --- a/core/src/Model/Workflow/Workflow_Main.cpp +++ b/core/src/Model/Workflow/Workflow_Main.cpp @@ -10,7 +10,9 @@ #include <imgui_node_editor.h> #include <imgui_stdlib.h> #include <tsl/robin_set.h> +#include <algorithm> #include <cassert> +#include <cstdint> #include <fstream> #include <iostream> #include <queue> @@ -755,8 +757,13 @@ std::string WorkflowAssetList::RetrieveNameFromFile(const fs::path& file) const std::ifstream ifs(file); if (!ifs) return ""; + uint64_t len; + ifs >> len; + std::string name; - ifs >> name; + name.reserve(len); + std::copy_n(std::istreambuf_iterator(ifs), len, std::back_inserter(name)); + return name; } @@ -777,6 +784,7 @@ void WorkflowAssetList::SaveEmptyInstance(const SavedAsset& asset) const std::ofstream ofs(path); if (!ofs) return; + ofs << (uint64_t)asset.Name.size(); ofs << asset.Name; } diff --git a/core/src/UI/UI_Templates.cpp b/core/src/UI/UI_Templates.cpp index 7d0251a..48393dc 100644 --- a/core/src/UI/UI_Templates.cpp +++ b/core/src/UI/UI_Templates.cpp @@ -1,4 +1,4 @@ -#include "UI.hpp" +#include "UI.hpp" #include "Model/GlobalStates.hpp" #include "Model/Project.hpp" @@ -22,7 +22,7 @@ public: static std::unique_ptr<TemplateUI> CreateByKind(Template::Kind kind); virtual ~TemplateUI() = default; - virtual void Draw() = 0; + virtual void Display() = 0; }; class TableTemplateUI : public TemplateUI @@ -30,6 +30,14 @@ class TableTemplateUI : public TemplateUI private: std::unique_ptr<TableTemplate> mTable; + struct UICell + { + bool Hovered = false; + bool Held = false; + bool Selected = false; + }; + std::vector<UICell> mUICells; + Vec2i mSelectionTL; Vec2i mSelectionBR; @@ -39,12 +47,14 @@ private: public: TableTemplateUI(std::unique_ptr<TableTemplate> table) : mTable{ std::move(table) } + , mSelectionTL{ -1, -1 } + , mSelectionBR{ -1, -1 } { // TODO debug code - mTable->Resize(6, 2); + Resize(6, 5); } - virtual void Draw() override + virtual void Display() override { ImGui::Columns(2); if (mFirstDraw) { @@ -52,60 +62,122 @@ public: ImGui::SetColumnWidth(0, ImGui::GetWindowWidth() * 0.15f); } - DrawInspector(); + DisplayInspector(); ImGui::NextColumn(); - DrawTable(); + DisplayTable(); ImGui::NextColumn(); ImGui::Columns(1); } + void Resize(int width, int height) + { + mTable->Resize(width, height); + mUICells.resize(width * height); + } + private: - void DrawInspector() + void DisplayInspector() { if (ImGui::BeginTabBar("Inspector")) { if (ImGui::BeginTabItem("Cell")) { - DrawCellInspector(); + if (!IsSelected()) { + ImGui::Text("Select a cell to edit"); + } else if (mSelectionTL == mSelectionBR) { + auto& selectCell = mTable->GetCell(mSelectionTL); + DisplayCellProperties(mSelectionTL); + } else { + DisplayRangeProperties(mSelectionTL, mSelectionBR); + } ImGui::EndTabItem(); } + if (ImGui::BeginTabItem("Table")) { - DrawTableInspector(); + DisplayTableInspector(); ImGui::EndTabItem(); } + ImGui::EndTabBar(); } } - void DrawCellInspector() + void DisplayCellProperties(Vec2i pos) { - if (IsSelected()) { - if (mSelectionTL == mSelectionBR) { - auto& selectCell = mTable->GetCell(mSelectionTL); - // TODO - } else { - // TODO + auto& cell = mTable->GetCell(pos); + auto& uiCell = mUICells[pos.y * mTable->GetTableWidth() + pos.x]; + + constexpr auto kLeft = I18N_TEXT("Left", L10N_TABLE_CELL_ALIGN_LEFT); + constexpr auto kCenter = I18N_TEXT("Center", L10N_TABLE_CELL_ALIGN_CENTER); + constexpr auto kRight = I18N_TEXT("Right", L10N_TABLE_CELL_ALIGN_RIGHT); + + const char* horizontalText; + switch (cell.HorizontalAlignment) { + case TableCell::AlignAxisMin: horizontalText = kLeft; break; + case TableCell::AlignCenter: horizontalText = kCenter; break; + case TableCell::AlignAxisMax: horizontalText = kRight; break; + } + + if (ImGui::BeginCombo(I18N_TEXT("Horizontal alignment", L10N_TABLE_CELL_HORIZONTAL_ALIGNMENT), horizontalText)) { + if (ImGui::Selectable(kLeft, cell.HorizontalAlignment == TableCell::AlignAxisMin)) { + cell.HorizontalAlignment = TableCell::AlignAxisMin; + } + if (ImGui::Selectable(kCenter, cell.HorizontalAlignment == TableCell::AlignCenter)) { + cell.HorizontalAlignment = TableCell::AlignCenter; } - } else { - ImGui::Text("Select a cell to edit"); + if (ImGui::Selectable(kRight, cell.HorizontalAlignment == TableCell::AlignAxisMax)) { + cell.HorizontalAlignment = TableCell::AlignAxisMax; + } + ImGui::EndCombo(); + } + + constexpr auto kTop = I18N_TEXT("Left", L10N_TABLE_CELL_ALIGN_TOP); + constexpr auto kMiddle = I18N_TEXT("Middle", L10N_TABLE_CELL_ALIGN_MIDDLE); + constexpr auto kBottom = I18N_TEXT("Right", L10N_TABLE_CELL_ALIGN_BOTTOM); + + const char* verticalText; + switch (cell.VerticalAlignment) { + case TableCell::AlignAxisMin: verticalText = kTop; break; + case TableCell::AlignCenter: verticalText = kMiddle; break; + case TableCell::AlignAxisMax: verticalText = kBottom; break; + } + + if (ImGui::BeginCombo(I18N_TEXT("Vertical alignment", L10N_TABLE_CELL_VERTICAL_ALIGNMENT), verticalText)) { + if (ImGui::Selectable(kTop, cell.VerticalAlignment == TableCell::AlignAxisMin)) { + cell.VerticalAlignment = TableCell::AlignAxisMin; + } + if (ImGui::Selectable(kMiddle, cell.VerticalAlignment == TableCell::AlignCenter)) { + cell.VerticalAlignment = TableCell::AlignCenter; + } + if (ImGui::Selectable(kBottom, cell.VerticalAlignment == TableCell::AlignAxisMax)) { + cell.VerticalAlignment = TableCell::AlignAxisMax; + } + ImGui::EndCombo(); } } - void DrawTableInspector() + void DisplayRangeProperties(Vec2i tl, Vec2i br) { // TODO } - void DrawTable() + void DisplayTableInspector() { - constexpr int kCellSpacing = 20; + // TODO + } + void DisplayTable() + { + ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(8, 8)); ImGui::BeginChild("TableTemplate"); + auto regularColor = ImGui::GetColorU32(ImGuiCol_Button); + auto hoveredColor = ImGui::GetColorU32(ImGuiCol_ButtonHovered); + auto activeColor = ImGui::GetColorU32(ImGuiCol_ButtonActive); + auto navHighlight = ImGui::GetColorU32(ImGuiCol_NavHighlight); + int colCount = mTable->GetTableWidth(); int rowCount = mTable->GetTableHeight(); - float x = 0.0f; - float y = 0.0f; for (int rowIdx = 0; rowIdx < rowCount; ++rowIdx) { int rowHeight = mTable->GetRowHeight(rowIdx); @@ -113,37 +185,69 @@ private: int colWidth = mTable->GetColumnWidth(colIdx); int i = rowIdx * colCount + colIdx; - ImGuiID id = ImGui::GetCurrentWindow()->GetID(i); + auto window = ImGui::GetCurrentWindow(); + auto id = window->GetID(i); - auto p = ImGui::GetCursorPos(); - ImGui::GetWindowDrawList()->AddRectFilled( - ImVec2(p.x + x, p.y + y), - ImVec2(p.x + x + colWidth, p.y + y + rowHeight), - RgbaColor(170, 204, 244).AsImU32()); + Vec2i cellLoc{ colIdx, rowIdx }; + auto& cell = mTable->GetCell(cellLoc); + auto& uiCell = mUICells[i]; + ImVec2 size(colWidth, rowHeight); ImRect rect{ - ImVec2(x, y), - ImVec2(colWidth, rowHeight), + window->DC.CursorPos, + window->DC.CursorPos + ImGui::CalcItemSize(size, 0.0f, 0.0f), }; - if (ImGui::ButtonBehavior(rect, id, nullptr, nullptr)) { + + if (uiCell.Selected) { + window->DrawList->AddRectFilled( + rect.Min - ImVec2(2, 1), + rect.Max + ImVec2(2, 1), + navHighlight); + } else { + ImU32 color; + if (uiCell.Held) { + color = activeColor; + } else if (uiCell.Hovered) { + color = hoveredColor; + } else { + color = regularColor; + } + window->DrawList->AddRectFilled(rect.Min, rect.Max, color); + } + + ImGui::ItemSize(size); + if (!ImGui::ItemAdd(rect, id)) { + continue; + } + + if (ImGui::ButtonBehavior(rect, id, &uiCell.Hovered, &uiCell.Held)) { if (ImGui::GetIO().KeyShift && IsSelected()) { - // Select range - mSelectionBR = { colIdx, rowIdx }; + SelectRange(mSelectionTL, { colIdx, rowIdx }); } else { - // Select a single cell SelectCell({ colIdx, rowIdx }); } } - x += colWidth; - x += kCellSpacing; + // Don't SameLine() if we are on the last cell in the row + if (colIdx != colCount - 1) { + ImGui::SameLine(); + } } - - y += rowHeight; - y += kCellSpacing; } ImGui::EndChild(); + ImGui::PopStyleVar(); + } + + template <class TFunction> + void ForeachSelectedCell(const TFunction& func) + { + for (int y = mSelectionTL.y; y <= mSelectionBR.y; ++y) { + for (int x = mSelectionTL.x; x <= mSelectionBR.x; ++x) { + int i = y * mTable->GetTableWidth() + x; + func(i, x, y); + } + } } bool IsSelected() const @@ -153,14 +257,46 @@ private: void ClearSelection() { + if (IsSelected()) { + ForeachSelectedCell([this](int i, int, int) { + auto& uiCell = mUICells[i]; + uiCell.Selected = false; + }); + } + mSelectionTL = { -1, -1 }; mSelectionBR = { -1, -1 }; } + void SelectRange(Vec2i p1, Vec2i p2) + { + ClearSelection(); + + if (p2.x < p1.x) { + std::swap(p2.x, p1.x); + } + if (p2.y < p1.y) { + std::swap(p2.y, p1.y); + } + + mSelectionTL = p1; + mSelectionBR = p2; + + ForeachSelectedCell([this](int i, int, int) { + auto& uiCell = mUICells[i]; + uiCell.Selected = true; + }); + } + void SelectCell(Vec2i cell) { + ClearSelection(); + mSelectionTL = cell; mSelectionBR = cell; + + int i = cell.y * mTable->GetTableWidth() + cell.x; + mUICells[i].Selected = true; } }; @@ -228,6 +364,6 @@ void UI::TemplatesTab() } if (openTemplate) { - openTemplate->Draw(); + openTemplate->Display(); } } |