Squashed 'deps/nostalgia/' changes from 5f10edd3..0daf938f

0daf938f [nostalgia/core/studio] Cleanup, make all number keys after num colors jump to last
b90ab27a [nostalgia/core/studio] Fix Palette Color Name input to properly take focus
c711f435 [nostalgia/core/studio] Fix PaletteEditor 0 key shortcut
84cb03d8 [nostalgia/core/studio] Cleanup
945a55f9 [studio] Fix Project to cut off correct end of OC data
2173b12c [nostalgia/core/studio] Give PaletteEditor keyboard shortcuts
aa970b1f [keel,studio] Cleanup
6ad79b30 [ox] Cleanup
a7cf2673 [studio] Remove null terminator from OC output
1a9f0d49 [ox] Rename CRString to StringCR
a1b5b565 [olympic,nostalgia] Rename CRStringView to StringViewCR
256be6da [glutils] Rename CRStringView to StringViewCR
cc10631b [ox] Rename CRStringView to StringViewCR
829dc029 [keel] Fix Linux build
e8a1ff06 [ox/oc] Fix Linux build
bdfb5e97 [nostalgia/core] Cleanup
396fecab [ox/oc] Add option for writeOC to return a string
5373b63c [keel,studio] Removing null terminator from JSON file output
8b655c40 [ox/std] Add HashMap::values
92d85d11 Merge commit '9f5f3e26efed6cd27f2a8ff0746f018d75986934'
118fef61 [buildcore] Remove python -m prefix from mypy command
8769305d [nostalgia] Allow disabling of BUILD_SHARED_LIBS
c5999050 [nostalgia] Add support for partial tilesheet loading
da23c930 [ox/std] Add oxModelFwdDecl macro for broken Apple Clang
3ae1d6c8 [ox/std] Make operator[] in Array and Vector nodiscard
a7af6c66 [keel] Cleanup
0cc6757c [keel] Add manifest to pack output
3b8eaef3 [keel] Move vald and repair funcs to their own file, make conversion to validation
b7990ed2 [keel] Make pack file copy logging nest for dir level
71313ed8 [ox/std] Cleanup
10531b6e [keel] Cleanup
dfbc298d [keel] Add pack file copy status to logging
76760daf [ox/std] Cleanup Defer
5834b9c9 [ox/std] Cleanup logging output
2a584905 [ox/fs] More cleanup and bug fix from previous cleanup
702b166b [ox/fs] Cleanup
8dd837b3 [nostalgia/core] Add a valid function for CompactTileSheet
1d262597 [keel] Make default repair return a no repair error
712299fa [studio] Cleanup
c45efa60 [ox/std] Make Result copyTo and moveTo able to convert

git-subtree-dir: deps/nostalgia
git-subtree-split: 0daf938f765b3a3ce8ba7fb292572a6a5a004634
This commit is contained in:
2024-09-28 23:44:24 -05:00
parent 9f5f3e26ef
commit 511548a2ee
99 changed files with 932 additions and 681 deletions

View File

@ -139,7 +139,15 @@ ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
CompactTileSheet const&ts,
ox::Optional<unsigned> const&paletteBank) noexcept;
size_t dstTileIdx,
size_t srcTileIdx,
size_t tileCnt) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
CompactTileSheet const&ts,
ox::Optional<unsigned> const&paletteBank = {}) noexcept;
ox::Error loadBgTileSheet(
Context &ctx,
@ -192,7 +200,7 @@ uint_t spriteCount(Context &ctx) noexcept;
ox::Error initConsole(Context &ctx) noexcept;
void puts(Context &ctx, int column, int row, ox::CRStringView str) noexcept;
void puts(Context &ctx, int column, int row, ox::StringViewCR str) noexcept;
}

View File

@ -67,12 +67,22 @@ struct NostalgiaPalette {
ox::Vector<Color16> colors = {};
};
oxModelBegin(NostalgiaPalette)
oxModelField(colors)
oxModelEnd()
struct PaletteV1 {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette";
static constexpr auto TypeVersion = 1;
ox::Vector<Color16> colors;
};
oxModelBegin(PaletteV1)
oxModelField(colors)
oxModelEnd()
struct PaletteV2 {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette";
static constexpr auto TypeVersion = 2;
@ -80,6 +90,10 @@ struct PaletteV2 {
ox::Vector<ox::Vector<Color16>> pages;
};
oxModelBegin(PaletteV2)
oxModelField(pages)
oxModelEnd()
struct PaletteV3 {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.Palette";
@ -96,6 +110,15 @@ struct PaletteV3 {
ox::Vector<ox::Vector<Color16>> pages;
};
oxModelBegin(PaletteV3::ColorInfo)
oxModelField(name)
oxModelEnd()
oxModelBegin(PaletteV3)
oxModelField(colorInfo)
oxModelField(pages)
oxModelEnd()
[[nodiscard]]
constexpr bool valid(PaletteV3 const&p) noexcept {
auto const colors = p.colorInfo.size();
@ -121,6 +144,11 @@ struct PaletteV4 {
ox::Vector<PalettePageV1> pages;
};
oxModelBegin(PaletteV4)
oxModelField(colorNames)
oxModelField(pages)
oxModelEnd()
[[nodiscard]]
constexpr bool valid(PaletteV4 const&p) noexcept {
auto const colors = p.colorNames.size();
@ -148,6 +176,10 @@ struct CompactPaletteV1 {
ox::Vector<ox::Vector<Color16>> pages{};
};
oxModelBegin(CompactPaletteV1)
oxModelField(pages)
oxModelEnd()
[[nodiscard]]
constexpr bool valid(CompactPaletteV1 const&p) noexcept {
size_t colors{};
@ -254,34 +286,4 @@ constexpr size_t largestPage(CompactPalette const&pal) noexcept {
return out;
}
oxModelBegin(NostalgiaPalette)
oxModelField(colors)
oxModelEnd()
oxModelBegin(PaletteV1)
oxModelField(colors)
oxModelEnd()
oxModelBegin(PaletteV2)
oxModelField(pages)
oxModelEnd()
oxModelBegin(PaletteV3::ColorInfo)
oxModelField(name)
oxModelEnd()
oxModelBegin(PaletteV3)
oxModelField(colorInfo)
oxModelField(pages)
oxModelEnd()
oxModelBegin(PaletteV4)
oxModelField(colorNames)
oxModelField(pages)
oxModelEnd()
oxModelBegin(CompactPaletteV1)
oxModelField(pages)
oxModelEnd()
}

View File

@ -31,6 +31,12 @@ struct TileSheetV1 {
ox::Vector<uint8_t> pixels = {};
};
[[nodiscard]]
constexpr bool valid(TileSheetV1 const&ts) noexcept {
return ts.bpp == 4 || ts.bpp == 8;
}
struct TileSheetV2 {
using SubSheetIdx = ox::Vector<std::size_t, 4>;
@ -43,8 +49,8 @@ struct TileSheetV2 {
ox::Vector<SubSheet> subsheets;
ox::Vector<uint8_t> pixels;
constexpr SubSheet() noexcept = default;
constexpr SubSheet(ox::CRStringView pName, int pColumns, int pRows, int bpp) noexcept:
name(pName),
constexpr SubSheet(ox::StringParam pName, int pColumns, int pRows, int bpp) noexcept:
name(std::move(pName)),
columns(pColumns),
rows(pRows),
pixels(static_cast<size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
@ -59,6 +65,12 @@ struct TileSheetV2 {
};
[[nodiscard]]
constexpr bool valid(TileSheetV2 const&ts) noexcept {
return ts.bpp == 4 || ts.bpp == 8;
}
using SubSheetId = int32_t;
struct TileSheetV3 {
@ -74,14 +86,14 @@ struct TileSheetV3 {
ox::Vector<SubSheet> subsheets;
ox::Vector<uint8_t> pixels;
constexpr SubSheet() noexcept = default;
inline SubSheet(
SubSheet(
SubSheetId pId,
ox::CRStringView pName,
ox::StringParam pName,
int pColumns,
int pRows,
int bpp) noexcept:
id(pId),
name(pName),
name(std::move(pName)),
columns(pColumns),
rows(pRows),
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
@ -98,7 +110,13 @@ struct TileSheetV3 {
};
struct TileSheet {
[[nodiscard]]
constexpr bool valid(TileSheetV3 const&ts) noexcept {
return ts.bpp == 4 || ts.bpp == 8;
}
struct TileSheetV4 {
using SubSheetIdx = ox::Vector<std::size_t, 4>;
struct SubSheet {
@ -112,26 +130,26 @@ struct TileSheet {
ox::Vector<uint8_t> pixels;
constexpr SubSheet() noexcept = default;
inline SubSheet(
SubSheet(
SubSheetId pId,
ox::CRStringView pName,
ox::StringParam pName,
int pColumns,
int pRows,
int bpp) noexcept:
id(pId),
name(pName),
name(std::move(pName)),
columns(pColumns),
rows(pRows),
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
}
inline SubSheet(
SubSheet(
SubSheetId pId,
ox::CRStringView pName,
ox::StringParam pName,
int pColumns,
int pRows,
ox::Vector<uint8_t> pPixels) noexcept:
id(pId),
name(pName),
name(std::move(pName)),
columns(pColumns),
rows(pRows),
pixels(std::move(pPixels)) {
@ -151,10 +169,18 @@ struct TileSheet {
ox::FileAddress defaultPalette;
SubSheet subsheet{0, "Root", 1, 1, bpp};
constexpr TileSheet() noexcept = default;
constexpr TileSheetV4() noexcept = default;
};
[[nodiscard]]
constexpr bool valid(TileSheetV4 const&ts) noexcept {
return ts.bpp == 4 || ts.bpp == 8;
}
using TileSheet = TileSheetV4;
[[nodiscard]]
std::size_t idx(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
@ -280,18 +306,17 @@ uint8_t getPixel8Bpp(
ox::Point const&pt,
TileSheet::SubSheetIdx const&subsheetIdx) noexcept;
ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::CRStringView path) noexcept;
ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::StringViewCR path) noexcept;
ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::CRStringView pNamePath) noexcept;
ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept;
ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId pId) noexcept;
ox::Result<ox::StringView> getNameFor(TileSheet const&ss, SubSheetId pId) noexcept;
ox::Result<ox::StringView> getNameFor(TileSheet const&ts, SubSheetId pId) noexcept;
[[nodiscard]]
ox::Vector<uint8_t> pixels(TileSheet &ts) noexcept;
using TileSheetV4 = TileSheet;
struct CompactTileSheetV1 {
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
@ -302,8 +327,34 @@ struct CompactTileSheetV1 {
ox::Vector<uint8_t> pixels;
};
[[nodiscard]]
constexpr bool valid(CompactTileSheetV1 const&ts) noexcept {
return ts.bpp == 4 || ts.bpp == 8;
}
using CompactTileSheet = CompactTileSheetV1;
[[nodiscard]]
uint8_t getPixel4Bpp(
CompactTileSheet const&ts,
size_t idx) noexcept;
[[nodiscard]]
uint8_t getPixel8Bpp(
CompactTileSheet const&ts,
size_t idx) noexcept;
[[nodiscard]]
ox::Pair<uint8_t> get2Pixels4Bpp(
CompactTileSheet const&ts,
size_t idx) noexcept;
[[nodiscard]]
ox::Pair<uint8_t> get2Pixels8Bpp(
CompactTileSheet const&ts,
size_t idx) noexcept;
oxModelBegin(TileSheetV1)
oxModelField(bpp)
oxModelField(rows)

View File

@ -3,7 +3,6 @@
*/
#include <ox/fs/fs.hpp>
#include <ox/mc/mc.hpp>
#include <ox/std/array.hpp>
#include <teagba/addresses.hpp>
@ -11,9 +10,7 @@
#include <teagba/registers.hpp>
#include <keel/keel.hpp>
#include <turbine/turbine.hpp>
#include <nostalgia/core/color.hpp>
#include <nostalgia/core/context.hpp>
#include <nostalgia/core/gfx.hpp>
#include <nostalgia/core/tilesheet.hpp>
@ -22,7 +19,7 @@
namespace nostalgia::core {
constexpr auto SpriteCount = 128;
static constexpr auto SpriteCount = 128;
ox::Error initGfx(Context&, InitParams const&) noexcept {
for (auto bgCtl = &REG_BG0CTL; bgCtl <= &REG_BG3CTL; bgCtl += 2) {
@ -81,7 +78,7 @@ ox::Error loadSpritePalette(
static ox::Error loadTileSheetSet(
Context &ctx,
uint16_t *tileMapTargetMem,
ox::Span<uint16_t> tileMapTargetMem,
TileSheetSet const&set) noexcept {
size_t tileWriteIdx = 0;
size_t const bppMod = set.bpp == 4;
@ -106,6 +103,34 @@ static ox::Error loadTileSheetSet(
return {};
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned const cbb,
CompactTileSheet const&ts,
size_t const dstTileIdx,
size_t const srcTileIdx,
size_t const tileCnt) noexcept {
size_t const bppMod = ts.bpp == 4;
size_t const bytesPerTile = PixelsPerTile >> bppMod;
auto const pixCnt = tileCnt * bytesPerTile;
auto const srcPxIdx = srcTileIdx * bytesPerTile;
auto const dstPxIdx = (dstTileIdx * bytesPerTile) / 2;
for (size_t i = 0; i < pixCnt; ++i) {
auto const srcIdx = srcPxIdx + i * 2;
auto const p1 = static_cast<uint16_t>(ts.pixels[srcIdx]);
auto const p2 = static_cast<uint16_t>(ts.pixels[srcIdx + 1]);
MEM_BG_TILES[cbb][dstPxIdx + i] = static_cast<uint16_t>(p1 | (p2 << 8));
}
// update bpp of all bgs with the updated cbb
auto const bpp = ctx.cbbData[cbb].bpp;
teagba::iterateBgCtl([bpp, cbb](volatile BgCtl &bgCtl) {
if (teagba::bgCbb(bgCtl) == cbb) {
teagba::bgSetBpp(bgCtl, bpp);
}
});
return {};
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
@ -142,10 +167,10 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet(
Context &ctx,
unsigned cbb,
unsigned const cbb,
TileSheetSet const&set) noexcept {
auto const bpp = static_cast<unsigned>(set.bpp);
oxReturnError(loadTileSheetSet(ctx, MEM_BG_TILES[cbb].data(), set));
oxReturnError(loadTileSheetSet(ctx, MEM_BG_TILES[cbb], set));
// update bpp of all bgs with the updated cbb
ctx.cbbData[cbb].bpp = bpp;
teagba::iterateBgCtl([bpp, cbb](volatile BgCtl &bgCtl) {
@ -193,7 +218,7 @@ ox::Error loadSpriteTileSheet(
Context &ctx,
TileSheetSet const&set) noexcept {
auto const bpp = static_cast<unsigned>(set.bpp);
oxReturnError(loadTileSheetSet(ctx, MEM_SPRITE_TILES, set));
oxReturnError(loadTileSheetSet(ctx, {MEM_SPRITE_TILES, 32 * ox::units::KB}, set));
setSpritesBpp(bpp);
return {};
}

View File

@ -168,7 +168,7 @@ void puts(
Context &ctx,
int const column,
int const row,
ox::CRStringView str) noexcept {
ox::StringViewCR str) noexcept {
auto const col = static_cast<uint_t>(column);
for (auto i = 0u; i < str.bytes(); ++i) {
setBgTile(

View File

@ -22,8 +22,8 @@ namespace nostalgia::core {
namespace renderer {
constexpr auto Scale = 1;
constexpr auto PriorityScale = 0.01f;
static constexpr auto Scale = 1;
static constexpr auto PriorityScale = 0.01f;
Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {}
@ -31,7 +31,7 @@ void Drawer::draw(turbine::Context &tctx) noexcept {
core::gl::draw(m_ctx, turbine::getScreenSize(tctx));
}
constexpr ox::CStringView bgvshadTmpl = R"glsl(
static constexpr ox::CStringView bgvshadTmpl = R"glsl(
{}
in vec2 vTexCoord;
in vec3 vPosition;
@ -55,7 +55,7 @@ constexpr ox::CStringView bgvshadTmpl = R"glsl(
fPalOffset = vPalOffset;
})glsl";
constexpr ox::CStringView bgfshadTmpl = R"glsl(
static constexpr ox::CStringView bgfshadTmpl = R"glsl(
{}
out vec4 outColor;
in float fPalOffset;
@ -71,7 +71,7 @@ constexpr ox::CStringView bgfshadTmpl = R"glsl(
}
})glsl";
constexpr ox::CStringView spritevshadTmpl = R"glsl(
static constexpr ox::CStringView spritevshadTmpl = R"glsl(
{}
in float vEnabled;
in vec3 vPosition;
@ -90,7 +90,7 @@ constexpr ox::CStringView spritevshadTmpl = R"glsl(
fTexCoord = vTexCoord * vec2(1, vTileHeight);
})glsl";
constexpr ox::CStringView spritefshadTmpl = R"glsl(
static constexpr ox::CStringView spritefshadTmpl = R"glsl(
{}
out vec4 outColor;
in vec2 fTexCoord;
@ -279,7 +279,7 @@ static void initBackgroundBufferset(
static glutils::GLTexture createTexture(
GLsizei w,
GLsizei h,
const void *pixels) noexcept {
void const*pixels) noexcept {
GLuint texId = 0;
glGenTextures(1, &texId);
glutils::GLTexture tex(texId);
@ -492,22 +492,22 @@ struct TileSheetData {
};
static ox::Result<TileSheetData> normalizeTileSheet(
CompactTileSheet const&tilesheet) noexcept {
const uint_t bytesPerTile = tilesheet.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2;
const auto tiles = tilesheet.pixels.size() / bytesPerTile;
CompactTileSheet const&ts) noexcept {
const uint_t bytesPerTile = ts.bpp == 8 ? PixelsPerTile : PixelsPerTile / 2;
const auto tiles = ts.pixels.size() / bytesPerTile;
constexpr int width = 8;
const int height = 8 * static_cast<int>(tiles);
ox::Vector<uint32_t> pixels;
if (bytesPerTile == 64) { // 8 BPP
pixels.resize(tilesheet.pixels.size());
for (std::size_t i = 0; i < tilesheet.pixels.size(); ++i) {
pixels[i] = tilesheet.pixels[i];
pixels.resize(ts.pixels.size());
for (std::size_t i = 0; i < ts.pixels.size(); ++i) {
pixels[i] = ts.pixels[i];
}
} else { // 4 BPP
pixels.resize(tilesheet.pixels.size() * 2);
for (std::size_t i = 0; i < tilesheet.pixels.size(); ++i) {
pixels[i * 2 + 0] = tilesheet.pixels[i] & 0xF;
pixels[i * 2 + 1] = tilesheet.pixels[i] >> 4;
pixels.resize(ts.pixels.size() * 2);
for (std::size_t i = 0; i < ts.pixels.size(); ++i) {
pixels[i * 2 + 0] = ts.pixels[i] & 0xF;
pixels[i * 2 + 1] = ts.pixels[i] >> 4;
}
}
return TileSheetData{std::move(pixels), width, height};
@ -572,14 +572,58 @@ static ox::Result<TileSheetData> buildSetTsd(
return setTsd;
}
static void copyPixels(
CompactTileSheet const&ts,
uint32_t *dst,
size_t const srcPxIdx,
size_t pxlCnt) noexcept {
if (ts.bpp == 4) {
for (size_t i = 0; i < pxlCnt; i += 2) {
auto const [a, b] = get2Pixels4Bpp(ts, i + srcPxIdx);
*(dst++) = a;
*(dst++) = b;
}
} else if (ts.bpp == 8) {
for (size_t i = 0; i < pxlCnt; i += 2) {
auto const [a, b] = get2Pixels8Bpp(ts, i + srcPxIdx);
*(dst++) = a;
*(dst++) = b;
}
}
}
ox::Error loadBgTileSheet(
Context &ctx,
unsigned const cbb,
CompactTileSheet const&ts,
size_t const dstTileIdx,
size_t const srcTileIdx,
size_t const tileCnt) noexcept {
auto &cbbPxls = ctx.cbbs[cbb].pixels;
auto const bytesPerTile = static_cast<uint64_t>(PixelsPerTile / (1 + (ts.bpp == 4)));
auto const pxlCnt = tileCnt * PixelsPerTile;
auto const srcPxIdx = srcTileIdx * PixelsPerTile;
auto const dstPxIdx = dstTileIdx * PixelsPerTile;
if (dstPxIdx + pxlCnt >= cbbPxls.size()) {
return OxError(1, "video mem dst overflow");
}
auto const dst = &cbbPxls[dstPxIdx];
copyPixels(ts, dst, srcPxIdx, pxlCnt);
auto const cbbTiles = cbbPxls.size() / bytesPerTile;
int constexpr cbbWidth = 8;
int const cbbHeight = 8 * static_cast<int>(cbbTiles);
ctx.cbbs[cbb].tex = renderer::createTexture(cbbWidth, cbbHeight, cbbPxls.data());
return {};
}
ox::Error loadBgTileSheet(
Context &ctx,
uint_t cbb,
CompactTileSheet const&ts,
ox::Optional<unsigned> const&paletteBank) noexcept {
oxRequire(tsd, normalizeTileSheet(ts));
oxTracef("nostalgia.core.gfx.gl", "loadBgTexture: { cbbIdx: {}, w: {}, h: {} }", cbb, tsd.width, tsd.height);
ctx.cbbs[cbb].tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data());
auto const bytesPerTile = static_cast<uint64_t>(PixelsPerTile / (1 + (ts.bpp == 4)));
auto const tiles = ts.pixels.size() / bytesPerTile;
oxReturnError(loadBgTileSheet(ctx, cbb, ts, 0, 0, tiles));
if (paletteBank.has_value() && ts.defaultPalette) {
oxReturnError(loadBgPalette(ctx, *paletteBank, ts.defaultPalette));
}

View File

@ -28,6 +28,7 @@ constexpr uint64_t SpriteVertexEboLength = 6;
struct CBB: public glutils::BufferSet {
bool updated = false;
ox::Array<uint32_t, 32768> pixels;
constexpr CBB() noexcept {
vertices.resize(TileCount * BgVertexVboLength);
elements.resize(TileCount * BgVertexEboLength);

View File

@ -41,7 +41,7 @@ PaletteEditorImGui::PaletteEditorImGui(studio::StudioContext &sctx, ox::StringPa
m_sctx(sctx),
m_tctx(sctx.tctx),
m_pal(*keel::readObj<Palette>(keelCtx(m_tctx), itemPath()).unwrapThrow()) {
if (!valid(m_pal)) {
if (keel::ensureValid(m_pal).errCode) {
throw OxException(1, "PaletteEditorImGui: invalid Palette object");
}
undoStack()->changeTriggered.connect(this, &PaletteEditorImGui::handleCommand);
@ -98,6 +98,12 @@ void PaletteEditorImGui::drawColumn(ox::CStringView txt) noexcept {
ImGui::Text("%s", txt.c_str());
}
void PaletteEditorImGui::colorInput(ox::CStringView label, int &v, bool &inputFocused) noexcept {
ImGui::InputInt(label.c_str(), &v, 1, 5);
inputFocused = inputFocused || ImGui::IsItemFocused();
v = ox::max(v, 0);
}
void PaletteEditorImGui::drawColorsEditor() noexcept {
constexpr auto tableFlags = ImGuiTableFlags_RowBg;
auto const colorsSz = ImGui::GetContentRegionAvail();
@ -238,17 +244,27 @@ void PaletteEditorImGui::drawColorEditor() noexcept {
ox::IString<50> name;
name = currentName;
ImGui::InputText("Name", name.data(), name.cap() + 1);
bool inputFocused = ImGui::IsItemFocused();
ImGui::Separator();
ImGui::InputInt("Red", &r, 1, 5);
ImGui::InputInt("Green", &g, 1, 5);
ImGui::InputInt("Blue", &b, 1, 5);
colorInput("Red", r, inputFocused);
colorInput("Green", g, inputFocused);
colorInput("Blue", b, inputFocused);
if (ig::PushButton("Apply to all pages", {-1, ig::BtnSz.y})) {
std::ignore = pushCommand<ApplyColorAllPagesCommand>(
m_pal, m_page, m_selectedColorRow);
}
r = ox::max(r, 0);
g = ox::max(g, 0);
b = ox::max(b, 0);
if (!inputFocused) {
auto const lastColor = largestPage(m_pal) - 1;
if (ImGui::IsKeyPressed(ImGuiKey_0, false)) {
m_selectedColorRow = ox::min<size_t>(9, lastColor);
} else for (auto i = 9u; i < 10; --i) {
auto const key = static_cast<ImGuiKey>(ImGuiKey_1 + i);
if (ImGui::IsKeyPressed(key, false)) {
m_selectedColorRow = ox::min<size_t>(i, lastColor);
break;
}
}
}
auto const newColor = color16(r, g, b, a);
if (c != newColor) {
std::ignore = pushCommand<UpdateColorCommand>(m_pal, m_page, m_selectedColorRow, newColor);

View File

@ -56,6 +56,8 @@ class PaletteEditorImGui: public studio::Editor {
drawColumn(ox::itoa(i));
}
static void colorInput(ox::CStringView label, int &v, bool &inputFocused) noexcept;
void drawColorsEditor() noexcept;
void drawPagesEditor() noexcept;

View File

@ -10,6 +10,8 @@
namespace nostalgia::core {
oxModelFwdDecl(class TileSheetClipboard);
class TileSheetClipboard: public turbine::ClipboardObject<TileSheetClipboard> {
public:
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.studio.TileSheetClipboard";

View File

@ -9,7 +9,7 @@ namespace nostalgia::core {
core::PaletteChangeCommand::PaletteChangeCommand(
TileSheet::SubSheetIdx idx,
TileSheet &img,
ox::CRStringView newPalette) noexcept:
ox::StringViewCR newPalette) noexcept:
m_img(img),
m_idx(std::move(idx)),
m_oldPalette(m_img.defaultPalette),

View File

@ -19,7 +19,7 @@ class PaletteChangeCommand: public TileSheetCommand {
PaletteChangeCommand(
TileSheet::SubSheetIdx idx,
TileSheet &img,
ox::CRStringView newPalette) noexcept;
ox::StringViewCR newPalette) noexcept;
ox::Error redo() noexcept final;

View File

@ -312,9 +312,8 @@ void TileSheetEditorImGui::drawSubsheetSelector(
for (auto i = 0ul; auto &child : subsheet.subsheets) {
path.push_back(i);
ImGui::PushID(static_cast<int>(i));
ImGui::Indent(-indentReduce);
ig::IndentStackItem const indentStackItem{-indentReduce};
drawSubsheetSelector(child, path);
ImGui::Indent(indentReduce);
ImGui::PopID();
path.pop_back();
++i;
@ -440,7 +439,7 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept {
}
auto const pages = m_model.pal().pages.size();
if (pages > 1) {
ImGui::Indent(20);
ig::IndentStackItem const indentStackItem{20};
using Str = ox::IString<55>;
auto numStr = ox::sfmt<Str>(
"{} - {}", m_model.palettePage() + 1, m_model.pal().pages[m_model.palettePage()].name);
@ -458,7 +457,6 @@ void TileSheetEditorImGui::drawPaletteSelector() noexcept {
}
ImGui::EndCombo();
}
ImGui::Indent(-20);
}
// header
if (ImGui::BeginTable(

View File

@ -280,7 +280,7 @@ uint8_t getPixel4Bpp(
TileSheet::SubSheetIdx const&subsheetIdx) noexcept {
oxAssert(ts.bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp");
auto &s = getSubSheet(ts, subsheetIdx);
const auto idx = ptToIdx(pt, s.columns);
auto const idx = ptToIdx(pt, s.columns);
return getPixel4Bpp(s, idx);
}
@ -290,10 +290,49 @@ uint8_t getPixel8Bpp(
TileSheet::SubSheetIdx const&subsheetIdx) noexcept {
oxAssert(ts.bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp");
auto &s = getSubSheet(ts, subsheetIdx);
const auto idx = ptToIdx(pt, s.columns);
auto const idx = ptToIdx(pt, s.columns);
return getPixel8Bpp(s, idx);
}
uint8_t getPixel4Bpp(
CompactTileSheet const&ts,
size_t const idx) noexcept {
oxAssert(ts.bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp");
if (idx & 1) {
return ts.pixels[idx / 2] >> 4;
} else {
return ts.pixels[idx / 2] & 0b0000'1111;
}
}
uint8_t getPixel8Bpp(
CompactTileSheet const&ts,
size_t const idx) noexcept {
oxAssert(ts.bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp");
return ts.pixels[idx];
}
ox::Pair<uint8_t> get2Pixels4Bpp(
CompactTileSheet const&ts,
size_t const idx) noexcept {
oxAssert(ts.bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp");
auto const out = ts.pixels[idx / 2];
return {
static_cast<uint8_t>(out & 0x0f),
static_cast<uint8_t>(out >> 4),
};
}
ox::Pair<uint8_t> get2Pixels8Bpp(
CompactTileSheet const&ts,
size_t const idx) noexcept {
oxAssert(ts.bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp");
return {
static_cast<uint8_t>(ts.pixels[idx]),
static_cast<uint8_t>(ts.pixels[idx + 1]),
};
}
static ox::Result<SubSheetId> getIdFor(
TileSheet::SubSheet const&ss,
ox::SpanView<ox::StringView> const&pNamePath,
@ -309,7 +348,7 @@ static ox::Result<SubSheetId> getIdFor(
return OxError(1, "SubSheet not found");
}
ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::CRStringView path) noexcept {
ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::StringViewCR path) noexcept {
return getIdFor(ts.subsheet, ox::split<8>(path, '.'));
}
@ -340,7 +379,7 @@ static ox::Result<unsigned> getTileOffset(
return OxError(1, "SubSheet not found");
}
ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::CRStringView pNamePath) noexcept {
ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::StringViewCR pNamePath) noexcept {
return core::getTileOffset(ts.subsheet, ox::split<8>(pNamePath, '.'), ts.bpp);
}

View File

@ -8,7 +8,7 @@
namespace nostalgia::scene {
SceneEditor::SceneEditor(turbine::Context &ctx, ox::CRStringView path):
SceneEditor::SceneEditor(turbine::Context &ctx, ox::StringViewCR path):
m_ctx(ctx),
m_scene(*keel::readObj<SceneStatic>(keelCtx(m_ctx), path).unwrapThrow()) {
}

View File

@ -19,7 +19,7 @@ class SceneEditor {
SceneStatic m_scene;
public:
SceneEditor(turbine::Context &ctx, ox::CRStringView path);
SceneEditor(turbine::Context &ctx, ox::StringViewCR path);
[[nodiscard]]
SceneStatic const&scene() const noexcept {