From ca2d9eb5349ead95bfdf1e16ce129ed3ba18261a Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Sat, 7 Sep 2024 00:16:03 -0500 Subject: [PATCH] Squashed 'deps/nostalgia/' changes from ab025e88..4d63a65f 4d63a65f [nostalgia/core/studio] Show Palette page names in TileSheetEditor 686db99d [nostalgia/core/studio] Disable Palette page hotkeys when Rename popup is open 52533c8c [nostalgia/core/studio] Add Palette page names to editor ba4540e4 [ox/std] Add IString::unsafeResize 36057bb0 [nostalgia/core/studio] Fix Clang build 1a2b2b8b [nostalgia/core] Add PaletteV4, with support for page names, make PaletteColor object 6189193a [nostalgia] Add NFDE install 67a10d35 [nostalgia/sample_project] Update type descriptor git-subtree-dir: deps/nostalgia git-subtree-split: 4d63a65fbde480235edd961e5cd19d8b4de1b66d --- CMakeLists.txt | 1 + deps/ox/src/ox/std/istring.hpp | 14 ++ ...nkingtea.nostalgia.core.CompactTileSheet;1 | 1 + ...kingtea.nostalgia.core.Palette.ColorInfo;3 | 12 ++ ...ngtea.nostalgia.core.Palette.PalettePage;1 | 23 +++ .../net.drinkingtea.nostalgia.core.Palette;3 | 13 +- .../net.drinkingtea.nostalgia.core.Palette;4 | 31 ++++ ....drinkingtea.nostalgia.core.PaletteColor;1 | 24 +++ .../core/include/nostalgia/core/palette.hpp | 140 +++++++++++++++--- .../modules/core/src/keel/keelmodule.cpp | 7 +- .../modules/core/src/keel/typeconv.cpp | 25 +++- .../modules/core/src/keel/typeconv.hpp | 4 + .../paletteeditor/paletteeditor-imgui.cpp | 72 ++++++--- .../paletteeditor/paletteeditor-imgui.hpp | 19 +++ .../studio/paletteeditor/paletteeditor.cpp | 68 +++++---- .../studio/paletteeditor/paletteeditor.hpp | 35 ++++- .../tilesheeteditor/tilesheeteditor-imgui.cpp | 12 +- .../tilesheeteditor/tilesheeteditor-imgui.hpp | 2 +- .../tilesheeteditor/tilesheeteditormodel.cpp | 4 +- src/olympic/studio/applib/src/aboutpopup.cpp | 9 +- .../studio/modlib/include/studio/context.hpp | 2 +- .../modlib/include/studio/imguiutil.hpp | 27 +++- src/olympic/studio/modlib/src/imguiutil.cpp | 34 ++--- 23 files changed, 459 insertions(+), 120 deletions(-) create mode 100644 sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette.ColorInfo;3 create mode 100644 sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette.PalettePage;1 create mode 100644 sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette;4 create mode 100644 sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.PaletteColor;1 diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c9c113..9529a1e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -61,6 +61,7 @@ if(NOT BUILDCORE_TARGET STREQUAL "gba") add_subdirectory(deps/glutils) add_subdirectory(deps/imgui) add_subdirectory(deps/lodepng) + set(NFD_INSTALL ON) add_subdirectory(deps/nfde) endif() diff --git a/deps/ox/src/ox/std/istring.hpp b/deps/ox/src/ox/std/istring.hpp index 7ffee5e..83dea25 100644 --- a/deps/ox/src/ox/std/istring.hpp +++ b/deps/ox/src/ox/std/istring.hpp @@ -81,6 +81,11 @@ class IString { constexpr ox::Error resize(size_t sz) noexcept; + /** + * Resizes without clearing memory between current end and new end. + */ + constexpr ox::Error unsafeResize(size_t sz) noexcept; + /** * Returns the capacity of bytes for this string. */ @@ -220,6 +225,15 @@ constexpr ox::Error IString::resize(size_t sz) noexcept { return {}; } +template +constexpr ox::Error IString::unsafeResize(size_t sz) noexcept { + if (sz > StrCap) [[unlikely]] { + return OxError(1, "Trying to extend IString beyond its cap"); + } + m_size = sz; + return {}; +} + template struct MaybeView> { using type = ox::StringView; diff --git a/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.CompactTileSheet;1 b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.CompactTileSheet;1 index 2f891fa..bb9db51 100644 --- a/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.CompactTileSheet;1 +++ b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.CompactTileSheet;1 @@ -21,6 +21,7 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{ "typeId" : "B.uint8;0" } ], + "preloadable" : true, "primitiveType" : 5, "typeName" : "net.drinkingtea.nostalgia.core.CompactTileSheet", "typeVersion" : 1 diff --git a/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette.ColorInfo;3 b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette.ColorInfo;3 new file mode 100644 index 0000000..1c2ad7d --- /dev/null +++ b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette.ColorInfo;3 @@ -0,0 +1,12 @@ +O1;net.drinkingtea.ox.TypeDescriptor;1;{ + "fieldList" : + [ + { + "fieldName" : "name", + "typeId" : "net.drinkingtea.ox.BasicString#8#;1" + } + ], + "primitiveType" : 5, + "typeName" : "net.drinkingtea.nostalgia.core.Palette.ColorInfo", + "typeVersion" : 3 +} diff --git a/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette.PalettePage;1 b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette.PalettePage;1 new file mode 100644 index 0000000..503ed99 --- /dev/null +++ b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette.PalettePage;1 @@ -0,0 +1,23 @@ +O1;net.drinkingtea.ox.TypeDescriptor;1;{ + "fieldList" : + [ + { + "fieldName" : "name", + "typeId" : "net.drinkingtea.ox.BasicString#8#;1" + }, + { + "fieldName" : "colors", + "subscriptLevels" : 1, + "subscriptStack" : + [ + { + "subscriptType" : 4 + } + ], + "typeId" : "net.drinkingtea.nostalgia.core.PaletteColor;1" + } + ], + "primitiveType" : 5, + "typeName" : "net.drinkingtea.nostalgia.core.Palette.PalettePage", + "typeVersion" : 1 +} diff --git a/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette;3 b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette;3 index ba52267..56f85fc 100644 --- a/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette;3 +++ b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette;3 @@ -1,6 +1,17 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{ "fieldList" : [ + { + "fieldName" : "colorInfo", + "subscriptLevels" : 1, + "subscriptStack" : + [ + { + "subscriptType" : 4 + } + ], + "typeId" : "net.drinkingtea.nostalgia.core.Palette.ColorInfo;3" + }, { "fieldName" : "pages", "subscriptLevels" : 2, @@ -13,7 +24,7 @@ O1;net.drinkingtea.ox.TypeDescriptor;1;{ "subscriptType" : 4 } ], - "typeId" : "net.drinkingtea.nostalgia.core.Palette.Page;3" + "typeId" : "B.uint16;0" } ], "preloadable" : true, diff --git a/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette;4 b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette;4 new file mode 100644 index 0000000..9aff393 --- /dev/null +++ b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.Palette;4 @@ -0,0 +1,31 @@ +O1;net.drinkingtea.ox.TypeDescriptor;1;{ + "fieldList" : + [ + { + "fieldName" : "colorNames", + "subscriptLevels" : 1, + "subscriptStack" : + [ + { + "subscriptType" : 4 + } + ], + "typeId" : "net.drinkingtea.ox.BasicString#8#;1" + }, + { + "fieldName" : "pages", + "subscriptLevels" : 1, + "subscriptStack" : + [ + { + "subscriptType" : 4 + } + ], + "typeId" : "net.drinkingtea.nostalgia.core.Palette.PalettePage;1" + } + ], + "preloadable" : true, + "primitiveType" : 5, + "typeName" : "net.drinkingtea.nostalgia.core.Palette", + "typeVersion" : 4 +} diff --git a/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.PaletteColor;1 b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.PaletteColor;1 new file mode 100644 index 0000000..816e719 --- /dev/null +++ b/sample_project/.nostalgia/type_descriptors/net.drinkingtea.nostalgia.core.PaletteColor;1 @@ -0,0 +1,24 @@ +O1;net.drinkingtea.ox.TypeDescriptor;1;{ + "fieldList" : + [ + { + "fieldName" : "r", + "typeId" : "B.uint8;0" + }, + { + "fieldName" : "g", + "typeId" : "B.uint8;0" + }, + { + "fieldName" : "b", + "typeId" : "B.uint8;0" + }, + { + "fieldName" : "a", + "typeId" : "B.uint8;0" + } + ], + "primitiveType" : 5, + "typeName" : "net.drinkingtea.nostalgia.core.PaletteColor", + "typeVersion" : 1 +} diff --git a/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp b/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp index af61225..6a2c914 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp @@ -4,10 +4,6 @@ #pragma once -#include -#include -#include -#include #include #include @@ -17,6 +13,54 @@ namespace nostalgia::core { +struct PaletteColorV1 { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.PaletteColor"; + static constexpr auto TypeVersion = 1; + uint8_t r{}, g{}, b{}, a{}; + constexpr PaletteColorV1() noexcept = default; + constexpr PaletteColorV1(Color16 const c) noexcept: + r{red16(c)}, + g{green16(c)}, + b{blue16(c)}, + a{alpha16(c)} {} + constexpr operator Color16() const noexcept { return color16(r, g, b, a); } +}; + +oxModelBegin(PaletteColorV1) + oxModelField(r) + oxModelField(g) + oxModelField(b) + oxModelField(a) +oxModelEnd() + +using PaletteColor = PaletteColorV1; + + +struct PalettePageV1 { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette.PalettePage"; + static constexpr auto TypeVersion = 1; + ox::String name; + ox::Vector colors; + constexpr PalettePageV1() noexcept = default; + constexpr PalettePageV1(ox::StringParam pName, ox::Vector pColors) noexcept: + name(std::move(pName)), colors(std::move(pColors)) {} + constexpr PalettePageV1(ox::StringParam pName, ox::Vector const&pColors) noexcept: + name(std::move(pName)) { + colors.reserve(pColors.size()); + for (auto const c : pColors) { + colors.emplace_back(c); + } + } +}; + +oxModelBegin(PalettePageV1) + oxModelField(name) + oxModelField(colors) +oxModelEnd() + +using PalettePage = PalettePageV1; + + struct NostalgiaPalette { static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.NostalgiaPalette"; static constexpr auto TypeVersion = 1; @@ -36,6 +80,7 @@ struct PaletteV2 { ox::Vector> pages; }; + struct PaletteV3 { static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette"; static constexpr auto TypeVersion = 3; @@ -45,16 +90,55 @@ struct PaletteV3 { static constexpr auto TypeVersion = 3; ox::String name; constexpr ColorInfo() noexcept = default; - constexpr explicit ColorInfo(ox::StringView pName) noexcept: - name(pName) {} - constexpr explicit ColorInfo(ox::String &&pName) noexcept: - name(std::move(pName)) {} + constexpr ColorInfo(ox::StringParam pName) noexcept: name{std::move(pName)} {} }; ox::Vector colorInfo; ox::Vector> pages; }; -using Palette = PaletteV3; +[[nodiscard]] +constexpr bool valid(PaletteV3 const&p) noexcept { + auto const colors = p.colorInfo.size(); + return ox::all_of(p.pages.begin(), p.pages.end(), [colors](auto const&page) { + return page.size() == colors; + }); +} + +constexpr ox::Error repair(PaletteV3 &p) noexcept { + auto const colors = p.colorInfo.size(); + for (auto &page : p.pages) { + page.resize(colors); + } + return {}; +} + + +struct PaletteV4 { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette"; + static constexpr auto TypeVersion = 4; + static constexpr auto Preloadable = true; + ox::Vector colorNames; + ox::Vector pages; +}; + +[[nodiscard]] +constexpr bool valid(PaletteV4 const&p) noexcept { + auto const colors = p.colorNames.size(); + return ox::all_of(p.pages.begin(), p.pages.end(), [colors](PalettePageV1 const&page) { + return page.colors.size() == colors; + }); +} + +constexpr ox::Error repair(PaletteV4 &p) noexcept { + auto const colors = p.colorNames.size(); + for (auto &page : p.pages) { + page.colors.resize(colors); + } + return {}; +} + + +using Palette = PaletteV4; struct CompactPaletteV1 { @@ -64,29 +148,36 @@ struct CompactPaletteV1 { ox::Vector> pages{}; }; -using CompactPalette = CompactPaletteV1; - [[nodiscard]] -constexpr bool valid(Palette const&p) noexcept { - auto const colors = p.colorInfo.size(); - return ox::all_of(p.pages.begin(), p.pages.end(), [colors](auto const&page) { +constexpr bool valid(CompactPaletteV1 const&p) noexcept { + size_t colors{}; + for (auto const&page : p.pages) { + colors = ox::max(colors, page.size()); + } + return ox::all_of(p.pages.begin(), p.pages.end(), [colors](ox::Vector const&page) { return page.size() == colors; }); } -[[nodiscard]] -constexpr ox::Error repair(Palette &p) noexcept { - auto const colors = p.colorInfo.size(); +constexpr ox::Error repair(CompactPaletteV1 &p) noexcept { + size_t colors{}; + for (auto const&page : p.pages) { + colors = ox::max(colors, page.size()); + } for (auto &page : p.pages) { page.resize(colors); } return {}; } + +using CompactPalette = CompactPaletteV1; + + [[nodiscard]] constexpr Color16 color(Palette const&pal, size_t page, size_t idx) noexcept { - if (page < pal.pages.size() && idx < pal.pages[page].size()) [[likely]] { - return pal.pages[page][idx]; + if (page < pal.pages.size() && idx < pal.pages[page].colors.size()) [[likely]] { + return pal.pages[page].colors[idx]; } return 0; } @@ -111,7 +202,7 @@ constexpr Color16 color(CompactPalette const&pal, size_t idx) noexcept { [[nodiscard]] constexpr auto &colors(Palette &pal, size_t page = 0) noexcept { - return pal.pages[page]; + return pal.pages[page].colors; } [[nodiscard]] @@ -132,7 +223,7 @@ constexpr auto &colors(CompactPalette const&pal, size_t page = 0) noexcept { [[nodiscard]] constexpr size_t colorCnt(Palette const&pal, size_t page = 0) noexcept { if (page < pal.pages.size()) [[likely]] { - return pal.pages[page].size(); + return pal.pages[page].colors.size(); } return 0; } @@ -149,7 +240,7 @@ constexpr size_t colorCnt(CompactPalette const&pal, size_t page = 0) noexcept { constexpr size_t largestPage(Palette const&pal) noexcept { size_t out{}; for (auto const&page : pal.pages) { - out = ox::max(out, page.size()); + out = ox::max(out, page.colors.size()); } return out; } @@ -184,6 +275,11 @@ oxModelBegin(PaletteV3) oxModelField(pages) oxModelEnd() +oxModelBegin(PaletteV4) + oxModelField(colorNames) + oxModelField(pages) +oxModelEnd() + oxModelBegin(CompactPaletteV1) oxModelField(pages) oxModelEnd() diff --git a/src/nostalgia/modules/core/src/keel/keelmodule.cpp b/src/nostalgia/modules/core/src/keel/keelmodule.cpp index bc70202..29f829e 100644 --- a/src/nostalgia/modules/core/src/keel/keelmodule.cpp +++ b/src/nostalgia/modules/core/src/keel/keelmodule.cpp @@ -19,6 +19,7 @@ static class: public keel::Module { NostalgiaPaletteToPaletteV1Converter m_nostalgiaPaletteToPaletteV1Converter; PaletteV1ToPaletteV2Converter m_paletteV1ToPaletteV2Converter; PaletteV2ToPaletteV3Converter m_paletteV2ToPaletteV3Converter; + PaletteV3ToPaletteV4Converter m_paletteV3ToPaletteV4Converter; PaletteToCompactPaletteConverter m_paletteToCompactPaletteConverter; TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter; TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter; @@ -41,6 +42,8 @@ static class: public keel::Module { keel::generateTypeDesc, keel::generateTypeDesc, keel::generateTypeDesc, + keel::generateTypeDesc, + keel::generateTypeDesc, keel::generateTypeDesc, }; } @@ -51,6 +54,7 @@ static class: public keel::Module { &m_nostalgiaPaletteToPaletteV1Converter, &m_paletteV1ToPaletteV2Converter, &m_paletteV2ToPaletteV3Converter, + &m_paletteV3ToPaletteV4Converter, &m_paletteToCompactPaletteConverter, &m_tileSheetV1ToTileSheetV2Converter, &m_tileSheetV2ToTileSheetV3Converter, @@ -78,7 +82,8 @@ static class: public keel::Module { if (typeId == ox::ModelTypeId_v || typeId == ox::ModelTypeId_v || typeId == ox::ModelTypeId_v || - typeId == ox::ModelTypeId_v) { + typeId == ox::ModelTypeId_v || + typeId == ox::ModelTypeId_v) { oxReturnError(keel::convertBuffToBuff( ctx, buff, ox::ClawFormat::Metal).moveTo(buff)); return true; diff --git a/src/nostalgia/modules/core/src/keel/typeconv.cpp b/src/nostalgia/modules/core/src/keel/typeconv.cpp index b7d8f31..e28d684 100644 --- a/src/nostalgia/modules/core/src/keel/typeconv.cpp +++ b/src/nostalgia/modules/core/src/keel/typeconv.cpp @@ -28,6 +28,7 @@ ox::Error PaletteV2ToPaletteV3Converter::convert( PaletteV3 &dst) const noexcept { dst.pages = std::move(src.pages); if (!dst.pages.empty()) { + dst.colorInfo.reserve(dst.pages[0].size()); for (size_t i = 0; i < dst.pages[0].size(); ++i) { dst.colorInfo.emplace_back(ox::sfmt("Color {}", i + 1)); } @@ -35,11 +36,33 @@ ox::Error PaletteV2ToPaletteV3Converter::convert( return {}; } +ox::Error PaletteV3ToPaletteV4Converter::convert( + keel::Context&, + PaletteV3 &src, + PaletteV4 &dst) const noexcept { + dst.pages.reserve(src.pages.size()); + for (auto i = 1; auto &page : src.pages) { + dst.pages.emplace_back(ox::sfmt("Page {}", i), std::move(page)); + ++i; + } + dst.colorNames.reserve(src.colorInfo.size()); + for (auto &ci : src.colorInfo) { + dst.colorNames.emplace_back(std::move(ci.name)); + } + return {}; +} + ox::Error PaletteToCompactPaletteConverter::convert( keel::Context&, Palette &src, CompactPalette &dst) const noexcept { - dst.pages = std::move(src.pages); + dst.pages.reserve(src.pages.size()); + for (auto &page : src.pages) { + auto &p = dst.pages.emplace_back(); + for (auto const c : page.colors) { + p.emplace_back(c); + } + } return {}; } diff --git a/src/nostalgia/modules/core/src/keel/typeconv.hpp b/src/nostalgia/modules/core/src/keel/typeconv.hpp index 30347b1..d25fc38 100644 --- a/src/nostalgia/modules/core/src/keel/typeconv.hpp +++ b/src/nostalgia/modules/core/src/keel/typeconv.hpp @@ -28,6 +28,10 @@ class PaletteV2ToPaletteV3Converter: public keel::Converter { + ox::Error convert(keel::Context&, PaletteV3 &src, PaletteV4 &dst) const noexcept final; +}; + class PaletteToCompactPaletteConverter: public keel::Converter { ox::Error convert(keel::Context&, Palette &src, CompactPalette &dst) const noexcept final; }; diff --git a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.cpp b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.cpp index 8faf6a0..f197f1c 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.cpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.cpp @@ -4,8 +4,6 @@ #include -#include - #include #include @@ -17,6 +15,27 @@ namespace nostalgia::core { namespace ig = studio::ig; + +void PaletteEditorImGui::PageRename::draw(turbine::Context &tctx) noexcept { + if (!m_show) { + return; + } + if (ig::BeginPopup(tctx, "Rename Page", m_show)) { + ig::InputText("Name", m_name); + switch (ig::PopupControlsOkCancel(m_show)) { + case ig::PopupResponse::OK: + inputSubmitted.emit(m_name); + [[fallthrough]]; + case ig::PopupResponse::Cancel: + close(); + default: + break; + } + ImGui::EndPopup(); + } +} + + PaletteEditorImGui::PaletteEditorImGui(studio::StudioContext &sctx, ox::StringParam path): Editor(std::move(path)), m_sctx(sctx), @@ -26,10 +45,11 @@ PaletteEditorImGui::PaletteEditorImGui(studio::StudioContext &sctx, ox::StringPa throw OxException(1, "PaletteEditorImGui: invalid Palette object"); } undoStack()->changeTriggered.connect(this, &PaletteEditorImGui::handleCommand); + m_pageRename.inputSubmitted.connect(this, &PaletteEditorImGui::renamePage); } void PaletteEditorImGui::keyStateChanged(turbine::Key key, bool down) { - if (!down) { + if (!down || m_pageRename.isOpen()) { return; } if (key >= turbine::Key::Num_1 && key <= turbine::Key::Num_9) { @@ -49,16 +69,17 @@ void PaletteEditorImGui::keyStateChanged(turbine::Key key, bool down) { void PaletteEditorImGui::draw(studio::StudioContext&) noexcept { auto const paneSize = ImGui::GetContentRegionAvail(); { - ImGui::BeginChild("Pages", ImVec2(250, paneSize.y), true); + ImGui::BeginChild("Pages", {280, paneSize.y}, true); drawPagesEditor(); ImGui::EndChild(); } ImGui::SameLine(); { - ImGui::BeginChild("Colors", ImVec2(-1, paneSize.y), true); + ImGui::BeginChild("Colors", {-1, paneSize.y}, true); drawColorsEditor(); ImGui::EndChild(); } + m_pageRename.draw(m_tctx); } ox::Error PaletteEditorImGui::saveItem() noexcept { @@ -84,7 +105,7 @@ void PaletteEditorImGui::drawColorsEditor() noexcept { auto const colorEditorWidth = 220; static constexpr auto toolbarHeight = 40; { - auto const sz = ImVec2(70, 24); + auto constexpr sz = ImVec2{70, 24}; if (ImGui::Button("Add", sz)) { auto const colorSz = colorCnt(m_pal, m_page); constexpr Color16 c = 0; @@ -126,7 +147,7 @@ void PaletteEditorImGui::drawColorsEditor() noexcept { "Colors", 6, tableFlags, - ImVec2(tblWidth, colorsSz.y - (toolbarHeight + 5))); + {tblWidth, colorsSz.y - (toolbarHeight + 5)}); { ImGui::TableSetupColumn("Idx", ImGuiTableColumnFlags_WidthFixed, 25); ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 100); @@ -135,30 +156,28 @@ void PaletteEditorImGui::drawColorsEditor() noexcept { ImGui::TableSetupColumn("Blue", ImGuiTableColumnFlags_WidthFixed, 40); ImGui::TableSetupColumn("Preview", ImGuiTableColumnFlags_NoHide); ImGui::TableHeadersRow(); - for (auto i = 0u; auto const&c : m_pal.pages[m_page]) { - ImGui::PushID(static_cast(i)); + for (auto i = 0u; auto const&c : m_pal.pages[m_page].colors) { + ig::IDStackItem const idStackItem(static_cast(i)); ImGui::TableNextRow(); drawColumn(i + 1); - drawColumnLeftAlign(m_pal.colorInfo[i].name); + drawColumnLeftAlign(m_pal.colorNames[i]); drawColumn(red16(c)); drawColumn(green16(c)); drawColumn(blue16(c)); ImGui::TableNextColumn(); - auto const ic = ImGui::GetColorU32( - ImVec4(redf(c), greenf(c), bluef(c), 1)); + auto const ic = ImGui::GetColorU32({redf(c), greenf(c), bluef(c), 1}); ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic); if (ImGui::Selectable( "##ColorRow", i == m_selectedColorRow, ImGuiSelectableFlags_SpanAllColumns)) { m_selectedColorRow = i; } - ImGui::PopID(); ++i; } } ImGui::EndTable(); if (colorEditor) { ImGui::SameLine(); - ImGui::BeginChild("ColorEditor", ImVec2(colorEditorWidth, -1), true); + ImGui::BeginChild("ColorEditor", {colorEditorWidth, -1}, true); drawColorEditor(); ImGui::EndChild(); } @@ -168,7 +187,7 @@ void PaletteEditorImGui::drawPagesEditor() noexcept { constexpr auto tableFlags = ImGuiTableFlags_RowBg; auto const paneSz = ImGui::GetContentRegionAvail(); constexpr auto toolbarHeight = 40; - auto const btnSz = ImVec2(paneSz.x / 3 - 5.5f, 24); + auto const btnSz = ImVec2{paneSz.x / 4 - 5.5f, 24}; if (ImGui::Button("Add", btnSz)) { std::ignore = pushCommand(m_pal, 0u, m_pal.pages.size()); m_page = m_pal.pages.size() - 1; @@ -179,26 +198,31 @@ void PaletteEditorImGui::drawPagesEditor() noexcept { m_page = std::min(m_page, m_pal.pages.size() - 1); } ImGui::SameLine(); - if (ImGui::Button("Duplicate", btnSz)) { + if (ImGui::Button("Clone", btnSz)) { std::ignore = pushCommand(m_pal, m_page, m_pal.pages.size()); } + ImGui::SameLine(); + if (ImGui::Button("Rename", btnSz)) { + m_pageRename.show(m_pal.pages[m_page].name); + } ImGui::BeginTable( "PageSelect", 2, tableFlags, - ImVec2(paneSz.x, paneSz.y - (toolbarHeight + 5))); + {paneSz.x, paneSz.y - (toolbarHeight + 5)}); { ImGui::TableSetupColumn("Page", ImGuiTableColumnFlags_WidthFixed, 60); + ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 200); ImGui::TableHeadersRow(); for (auto i = 0u; i < m_pal.pages.size(); ++i) { - ImGui::PushID(static_cast(i)); + ig::IDStackItem const idStackItem(static_cast(i)); ImGui::TableNextRow(); drawColumn(i + 1); + drawColumnLeftAlign(m_pal.pages[i].name); ImGui::SameLine(); if (ImGui::Selectable("##PageRow", i == m_page, ImGuiSelectableFlags_SpanAllColumns)) { m_page = i; } - ImGui::PopID(); } } ImGui::EndTable(); @@ -210,7 +234,7 @@ void PaletteEditorImGui::drawColorEditor() noexcept { int g = green16(c); int b = blue16(c); int const a = alpha16(c); - auto const¤tName = m_pal.colorInfo[m_selectedColorRow].name; + auto const¤tName = m_pal.colorNames[m_selectedColorRow]; ox::IString<50> name; name = currentName; ImGui::InputText("Name", name.data(), name.cap() + 1); @@ -229,12 +253,16 @@ void PaletteEditorImGui::drawColorEditor() noexcept { if (c != newColor) { std::ignore = pushCommand(m_pal, m_page, m_selectedColorRow, newColor); } - if (currentName != name.data()) { + if (currentName != name) { std::ignore = pushCommand( - m_pal, m_selectedColorRow, Palette::ColorInfo{name.data()}); + m_pal, m_selectedColorRow, ox::String{name}); } } +ox::Error PaletteEditorImGui::renamePage(ox::StringView name) noexcept { + return pushCommand(m_pal, m_page, name); +} + ox::Error PaletteEditorImGui::handleCommand(studio::UndoCommand const*cmd) noexcept { if (dynamic_cast(cmd)) { m_page = ox::min(m_page, m_pal.pages.size() - 1); diff --git a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.hpp b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.hpp index 0289f05..feefa08 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.hpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.hpp @@ -14,6 +14,23 @@ namespace nostalgia::core { class PaletteEditorImGui: public studio::Editor { private: + class PageRename { + private: + ox::IString<50> m_name; + bool m_show = false; + public: + ox::Signal inputSubmitted; + constexpr void show(ox::StringView const&name) noexcept { + m_show = true; + m_name = name; + } + constexpr void close() noexcept { + m_show = false; + } + [[nodiscard]] + constexpr bool isOpen() const noexcept { return m_show; } + void draw(turbine::Context &tctx) noexcept; + } m_pageRename; studio::StudioContext &m_sctx; turbine::Context &m_tctx; Palette m_pal; @@ -45,6 +62,8 @@ class PaletteEditorImGui: public studio::Editor { void drawColorEditor() noexcept; + ox::Error renamePage(ox::StringView name) noexcept; + ox::Error handleCommand(studio::UndoCommand const*) noexcept; }; diff --git a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.cpp b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.cpp index 8935748..854bc28 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.cpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.cpp @@ -14,13 +14,13 @@ ApplyColorAllPagesCommand::ApplyColorAllPagesCommand(Palette &pal, size_t const ox::Vector colors; colors.reserve(m_pal.pages.size()); for (auto const&p : m_pal.pages) { - colors.emplace_back(p[m_idx]); + colors.emplace_back(p.colors[m_idx]); } return colors; }()) { auto const c = color(m_pal, m_page, m_idx); - if (ox::all_of(m_pal.pages.begin(), m_pal.pages.end(), [this, c](ox::SpanView const page) { - return page[m_idx] == c; + if (ox::all_of(m_pal.pages.begin(), m_pal.pages.end(), [this, c](PalettePage const&page) { + return page.colors[m_idx] == c; })) { throw studio::NoChangesException(); } @@ -33,26 +33,46 @@ int ApplyColorAllPagesCommand::commandId() const noexcept { ox::Error ApplyColorAllPagesCommand::redo() noexcept { auto const c = color(m_pal, m_page, m_idx); for (auto &page : m_pal.pages) { - page[m_idx] = c; + page.colors[m_idx] = c; } return {}; } ox::Error ApplyColorAllPagesCommand::undo() noexcept { for (size_t p = 0u; auto &page : m_pal.pages) { - page[m_idx] = m_origColors[p]; + page.colors[m_idx] = m_origColors[p]; ++p; } return {}; } +RenamePageCommand::RenamePageCommand(Palette &pal, size_t const page, ox::StringParam name) noexcept: + m_pal(pal), + m_page(page), + m_name{std::move(name)} {} + +int RenamePageCommand::commandId() const noexcept { + return static_cast(PaletteEditorCommandId::RenamePage); +} + +ox::Error RenamePageCommand::redo() noexcept { + std::swap(m_pal.pages[m_page].name, m_name); + return {}; +} + +ox::Error RenamePageCommand::undo() noexcept { + std::swap(m_pal.pages[m_page].name, m_name); + return {}; +} + + DuplicatePageCommand::DuplicatePageCommand(Palette &pal, size_t srcIdx, size_t dstIdx) noexcept: m_pal(pal), m_dstIdx(dstIdx) { auto const&src = m_pal.pages[srcIdx]; - m_page.reserve(src.size()); - for (auto const&s : src) { + m_page.reserve(src.colors.size()); + for (auto const&s : src.colors) { m_page.emplace_back(s); } } @@ -62,12 +82,12 @@ int DuplicatePageCommand::commandId() const noexcept { } ox::Error DuplicatePageCommand::redo() noexcept { - m_pal.pages.emplace(m_dstIdx, std::move(m_page)); + m_pal.pages.emplace(m_dstIdx, "", std::move(m_page)); return {}; } ox::Error DuplicatePageCommand::undo() noexcept { - m_page = std::move(m_pal.pages[m_dstIdx]); + m_page = std::move(m_pal.pages[m_dstIdx].colors); return m_pal.pages.erase(m_dstIdx).error; } @@ -85,7 +105,7 @@ int RemovePageCommand::commandId() const noexcept { } ox::Error RemovePageCommand::redo() noexcept { - m_page = std::move(colors(m_pal, m_idx)); + m_page = std::move(m_pal.pages[m_idx]); return m_pal.pages.erase(m_idx).error; } @@ -105,17 +125,17 @@ int AddColorCommand::commandId() const noexcept { } ox::Error AddColorCommand::redo() noexcept { - m_pal.colorInfo.emplace(m_idx, ox::sfmt("Color {}", m_pal.colorInfo.size() + 1)); + m_pal.colorNames.emplace(m_idx, ox::sfmt("Color {}", m_pal.colorNames.size() + 1)); for (auto &page : m_pal.pages) { - page.emplace(m_idx, m_color); + page.colors.emplace(m_idx, m_color); } return {}; } ox::Error AddColorCommand::undo() noexcept { - oxReturnError(m_pal.colorInfo.erase(m_idx)); + oxReturnError(m_pal.colorNames.erase(m_idx)); for (auto &page : m_pal.pages) { - oxReturnError(page.erase(m_idx)); + oxReturnError(page.colors.erase(m_idx)); } return {}; } @@ -128,7 +148,7 @@ RemoveColorCommand::RemoveColorCommand(Palette &pal, size_t const idx) noexcept: ox::Vector colors; colors.reserve(m_pal.pages.size()); for (auto const&p : m_pal.pages) { - colors.emplace_back(p[m_idx]); + colors.emplace_back(p.colors[m_idx]); } return colors; }()) {} @@ -138,18 +158,18 @@ int RemoveColorCommand::commandId() const noexcept { } ox::Error RemoveColorCommand::redo() noexcept { - m_colorInfo = std::move(m_pal.colorInfo[m_idx]); - oxReturnError(m_pal.colorInfo.erase(m_idx)); + m_colorInfo = std::move(m_pal.colorNames[m_idx]); + oxReturnError(m_pal.colorNames.erase(m_idx)); for (auto &page : m_pal.pages) { - oxReturnError(page.erase(m_idx)); + oxReturnError(page.colors.erase(m_idx)); } return {}; } ox::Error RemoveColorCommand::undo() noexcept { - m_pal.colorInfo.emplace(m_idx, std::move(m_colorInfo)); + m_pal.colorNames.emplace(m_idx, std::move(m_colorInfo)); for (size_t p = 0; auto &page : m_pal.pages) { - page.emplace(m_idx, m_colors[p]); + page.colors.emplace(m_idx, m_colors[p]); ++p; } return {}; @@ -159,11 +179,11 @@ ox::Error RemoveColorCommand::undo() noexcept { UpdateColorInfoCommand::UpdateColorInfoCommand( Palette &pal, size_t idx, - Palette::ColorInfo newColorInfo): + ox::StringParam newColorInfo): m_pal(pal), m_idx(idx), m_altColorInfo(std::move(newColorInfo)) { - if (m_pal.colorInfo[m_idx].name == m_altColorInfo.name) { + if (m_pal.colorNames[m_idx] == m_altColorInfo) { throw studio::NoChangesException(); } } @@ -179,7 +199,6 @@ bool UpdateColorInfoCommand::mergeWith(UndoCommand const&cmd) noexcept { return true; } -[[nodiscard]] int UpdateColorInfoCommand::commandId() const noexcept { return static_cast(PaletteEditorCommandId::UpdateColor); } @@ -195,7 +214,7 @@ ox::Error UpdateColorInfoCommand::undo() noexcept { } void UpdateColorInfoCommand::swap() noexcept { - std::swap(m_pal.colorInfo[m_idx], m_altColorInfo); + std::swap(m_pal.colorNames[m_idx], m_altColorInfo); } @@ -224,7 +243,6 @@ bool UpdateColorCommand::mergeWith(UndoCommand const&cmd) noexcept { return true; } -[[nodiscard]] int UpdateColorCommand::commandId() const noexcept { return static_cast(PaletteEditorCommandId::UpdateColor); } diff --git a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp index 727266d..60efb60 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp @@ -7,13 +7,13 @@ #include #include -#include #include namespace nostalgia::core { enum class PaletteEditorCommandId { ApplyColorAllPages, + RenamePage, DuplicatePage, RemovePage, AddColor, @@ -44,11 +44,31 @@ class ApplyColorAllPagesCommand: public studio::UndoCommand { ox::Error undo() noexcept final; }; +class RenamePageCommand: public studio::UndoCommand { + private: + Palette &m_pal; + size_t m_page = 0; + ox::String m_name; + + public: + RenamePageCommand(Palette &pal, size_t page, ox::StringParam name) noexcept; + + ~RenamePageCommand() noexcept override = default; + + [[nodiscard]] + int commandId() const noexcept final; + + ox::Error redo() noexcept final; + + ox::Error undo() noexcept final; + +}; + class DuplicatePageCommand: public studio::UndoCommand { private: Palette &m_pal; size_t m_dstIdx = 0; - ox::Vector m_page; + ox::Vector m_page; public: DuplicatePageCommand(Palette &pal, size_t srcIdx, size_t dstIdx) noexcept; @@ -71,7 +91,7 @@ class RemovePageCommand: public studio::UndoCommand { private: Palette &m_pal; size_t m_idx = 0; - ox::Vector m_page; + PalettePage m_page; public: RemovePageCommand(Palette &pal, size_t idx) noexcept; @@ -111,7 +131,7 @@ class RemoveColorCommand: public studio::UndoCommand { private: Palette &m_pal; size_t const m_idx = 0; - Palette::ColorInfo m_colorInfo; + ox::String m_colorInfo; ox::Vector const m_colors; public: @@ -132,13 +152,13 @@ class UpdateColorInfoCommand: public studio::UndoCommand { private: Palette &m_pal; size_t const m_idx{}; - Palette::ColorInfo m_altColorInfo; + ox::String m_altColorInfo; public: UpdateColorInfoCommand( Palette &pal, size_t idx, - Palette::ColorInfo newColorInfo); + ox::StringParam newColorInfo); ~UpdateColorInfoCommand() noexcept override = default; @@ -162,7 +182,7 @@ class UpdateColorCommand: public studio::UndoCommand { Palette &m_pal; size_t const m_page = 0; size_t const m_idx{}; - Color16 m_altColor{}; + PaletteColor m_altColor{}; public: UpdateColorCommand( @@ -203,7 +223,6 @@ class MoveColorCommand: public studio::UndoCommand { [[nodiscard]] int commandId() const noexcept override; - public: ox::Error redo() noexcept override; ox::Error undo() noexcept override; diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp index e7d6879..d8df5f5 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp @@ -343,7 +343,7 @@ void TileSheetEditorImGui::showSubsheetEditor() noexcept { } } -ox::Error TileSheetEditorImGui::exportSubhseetToPng(int scale) noexcept { +ox::Error TileSheetEditorImGui::exportSubhseetToPng(int const scale) const noexcept { oxRequire(path, studio::saveFile({{"PNG", "png"}})); // subsheet to png auto const&img = m_model.img(); @@ -441,12 +441,14 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept { auto const pages = m_model.pal().pages.size(); if (pages > 1) { ImGui::Indent(20); - auto numStr = ox::itoa(m_model.palettePage() + 1); + using Str = ox::IString<55>; + auto numStr = ox::sfmt( + "{} - {}", m_model.palettePage() + 1, m_model.pal().pages[m_model.palettePage()].name); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - comboWidthSub); if (ImGui::BeginCombo("Page", numStr.c_str(), 0)) { for (auto n = 0u; n < pages; ++n) { auto const selected = (m_model.palettePage() == n); - numStr = ox::itoa(n + 1); + numStr = ox::sfmt("{} - {}", n + 1, m_model.pal().pages[n].name); if (ImGui::Selectable(numStr.c_str(), selected) && m_model.palettePage() != n) { m_model.setPalettePage(n); } @@ -469,7 +471,7 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept { { auto const&pal = m_model.pal(); if (pal.pages.size() > m_model.palettePage()) { - for (auto i = 0u; auto const&c: pal.pages[m_model.palettePage()]) { + for (auto i = 0u; auto const&c: pal.pages[m_model.palettePage()].colors) { ImGui::PushID(static_cast(i)); // Column: color idx ImGui::TableNextColumn(); @@ -484,7 +486,7 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept { auto ic = ImGui::GetColorU32(ImVec4(redf(c), greenf(c), bluef(c), 1)); ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic); ImGui::TableNextColumn(); - auto const&name = i < pal.colorInfo.size() ? pal.colorInfo[i].name.c_str() : ""; + auto const&name = i < pal.colorNames.size() ? pal.colorNames[i].c_str() : ""; ImGui::Text("%s", name); ImGui::TableNextColumn(); ImGui::Text("(%02d, %02d, %02d)", red16(c), green16(c), blue16(c)); diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp index 251a27c..f891208 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp @@ -97,7 +97,7 @@ class TileSheetEditorImGui: public studio::Editor { private: void showSubsheetEditor() noexcept; - ox::Error exportSubhseetToPng(int scale) noexcept; + ox::Error exportSubhseetToPng(int scale) const noexcept; void drawTileSheet(ox::Vec2 const&fbSize) noexcept; diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp index be546ea..740ea19 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp @@ -27,8 +27,8 @@ namespace nostalgia::core { Palette const TileSheetEditorModel::s_defaultPalette = { - .colorInfo = {ox::Vector{{}}}, - .pages = {{ox::Vector(128)}}, + .colorNames = {ox::Vector{{}}}, + .pages = {{"Page 1", ox::Vector(128)}}, }; // delete pixels of all non-leaf nodes diff --git a/src/olympic/studio/applib/src/aboutpopup.cpp b/src/olympic/studio/applib/src/aboutpopup.cpp index 6bbd2c7..0a5ca95 100644 --- a/src/olympic/studio/applib/src/aboutpopup.cpp +++ b/src/olympic/studio/applib/src/aboutpopup.cpp @@ -29,7 +29,7 @@ bool AboutPopup::isOpen() const noexcept { return m_stage == Stage::Open; } -void AboutPopup::draw(studio::StudioContext &sctx) noexcept { +void AboutPopup::draw(StudioContext &sctx) noexcept { switch (m_stage) { case Stage::Closed: break; @@ -40,15 +40,14 @@ void AboutPopup::draw(studio::StudioContext &sctx) noexcept { case Stage::Open: { constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; - ImGui::SetNextWindowSize(ImVec2(215, 90)); - studio::ig::centerNextWindow(sctx.tctx); + ig::centerNextWindow(sctx.tctx); auto open = true; if (ImGui::BeginPopupModal("About", &open, modalFlags)) { ImGui::Text("%s", m_text.c_str()); ImGui::NewLine(); - ImGui::Dummy(ImVec2(148.0f, 0.0f)); + ImGui::Dummy({148.0f, 0.0f}); ImGui::SameLine(); - if (ImGui::Button("Close")) { + if (ig::PushButton("Close")) { ImGui::CloseCurrentPopup(); open = false; } diff --git a/src/olympic/studio/modlib/include/studio/context.hpp b/src/olympic/studio/modlib/include/studio/context.hpp index 21cb042..16ca8d1 100644 --- a/src/olympic/studio/modlib/include/studio/context.hpp +++ b/src/olympic/studio/modlib/include/studio/context.hpp @@ -18,7 +18,7 @@ struct StudioContext { StudioUI &ui; Project *project = nullptr; turbine::Context &tctx; - inline StudioContext(StudioUI &pUi, turbine::Context &pTctx) noexcept: + StudioContext(StudioUI &pUi, turbine::Context &pTctx) noexcept: ui(pUi), tctx(pTctx) {} }; diff --git a/src/olympic/studio/modlib/include/studio/imguiutil.hpp b/src/olympic/studio/modlib/include/studio/imguiutil.hpp index bab5e7d..e005390 100644 --- a/src/olympic/studio/modlib/include/studio/imguiutil.hpp +++ b/src/olympic/studio/modlib/include/studio/imguiutil.hpp @@ -45,10 +45,10 @@ class DragDropSource { private: bool const m_active{}; public: - inline DragDropSource() noexcept: + DragDropSource() noexcept: m_active(ImGui::BeginDragDropSource()) { } - inline ~DragDropSource() noexcept { + ~DragDropSource() noexcept { if (m_active) { ImGui::EndDragDropSource(); } @@ -58,7 +58,7 @@ class DragDropSource { } }; -inline auto dragDropSource(auto const&cb) noexcept { +auto dragDropSource(auto const&cb) noexcept { if constexpr(ox::is_same_v) { if (ig::DragDropSource const tgt; tgt) [[unlikely]] { return cb(); @@ -75,10 +75,10 @@ class DragDropTarget { private: bool const m_active{}; public: - inline DragDropTarget() noexcept: + DragDropTarget() noexcept: m_active(ImGui::BeginDragDropTarget()) { } - inline ~DragDropTarget() noexcept { + ~DragDropTarget() noexcept { if (m_active) { ImGui::EndDragDropTarget(); } @@ -128,6 +128,21 @@ void centerNextWindow(turbine::Context &ctx) noexcept; bool PushButton(ox::CStringView lbl, ImVec2 const&btnSz = BtnSz) noexcept; +template +bool InputText( + ox::CStringView label, + ox::IString &text, + ImGuiInputTextFlags const flags = 0, + ImGuiInputTextCallback const callback = nullptr, + void *user_data = nullptr) noexcept { + auto const out = ImGui::InputText( + label.c_str(), text.data(), StrCap + 1, flags, callback, user_data); + if (out) { + std::ignore = text.unsafeResize(ox::strlen(text.c_str())); + } + return out; +} + enum class PopupResponse { None, OK, @@ -136,6 +151,8 @@ enum class PopupResponse { PopupResponse PopupControlsOkCancel(float popupWidth, bool &popupOpen); +PopupResponse PopupControlsOkCancel(bool &popupOpen); + [[nodiscard]] bool BeginPopup(turbine::Context &ctx, ox::CStringView popupName, bool &show, ImVec2 const&sz = {285, 0}); diff --git a/src/olympic/studio/modlib/src/imguiutil.cpp b/src/olympic/studio/modlib/src/imguiutil.cpp index 0af15b9..72c9898 100644 --- a/src/olympic/studio/modlib/src/imguiutil.cpp +++ b/src/olympic/studio/modlib/src/imguiutil.cpp @@ -73,9 +73,13 @@ PopupResponse PopupControlsOkCancel(float popupWidth, bool &popupOpen) { return out; } +PopupResponse PopupControlsOkCancel(bool &popupOpen) { + return PopupControlsOkCancel(ImGui::GetContentRegionAvail().x + 17, popupOpen); +} + bool BeginPopup(turbine::Context &ctx, ox::CStringView popupName, bool &show, ImVec2 const&sz) { constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize; - ig::centerNextWindow(ctx); + centerNextWindow(ctx); ImGui::OpenPopup(popupName.c_str()); ImGui::SetNextWindowSize(sz); return ImGui::BeginPopupModal(popupName.c_str(), &show, modalFlags); @@ -122,23 +126,11 @@ bool ComboBox( bool FileComboBox( ox::CStringView lbl, - studio::StudioContext &sctx, + 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; + return ComboBox(lbl, list, selectedIdx); } bool ListBox( @@ -164,14 +156,14 @@ bool ListBox( } bool ListBox(ox::CStringView name, ox::SpanView const&list, size_t &selIdx) noexcept { - return ig::ListBox(name, [list](size_t i) -> ox::CStringView { + return ListBox(name, [list](size_t i) -> ox::CStringView { return list[i]; }, list.size(), selIdx); } FilePicker::FilePicker( - studio::StudioContext &sctx, + StudioContext &sctx, ox::String title, ox::String fileExt, ImVec2 const&size) noexcept: @@ -186,12 +178,12 @@ void FilePicker::draw() noexcept { 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)) { + IDStackItem const idStackItem(m_title); + if (BeginPopup(m_sctx.tctx, m_title, 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) { + ComboBox(m_title, list, selIdx); + if (PopupControlsOkCancel(popupSz.x, m_show) == ig::PopupResponse::OK) { filePicked.emit(list[selIdx]); } ImGui::EndPopup();