From 5433fd9b1dd9238260be0a37317610c467fd0206 Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Wed, 17 Jan 2024 01:30:29 -0600 Subject: [PATCH] [nostalgia/core] Add new version of Palette with pages --- .../core/include/nostalgia/core/context.hpp | 4 + .../core/include/nostalgia/core/gfx.hpp | 12 + .../core/include/nostalgia/core/palette.hpp | 49 +++- .../modules/core/src/gba/context.cpp | 10 + src/nostalgia/modules/core/src/gba/gfx.cpp | 68 ++--- .../modules/core/src/keel/keelmodule.cpp | 20 +- .../modules/core/src/keel/typeconv.cpp | 12 +- .../modules/core/src/keel/typeconv.hpp | 8 +- .../modules/core/src/opengl/context.cpp | 8 + src/nostalgia/modules/core/src/opengl/gfx.cpp | 24 +- .../paletteeditor/paletteeditor-imgui.cpp | 269 +++++++++++------- .../paletteeditor/paletteeditor-imgui.hpp | 15 +- .../studio/paletteeditor/paletteeditor.cpp | 99 ++++++- .../studio/paletteeditor/paletteeditor.hpp | 76 ++++- .../tilesheeteditor/tilesheeteditor-imgui.cpp | 52 +++- .../tilesheeteditor/tilesheeteditor-imgui.hpp | 1 + .../tilesheeteditor/tilesheeteditormodel.cpp | 14 +- .../tilesheeteditor/tilesheeteditormodel.hpp | 16 +- .../tilesheeteditor/tilesheetpixels.cpp | 2 +- 19 files changed, 566 insertions(+), 193 deletions(-) diff --git a/src/nostalgia/modules/core/include/nostalgia/core/context.hpp b/src/nostalgia/modules/core/include/nostalgia/core/context.hpp index 1c21992f..e71b23d2 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/context.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/context.hpp @@ -25,5 +25,9 @@ using ContextUPtr = ox::UPtr; ox::Result init(turbine::Context &tctx, InitParams const¶ms = {}) noexcept; +keel::Context &keelCtx(Context &ctx) noexcept; + +turbine::Context &turbineCtx(Context &ctx) noexcept; + } diff --git a/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp b/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp index b2b902bf..90340117 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/gfx.hpp @@ -10,6 +10,7 @@ #include #include "context.hpp" +#include "palette.hpp" namespace nostalgia::core { @@ -100,6 +101,17 @@ oxModelBegin(TileSheetSet) oxModelField(entries) oxModelEnd() +ox::Error loadBgPalette( + Context &ctx, + size_t palBank, + Palette const&palette, + size_t page = 0) noexcept; + +ox::Error loadSpritePalette( + Context &ctx, + Palette const&palette, + size_t page = 0) noexcept; + ox::Error loadBgPalette( Context &ctx, size_t palBank, diff --git a/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp b/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp index b9a13706..06eba728 100644 --- a/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp +++ b/src/nostalgia/modules/core/include/nostalgia/core/palette.hpp @@ -11,6 +11,7 @@ #include #include +#include #include "color.hpp" @@ -22,25 +23,53 @@ struct NostalgiaPalette { ox::Vector colors = {}; }; -struct Palette { +struct PaletteV1 { static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette"; static constexpr auto TypeVersion = 1; - ox::Vector colors = {}; - [[nodiscard]] - constexpr Color16 color(auto idx) const noexcept { - if (idx < colors.size()) [[likely]] { - return colors[idx]; - } - return 0; - } + ox::Vector colors; }; +struct PaletteV2 { + static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette"; + static constexpr auto TypeVersion = 2; + static constexpr auto Preloadable = true; + ox::Vector> pages; +}; + +using Palette = PaletteV2; + +[[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]; + } + return 0; +} + +[[nodiscard]] +constexpr Color16 color(Palette const&pal, size_t idx) noexcept { + auto constexpr page = 0; + return color(pal, page, idx); +} + +[[nodiscard]] +constexpr size_t colors(Palette const&pal, size_t page = 0) noexcept { + if (page < pal.pages.size()) [[likely]] { + return pal.pages[page].size(); + } + return 0; +} + oxModelBegin(NostalgiaPalette) oxModelField(colors) oxModelEnd() -oxModelBegin(Palette) +oxModelBegin(PaletteV1) oxModelField(colors) oxModelEnd() +oxModelBegin(PaletteV2) + oxModelField(pages) +oxModelEnd() + } diff --git a/src/nostalgia/modules/core/src/gba/context.cpp b/src/nostalgia/modules/core/src/gba/context.cpp index e156239d..2d99f862 100644 --- a/src/nostalgia/modules/core/src/gba/context.cpp +++ b/src/nostalgia/modules/core/src/gba/context.cpp @@ -2,6 +2,8 @@ * Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved. */ +#include + #include #include "context.hpp" @@ -23,4 +25,12 @@ ox::Result init(turbine::Context &tctx, InitParams const¶ms) no return ContextUPtr(std::move(ctx)); } +keel::Context &keelCtx(Context &ctx) noexcept { + return turbine::keelCtx(ctx.turbineCtx); +} + +turbine::Context &turbineCtx(Context &ctx) noexcept { + return ctx.turbineCtx; +} + } \ No newline at end of file diff --git a/src/nostalgia/modules/core/src/gba/gfx.cpp b/src/nostalgia/modules/core/src/gba/gfx.cpp index 3c2a8046..308be953 100644 --- a/src/nostalgia/modules/core/src/gba/gfx.cpp +++ b/src/nostalgia/modules/core/src/gba/gfx.cpp @@ -10,6 +10,7 @@ #include #include +#include #include #include @@ -25,12 +26,6 @@ constexpr auto GbaTileColumns = 32; constexpr auto GbaTileRows = 32; constexpr auto SpriteCount = 128; -struct GbaPaletteTarget { - static constexpr auto TypeName = Palette::TypeName; - static constexpr auto TypeVersion = Palette::TypeVersion; - volatile uint16_t *palette = nullptr; -}; - struct GbaTileMapTarget { static constexpr auto TypeName = CompactTileSheet::TypeName; static constexpr auto TypeVersion = CompactTileSheet::TypeVersion; @@ -44,22 +39,6 @@ struct GbaTileMapTarget { TileSheetSetEntry const*setEntry = nullptr; }; -constexpr ox::Error model(auto *io, ox::CommonPtrWith auto *t) noexcept { - oxReturnError(io->template setTypeInfo()); - if (t->palette) { - const auto colorHandler = [t](std::size_t i, const Color16 *c) { - t->palette[i] = *c; - return ox::Error{}; - }; - return io->template field("colors", colorHandler); - } else { - constexpr auto colorHandler = [](std::size_t, const Color16*) { - return ox::Error{}; - }; - return io->template field("colors", colorHandler); - } -} - [[nodiscard]] static bool loadPixel(TileSheetSetEntry const&setEntry, size_t §ionIdx, int tileIdx) noexcept { if (setEntry.sections.size() <= sectionIdx) { @@ -156,27 +135,48 @@ ox::Error initGfx(Context&, InitParams const&) noexcept { return {}; } +ox::Error loadBgPalette( + Context&, + size_t palBank, + Palette 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) { + paletteMem[i] = color(palette, page, i); + } + return {}; +} + +ox::Error loadSpritePalette( + Context&, + Palette 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) { + paletteMem[i] = color(palette, page, i); + } + return {}; +} + ox::Error loadBgPalette( Context &ctx, size_t palBank, ox::FileAddress const&paletteAddr) noexcept { - auto &rom = ctx.rom(); - GbaPaletteTarget const palTarget{.palette = MEM_BG_PALETTE + palBank * 16}; - oxRequire(palStat, rom.stat(paletteAddr)); - oxRequire(pal, rom.directAccess(paletteAddr)); - oxReturnError(ox::readMC(pal, static_cast(palStat.size), &palTarget)); - return {}; + oxRequire(pal, keel::readObj(keelCtx(ctx), paletteAddr)); + return loadBgPalette(ctx, palBank, *pal, 0); } ox::Error loadSpritePalette( Context &ctx, ox::FileAddress const&paletteAddr) noexcept { - auto &rom = ctx.rom(); - GbaPaletteTarget const palTarget{.palette = MEM_SPRITE_PALETTE}; - oxRequire(palStat, rom.stat(paletteAddr)); - oxRequire(pal, rom.directAccess(paletteAddr)); - oxReturnError(ox::readMC(pal, static_cast(palStat.size), &palTarget)); - return {}; + oxRequire(pal, keel::readObj(keelCtx(ctx), paletteAddr)); + return loadSpritePalette(ctx, *pal, 0); } static ox::Error loadTileSheetSet( diff --git a/src/nostalgia/modules/core/src/keel/keelmodule.cpp b/src/nostalgia/modules/core/src/keel/keelmodule.cpp index 8e71dbd8..7488528b 100644 --- a/src/nostalgia/modules/core/src/keel/keelmodule.cpp +++ b/src/nostalgia/modules/core/src/keel/keelmodule.cpp @@ -16,7 +16,8 @@ namespace nostalgia::core { class KeelModule: public keel::Module { private: - NostalgiaPaletteToPaletteConverter m_nostalgiaPaletteToPaletteConverter; + NostalgiaPaletteToPaletteV1Converter m_nostalgiaPaletteToPaletteV1Converter; + PaletteV1ToPaletteV2Converter m_paletteV1ToPaletteV2Converter; TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter; TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter; TileSheetV3ToTileSheetV4Converter m_tileSheetV3ToTileSheetV4Converter; @@ -36,14 +37,16 @@ class KeelModule: public keel::Module { keel::generateTypeDesc, keel::generateTypeDesc, keel::generateTypeDesc, - keel::generateTypeDesc, + keel::generateTypeDesc, + keel::generateTypeDesc, }; } [[nodiscard]] ox::Vector converters() const noexcept final { return { - &m_nostalgiaPaletteToPaletteConverter, + &m_nostalgiaPaletteToPaletteV1Converter, + &m_paletteV1ToPaletteV2Converter, &m_tileSheetV1ToTileSheetV2Converter, &m_tileSheetV2ToTileSheetV3Converter, &m_tileSheetV3ToTileSheetV4Converter, @@ -68,6 +71,17 @@ class KeelModule: public keel::Module { } return {}; }, + [](keel::Context &ctx, ox::Buffer &buff) -> ox::Error { + oxRequire(hdr, keel::readAssetHeader(buff)); + auto const typeId = ox::buildTypeId( + hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams); + if (typeId == ox::buildTypeId() || + typeId == ox::buildTypeId()) { + oxReturnError(keel::convertBuffToBuff( + ctx, buff, ox::ClawFormat::Metal).moveTo(buff)); + } + return {}; + }, }; } }; diff --git a/src/nostalgia/modules/core/src/keel/typeconv.cpp b/src/nostalgia/modules/core/src/keel/typeconv.cpp index 5c8dde79..7df8d0a2 100644 --- a/src/nostalgia/modules/core/src/keel/typeconv.cpp +++ b/src/nostalgia/modules/core/src/keel/typeconv.cpp @@ -6,14 +6,22 @@ namespace nostalgia::core { -ox::Error NostalgiaPaletteToPaletteConverter::convert( +ox::Error NostalgiaPaletteToPaletteV1Converter::convert( keel::Context&, NostalgiaPalette &src, - Palette &dst) const noexcept { + PaletteV1 &dst) const noexcept { dst.colors = std::move(src.colors); return {}; } +ox::Error PaletteV1ToPaletteV2Converter::convert( + keel::Context&, + PaletteV1 &src, + PaletteV2 &dst) const noexcept { + dst.pages.emplace_back(std::move(src.colors)); + 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 7e7e9782..7c27fa7d 100644 --- a/src/nostalgia/modules/core/src/keel/typeconv.hpp +++ b/src/nostalgia/modules/core/src/keel/typeconv.hpp @@ -16,8 +16,12 @@ namespace nostalgia::core { // Type converters -class NostalgiaPaletteToPaletteConverter: public keel::Converter { - ox::Error convert(keel::Context&, NostalgiaPalette &src, Palette &dst) const noexcept final; +class NostalgiaPaletteToPaletteV1Converter: public keel::Converter { + ox::Error convert(keel::Context&, NostalgiaPalette &src, PaletteV1 &dst) const noexcept final; +}; + +class PaletteV1ToPaletteV2Converter: public keel::Converter { + ox::Error convert(keel::Context&, PaletteV1 &src, PaletteV2 &dst) const noexcept final; }; class TileSheetV1ToTileSheetV2Converter: public keel::Converter { diff --git a/src/nostalgia/modules/core/src/opengl/context.cpp b/src/nostalgia/modules/core/src/opengl/context.cpp index b4c3bedd..8f410300 100644 --- a/src/nostalgia/modules/core/src/opengl/context.cpp +++ b/src/nostalgia/modules/core/src/opengl/context.cpp @@ -29,4 +29,12 @@ ox::Result init(turbine::Context &tctx, InitParams const¶ms) no return ContextUPtr(ctx.release()); } +keel::Context &keelCtx(Context &ctx) noexcept { + return turbine::keelCtx(ctx.turbineCtx); +} + +turbine::Context &turbineCtx(Context &ctx) noexcept { + return ctx.turbineCtx; +} + } diff --git a/src/nostalgia/modules/core/src/opengl/gfx.cpp b/src/nostalgia/modules/core/src/opengl/gfx.cpp index 97f3e3d9..2a5add06 100644 --- a/src/nostalgia/modules/core/src/opengl/gfx.cpp +++ b/src/nostalgia/modules/core/src/opengl/gfx.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include "context.hpp" @@ -359,9 +360,10 @@ static void loadPalette( ox::Array &palette, size_t palOffset, GLuint shaderPgrm, - Palette const&pal) noexcept { + Palette const&pal, + size_t page = 0) noexcept { static constexpr std::size_t ColorCnt = 256; - for (auto i = palOffset; auto const c : pal.colors) { + for (auto i = palOffset; auto const c : pal.pages[page]) { palette[i++] = redf(c); palette[i++] = greenf(c); palette[i++] = bluef(c); @@ -506,6 +508,24 @@ static ox::Result normalizeTileSheet( return TileSheetData{std::move(pixels), width, height}; } +ox::Error loadBgPalette( + Context &ctx, + size_t palBank, + Palette const&palette, + size_t page) noexcept { + renderer::loadPalette(ctx.bgPalette, palBank * 16 * 4, ctx.bgShader, palette, page); + return {}; +} + +ox::Error loadSpritePalette( + Context &ctx, + Palette const&palette, + size_t page) noexcept { + ox::Array pal; + renderer::loadPalette(pal, 0, ctx.spriteShader, palette, page); + return {}; +} + ox::Error loadBgPalette( Context &ctx, size_t palBank, 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 d6dba694..bd7ccc2e 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.cpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.cpp @@ -19,112 +19,20 @@ PaletteEditorImGui::PaletteEditorImGui(turbine::Context &ctx, ox::CRStringView p Editor(path), m_ctx(ctx), m_pal(*keel::readObj(keelCtx(m_ctx), ox::FileAddress(itemPath())).unwrapThrow()) { + undoStack()->changeTriggered.connect(this, &PaletteEditorImGui::handleCommand); } void PaletteEditorImGui::draw(turbine::Context&) noexcept { - static constexpr auto flags = ImGuiTableFlags_RowBg; - const auto paneSize = ImGui::GetContentRegionAvail(); - ImGui::BeginChild("Colors", ImVec2(paneSize.x - 208, paneSize.y), true); + auto const paneSize = ImGui::GetContentRegionAvail(); { - const auto colorsSz = ImGui::GetContentRegionAvail(); - static constexpr auto toolbarHeight = 40; - { - const auto sz = ImVec2(70, 24); - if (ImGui::Button("Add", sz)) { - const auto colorSz = static_cast(m_pal.colors.size()); - constexpr Color16 c = 0; - undoStack()->push(ox::make_unique(&m_pal, c, colorSz)); - } - ImGui::SameLine(); - ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size()); - { - if (ImGui::Button("Remove", sz)) { - undoStack()->push( - ox::make_unique( - &m_pal, - m_pal.colors[static_cast(m_selectedRow)], - static_cast(m_selectedRow))); - m_selectedRow = ox::min(m_pal.colors.size() - 1, m_selectedRow); - } - ImGui::SameLine(); - ImGui::BeginDisabled(m_selectedRow <= 0); - { - if (ImGui::Button("Move Up", sz)) { - undoStack()->push(ox::make_unique(&m_pal, m_selectedRow, -1)); - --m_selectedRow; - } - } - ImGui::EndDisabled(); - ImGui::SameLine(); - ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size() - 1); - { - if (ImGui::Button("Move Down", sz)) { - undoStack()->push(ox::make_unique(&m_pal, m_selectedRow, 1)); - ++m_selectedRow; - } - } - ImGui::EndDisabled(); - } - ImGui::EndDisabled(); - } - ImGui::BeginTable("Colors", 5, flags, ImVec2(colorsSz.x, colorsSz.y - (toolbarHeight + 5))); - { - ImGui::TableSetupColumn("Idx", ImGuiTableColumnFlags_WidthFixed, 25); - ImGui::TableSetupColumn("Red", ImGuiTableColumnFlags_WidthFixed, 50); - ImGui::TableSetupColumn("Green", ImGuiTableColumnFlags_WidthFixed, 50); - ImGui::TableSetupColumn("Blue", ImGuiTableColumnFlags_WidthFixed, 50); - ImGui::TableSetupColumn("Color Preview", ImGuiTableColumnFlags_NoHide); - ImGui::TableHeadersRow(); - constexpr auto colVal = [] (unsigned num) { - ox::Array numStr; - ImGui::TableNextColumn(); - ox_itoa(num, numStr.data()); - ImGui::SetCursorPosX( - ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(numStr.data()).x); - ImGui::Text("%s", numStr.data()); - }; - for (auto i = 0u; const auto c : m_pal.colors) { - ImGui::PushID(static_cast(i)); - ImGui::TableNextRow(); - // Color No. - colVal(i); - // Red - colVal(red16(c)); - // Green - colVal(green16(c)); - // Blue - colVal(blue16(c)); - // ColorPreview - ImGui::TableNextColumn(); - const auto ic = ImGui::GetColorU32(ImVec4(redf(c), greenf(c), bluef(c), 1)); - ImGui::TableSetBgColor(ImGuiTableBgTarget_CellBg, ic); - if (ImGui::Selectable("##ColorRow", i == m_selectedRow, ImGuiSelectableFlags_SpanAllColumns)) { - m_selectedRow = i; - } - ImGui::PopID(); - ++i; - } - } - ImGui::EndTable(); + ImGui::BeginChild("Pages", ImVec2(250, paneSize.y), true); + drawPagesEditor(); + ImGui::EndChild(); } - ImGui::EndChild(); - if (m_selectedRow < m_pal.colors.size()) { - ImGui::SameLine(); - ImGui::BeginChild("ColorEditor", ImVec2(200, paneSize.y), true); - { - const auto c = m_pal.colors[m_selectedRow]; - int r = red16(c); - int g = green16(c); - int b = blue16(c); - int const a = alpha16(c); - ImGui::InputInt("Red", &r, 1, 5); - ImGui::InputInt("Green", &g, 1, 5); - ImGui::InputInt("Blue", &b, 1, 5); - const auto newColor = color16(r, g, b, a); - if (c != newColor) { - undoStack()->push(ox::make_unique(&m_pal, static_cast(m_selectedRow), c, newColor)); - } - } + ImGui::SameLine(); + { + ImGui::BeginChild("Colors", ImVec2(-1, paneSize.y), true); + drawColorsEditor(); ImGui::EndChild(); } } @@ -134,4 +42,163 @@ ox::Error PaletteEditorImGui::saveItem() noexcept { return sctx->project->writeObj(itemPath(), m_pal); } +void PaletteEditorImGui::drawColumn(ox::CStringView txt) noexcept { + ImGui::TableNextColumn(); + ImGui::SetCursorPosX( + ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(txt.data()).x); + ImGui::Text("%s", txt.c_str()); +} + +void PaletteEditorImGui::drawColumn(uint64_t i) noexcept { + ox::Array numStr; + ox_itoa(i, numStr.data()); + drawColumn(numStr.data()); +} + +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 colorEditorWidth = 220; + static constexpr auto toolbarHeight = 40; + { + auto const sz = ImVec2(70, 24); + if (ImGui::Button("Add", sz)) { + auto const colorSz = static_cast(colors(m_pal, m_page)); + constexpr Color16 c = 0; + undoStack()->push(ox::make_unique(&m_pal, c, m_page, colorSz)); + } + ImGui::SameLine(); + ImGui::BeginDisabled(m_selectedColorRow >= colors(m_pal, m_page)); + { + if (ImGui::Button("Remove", sz)) { + undoStack()->push( + ox::make_unique( + &m_pal, + color(m_pal, m_page, static_cast(m_selectedColorRow)), + m_page, + static_cast(m_selectedColorRow))); + m_selectedColorRow = ox::min(colors(m_pal, m_page) - 1, m_selectedColorRow); + } + ImGui::SameLine(); + ImGui::BeginDisabled(m_selectedColorRow <= 0); + { + if (ImGui::Button("Move Up", sz)) { + undoStack()->push(ox::make_unique(&m_pal, m_page, m_selectedColorRow, -1)); + --m_selectedColorRow; + } + } + ImGui::EndDisabled(); + ImGui::SameLine(); + ImGui::BeginDisabled(m_selectedColorRow >= colors(m_pal, m_page) - 1); + { + if (ImGui::Button("Move Down", sz)) { + undoStack()->push(ox::make_unique(&m_pal, m_page, m_selectedColorRow, 1)); + ++m_selectedColorRow; + } + } + ImGui::EndDisabled(); + } + ImGui::EndDisabled(); + } + auto const tblWidth = (colorsSz.x - colorEditorWidth - 8) * colorEditor; + ImGui::BeginTable("Colors", 5, tableFlags, ImVec2(tblWidth, colorsSz.y - (toolbarHeight + 5))); + { + ImGui::TableSetupColumn("Idx", ImGuiTableColumnFlags_WidthFixed, 25); + ImGui::TableSetupColumn("Red", ImGuiTableColumnFlags_WidthFixed, 50); + ImGui::TableSetupColumn("Green", ImGuiTableColumnFlags_WidthFixed, 50); + 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]) { + ImGui::PushID(static_cast(i)); + ImGui::TableNextRow(); + drawColumn(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)); + 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); + drawColorEditor(); + ImGui::EndChild(); + } +} + +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); + if (ImGui::Button("Add", btnSz)) { + undoStack()->push(ox::make_unique(m_pal)); + m_page = m_pal.pages.size() - 1; + } + ImGui::SameLine(); + if (ImGui::Button("Remove", btnSz)) { + undoStack()->push(ox::make_unique(m_pal, m_page)); + m_page = std::min(m_page, m_pal.pages.size() - 1); + } + ImGui::SameLine(); + if (ImGui::Button("Duplicate", btnSz)) { + undoStack()->push(ox::make_unique(m_pal, m_page, m_pal.pages.size())); + } + 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(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; + } + ImGui::PopID(); + } + } + ImGui::EndTable(); +} + +void PaletteEditorImGui::drawColorEditor() noexcept { + auto const c = color(m_pal, m_page, m_selectedColorRow); + int r = red16(c); + int g = green16(c); + int b = blue16(c); + int const a = alpha16(c); + ImGui::InputInt("Red", &r, 1, 5); + ImGui::InputInt("Green", &g, 1, 5); + ImGui::InputInt("Blue", &b, 1, 5); + auto const newColor = color16(r, g, b, a); + if (c != newColor) { + undoStack()->push(ox::make_unique( + &m_pal, m_page, static_cast(m_selectedColorRow), c, newColor)); + } +} + +ox::Error PaletteEditorImGui::handleCommand(studio::UndoCommand const*cmd) noexcept { + if (dynamic_cast(cmd)) { + m_page = m_pal.pages.size() - 1; + } else if (dynamic_cast(cmd)) { + m_page = ox::min(m_page, m_pal.pages.size() - 1); + } else if (auto const dupPageCmd = dynamic_cast(cmd)) { + m_page = ox::clamp(dupPageCmd->insertIdx(), 0, m_pal.pages.size() - 1); + } + return {}; +} + } 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 b1b07bec..183aa2f4 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.hpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor-imgui.hpp @@ -16,7 +16,8 @@ class PaletteEditorImGui: public studio::Editor { private: turbine::Context &m_ctx; Palette m_pal; - std::size_t m_selectedRow = 0; + size_t m_selectedColorRow = 0; + size_t m_page = 0; public: PaletteEditorImGui(turbine::Context &ctx, ox::CRStringView path); @@ -26,6 +27,18 @@ class PaletteEditorImGui: public studio::Editor { protected: ox::Error saveItem() noexcept final; + private: + static void drawColumn(ox::CStringView txt) noexcept; + + static void drawColumn(uint64_t i) noexcept; + + void drawColorsEditor() noexcept; + + void drawPagesEditor() noexcept; + + void drawColorEditor() 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 6f3cc38b..9ecc7e6a 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.cpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.cpp @@ -6,9 +6,74 @@ namespace nostalgia::core { -AddColorCommand::AddColorCommand(Palette *pal, Color16 color, int idx) noexcept { +AddPageCommand::AddPageCommand(Palette &pal) noexcept: + m_pal(pal) { +} + +int AddPageCommand::commandId() const noexcept { + return static_cast(PaletteEditorCommandId::AddPage); +} + +void AddPageCommand::redo() noexcept { + m_pal.pages.emplace_back(); +} + +void AddPageCommand::undo() noexcept { + oxIgnoreError(m_pal.pages.erase(static_cast(m_pal.pages.size() - 1))); +} + + +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.emplace_back(s); + } +} + +int DuplicatePageCommand::commandId() const noexcept { + return static_cast(PaletteEditorCommandId::DuplicatePage); +} + +void DuplicatePageCommand::redo() noexcept { + m_pal.pages.emplace(m_dstIdx, std::move(m_page)); +} + +void DuplicatePageCommand::undo() noexcept { + m_page = std::move(m_pal.pages[m_dstIdx]); + oxIgnoreError(m_pal.pages.erase(static_cast(m_dstIdx))); +} + +size_t DuplicatePageCommand::insertIdx() const noexcept { + return m_dstIdx; +} + + +RemovePageCommand::RemovePageCommand(Palette &pal, size_t idx) noexcept: + m_pal(pal), + m_idx(idx) { +} + +int RemovePageCommand::commandId() const noexcept { + return static_cast(PaletteEditorCommandId::RemovePage); +} + +void RemovePageCommand::redo() noexcept { + m_page = std::move(m_pal.pages[m_idx]); + oxIgnoreError(m_pal.pages.erase(static_cast(m_idx))); +} + +void RemovePageCommand::undo() noexcept { + m_pal.pages.insert(m_idx, std::move(m_page)); +} + + +AddColorCommand::AddColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept { m_pal = pal; m_color = color; + m_page = page; m_idx = idx; } @@ -17,17 +82,18 @@ int AddColorCommand::commandId() const noexcept { } void AddColorCommand::redo() noexcept { - m_pal->colors.insert(static_cast(m_idx), m_color); + m_pal->pages[m_page].insert(static_cast(m_idx), m_color); } void AddColorCommand::undo() noexcept { - oxIgnoreError(m_pal->colors.erase(static_cast(m_idx))); + oxIgnoreError(m_pal->pages[m_page].erase(static_cast(m_idx))); } -RemoveColorCommand::RemoveColorCommand(Palette *pal, Color16 color, int idx) noexcept { +RemoveColorCommand::RemoveColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept { m_pal = pal; m_color = color; + m_page = page; m_idx = idx; } @@ -36,16 +102,22 @@ int RemoveColorCommand::commandId() const noexcept { } void RemoveColorCommand::redo() noexcept { - oxIgnoreError(m_pal->colors.erase(static_cast(m_idx))); + oxIgnoreError(m_pal->pages[m_page].erase(static_cast(m_idx))); } void RemoveColorCommand::undo() noexcept { -m_pal->colors.insert(static_cast(m_idx), m_color); +m_pal->pages[m_page].insert(static_cast(m_idx), m_color); } -UpdateColorCommand::UpdateColorCommand(Palette *pal, int idx, Color16 oldColor, Color16 newColor) noexcept { +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; @@ -70,16 +142,17 @@ int UpdateColorCommand::commandId() const noexcept { } void UpdateColorCommand::redo() noexcept { - m_pal->colors[static_cast(m_idx)] = m_newColor; + m_pal->pages[m_page][static_cast(m_idx)] = m_newColor; } void UpdateColorCommand::undo() noexcept { - m_pal->colors[static_cast(m_idx)] = m_oldColor; + m_pal->pages[m_page][static_cast(m_idx)] = m_oldColor; } -MoveColorCommand::MoveColorCommand(Palette *pal, std::size_t idx, int offset) noexcept { +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; } @@ -97,9 +170,9 @@ void MoveColorCommand::undo() noexcept { } void MoveColorCommand::moveColor(int idx, int offset) noexcept { - const auto c = m_pal->colors[static_cast(idx)]; - oxIgnoreError(m_pal->colors.erase(static_cast(idx))); - m_pal->colors.insert(static_cast(idx + offset), c); + const auto c = m_pal->pages[m_page][static_cast(idx)]; + oxIgnoreError(m_pal->pages[m_page].erase(static_cast(idx))); + m_pal->pages[m_page].insert(static_cast(idx + offset), c); } } \ No newline at end of file diff --git a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp index 7519adf6..92b68b94 100644 --- a/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp +++ b/src/nostalgia/modules/core/src/studio/paletteeditor/paletteeditor.hpp @@ -13,6 +13,9 @@ namespace nostalgia::core { enum class PaletteEditorCommandId { + AddPage, + DuplicatePage, + RemovePage, AddColor, RemoveColor, UpdateColor, @@ -20,14 +23,76 @@ enum class PaletteEditorCommandId { }; +class AddPageCommand: public studio::UndoCommand { + private: + Palette &m_pal; + + public: + AddPageCommand(Palette &pal) noexcept; + + ~AddPageCommand() noexcept override = default; + + [[nodiscard]] + int commandId() const noexcept final; + + void redo() noexcept final; + + void undo() noexcept final; + +}; + +class DuplicatePageCommand: public studio::UndoCommand { + private: + Palette &m_pal; + size_t m_dstIdx = 0; + ox::Vector m_page; + + public: + DuplicatePageCommand(Palette &pal, size_t srcIdx, size_t dstIdx) noexcept; + + ~DuplicatePageCommand() noexcept override = default; + + [[nodiscard]] + int commandId() const noexcept final; + + void redo() noexcept final; + + void undo() noexcept final; + + [[nodiscard]] + size_t insertIdx() const noexcept; + +}; + +class RemovePageCommand: public studio::UndoCommand { + private: + Palette &m_pal; + size_t m_idx = 0; + ox::Vector m_page; + + public: + RemovePageCommand(Palette &pal, size_t idx) noexcept; + + ~RemovePageCommand() noexcept override = default; + + [[nodiscard]] + int commandId() const noexcept final; + + void redo() noexcept final; + + void undo() noexcept final; + +}; + class AddColorCommand: public studio::UndoCommand { private: Palette *m_pal = nullptr; Color16 m_color = 0; int m_idx = -1; + size_t m_page = 0; public: - AddColorCommand(Palette *pal, Color16 color, int idx) noexcept; + AddColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept; ~AddColorCommand() noexcept override = default; @@ -44,10 +109,11 @@ class RemoveColorCommand: public studio::UndoCommand { private: Palette *m_pal = nullptr; Color16 m_color = 0; + size_t m_page = 0; int m_idx = -1; public: - RemoveColorCommand(Palette *pal, Color16 color, int idx) noexcept; + RemoveColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept; ~RemoveColorCommand() noexcept override = default; @@ -65,10 +131,11 @@ class UpdateColorCommand: public studio::UndoCommand { Palette *m_pal = nullptr; Color16 m_oldColor = 0; Color16 m_newColor = 0; + size_t m_page = 0; int m_idx = -1; public: - UpdateColorCommand(Palette *pal, int idx, Color16 oldColor, Color16 newColor) noexcept; + UpdateColorCommand(Palette *pal, size_t page, int idx, Color16 oldColor, Color16 newColor) noexcept; ~UpdateColorCommand() noexcept override = default; @@ -87,11 +154,12 @@ class UpdateColorCommand: public studio::UndoCommand { 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; public: - MoveColorCommand(Palette *pal, std::size_t idx, int offset) noexcept; + MoveColorCommand(Palette *pal, size_t page, std::size_t idx, int offset) noexcept; ~MoveColorCommand() noexcept override = default; 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 e5249d4b..0f68ec52 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.cpp @@ -56,10 +56,11 @@ static ox::Error toPngFile( ox::CStringView const&path, ox::Vector &&pixels, Palette const&pal, + size_t page, unsigned width, unsigned height) noexcept { for (auto &c : pixels) { - c = color32(pal.color(c)) | static_cast(0XFF << 24); + c = color32(color(pal, page, c)) | static_cast(0XFF << 24); } constexpr auto fmt = LCT_RGBA; return OxError(static_cast( @@ -112,7 +113,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 (pal && !popupOpen) { - const auto colorCnt = pal->colors.size(); + const auto colorCnt = pal->pages[m_palPage].size(); if (key == turbine::Key::Alpha_D) { m_tool = Tool::Draw; setCopyEnabled(false); @@ -306,6 +307,7 @@ ox::Error TileSheetEditorImGui::exportSubhseetToPng(int scale) noexcept { path, std::move(pixels), *pal, + m_palPage, static_cast(width * scale), static_cast(height * scale)); if (err) { @@ -315,8 +317,8 @@ ox::Error TileSheetEditorImGui::exportSubhseetToPng(int scale) noexcept { } void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept { - const auto winPos = ImGui::GetWindowPos(); - const auto fbSizei = ox::Size(static_cast(fbSize.x), static_cast(fbSize.y)); + auto const winPos = ImGui::GetWindowPos(); + auto const fbSizei = ox::Size(static_cast(fbSize.x), static_cast(fbSize.y)); if (m_framebuffer.width != fbSizei.width || m_framebuffer.height != fbSizei.height) { glutils::resizeInitFrameBuffer(m_framebuffer, fbSizei.width, fbSizei.height); m_view.resizeView(fbSize); @@ -334,11 +336,11 @@ void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept { ImVec2(0, 1), ImVec2(1, 0)); // handle input, this must come after drawing - const auto &io = ImGui::GetIO(); - const auto mousePos = ox::Vec2(io.MousePos); + auto const&io = ImGui::GetIO(); + auto const mousePos = ox::Vec2(io.MousePos); if (ImGui::IsItemHovered()) { - const auto wheel = io.MouseWheel; - const auto wheelh = io.MouseWheelH; + auto const wheel = io.MouseWheel; + auto const wheelh = io.MouseWheelH; if (wheel != 0) { const auto zoomMod = ox::defines::OS == ox::OS::Darwin ? io.KeySuper : turbine::buttonDown(m_ctx, turbine::Key::Mod_Ctrl); @@ -365,7 +367,7 @@ void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept { } } if (ImGui::BeginPopupContextItem("TileMenu", ImGuiPopupFlags_MouseButtonRight)) { - const auto popupPos = ox::Vec2(ImGui::GetWindowPos()); + auto const popupPos = ox::Vec2(ImGui::GetWindowPos()); if (ImGui::MenuItem("Insert Tile")) { m_view.insertTile(fbSize, clickPos(winPos, popupPos)); } @@ -382,11 +384,13 @@ void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept { void TileSheetEditorImGui::drawPaletteSelector() noexcept { auto &sctx = *applicationData(m_ctx); - const auto &files = sctx.project->fileList(core::FileExt_npal); - const auto first = m_selectedPaletteIdx < files.size() ? + auto const&files = sctx.project->fileList(core::FileExt_npal); + auto const first = m_selectedPaletteIdx < files.size() ? files[m_selectedPaletteIdx].c_str() : ""; + auto const comboWidthSub = 62; + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - comboWidthSub); if (ImGui::BeginCombo("Palette", first, 0)) { - for (auto n = 0u; n < files.size(); n++) { + for (auto n = 0u; n < files.size(); ++n) { const auto selected = (m_selectedPaletteIdx == n); if (ImGui::Selectable(files[n].c_str(), selected) && m_selectedPaletteIdx != n) { m_selectedPaletteIdx = n; @@ -398,6 +402,28 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept { } ImGui::EndCombo(); } + auto const pages = m_model.pal()->pages.size(); + if (pages > 1) { + ImGui::Indent(20); + ox::Array numStr; + ox_itoa(m_palPage + 1, numStr.data()); + ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - comboWidthSub); + if (ImGui::BeginCombo("Page", numStr.data(), 0)) { + for (auto n = 0u; n < pages; ++n) { + const auto selected = (m_palPage == n); + ox_itoa(n + 1, numStr.data()); + if (ImGui::Selectable(numStr.data(), selected) && m_palPage != n) { + m_palPage = n; + m_model.setPalettePage(m_palPage); + } + if (selected) { + ImGui::SetItemDefaultFocus(); + } + } + ImGui::EndCombo(); + } + ImGui::Indent(-20); + } // header if (ImGui::BeginTable("PaletteTable", 3, ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingStretchProp)) { ImGui::TableSetupColumn("No.", 0, 0.45f); @@ -405,7 +431,7 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept { ImGui::TableSetupColumn("Color16", 0, 3); ImGui::TableHeadersRow(); if (auto pal = m_view.pal()) { - for (auto i = 0u; auto c: pal->colors) { + for (auto i = 0u; auto c: pal->pages[m_palPage]) { ImGui::PushID(static_cast(i)); // Column: color idx ImGui::TableNextColumn(); 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 2670ab3d..ad1689c7 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditor-imgui.hpp @@ -69,6 +69,7 @@ class TileSheetEditorImGui: public studio::Editor { float m_palViewWidth = 300; ox::Vec2 m_prevMouseDownPos; Tool m_tool = Tool::Draw; + size_t m_palPage = 0; public: TileSheetEditorImGui(turbine::Context &ctx, ox::CRStringView path); diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp index 3e733e49..fa9bf648 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.cpp @@ -4,6 +4,7 @@ #include +#include #include #include @@ -25,8 +26,8 @@ namespace nostalgia::core { -const Palette TileSheetEditorModel::s_defaultPalette = { - .colors = ox::Vector(128), +Palette const TileSheetEditorModel::s_defaultPalette = { + .pages = {ox::Vector(128)}, }; TileSheetEditorModel::TileSheetEditorModel(turbine::Context &ctx, ox::StringView path, studio::UndoStack &undoStack): @@ -114,6 +115,15 @@ ox::Error TileSheetEditorModel::setPalette(ox::StringView path) noexcept { return {}; } +void TileSheetEditorModel::setPalettePage(size_t pg) noexcept { + m_palettePage = ox::clamp(pg, 0, m_pal->pages.size() - 1); + m_updated = true; +} + +size_t TileSheetEditorModel::palettePage() const noexcept { + return m_palettePage; +} + void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t palIdx) noexcept { const auto &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx); if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) { diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.hpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.hpp index 72e24bfa..d54bedf4 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.hpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheeteditormodel.hpp @@ -23,12 +23,13 @@ class TileSheetEditorModel: public ox::SignalHandler { ox::Signal paletteChanged; private: - static const Palette s_defaultPalette; + static Palette const s_defaultPalette; turbine::Context &m_ctx; ox::String m_path; TileSheet m_img; TileSheet::SubSheetIdx m_activeSubsSheetIdx; keel::AssetRef m_pal; + size_t m_palettePage{}; studio::UndoStack &m_undoStack; class DrawCommand *m_ongoingDrawCommand = nullptr; bool m_updated = false; @@ -48,19 +49,24 @@ class TileSheetEditorModel: public ox::SignalHandler { void paste(); [[nodiscard]] - constexpr const TileSheet &img() const noexcept; + constexpr TileSheet const&img() const noexcept; [[nodiscard]] constexpr TileSheet &img() noexcept; [[nodiscard]] - constexpr const Palette *pal() const noexcept; + constexpr Palette const*pal() const noexcept; [[nodiscard]] ox::StringView palPath() const noexcept; ox::Error setPalette(ox::StringView path) noexcept; + void setPalettePage(size_t pg) noexcept; + + [[nodiscard]] + size_t palettePage() const noexcept; + void drawCommand(ox::Point const&pt, std::size_t palIdx) noexcept; void endDrawCommand() noexcept; @@ -125,7 +131,7 @@ class TileSheetEditorModel: public ox::SignalHandler { }; -constexpr const TileSheet &TileSheetEditorModel::img() const noexcept { +constexpr TileSheet const&TileSheetEditorModel::img() const noexcept { return m_img; } @@ -133,7 +139,7 @@ constexpr TileSheet &TileSheetEditorModel::img() noexcept { return m_img; } -constexpr const Palette *TileSheetEditorModel::pal() const noexcept { +constexpr Palette const*TileSheetEditorModel::pal() const noexcept { if (m_pal) { return m_pal.get(); } diff --git a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheetpixels.cpp b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheetpixels.cpp index 8c218e9b..1c91d2d7 100644 --- a/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheetpixels.cpp +++ b/src/nostalgia/modules/core/src/studio/tilesheeteditor/tilesheetpixels.cpp @@ -103,7 +103,7 @@ void TileSheetPixels::setBufferObjects(ox::Vec2 const&paneSize) noexcept { m_bufferSet.elements.resize(pixels * VertexEboLength); // set pixels walkPixels(*subSheet, m_model.img().bpp, [&](std::size_t i, uint8_t p) { - auto color = pal->color(p); + auto color = core::color(*pal, m_model.palettePage(), p); const auto pt = idxToPt(static_cast(i), subSheet->columns); const auto fx = static_cast(pt.x); const auto fy = static_cast(pt.y);