diff --git a/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp b/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp index 0d3e34e5..37974d61 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp @@ -112,12 +112,12 @@ int tileRows(Context&) noexcept; ox::Error loadBgPalette( Context &ctx, size_t palBank, - Palette const&palette, + CompactPalette const&palette, size_t page = 0) noexcept; ox::Error loadSpritePalette( Context &ctx, - Palette const&palette, + CompactPalette const&palette, size_t page = 0) noexcept; ox::Error loadBgPalette( diff --git a/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp b/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp index 72f97859..454c8745 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp @@ -36,7 +36,43 @@ struct PaletteV2 { ox::Vector<ox::Vector<Color16>> pages; }; -using Palette = PaletteV2; +struct PaletteV3 { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette"; + static constexpr auto TypeVersion = 3; + static constexpr auto Preloadable = true; + struct ColorInfo { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette.ColorInfo"; + 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)) {} + }; + ox::Vector<ColorInfo> colorInfo; + ox::Vector<ox::Vector<Color16>> pages; +}; + +using Palette = PaletteV3; + + +struct CompactPaletteV1 { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette"; + static constexpr auto TypeVersion = 2; + static constexpr auto Preloadable = true; + ox::Vector<ox::Vector<Color16>> 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) { + return page.size() == colors; + }); +} [[nodiscard]] constexpr Color16 color(Palette const&pal, size_t page, size_t idx) noexcept { @@ -47,13 +83,53 @@ constexpr Color16 color(Palette const&pal, size_t page, size_t idx) noexcept { } [[nodiscard]] -constexpr Color16 color(Palette const&pal, size_t idx) noexcept { - auto constexpr page = 0; - return color(pal, page, idx); +constexpr Color16 color(CompactPalette 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]; + } + return 0; } [[nodiscard]] -constexpr size_t colors(Palette const&pal, size_t page = 0) noexcept { +constexpr Color16 color(Palette const&pal, size_t idx) noexcept { + return color(pal, 0, idx); +} + +[[nodiscard]] +constexpr Color16 color(CompactPalette const&pal, size_t idx) noexcept { + return color(pal, 0, idx); +} + +[[nodiscard]] +constexpr auto &colors(Palette &pal, size_t page = 0) noexcept { + return pal.pages[page]; +} + +[[nodiscard]] +constexpr auto &colors(CompactPalette &pal, size_t page = 0) noexcept { + return pal.pages[page]; +} + +[[nodiscard]] +constexpr auto &colors(Palette const&pal, size_t page = 0) noexcept { + return pal.pages[page]; +} + +[[nodiscard]] +constexpr auto &colors(CompactPalette const&pal, size_t page = 0) noexcept { + return pal.pages[page]; +} + +[[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 0; +} + +[[nodiscard]] +constexpr size_t colorCnt(CompactPalette const&pal, size_t page = 0) noexcept { if (page < pal.pages.size()) [[likely]] { return pal.pages[page].size(); } @@ -69,6 +145,15 @@ constexpr size_t largestPage(Palette const&pal) noexcept { return out; } +[[nodiscard]] +constexpr size_t largestPage(CompactPalette const&pal) noexcept { + size_t out{}; + for (auto const&page : pal.pages) { + out = ox::max(out, page.size()); + } + return out; +} + oxModelBegin(NostalgiaPalette) oxModelField(colors) oxModelEnd() @@ -81,4 +166,17 @@ oxModelBegin(PaletteV2) oxModelField(pages) oxModelEnd() +oxModelBegin(PaletteV3::ColorInfo) + oxModelField(name) +oxModelEnd() + +oxModelBegin(PaletteV3) + oxModelField(colorInfo) + oxModelField(pages) +oxModelEnd() + +oxModelBegin(CompactPaletteV1) + oxModelField(pages) +oxModelEnd() + } diff --git a/src/nostalgia/modules/core/src/gba/gfx.cpp b/src/nostalgia/modules/core/src/gba/gfx.cpp index 5ac60af1..fb738660 100644 --- a/src/nostalgia/modules/core/src/gba/gfx.cpp +++ b/src/nostalgia/modules/core/src/gba/gfx.cpp @@ -136,13 +136,13 @@ ox::Error initGfx(Context&, InitParams const&) noexcept { ox::Error loadBgPalette( Context&, size_t palBank, - Palette const&palette, + CompactPalette const&palette, size_t page) noexcept { if (palette.pages.empty()) { return {}; } auto const paletteMem = MEM_BG_PALETTE + palBank * 16; - for (auto i = 0u; i < colors(palette, page); ++i) { + for (auto i = 0u; i < colorCnt(palette, page); ++i) { paletteMem[i] = color(palette, page, i); } return {}; @@ -150,13 +150,13 @@ ox::Error loadBgPalette( ox::Error loadSpritePalette( Context&, - Palette const&palette, + CompactPalette const&palette, size_t page) noexcept { if (palette.pages.empty()) { return {}; } auto const paletteMem = MEM_SPRITE_PALETTE; - for (auto i = 0u; i < colors(palette, page); ++i) { + for (auto i = 0u; i < colorCnt(palette, page); ++i) { paletteMem[i] = color(palette, page, i); } return {}; @@ -166,14 +166,14 @@ ox::Error loadBgPalette( Context &ctx, size_t palBank, ox::FileAddress const&paletteAddr) noexcept { - oxRequire(pal, keel::readObj<Palette>(keelCtx(ctx), paletteAddr)); + oxRequire(pal, keel::readObj<CompactPalette>(keelCtx(ctx), paletteAddr)); return loadBgPalette(ctx, palBank, *pal, 0); } ox::Error loadSpritePalette( Context &ctx, ox::FileAddress const&paletteAddr) noexcept { - oxRequire(pal, keel::readObj<Palette>(keelCtx(ctx), paletteAddr)); + oxRequire(pal, keel::readObj<CompactPalette>(keelCtx(ctx), paletteAddr)); return loadSpritePalette(ctx, *pal, 0); } diff --git a/src/nostalgia/modules/core/src/keel/keelmodule.cpp b/src/nostalgia/modules/core/src/keel/keelmodule.cpp index 140dfa71..ff457c4c 100644 --- a/src/nostalgia/modules/core/src/keel/keelmodule.cpp +++ b/src/nostalgia/modules/core/src/keel/keelmodule.cpp @@ -18,6 +18,8 @@ static class: public keel::Module { private: NostalgiaPaletteToPaletteV1Converter m_nostalgiaPaletteToPaletteV1Converter; PaletteV1ToPaletteV2Converter m_paletteV1ToPaletteV2Converter; + PaletteV2ToPaletteV3Converter m_paletteV2ToPaletteV3Converter; + PaletteToCompactPaletteConverter m_paletteToCompactPaletteConverter; TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter; TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter; TileSheetV3ToTileSheetV4Converter m_tileSheetV3ToTileSheetV4Converter; @@ -47,6 +49,8 @@ static class: public keel::Module { return { &m_nostalgiaPaletteToPaletteV1Converter, &m_paletteV1ToPaletteV2Converter, + &m_paletteV2ToPaletteV3Converter, + &m_paletteToCompactPaletteConverter, &m_tileSheetV1ToTileSheetV2Converter, &m_tileSheetV2ToTileSheetV3Converter, &m_tileSheetV3ToTileSheetV4Converter, @@ -71,8 +75,10 @@ static class: public keel::Module { }, [](keel::Context &ctx, ox::Buffer &buff, ox::StringView typeId) -> ox::Result<bool> { if (typeId == ox::ModelTypeId_v<NostalgiaPalette> || - typeId == ox::ModelTypeId_v<PaletteV1>) { - oxReturnError(keel::convertBuffToBuff<Palette>( + typeId == ox::ModelTypeId_v<PaletteV1> || + typeId == ox::ModelTypeId_v<PaletteV2> || + typeId == ox::ModelTypeId_v<PaletteV3>) { + oxReturnError(keel::convertBuffToBuff<CompactPalette>( 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 7df8d0a2..61287324 100644 --- a/src/nostalgia/modules/core/src/keel/typeconv.cpp +++ b/src/nostalgia/modules/core/src/keel/typeconv.cpp @@ -22,6 +22,27 @@ ox::Error PaletteV1ToPaletteV2Converter::convert( return {}; } +ox::Error PaletteV2ToPaletteV3Converter::convert( + keel::Context&, + PaletteV2 &src, + PaletteV3 &dst) const noexcept { + dst.pages = std::move(src.pages); + if (!dst.pages.empty()) { + for (size_t i = 0; i < dst.pages[0].size(); ++i) { + dst.colorInfo.emplace_back(ox::sfmt("Color {}", i)); + } + } + return {}; +} + +ox::Error PaletteToCompactPaletteConverter::convert( + keel::Context&, + Palette &src, + CompactPalette &dst) const noexcept { + dst.pages = std::move(src.pages); + return {}; +} + ox::Error TileSheetV1ToTileSheetV2Converter::convert( keel::Context&, TileSheetV1 &src, diff --git a/src/nostalgia/modules/core/src/keel/typeconv.hpp b/src/nostalgia/modules/core/src/keel/typeconv.hpp index b7b47722..30347b11 100644 --- a/src/nostalgia/modules/core/src/keel/typeconv.hpp +++ b/src/nostalgia/modules/core/src/keel/typeconv.hpp @@ -21,7 +21,15 @@ class NostalgiaPaletteToPaletteV1Converter: public keel::Converter<NostalgiaPale }; class PaletteV1ToPaletteV2Converter: public keel::Converter<PaletteV1, PaletteV2> { - ox::Error convert(keel::Context&, PaletteV1 &src, PaletteV2 &dst) const noexcept final; + ox::Error convert(keel::Context&, PaletteV1 &src, PaletteV2 &dst) const noexcept final; +}; + +class PaletteV2ToPaletteV3Converter: public keel::Converter<PaletteV2, PaletteV3> { + ox::Error convert(keel::Context&, PaletteV2 &src, PaletteV3 &dst) const noexcept final; +}; + +class PaletteToCompactPaletteConverter: public keel::Converter<Palette, CompactPalette> { + ox::Error convert(keel::Context&, Palette &src, CompactPalette &dst) const noexcept final; }; class TileSheetV1ToTileSheetV2Converter: public keel::Converter<TileSheetV1, TileSheetV2> { diff --git a/src/nostalgia/modules/core/src/opengl/gfx.cpp b/src/nostalgia/modules/core/src/opengl/gfx.cpp index b9e04721..19f77a4a 100644 --- a/src/nostalgia/modules/core/src/opengl/gfx.cpp +++ b/src/nostalgia/modules/core/src/opengl/gfx.cpp @@ -364,7 +364,7 @@ static void loadPalette( ox::Array<GLfloat, 1024> &palette, size_t palOffset, GLuint shaderPgrm, - Palette const&pal, + CompactPalette const&pal, size_t page = 0) noexcept { static constexpr std::size_t ColorCnt = 256; for (auto i = palOffset; auto const c : pal.pages[page]) { @@ -516,7 +516,7 @@ static ox::Result<TileSheetData> normalizeTileSheet( ox::Error loadBgPalette( Context &ctx, size_t palBank, - Palette const&palette, + CompactPalette const&palette, size_t page) noexcept { renderer::loadPalette(ctx.bgPalette, palBank * 16 * 4, ctx.bgShader, palette, page); return {}; @@ -524,7 +524,7 @@ ox::Error loadBgPalette( ox::Error loadSpritePalette( Context &ctx, - Palette const&palette, + CompactPalette const&palette, size_t page) noexcept { ox::Array<GLfloat, 1024> pal; renderer::loadPalette(pal, 0, ctx.spriteShader, palette, page); @@ -536,7 +536,7 @@ ox::Error loadBgPalette( size_t palBank, ox::FileAddress const&paletteAddr) noexcept { auto &kctx = keelCtx(ctx.turbineCtx); - oxRequire(palette, readObj<Palette>(kctx, paletteAddr)); + oxRequire(palette, readObj<CompactPalette>(kctx, paletteAddr)); renderer::loadPalette(ctx.bgPalette, palBank * 16 * 4, ctx.bgShader, *palette); return {}; } @@ -545,7 +545,7 @@ ox::Error loadSpritePalette( Context &ctx, ox::FileAddress const&paletteAddr) noexcept { auto &kctx = keelCtx(ctx.turbineCtx); - oxRequire(palette, readObj<Palette>(kctx, paletteAddr)); + oxRequire(palette, readObj<CompactPalette>(kctx, paletteAddr)); ox::Array<GLfloat, 1024> pal; renderer::loadPalette(pal, 0, ctx.spriteShader, *palette); return {}; 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 c21a50d6..383cd61d 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.cpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.cpp @@ -15,11 +15,16 @@ namespace nostalgia::core { -PaletteEditorImGui::PaletteEditorImGui(studio::StudioContext &sctx, ox::CRStringView path): - Editor(path), - m_sctx(sctx), - m_tctx(sctx.tctx), - m_pal(*keel::readObj<Palette>(keelCtx(m_tctx), ox::FileAddress(itemPath())).unwrapThrow()) { +namespace ig = studio::ig; + +PaletteEditorImGui::PaletteEditorImGui(studio::StudioContext &sctx, ox::StringView const path): + Editor(path), + m_sctx(sctx), + m_tctx(sctx.tctx), + m_pal(*keel::readObj<Palette>(keelCtx(m_tctx), itemPath()).unwrapThrow()) { + if (!valid(m_pal)) { + throw OxException(1, "PaletteEditorImGui: invalid Palette object"); + } undoStack()->changeTriggered.connect(this, &PaletteEditorImGui::handleCommand); } @@ -36,10 +41,9 @@ void PaletteEditorImGui::keyStateChanged(turbine::Key key, bool down) { if (turbine::buttonDown(m_tctx, turbine::Key::Mod_Alt)) { m_selectedColorRow = ox::min<std::size_t>( - static_cast<uint32_t>(key - turbine::Key::Num_1 + 9), m_pal.pages.size() - 1); + static_cast<uint32_t>(key - turbine::Key::Num_1 + 9), m_pal.pages.size() - 1); } } - } void PaletteEditorImGui::draw(studio::StudioContext&) noexcept { @@ -58,7 +62,7 @@ void PaletteEditorImGui::draw(studio::StudioContext&) noexcept { } ox::Error PaletteEditorImGui::saveItem() noexcept { - return m_sctx.project->writeObj(itemPath(), m_pal); + return m_sctx.project->writeObj(itemPath(), m_pal, ox::ClawFormat::Organic); } void PaletteEditorImGui::drawColumn(ox::CStringView txt) noexcept { @@ -71,42 +75,39 @@ void PaletteEditorImGui::drawColumn(ox::CStringView txt) noexcept { void PaletteEditorImGui::drawColorsEditor() noexcept { constexpr auto tableFlags = ImGuiTableFlags_RowBg; auto const colorsSz = ImGui::GetContentRegionAvail(); - auto const colorEditor = m_selectedColorRow < colors(m_pal, m_page); + auto const colorEditor = m_selectedColorRow < colorCnt(m_pal, m_page); auto const colorEditorWidth = 220; static constexpr auto toolbarHeight = 40; { auto const sz = ImVec2(70, 24); if (ImGui::Button("Add", sz)) { - auto const colorSz = static_cast<int>(colors(m_pal, m_page)); + auto const colorSz = colorCnt(m_pal, m_page); constexpr Color16 c = 0; - std::ignore = undoStack()->push(ox::make_unique<AddColorCommand>(&m_pal, c, m_page, colorSz)); + std::ignore = pushCommand<AddColorCommand>(m_pal, c, colorSz); } ImGui::SameLine(); - ImGui::BeginDisabled(m_selectedColorRow >= colors(m_pal, m_page)); + ImGui::BeginDisabled(m_selectedColorRow >= colorCnt(m_pal, m_page)); { if (ImGui::Button("Remove", sz)) { - std::ignore = undoStack()->push( - ox::make_unique<RemoveColorCommand>( - &m_pal, - color(m_pal, m_page, static_cast<std::size_t>(m_selectedColorRow)), - m_page, - static_cast<int>(m_selectedColorRow))); - m_selectedColorRow = ox::min(colors(m_pal, m_page) - 1, m_selectedColorRow); + std::ignore = pushCommand<RemoveColorCommand>(m_pal, m_selectedColorRow); + m_selectedColorRow = ox::min(colorCnt(m_pal, m_page) - 1, m_selectedColorRow); } ImGui::SameLine(); ImGui::BeginDisabled(m_selectedColorRow <= 0); { if (ImGui::Button("Move Up", sz)) { - std::ignore = undoStack()->push(ox::make_unique<MoveColorCommand>(&m_pal, m_page, m_selectedColorRow, -1)); + std::ignore = pushCommand<MoveColorCommand>( + m_pal, m_page, m_selectedColorRow, m_selectedColorRow - 1); --m_selectedColorRow; } } ImGui::EndDisabled(); ImGui::SameLine(); - ImGui::BeginDisabled(m_selectedColorRow >= colors(m_pal, m_page) - 1); + ImGui::BeginDisabled(m_selectedColorRow >= colorCnt(m_pal, m_page) - 1); { if (ImGui::Button("Move Down", sz)) { - std::ignore = undoStack()->push(ox::make_unique<MoveColorCommand>(&m_pal, m_page, m_selectedColorRow, 1)); + std::ignore = pushCommand<MoveColorCommand>( + m_pal, m_page, m_selectedColorRow, m_selectedColorRow + 1); ++m_selectedColorRow; } } @@ -114,8 +115,13 @@ void PaletteEditorImGui::drawColorsEditor() noexcept { } ImGui::EndDisabled(); } - auto const tblWidth = (colorsSz.x - colorEditorWidth - 8) * colorEditor; - ImGui::BeginTable("Colors", 5, tableFlags, ImVec2(tblWidth, colorsSz.y - (toolbarHeight + 5))); + auto const tblWidth = (colorsSz.x - static_cast<float>(colorEditorWidth) - 8.f) + * static_cast<float>(colorEditor); + ImGui::BeginTable( + "Colors", + 5, + tableFlags, + ImVec2(tblWidth, colorsSz.y - (toolbarHeight + 5))); { ImGui::TableSetupColumn("Idx", ImGuiTableColumnFlags_WidthFixed, 25); ImGui::TableSetupColumn("Red", ImGuiTableColumnFlags_WidthFixed, 50); @@ -123,17 +129,19 @@ void PaletteEditorImGui::drawColorsEditor() noexcept { ImGui::TableSetupColumn("Blue", ImGuiTableColumnFlags_WidthFixed, 50); ImGui::TableSetupColumn("Color Preview", ImGuiTableColumnFlags_NoHide); ImGui::TableHeadersRow(); - for (auto i = 0u; auto const c : m_pal.pages[m_page]) { + for (auto i = 0u; auto const&c : m_pal.pages[m_page]) { ImGui::PushID(static_cast<int>(i)); ImGui::TableNextRow(); - drawColumn(i); + drawColumn(i + 1); 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( + ImVec4(redf(c), greenf(c), bluef(c), 1)); ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic); - if (ImGui::Selectable("##ColorRow", i == m_selectedColorRow, ImGuiSelectableFlags_SpanAllColumns)) { + if (ImGui::Selectable( + "##ColorRow", i == m_selectedColorRow, ImGuiSelectableFlags_SpanAllColumns)) { m_selectedColorRow = i; } ImGui::PopID(); @@ -155,28 +163,30 @@ void PaletteEditorImGui::drawPagesEditor() noexcept { constexpr auto toolbarHeight = 40; auto const btnSz = ImVec2(paneSz.x / 3 - 5.5f, 24); if (ImGui::Button("Add", btnSz)) { - std::ignore = undoStack()->push(ox::make_unique<AddPageCommand>(m_pal)); + std::ignore = pushCommand<DuplicatePageCommand>(m_pal, 0u, m_pal.pages.size()); m_page = m_pal.pages.size() - 1; } ImGui::SameLine(); if (ImGui::Button("Remove", btnSz)) { - std::ignore = undoStack()->push(ox::make_unique<RemovePageCommand>(m_pal, m_page)); + std::ignore = pushCommand<RemovePageCommand>(m_pal, m_page); m_page = std::min(m_page, m_pal.pages.size() - 1); } ImGui::SameLine(); if (ImGui::Button("Duplicate", btnSz)) { - std::ignore = undoStack()->push(ox::make_unique<DuplicatePageCommand>(m_pal, m_page, m_pal.pages.size())); + std::ignore = pushCommand<DuplicatePageCommand>(m_pal, m_page, m_pal.pages.size()); } - ImGui::BeginTable("PageSelect", 2, tableFlags, ImVec2(paneSz.x, paneSz.y - (toolbarHeight + 5))); + ImGui::BeginTable( + "PageSelect", + 2, + tableFlags, + ImVec2(paneSz.x, paneSz.y - (toolbarHeight + 5))); { ImGui::TableSetupColumn("Page", ImGuiTableColumnFlags_WidthFixed, 60); - ImGui::TableSetupColumn("Colors", ImGuiTableColumnFlags_NoHide); ImGui::TableHeadersRow(); for (auto i = 0u; i < m_pal.pages.size(); ++i) { ImGui::PushID(static_cast<int>(i)); ImGui::TableNextRow(); drawColumn(i + 1); - drawColumn(colors(m_pal, i)); ImGui::SameLine(); if (ImGui::Selectable("##PageRow", i == m_page, ImGuiSelectableFlags_SpanAllColumns)) { m_page = i; @@ -193,20 +203,33 @@ 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; + ox::IString<50> name; + name = currentName; + ImGui::InputText("Name", name.data(), name.cap() + 1); + ImGui::Separator(); ImGui::InputInt("Red", &r, 1, 5); ImGui::InputInt("Green", &g, 1, 5); ImGui::InputInt("Blue", &b, 1, 5); + if (ig::PushButton("Apply to all pages", {-1, ig::BtnSz.y})) { + std::ignore = pushCommand<ApplyColorAllPagesCommand>( + m_pal, m_page, m_selectedColorRow); + } + r = ox::max(r, 0); + g = ox::max(g, 0); + b = ox::max(b, 0); auto const newColor = color16(r, g, b, a); if (c != newColor) { - std::ignore = undoStack()->push(ox::make_unique<UpdateColorCommand>( - &m_pal, m_page, static_cast<int>(m_selectedColorRow), c, newColor)); + std::ignore = pushCommand<UpdateColorCommand>(m_pal, m_page, m_selectedColorRow, newColor); + } + if (currentName != name.data()) { + std::ignore = pushCommand<UpdateColorInfoCommand>( + m_pal, m_selectedColorRow, Palette::ColorInfo{name.data()}); } } ox::Error PaletteEditorImGui::handleCommand(studio::UndoCommand const*cmd) noexcept { - if (dynamic_cast<AddPageCommand const*>(cmd)) { - m_page = m_pal.pages.size() - 1; - } else if (dynamic_cast<RemovePageCommand const*>(cmd)) { + if (dynamic_cast<RemovePageCommand const*>(cmd)) { m_page = ox::min(m_page, m_pal.pages.size() - 1); } else if (auto const dupPageCmd = dynamic_cast<DuplicatePageCommand const*>(cmd)) { m_page = ox::clamp<size_t>(dupPageCmd->insertIdx(), 0, 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 1a828efe..649f32ae 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.hpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.hpp @@ -21,7 +21,7 @@ class PaletteEditorImGui: public studio::Editor { size_t m_page = 0; public: - PaletteEditorImGui(studio::StudioContext &sctx, ox::CRStringView path); + PaletteEditorImGui(studio::StudioContext &sctx, ox::StringView path); void keyStateChanged(turbine::Key key, bool down) override; diff --git a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.cpp b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.cpp index 6cc3d691..1a4acd05 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.cpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.cpp @@ -6,21 +6,44 @@ namespace nostalgia::core { -AddPageCommand::AddPageCommand(Palette &pal) noexcept: - m_pal(pal) { +ApplyColorAllPagesCommand::ApplyColorAllPagesCommand(Palette &pal, size_t const page, size_t const idx): + m_pal(pal), + m_page(page), + m_idx(idx), + m_origColors([this] { + ox::Vector<Color16> colors; + colors.reserve(m_pal.pages.size()); + for (auto const&p : m_pal.pages) { + colors.emplace_back(p[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<Color16> const page) { + return page[m_idx] == c; + })) { + throw studio::NoChangesException(); + } } -int AddPageCommand::commandId() const noexcept { - return static_cast<int>(PaletteEditorCommandId::AddPage); +int ApplyColorAllPagesCommand::commandId() const noexcept { + return static_cast<int>(PaletteEditorCommandId::ApplyColorAllPages); } -ox::Error AddPageCommand::redo() noexcept { - m_pal.pages.emplace_back(); +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; + } return {}; } -ox::Error AddPageCommand::undo() noexcept { - return m_pal.pages.erase(static_cast<std::size_t>(m_pal.pages.size() - 1)).error; +ox::Error ApplyColorAllPagesCommand::undo() noexcept { + for (size_t p = 0u; auto &page : m_pal.pages) { + page[m_idx] = m_origColors[p]; + ++p; + } + return {}; } @@ -55,78 +78,134 @@ size_t DuplicatePageCommand::insertIdx() const noexcept { RemovePageCommand::RemovePageCommand(Palette &pal, size_t idx) noexcept: m_pal(pal), - m_idx(idx) { -} + m_idx(idx) {} int RemovePageCommand::commandId() const noexcept { return static_cast<int>(PaletteEditorCommandId::RemovePage); } ox::Error RemovePageCommand::redo() noexcept { - m_page = std::move(m_pal.pages[m_idx]); + m_page = std::move(colors(m_pal, m_idx)); return m_pal.pages.erase(static_cast<std::size_t>(m_idx)).error; } ox::Error RemovePageCommand::undo() noexcept { - m_pal.pages.insert(m_idx, std::move(m_page)); + m_pal.pages.emplace(m_idx, std::move(m_page)); return {}; } -AddColorCommand::AddColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept { - m_pal = pal; - m_color = color; - m_page = page; - m_idx = idx; -} +AddColorCommand::AddColorCommand(Palette &pal, Color16 const color, size_t const idx) noexcept: + m_pal(pal), + m_color(color), + m_idx(idx) {} int AddColorCommand::commandId() const noexcept { return static_cast<int>(PaletteEditorCommandId::AddColor); } ox::Error AddColorCommand::redo() noexcept { - m_pal->pages[m_page].insert(static_cast<std::size_t>(m_idx), m_color); + for (auto &page : m_pal.pages) { + page.emplace(static_cast<size_t>(m_idx), m_color); + } return {}; } ox::Error AddColorCommand::undo() noexcept { - return m_pal->pages[m_page].erase(static_cast<std::size_t>(m_idx)).error; + for (auto &page : m_pal.pages) { + oxReturnError(page.erase(static_cast<std::size_t>(m_idx))); + } + return {}; } -RemoveColorCommand::RemoveColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept { - m_pal = pal; - m_color = color; - m_page = page; - m_idx = idx; -} +RemoveColorCommand::RemoveColorCommand(Palette &pal, size_t const idx) noexcept: + m_pal(pal), + m_idx(idx), + m_colors([this] { + ox::Vector<Color16> colors; + colors.reserve(m_pal.pages.size()); + for (auto const&p : m_pal.pages) { + colors.emplace_back(p[m_idx]); + } + return colors; + }()) {} int RemoveColorCommand::commandId() const noexcept { return static_cast<int>(PaletteEditorCommandId::RemoveColor); } ox::Error RemoveColorCommand::redo() noexcept { - return m_pal->pages[m_page].erase(static_cast<std::size_t>(m_idx)).error; + for (auto &page : m_pal.pages) { + oxReturnError(page.erase(m_idx)); + } + return {}; } ox::Error RemoveColorCommand::undo() noexcept { - m_pal->pages[m_page].insert(static_cast<std::size_t>(m_idx), m_color); + for (size_t p = 0; auto &page : m_pal.pages) { + page.emplace(m_idx, m_colors[p]); + ++p; + } return {}; } +UpdateColorInfoCommand::UpdateColorInfoCommand( + Palette &pal, + size_t idx, + Palette::ColorInfo newColorInfo): + m_pal(pal), + m_idx(idx), + m_altColorInfo(std::move(newColorInfo)) { + if (m_pal.colorInfo[m_idx].name == m_altColorInfo.name) { + throw studio::NoChangesException(); + } +} + +bool UpdateColorInfoCommand::mergeWith(UndoCommand const&cmd) noexcept { + if (cmd.commandId() != static_cast<int>(PaletteEditorCommandId::UpdateColor)) { + return false; + } + auto ucCmd = static_cast<UpdateColorInfoCommand const*>(&cmd); + if (m_idx != ucCmd->m_idx) { + return false; + } + return true; +} + +[[nodiscard]] +int UpdateColorInfoCommand::commandId() const noexcept { + return static_cast<int>(PaletteEditorCommandId::UpdateColor); +} + +ox::Error UpdateColorInfoCommand::redo() noexcept { + swap(); + return {}; +} + +ox::Error UpdateColorInfoCommand::undo() noexcept { + swap(); + return {}; +} + +void UpdateColorInfoCommand::swap() noexcept { + std::swap(m_pal.colorInfo[m_idx], m_altColorInfo); +} + + UpdateColorCommand::UpdateColorCommand( - Palette *pal, - size_t page, - int idx, - Color16 oldColor, - Color16 newColor) noexcept { - m_pal = pal; - m_page = page; - m_idx = idx; - m_oldColor = oldColor; - m_newColor = newColor; - //setObsolete(m_oldColor == m_newColor); + Palette &pal, + size_t page, + size_t idx, + Color16 newColor): + m_pal(pal), + m_page(page), + m_idx(idx), + m_altColor(newColor) { + if (color(m_pal, m_page, m_idx) == newColor) { + throw studio::NoChangesException(); + } } bool UpdateColorCommand::mergeWith(UndoCommand const&cmd) noexcept { @@ -137,7 +216,6 @@ bool UpdateColorCommand::mergeWith(UndoCommand const&cmd) noexcept { if (m_idx != ucCmd->m_idx) { return false; } - m_newColor = ucCmd->m_newColor; return true; } @@ -147,41 +225,46 @@ int UpdateColorCommand::commandId() const noexcept { } ox::Error UpdateColorCommand::redo() noexcept { - m_pal->pages[m_page][static_cast<std::size_t>(m_idx)] = m_newColor; + swap(); return {}; } ox::Error UpdateColorCommand::undo() noexcept { - m_pal->pages[m_page][static_cast<std::size_t>(m_idx)] = m_oldColor; + swap(); return {}; } - -MoveColorCommand::MoveColorCommand(Palette *pal, size_t page, std::size_t idx, int offset) noexcept { - m_pal = pal; - m_page = page; - m_idx = idx; - m_offset = offset; +void UpdateColorCommand::swap() noexcept { + auto &dst = colors(m_pal, m_page)[m_idx]; + std::swap(dst, m_altColor); } + +MoveColorCommand::MoveColorCommand( + Palette &pal, size_t page, size_t srcIdx, size_t dstIdx) noexcept: + m_pal(pal), + m_page(page), + m_srcIdx(srcIdx), + m_dstIdx(dstIdx) {} + int MoveColorCommand::commandId() const noexcept { return static_cast<int>(PaletteEditorCommandId::MoveColor); } ox::Error MoveColorCommand::redo() noexcept { - moveColor(static_cast<int>(m_idx), m_offset); + moveColor(m_srcIdx, m_dstIdx); return {}; } ox::Error MoveColorCommand::undo() noexcept { - moveColor(static_cast<int>(m_idx) + m_offset, -m_offset); + moveColor(m_dstIdx, m_srcIdx); return {}; } -void MoveColorCommand::moveColor(int idx, int offset) noexcept { - const auto c = m_pal->pages[m_page][static_cast<std::size_t>(idx)]; - std::ignore = m_pal->pages[m_page].erase(static_cast<std::size_t>(idx)); - m_pal->pages[m_page].insert(static_cast<std::size_t>(idx + offset), c); +void MoveColorCommand::moveColor(size_t srcIdx, size_t dstIdx) noexcept { + auto const c = color(m_pal, m_page, srcIdx); + std::ignore = colors(m_pal, m_page).erase(srcIdx); + colors(m_pal, m_page).emplace(dstIdx, c); } } diff --git a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp index 75c0115e..a12db670 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp @@ -13,24 +13,28 @@ namespace nostalgia::core { enum class PaletteEditorCommandId { - AddPage, + ApplyColorAllPages, DuplicatePage, RemovePage, AddColor, RemoveColor, + UpdateColorInfo, UpdateColor, MoveColor, }; -class AddPageCommand: public studio::UndoCommand { +class ApplyColorAllPagesCommand: public studio::UndoCommand { private: Palette &m_pal; + size_t const m_page{}; + size_t const m_idx{}; + ox::Vector<Color16> const m_origColors; public: - AddPageCommand(Palette &pal) noexcept; + ApplyColorAllPagesCommand(Palette &pal, size_t page, size_t idx); - ~AddPageCommand() noexcept override = default; + ~ApplyColorAllPagesCommand() noexcept override = default; [[nodiscard]] int commandId() const noexcept final; @@ -38,7 +42,6 @@ class AddPageCommand: public studio::UndoCommand { ox::Error redo() noexcept final; ox::Error undo() noexcept final; - }; class DuplicatePageCommand: public studio::UndoCommand { @@ -86,13 +89,12 @@ class RemovePageCommand: public studio::UndoCommand { class AddColorCommand: public studio::UndoCommand { private: - Palette *m_pal = nullptr; + Palette &m_pal; Color16 m_color = 0; - int m_idx = -1; - size_t m_page = 0; + size_t const m_idx = 0; public: - AddColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept; + AddColorCommand(Palette &pal, Color16 color, size_t idx) noexcept; ~AddColorCommand() noexcept override = default; @@ -107,13 +109,12 @@ class AddColorCommand: public studio::UndoCommand { class RemoveColorCommand: public studio::UndoCommand { private: - Palette *m_pal = nullptr; - Color16 m_color = 0; - size_t m_page = 0; - int m_idx = -1; + Palette &m_pal; + size_t const m_idx = 0; + ox::Vector<Color16> const m_colors; public: - RemoveColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept; + RemoveColorCommand(Palette &pal, size_t idx) noexcept; ~RemoveColorCommand() noexcept override = default; @@ -126,16 +127,48 @@ class RemoveColorCommand: public studio::UndoCommand { }; -class UpdateColorCommand: public studio::UndoCommand { +class UpdateColorInfoCommand: public studio::UndoCommand { private: - Palette *m_pal = nullptr; - Color16 m_oldColor = 0; - Color16 m_newColor = 0; - size_t m_page = 0; - int m_idx = -1; + Palette &m_pal; + size_t const m_idx{}; + Palette::ColorInfo m_altColorInfo; public: - UpdateColorCommand(Palette *pal, size_t page, int idx, Color16 oldColor, Color16 newColor) noexcept; + UpdateColorInfoCommand( + Palette &pal, + size_t idx, + Palette::ColorInfo newColorInfo); + + ~UpdateColorInfoCommand() noexcept override = default; + + [[nodiscard]] + bool mergeWith(const UndoCommand &cmd) noexcept final; + + [[nodiscard]] + int commandId() const noexcept final; + + ox::Error redo() noexcept final; + + ox::Error undo() noexcept final; + + private: + void swap() noexcept; + +}; + +class UpdateColorCommand: public studio::UndoCommand { + private: + Palette &m_pal; + size_t const m_page = 0; + size_t const m_idx{}; + Color16 m_altColor{}; + + public: + UpdateColorCommand( + Palette &pal, + size_t page, + size_t idx, + Color16 newColor); ~UpdateColorCommand() noexcept override = default; @@ -149,17 +182,20 @@ class UpdateColorCommand: public studio::UndoCommand { ox::Error undo() noexcept final; + private: + void swap() noexcept; + }; class MoveColorCommand: public studio::UndoCommand { private: - Palette *m_pal = nullptr; - size_t m_page = 0; - std::size_t m_idx = 0; - int m_offset = 0; + Palette &m_pal; + size_t const m_page = 0; + std::size_t const m_srcIdx = 0; + std::size_t const m_dstIdx = 0; public: - MoveColorCommand(Palette *pal, size_t page, std::size_t idx, int offset) noexcept; + MoveColorCommand(Palette &pal, size_t page, size_t srcIdx, size_t dstIdx) noexcept; ~MoveColorCommand() noexcept override = default; @@ -172,7 +208,7 @@ class MoveColorCommand: public studio::UndoCommand { ox::Error undo() noexcept override; private: - void moveColor(int idx, int offset) noexcept; + void moveColor(size_t srcIdx, size_t dstIdx) noexcept; }; } 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 4d6260e9..75a03783 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp @@ -7,6 +7,7 @@ #include <ox/std/point.hpp> #include <keel/media.hpp> +#include <studio/studio.hpp> #include "tilesheeteditor-imgui.hpp" @@ -14,6 +15,36 @@ namespace nostalgia::core { namespace ig = studio::ig; +static ox::String configName(ox::StringView str) noexcept { + auto out = ox::String{str}; + for (auto &c : out) { + if (c == '/' || c == '\\') { + c = '%'; + } + } + return out; +} + +struct TileSheetEditorConfig { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetEditorConfig"; + static constexpr auto TypeVersion = 1; + TileSheet::SubSheetIdx activeSubsheet{}; +}; + +oxModelBegin(TileSheetEditorConfig) + oxModelFieldRename(activeSubsheet, active_subsheet) +oxModelEnd() + +struct TileSheetEditorConfigs { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetEditorConfigs"; + static constexpr auto TypeVersion = 1; + ox::HashMap<ox::String, TileSheetEditorConfig> configs; +}; + +oxModelBegin(TileSheetEditorConfigs) + oxModelField(configs) +oxModelEnd() + static ox::Vector<uint32_t> normalizePixelSizes( ox::Vector<uint8_t> const&inPixels, int const bpp) noexcept { @@ -75,7 +106,7 @@ static ox::Error toPngFile( 8))); } -TileSheetEditorImGui::TileSheetEditorImGui(studio::StudioContext &sctx, ox::CRStringView path): +TileSheetEditorImGui::TileSheetEditorImGui(studio::StudioContext &sctx, ox::StringView const path): Editor(path), m_sctx(sctx), m_tctx(m_sctx.tctx), @@ -87,6 +118,12 @@ TileSheetEditorImGui::TileSheetEditorImGui(studio::StudioContext &sctx, ox::CRSt m_subsheetEditor.inputSubmitted.connect(this, &TileSheetEditorImGui::updateActiveSubsheet); m_exportMenu.inputSubmitted.connect(this, &TileSheetEditorImGui::exportSubhseetToPng); m_model.paletteChanged.connect(this, &TileSheetEditorImGui::setPaletteSelection); + // load config + auto const&config = studio::readConfig<TileSheetEditorConfig>( + keelCtx(m_sctx), configName(itemPath())); + if (config.ok()) { + m_model.setActiveSubsheet(validateSubSheetIdx(m_model.img(), config.value.activeSubsheet)); + } } void TileSheetEditorImGui::exportFile() { @@ -120,7 +157,7 @@ void TileSheetEditorImGui::keyStateChanged(turbine::Key key, bool down) { auto const popupOpen = m_subsheetEditor.isOpen() && m_exportMenu.isOpen(); auto const pal = m_model.pal(); if (!popupOpen) { - auto const colorCnt = pal.pages[m_model.palettePage()].size(); + auto const colorCnt = core::colorCnt(pal, m_model.palettePage()); if (key == turbine::Key::Alpha_D) { m_tool = TileSheetTool::Draw; setCopyEnabled(false); @@ -144,7 +181,8 @@ void TileSheetEditorImGui::keyStateChanged(turbine::Key key, bool down) { static_cast<uint32_t>(key - turbine::Key::Num_1), m_model.pal().pages.size() - 1); m_model.setPalettePage(idx); } else if (key <= turbine::Key::Num_0 + colorCnt) { - auto const idx = ox::min<std::size_t>(static_cast<uint32_t>(key - turbine::Key::Num_1), colorCnt - 1); + auto const idx = ox::min<std::size_t>( + static_cast<uint32_t>(key - turbine::Key::Num_1), colorCnt - 1); m_view.setPalIdx(idx); } } else if (key == turbine::Key::Num_0) { @@ -208,7 +246,7 @@ void TileSheetEditorImGui::draw(studio::StudioContext&) noexcept { auto const&parent = m_model.activeSubSheet(); m_model.addSubsheet(insertOnIdx); insertOnIdx.emplace_back(parent.subsheets.size() - 1); - m_model.setActiveSubsheet(insertOnIdx); + setActiveSubsheet(insertOnIdx); } ImGui::SameLine(); if (ig::PushButton("-", btnSize)) { @@ -241,7 +279,7 @@ void TileSheetEditorImGui::draw(studio::StudioContext&) noexcept { } ImGui::EndChild(); m_subsheetEditor.draw(m_tctx); - m_exportMenu.draw(m_sctx); + m_exportMenu.draw(m_tctx); } void TileSheetEditorImGui::drawSubsheetSelector( @@ -261,7 +299,7 @@ void TileSheetEditorImGui::drawSubsheetSelector( auto const open = ImGui::TreeNodeEx(lbl.c_str(), flags); ImGui::SameLine(); if (ImGui::IsItemClicked()) { - m_model.setActiveSubsheet(path); + setActiveSubsheet(path); } if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsItemHovered()) { showSubsheetEditor(); @@ -432,31 +470,35 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept { ImGui::Indent(-20); } // header - if (ImGui::BeginTable("PaletteTable", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp)) { + if (ImGui::BeginTable( + "PaletteTable", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("No.", 0, 0.45f); ImGui::TableSetupColumn("", 0, 0.22f); ImGui::TableSetupColumn("Color16", 0, 3); ImGui::TableHeadersRow(); { auto const&pal = m_model.pal(); - for (auto i = 0u; auto c: pal.pages[m_model.palettePage()]) { - ImGui::PushID(static_cast<int>(i)); - // Column: color idx - ImGui::TableNextColumn(); - auto const label = ox::itoa(i + 1); - auto const rowSelected = i == m_view.palIdx(); - if (ImGui::Selectable(label.c_str(), rowSelected, ImGuiSelectableFlags_SpanAllColumns)) { - m_view.setPalIdx(i); + if (pal.pages.size() > m_model.palettePage()) { + for (auto i = 0u; auto const&c: pal.pages[m_model.palettePage()]) { + ImGui::PushID(static_cast<int>(i)); + // Column: color idx + ImGui::TableNextColumn(); + auto const label = ox::itoa(i + 1); + auto const rowSelected = i == m_view.palIdx(); + if (ImGui::Selectable( + label.c_str(), rowSelected, ImGuiSelectableFlags_SpanAllColumns)) { + m_view.setPalIdx(i); + } + // Column: color RGB + ImGui::TableNextColumn(); + auto ic = ImGui::GetColorU32(ImVec4(redf(c), greenf(c), bluef(c), 1)); + ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic); + ImGui::TableNextColumn(); + ImGui::Text("(%02d, %02d, %02d)", red16(c), green16(c), blue16(c)); + ImGui::TableNextRow(); + ImGui::PopID(); + ++i; } - // Column: color RGB - ImGui::TableNextColumn(); - auto ic = ImGui::GetColorU32(ImVec4(redf(c), greenf(c), bluef(c), 1)); - ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic); - ImGui::TableNextColumn(); - ImGui::Text("(%02d, %02d, %02d)", red16(c), green16(c), blue16(c)); - ImGui::TableNextRow(); - ImGui::PopID(); - ++i; } } ImGui::EndTable(); @@ -480,12 +522,20 @@ ox::Error TileSheetEditorImGui::setPaletteSelection() noexcept { return {}; } +void TileSheetEditorImGui::setActiveSubsheet(TileSheet::SubSheetIdx path) noexcept { + m_model.setActiveSubsheet(path); + studio::editConfig<TileSheetEditorConfig>(keelCtx(m_sctx), configName(itemPath()), + [&path](TileSheetEditorConfig *config) { + config->activeSubsheet = std::move(path); + }); +} + ox::Error TileSheetEditorImGui::markUnsavedChanges(studio::UndoCommand const*) noexcept { setUnsavedChanges(true); return {}; } -void TileSheetEditorImGui::SubSheetEditor::draw(turbine::Context &sctx) noexcept { +void TileSheetEditorImGui::SubSheetEditor::draw(turbine::Context &tctx) noexcept { constexpr auto popupName = "Edit Subsheet"; if (!m_show) { return; @@ -494,7 +544,7 @@ void TileSheetEditorImGui::SubSheetEditor::draw(turbine::Context &sctx) noexcept auto constexpr popupWidth = 235.f; auto const popupHeight = modSize ? 130.f : 85.f; auto const popupSz = ImVec2(popupWidth, popupHeight); - if (ig::BeginPopup(sctx, popupName, m_show, popupSz)) { + if (ig::BeginPopup(tctx, popupName, m_show, popupSz)) { ImGui::InputText("Name", m_name.data(), m_name.cap()); if (modSize) { ImGui::InputInt("Columns", &m_cols); @@ -511,7 +561,7 @@ void TileSheetEditorImGui::SubSheetEditor::close() noexcept { m_show = false; } -void TileSheetEditorImGui::ExportMenu::draw(studio::StudioContext &sctx) noexcept { +void TileSheetEditorImGui::ExportMenu::draw(turbine::Context &tctx) noexcept { constexpr auto popupName = "Export Tile Sheet"; if (!m_show) { return; @@ -519,7 +569,7 @@ void TileSheetEditorImGui::ExportMenu::draw(studio::StudioContext &sctx) noexcep constexpr auto popupWidth = 235.f; constexpr auto popupHeight = 85.f; constexpr auto popupSz = ImVec2(popupWidth, popupHeight); - if (ig::BeginPopup(sctx.tctx, popupName, m_show, popupSz)) { + if (ig::BeginPopup(tctx, popupName, m_show, popupSz)) { ImGui::InputInt("Scale", &m_scale); m_scale = ox::clamp(m_scale, 1, 50); if (ig::PopupControlsOkCancel(popupWidth, m_show) == ig::PopupResponse::OK) { 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 fbdebb7f..deb45d47 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp @@ -48,7 +48,7 @@ class TileSheetEditorImGui: public studio::Editor { m_show = true; m_scale = 5; } - void draw(studio::StudioContext &sctx) noexcept; + void draw(turbine::Context &sctx) noexcept; void close() noexcept; [[nodiscard]] inline bool isOpen() const noexcept { return m_show; } @@ -67,7 +67,7 @@ class TileSheetEditorImGui: public studio::Editor { TileSheetTool m_tool = TileSheetTool::Draw; public: - TileSheetEditorImGui(studio::StudioContext &sctx, ox::CRStringView path); + TileSheetEditorImGui(studio::StudioContext &sctx, ox::StringView path); ~TileSheetEditorImGui() override = default; @@ -111,6 +111,8 @@ class TileSheetEditorImGui: public studio::Editor { private: ox::Error markUnsavedChanges(studio::UndoCommand const*) noexcept; + void setActiveSubsheet(TileSheet::SubSheetIdx path) noexcept; + }; } diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp index 510532ac..f94d68d1 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp @@ -27,7 +27,8 @@ namespace nostalgia::core { Palette const TileSheetEditorModel::s_defaultPalette = { - .pages = {ox::Vector<Color16>(128)}, + .colorInfo = {ox::Vector<Palette::ColorInfo>{{}}}, + .pages = {{ox::Vector<Color16>(128)}}, }; // delete pixels of all non-leaf nodes