From 09c57545bc7fe7a842dd31b739506ff3d9da347e Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sun, 28 Jan 2024 16:29:39 -0600 Subject: [PATCH 1/4] [ox/std] Add Vector::at --- deps/ox/src/ox/std/vector.hpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/deps/ox/src/ox/std/vector.hpp b/deps/ox/src/ox/std/vector.hpp index 2bb6008f..87033fda 100644 --- a/deps/ox/src/ox/std/vector.hpp +++ b/deps/ox/src/ox/std/vector.hpp @@ -221,6 +221,12 @@ class Vector: detail::VectorAllocator { constexpr const T &operator[](std::size_t i) const noexcept; + [[nodiscard]] + constexpr Result at(size_t i) noexcept; + + [[nodiscard]] + constexpr Result at(size_t i) const noexcept; + [[nodiscard]] constexpr Result front() noexcept; @@ -416,6 +422,22 @@ constexpr const T &Vector::operator[](std::size_t return m_items[i]; } +template +constexpr Result Vector::at(size_t i) noexcept { + if (i < size()) { + return &operator[](i); + } + return OxError(1, "Vector: Invalid index"); +} + +template +constexpr Result Vector::at(size_t i) const noexcept { + if (i < size()) { + return &operator[](i); + } + return OxError(1, "Vector: Invalid index"); +} + template constexpr Result Vector::front() noexcept { if (!m_size) { From 02db760b8cd21892febf3640f9dc2caae6358c6d Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sun, 28 Jan 2024 18:03:12 -0600 Subject: [PATCH 2/4] [olympic] Add more ImGui helpers, studio::Editor::pushCommand --- .../studio/modlib/include/studio/editor.hpp | 11 +++ .../modlib/include/studio/imguiutil.hpp | 38 ++++++++++ src/olympic/studio/modlib/src/editor.cpp | 4 ++ src/olympic/studio/modlib/src/imguiutil.cpp | 72 +++++++++++++++++++ 4 files changed, 125 insertions(+) diff --git a/src/olympic/studio/modlib/include/studio/editor.hpp b/src/olympic/studio/modlib/include/studio/editor.hpp index 20ddb0c3..59b7e2f0 100644 --- a/src/olympic/studio/modlib/include/studio/editor.hpp +++ b/src/olympic/studio/modlib/include/studio/editor.hpp @@ -131,6 +131,17 @@ class Editor: public studio::BaseEditor { [[nodiscard]] UndoStack *undoStack() noexcept final; + void pushCommand(ox::UPtr &&cmd) noexcept; + + template + void pushCommand(Args&&... args) noexcept { + try { + m_undoStack.push(ox::make_unique(ox::forward(args)...)); + } catch (ox::Exception const&ex) { + oxLogError(ex.toError()); + } + } + private: ox::Error markUnsavedChanges(UndoCommand const*) noexcept; }; diff --git a/src/olympic/studio/modlib/include/studio/imguiutil.hpp b/src/olympic/studio/modlib/include/studio/imguiutil.hpp index 9f4aea25..a77c4e3b 100644 --- a/src/olympic/studio/modlib/include/studio/imguiutil.hpp +++ b/src/olympic/studio/modlib/include/studio/imguiutil.hpp @@ -7,6 +7,7 @@ #include #include +#include namespace studio::ig { @@ -52,4 +53,41 @@ bool BeginPopup(turbine::Context &ctx, ox::CStringView popupName, bool &show, Im */ bool ComboBox(ox::CStringView lbl, ox::SpanView list, size_t &selectedIdx) noexcept; +bool FileComboBox( + ox::CStringView lbl, + studio::StudioContext &sctx, + ox::StringView fileExt, + size_t &selectedIdx) noexcept; + +/** + * + * @param name + * @param list + * @param selIdx + * @return true if new value selected, false otherwise + */ +bool ListBox(ox::CStringView name, ox::SpanView const&list, size_t &selIdx) noexcept; + +class FilePicker { + private: + bool m_show{}; + studio::StudioContext &m_sctx; + ox::String const m_title; + ox::String const m_fileExt; + ImVec2 const m_size; + public: + ox::Signal filePicked; + + FilePicker( + studio::StudioContext &sctx, + ox::String title, + ox::String fileExt, + ImVec2 const&size = {}) noexcept; + + void draw() noexcept; + + void show() noexcept; + +}; + } \ No newline at end of file diff --git a/src/olympic/studio/modlib/src/editor.cpp b/src/olympic/studio/modlib/src/editor.cpp index 61a74e8c..1c78de60 100644 --- a/src/olympic/studio/modlib/src/editor.cpp +++ b/src/olympic/studio/modlib/src/editor.cpp @@ -127,6 +127,10 @@ ox::CStringView Editor::itemDisplayName() const noexcept { return m_itemName; } +void Editor::pushCommand(ox::UPtr &&cmd) noexcept { + m_undoStack.push(std::move(cmd)); +} + UndoStack *Editor::undoStack() noexcept { return &m_undoStack; } diff --git a/src/olympic/studio/modlib/src/imguiutil.cpp b/src/olympic/studio/modlib/src/imguiutil.cpp index 67eca2bf..fbccc985 100644 --- a/src/olympic/studio/modlib/src/imguiutil.cpp +++ b/src/olympic/studio/modlib/src/imguiutil.cpp @@ -92,4 +92,76 @@ bool ComboBox( return out; } +bool FileComboBox( + ox::CStringView lbl, + studio::StudioContext &sctx, + ox::StringView fileExt, + size_t &selectedIdx) noexcept { + auto const&list = sctx.project->fileList(fileExt); + bool out{}; + auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : ""; + if (ImGui::BeginCombo(lbl.c_str(), first, 0)) { + for (auto i = 0u; i < list.size(); ++i) { + const auto selected = (selectedIdx == i); + if (ImGui::Selectable(list[i].c_str(), selected) && selectedIdx != i) { + selectedIdx = i; + out = true; + } + } + ImGui::EndCombo(); + } + return out; +} + +bool ListBox(ox::CStringView name, ox::SpanView const&list, size_t &selIdx) noexcept { + auto out = false; + if (ImGui::BeginListBox(name.c_str())) { + for (auto i = 0u; auto const&obj : list) { + ig::IDStackItem const idStackItem2(static_cast(i)); + if (ImGui::Selectable(obj.c_str(), selIdx == i)) { + if (i != selIdx) { + selIdx = i; + out = true; + } + } + ++i; + } + ImGui::EndListBox(); + } + return out; +} + + +FilePicker::FilePicker( + studio::StudioContext &sctx, + ox::String title, + ox::String fileExt, + ImVec2 const&size) noexcept: + m_sctx(sctx), + m_title(std::move(title)), + m_fileExt(std::move(fileExt)), + m_size(size) { +} + +void FilePicker::draw() noexcept { + if (!m_show) { + return; + } + auto constexpr popupSz = ImVec2{450.f, 0}; + ig::IDStackItem const idStackItem(m_title.c_str()); + if (ig::BeginPopup(m_sctx.tctx, m_title.c_str(), m_show, popupSz)) { + auto const&list = m_sctx.project->fileList(m_fileExt); + size_t selIdx{}; + ig::ComboBox(m_title.c_str(), list, selIdx); + if (ig::PopupControlsOkCancel(popupSz.x, m_show) == ig::PopupResponse::OK) { + filePicked.emit(list[selIdx]); + } + ImGui::EndPopup(); + } +} + +void FilePicker::show() noexcept { + m_show = true; +} + } From 227dd68a4f67ba83ce1d3243fca47131697d436d Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sun, 28 Jan 2024 17:59:36 -0600 Subject: [PATCH 3/4] [ox/model] Change order of oxModelFieldRename args --- deps/ox/src/ox/model/def.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps/ox/src/ox/model/def.hpp b/deps/ox/src/ox/model/def.hpp index 2648363d..50f8c95a 100644 --- a/deps/ox/src/ox/model/def.hpp +++ b/deps/ox/src/ox/model/def.hpp @@ -13,5 +13,5 @@ #define oxModelBegin(modelName) constexpr ox::Error model(auto *io, [[maybe_unused]] ox::CommonPtrWith auto *o) noexcept { oxReturnError(io->template setTypeInfo()); #define oxModelEnd() return OxError(0); } #define oxModelField(fieldName) oxReturnError(io->field(#fieldName, &o->fieldName)); -#define oxModelFieldRename(serFieldName, objFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName)); +#define oxModelFieldRename(objFieldName, serFieldName) oxReturnError(io->field(#serFieldName, &o->objFieldName)); #define oxModelFriend(modelName) friend constexpr ox::Error model(auto*, ox::CommonPtrWith auto*) noexcept From b75bbc4d200c0f4187f5c4068ba686dad34820cd Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sun, 28 Jan 2024 17:59:54 -0600 Subject: [PATCH 4/4] [olympic,nostalgia] Change order of oxModelFieldRename args --- .../studio/tilesheeteditor/commands/cutpastecommand.hpp | 2 +- .../modules/scene/include/nostalgia/scene/scenestatic.hpp | 6 +++--- src/olympic/studio/applib/src/studioapp.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.hpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.hpp index af72f09e..a0b1a59c 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.hpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/commands/cutpastecommand.hpp @@ -40,7 +40,7 @@ oxModelBegin(TileSheetClipboard::Pixel) oxModelEnd() oxModelBegin(TileSheetClipboard) - oxModelFieldRename(pixels, m_pixels) + oxModelFieldRename(m_pixels, pixels) oxModelEnd() class CutPasteCommand: public TileSheetCommand { diff --git a/src/nostalgia/modules/scene/include/nostalgia/scene/scenestatic.hpp b/src/nostalgia/modules/scene/include/nostalgia/scene/scenestatic.hpp index f3c9df5c..709a0ab4 100644 --- a/src/nostalgia/modules/scene/include/nostalgia/scene/scenestatic.hpp +++ b/src/nostalgia/modules/scene/include/nostalgia/scene/scenestatic.hpp @@ -58,10 +58,10 @@ struct TileDoc { }; oxModelBegin(TileDoc) - oxModelFieldRename(subsheet_id, subsheetId) - oxModelFieldRename(subsheet_path, subsheetPath) + oxModelFieldRename(subsheetId, subsheet_id) + oxModelFieldRename(subsheetPath, subsheet_path) oxModelField(type) - oxModelFieldRename(layer_attachments, layerAttachments) + oxModelFieldRename(layerAttachments, layer_attachments) oxModelEnd() struct SceneDoc { diff --git a/src/olympic/studio/applib/src/studioapp.cpp b/src/olympic/studio/applib/src/studioapp.cpp index c97b0771..984be43f 100644 --- a/src/olympic/studio/applib/src/studioapp.cpp +++ b/src/olympic/studio/applib/src/studioapp.cpp @@ -34,10 +34,10 @@ struct StudioConfig { }; oxModelBegin(StudioConfig) - oxModelFieldRename(active_tab_item_name, activeTabItemName) - oxModelFieldRename(project_path, projectPath) - oxModelFieldRename(open_files, openFiles) - oxModelFieldRename(show_project_explorer, showProjectExplorer) + oxModelFieldRename(activeTabItemName, active_tab_item_name) + oxModelFieldRename(projectPath, project_path) + oxModelFieldRename(openFiles, open_files) + oxModelFieldRename(showProjectExplorer, show_project_explorer) oxModelEnd() StudioUI::StudioUI(studio::StudioContext &ctx, ox::StringView projectDataDir) noexcept: