[nostalgia/core] Add new version of Palette with pages
All checks were successful
Build / build (push) Successful in 2m35s
All checks were successful
Build / build (push) Successful in 2m35s
This commit is contained in:
parent
b46cb65b7f
commit
5433fd9b1d
@ -25,5 +25,9 @@ using ContextUPtr = ox::UPtr<Context, ContextDeleter>;
|
|||||||
|
|
||||||
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const¶ms = {}) noexcept;
|
ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const¶ms = {}) noexcept;
|
||||||
|
|
||||||
|
keel::Context &keelCtx(Context &ctx) noexcept;
|
||||||
|
|
||||||
|
turbine::Context &turbineCtx(Context &ctx) noexcept;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include <ox/model/def.hpp>
|
#include <ox/model/def.hpp>
|
||||||
|
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
|
#include "palette.hpp"
|
||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
@ -100,6 +101,17 @@ oxModelBegin(TileSheetSet)
|
|||||||
oxModelField(entries)
|
oxModelField(entries)
|
||||||
oxModelEnd()
|
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(
|
ox::Error loadBgPalette(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
size_t palBank,
|
size_t palBank,
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <ox/std/vector.hpp>
|
#include <ox/std/vector.hpp>
|
||||||
#include <ox/model/def.hpp>
|
#include <ox/model/def.hpp>
|
||||||
|
|
||||||
|
#include <turbine/turbine.hpp>
|
||||||
|
|
||||||
#include "color.hpp"
|
#include "color.hpp"
|
||||||
|
|
||||||
@ -22,25 +23,53 @@ struct NostalgiaPalette {
|
|||||||
ox::Vector<Color16> colors = {};
|
ox::Vector<Color16> colors = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Palette {
|
struct PaletteV1 {
|
||||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette";
|
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette";
|
||||||
static constexpr auto TypeVersion = 1;
|
static constexpr auto TypeVersion = 1;
|
||||||
ox::Vector<Color16> colors = {};
|
ox::Vector<Color16> colors;
|
||||||
[[nodiscard]]
|
|
||||||
constexpr Color16 color(auto idx) const noexcept {
|
|
||||||
if (idx < colors.size()) [[likely]] {
|
|
||||||
return colors[idx];
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PaletteV2 {
|
||||||
|
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 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)
|
oxModelBegin(NostalgiaPalette)
|
||||||
oxModelField(colors)
|
oxModelField(colors)
|
||||||
oxModelEnd()
|
oxModelEnd()
|
||||||
|
|
||||||
oxModelBegin(Palette)
|
oxModelBegin(PaletteV1)
|
||||||
oxModelField(colors)
|
oxModelField(colors)
|
||||||
oxModelEnd()
|
oxModelEnd()
|
||||||
|
|
||||||
|
oxModelBegin(PaletteV2)
|
||||||
|
oxModelField(pages)
|
||||||
|
oxModelEnd()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <turbine/turbine.hpp>
|
||||||
|
|
||||||
#include <nostalgia/core/gfx.hpp>
|
#include <nostalgia/core/gfx.hpp>
|
||||||
|
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
@ -23,4 +25,12 @@ ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const¶ms) no
|
|||||||
return ContextUPtr(std::move(ctx));
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -10,6 +10,7 @@
|
|||||||
#include <teagba/gfx.hpp>
|
#include <teagba/gfx.hpp>
|
||||||
#include <teagba/registers.hpp>
|
#include <teagba/registers.hpp>
|
||||||
|
|
||||||
|
#include <keel/keel.hpp>
|
||||||
#include <turbine/turbine.hpp>
|
#include <turbine/turbine.hpp>
|
||||||
|
|
||||||
#include <nostalgia/core/color.hpp>
|
#include <nostalgia/core/color.hpp>
|
||||||
@ -25,12 +26,6 @@ constexpr auto GbaTileColumns = 32;
|
|||||||
constexpr auto GbaTileRows = 32;
|
constexpr auto GbaTileRows = 32;
|
||||||
constexpr auto SpriteCount = 128;
|
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 {
|
struct GbaTileMapTarget {
|
||||||
static constexpr auto TypeName = CompactTileSheet::TypeName;
|
static constexpr auto TypeName = CompactTileSheet::TypeName;
|
||||||
static constexpr auto TypeVersion = CompactTileSheet::TypeVersion;
|
static constexpr auto TypeVersion = CompactTileSheet::TypeVersion;
|
||||||
@ -44,22 +39,6 @@ struct GbaTileMapTarget {
|
|||||||
TileSheetSetEntry const*setEntry = nullptr;
|
TileSheetSetEntry const*setEntry = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr ox::Error model(auto *io, ox::CommonPtrWith<GbaPaletteTarget> auto *t) noexcept {
|
|
||||||
oxReturnError(io->template setTypeInfo<Palette>());
|
|
||||||
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<Color16, decltype(colorHandler)>("colors", colorHandler);
|
|
||||||
} else {
|
|
||||||
constexpr auto colorHandler = [](std::size_t, const Color16*) {
|
|
||||||
return ox::Error{};
|
|
||||||
};
|
|
||||||
return io->template field<Color16, decltype(colorHandler)>("colors", colorHandler);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
static bool loadPixel(TileSheetSetEntry const&setEntry, size_t §ionIdx, int tileIdx) noexcept {
|
static bool loadPixel(TileSheetSetEntry const&setEntry, size_t §ionIdx, int tileIdx) noexcept {
|
||||||
if (setEntry.sections.size() <= sectionIdx) {
|
if (setEntry.sections.size() <= sectionIdx) {
|
||||||
@ -156,27 +135,48 @@ ox::Error initGfx(Context&, InitParams const&) noexcept {
|
|||||||
return {};
|
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(
|
ox::Error loadBgPalette(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
size_t palBank,
|
size_t palBank,
|
||||||
ox::FileAddress const&paletteAddr) noexcept {
|
ox::FileAddress const&paletteAddr) noexcept {
|
||||||
auto &rom = ctx.rom();
|
oxRequire(pal, keel::readObj<Palette>(keelCtx(ctx), paletteAddr));
|
||||||
GbaPaletteTarget const palTarget{.palette = MEM_BG_PALETTE + palBank * 16};
|
return loadBgPalette(ctx, palBank, *pal, 0);
|
||||||
oxRequire(palStat, rom.stat(paletteAddr));
|
|
||||||
oxRequire(pal, rom.directAccess(paletteAddr));
|
|
||||||
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &palTarget));
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ox::Error loadSpritePalette(
|
ox::Error loadSpritePalette(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
ox::FileAddress const&paletteAddr) noexcept {
|
ox::FileAddress const&paletteAddr) noexcept {
|
||||||
auto &rom = ctx.rom();
|
oxRequire(pal, keel::readObj<Palette>(keelCtx(ctx), paletteAddr));
|
||||||
GbaPaletteTarget const palTarget{.palette = MEM_SPRITE_PALETTE};
|
return loadSpritePalette(ctx, *pal, 0);
|
||||||
oxRequire(palStat, rom.stat(paletteAddr));
|
|
||||||
oxRequire(pal, rom.directAccess(paletteAddr));
|
|
||||||
oxReturnError(ox::readMC(pal, static_cast<std::size_t>(palStat.size), &palTarget));
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ox::Error loadTileSheetSet(
|
static ox::Error loadTileSheetSet(
|
||||||
|
@ -16,7 +16,8 @@ namespace nostalgia::core {
|
|||||||
|
|
||||||
class KeelModule: public keel::Module {
|
class KeelModule: public keel::Module {
|
||||||
private:
|
private:
|
||||||
NostalgiaPaletteToPaletteConverter m_nostalgiaPaletteToPaletteConverter;
|
NostalgiaPaletteToPaletteV1Converter m_nostalgiaPaletteToPaletteV1Converter;
|
||||||
|
PaletteV1ToPaletteV2Converter m_paletteV1ToPaletteV2Converter;
|
||||||
TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter;
|
TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter;
|
||||||
TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter;
|
TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter;
|
||||||
TileSheetV3ToTileSheetV4Converter m_tileSheetV3ToTileSheetV4Converter;
|
TileSheetV3ToTileSheetV4Converter m_tileSheetV3ToTileSheetV4Converter;
|
||||||
@ -36,14 +37,16 @@ class KeelModule: public keel::Module {
|
|||||||
keel::generateTypeDesc<TileSheetV3>,
|
keel::generateTypeDesc<TileSheetV3>,
|
||||||
keel::generateTypeDesc<TileSheetV4>,
|
keel::generateTypeDesc<TileSheetV4>,
|
||||||
keel::generateTypeDesc<CompactTileSheet>,
|
keel::generateTypeDesc<CompactTileSheet>,
|
||||||
keel::generateTypeDesc<Palette>,
|
keel::generateTypeDesc<PaletteV1>,
|
||||||
|
keel::generateTypeDesc<PaletteV2>,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ox::Vector<keel::BaseConverter const*> converters() const noexcept final {
|
ox::Vector<keel::BaseConverter const*> converters() const noexcept final {
|
||||||
return {
|
return {
|
||||||
&m_nostalgiaPaletteToPaletteConverter,
|
&m_nostalgiaPaletteToPaletteV1Converter,
|
||||||
|
&m_paletteV1ToPaletteV2Converter,
|
||||||
&m_tileSheetV1ToTileSheetV2Converter,
|
&m_tileSheetV1ToTileSheetV2Converter,
|
||||||
&m_tileSheetV2ToTileSheetV3Converter,
|
&m_tileSheetV2ToTileSheetV3Converter,
|
||||||
&m_tileSheetV3ToTileSheetV4Converter,
|
&m_tileSheetV3ToTileSheetV4Converter,
|
||||||
@ -68,6 +71,17 @@ class KeelModule: public keel::Module {
|
|||||||
}
|
}
|
||||||
return {};
|
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<NostalgiaPalette>() ||
|
||||||
|
typeId == ox::buildTypeId<PaletteV1>()) {
|
||||||
|
oxReturnError(keel::convertBuffToBuff<core::Palette>(
|
||||||
|
ctx, buff, ox::ClawFormat::Metal).moveTo(buff));
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -6,14 +6,22 @@
|
|||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
ox::Error NostalgiaPaletteToPaletteConverter::convert(
|
ox::Error NostalgiaPaletteToPaletteV1Converter::convert(
|
||||||
keel::Context&,
|
keel::Context&,
|
||||||
NostalgiaPalette &src,
|
NostalgiaPalette &src,
|
||||||
Palette &dst) const noexcept {
|
PaletteV1 &dst) const noexcept {
|
||||||
dst.colors = std::move(src.colors);
|
dst.colors = std::move(src.colors);
|
||||||
return {};
|
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(
|
ox::Error TileSheetV1ToTileSheetV2Converter::convert(
|
||||||
keel::Context&,
|
keel::Context&,
|
||||||
TileSheetV1 &src,
|
TileSheetV1 &src,
|
||||||
|
@ -16,8 +16,12 @@ namespace nostalgia::core {
|
|||||||
|
|
||||||
// Type converters
|
// Type converters
|
||||||
|
|
||||||
class NostalgiaPaletteToPaletteConverter: public keel::Converter<NostalgiaPalette, Palette> {
|
class NostalgiaPaletteToPaletteV1Converter: public keel::Converter<NostalgiaPalette, PaletteV1> {
|
||||||
ox::Error convert(keel::Context&, NostalgiaPalette &src, Palette &dst) const noexcept final;
|
ox::Error convert(keel::Context&, NostalgiaPalette &src, PaletteV1 &dst) const noexcept final;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PaletteV1ToPaletteV2Converter: public keel::Converter<PaletteV1, PaletteV2> {
|
||||||
|
ox::Error convert(keel::Context&, PaletteV1 &src, PaletteV2 &dst) const noexcept final;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TileSheetV1ToTileSheetV2Converter: public keel::Converter<TileSheetV1, TileSheetV2> {
|
class TileSheetV1ToTileSheetV2Converter: public keel::Converter<TileSheetV1, TileSheetV2> {
|
||||||
|
@ -29,4 +29,12 @@ ox::Result<ContextUPtr> init(turbine::Context &tctx, InitParams const¶ms) no
|
|||||||
return ContextUPtr(ctx.release());
|
return ContextUPtr(ctx.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
keel::Context &keelCtx(Context &ctx) noexcept {
|
||||||
|
return turbine::keelCtx(ctx.turbineCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
turbine::Context &turbineCtx(Context &ctx) noexcept {
|
||||||
|
return ctx.turbineCtx;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include <nostalgia/core/context.hpp>
|
#include <nostalgia/core/context.hpp>
|
||||||
#include <nostalgia/core/gfx.hpp>
|
#include <nostalgia/core/gfx.hpp>
|
||||||
|
#include <nostalgia/core/palette.hpp>
|
||||||
#include <nostalgia/core/tilesheet.hpp>
|
#include <nostalgia/core/tilesheet.hpp>
|
||||||
|
|
||||||
#include "context.hpp"
|
#include "context.hpp"
|
||||||
@ -359,9 +360,10 @@ static void loadPalette(
|
|||||||
ox::Array<GLfloat, 1024> &palette,
|
ox::Array<GLfloat, 1024> &palette,
|
||||||
size_t palOffset,
|
size_t palOffset,
|
||||||
GLuint shaderPgrm,
|
GLuint shaderPgrm,
|
||||||
Palette const&pal) noexcept {
|
Palette const&pal,
|
||||||
|
size_t page = 0) noexcept {
|
||||||
static constexpr std::size_t ColorCnt = 256;
|
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++] = redf(c);
|
||||||
palette[i++] = greenf(c);
|
palette[i++] = greenf(c);
|
||||||
palette[i++] = bluef(c);
|
palette[i++] = bluef(c);
|
||||||
@ -506,6 +508,24 @@ static ox::Result<TileSheetData> normalizeTileSheet(
|
|||||||
return TileSheetData{std::move(pixels), width, height};
|
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<GLfloat, 1024> pal;
|
||||||
|
renderer::loadPalette(pal, 0, ctx.spriteShader, palette, page);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
ox::Error loadBgPalette(
|
ox::Error loadBgPalette(
|
||||||
Context &ctx,
|
Context &ctx,
|
||||||
size_t palBank,
|
size_t palBank,
|
||||||
|
@ -19,112 +19,20 @@ PaletteEditorImGui::PaletteEditorImGui(turbine::Context &ctx, ox::CRStringView p
|
|||||||
Editor(path),
|
Editor(path),
|
||||||
m_ctx(ctx),
|
m_ctx(ctx),
|
||||||
m_pal(*keel::readObj<Palette>(keelCtx(m_ctx), ox::FileAddress(itemPath())).unwrapThrow()) {
|
m_pal(*keel::readObj<Palette>(keelCtx(m_ctx), ox::FileAddress(itemPath())).unwrapThrow()) {
|
||||||
|
undoStack()->changeTriggered.connect(this, &PaletteEditorImGui::handleCommand);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaletteEditorImGui::draw(turbine::Context&) noexcept {
|
void PaletteEditorImGui::draw(turbine::Context&) noexcept {
|
||||||
static constexpr auto flags = ImGuiTableFlags_RowBg;
|
auto const paneSize = ImGui::GetContentRegionAvail();
|
||||||
const auto paneSize = ImGui::GetContentRegionAvail();
|
|
||||||
ImGui::BeginChild("Colors", ImVec2(paneSize.x - 208, paneSize.y), true);
|
|
||||||
{
|
{
|
||||||
const auto colorsSz = ImGui::GetContentRegionAvail();
|
ImGui::BeginChild("Pages", ImVec2(250, paneSize.y), true);
|
||||||
static constexpr auto toolbarHeight = 40;
|
drawPagesEditor();
|
||||||
{
|
ImGui::EndChild();
|
||||||
const auto sz = ImVec2(70, 24);
|
|
||||||
if (ImGui::Button("Add", sz)) {
|
|
||||||
const auto colorSz = static_cast<int>(m_pal.colors.size());
|
|
||||||
constexpr Color16 c = 0;
|
|
||||||
undoStack()->push(ox::make_unique<AddColorCommand>(&m_pal, c, colorSz));
|
|
||||||
}
|
|
||||||
ImGui::SameLine();
|
|
||||||
ImGui::BeginDisabled(m_selectedRow >= m_pal.colors.size());
|
|
||||||
{
|
|
||||||
if (ImGui::Button("Remove", sz)) {
|
|
||||||
undoStack()->push(
|
|
||||||
ox::make_unique<RemoveColorCommand>(
|
|
||||||
&m_pal,
|
|
||||||
m_pal.colors[static_cast<std::size_t>(m_selectedRow)],
|
|
||||||
static_cast<int>(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<MoveColorCommand>(&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<MoveColorCommand>(&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<char, 4> 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<int>(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::EndChild();
|
ImGui::SameLine();
|
||||||
if (m_selectedRow < m_pal.colors.size()) {
|
{
|
||||||
ImGui::SameLine();
|
ImGui::BeginChild("Colors", ImVec2(-1, paneSize.y), true);
|
||||||
ImGui::BeginChild("ColorEditor", ImVec2(200, paneSize.y), true);
|
drawColorsEditor();
|
||||||
{
|
|
||||||
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<UpdateColorCommand>(&m_pal, static_cast<int>(m_selectedRow), c, newColor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -134,4 +42,163 @@ ox::Error PaletteEditorImGui::saveItem() noexcept {
|
|||||||
return sctx->project->writeObj(itemPath(), m_pal);
|
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<char, 10> 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<int>(colors(m_pal, m_page));
|
||||||
|
constexpr Color16 c = 0;
|
||||||
|
undoStack()->push(ox::make_unique<AddColorCommand>(&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<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);
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::BeginDisabled(m_selectedColorRow <= 0);
|
||||||
|
{
|
||||||
|
if (ImGui::Button("Move Up", sz)) {
|
||||||
|
undoStack()->push(ox::make_unique<MoveColorCommand>(&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<MoveColorCommand>(&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<int>(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<AddPageCommand>(m_pal));
|
||||||
|
m_page = m_pal.pages.size() - 1;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Remove", btnSz)) {
|
||||||
|
undoStack()->push(ox::make_unique<RemovePageCommand>(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<DuplicatePageCommand>(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<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;
|
||||||
|
}
|
||||||
|
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<UpdateColorCommand>(
|
||||||
|
&m_pal, m_page, static_cast<int>(m_selectedColorRow), c, newColor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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)) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,8 @@ class PaletteEditorImGui: public studio::Editor {
|
|||||||
private:
|
private:
|
||||||
turbine::Context &m_ctx;
|
turbine::Context &m_ctx;
|
||||||
Palette m_pal;
|
Palette m_pal;
|
||||||
std::size_t m_selectedRow = 0;
|
size_t m_selectedColorRow = 0;
|
||||||
|
size_t m_page = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PaletteEditorImGui(turbine::Context &ctx, ox::CRStringView path);
|
PaletteEditorImGui(turbine::Context &ctx, ox::CRStringView path);
|
||||||
@ -26,6 +27,18 @@ class PaletteEditorImGui: public studio::Editor {
|
|||||||
protected:
|
protected:
|
||||||
ox::Error saveItem() noexcept final;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,9 +6,74 @@
|
|||||||
|
|
||||||
namespace nostalgia::core {
|
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<int>(PaletteEditorCommandId::AddPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddPageCommand::redo() noexcept {
|
||||||
|
m_pal.pages.emplace_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddPageCommand::undo() noexcept {
|
||||||
|
oxIgnoreError(m_pal.pages.erase(static_cast<std::size_t>(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<int>(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<std::size_t>(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<int>(PaletteEditorCommandId::RemovePage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemovePageCommand::redo() noexcept {
|
||||||
|
m_page = std::move(m_pal.pages[m_idx]);
|
||||||
|
oxIgnoreError(m_pal.pages.erase(static_cast<std::size_t>(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_pal = pal;
|
||||||
m_color = color;
|
m_color = color;
|
||||||
|
m_page = page;
|
||||||
m_idx = idx;
|
m_idx = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,17 +82,18 @@ int AddColorCommand::commandId() const noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AddColorCommand::redo() noexcept {
|
void AddColorCommand::redo() noexcept {
|
||||||
m_pal->colors.insert(static_cast<std::size_t>(m_idx), m_color);
|
m_pal->pages[m_page].insert(static_cast<std::size_t>(m_idx), m_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddColorCommand::undo() noexcept {
|
void AddColorCommand::undo() noexcept {
|
||||||
oxIgnoreError(m_pal->colors.erase(static_cast<std::size_t>(m_idx)));
|
oxIgnoreError(m_pal->pages[m_page].erase(static_cast<std::size_t>(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_pal = pal;
|
||||||
m_color = color;
|
m_color = color;
|
||||||
|
m_page = page;
|
||||||
m_idx = idx;
|
m_idx = idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,16 +102,22 @@ int RemoveColorCommand::commandId() const noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RemoveColorCommand::redo() noexcept {
|
void RemoveColorCommand::redo() noexcept {
|
||||||
oxIgnoreError(m_pal->colors.erase(static_cast<std::size_t>(m_idx)));
|
oxIgnoreError(m_pal->pages[m_page].erase(static_cast<std::size_t>(m_idx)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveColorCommand::undo() noexcept {
|
void RemoveColorCommand::undo() noexcept {
|
||||||
m_pal->colors.insert(static_cast<std::size_t>(m_idx), m_color);
|
m_pal->pages[m_page].insert(static_cast<std::size_t>(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_pal = pal;
|
||||||
|
m_page = page;
|
||||||
m_idx = idx;
|
m_idx = idx;
|
||||||
m_oldColor = oldColor;
|
m_oldColor = oldColor;
|
||||||
m_newColor = newColor;
|
m_newColor = newColor;
|
||||||
@ -70,16 +142,17 @@ int UpdateColorCommand::commandId() const noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UpdateColorCommand::redo() noexcept {
|
void UpdateColorCommand::redo() noexcept {
|
||||||
m_pal->colors[static_cast<std::size_t>(m_idx)] = m_newColor;
|
m_pal->pages[m_page][static_cast<std::size_t>(m_idx)] = m_newColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateColorCommand::undo() noexcept {
|
void UpdateColorCommand::undo() noexcept {
|
||||||
m_pal->colors[static_cast<std::size_t>(m_idx)] = m_oldColor;
|
m_pal->pages[m_page][static_cast<std::size_t>(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_pal = pal;
|
||||||
|
m_page = page;
|
||||||
m_idx = idx;
|
m_idx = idx;
|
||||||
m_offset = offset;
|
m_offset = offset;
|
||||||
}
|
}
|
||||||
@ -97,9 +170,9 @@ void MoveColorCommand::undo() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MoveColorCommand::moveColor(int idx, int offset) noexcept {
|
void MoveColorCommand::moveColor(int idx, int offset) noexcept {
|
||||||
const auto c = m_pal->colors[static_cast<std::size_t>(idx)];
|
const auto c = m_pal->pages[m_page][static_cast<std::size_t>(idx)];
|
||||||
oxIgnoreError(m_pal->colors.erase(static_cast<std::size_t>(idx)));
|
oxIgnoreError(m_pal->pages[m_page].erase(static_cast<std::size_t>(idx)));
|
||||||
m_pal->colors.insert(static_cast<std::size_t>(idx + offset), c);
|
m_pal->pages[m_page].insert(static_cast<std::size_t>(idx + offset), c);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -13,6 +13,9 @@
|
|||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
enum class PaletteEditorCommandId {
|
enum class PaletteEditorCommandId {
|
||||||
|
AddPage,
|
||||||
|
DuplicatePage,
|
||||||
|
RemovePage,
|
||||||
AddColor,
|
AddColor,
|
||||||
RemoveColor,
|
RemoveColor,
|
||||||
UpdateColor,
|
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<Color16> 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<Color16> 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 {
|
class AddColorCommand: public studio::UndoCommand {
|
||||||
private:
|
private:
|
||||||
Palette *m_pal = nullptr;
|
Palette *m_pal = nullptr;
|
||||||
Color16 m_color = 0;
|
Color16 m_color = 0;
|
||||||
int m_idx = -1;
|
int m_idx = -1;
|
||||||
|
size_t m_page = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AddColorCommand(Palette *pal, Color16 color, int idx) noexcept;
|
AddColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept;
|
||||||
|
|
||||||
~AddColorCommand() noexcept override = default;
|
~AddColorCommand() noexcept override = default;
|
||||||
|
|
||||||
@ -44,10 +109,11 @@ class RemoveColorCommand: public studio::UndoCommand {
|
|||||||
private:
|
private:
|
||||||
Palette *m_pal = nullptr;
|
Palette *m_pal = nullptr;
|
||||||
Color16 m_color = 0;
|
Color16 m_color = 0;
|
||||||
|
size_t m_page = 0;
|
||||||
int m_idx = -1;
|
int m_idx = -1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
RemoveColorCommand(Palette *pal, Color16 color, int idx) noexcept;
|
RemoveColorCommand(Palette *pal, Color16 color, size_t page, int idx) noexcept;
|
||||||
|
|
||||||
~RemoveColorCommand() noexcept override = default;
|
~RemoveColorCommand() noexcept override = default;
|
||||||
|
|
||||||
@ -65,10 +131,11 @@ class UpdateColorCommand: public studio::UndoCommand {
|
|||||||
Palette *m_pal = nullptr;
|
Palette *m_pal = nullptr;
|
||||||
Color16 m_oldColor = 0;
|
Color16 m_oldColor = 0;
|
||||||
Color16 m_newColor = 0;
|
Color16 m_newColor = 0;
|
||||||
|
size_t m_page = 0;
|
||||||
int m_idx = -1;
|
int m_idx = -1;
|
||||||
|
|
||||||
public:
|
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;
|
~UpdateColorCommand() noexcept override = default;
|
||||||
|
|
||||||
@ -87,11 +154,12 @@ class UpdateColorCommand: public studio::UndoCommand {
|
|||||||
class MoveColorCommand: public studio::UndoCommand {
|
class MoveColorCommand: public studio::UndoCommand {
|
||||||
private:
|
private:
|
||||||
Palette *m_pal = nullptr;
|
Palette *m_pal = nullptr;
|
||||||
|
size_t m_page = 0;
|
||||||
std::size_t m_idx = 0;
|
std::size_t m_idx = 0;
|
||||||
int m_offset = 0;
|
int m_offset = 0;
|
||||||
|
|
||||||
public:
|
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;
|
~MoveColorCommand() noexcept override = default;
|
||||||
|
|
||||||
|
@ -56,10 +56,11 @@ static ox::Error toPngFile(
|
|||||||
ox::CStringView const&path,
|
ox::CStringView const&path,
|
||||||
ox::Vector<uint32_t> &&pixels,
|
ox::Vector<uint32_t> &&pixels,
|
||||||
Palette const&pal,
|
Palette const&pal,
|
||||||
|
size_t page,
|
||||||
unsigned width,
|
unsigned width,
|
||||||
unsigned height) noexcept {
|
unsigned height) noexcept {
|
||||||
for (auto &c : pixels) {
|
for (auto &c : pixels) {
|
||||||
c = color32(pal.color(c)) | static_cast<Color32>(0XFF << 24);
|
c = color32(color(pal, page, c)) | static_cast<Color32>(0XFF << 24);
|
||||||
}
|
}
|
||||||
constexpr auto fmt = LCT_RGBA;
|
constexpr auto fmt = LCT_RGBA;
|
||||||
return OxError(static_cast<ox::ErrorCode>(
|
return OxError(static_cast<ox::ErrorCode>(
|
||||||
@ -112,7 +113,7 @@ void TileSheetEditorImGui::keyStateChanged(turbine::Key key, bool down) {
|
|||||||
auto const popupOpen = m_subsheetEditor.isOpen() && m_exportMenu.isOpen();
|
auto const popupOpen = m_subsheetEditor.isOpen() && m_exportMenu.isOpen();
|
||||||
auto const pal = m_model.pal();
|
auto const pal = m_model.pal();
|
||||||
if (pal && !popupOpen) {
|
if (pal && !popupOpen) {
|
||||||
const auto colorCnt = pal->colors.size();
|
const auto colorCnt = pal->pages[m_palPage].size();
|
||||||
if (key == turbine::Key::Alpha_D) {
|
if (key == turbine::Key::Alpha_D) {
|
||||||
m_tool = Tool::Draw;
|
m_tool = Tool::Draw;
|
||||||
setCopyEnabled(false);
|
setCopyEnabled(false);
|
||||||
@ -306,6 +307,7 @@ ox::Error TileSheetEditorImGui::exportSubhseetToPng(int scale) noexcept {
|
|||||||
path,
|
path,
|
||||||
std::move(pixels),
|
std::move(pixels),
|
||||||
*pal,
|
*pal,
|
||||||
|
m_palPage,
|
||||||
static_cast<unsigned>(width * scale),
|
static_cast<unsigned>(width * scale),
|
||||||
static_cast<unsigned>(height * scale));
|
static_cast<unsigned>(height * scale));
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -315,8 +317,8 @@ ox::Error TileSheetEditorImGui::exportSubhseetToPng(int scale) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept {
|
void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept {
|
||||||
const auto winPos = ImGui::GetWindowPos();
|
auto const winPos = ImGui::GetWindowPos();
|
||||||
const auto fbSizei = ox::Size(static_cast<int>(fbSize.x), static_cast<int>(fbSize.y));
|
auto const fbSizei = ox::Size(static_cast<int>(fbSize.x), static_cast<int>(fbSize.y));
|
||||||
if (m_framebuffer.width != fbSizei.width || m_framebuffer.height != fbSizei.height) {
|
if (m_framebuffer.width != fbSizei.width || m_framebuffer.height != fbSizei.height) {
|
||||||
glutils::resizeInitFrameBuffer(m_framebuffer, fbSizei.width, fbSizei.height);
|
glutils::resizeInitFrameBuffer(m_framebuffer, fbSizei.width, fbSizei.height);
|
||||||
m_view.resizeView(fbSize);
|
m_view.resizeView(fbSize);
|
||||||
@ -334,11 +336,11 @@ void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept {
|
|||||||
ImVec2(0, 1),
|
ImVec2(0, 1),
|
||||||
ImVec2(1, 0));
|
ImVec2(1, 0));
|
||||||
// handle input, this must come after drawing
|
// handle input, this must come after drawing
|
||||||
const auto &io = ImGui::GetIO();
|
auto const&io = ImGui::GetIO();
|
||||||
const auto mousePos = ox::Vec2(io.MousePos);
|
auto const mousePos = ox::Vec2(io.MousePos);
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
const auto wheel = io.MouseWheel;
|
auto const wheel = io.MouseWheel;
|
||||||
const auto wheelh = io.MouseWheelH;
|
auto const wheelh = io.MouseWheelH;
|
||||||
if (wheel != 0) {
|
if (wheel != 0) {
|
||||||
const auto zoomMod = ox::defines::OS == ox::OS::Darwin ?
|
const auto zoomMod = ox::defines::OS == ox::OS::Darwin ?
|
||||||
io.KeySuper : turbine::buttonDown(m_ctx, turbine::Key::Mod_Ctrl);
|
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)) {
|
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")) {
|
if (ImGui::MenuItem("Insert Tile")) {
|
||||||
m_view.insertTile(fbSize, clickPos(winPos, popupPos));
|
m_view.insertTile(fbSize, clickPos(winPos, popupPos));
|
||||||
}
|
}
|
||||||
@ -382,11 +384,13 @@ void TileSheetEditorImGui::drawTileSheet(ox::Vec2 const&fbSize) noexcept {
|
|||||||
|
|
||||||
void TileSheetEditorImGui::drawPaletteSelector() noexcept {
|
void TileSheetEditorImGui::drawPaletteSelector() noexcept {
|
||||||
auto &sctx = *applicationData<studio::StudioContext>(m_ctx);
|
auto &sctx = *applicationData<studio::StudioContext>(m_ctx);
|
||||||
const auto &files = sctx.project->fileList(core::FileExt_npal);
|
auto const&files = sctx.project->fileList(core::FileExt_npal);
|
||||||
const auto first = m_selectedPaletteIdx < files.size() ?
|
auto const first = m_selectedPaletteIdx < files.size() ?
|
||||||
files[m_selectedPaletteIdx].c_str() : "";
|
files[m_selectedPaletteIdx].c_str() : "";
|
||||||
|
auto const comboWidthSub = 62;
|
||||||
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - comboWidthSub);
|
||||||
if (ImGui::BeginCombo("Palette", first, 0)) {
|
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);
|
const auto selected = (m_selectedPaletteIdx == n);
|
||||||
if (ImGui::Selectable(files[n].c_str(), selected) && m_selectedPaletteIdx != n) {
|
if (ImGui::Selectable(files[n].c_str(), selected) && m_selectedPaletteIdx != n) {
|
||||||
m_selectedPaletteIdx = n;
|
m_selectedPaletteIdx = n;
|
||||||
@ -398,6 +402,28 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept {
|
|||||||
}
|
}
|
||||||
ImGui::EndCombo();
|
ImGui::EndCombo();
|
||||||
}
|
}
|
||||||
|
auto const pages = m_model.pal()->pages.size();
|
||||||
|
if (pages > 1) {
|
||||||
|
ImGui::Indent(20);
|
||||||
|
ox::Array<char, 10> 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
|
// 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("No.", 0, 0.45f);
|
||||||
@ -405,7 +431,7 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept {
|
|||||||
ImGui::TableSetupColumn("Color16", 0, 3);
|
ImGui::TableSetupColumn("Color16", 0, 3);
|
||||||
ImGui::TableHeadersRow();
|
ImGui::TableHeadersRow();
|
||||||
if (auto pal = m_view.pal()) {
|
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<int>(i));
|
ImGui::PushID(static_cast<int>(i));
|
||||||
// Column: color idx
|
// Column: color idx
|
||||||
ImGui::TableNextColumn();
|
ImGui::TableNextColumn();
|
||||||
|
@ -69,6 +69,7 @@ class TileSheetEditorImGui: public studio::Editor {
|
|||||||
float m_palViewWidth = 300;
|
float m_palViewWidth = 300;
|
||||||
ox::Vec2 m_prevMouseDownPos;
|
ox::Vec2 m_prevMouseDownPos;
|
||||||
Tool m_tool = Tool::Draw;
|
Tool m_tool = Tool::Draw;
|
||||||
|
size_t m_palPage = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TileSheetEditorImGui(turbine::Context &ctx, ox::CRStringView path);
|
TileSheetEditorImGui(turbine::Context &ctx, ox::CRStringView path);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <ox/claw/read.hpp>
|
#include <ox/claw/read.hpp>
|
||||||
|
#include <ox/std/algorithm.hpp>
|
||||||
#include <ox/std/buffer.hpp>
|
#include <ox/std/buffer.hpp>
|
||||||
#include <ox/std/memory.hpp>
|
#include <ox/std/memory.hpp>
|
||||||
|
|
||||||
@ -25,8 +26,8 @@
|
|||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
const Palette TileSheetEditorModel::s_defaultPalette = {
|
Palette const TileSheetEditorModel::s_defaultPalette = {
|
||||||
.colors = ox::Vector<Color16>(128),
|
.pages = {ox::Vector<Color16>(128)},
|
||||||
};
|
};
|
||||||
|
|
||||||
TileSheetEditorModel::TileSheetEditorModel(turbine::Context &ctx, ox::StringView path, studio::UndoStack &undoStack):
|
TileSheetEditorModel::TileSheetEditorModel(turbine::Context &ctx, ox::StringView path, studio::UndoStack &undoStack):
|
||||||
@ -114,6 +115,15 @@ ox::Error TileSheetEditorModel::setPalette(ox::StringView path) noexcept {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TileSheetEditorModel::setPalettePage(size_t pg) noexcept {
|
||||||
|
m_palettePage = ox::clamp<size_t>(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 {
|
void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t palIdx) noexcept {
|
||||||
const auto &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
|
const auto &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
|
||||||
if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) {
|
if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) {
|
||||||
|
@ -23,12 +23,13 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
|||||||
ox::Signal<ox::Error()> paletteChanged;
|
ox::Signal<ox::Error()> paletteChanged;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const Palette s_defaultPalette;
|
static Palette const s_defaultPalette;
|
||||||
turbine::Context &m_ctx;
|
turbine::Context &m_ctx;
|
||||||
ox::String m_path;
|
ox::String m_path;
|
||||||
TileSheet m_img;
|
TileSheet m_img;
|
||||||
TileSheet::SubSheetIdx m_activeSubsSheetIdx;
|
TileSheet::SubSheetIdx m_activeSubsSheetIdx;
|
||||||
keel::AssetRef<Palette> m_pal;
|
keel::AssetRef<Palette> m_pal;
|
||||||
|
size_t m_palettePage{};
|
||||||
studio::UndoStack &m_undoStack;
|
studio::UndoStack &m_undoStack;
|
||||||
class DrawCommand *m_ongoingDrawCommand = nullptr;
|
class DrawCommand *m_ongoingDrawCommand = nullptr;
|
||||||
bool m_updated = false;
|
bool m_updated = false;
|
||||||
@ -48,19 +49,24 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
|||||||
void paste();
|
void paste();
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr const TileSheet &img() const noexcept;
|
constexpr TileSheet const&img() const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr TileSheet &img() noexcept;
|
constexpr TileSheet &img() noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
constexpr const Palette *pal() const noexcept;
|
constexpr Palette const*pal() const noexcept;
|
||||||
|
|
||||||
[[nodiscard]]
|
[[nodiscard]]
|
||||||
ox::StringView palPath() const noexcept;
|
ox::StringView palPath() const noexcept;
|
||||||
|
|
||||||
ox::Error setPalette(ox::StringView path) 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 drawCommand(ox::Point const&pt, std::size_t palIdx) noexcept;
|
||||||
|
|
||||||
void endDrawCommand() 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;
|
return m_img;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,7 +139,7 @@ constexpr TileSheet &TileSheetEditorModel::img() noexcept {
|
|||||||
return m_img;
|
return m_img;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const Palette *TileSheetEditorModel::pal() const noexcept {
|
constexpr Palette const*TileSheetEditorModel::pal() const noexcept {
|
||||||
if (m_pal) {
|
if (m_pal) {
|
||||||
return m_pal.get();
|
return m_pal.get();
|
||||||
}
|
}
|
||||||
|
@ -103,7 +103,7 @@ void TileSheetPixels::setBufferObjects(ox::Vec2 const&paneSize) noexcept {
|
|||||||
m_bufferSet.elements.resize(pixels * VertexEboLength);
|
m_bufferSet.elements.resize(pixels * VertexEboLength);
|
||||||
// set pixels
|
// set pixels
|
||||||
walkPixels(*subSheet, m_model.img().bpp, [&](std::size_t i, uint8_t p) {
|
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<int>(i), subSheet->columns);
|
const auto pt = idxToPt(static_cast<int>(i), subSheet->columns);
|
||||||
const auto fx = static_cast<float>(pt.x);
|
const auto fx = static_cast<float>(pt.x);
|
||||||
const auto fy = static_cast<float>(pt.y);
|
const auto fy = static_cast<float>(pt.y);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user