Compare commits

..

10 Commits

Author SHA1 Message Date
0de428a2e5 [studio/applib] Cleanup
All checks were successful
Build / build (push) Successful in 1m19s
2025-05-14 22:11:43 -05:00
8a52df4f76 [nostalgia/gfx] More cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-05-14 01:43:59 -05:00
efec6eb3c8 [nostalgia/gfx/studio/palette] Add RGB key shortcuts for focusing color channels
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-14 01:13:40 -05:00
56eeb24900 [nostalgia/gfx/opengl] More cleanup
All checks were successful
Build / build (push) Successful in 1m56s
2025-05-13 22:06:08 -05:00
ae81f6b3de [ox/std] Make Span::operator[] const
All checks were successful
Build / build (push) Successful in 1m17s
2025-05-13 22:02:23 -05:00
c1108301c0 [nostalgia/gfx] Cleanup 2025-05-13 22:01:59 -05:00
83fbe6ac74 [keel,turbine,studio] Fix some install mistakes
All checks were successful
Build / build (push) Successful in 2m17s
2025-05-13 21:39:37 -05:00
80b452833f [nostalgia/gfx] Cleanup
All checks were successful
Build / build (push) Successful in 2m28s
2025-05-13 21:24:04 -05:00
0fa394333b [nostalgia] Add release note about Mac menubar using Cmd
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-10 01:01:11 -05:00
cae7535034 [nostalgia] Fix typos in release notes
All checks were successful
Build / build (push) Successful in 1m15s
2025-05-10 00:57:45 -05:00
22 changed files with 150 additions and 155 deletions

View File

@@ -11,7 +11,6 @@
# "Python Busy Box" - adds cross-platform equivalents to Unix commands that # "Python Busy Box" - adds cross-platform equivalents to Unix commands that
# don't translate well to that other operating system # don't translate well to that other operating system
import multiprocessing
import os import os
import platform import platform
import shutil import shutil
@@ -58,11 +57,7 @@ def cmake_build(base_path: str, target: Optional[str]) -> int:
path = os.path.join(base_path, d) path = os.path.join(base_path, d)
if not os.path.isdir(path): if not os.path.isdir(path):
continue continue
args = ['cmake', '--build', path, f'-j{multiprocessing.cpu_count()}'] args = ['cmake', '--build', path]
if path.endswith('release'):
args.append('--config=release')
elif path.endswith('debug'):
args.append('--config=debug')
if target is not None: if target is not None:
args.extend(['--target', target]) args.extend(['--target', target])
err = subprocess.run(args).returncode err = subprocess.run(args).returncode

View File

@@ -24,6 +24,9 @@ enum class FileAddressType: int8_t {
Inode, Inode,
}; };
template<typename T>
constexpr Error model(T *h, CommonPtrWith<class FileAddress> auto *fa) noexcept;
class FileAddress { class FileAddress {
template<typename T> template<typename T>

View File

@@ -146,12 +146,7 @@ class Span {
return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size); return iterator<const T&, const T*, true>(m_items, MaxValue<size_type>, m_size);
} }
constexpr T &operator[](std::size_t i) noexcept { constexpr T &operator[](std::size_t i) const noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
return m_items[i];
}
constexpr T const&operator[](std::size_t i) const noexcept {
boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow"); boundsCheck(__FILE__, __LINE__, i, size(), "Span access overflow");
return m_items[i]; return m_items[i];
} }

View File

@@ -1,35 +1,24 @@
# d2025.06.0 # d2025.06.0
* Add ability to remember recent projects in config
* PaletteEditor: Add RGB key shortcuts for focusing color channels * PaletteEditor: Add RGB key shortcuts for focusing color channels
# d2025.05.2
* TileSheetEditor: Fix manual redo of draw actions, fix drawing to pixel 0, 0 as first action (cce5f52f96511694afd98f0b9b6b1f19c06ecd20)
* TileSheetEditor: Fix draw command to work on same pixel after switching subsheets (514cb978351ee4b0a5335c22a506a6d9f608f0a7)
# d2025.05.1
* TileSheetEditor: Fix overrun errors when switching subsheets, clear selection
on switch (261e324acd)
* Fix new build error that occurs in MSVC (26d5048e6720c4c2d52508a6ee44c67dd9fe3ee5)
# d2025.05.0 # d2025.05.0
* Add app icon for both window and file * Add app icon for both window and file
* Change application font to Roboto Medium * Change application font to Roboto Medium
* Closing application will now confirm with user if any files have unsaved * Closing application will now confirm with user if any files have unsaved
changes. changes.
* UUID duplicates will now be reported when opening a project * UUID duplicates will now be reported when opening a project.
* Deleting a directory now closes files in that directory * Deleting a directory now closes files in that directory.
* Delete key now initiates deletion of selected directory * Delete key now initiates deletion of selected directory.
* Remove ability to re-order tabs. There were bugs associated with that. * Remove ability to re-order tabs. There were bugs associated with that.
* TileSheetEditor: Fix selection clearing in to work when clicking outside * Mac: Menu bar shortcuts now say Cmd instead of Ctrl.
image. * TileSheetEditor: Fix selection clearing to work when clicking outside image.
* TileSheetEditor: Fix Delete Tile functionality, which was completely broken * TileSheetEditor: Fix Delete Tile functionality, which was completely broken
* PaletteEditor: Fix color number key range in. Previously, pressing A caused * TileSheetEditor: Fix Insert Tile functionality, which was completely broken
the editor to jump to the last color. * PaletteEditor: Fix color number key range. Previously, pressing A caused the
* PaletteEditor: page rename will now take effect upon pressing enter if the editor to jump to the last color.
* PaletteEditor: Page rename will now take effect upon pressing enter if the
text input has focus text input has focus
# d2025.02.1 # d2025.02.1

View File

@@ -223,7 +223,7 @@ bool bgStatus(Context &ctx, unsigned bg) noexcept;
void setBgStatus(Context &ctx, unsigned bg, bool status) noexcept; void setBgStatus(Context &ctx, unsigned bg, bool status) noexcept;
void setBgCbb(Context &ctx, unsigned bgIdx, unsigned cbb) noexcept; void setBgCbb(Context &ctx, unsigned bgIdx, unsigned cbbIdx) noexcept;
void setBgPriority(Context &ctx, uint_t bgIdx, uint_t priority) noexcept; void setBgPriority(Context &ctx, uint_t bgIdx, uint_t priority) noexcept;
@@ -231,10 +231,10 @@ void hideSprite(Context &ctx, unsigned) noexcept;
void showSprite(Context &ctx, unsigned) noexcept; void showSprite(Context &ctx, unsigned) noexcept;
void setSprite(Context &c, uint_t idx, Sprite const&s) noexcept; void setSprite(Context &ctx, uint_t idx, Sprite const&sprite) noexcept;
[[nodiscard]] [[nodiscard]]
uint_t spriteCount(Context &ctx) noexcept; uint_t spriteCount(Context const &ctx) noexcept;
ox::Error initConsole(Context &ctx) noexcept; ox::Error initConsole(Context &ctx) noexcept;

View File

@@ -22,7 +22,7 @@ ox::Error initGfx(Context &ctx, InitParams const&) noexcept;
ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&params) noexcept { ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&params) noexcept {
auto ctx = ox::make_unique<Context>(tctx); auto ctx = ox::make_unique<Context>(tctx);
OX_RETURN_ERROR(initGfx(*ctx, params)); OX_RETURN_ERROR(initGfx(*ctx, params));
return ox::UPtr<Context>(std::move(ctx)); return ctx;
} }
keel::Context &keelCtx(Context &ctx) noexcept { keel::Context &keelCtx(Context &ctx) noexcept {

View File

@@ -36,9 +36,9 @@ ox::Error initGfx(Context&, InitParams const&) noexcept {
ox::Error loadBgPalette( ox::Error loadBgPalette(
Context&, Context&,
size_t palBank, size_t const palBank,
CompactPalette const&palette, CompactPalette const&palette,
size_t page) noexcept { size_t const page) noexcept {
if (palette.pages.empty()) { if (palette.pages.empty()) {
return {}; return {};
} }
@@ -52,7 +52,7 @@ ox::Error loadBgPalette(
ox::Error loadSpritePalette( ox::Error loadSpritePalette(
Context&, Context&,
CompactPalette const&palette, CompactPalette const&palette,
size_t page) noexcept { size_t const page) noexcept {
if (palette.pages.empty()) { if (palette.pages.empty()) {
return {}; return {};
} }
@@ -133,7 +133,7 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet( ox::Error loadBgTileSheet(
Context &ctx, Context &ctx,
unsigned cbb, unsigned const cbb,
CompactTileSheet const&ts, CompactTileSheet const&ts,
ox::Optional<unsigned> const&paletteBank) noexcept { ox::Optional<unsigned> const&paletteBank) noexcept {
auto const cnt = (ts.pixels.size() * PixelsPerTile) / (1 + (ts.bpp == 4)); auto const cnt = (ts.pixels.size() * PixelsPerTile) / (1 + (ts.bpp == 4));
@@ -184,7 +184,7 @@ static void setSpritesBpp(unsigned const bpp) noexcept {
ox::Error loadSpriteTileSheet( ox::Error loadSpriteTileSheet(
Context &ctx, Context &ctx,
CompactTileSheet const&ts, CompactTileSheet const&ts,
bool loadDefaultPalette) noexcept { bool const loadDefaultPalette) noexcept {
for (size_t i = 0; i < ts.pixels.size(); i += 2) { for (size_t i = 0; i < ts.pixels.size(); i += 2) {
uint16_t v = ts.pixels[i]; uint16_t v = ts.pixels[i];
v |= static_cast<uint16_t>(ts.pixels[i + 1] << 8); v |= static_cast<uint16_t>(ts.pixels[i + 1] << 8);
@@ -206,7 +206,8 @@ ox::Error loadSpriteTileSheet(
return {}; return {};
} }
void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, BgTile const&tile) noexcept { void setBgTile(
Context &ctx, uint_t const bgIdx, int const column, int const row, BgTile const&tile) noexcept {
auto const tileIdx = static_cast<std::size_t>(row * tileColumns(ctx) + column); auto const tileIdx = static_cast<std::size_t>(row * tileColumns(ctx) + column);
// see Tonc 9.3 // see Tonc 9.3
MEM_BG_MAP[bgIdx][tileIdx] = MEM_BG_MAP[bgIdx][tileIdx] =
@@ -216,7 +217,7 @@ void setBgTile(Context &ctx, uint_t bgIdx, int column, int row, BgTile const&til
static_cast<uint16_t>(tile.palBank << 0xc); static_cast<uint16_t>(tile.palBank << 0xc);
} }
void clearBg(Context &ctx, uint_t bgIdx) noexcept { void clearBg(Context &ctx, uint_t const bgIdx) noexcept {
memset(MEM_BG_MAP[bgIdx].data(), 0, static_cast<size_t>(tileRows(ctx) * tileColumns(ctx))); memset(MEM_BG_MAP[bgIdx].data(), 0, static_cast<size_t>(tileRows(ctx) * tileColumns(ctx)));
} }
@@ -224,39 +225,39 @@ uint8_t bgStatus(Context&) noexcept {
return (REG_DISPCTL >> 8u) & 0b1111u; return (REG_DISPCTL >> 8u) & 0b1111u;
} }
void setBgStatus(Context&, uint32_t status) noexcept { void setBgStatus(Context&, uint32_t const status) noexcept {
constexpr auto BgStatus = 8; constexpr auto BgStatus = 8;
REG_DISPCTL = (REG_DISPCTL & ~0b111100000000u) | status << BgStatus; REG_DISPCTL = (REG_DISPCTL & ~0b111100000000u) | status << BgStatus;
} }
bool bgStatus(Context&, unsigned bg) noexcept { bool bgStatus(Context&, unsigned const bg) noexcept {
return (REG_DISPCTL >> (8 + bg)) & 1; return (REG_DISPCTL >> (8 + bg)) & 1;
} }
void setBgStatus(Context&, unsigned bg, bool status) noexcept { void setBgStatus(Context&, unsigned const bg, bool const status) noexcept {
constexpr auto Bg0Status = 8; constexpr auto Bg0Status = 8;
const auto mask = static_cast<uint32_t>(status) << (Bg0Status + bg); const auto mask = static_cast<uint32_t>(status) << (Bg0Status + bg);
REG_DISPCTL = REG_DISPCTL | ((REG_DISPCTL & ~mask) | mask); REG_DISPCTL = REG_DISPCTL | ((REG_DISPCTL & ~mask) | mask);
} }
void setBgBpp(Context&, unsigned bgIdx, unsigned bpp) noexcept { void setBgBpp(Context&, unsigned const bgIdx, unsigned const bpp) noexcept {
auto &bgCtl = regBgCtl(bgIdx); auto &bgCtl = regBgCtl(bgIdx);
teagba::bgSetBpp(bgCtl, bpp); teagba::bgSetBpp(bgCtl, bpp);
} }
void setBgCbb(Context &ctx, unsigned bgIdx, unsigned cbb) noexcept { void setBgCbb(Context &ctx, unsigned const bgIdx, unsigned const cbbIdx) noexcept {
auto &bgCtl = regBgCtl(bgIdx); auto &bgCtl = regBgCtl(bgIdx);
const auto &cbbData = ctx.cbbData[cbb]; const auto &cbbData = ctx.cbbData[cbbIdx];
teagba::bgSetBpp(bgCtl, cbbData.bpp); teagba::bgSetBpp(bgCtl, cbbData.bpp);
teagba::bgSetCbb(bgCtl, cbb); teagba::bgSetCbb(bgCtl, cbbIdx);
} }
void setBgPriority(Context&, uint_t bgIdx, uint_t priority) noexcept { void setBgPriority(Context&, uint_t const bgIdx, uint_t const priority) noexcept {
auto &bgCtl = regBgCtl(bgIdx); auto &bgCtl = regBgCtl(bgIdx);
bgCtl = (bgCtl & 0b1111'1111'1111'1100u) | (priority & 0b11); bgCtl = (bgCtl & 0b1111'1111'1111'1100u) | (priority & 0b11);
} }
void hideSprite(Context&, unsigned idx) noexcept { void hideSprite(Context&, unsigned const idx) noexcept {
//oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow"); //oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
teagba::addSpriteUpdate({ teagba::addSpriteUpdate({
.attr0 = uint16_t{0b11 << 8}, .attr0 = uint16_t{0b11 << 8},
@@ -264,7 +265,7 @@ void hideSprite(Context&, unsigned idx) noexcept {
}); });
} }
void showSprite(Context&, unsigned idx) noexcept { void showSprite(Context&, unsigned const idx) noexcept {
//oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow"); //oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
teagba::addSpriteUpdate({ teagba::addSpriteUpdate({
.attr0 = 0, .attr0 = 0,
@@ -272,7 +273,7 @@ void showSprite(Context&, unsigned idx) noexcept {
}); });
} }
void setSprite(Context&, uint_t idx, Sprite const&s) noexcept { void setSprite(Context&, uint_t const idx, Sprite const&s) noexcept {
//oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow"); //oxAssert(g_spriteUpdates < config::GbaSpriteBufferLen, "Sprite update buffer overflow");
uint16_t const eightBpp = s.bpp == 8; uint16_t const eightBpp = s.bpp == 8;
teagba::addSpriteUpdate({ teagba::addSpriteUpdate({
@@ -293,7 +294,7 @@ void setSprite(Context&, uint_t idx, Sprite const&s) noexcept {
}); });
} }
uint_t spriteCount(Context&) noexcept { uint_t spriteCount(Context const&) noexcept {
return SpriteCount; return SpriteCount;
} }

View File

@@ -26,7 +26,7 @@ Context::~Context() noexcept {
ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&params) noexcept { ox::Result<ox::UPtr<Context>> init(turbine::Context &tctx, InitParams const&params) noexcept {
auto ctx = ox::make_unique<Context>(tctx, params); auto ctx = ox::make_unique<Context>(tctx, params);
OX_RETURN_ERROR(initGfx(*ctx, params)); OX_RETURN_ERROR(initGfx(*ctx, params));
return ox::UPtr<Context>(ctx.release()); return ctx;
} }
keel::Context &keelCtx(Context &ctx) noexcept { keel::Context &keelCtx(Context &ctx) noexcept {

View File

@@ -28,7 +28,7 @@ static constexpr auto PriorityScale = 0.01f;
Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {} Drawer::Drawer(Context &ctx) noexcept: m_ctx(ctx) {}
void Drawer::draw(turbine::Context &tctx) noexcept { void Drawer::draw(turbine::Context &tctx) noexcept {
gfx::gl::draw(m_ctx, turbine::getScreenSize(tctx)); gl::draw(m_ctx, turbine::getScreenSize(tctx));
} }
static constexpr ox::CStringView bgvshadTmpl = R"glsl( static constexpr ox::CStringView bgvshadTmpl = R"glsl(
@@ -106,7 +106,7 @@ static constexpr ox::CStringView spritefshadTmpl = R"glsl(
})glsl"; })glsl";
[[nodiscard]] [[nodiscard]]
static constexpr auto bgVertexRow(uint_t x, uint_t y) noexcept { static constexpr auto bgVertexRow(uint_t const x, uint_t const y) noexcept {
return y * TileRows + x; return y * TileRows + x;
} }
@@ -183,7 +183,7 @@ static void setTileBufferObject(
ox::spancpy<GLuint>(ebo, elms); ox::spancpy<GLuint>(ebo, elms);
} }
static void initSpriteBufferObjects(Context &ctx, glutils::BufferSet &bs) noexcept { static void initSpriteBufferObjects(Context const &ctx, glutils::BufferSet &bs) noexcept {
for (auto i = 0u; i < ctx.spriteCount; ++i) { for (auto i = 0u; i < ctx.spriteCount; ++i) {
auto const vbo = ox::Span{bs.vertices} auto const vbo = ox::Span{bs.vertices}
+ i * static_cast<std::size_t>(SpriteVertexVboLength); + i * static_cast<std::size_t>(SpriteVertexVboLength);
@@ -256,7 +256,7 @@ static void initSpritesBufferset(Context &ctx) noexcept {
} }
static void initBackgroundBufferset( static void initBackgroundBufferset(
GLuint shader, GLuint const shader,
glutils::BufferSet &bs) noexcept { glutils::BufferSet &bs) noexcept {
// vao // vao
bs.vao = glutils::generateVertexArrayObject(); bs.vao = glutils::generateVertexArrayObject();
@@ -290,8 +290,8 @@ static void initBackgroundBufferset(
} }
static glutils::GLTexture createTexture( static glutils::GLTexture createTexture(
GLsizei w, GLsizei const w,
GLsizei h, GLsizei const h,
void const*pixels) noexcept { void const*pixels) noexcept {
GLuint texId = 0; GLuint texId = 0;
glGenTextures(1, &texId); glGenTextures(1, &texId);
@@ -375,10 +375,10 @@ static void drawSprites(Context &ctx, ox::Size const&renderSz) noexcept {
static void loadPalette( static void loadPalette(
ox::Array<GLfloat, 1024> &palette, ox::Array<GLfloat, 1024> &palette,
size_t palOffset, size_t const palOffset,
GLuint shaderPgrm, GLuint const shaderPgrm,
CompactPalette const&pal, CompactPalette const&pal,
size_t page = 0) noexcept { size_t const 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.pages[page]) { for (auto i = palOffset; auto const c : pal.pages[page]) {
palette[i++] = redf(c); palette[i++] = redf(c);
@@ -523,14 +523,18 @@ static ox::Result<TileSheetData> normalizeTileSheet(
pixels[i * 2 + 1] = ts.pixels[i] >> 4; pixels[i * 2 + 1] = ts.pixels[i] >> 4;
} }
} }
return TileSheetData{std::move(pixels), width, height}; return TileSheetData{
.pixels = std::move(pixels),
.width = width,
.height = height
};
} }
ox::Error loadBgPalette( ox::Error loadBgPalette(
Context &ctx, Context &ctx,
size_t palBank, size_t const palBank,
CompactPalette const&palette, CompactPalette const&palette,
size_t page) noexcept { size_t const page) noexcept {
renderer::loadPalette(ctx.bgPalette, palBank * 16 * 4, ctx.bgShader, palette, page); renderer::loadPalette(ctx.bgPalette, palBank * 16 * 4, ctx.bgShader, palette, page);
return {}; return {};
} }
@@ -538,14 +542,14 @@ ox::Error loadBgPalette(
ox::Error loadSpritePalette( ox::Error loadSpritePalette(
Context &ctx, Context &ctx,
CompactPalette const&palette, CompactPalette const&palette,
size_t page) noexcept { size_t const page) noexcept {
ox::Array<GLfloat, 1024> pal; ox::Array<GLfloat, 1024> pal;
renderer::loadPalette(pal, 0, ctx.spriteShader, palette, page); renderer::loadPalette(pal, 0, ctx.spriteShader, palette, page);
return {}; return {};
} }
static ox::Result<TileSheetData> buildSetTsd( static ox::Result<TileSheetData> buildSetTsd(
Context &ctx, Context const &ctx,
TileSheetSet const&set) noexcept { TileSheetSet const&set) noexcept {
auto &kctx = keelCtx(ctx.turbineCtx); auto &kctx = keelCtx(ctx.turbineCtx);
TileSheetData setTsd; TileSheetData setTsd;
@@ -567,7 +571,7 @@ static ox::Result<TileSheetData> buildSetTsd(
static void copyPixels( static void copyPixels(
CompactTileSheet const&ts, CompactTileSheet const&ts,
ox::Span<uint32_t> dst, ox::Span<uint32_t> const dst,
size_t const srcPxIdx, size_t const srcPxIdx,
size_t const pxlCnt) noexcept { size_t const pxlCnt) noexcept {
size_t idx{}; size_t idx{};
@@ -624,7 +628,7 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet( ox::Error loadBgTileSheet(
Context &ctx, Context &ctx,
uint_t cbb, uint_t const cbb,
CompactTileSheet const&ts, CompactTileSheet const&ts,
ox::Optional<unsigned> const&paletteBank) noexcept { ox::Optional<unsigned> const&paletteBank) noexcept {
auto const bytesPerTile = static_cast<uint64_t>(PixelsPerTile / (1 + (ts.bpp == 4))); auto const bytesPerTile = static_cast<uint64_t>(PixelsPerTile / (1 + (ts.bpp == 4)));
@@ -638,7 +642,7 @@ ox::Error loadBgTileSheet(
ox::Error loadBgTileSheet( ox::Error loadBgTileSheet(
Context &ctx, Context &ctx,
unsigned cbb, unsigned const cbb,
TileSheetSet const&set) noexcept { TileSheetSet const&set) noexcept {
OX_REQUIRE(setTsd, buildSetTsd(ctx, set)); OX_REQUIRE(setTsd, buildSetTsd(ctx, set));
ctx.cbbs[cbb].tex = renderer::createTexture(setTsd.width, setTsd.height, setTsd.pixels.data()); ctx.cbbs[cbb].tex = renderer::createTexture(setTsd.width, setTsd.height, setTsd.pixels.data());
@@ -648,7 +652,7 @@ ox::Error loadBgTileSheet(
ox::Error loadSpriteTileSheet( ox::Error loadSpriteTileSheet(
Context &ctx, Context &ctx,
CompactTileSheet const&ts, CompactTileSheet const&ts,
bool loadDefaultPalette) noexcept { bool const loadDefaultPalette) noexcept {
OX_REQUIRE(tsd, normalizeTileSheet(ts)); OX_REQUIRE(tsd, normalizeTileSheet(ts));
oxTracef("nostalgia.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", tsd.width, tsd.height); oxTracef("nostalgia.gfx.gl", "loadSpriteTexture: { w: {}, h: {} }", tsd.width, tsd.height);
ctx.spriteBlocks.tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data()); ctx.spriteBlocks.tex = renderer::createTexture(tsd.width, tsd.height, tsd.pixels.data());
@@ -668,9 +672,9 @@ ox::Error loadSpriteTileSheet(
void setBgTile( void setBgTile(
Context &ctx, Context &ctx,
uint_t bgIdx, uint_t const bgIdx,
int column, int const column,
int row, int const row,
BgTile const&tile) noexcept { BgTile const&tile) noexcept {
oxTracef( oxTracef(
"nostalgia.gfx.setBgTile", "nostalgia.gfx.setBgTile",
@@ -698,7 +702,7 @@ void setBgTile(
cbb.updated = true; cbb.updated = true;
} }
void clearBg(Context &ctx, uint_t bgIdx) noexcept { void clearBg(Context &ctx, uint_t const bgIdx) noexcept {
auto &cbb = ctx.cbbs[static_cast<std::size_t>(bgIdx)]; auto &cbb = ctx.cbbs[static_cast<std::size_t>(bgIdx)];
initBackgroundBufferObjects(cbb); initBackgroundBufferObjects(cbb);
cbb.updated = true; cbb.updated = true;
@@ -714,61 +718,59 @@ uint8_t bgStatus(Context &ctx) noexcept {
return out; return out;
} }
void setBgStatus(Context &ctx, uint32_t status) noexcept { void setBgStatus(Context &ctx, uint32_t const status) noexcept {
for (uint_t i = 0; i < ctx.cbbs.size(); ++i) { for (uint_t i = 0; i < ctx.cbbs.size(); ++i) {
ctx.backgrounds[i].enabled = (status >> i) & 1; ctx.backgrounds[i].enabled = (status >> i) & 1;
} }
} }
bool bgStatus(Context &ctx, uint_t bg) noexcept { bool bgStatus(Context &ctx, uint_t const bg) noexcept {
return ctx.backgrounds[bg].enabled; return ctx.backgrounds[bg].enabled;
} }
void setBgStatus(Context&ctx, uint_t bg, bool status) noexcept { void setBgStatus(Context&ctx, uint_t const bg, bool const status) noexcept {
ctx.backgrounds[bg].enabled = status; ctx.backgrounds[bg].enabled = status;
} }
void setBgBpp(Context&, unsigned, unsigned) noexcept {} void setBgCbb(Context &ctx, uint_t const bgIdx, uint_t const cbbIdx) noexcept {
void setBgCbb(Context &ctx, uint_t bgIdx, uint_t cbbIdx) noexcept {
auto &bg = ctx.backgrounds[bgIdx]; auto &bg = ctx.backgrounds[bgIdx];
bg.cbbIdx = cbbIdx; bg.cbbIdx = cbbIdx;
} }
void setBgPriority(Context &ctx, uint_t bgIdx, uint_t priority) noexcept { void setBgPriority(Context &ctx, uint_t const bgIdx, uint_t const priority) noexcept {
auto &bg = ctx.backgrounds[bgIdx]; auto &bg = ctx.backgrounds[bgIdx];
bg.priority = static_cast<float>(priority & 0b11); bg.priority = static_cast<float>(priority & 0b11);
} }
void hideSprite(Context &ctx, uint_t idx) noexcept { void hideSprite(Context &ctx, uint_t const idx) noexcept {
auto &s = ctx.spriteStates[idx]; auto &s = ctx.spriteStates[idx];
s.enabled = false; s.enabled = false;
renderer::setSprite(ctx, idx, s); renderer::setSprite(ctx, idx, s);
} }
void showSprite(Context &ctx, uint_t idx) noexcept { void showSprite(Context &ctx, uint_t const idx) noexcept {
auto &s = ctx.spriteStates[idx]; auto &s = ctx.spriteStates[idx];
s.enabled = true; s.enabled = true;
renderer::setSprite(ctx, idx, s); renderer::setSprite(ctx, idx, s);
} }
void setSprite(Context &ctx, uint_t idx, Sprite const&sprite) noexcept { void setSprite(Context &ctx, uint_t const idx, Sprite const&sprite) noexcept {
auto &s = ctx.spriteStates[idx]; auto &s = ctx.spriteStates[idx];
s = sprite; s = sprite;
renderer::setSprite(ctx, idx, s); renderer::setSprite(ctx, idx, s);
} }
uint_t spriteCount(Context &ctx) noexcept { uint_t spriteCount(Context const &ctx) noexcept {
return ctx.spriteCount; return ctx.spriteCount;
} }
namespace gl { namespace gl {
ox::Size drawSize(int scale) noexcept { ox::Size drawSize(int const scale) noexcept {
return {240 * scale, 160 * scale}; return {240 * scale, 160 * scale};
} }
void draw(gfx::Context &ctx, ox::Size const&renderSz) noexcept { void draw(Context &ctx, ox::Size const&renderSz) noexcept {
glViewport(0, 0, renderSz.width, renderSz.height); glViewport(0, 0, renderSz.width, renderSz.height);
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND); glEnable(GL_BLEND);
@@ -783,7 +785,7 @@ void draw(gfx::Context &ctx, ox::Size const&renderSz) noexcept {
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
void draw(gfx::Context &ctx, int scale) noexcept { void draw(Context &ctx, int const scale) noexcept {
draw(ctx, drawSize(scale)); draw(ctx, drawSize(scale));
} }

View File

@@ -118,12 +118,12 @@ void PaletteEditorImGui::navigateTo(ox::StringViewCR arg) noexcept {
} }
} }
void PaletteEditorImGui::drawColumnLeftAlign(ox::CStringView txt) noexcept { void PaletteEditorImGui::drawColumnLeftAlign(ox::CStringViewCR txt) noexcept {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::Text("%s", txt.c_str()); ImGui::Text("%s", txt.c_str());
} }
void PaletteEditorImGui::drawColumn(ox::CStringView txt) noexcept { void PaletteEditorImGui::drawColumn(ox::CStringViewCR txt) noexcept {
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::SetCursorPosX( ImGui::SetCursorPosX(
ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(txt.data()).x); ImGui::GetCursorPosX() + ImGui::GetColumnWidth() - ImGui::CalcTextSize(txt.data()).x);
@@ -143,7 +143,15 @@ void PaletteEditorImGui::numShortcuts(size_t &val, size_t const sizeRange) noexc
} }
} }
void PaletteEditorImGui::colorInput(ox::CStringView label, int &v, bool &inputFocused) noexcept { void PaletteEditorImGui::colorInput(
ox::CStringViewCR label,
int &v,
bool &inputFocused,
FocusCmd const colorChannel) noexcept {
if (colorChannel == m_focusCmd) [[unlikely]] {
ImGui::SetKeyboardFocusHere();
m_focusCmd = FocusCmd::None;
}
ImGui::InputInt(label.c_str(), &v, 1, 5); ImGui::InputInt(label.c_str(), &v, 1, 5);
inputFocused = inputFocused || ImGui::IsItemFocused(); inputFocused = inputFocused || ImGui::IsItemFocused();
v = ox::max(v, 0); v = ox::max(v, 0);
@@ -296,9 +304,9 @@ void PaletteEditorImGui::drawColorEditor() noexcept {
"Name", m_pal.colorNames[m_selectedColorRow]); "Name", m_pal.colorNames[m_selectedColorRow]);
bool inputFocused = ImGui::IsItemFocused(); bool inputFocused = ImGui::IsItemFocused();
ImGui::Separator(); ImGui::Separator();
colorInput("Red", r, inputFocused); colorInput("Red", r, inputFocused, FocusCmd::Red);
colorInput("Green", g, inputFocused); colorInput("Green", g, inputFocused, FocusCmd::Green);
colorInput("Blue", b, inputFocused); colorInput("Blue", b, inputFocused, FocusCmd::Blue);
if (ig::PushButton("Apply to all pages", {-1, ig::BtnSz.y})) { if (ig::PushButton("Apply to all pages", {-1, ig::BtnSz.y})) {
std::ignore = pushCommand<ApplyColorAllPagesCommand>( std::ignore = pushCommand<ApplyColorAllPagesCommand>(
m_pal, m_page, m_selectedColorRow); m_pal, m_page, m_selectedColorRow);
@@ -309,6 +317,15 @@ void PaletteEditorImGui::drawColorEditor() noexcept {
} else { } else {
numShortcuts(m_page, m_pal.pages.size()); numShortcuts(m_page, m_pal.pages.size());
} }
if (ImGui::IsKeyDown(ImGuiKey_R)) {
m_focusCmd = FocusCmd::Red;
}
if (ImGui::IsKeyDown(ImGuiKey_G)) {
m_focusCmd = FocusCmd::Green;
}
if (ImGui::IsKeyDown(ImGuiKey_B)) {
m_focusCmd = FocusCmd::Blue;
}
} }
auto const newColor = color16(r, g, b, a); auto const newColor = color16(r, g, b, a);
if (c != newColor) { if (c != newColor) {
@@ -320,7 +337,7 @@ void PaletteEditorImGui::drawColorEditor() noexcept {
} }
} }
ox::Error PaletteEditorImGui::renamePage(ox::StringView name) noexcept { ox::Error PaletteEditorImGui::renamePage(ox::StringViewCR name) noexcept {
return pushCommand<RenamePageCommand>(m_pal, m_page, name); return pushCommand<RenamePageCommand>(m_pal, m_page, name);
} }

View File

@@ -36,6 +36,13 @@ class PaletteEditorImGui: public studio::Editor {
Palette m_pal; Palette m_pal;
size_t m_selectedColorRow = 0; size_t m_selectedColorRow = 0;
size_t m_page = 0; size_t m_page = 0;
enum class FocusCmd {
None,
Red,
Green,
Blue,
};
FocusCmd m_focusCmd;
public: public:
PaletteEditorImGui(studio::Context &sctx, ox::StringParam path); PaletteEditorImGui(studio::Context &sctx, ox::StringParam path);
@@ -48,9 +55,9 @@ class PaletteEditorImGui: public studio::Editor {
void navigateTo(ox::StringViewCR arg) noexcept override; void navigateTo(ox::StringViewCR arg) noexcept override;
private: private:
static void drawColumnLeftAlign(ox::CStringView txt) noexcept; static void drawColumnLeftAlign(ox::CStringViewCR txt) noexcept;
static void drawColumn(ox::CStringView txt) noexcept; static void drawColumn(ox::CStringViewCR txt) noexcept;
static void drawColumn(ox::Integer_c auto i) noexcept { static void drawColumn(ox::Integer_c auto i) noexcept {
drawColumn(ox::intToStr(i)); drawColumn(ox::intToStr(i));
@@ -58,7 +65,7 @@ class PaletteEditorImGui: public studio::Editor {
static void numShortcuts(size_t &val, size_t sizeRange) noexcept; static void numShortcuts(size_t &val, size_t sizeRange) noexcept;
static void colorInput(ox::CStringView label, int &v, bool &inputFocused) noexcept; void colorInput(ox::CStringViewCR label, int &v, bool &inputFocused, FocusCmd colorChannel) noexcept;
void drawColorsEditor() noexcept; void drawColorsEditor() noexcept;
@@ -66,7 +73,7 @@ class PaletteEditorImGui: public studio::Editor {
void drawColorEditor() noexcept; void drawColorEditor() noexcept;
ox::Error renamePage(ox::StringView name) noexcept; ox::Error renamePage(ox::StringViewCR name) noexcept;
ox::Error handleCommand(studio::UndoCommand const*) noexcept; ox::Error handleCommand(studio::UndoCommand const*) noexcept;
}; };

View File

@@ -27,14 +27,11 @@ CutPasteCommand::CutPasteCommand(
TileSheet::SubSheetIdx subSheetIdx, TileSheet::SubSheetIdx subSheetIdx,
ox::Point const&dstStart, ox::Point const&dstStart,
ox::Point dstEnd, ox::Point dstEnd,
TileSheetClipboard const&cb): TileSheetClipboard const&cb) noexcept:
m_commandId(commandId), m_commandId(commandId),
m_img(img), m_img(img),
m_subSheetIdx(std::move(subSheetIdx)) { m_subSheetIdx(std::move(subSheetIdx)) {
auto const&ss = getSubSheet(m_img, m_subSheetIdx); auto const&ss = getSubSheet(m_img, m_subSheetIdx);
if (dstStart.x >= ss.columns * TileWidth || dstStart.y >= ss.rows * TileHeight) {
throw ox::Exception{1, "paste starts beyond the bounds of target"};
}
dstEnd.x = std::min(ss.columns * TileWidth - 1, dstEnd.x); dstEnd.x = std::min(ss.columns * TileWidth - 1, dstEnd.x);
dstEnd.y = std::min(ss.rows * TileHeight - 1, dstEnd.y); dstEnd.y = std::min(ss.rows * TileHeight - 1, dstEnd.y);
for (auto const&p : cb.pixels()) { for (auto const&p : cb.pixels()) {

View File

@@ -69,7 +69,7 @@ class CutPasteCommand: public TileSheetCommand {
TileSheet::SubSheetIdx subSheetIdx, TileSheet::SubSheetIdx subSheetIdx,
ox::Point const&dstStart, ox::Point const&dstStart,
ox::Point dstEnd, ox::Point dstEnd,
TileSheetClipboard const&cb); TileSheetClipboard const&cb) noexcept;
ox::Error redo() noexcept final; ox::Error redo() noexcept final;

View File

@@ -46,13 +46,13 @@ Palette const TileSheetEditorModel::s_defaultPalette = {
TileSheetEditorModel::TileSheetEditorModel( TileSheetEditorModel::TileSheetEditorModel(
studio::Context &sctx, ox::StringParam path, studio::UndoStack &undoStack): studio::Context &sctx, ox::StringParam path, studio::UndoStack &undoStack):
m_sctx{sctx}, m_sctx(sctx),
m_tctx{m_sctx.tctx}, m_tctx(m_sctx.tctx),
m_path{std::move(path)}, m_path(std::move(path)),
m_img{*readObj<TileSheet>(keelCtx(m_tctx), m_path).unwrapThrow()}, m_img(*readObj<TileSheet>(keelCtx(m_tctx), m_path).unwrapThrow()),
// ignore failure to load palette // ignore failure to load palette
m_pal{readObj<Palette>(keelCtx(m_tctx), m_img.defaultPalette).value}, m_pal(readObj<Palette>(keelCtx(m_tctx), m_img.defaultPalette).value),
m_undoStack{undoStack} { m_undoStack(undoStack) {
normalizeSubsheets(m_img.subsheet); normalizeSubsheets(m_img.subsheet);
m_pal.updated.connect(this, &TileSheetEditorModel::markUpdated); m_pal.updated.connect(this, &TileSheetEditorModel::markUpdated);
m_undoStack.changeTriggered.connect(this, &TileSheetEditorModel::markUpdatedCmdId); m_undoStack.changeTriggered.connect(this, &TileSheetEditorModel::markUpdatedCmdId);
@@ -67,27 +67,19 @@ void TileSheetEditorModel::cut() {
TileSheetClipboard blankCb; TileSheetClipboard blankCb;
auto cb = ox::make_unique<TileSheetClipboard>(); auto cb = ox::make_unique<TileSheetClipboard>();
auto const&s = activeSubSheet(); auto const&s = activeSubSheet();
if (iterateSelectionRows(*m_selection, [&](int const x, int const y) { iterateSelectionRows(*m_selection, [&](int const x, int const y) {
auto pt = ox::Point{x, y}; auto pt = ox::Point{x, y};
auto const idx = gfx::idx(s, pt); auto const idx = gfx::idx(s, pt);
if (idx >= s.pixels.size()) { auto const c = getPixel(s, idx);
return ox::Error{1, "invalid idx"};
}
auto const c = s.pixels[idx];
pt -= m_selection->a; pt -= m_selection->a;
cb->addPixel(pt, c); cb->addPixel(pt, c);
blankCb.addPixel(pt, 0); blankCb.addPixel(pt, 0);
return ox::Error{}; });
})) {
return;
}
auto const pt1 = m_selection->a; auto const pt1 = m_selection->a;
auto const pt2 = ox::Point{s.columns * TileWidth, s.rows * TileHeight}; auto const pt2 = ox::Point{s.columns * TileWidth, s.rows * TileHeight};
turbine::setClipboardObject(m_tctx, std::move(cb)); turbine::setClipboardObject(m_tctx, std::move(cb));
if (auto const cmd = ox::makeCatch<CutPasteCommand>( std::ignore = pushCommand(ox::make<CutPasteCommand>(
CommandId::Cut, m_img, m_activeSubsSheetIdx, pt1, pt2, blankCb); cmd.ok()) { CommandId::Cut, m_img, m_activeSubsSheetIdx, pt1, pt2, blankCb));
std::ignore = pushCommand(cmd.value);
}
} }
void TileSheetEditorModel::copy() { void TileSheetEditorModel::copy() {
@@ -95,20 +87,14 @@ void TileSheetEditorModel::copy() {
return; return;
} }
auto cb = ox::make_unique<TileSheetClipboard>(); auto cb = ox::make_unique<TileSheetClipboard>();
if (iterateSelectionRows(*m_selection, [&](int const x, int const y) { iterateSelectionRows(*m_selection, [&](int const x, int const y) {
auto pt = ox::Point{x, y}; auto pt = ox::Point{x, y};
auto const&s = activeSubSheet(); auto const&s = activeSubSheet();
auto const idx = gfx::idx(s, pt); auto const idx = gfx::idx(s, pt);
if (idx >= s.pixels.size()) { auto const c = getPixel(s, idx);
return ox::Error{1, "invalid idx"};
}
auto const c = s.pixels[idx];
pt -= m_selection->a; pt -= m_selection->a;
cb->addPixel(pt, c); cb->addPixel(pt, c);
return ox::Error{}; });
})) {
return;
}
turbine::setClipboardObject(m_tctx, std::move(cb)); turbine::setClipboardObject(m_tctx, std::move(cb));
} }
@@ -125,10 +111,8 @@ void TileSheetEditorModel::paste() {
auto const&s = activeSubSheet(); auto const&s = activeSubSheet();
auto const pt1 = m_selection->a; auto const pt1 = m_selection->a;
auto const pt2 = ox::Point{s.columns * TileWidth, s.rows * TileHeight}; auto const pt2 = ox::Point{s.columns * TileWidth, s.rows * TileHeight};
if (auto const cmd = ox::makeCatch<CutPasteCommand>( std::ignore = pushCommand(ox::make<CutPasteCommand>(
CommandId::Paste, m_img, m_activeSubsSheetIdx, pt1, pt2, *cb); cmd.ok()) { CommandId::Paste, m_img, m_activeSubsSheetIdx, pt1, pt2, *cb));
std::ignore = pushCommand(cmd.value);
}
} }
bool TileSheetEditorModel::acceptsClipboardPayload() const noexcept { bool TileSheetEditorModel::acceptsClipboardPayload() const noexcept {
@@ -168,7 +152,7 @@ void TileSheetEditorModel::drawCommand(ox::Point const &pt, std::size_t const pa
auto const idx = gfx::idx(activeSubSheet, pt); auto const idx = gfx::idx(activeSubSheet, pt);
if (m_ongoingDrawCommand) { if (m_ongoingDrawCommand) {
m_updated = m_updated || m_ongoingDrawCommand->append(idx); m_updated = m_updated || m_ongoingDrawCommand->append(idx);
} else if (activeSubSheet.pixels[idx] != palIdx) { } else if (getPixel(activeSubSheet, idx) != palIdx) {
std::ignore = pushCommand(ox::make<DrawCommand>( std::ignore = pushCommand(ox::make<DrawCommand>(
m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx))); m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx)));
} }
@@ -198,7 +182,6 @@ void TileSheetEditorModel::endDrawCommand() noexcept {
if (m_ongoingDrawCommand) { if (m_ongoingDrawCommand) {
m_ongoingDrawCommand->finish(); m_ongoingDrawCommand->finish();
m_ongoingDrawCommand = nullptr; m_ongoingDrawCommand = nullptr;
m_lastDrawUpdatePt = {-1, -1};
} }
} }
@@ -230,8 +213,6 @@ ox::Error TileSheetEditorModel::updateSubsheet(
void TileSheetEditorModel::setActiveSubsheet(TileSheet::SubSheetIdx const&idx) noexcept { void TileSheetEditorModel::setActiveSubsheet(TileSheet::SubSheetIdx const&idx) noexcept {
m_activeSubsSheetIdx = idx; m_activeSubsSheetIdx = idx;
this->activeSubsheetChanged.emit(m_activeSubsSheetIdx); this->activeSubsheetChanged.emit(m_activeSubsSheetIdx);
clearSelection();
m_lastDrawUpdatePt = {-1, -1};
} }
void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) noexcept { void TileSheetEditorModel::fill(ox::Point const&pt, int const palIdx) noexcept {
@@ -400,7 +381,7 @@ void TileSheetEditorModel::getFillPixels(
int const oldColor) const noexcept { int const oldColor) const noexcept {
auto const idx = ptToIdx(pt, activeSubSheet.columns); auto const idx = ptToIdx(pt, activeSubSheet.columns);
auto const relIdx = idx % PixelsPerTile; auto const relIdx = idx % PixelsPerTile;
if (pixels[relIdx] || activeSubSheet.pixels[idx] != oldColor) { if (pixels[relIdx] || getPixel(activeSubSheet, idx) != oldColor) {
return; return;
} }
// mark pixels to update // mark pixels to update
@@ -438,7 +419,7 @@ void TileSheetEditorModel::setPalPath() noexcept {
} }
ox::Error TileSheetEditorModel::pushCommand(studio::UndoCommand *cmd) noexcept { ox::Error TileSheetEditorModel::pushCommand(studio::UndoCommand *cmd) noexcept {
std::ignore = m_undoStack.push(ox::UPtr{cmd}); std::ignore = m_undoStack.push(ox::UPtr<studio::UndoCommand>{cmd});
m_ongoingDrawCommand = dynamic_cast<DrawCommand*>(cmd); m_ongoingDrawCommand = dynamic_cast<DrawCommand*>(cmd);
m_updated = true; m_updated = true;
return {}; return {};

View File

@@ -35,7 +35,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
studio::SelectionTracker m_selTracker; studio::SelectionTracker m_selTracker;
ox::Optional<studio::Selection> m_selection; ox::Optional<studio::Selection> m_selection;
ox::Point m_lineStartPt; ox::Point m_lineStartPt;
ox::Point m_lastDrawUpdatePt{-1, -1}; ox::Point m_lastDrawUpdatePt;
bool m_updated = false; bool m_updated = false;
public: public:

View File

@@ -15,7 +15,7 @@ target_link_libraries(
target_compile_definitions( target_compile_definitions(
NostalgiaStudio PUBLIC NostalgiaStudio PUBLIC
OLYMPIC_APP_VERSION="d2025.05.1" OLYMPIC_APP_VERSION="dev build"
) )
install( install(

View File

@@ -18,7 +18,7 @@
<string>APPL</string> <string>APPL</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>d2025.05.1</string> <string>dev build</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>12.0.0</string> <string>12.0.0</string>

View File

@@ -28,7 +28,7 @@ install(
DIRECTORY DIRECTORY
../include/keel ../include/keel
DESTINATION DESTINATION
include/keel include
) )
install( install(
@@ -60,4 +60,11 @@ if(TURBINE_BUILD_TYPE STREQUAL "Native")
OxClaw OxClaw
OxLogConn OxLogConn
) )
install(
TARGETS
KeelPack-AppLib
DESTINATION
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
endif() endif()

View File

@@ -13,8 +13,9 @@ extern ox::String appVersion;
namespace studio { namespace studio {
AboutPopup::AboutPopup(turbine::Context &ctx) noexcept: Popup("About") { AboutPopup::AboutPopup(turbine::Context &ctx) noexcept:
m_text = ox::sfmt("{} - {}", keelCtx(ctx).appName, olympic::appVersion); Popup("About"),
m_text{sfmt("{} - {}", keelCtx(ctx).appName, olympic::appVersion)} {
} }
void AboutPopup::draw(Context &sctx) noexcept { void AboutPopup::draw(Context &sctx) noexcept {

View File

@@ -15,7 +15,7 @@ namespace studio {
class AboutPopup final: public ig::Popup { class AboutPopup final: public ig::Popup {
private: private:
ox::String m_text; ox::String const m_text;
public: public:
explicit AboutPopup(turbine::Context &ctx) noexcept; explicit AboutPopup(turbine::Context &ctx) noexcept;

View File

@@ -44,5 +44,5 @@ install(
DIRECTORY DIRECTORY
../include/studio ../include/studio
DESTINATION DESTINATION
include/studio include
) )

View File

@@ -38,7 +38,7 @@ install(
DIRECTORY DIRECTORY
../include/turbine ../include/turbine
DESTINATION DESTINATION
include/turbine include
) )
install( install(