Compare commits

..

37 Commits

Author SHA1 Message Date
ee63a4a1e4 [keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m17s
2025-04-17 21:04:43 -05:00
89ae226b1d [keel] Improve correctness
All checks were successful
Build / build (push) Successful in 1m18s
2025-04-17 01:17:40 -05:00
477834ac04 [keel] Cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-17 01:06:08 -05:00
97b707b61c [keel] Fix MSVC build
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-17 01:01:22 -05:00
e86180e842 [nostalgia/core/keel] Consistency cleanup
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-17 00:39:34 -05:00
035ba8810f [keel,nostalgia] Fix converter type names 2025-04-17 00:37:05 -05:00
f1c2113dd3 [keel] Fix some completely incomprehensible build break in GCC12...
All checks were successful
Build / build (push) Successful in 1m16s
2025-04-17 00:32:38 -05:00
56b79f414d [keel,nostalgia] Further simplify writing type converters
Some checks failed
Build / build (push) Failing after 14s
2025-04-17 00:22:47 -05:00
844656d557 [nostalgia/gfx/keel] Update type converter style
All checks were successful
Build / build (push) Successful in 1m14s
2025-04-16 23:12:24 -05:00
849aceb86d [keel] Add cleaner way to write type converters 2025-04-16 23:11:47 -05:00
c84b85102c [nostalgia/gfx/studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m15s
2025-04-15 22:05:46 -05:00
3fe62464c3 [nostalgia/sample_project] Add NS_Logo32
All checks were successful
Build / build (push) Successful in 1m18s
2025-04-14 22:20:06 -05:00
db55fc722f [nostalgia/player] Cleanup 2025-04-14 22:05:23 -05:00
2094450898 [studio] Cleanup
All checks were successful
Build / build (push) Successful in 1m22s
2025-04-14 22:00:05 -05:00
889bec04b1 [nostalgia/gfx/studio/tilesheet] Cleanup 2025-04-13 23:20:49 -05:00
ac1e34d4cd [nostalgia] Update release notes
All checks were successful
Build / build (push) Successful in 1m19s
2025-04-13 00:37:32 -05:00
55ed75f44d [nostalgia/gfx/studio/tilesheet] Fix selection clearing to work when clicking outside image
All checks were successful
Build / build (push) Successful in 1m19s
2025-04-13 00:33:06 -05:00
2751872c59 [nostalgia] Cleanup file-to-cpp output
All checks were successful
Build / build (push) Successful in 1m15s
2025-04-12 16:50:09 -05:00
2a3cd35cc4 [nostalgia] Fix release notes version, add d2025.02.1
Some checks are pending
Build / build (push) Waiting to run
2025-04-12 16:45:58 -05:00
b66f459f75 [nostalgia] Cleanup icon rsrc generation
Some checks are pending
Build / build (push) Waiting to run
2025-04-12 16:40:49 -05:00
3910f4e77c [nostalgia] Fix debug and gba-run commands in Makefile
Some checks are pending
Build / build (push) Waiting to run
2025-04-12 14:04:41 -05:00
c0e96216ae [turbine] Make accessor functions take const ref to Context
Some checks are pending
Build / build (push) Waiting to run
2025-04-12 13:49:43 -05:00
f9512d72e8 [turbine/glfw] Fix implicit conversion
Some checks are pending
Build / build (push) Waiting to run
2025-04-12 00:22:49 -05:00
b7f2c169ec [nostalgia/studio/gfx] Fix typo
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 23:14:57 -05:00
1e5057d6e6 [nostalgia] Add app icon note to release notes
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 23:12:36 -05:00
c6255e3224 [nostalgia/studio] Add icon 16 src
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 23:06:42 -05:00
02230ef619 [turbine,studio,nostalgia/studio] Add support for window icon scaling, expand icons sizes for Nostalgia Studio
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 22:45:11 -05:00
9b6b60e4d1 [turbine] Cleanup
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 21:47:26 -05:00
b9a26ab61e [turbine] Fix GLFWimage member init order
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 21:44:52 -05:00
a521887ddd [studio,turbine] Add support for window icons
Some checks are pending
Build / build (push) Waiting to run
2025-04-11 21:41:30 -05:00
5ca7e2f226 [ox/fs] Cleanup
All checks were successful
Build / build (push) Successful in 1m14s
2025-04-02 01:30:58 -05:00
125a235dd1 [ox/fs] Cleanup
All checks were successful
Build / build (push) Successful in 1m26s
2025-04-02 01:29:02 -05:00
91a7129f8f [nostalgia/gfx/keel] Cleanup 2025-04-02 01:07:26 -05:00
df48a232ec [nostalgia/studio] Add icon to Windows executable
All checks were successful
Build / build (push) Successful in 1m28s
2025-04-02 00:49:13 -05:00
ab11b885e6 [keel] Add missing new line to log message
All checks were successful
Build / build (push) Successful in 1m25s
2025-03-24 21:02:20 -05:00
36fc25fb7e [studio] Fix closing tab with unsaved changes 2025-03-24 21:02:20 -05:00
4803cca334 [nostalgia/player] Cleanup
All checks were successful
Build / build (push) Successful in 1m29s
2025-03-08 22:28:29 -06:00
42 changed files with 3192 additions and 222 deletions

View File

@@ -15,7 +15,11 @@ PROJECT_PLAYER=./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME_CAP}
.PHONY: pkg-gba .PHONY: pkg-gba
pkg-gba: build pkg-gba: build
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME} ${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/pkg-gba.py sample_project ${BC_VAR_PROJECT_NAME_CAP}
.PHONY: generate-studio-rsrc
generate-studio-rsrc:
${BC_CMD_ENVRUN} ${BC_PY3} ./util/scripts/file-to-cpp.py --rsrc src/nostalgia/studio/rsrc.json
.PHONY: build-player .PHONY: build-player
build-player: build-player:
@@ -28,10 +32,10 @@ run-studio: build
${PROJECT_STUDIO} ${PROJECT_STUDIO}
.PHONY: gba-run .PHONY: gba-run
gba-run: pkg-gba gba-run: pkg-gba
${MGBA} ${BC_VAR_PROJECT_NAME}.gba ${MGBA} ${BC_VAR_PROJECT_NAME_CAP}.gba
.PHONY: debug .PHONY: debug
debug: build debug: build
${BC_CMD_HOST_DEBUGGER} ./build/${BC_VAR_CURRENT_BUILD}/bin/${BC_VAR_PROJECT_NAME} sample_project ${BC_CMD_HOST_DEBUGGER} ${PROJECT_PLAYER} sample_project
.PHONY: debug-studio .PHONY: debug-studio
debug-studio: build debug-studio: build
${BC_CMD_HOST_DEBUGGER} ${PROJECT_STUDIO} ${BC_CMD_HOST_DEBUGGER} ${PROJECT_STUDIO}

View File

@@ -1,30 +0,0 @@
#! /usr/bin/env python3
#
# Copyright 2016 - 2025 gary@drinkingtea.net
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
import argparse
import sys
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument('--file', help='path to file')
parser.add_argument('--out-cpp', help='path to output cpp file')
parser.add_argument('--out-hpp', help='path to output hpp file')
parser.add_argument('--namespace', help='path to output hpp file')
args = parser.parse_args()
return 0
if __name__ == '__main__':
try:
err = main()
sys.exit(err)
except KeyboardInterrupt:
sys.exit(1)

View File

@@ -433,14 +433,14 @@ Error FileStoreTemplate<size_t>::resize() {
template<typename size_t> template<typename size_t>
Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) { Error FileStoreTemplate<size_t>::resize(std::size_t size, void *newBuff) {
if (m_buffer->size() > size) { if (m_buffer->size() > size) {
return ox::Error(1); return ox::Error{1, "new buffer is too small for existing data"};
} }
m_buffSize = static_cast<size_t>(size); m_buffSize = static_cast<size_t>(size);
if (newBuff) { if (newBuff) {
m_buffer = reinterpret_cast<Buffer*>(newBuff); m_buffer = static_cast<Buffer*>(newBuff);
OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size))); OX_RETURN_ERROR(m_buffer->setSize(static_cast<size_t>(size)));
} }
return ox::Error(0); return {};
} }
template<typename size_t> template<typename size_t>

View File

@@ -20,7 +20,7 @@
namespace ox { namespace ox {
namespace detail { namespace detail {
static inline void fsBuffFree(char *buff) noexcept { inline void fsBuffFree(char *buff) noexcept {
safeDelete(buff); safeDelete(buff);
} }
} }
@@ -49,11 +49,11 @@ class FileSystem {
Result<Buffer> read(StringViewCR path) noexcept; Result<Buffer> read(StringViewCR path) noexcept;
inline Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept { Error read(StringViewCR path, void *buffer, std::size_t buffSize) noexcept {
return readFilePath(path, buffer, buffSize); return readFilePath(path, buffer, buffSize);
} }
inline Error read(uint64_t inode, void *buffer, std::size_t buffSize) noexcept { Error read(uint64_t inode, void *buffer, std::size_t buffSize) noexcept {
return readFileInode(inode, buffer, buffSize); return readFileInode(inode, buffer, buffSize);
} }
@@ -69,8 +69,7 @@ class FileSystem {
* @param path * @param path
* @param readStart * @param readStart
* @param readSize * @param readSize
* @param buffer * @param buff
* @param size
* @return error or number of bytes read * @return error or number of bytes read
*/ */
Result<size_t> read( Result<size_t> read(
@@ -102,36 +101,36 @@ class FileSystem {
Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept; Error write(const FileAddress &addr, const void *buffer, uint64_t size, FileType fileType = FileType::NormalFile) noexcept;
inline Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept { Error write(StringViewCR path, const void *buffer, uint64_t size, FileType fileType) noexcept {
return writeFilePath(path, buffer, size, fileType); return writeFilePath(path, buffer, size, fileType);
} }
inline Error write(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept { Error write(uint64_t inode, const void *buffer, uint64_t size, FileType fileType) noexcept {
return writeFileInode(inode, buffer, size, fileType); return writeFileInode(inode, buffer, size, fileType);
} }
inline Result<FileStat> stat(uint64_t inode) const noexcept { Result<FileStat> stat(uint64_t inode) const noexcept {
return statInode(inode); return statInode(inode);
} }
inline Result<FileStat> stat(StringViewCR path) const noexcept { Result<FileStat> stat(StringViewCR path) const noexcept {
return statPath(path); return statPath(path);
} }
Result<FileStat> stat(const FileAddress &addr) const noexcept; Result<FileStat> stat(const FileAddress &addr) const noexcept;
[[nodiscard]] [[nodiscard]]
inline bool exists(uint64_t inode) const noexcept { bool exists(uint64_t inode) const noexcept {
return statInode(inode).ok(); return statInode(inode).ok();
} }
[[nodiscard]] [[nodiscard]]
inline bool exists(ox::StringView path) const noexcept { bool exists(ox::StringView path) const noexcept {
return statPath(path).ok(); return statPath(path).ok();
} }
[[nodiscard]] [[nodiscard]]
inline bool exists(FileAddress const&addr) const noexcept { bool exists(FileAddress const&addr) const noexcept {
return stat(addr).ok(); return stat(addr).ok();
} }
@@ -178,11 +177,11 @@ class MemFS: public FileSystem {
public: public:
Result<const char*> directAccess(const FileAddress &addr) const noexcept; Result<const char*> directAccess(const FileAddress &addr) const noexcept;
inline Result<const char*> directAccess(StringViewCR path) const noexcept { Result<const char*> directAccess(StringViewCR path) const noexcept {
return directAccessPath(path); return directAccessPath(path);
} }
inline Result<const char*> directAccess(uint64_t inode) const noexcept { Result<const char*> directAccess(uint64_t inode) const noexcept {
return directAccessInode(inode); return directAccessInode(inode);
} }

View File

@@ -1,4 +1,14 @@
# d2025.02 # d2025.04.0
* Add app icon for both window and file
* Fix selection clearing in TileSheet editor to work when clicking outside
image.
# d2025.02.1
* Fix closing tab with unsaved changes (a44c5acc4b)
# d2025.02.0
* Rename core namespace to gfx. * Rename core namespace to gfx.
* Add PaletteV5 to accommodate namespace change. * Add PaletteV5 to accommodate namespace change.

View File

@@ -0,0 +1,269 @@
K1;e7ae945e-d6c5-4444-5738-be95b4e5937a;O1;net.drinkingtea.nostalgia.gfx.TileSheet;5;{
"bpp" : 4,
"defaultPalette" : "uuid://c79f21e2-f74f-4ad9-90ed-32b0ef7da6ed",
"subsheet" :
{
"columns" : 2,
"name" : "Root",
"pixels" :
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
3,
3,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
1,
0,
0,
2,
3,
0,
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
3,
2,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
3,
3,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0
],
"rows" : 2
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -14,19 +14,6 @@
namespace nostalgia::gfx { namespace nostalgia::gfx {
static class: public keel::Module { static class: public keel::Module {
private:
NostalgiaPaletteToPaletteV1Converter m_nostalgiaPaletteToPaletteV1Converter;
PaletteV1ToPaletteV2Converter m_paletteV1ToPaletteV2Converter;
PaletteV2ToPaletteV3Converter m_paletteV2ToPaletteV3Converter;
PaletteV3ToPaletteV4Converter m_paletteV3ToPaletteV4Converter;
PaletteV4ToPaletteV5Converter m_paletteV4ToPaletteV5Converter;
PaletteToCompactPaletteConverter m_paletteToCompactPaletteConverter;
TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter;
TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter;
TileSheetV3ToTileSheetV4Converter m_tileSheetV3ToTileSheetV4Converter;
TileSheetV4ToTileSheetV5Converter m_tileSheetV4ToTileSheetV5Converter;
TileSheetToCompactTileSheetConverter m_tileSheetToCompactTileSheetConverter;
public: public:
[[nodiscard]] [[nodiscard]]
ox::String id() const noexcept override { ox::String id() const noexcept override {
@@ -52,19 +39,19 @@ static class: public keel::Module {
} }
[[nodiscard]] [[nodiscard]]
ox::Vector<keel::BaseConverter const*> converters() const noexcept final { ox::Vector<keel::Converter> converters() const noexcept final {
return { return {
&m_nostalgiaPaletteToPaletteV1Converter, keel::Converter::make<convertNostalgiaPaletteToPaletteV1>(),
&m_paletteV1ToPaletteV2Converter, keel::Converter::make<convertPaletteV1ToPaletteV2>(),
&m_paletteV2ToPaletteV3Converter, keel::Converter::make<convertPaletteV2ToPaletteV3>(),
&m_paletteV3ToPaletteV4Converter, keel::Converter::make<convertPaletteV3ToPaletteV4>(),
&m_paletteV4ToPaletteV5Converter, keel::Converter::make<convertPaletteV4ToPaletteV5>(),
&m_paletteToCompactPaletteConverter, keel::Converter::make<convertPaletteToCompactPalette>(),
&m_tileSheetV1ToTileSheetV2Converter, keel::Converter::make<convertTileSheetV1ToTileSheetV2>(),
&m_tileSheetV2ToTileSheetV3Converter, keel::Converter::make<convertTileSheetV2ToTileSheetV3>(),
&m_tileSheetV3ToTileSheetV4Converter, keel::Converter::make<convertTileSheetV3ToTileSheetV4>(),
&m_tileSheetV4ToTileSheetV5Converter, keel::Converter::make<convertTileSheetV4ToTileSheetV5>(),
&m_tileSheetToCompactTileSheetConverter, keel::Converter::make<convertTileSheetToCompactTileSheet>(),
}; };
} }

View File

@@ -6,26 +6,26 @@
namespace nostalgia::gfx { namespace nostalgia::gfx {
ox::Error NostalgiaPaletteToPaletteV1Converter::convert( ox::Error convertNostalgiaPaletteToPaletteV1(
keel::Context&, keel::Context&,
NostalgiaPalette &src, NostalgiaPalette &src,
PaletteV1 &dst) const noexcept { PaletteV1 &dst) noexcept {
dst.colors = std::move(src.colors); dst.colors = std::move(src.colors);
return {}; return {};
} }
ox::Error PaletteV1ToPaletteV2Converter::convert( ox::Error convertPaletteV1ToPaletteV2(
keel::Context&, keel::Context&,
PaletteV1 &src, PaletteV1 &src,
PaletteV2 &dst) const noexcept { PaletteV2 &dst) noexcept {
dst.pages.emplace_back(std::move(src.colors)); dst.pages.emplace_back(std::move(src.colors));
return {}; return {};
} }
ox::Error PaletteV2ToPaletteV3Converter::convert( ox::Error convertPaletteV2ToPaletteV3(
keel::Context&, keel::Context&,
PaletteV2 &src, PaletteV2 &src,
PaletteV3 &dst) const noexcept { PaletteV3 &dst) noexcept {
dst.pages = std::move(src.pages); dst.pages = std::move(src.pages);
if (!dst.pages.empty()) { if (!dst.pages.empty()) {
dst.colorInfo.reserve(dst.pages[0].size()); dst.colorInfo.reserve(dst.pages[0].size());
@@ -36,10 +36,10 @@ ox::Error PaletteV2ToPaletteV3Converter::convert(
return {}; return {};
} }
ox::Error PaletteV3ToPaletteV4Converter::convert( ox::Error convertPaletteV3ToPaletteV4(
keel::Context&, keel::Context&,
PaletteV3 &src, PaletteV3 &src,
PaletteV4 &dst) const noexcept { PaletteV4 &dst) noexcept {
dst.pages.reserve(src.pages.size()); dst.pages.reserve(src.pages.size());
for (auto i = 1; auto &page : src.pages) { for (auto i = 1; auto &page : src.pages) {
dst.pages.emplace_back(ox::sfmt("Page {}", i), std::move(page)); dst.pages.emplace_back(ox::sfmt("Page {}", i), std::move(page));
@@ -52,10 +52,10 @@ ox::Error PaletteV3ToPaletteV4Converter::convert(
return {}; return {};
} }
ox::Error PaletteV4ToPaletteV5Converter::convert( ox::Error convertPaletteV4ToPaletteV5(
keel::Context&, keel::Context&,
PaletteV4 &src, PaletteV4 &src,
PaletteV5 &dst) const noexcept { PaletteV5 &dst) noexcept {
dst.colorNames = std::move(src.colorNames); dst.colorNames = std::move(src.colorNames);
dst.pages.reserve(src.pages.size()); dst.pages.reserve(src.pages.size());
for (auto &s : src.pages) { for (auto &s : src.pages) {
@@ -72,10 +72,10 @@ ox::Error PaletteV4ToPaletteV5Converter::convert(
return {}; return {};
} }
ox::Error PaletteToCompactPaletteConverter::convert( ox::Error convertPaletteToCompactPalette(
keel::Context&, keel::Context&,
Palette &src, Palette &src,
CompactPalette &dst) const noexcept { CompactPalette &dst) noexcept {
dst.pages.reserve(src.pages.size()); dst.pages.reserve(src.pages.size());
for (auto &page : src.pages) { for (auto &page : src.pages) {
auto &p = dst.pages.emplace_back(); auto &p = dst.pages.emplace_back();
@@ -86,10 +86,10 @@ ox::Error PaletteToCompactPaletteConverter::convert(
return {}; return {};
} }
ox::Error TileSheetV1ToTileSheetV2Converter::convert( ox::Error convertTileSheetV1ToTileSheetV2(
keel::Context&, keel::Context&,
TileSheetV1 &src, TileSheetV1 &src,
TileSheetV2 &dst) const noexcept { TileSheetV2 &dst) noexcept {
dst.bpp = src.bpp; dst.bpp = src.bpp;
dst.defaultPalette = std::move(src.defaultPalette); dst.defaultPalette = std::move(src.defaultPalette);
dst.subsheet.name = "Root"; dst.subsheet.name = "Root";
@@ -99,7 +99,7 @@ ox::Error TileSheetV1ToTileSheetV2Converter::convert(
return {}; return {};
} }
void TileSheetV2ToTileSheetV3Converter::convertSubsheet( static void convertSubsheet(
TileSheetV2::SubSheet &src, TileSheetV2::SubSheet &src,
TileSheetV3::SubSheet &dst, TileSheetV3::SubSheet &dst,
SubSheetId &idIt) noexcept { SubSheetId &idIt) noexcept {
@@ -115,10 +115,10 @@ void TileSheetV2ToTileSheetV3Converter::convertSubsheet(
} }
} }
ox::Error TileSheetV2ToTileSheetV3Converter::convert( ox::Error convertTileSheetV2ToTileSheetV3(
keel::Context&, keel::Context&,
TileSheetV2 &src, TileSheetV2 &src,
TileSheetV3 &dst) const noexcept { TileSheetV3 &dst) noexcept {
dst.bpp = src.bpp; dst.bpp = src.bpp;
dst.defaultPalette = std::move(src.defaultPalette); dst.defaultPalette = std::move(src.defaultPalette);
convertSubsheet(src.subsheet, dst.subsheet, dst.idIt); convertSubsheet(src.subsheet, dst.subsheet, dst.idIt);
@@ -126,7 +126,7 @@ ox::Error TileSheetV2ToTileSheetV3Converter::convert(
} }
void TileSheetV3ToTileSheetV4Converter::convertSubsheet( static void convertSubsheet(
TileSheetV3::SubSheet &src, TileSheetV3::SubSheet &src,
TileSheetV4::SubSheet &dst, TileSheetV4::SubSheet &dst,
SubSheetId &idIt) noexcept { SubSheetId &idIt) noexcept {
@@ -142,10 +142,10 @@ void TileSheetV3ToTileSheetV4Converter::convertSubsheet(
} }
} }
ox::Error TileSheetV3ToTileSheetV4Converter::convert( ox::Error convertTileSheetV3ToTileSheetV4(
keel::Context&, keel::Context&,
TileSheetV3 &src, TileSheetV3 &src,
TileSheetV4 &dst) const noexcept { TileSheetV4 &dst) noexcept {
dst.bpp = src.bpp; dst.bpp = src.bpp;
dst.idIt = src.idIt; dst.idIt = src.idIt;
dst.defaultPalette = std::move(src.defaultPalette); dst.defaultPalette = std::move(src.defaultPalette);
@@ -154,7 +154,7 @@ ox::Error TileSheetV3ToTileSheetV4Converter::convert(
} }
void TileSheetV4ToTileSheetV5Converter::convertSubsheet( static void convertSubsheet(
int const bpp, int const bpp,
TileSheetV4::SubSheet &src, TileSheetV4::SubSheet &src,
TileSheetV5::SubSheet &dst) noexcept { TileSheetV5::SubSheet &dst) noexcept {
@@ -179,22 +179,22 @@ void TileSheetV4ToTileSheetV5Converter::convertSubsheet(
} }
} }
ox::Error TileSheetV4ToTileSheetV5Converter::convert( ox::Error convertTileSheetV4ToTileSheetV5(
keel::Context&, keel::Context&,
TileSheetV4 &src, TileSheetV4 &src,
TileSheetV5 &dst) const noexcept { TileSheetV5 &dst) noexcept {
dst.bpp = src.bpp; dst.bpp = src.bpp;
dst.idIt = src.idIt; dst.idIt = src.idIt;
OX_RETURN_ERROR(src.defaultPalette.getPath().moveTo(dst.defaultPalette)); OX_RETURN_ERROR(src.defaultPalette.getPath().moveTo(dst.defaultPalette));
convertSubsheet(dst.bpp, src.subsheet, dst.subsheet); convertSubsheet(dst.bpp, src.subsheet, dst.subsheet);
return {}; return {};
} }
ox::Error TileSheetToCompactTileSheetConverter::convert( ox::Error convertTileSheetToCompactTileSheet(
keel::Context&, keel::Context&,
TileSheet &src, TileSheet &src,
CompactTileSheet &dst) const noexcept { CompactTileSheet &dst) noexcept {
dst.bpp = src.bpp; dst.bpp = src.bpp;
dst.defaultPalette = ox::FileAddress{src.defaultPalette}; dst.defaultPalette = ox::FileAddress{src.defaultPalette};
dst.pixels = pixels(src); dst.pixels = pixels(src);

View File

@@ -16,60 +16,26 @@ namespace nostalgia::gfx {
// Type converters // Type converters
class NostalgiaPaletteToPaletteV1Converter: public keel::Converter<NostalgiaPalette, PaletteV1> { ox::Error convertNostalgiaPaletteToPaletteV1(keel::Context&, NostalgiaPalette &src, PaletteV1 &dst) noexcept;
ox::Error convert(keel::Context&, NostalgiaPalette &src, PaletteV1 &dst) const noexcept final;
};
class PaletteV1ToPaletteV2Converter: public keel::Converter<PaletteV1, PaletteV2> { ox::Error convertPaletteV1ToPaletteV2(keel::Context&, PaletteV1 &src, PaletteV2 &dst) noexcept;
ox::Error convert(keel::Context&, PaletteV1 &src, PaletteV2 &dst) const noexcept final;
};
class PaletteV2ToPaletteV3Converter: public keel::Converter<PaletteV2, PaletteV3> { ox::Error convertPaletteV2ToPaletteV3(keel::Context&, PaletteV2 &src, PaletteV3 &dst) noexcept;
ox::Error convert(keel::Context&, PaletteV2 &src, PaletteV3 &dst) const noexcept final;
};
class PaletteV3ToPaletteV4Converter: public keel::Converter<PaletteV3, PaletteV4> { ox::Error convertPaletteV3ToPaletteV4(keel::Context&, PaletteV3 &src, PaletteV4 &dst) noexcept;
ox::Error convert(keel::Context&, PaletteV3 &src, PaletteV4 &dst) const noexcept final;
};
class PaletteV4ToPaletteV5Converter: public keel::Converter<PaletteV4, PaletteV5> { ox::Error convertPaletteV4ToPaletteV5(keel::Context&, PaletteV4 &src, PaletteV5 &dst) noexcept;
ox::Error convert(keel::Context&, PaletteV4 &src, PaletteV5 &dst) const noexcept final;
};
class PaletteToCompactPaletteConverter: public keel::Converter<Palette, CompactPalette> { ox::Error convertPaletteToCompactPalette(keel::Context&, Palette &src, CompactPalette &dst) noexcept;
ox::Error convert(keel::Context&, Palette &src, CompactPalette &dst) const noexcept final;
};
class TileSheetV1ToTileSheetV2Converter: public keel::Converter<TileSheetV1, TileSheetV2> { ox::Error convertTileSheetV1ToTileSheetV2(keel::Context&, TileSheetV1 &src, TileSheetV2 &dst) noexcept;
ox::Error convert(keel::Context&, TileSheetV1 &src, TileSheetV2 &dst) const noexcept final;
};
class TileSheetV2ToTileSheetV3Converter: public keel::Converter<TileSheetV2, TileSheetV3> { ox::Error convertTileSheetV2ToTileSheetV3(keel::Context&, TileSheetV2 &src, TileSheetV3 &dst) noexcept;
static void convertSubsheet(
TileSheetV2::SubSheet &src,
TileSheetV3::SubSheet &dst,
SubSheetId &idIt) noexcept;
ox::Error convert(keel::Context&, TileSheetV2 &src, TileSheetV3 &dst) const noexcept final;
};
class TileSheetV3ToTileSheetV4Converter: public keel::Converter<TileSheetV3, TileSheetV4> { ox::Error convertTileSheetV3ToTileSheetV4(keel::Context&, TileSheetV3 &src, TileSheetV4 &dst) noexcept;
static void convertSubsheet(
TileSheetV3::SubSheet &src,
TileSheetV4::SubSheet &dst,
SubSheetId &idIt) noexcept;
ox::Error convert(keel::Context&, TileSheetV3 &src, TileSheetV4 &dst) const noexcept final;
};
class TileSheetV4ToTileSheetV5Converter final: public keel::Converter<TileSheetV4, TileSheetV5> { ox::Error convertTileSheetV4ToTileSheetV5(keel::Context&, TileSheetV4 &src, TileSheetV5 &dst) noexcept;
static void convertSubsheet(
int bpp,
TileSheetV4::SubSheet &src,
TileSheetV5::SubSheet &dst) noexcept;
ox::Error convert(keel::Context&, TileSheetV4 &src, TileSheetV5 &dst) const noexcept override;
};
class TileSheetToCompactTileSheetConverter: public keel::Converter<TileSheet, CompactTileSheet> { ox::Error convertTileSheetToCompactTileSheet(keel::Context&, TileSheet &src, CompactTileSheet &dst) noexcept;
ox::Error convert(keel::Context&, TileSheet &src, CompactTileSheet &dst) const noexcept final;
};
} }

View File

@@ -96,7 +96,7 @@ TileSheetEditorImGui::TileSheetEditorImGui(studio::StudioContext &sctx, ox::Stri
m_model{m_view.model()} { m_model{m_view.model()} {
// connect signal/slots // connect signal/slots
m_subsheetEditor.inputSubmitted.connect(this, &TileSheetEditorImGui::updateActiveSubsheet); m_subsheetEditor.inputSubmitted.connect(this, &TileSheetEditorImGui::updateActiveSubsheet);
m_exportMenu.inputSubmitted.connect(this, &TileSheetEditorImGui::exportSubhseetToPng); m_exportMenu.inputSubmitted.connect(this, &TileSheetEditorImGui::exportSubsheetToPng);
// load config // load config
auto const&config = studio::readConfig<TileSheetEditorConfig>( auto const&config = studio::readConfig<TileSheetEditorConfig>(
keelCtx(m_sctx), itemPath()); keelCtx(m_sctx), itemPath());
@@ -397,7 +397,7 @@ void TileSheetEditorImGui::showSubsheetEditor() noexcept {
} }
} }
ox::Error TileSheetEditorImGui::exportSubhseetToPng(int const scale) const noexcept { ox::Error TileSheetEditorImGui::exportSubsheetToPng(int const scale) const noexcept {
OX_REQUIRE(path, studio::saveFile({{"PNG", "png"}})); OX_REQUIRE(path, studio::saveFile({{"PNG", "png"}}));
// subsheet to png // subsheet to png
auto const&s = m_model.activeSubSheet(); auto const&s = m_model.activeSubSheet();
@@ -414,7 +414,7 @@ ox::Error TileSheetEditorImGui::exportSubhseetToPng(int const scale) const noexc
static_cast<unsigned>(width * scale), static_cast<unsigned>(width * scale),
static_cast<unsigned>(height * scale)); static_cast<unsigned>(height * scale));
if (err) { if (err) {
oxErrorf("Tilesheet export failed: {}", toStr(err)); oxErrorf("TileSheet export failed: {}", toStr(err));
} }
return err; return err;
} }

View File

@@ -10,7 +10,6 @@
#include <studio/editor.hpp> #include <studio/editor.hpp>
#include <studio/filepickerpopup.hpp> #include <studio/filepickerpopup.hpp>
#include "tilesheetpixelgrid.hpp"
#include "tilesheetpixels.hpp" #include "tilesheetpixels.hpp"
#include "tilesheeteditorview.hpp" #include "tilesheeteditorview.hpp"
@@ -91,7 +90,7 @@ class TileSheetEditorImGui: public studio::Editor {
private: private:
void showSubsheetEditor() noexcept; void showSubsheetEditor() noexcept;
ox::Error exportSubhseetToPng(int scale) const noexcept; ox::Error exportSubsheetToPng(int scale) const noexcept;
void drawTileSheet(ox::Vec2 const&fbSize) noexcept; void drawTileSheet(ox::Vec2 const&fbSize) noexcept;
@@ -99,8 +98,6 @@ class TileSheetEditorImGui: public studio::Editor {
ox::Error updateActiveSubsheet(ox::StringView const&name, int cols, int rows) noexcept; ox::Error updateActiveSubsheet(ox::StringView const&name, int cols, int rows) noexcept;
// slots
private:
void setActiveSubsheet(TileSheet::SubSheetIdx path) noexcept; void setActiveSubsheet(TileSheet::SubSheetIdx path) noexcept;
}; };

View File

@@ -120,7 +120,7 @@ bool TileSheetEditorModel::acceptsClipboardPayload() const noexcept {
return cb.ok(); return cb.ok();
} }
ox::StringView TileSheetEditorModel::palPath() const noexcept { ox::String const &TileSheetEditorModel::palPath() const & noexcept {
return m_palPath; return m_palPath;
} }
@@ -263,7 +263,13 @@ ox::Error TileSheetEditorModel::rotateRight() noexcept {
} }
void TileSheetEditorModel::setSelection(studio::Selection const&sel) noexcept { void TileSheetEditorModel::setSelection(studio::Selection const&sel) noexcept {
m_selection.emplace(sel); auto const &ss = activeSubSheet();
if (sel.a.x < ss.columns * TileWidth && sel.a.y < ss.rows * TileHeight) {
m_selection.emplace(sel);
} else {
m_selTracker.finishSelection();
m_selection.reset();
}
m_updated = true; m_updated = true;
} }

View File

@@ -62,7 +62,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
constexpr Palette const&pal() const noexcept; constexpr Palette const&pal() const noexcept;
[[nodiscard]] [[nodiscard]]
ox::StringView palPath() const noexcept; ox::String const &palPath() const & noexcept;
ox::Error setPalette(ox::StringViewCR path) noexcept; ox::Error setPalette(ox::StringViewCR path) noexcept;

View File

@@ -26,7 +26,7 @@ static class: public keel::Module {
} }
[[nodiscard]] [[nodiscard]]
ox::Vector<keel::BaseConverter const*> converters() const noexcept final { ox::Vector<keel::Converter> converters() const noexcept final {
return { return {
}; };
} }

View File

@@ -64,13 +64,10 @@ static void testKeyEventHandler(turbine::Context &tctx, turbine::Key key, bool d
[[maybe_unused]] [[maybe_unused]]
static ox::Error runTest(turbine::Context &tctx) { static ox::Error runTest(turbine::Context &tctx) {
constexpr ox::StringView TileSheetAddr{"/TileSheets/Charset.nts"};
constexpr ox::StringView PaletteAddr{"/Palettes/Chester.npal"};
OX_REQUIRE_M(cctx, gfx::init(tctx)); OX_REQUIRE_M(cctx, gfx::init(tctx));
turbine::setApplicationData(tctx, cctx.get()); turbine::setApplicationData(tctx, cctx.get());
OX_REQUIRE(tsStat, turbine::rom(tctx)->stat(PaletteAddr)); OX_RETURN_ERROR(gfx::loadSpriteTileSheet(*cctx, "/TileSheets/Charset.nts"));
OX_RETURN_ERROR(gfx::loadSpriteTileSheet(*cctx, TileSheetAddr)); OX_RETURN_ERROR(gfx::loadSpritePalette(*cctx, "/Palettes/Chester.npal"));
OX_RETURN_ERROR(gfx::loadSpritePalette(*cctx, PaletteAddr));
OX_RETURN_ERROR(gfx::initConsole(*cctx)); OX_RETURN_ERROR(gfx::initConsole(*cctx));
gfx::puts(*cctx, 10, 9, "DOPENESS!!!"); gfx::puts(*cctx, 10, 9, "DOPENESS!!!");
turbine::setUpdateHandler(tctx, testUpdateHandler); turbine::setUpdateHandler(tctx, testUpdateHandler);
@@ -86,7 +83,6 @@ static ox::Error runTileSheetSetTest(turbine::Context &tctx) {
constexpr ox::StringView PaletteAddr{"/Palettes/Charset.npal"}; constexpr ox::StringView PaletteAddr{"/Palettes/Charset.npal"};
OX_REQUIRE_M(cctx, gfx::init(tctx)); OX_REQUIRE_M(cctx, gfx::init(tctx));
turbine::setApplicationData(tctx, cctx.get()); turbine::setApplicationData(tctx, cctx.get());
OX_REQUIRE(tsStat, turbine::rom(tctx)->stat(PaletteAddr));
gfx::TileSheetSet const set{ gfx::TileSheetSet const set{
.bpp = 4, .bpp = 4,
.entries = { .entries = {
@@ -134,7 +130,6 @@ ox::Error run(
return ox::Error{1, "Please provide path to project directory or OxFS file."}; return ox::Error{1, "Please provide path to project directory or OxFS file."};
} }
auto const path = args[1]; auto const path = args[1];
OX_REQUIRE_M(fs, keel::loadRomFs(path)); OX_REQUIRE_M(tctx, turbine::init(path, project));
OX_REQUIRE_M(tctx, turbine::init(std::move(fs), project));
return runTileSheetSetTest(*tctx); return runTileSheetSetTest(*tctx);
} }

View File

@@ -1,4 +1,8 @@
add_executable(NostalgiaStudio WIN32 MACOSX_BUNDLE) add_executable(
NostalgiaStudio WIN32 MACOSX_BUNDLE
ns.rc
icondata.cpp
)
target_link_libraries( target_link_libraries(
NostalgiaStudio NostalgiaStudio
@@ -11,7 +15,7 @@ target_link_libraries(
target_compile_definitions( target_compile_definitions(
NostalgiaStudio PUBLIC NostalgiaStudio PUBLIC
OLYMPIC_APP_VERSION="d2025.02.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.02.1</string> <string>dev build</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>12.0.0</string> <string>12.0.0</string>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "ns_logo.ico"

Binary file not shown.

After

Width:  |  Height:  |  Size: 162 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 B

View File

@@ -0,0 +1,39 @@
{
"cpp": "icondata.cpp",
"namespace": "studio",
"all_files": "WindowIcons",
"files": [
{
"path": "ns_logo16.png",
"cpp_name": "WindowIcon16"
},
{
"path": "ns_logo24.png",
"cpp_name": "WindowIcon24"
},
{
"path": "ns_logo32.png",
"cpp_name": "WindowIcon32"
},
{
"path": "ns_logo40.png",
"cpp_name": "WindowIcon40"
},
{
"path": "ns_logo48.png",
"cpp_name": "WindowIcon48"
},
{
"path": "ns_logo128.png",
"cpp_name": "WindowIcon128"
},
{
"path": "ns_logo264.png",
"cpp_name": "WindowIcon264"
},
{
"path": "ns_logo1080.png",
"cpp_name": "WindowIcon1080"
}
]
}

View File

@@ -4,7 +4,7 @@
#pragma once #pragma once
#include <ox/claw/claw.hpp> #include <ox/claw/read.hpp>
#include <ox/fs/fs.hpp> #include <ox/fs/fs.hpp>
#include "validation.hpp" #include "validation.hpp"

View File

@@ -8,11 +8,11 @@
#include <ox/std/memory.hpp> #include <ox/std/memory.hpp>
#include "assetmanager.hpp" #include "assetmanager.hpp"
#include "typeconv.hpp"
namespace keel { namespace keel {
class Context; class Context;
using PackTransform = ox::Result<bool>(*)(Context&, ox::Buffer &clawData, ox::StringViewCR);
class Context { class Context {
public: public:
@@ -22,7 +22,7 @@ class Context {
AssetManager assetManager; AssetManager assetManager;
ox::HashMap<ox::String, ox::UUID> pathToUuid; ox::HashMap<ox::String, ox::UUID> pathToUuid;
ox::HashMap<ox::UUIDStr, ox::String> uuidToPath; ox::HashMap<ox::UUIDStr, ox::String> uuidToPath;
ox::Vector<class BaseConverter const*> converters; ox::Vector<Converter> converters;
ox::Vector<PackTransform> packTransforms; ox::Vector<PackTransform> packTransforms;
#else #else
std::size_t preloadSectionOffset = 0; std::size_t preloadSectionOffset = 0;
@@ -45,7 +45,7 @@ constexpr ox::SpanView<PackTransform> packTransforms(
#endif #endif
} }
constexpr ox::SpanView<class BaseConverter const*> converters( constexpr ox::SpanView<Converter> converters(
[[maybe_unused]] Context const&ctx) noexcept { [[maybe_unused]] Context const&ctx) noexcept {
#ifndef OX_BARE_METAL #ifndef OX_BARE_METAL
return ctx.converters; return ctx.converters;

View File

@@ -32,7 +32,7 @@ class Module {
[[nodiscard]] [[nodiscard]]
virtual ox::Vector<TypeDescGenerator> types() const noexcept; virtual ox::Vector<TypeDescGenerator> types() const noexcept;
[[nodiscard]] [[nodiscard]]
virtual ox::Vector<const keel::BaseConverter*> converters() const noexcept; virtual ox::Vector<Converter> converters() const noexcept;
[[nodiscard]] [[nodiscard]]
virtual ox::Vector<PackTransform> packTransforms() const noexcept; virtual ox::Vector<PackTransform> packTransforms() const noexcept;
}; };

View File

@@ -4,15 +4,17 @@
#pragma once #pragma once
#include <ox/claw/write.hpp>
#include <ox/std/def.hpp> #include <ox/std/def.hpp>
#include <ox/std/error.hpp> #include <ox/std/error.hpp>
#include <ox/std/string.hpp> #include <ox/std/string.hpp>
#include "asset.hpp" #include "asset.hpp"
#include "context.hpp"
namespace keel { namespace keel {
class Context;
class Wrap { class Wrap {
public: public:
virtual ~Wrap() = default; virtual ~Wrap() = default;
@@ -113,7 +115,7 @@ class BaseConverter {
virtual ox::Result<ox::UPtr<Wrap>> convertPtrToPtr(keel::Context &ctx, Wrap &src) const noexcept = 0; virtual ox::Result<ox::UPtr<Wrap>> convertPtrToPtr(keel::Context &ctx, Wrap &src) const noexcept = 0;
virtual ox::Result<ox::UPtr<Wrap>> convertBuffToPtr( virtual ox::Result<ox::UPtr<Wrap>> convertBuffToPtr(
keel::Context &ctx, ox::BufferView const&srcBuff) const noexcept = 0; Context &ctx, ox::BufferView const&srcBuff) const noexcept = 0;
[[nodiscard]] [[nodiscard]]
constexpr bool matches( constexpr bool matches(
@@ -125,21 +127,37 @@ class BaseConverter {
}; };
template<typename SrcType, typename DstType>
class Converter: public BaseConverter { template<auto Func>
class ConverterFunc final: public BaseConverter {
private:
template<typename SrcType, typename DstType>
struct ParamPack {
using Src = SrcType;
using Dst = DstType;
};
template<typename Src, typename Dst>
static ParamPack<Src, Dst> extractParams(ox::Error (*)(Context&, Src&, Dst&)) {
return {};
}
public: public:
using SrcType = typename decltype(extractParams(Func))::Src;
using DstType = typename decltype(extractParams(Func))::Dst;
[[nodiscard]] [[nodiscard]]
constexpr ox::StringView srcTypeName() const noexcept final { constexpr ox::StringView srcTypeName() const noexcept override {
return ox::ModelTypeName_v<SrcType>; return ox::ModelTypeName_v<SrcType>;
} }
[[nodiscard]] [[nodiscard]]
constexpr int srcTypeVersion() const noexcept final { constexpr int srcTypeVersion() const noexcept override {
return ox::ModelTypeVersion_v<SrcType>; return ox::ModelTypeVersion_v<SrcType>;
} }
[[nodiscard]] [[nodiscard]]
constexpr bool srcMatches(ox::StringViewCR pSrcTypeName, int pSrcTypeVersion) const noexcept final { constexpr bool srcMatches(ox::StringViewCR pSrcTypeName, int pSrcTypeVersion) const noexcept override {
constexpr auto SrcTypeName = ox::requireModelTypeName<SrcType>(); constexpr auto SrcTypeName = ox::requireModelTypeName<SrcType>();
constexpr auto SrcTypeVersion = ox::requireModelTypeVersion<SrcType>(); constexpr auto SrcTypeVersion = ox::requireModelTypeVersion<SrcType>();
return pSrcTypeName == SrcTypeName return pSrcTypeName == SrcTypeName
@@ -147,7 +165,7 @@ class Converter: public BaseConverter {
} }
[[nodiscard]] [[nodiscard]]
constexpr bool dstMatches(ox::StringViewCR dstTypeName, int dstTypeVersion) const noexcept final { constexpr bool dstMatches(ox::StringViewCR dstTypeName, int dstTypeVersion) const noexcept override {
constexpr auto DstTypeName = ox::StringView{ox::requireModelTypeName<DstType>()}; constexpr auto DstTypeName = ox::StringView{ox::requireModelTypeName<DstType>()};
constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>(); constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
return dstTypeName == DstTypeName return dstTypeName == DstTypeName
@@ -155,14 +173,14 @@ class Converter: public BaseConverter {
} }
ox::Result<ox::UPtr<Wrap>> convertPtrToPtr( ox::Result<ox::UPtr<Wrap>> convertPtrToPtr(
keel::Context &ctx, Wrap &src) const noexcept final { Context &ctx, Wrap &src) const noexcept override {
ox::Result<ox::UPtr<Wrap>> dst{makeWrap<DstType>()}; ox::Result<ox::UPtr<Wrap>> dst{makeWrap<DstType>()};
OX_RETURN_ERROR(convert(ctx, wrapCast<SrcType>(src), wrapCast<DstType>(*dst.value))); OX_RETURN_ERROR(convert(ctx, wrapCast<SrcType>(src), wrapCast<DstType>(*dst.value)));
return dst; return dst;
} }
ox::Result<ox::UPtr<Wrap>> convertBuffToPtr( ox::Result<ox::UPtr<Wrap>> convertBuffToPtr(
keel::Context &ctx, ox::BufferView const&srcBuff) const noexcept final { Context &ctx, ox::BufferView const&srcBuff) const noexcept override {
OX_REQUIRE_M(src, readAsset<SrcType>(srcBuff)); OX_REQUIRE_M(src, readAsset<SrcType>(srcBuff));
ox::Result<ox::UPtr<Wrap>> dst{makeWrap<DstType>()}; ox::Result<ox::UPtr<Wrap>> dst{makeWrap<DstType>()};
OX_RETURN_ERROR(convert(ctx, src, wrapCast<DstType>(*dst.value))); OX_RETURN_ERROR(convert(ctx, src, wrapCast<DstType>(*dst.value)));
@@ -170,24 +188,43 @@ class Converter: public BaseConverter {
} }
protected: protected:
virtual ox::Error convert(keel::Context &ctx, SrcType&, DstType&) const noexcept = 0; static ox::Error convert(Context &ctx, SrcType &src, DstType &dst) noexcept {
return Func(ctx, src, dst);
}
}; };
class Converter {
private:
ox::AllocAlias<BaseConverter> m_buff{};
public:
template<auto Func>
static Converter make() noexcept {
Converter out;
static_assert(sizeof(ConverterFunc<Func>) <= sizeof(out.m_buff));
new (out.m_buff.data()) ConverterFunc<Func>{};
return out;
}
[[nodiscard]]
BaseConverter const &converter() const noexcept {
return *m_buff.data();
}
};
ox::Result<ox::UPtr<Wrap>> convert( ox::Result<ox::UPtr<Wrap>> convert(
keel::Context &ctx, Context &ctx,
ox::BufferView const&srcBuffer, ox::BufferView const&srcBuffer,
ox::StringViewCR dstTypeName, ox::StringViewCR dstTypeName,
int dstTypeVersion) noexcept; int dstTypeVersion) noexcept;
ox::Result<ox::UPtr<Wrap>> convert( ox::Result<ox::UPtr<Wrap>> convert(
keel::Context &ctx, Context &ctx,
Wrap &src, Wrap &src,
ox::StringViewCR dstTypeName, ox::StringViewCR dstTypeName,
int dstTypeVersion) noexcept; int dstTypeVersion) noexcept;
ox::Result<ox::UPtr<Wrap>> convert( ox::Result<ox::UPtr<Wrap>> convert(
keel::Context &ctx, Context &ctx,
auto &src, auto &src,
ox::StringViewCR dstTypeName, ox::StringViewCR dstTypeName,
int const dstTypeVersion) noexcept { int const dstTypeVersion) noexcept {
@@ -196,7 +233,7 @@ ox::Result<ox::UPtr<Wrap>> convert(
} }
ox::Result<ox::UPtr<Wrap>> convert( ox::Result<ox::UPtr<Wrap>> convert(
keel::Context &ctx, Context &ctx,
auto const&src, auto const&src,
ox::StringViewCR dstTypeName, ox::StringViewCR dstTypeName,
int const dstTypeVersion) noexcept { int const dstTypeVersion) noexcept {
@@ -207,27 +244,27 @@ ox::Result<ox::UPtr<Wrap>> convert(
template<typename DstType> template<typename DstType>
ox::Result<DstType> convertObjToObj( ox::Result<DstType> convertObjToObj(
keel::Context &ctx, Context &ctx,
auto &src) noexcept { auto &src) noexcept {
OX_REQUIRE_M(out, convert(ctx, WrapRef{src}, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>)); OX_REQUIRE_M(out, convert(ctx, WrapRef{src}, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>));
return std::move(wrapCast(*out)); return std::move(wrapCast(*out));
} }
template<typename DstType> template<typename DstType>
ox::Result<DstType> convert(keel::Context &ctx, ox::BufferView const&src) noexcept { ox::Result<DstType> convert(Context &ctx, ox::BufferView const&src) noexcept {
OX_REQUIRE(out, convert(ctx, src, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>)); OX_REQUIRE(out, convert(ctx, src, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>));
return std::move(wrapCast<DstType>(out)); return std::move(wrapCast<DstType>(out));
} }
template<typename DstType> template<typename DstType>
ox::Error convert(keel::Context &ctx, ox::BufferView const&buff, DstType &outObj) noexcept { ox::Error convert(Context &ctx, ox::BufferView const&buff, DstType &outObj) noexcept {
OX_REQUIRE(out, convert(ctx, buff, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>)); OX_REQUIRE(out, convert(ctx, buff, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>));
outObj = std::move(wrapCast<DstType>(*out)); outObj = std::move(wrapCast<DstType>(*out));
return {}; return {};
} }
template<typename DstType> template<typename DstType>
ox::Error convertObjToObj(keel::Context &ctx, auto &src, DstType &outObj) noexcept { ox::Error convertObjToObj(Context &ctx, auto &src, DstType &outObj) noexcept {
OX_REQUIRE(outPtr, convert(ctx, src, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>)); OX_REQUIRE(outPtr, convert(ctx, src, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>));
outObj = std::move(wrapCast<DstType>(*outPtr)); outObj = std::move(wrapCast<DstType>(*outPtr));
return {}; return {};
@@ -235,13 +272,13 @@ ox::Error convertObjToObj(keel::Context &ctx, auto &src, DstType &outObj) noexce
template<typename DstType> template<typename DstType>
ox::Result<ox::Buffer> convertBuffToBuff( ox::Result<ox::Buffer> convertBuffToBuff(
keel::Context &ctx, ox::BufferView const&src, ox::ClawFormat const fmt) noexcept { Context &ctx, ox::BufferView const&src, ox::ClawFormat const fmt) noexcept {
OX_REQUIRE(out, convert(ctx, src, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>)); OX_REQUIRE(out, convert(ctx, src, ox::ModelTypeName_v<DstType>, ox::ModelTypeVersion_v<DstType>));
return ox::writeClaw<DstType>(wrapCast<DstType>(*out), fmt); return ox::writeClaw<DstType>(wrapCast<DstType>(*out), fmt);
} }
template<typename From, typename To, ox::ClawFormat fmt = ox::ClawFormat::Metal> template<typename From, typename To, ox::ClawFormat fmt = ox::ClawFormat::Metal>
ox::Result<bool> transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringViewCR typeId) noexcept { ox::Result<bool> transformRule(Context &ctx, ox::Buffer &buff, ox::StringViewCR typeId) noexcept {
if (typeId == ox::ModelTypeId_v<From>) { if (typeId == ox::ModelTypeId_v<From>) {
OX_RETURN_ERROR(keel::convertBuffToBuff<To>(ctx, buff, fmt).moveTo(buff)); OX_RETURN_ERROR(keel::convertBuffToBuff<To>(ctx, buff, fmt).moveTo(buff));
return true; return true;
@@ -249,4 +286,6 @@ ox::Result<bool> transformRule(keel::Context &ctx, ox::Buffer &buff, ox::StringV
return false; return false;
}; };
using PackTransform = ox::Result<bool>(*)(Context&, ox::Buffer &clawData, ox::StringViewCR);
} }

View File

@@ -24,7 +24,7 @@ ox::Vector<TypeDescGenerator> Module::types() const noexcept {
return {}; return {};
} }
ox::Vector<keel::BaseConverter const*> Module::converters() const noexcept { ox::Vector<Converter> Module::converters() const noexcept {
return {}; return {};
} }

View File

@@ -2,20 +2,21 @@
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved. * Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/ */
#include <keel/context.hpp>
#include <keel/media.hpp> #include <keel/media.hpp>
#include <keel/typeconv.hpp> #include <keel/typeconv.hpp>
namespace keel { namespace keel {
static ox::Result<BaseConverter const*> findConverter( static ox::Result<BaseConverter const*> findConverter(
ox::SpanView<BaseConverter const*> const&converters, ox::SpanView<Converter> const&converters,
ox::StringViewCR srcTypeName, ox::StringViewCR srcTypeName,
int const srcTypeVersion, int const srcTypeVersion,
ox::StringViewCR dstTypeName, ox::StringViewCR dstTypeName,
int const dstTypeVersion) noexcept { int const dstTypeVersion) noexcept {
for (auto const&c : converters) { for (auto const&c : converters) {
if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) { if (c.converter().matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
return c; return &c.converter();
} }
} }
return ox::Error{1, "Could not find converter"}; return ox::Error{1, "Could not find converter"};
@@ -31,7 +32,7 @@ static ox::Result<ox::UPtr<Wrap>> convert(BaseConverter const&c, Context &ctx, W
static ox::Result<ox::UPtr<Wrap>> convert( static ox::Result<ox::UPtr<Wrap>> convert(
Context &ctx, Context &ctx,
ox::SpanView<BaseConverter const*> const&converters, ox::SpanView<Converter> const&converters,
auto &src, auto &src,
ox::StringViewCR srcTypeName, ox::StringViewCR srcTypeName,
int const srcTypeVersion, int const srcTypeVersion,
@@ -45,14 +46,14 @@ static ox::Result<ox::UPtr<Wrap>> convert(
} }
// try to chain multiple converters // try to chain multiple converters
for (auto const&subConverter : converters) { for (auto const&subConverter : converters) {
if (!subConverter->dstMatches(dstTypeName, dstTypeVersion)) { if (!subConverter.converter().dstMatches(dstTypeName, dstTypeVersion)) {
continue; continue;
} }
const auto [intermediate, chainErr] = const auto [intermediate, chainErr] =
convert(ctx, converters, src, srcTypeName, srcTypeVersion, convert(ctx, converters, src, srcTypeName, srcTypeVersion,
subConverter->srcTypeName(), subConverter->srcTypeVersion()); subConverter.converter().srcTypeName(), subConverter.converter().srcTypeVersion());
if (!chainErr) { if (!chainErr) {
return subConverter->convertPtrToPtr(ctx, *intermediate); return subConverter.converter().convertPtrToPtr(ctx, *intermediate);
} }
} }
return ox::Error{1, "Could not convert between types"}; return ox::Error{1, "Could not convert between types"};

View File

@@ -32,11 +32,15 @@ static void keyEventHandler(turbine::Context &ctx, turbine::Key key, bool down)
sctx->ui.handleKeyEvent(key, down); sctx->ui.handleKeyEvent(key, down);
} }
[[nodiscard]]
ox::Vector<ox::SpanView<uint8_t>> WindowIcons() noexcept;
static ox::Error runApp( static ox::Error runApp(
ox::StringViewCR appName, ox::StringViewCR appName,
ox::StringViewCR projectDataDir, ox::StringViewCR projectDataDir,
ox::UPtr<ox::FileSystem> &&fs) noexcept { ox::UPtr<ox::FileSystem> &&fs) noexcept {
OX_REQUIRE_M(ctx, turbine::init(std::move(fs), appName)); OX_REQUIRE_M(ctx, turbine::init(std::move(fs), appName));
oxLogError(turbine::setWindowIcon(*ctx, WindowIcons()));
turbine::setWindowTitle(*ctx, keelCtx(*ctx).appName); turbine::setWindowTitle(*ctx, keelCtx(*ctx).appName);
turbine::setKeyEventHandler(*ctx, keyEventHandler); turbine::setKeyEventHandler(*ctx, keyEventHandler);
turbine::setRefreshWithin(*ctx, 0); turbine::setRefreshWithin(*ctx, 0);

View File

@@ -71,12 +71,6 @@ class SelectionTracker {
return m_selectionOngoing; return m_selectionOngoing;
} }
constexpr void startSelection(ox::Point cursor) noexcept {
m_pointA = cursor;
m_pointB = cursor;
m_selectionOngoing = true;
}
/** /**
* *
* @param cursor * @param cursor

View File

@@ -26,20 +26,22 @@ void removeDrawer(Context &ctx, Drawer *cd) noexcept;
ox::Error initGfx(Context &ctx) noexcept; ox::Error initGfx(Context &ctx) noexcept;
ox::Error setWindowIcon(Context &ctx, ox::SpanView<ox::SpanView<uint8_t>> const &iconPngs) noexcept;
void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept; void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept;
void focusWindow(Context &ctx) noexcept; void focusWindow(Context &ctx) noexcept;
[[nodiscard]] [[nodiscard]]
int getScreenWidth(Context &ctx) noexcept; int getScreenWidth(Context const &ctx) noexcept;
[[nodiscard]] [[nodiscard]]
int getScreenHeight(Context &ctx) noexcept; int getScreenHeight(Context const &ctx) noexcept;
[[nodiscard]] [[nodiscard]]
ox::Size getScreenSize(Context &ctx) noexcept; ox::Size getScreenSize(Context const &ctx) noexcept;
ox::Bounds getWindowBounds(Context &ctx) noexcept; ox::Bounds getWindowBounds(Context const &ctx) noexcept;
ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept; ox::Error setWindowBounds(Context &ctx, ox::Bounds const&bnds) noexcept;

View File

@@ -27,19 +27,19 @@ ox::Error initGfx(Context&) noexcept {
void setWindowTitle(Context&, ox::StringViewCR) noexcept { void setWindowTitle(Context&, ox::StringViewCR) noexcept {
} }
int getScreenWidth(Context&) noexcept { int getScreenWidth(Context const&) noexcept {
return 240; return 240;
} }
int getScreenHeight(Context&) noexcept { int getScreenHeight(Context const&) noexcept {
return 160; return 160;
} }
ox::Size getScreenSize(Context&) noexcept { ox::Size getScreenSize(Context const&) noexcept {
return {240, 160}; return {240, 160};
} }
ox::Bounds getWindowBounds(Context&) noexcept { ox::Bounds getWindowBounds(Context const&) noexcept {
return {0, 0, 240, 160}; return {0, 0, 240, 160};
} }

View File

@@ -21,4 +21,5 @@ target_link_libraries(
glad glad
glfw glfw
imgui imgui
lodepng
) )

View File

@@ -4,6 +4,7 @@
#include <glad/glad.h> #include <glad/glad.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <lodepng.h>
#if TURBINE_USE_IMGUI #if TURBINE_USE_IMGUI
#include <imgui_impl_glfw.h> #include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h> #include <imgui_impl_opengl3.h>
@@ -228,6 +229,39 @@ ox::Error initGfx(Context &ctx) noexcept {
return {}; return {};
} }
struct IconData {
std::vector<uint8_t> pixels;
int w{}, h{};
};
[[nodiscard]]
static ox::Result<IconData> toGlfwImgPixels(ox::SpanView<uint8_t> const &iconPng) noexcept {
ox::Result<IconData> out;
unsigned w{}, h{};
if (lodepng::decode(out.value.pixels, w, h, iconPng.data(), iconPng.size())) {
return ox::Error{1, "unable to decode window icon PNG data"};
}
out.value.w = static_cast<int>(w);
out.value.h = static_cast<int>(h);
return out;
}
ox::Error setWindowIcon(Context &ctx, ox::SpanView<ox::SpanView<uint8_t>> const &iconPngs) noexcept {
ox::Vector<IconData, 8> src;
ox::Vector<GLFWimage, 8> imgs;
for (auto const &iconPng : iconPngs) {
OX_RETURN_ERROR(toGlfwImgPixels(iconPng).moveTo(src.emplace_back()));
auto &icon = *src.back().unwrap();
imgs.emplace_back(GLFWimage{
.width = icon.w,
.height = icon.h,
.pixels = icon.pixels.data(),
});
}
glfwSetWindowIcon(ctx.window, static_cast<int>(imgs.size()), imgs.data());
return {};
}
void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept { void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept {
auto cstr = ox_malloca(title.bytes() + 1, char); auto cstr = ox_malloca(title.bytes() + 1, char);
ox::strncpy(cstr.get(), title.data(), title.bytes()); ox::strncpy(cstr.get(), title.data(), title.bytes());
@@ -238,25 +272,25 @@ void focusWindow(Context &ctx) noexcept {
glfwFocusWindow(ctx.window); glfwFocusWindow(ctx.window);
} }
int getScreenWidth(Context &ctx) noexcept { int getScreenWidth(Context const &ctx) noexcept {
int w = 0, h = 0; int w = 0, h = 0;
glfwGetFramebufferSize(ctx.window, &w, &h); glfwGetFramebufferSize(ctx.window, &w, &h);
return w; return w;
} }
int getScreenHeight(Context &ctx) noexcept { int getScreenHeight(Context const &ctx) noexcept {
int w = 0, h = 0; int w = 0, h = 0;
glfwGetFramebufferSize(ctx.window, &w, &h); glfwGetFramebufferSize(ctx.window, &w, &h);
return h; return h;
} }
ox::Size getScreenSize(Context &ctx) noexcept { ox::Size getScreenSize(Context const &ctx) noexcept {
int w = 0, h = 0; int w = 0, h = 0;
glfwGetFramebufferSize(ctx.window, &w, &h); glfwGetFramebufferSize(ctx.window, &w, &h);
return {w, h}; return {w, h};
} }
ox::Bounds getWindowBounds(Context &ctx) noexcept { ox::Bounds getWindowBounds(Context const &ctx) noexcept {
ox::Bounds bnds; ox::Bounds bnds;
glfwGetWindowPos(ctx.window, &bnds.x, &bnds.y); glfwGetWindowPos(ctx.window, &bnds.x, &bnds.y);
glfwGetWindowSize(ctx.window, &bnds.width, &bnds.height); glfwGetWindowSize(ctx.window, &bnds.width, &bnds.height);

114
util/scripts/file-to-cpp.py Executable file
View File

@@ -0,0 +1,114 @@
#! /usr/bin/env python3
#
# Copyright 2016 - 2025 gary@drinkingtea.net
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
import argparse
import os
import json
import pathlib
import sys
def write_txt_file(path: str, txt: str):
with open(path, "w") as f:
f.write(txt)
print(f'Wrote {path}')
def file_to_hex(path: str, line_prefix: str) -> tuple[str, int]:
with open(path, 'rb') as f:
out = line_prefix
data = f.read()
i = 1
for b in data:
out += f"{b:#0{4}x},"
if i % 10 == 0:
out += '\n\t'
else:
out += ' '
i += 1
return out[:-1], len(data)
def file_to_cpp(path: str, cpp_name: str) -> tuple[str, str]:
cpp = ''
hpp = ''
data, data_len = file_to_hex(path, "\t")
cpp += f'\nstatic constexpr ox::Array<uint8_t, {data_len}> {cpp_name}Data {{\n{data}\n}};\n'
cpp += f'\nox::SpanView<uint8_t> {cpp_name}() noexcept {{ return {cpp_name}Data; }}\n'
hpp += f'\n[[nodiscard]]\nox::SpanView<uint8_t> {cpp_name}() noexcept;\n'
return cpp, hpp
def proc_rsrc_file(rsrc_path: str):# Open and read the JSON file
with open(rsrc_path, 'r') as file:
data = json.load(file)
base_path = pathlib.Path(rsrc_path).parent.absolute()
if 'all_files' in data:
all_files = data['all_files']
else:
all_files = None
if 'namespace' in data:
namespace = data['namespace']
else:
namespace = ''
if len(namespace) > 0:
push_ns = f'namespace {namespace} {{\n'
pop_ns = '\n}\n'
else:
push_ns = ''
pop_ns = ''
cpp = '// Generated\n\n#include <ox/std/array.hpp>\n'
cpp += '#include <ox/std/span.hpp>\n\n'
hpp = '// Generated\n\n#include <ox/std/span.hpp>\n\n'
cpp += push_ns
hpp += push_ns
all_files_func_decl = ''
all_files_func = ''
if all_files is not None:
all_files_func_decl += f'\n[[nodiscard]]\nox::Vector<ox::SpanView<uint8_t>> {all_files}() noexcept;\n'
all_files_func += f'\nox::Vector<ox::SpanView<uint8_t>> {all_files}() noexcept {{\n\treturn {{\n'
for f in data['files']:
if 'path' not in f:
print('src file path missing', file=sys.stderr)
sys.exit(1)
path = f['path']
if 'cpp_name' not in f:
print('var name missing', file=sys.stderr)
sys.exit(1)
cpp_name = f['cpp_name']
c, h = file_to_cpp(os.path.join(base_path, path), cpp_name)
cpp += c
if len(h) > 0:
hpp += h
if all_files is not None:
all_files_func += f'\t\t{cpp_name}(),\n'
cpp += all_files_func + '\t};\n}\n'
hpp += all_files_func_decl
cpp += pop_ns
hpp += pop_ns
write_txt_file(os.path.join(base_path, data['cpp']), cpp)
if 'hpp' in data:
write_txt_file(os.path.join(base_path, data['hpp']), hpp)
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument('--rsrc', help='path to file', required=True)
args = parser.parse_args()
proc_rsrc_file(args.rsrc)
return 0
if __name__ == '__main__':
try:
err = main()
sys.exit(err)
except KeyboardInterrupt:
sys.exit(1)