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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -14,6 +14,8 @@
#include <ox/std/hashmap.hpp>
#include <ox/std/utility.hpp>
#include "validation.hpp"
namespace keel {
class AssetManager;
@@ -21,17 +23,6 @@ class AssetManager;
template<typename T>
class AssetRef;
[[nodiscard]]
constexpr bool valid(auto const&) noexcept {
return true;
}
[[nodiscard]]
constexpr ox::Error repair(auto const&) noexcept {
return {};
}
#ifndef OX_BARE_METAL
template<typename T>
class AssetContainer {
@@ -226,9 +217,7 @@ class AssetManager {
ox::Result<AssetRef<T>> loadAsset(ox::StringView const assetId) noexcept {
auto &p = m_cache[assetId];
oxRequireM(obj, m_loader(assetId));
if (!valid(obj) && repair(obj)) {
return OxError(1, "asset is invalid state and could not be repaired");
}
oxReturnError(ensureValid(obj));
if (!p) {
p = ox::make_unique<AssetContainer<T>>(std::move(obj));
} else {

View File

@@ -17,10 +17,10 @@ namespace keel {
ox::Error init(
keel::Context &ctx,
ox::UPtr<ox::FileSystem> &&fs,
ox::CRStringView appName) noexcept;
ox::StringViewCR appName) noexcept;
ox::Result<ox::UPtr<Context>> init(
ox::UPtr<ox::FileSystem> &&fs,
ox::CRStringView appName) noexcept;
ox::StringViewCR appName) noexcept;
}

View File

@@ -30,14 +30,14 @@ oxModelBegin(PreloadPtr)
oxModelEnd()
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::FileAddress const&file) noexcept;
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::CRStringView file) noexcept;
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::StringViewCR file) noexcept;
void createUuidMapping(Context &ctx, ox::StringView filePath, ox::UUID const&uuid) noexcept;
ox::Error buildUuidMap(Context &ctx) noexcept;
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::CRStringView path) noexcept;
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::StringViewCR path) noexcept;
ox::Result<ox::UUID> getUuid(Context &ctx, ox::FileAddress const&fileAddr) noexcept;
@@ -53,12 +53,10 @@ constexpr ox::Result<ox::UUID> uuidUrlToUuid(ox::StringView uuidUrl) noexcept {
ox::Result<ox::CStringView> uuidUrlToPath(Context &ctx, ox::StringView uuid) noexcept;
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept;
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::StringViewCR uuid) noexcept;
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexcept;
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept;
#ifndef OX_BARE_METAL
namespace detail {
@@ -116,7 +114,7 @@ ox::Result<keel::AssetRef<T>> readObjFile(
template<typename T>
ox::Result<keel::AssetRef<T>> readObjNoCache(
keel::Context &ctx,
ox::CRStringView assetId) noexcept {
ox::StringViewCR assetId) noexcept {
if constexpr(ox::preloadable<T>::value) {
oxRequire(addr, getPreloadAddr(ctx, assetId));
return keel::AssetRef<T>(std::bit_cast<T const*>(uintptr_t{addr}));
@@ -132,7 +130,7 @@ ox::Error reloadAsset(keel::Context &ctx, ox::StringView assetId) noexcept;
template<typename T>
ox::Result<keel::AssetRef<T>> readObj(
keel::Context &ctx,
ox::CRStringView assetId,
ox::StringViewCR assetId,
[[maybe_unused]] bool forceLoad = false) noexcept {
#ifndef OX_BARE_METAL
return readObjFile<T>(ctx, assetId, forceLoad);
@@ -171,9 +169,9 @@ ox::Error writeObj(
ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs) noexcept;
ox::Result<ox::UniquePtr<ox::FileSystem>> loadRomFs(ox::CRStringView path) noexcept;
ox::Result<ox::UniquePtr<ox::FileSystem>> loadRomFs(ox::StringViewCR path) noexcept;
ox::Result<char*> loadRom(ox::CRStringView path = "") noexcept;
ox::Result<char*> loadRom(ox::StringViewCR path = "") noexcept;
void unloadRom(char*) noexcept;

View File

@@ -15,7 +15,7 @@ using TypeDescGenerator = ox::Error(*)(ox::TypeStore&);
template<typename T>
ox::Error generateTypeDesc(ox::TypeStore &ts) noexcept {
return ox::buildTypeDef<T>(&ts).error;
return ox::buildTypeDef<T>(ts).error;
}
class Module {

View File

@@ -12,6 +12,31 @@
namespace keel {
struct ManifestEntry {
static constexpr auto TypeName = "net.drinkingtea.keel.ManifestEntry";
static constexpr auto TypeVersion = 1;
uint64_t inode{};
bool preloaded{};
ox::String type;
};
oxModelBegin(ManifestEntry)
oxModelField(inode)
oxModelField(preloaded)
oxModelField(type)
oxModelEnd()
struct Manifest {
static constexpr auto TypeName = "net.drinkingtea.keel.Manifest";
static constexpr auto TypeVersion = 1;
ox::HashMap<ox::String, ManifestEntry> files;
};
oxModelBegin(Manifest)
oxModelField(files)
oxModelEnd()
class Context;
struct GbaPlatSpec {
@@ -113,10 +138,11 @@ ox::Error preloadObj(
// transformations need to be done after the copy to the new FS is complete
template<typename PlatSpec>
ox::Error preloadDir(
Manifest &manifest,
ox::TypeStore &ts,
ox::FileSystem &romFs,
ox::Preloader<PlatSpec> &pl,
ox::CRStringView path) noexcept {
ox::StringViewCR path) noexcept {
// copy
oxTracef("pack.preload", "path: {}", path);
oxRequire(fileList, romFs.ls(path));
@@ -125,13 +151,14 @@ ox::Error preloadDir(
oxRequire(stat, romFs.stat(filePath));
if (stat.fileType == ox::FileType::Directory) {
auto const dir = ox::sfmt("{}{}/", path, name);
oxReturnError(preloadDir(ts, romFs, pl, dir));
oxReturnError(preloadDir(manifest, ts, romFs, pl, dir));
} else {
auto const err = preloadObj(ts, romFs, pl, filePath);
if (err) {
oxErrf("\033[31;1;1mCould not preload {}:\n\t{}\n", filePath, toStr(err));
return err;
}
manifest.files[filePath].preloaded = true;
}
}
return {};
@@ -162,11 +189,15 @@ ox::Error appendBinary(ox::Buffer &binBuff, ox::SpanView<char> const&fsBuff, ox:
}
template<typename PlatSpec>
ox::Error preload(ox::TypeStore &ts, ox::FileSystem &src, ox::Preloader<PlatSpec> &pl) noexcept {
ox::Error preload(
Manifest &manifest,
ox::TypeStore &ts,
ox::FileSystem &src,
ox::Preloader<PlatSpec> &pl) noexcept {
oxOut("Preloading\n");
return detail::preloadDir(ts, src, pl, "/");
return detail::preloadDir(manifest, ts, src, pl, "/");
}
ox::Error pack(keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept;
ox::Error pack(Manifest &manifest, keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept;
}

View File

@@ -51,29 +51,29 @@ constexpr T &wrapCast(Wrap &ptr) noexcept {
class BaseConverter {
public:
virtual ~BaseConverter() noexcept = default;
constexpr virtual ~BaseConverter() noexcept = default;
[[nodiscard]]
virtual ox::StringView srcTypeName() const noexcept = 0;
constexpr virtual ox::StringView srcTypeName() const noexcept = 0;
[[nodiscard]]
virtual int srcTypeVersion() const noexcept = 0;
constexpr virtual int srcTypeVersion() const noexcept = 0;
[[nodiscard]]
virtual bool srcMatches(ox::CRStringView pSrcTypeName, int pSrcTypeVersion) const noexcept = 0;
constexpr virtual bool srcMatches(ox::StringViewCR pSrcTypeName, int pSrcTypeVersion) const noexcept = 0;
[[nodiscard]]
virtual bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept = 0;
constexpr virtual bool dstMatches(ox::StringViewCR dstTypeName, int dstTypeVersion) 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(
keel::Context &ctx, ox::Buffer const&srcBuff) const noexcept = 0;
keel::Context &ctx, ox::BufferView const&srcBuff) const noexcept = 0;
[[nodiscard]]
inline bool matches(
ox::CRStringView srcTypeName, int srcTypeVersion,
ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept {
constexpr bool matches(
ox::StringViewCR srcTypeName, int srcTypeVersion,
ox::StringViewCR dstTypeName, int dstTypeVersion) const noexcept {
return srcMatches(srcTypeName, srcTypeVersion)
&& dstMatches(dstTypeName, dstTypeVersion);
}
@@ -84,17 +84,17 @@ template<typename SrcType, typename DstType>
class Converter: public BaseConverter {
public:
[[nodiscard]]
ox::StringView srcTypeName() const noexcept final {
constexpr ox::StringView srcTypeName() const noexcept final {
return ox::ModelTypeName_v<SrcType>;
}
[[nodiscard]]
int srcTypeVersion() const noexcept final {
constexpr int srcTypeVersion() const noexcept final {
return ox::ModelTypeVersion_v<SrcType>;
}
[[nodiscard]]
bool srcMatches(ox::CRStringView pSrcTypeName, int pSrcTypeVersion) const noexcept final {
constexpr bool srcMatches(ox::StringViewCR pSrcTypeName, int pSrcTypeVersion) const noexcept final {
constexpr auto SrcTypeName = ox::requireModelTypeName<SrcType>();
constexpr auto SrcTypeVersion = ox::requireModelTypeVersion<SrcType>();
return pSrcTypeName == SrcTypeName
@@ -102,8 +102,8 @@ class Converter: public BaseConverter {
}
[[nodiscard]]
bool dstMatches(ox::CRStringView dstTypeName, int dstTypeVersion) const noexcept final {
constexpr auto DstTypeName = ox::StringView(ox::requireModelTypeName<DstType>());
constexpr bool dstMatches(ox::StringViewCR dstTypeName, int dstTypeVersion) const noexcept final {
constexpr auto DstTypeName = ox::StringView{ox::requireModelTypeName<DstType>()};
constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
return dstTypeName == DstTypeName
&& dstTypeVersion == DstTypeVersion;
@@ -117,8 +117,9 @@ class Converter: public BaseConverter {
}
ox::Result<ox::UPtr<Wrap>> convertBuffToPtr(
keel::Context &ctx, ox::Buffer const&srcBuff) const noexcept final {
keel::Context &ctx, ox::BufferView const&srcBuff) const noexcept final {
oxRequireM(src, readAsset<SrcType>(srcBuff));
oxReturnError(ensureValid(src));
auto dst = makeWrap<DstType>();
oxReturnError(convert(ctx, src, wrapCast<DstType>(*dst)));
return {std::move(dst)};
@@ -131,12 +132,12 @@ class Converter: public BaseConverter {
ox::Result<ox::UPtr<Wrap>> convert(
keel::Context &ctx,
ox::Buffer const&srcBuffer,
ox::CRStringView dstTypeName,
ox::BufferView const&srcBuffer,
ox::StringViewCR dstTypeName,
int dstTypeVersion) noexcept;
template<typename DstType>
ox::Result<DstType> convert(keel::Context &ctx, ox::Buffer const&srcBuffer) noexcept {
ox::Result<DstType> convert(keel::Context &ctx, ox::BufferView const&srcBuffer) noexcept {
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));
@@ -144,7 +145,7 @@ ox::Result<DstType> convert(keel::Context &ctx, ox::Buffer const&srcBuffer) noex
}
template<typename DstType>
ox::Error convert(keel::Context &ctx, ox::Buffer const&buff, DstType *outObj) noexcept {
ox::Error convert(keel::Context &ctx, ox::BufferView const&buff, DstType *outObj) noexcept {
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
oxRequire(outPtr, convert(ctx, buff, DstTypeName, DstTypeVersion));
@@ -154,7 +155,7 @@ ox::Error convert(keel::Context &ctx, ox::Buffer const&buff, DstType *outObj) no
template<typename DstType>
ox::Result<ox::Buffer> convertBuffToBuff(
keel::Context &ctx, ox::Buffer const&srcBuffer, ox::ClawFormat fmt) noexcept {
keel::Context &ctx, ox::BufferView const&srcBuffer, ox::ClawFormat fmt) noexcept {
static constexpr auto DstTypeName = ox::requireModelTypeName<DstType>();
static constexpr auto DstTypeVersion = ox::requireModelTypeVersion<DstType>();
oxRequire(out, convert(ctx, srcBuffer, DstTypeName, DstTypeVersion));

View File

@@ -0,0 +1,27 @@
/*
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#pragma once
#include <ox/std/error.hpp>
namespace keel {
[[nodiscard]]
constexpr bool valid(auto const&) noexcept {
return true;
}
constexpr ox::Error repair(auto const&) noexcept {
return OxError(1, "No repair function for this type");
}
constexpr ox::Error ensureValid(auto &o) noexcept {
if (!valid(o)) {
return repair(o);
}
return {};
}
}

View File

@@ -9,7 +9,7 @@ namespace keel {
ox::Error init(
keel::Context &ctx,
ox::UPtr<ox::FileSystem> &&fs,
ox::CRStringView appName) noexcept {
ox::StringViewCR appName) noexcept {
ctx.appName = appName;
std::ignore = setRomFs(ctx, std::move(fs));
#ifndef OX_BARE_METAL
@@ -28,7 +28,7 @@ ox::Error init(
return {};
}
ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView appName) noexcept {
ox::Result<ox::UPtr<Context>> init(ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept {
auto ctx = ox::make_unique<Context>();
oxReturnError(keel::init(*ctx, std::move(fs), appName));
return ctx;

View File

@@ -12,7 +12,7 @@
namespace keel {
ox::Result<char*> loadRom(ox::CRStringView path) noexcept {
ox::Result<char*> loadRom(ox::StringViewCR path) noexcept {
std::ifstream file(std::string(toStdStringView(path)), std::ios::binary | std::ios::ate);
if (!file.good()) {
oxErrorf("Could not find ROM file: {}", path);
@@ -47,7 +47,7 @@ void createUuidMapping(Context &ctx, ox::StringView filePath, ox::UUID const&uui
ctx.uuidToPath[uuid.toString()] = filePath;
}
static ox::Error buildUuidMap(Context &ctx, ox::CRStringView path) noexcept {
static ox::Error buildUuidMap(Context &ctx, ox::StringViewCR path) noexcept {
oxRequire(files, ctx.rom->ls(path));
for (auto const&f : files) {
oxRequireM(filePath, ox::join("/", ox::Array<ox::StringView, 2>{path, f}));
@@ -74,7 +74,7 @@ ox::Error buildUuidMap(Context &ctx) noexcept {
return buildUuidMap(ctx, "");
}
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::CRStringView path) noexcept {
ox::Result<ox::UUID> pathToUuid(Context &ctx, ox::StringViewCR path) noexcept {
#ifndef OX_BARE_METAL
oxRequire(out, ctx.pathToUuid.at(path));
return *out;
@@ -136,7 +136,7 @@ ox::Result<ox::CStringView> uuidUrlToPath(Context &ctx, ox::StringView uuid) noe
#endif
}
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::CRStringView uuid) noexcept {
ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::StringViewCR uuid) noexcept {
#ifndef OX_BARE_METAL
oxRequireM(out, ctx.uuidToPath.at(uuid));
return ox::CStringView(*out);
@@ -154,18 +154,6 @@ ox::Result<ox::CStringView> uuidToPath(Context &ctx, ox::UUID const&uuid) noexce
#endif
}
ox::Error performPackTransforms(Context &ctx, ox::Buffer &clawData) noexcept {
oxRequireM(typeId, readAssetTypeId(clawData));
for (auto const tr : packTransforms(ctx)) {
bool changed{};
oxReturnError(tr(ctx, clawData, typeId).moveTo(changed));
if (changed) {
oxReturnError(readAssetTypeId(clawData).moveTo(typeId));
}
}
return {};
}
ox::Error reloadAsset(keel::Context &ctx, ox::StringView assetId) noexcept {
ox::UUIDStr uuidStr;
if (beginsWith(assetId, "uuid://")) {
@@ -198,7 +186,7 @@ ox::Error buildUuidMap(Context&) noexcept {
return {};
}
ox::Result<char*> loadRom(ox::CRStringView) noexcept {
ox::Result<char*> loadRom(ox::StringViewCR) noexcept {
// put the header in the wrong order to prevent mistaking this code for the
// media section
constexpr auto headerP2 = "R_______________";
@@ -218,7 +206,7 @@ ox::Result<char*> loadRom(ox::CRStringView) noexcept {
void unloadRom(char*) noexcept {
}
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::CRStringView path) noexcept {
ox::Result<std::size_t> getPreloadAddr(keel::Context &ctx, ox::StringViewCR path) noexcept {
oxRequire(stat, ctx.rom->stat(path));
oxRequire(buff, static_cast<ox::MemFS*>(ctx.rom.get())->directAccess(path));
PreloadPtr p;
@@ -250,7 +238,7 @@ ox::Error setRomFs(Context &ctx, ox::UPtr<ox::FileSystem> &&fs) noexcept {
return buildUuidMap(ctx);
}
ox::Result<ox::UniquePtr<ox::FileSystem>> loadRomFs(ox::CRStringView path) noexcept {
ox::Result<ox::UniquePtr<ox::FileSystem>> loadRomFs(ox::StringViewCR path) noexcept {
auto const lastDot = ox::lastIndexOf(path, '.');
if (!lastDot.error && substr(path, lastDot.value) == ".oxfs") {
oxRequire(rom, loadRom(path));

View File

@@ -8,6 +8,7 @@
#include <ox/fs/fs.hpp>
#include <ox/logconn/def.hpp>
#include <ox/logconn/logconn.hpp>
#include <ox/oc/write.hpp>
#include <keel/keel.hpp>
@@ -48,16 +49,21 @@ static ox::Error generateTypes(ox::TypeStore &ts) noexcept {
return {};
}
static ox::Error pack(ox::StringView argSrc, ox::StringView argRomBin, ox::StringView projectDataDir) noexcept {
static ox::Error pack(
ox::StringView argSrc,
ox::StringView argRomBin,
ox::StringView argManifest,
ox::StringView projectDataDir) noexcept {
ox::Buffer dstBuff(32 * ox::units::MB);
oxReturnError(ox::FileSystem32::format(dstBuff.data(), dstBuff.size()));
ox::FileSystem32 dst(dstBuff);
oxRequire(ctx, keel::init(ox::make_unique<ox::PassThroughFS>(argSrc), "keel-pack"));
keel::TypeStore ts(*ctx->rom, ox::sfmt("{}/type_descriptors", projectDataDir));
oxReturnError(generateTypes(ts));
oxReturnError(keel::pack(*ctx, ts, dst));
keel::Manifest manifest;
oxReturnError(keel::pack(manifest, *ctx, ts, dst));
oxRequireM(pl, keel::GbaPreloader::make());
oxReturnError(preload(ts, dst, *pl));
oxReturnError(preload(manifest, ts, dst, *pl));
oxReturnError(dst.resize());
// resize buffer
oxRequire(dstSize, dst.size());
@@ -70,6 +76,8 @@ static ox::Error pack(ox::StringView argSrc, ox::StringView argRomBin, ox::Strin
oxReturnError(appendBinary(romBuff, dstBuff, *pl));
oxOutf("Final ROM buff size: {} bytes\n", romBuff.size());
oxReturnError(writeFileBuff(argRomBin, romBuff));
oxRequire(manifestJson, ox::writeOCString(manifest));
oxReturnError(writeFileBuff(argManifest, {manifestJson.data(), manifestJson.len()}));
return {};
}
@@ -77,6 +85,7 @@ static ox::Error run(int argc, char const**argv, ox::StringView projectDataDir)
ox::ClArgs const args(argc, argv);
auto const argSrc = args.getString("src", "");
auto const argRomBin = args.getString("rom-bin", "");
auto const argManifest = args.getString("manifest", "");
if (argSrc == "") {
oxErr("\033[31;1;1merror:\033[0m must specify a source directory\n");
return OxError(1, "must specify a source directory");
@@ -85,7 +94,7 @@ static ox::Error run(int argc, char const**argv, ox::StringView projectDataDir)
oxErr("\033[31;1;1merror:\033[0m must specify a path for ROM file\n");
return OxError(1, "must specify a path for preload file");
}
return pack(argSrc, argRomBin, projectDataDir);
return pack(argSrc, argRomBin, argManifest, projectDataDir);
}
namespace olympic {

View File

@@ -6,13 +6,14 @@
#include <ox/model/modelvalue.hpp>
#include <keel/media.hpp>
#include <keel/pack.hpp>
namespace keel {
static ox::Error pathToInode(
keel::Context &ctx, ox::FileSystem &dest, ox::ModelObject &obj) noexcept {
keel::Context &ctx,
ox::FileSystem &dest,
ox::ModelObject &obj) noexcept {
auto &o = obj;
auto type = static_cast<ox::FileAddressType>(o.at("type").unwrap()->get<int8_t>());
auto &data = o.at("data").unwrap()->get<ox::ModelUnion>();
@@ -85,16 +86,33 @@ static ox::Error transformFileAddressesObj(
return {};
}
static ox::Error performPackTransforms(
ManifestEntry &entry,
Context &ctx,
ox::Buffer &clawData) noexcept {
oxRequireM(typeId, readAssetTypeId(clawData));
for (auto const tr : packTransforms(ctx)) {
bool changed{};
oxReturnError(tr(ctx, clawData, typeId).moveTo(changed));
if (changed) {
oxReturnError(readAssetTypeId(clawData).moveTo(typeId));
}
}
entry.type = ox::String{typeId};
return {};
}
static ox::Error doTransformations(
Manifest &manifest,
keel::Context &ctx,
ox::TypeStore &ts,
ox::FileSystem &dest,
ox::CRStringView filePath) noexcept {
ox::StringViewCR filePath) noexcept {
// load file
oxRequire(s, dest.stat(filePath));
// do transformations
oxRequireM(buff, dest.read(s.inode));
oxReturnError(keel::performPackTransforms(ctx, buff));
oxReturnError(keel::performPackTransforms(manifest.files[filePath], ctx, buff));
// transform FileAddresses
oxRequireM(obj, keel::readAsset(ts, buff));
oxOutf("transforming {}\n", filePath);
@@ -108,10 +126,11 @@ static ox::Error doTransformations(
// claw file transformations are broken out from copy because path to inode
// transformations need to be done after the copy to the new FS is complete
static ox::Error transformClaw(
Manifest &manifest,
keel::Context &ctx,
ox::TypeStore &ts,
ox::FileSystem &dest,
ox::CRStringView path) noexcept {
ox::StringViewCR path) noexcept {
// copy
oxTracef("pack.transformClaw", "path: {}", path);
oxRequire(fileList, dest.ls(path));
@@ -120,9 +139,9 @@ static ox::Error transformClaw(
oxRequire(stat, dest.stat(filePath));
if (stat.fileType == ox::FileType::Directory) {
auto const dir = ox::sfmt("{}{}/", path, name);
oxReturnError(transformClaw(ctx, ts, dest, dir));
oxReturnError(transformClaw(manifest, ctx, ts, dest, dir));
} else {
auto const err = doTransformations(ctx, ts, dest, filePath);
auto const err = doTransformations(manifest, ctx, ts, dest, filePath);
if (err) {
oxErrf("\033[31;1;1mCould not do transformations for {}:\n\t{}\n", filePath, toStr(err));
return err;
@@ -133,10 +152,13 @@ static ox::Error transformClaw(
}
static ox::Error copy(
Manifest &manifest,
ox::FileSystem &src,
ox::FileSystem &dest,
ox::CRStringView path) noexcept {
oxOutf("copying directory: {}\n", path);
ox::StringViewCR path,
ox::StringViewCR logPrefix = "") noexcept {
oxOutf("{}copying directory: {}\n", logPrefix, path);
auto const childLogPrefix = ox::sfmt("{}\t", logPrefix);
// copy
oxRequire(fileList, src.ls(path));
for (auto const&name : fileList) {
@@ -147,27 +169,36 @@ static ox::Error copy(
oxRequire(stat, src.stat(currentFile));
if (stat.fileType == ox::FileType::Directory) {
oxReturnError(dest.mkdir(currentFile, true));
oxReturnError(copy(src, dest, currentFile + '/'));
oxReturnError(copy(manifest, src, dest, currentFile + '/', childLogPrefix));
} else {
// load file
oxOutf("copying file: {}\n", currentFile);
oxOutf("{}copying file: {}...", childLogPrefix, currentFile);
ox::StringView status = "failed";
oxDefer [&status] {
oxOutf(" {}\n", status);
};
oxRequireM(buff, src.read(currentFile));
// write file to dest
oxReturnError(dest.write(currentFile, buff));
status = "OK";
oxRequire(stat, dest.stat(currentFile));
manifest.files[currentFile] = {
.inode = stat.inode,
.type = ox::String{keel::readAssetTypeId(buff).or_value({})},
};
}
}
return {};
}
static ox::Error copyFS(ox::FileSystem &src, ox::FileSystem &dest) noexcept {
oxReturnError(copy(src, dest, "/"));
return {};
}
ox::Error pack(keel::Context &ctx, ox::TypeStore &ts, ox::FileSystem &dest) noexcept {
oxReturnError(copyFS(*ctx.rom, dest));
ox::Error pack(
Manifest &manifest,
keel::Context &ctx,
ox::TypeStore &ts,
ox::FileSystem &dest) noexcept {
oxReturnError(copy(manifest, *ctx.rom, dest, "/"));
oxOut("Doing transforms\n");
oxReturnError(transformClaw(ctx, ts, dest, "/"));
oxReturnError(transformClaw(manifest, ctx, ts, dest, "/"));
return {};
}

View File

@@ -9,12 +9,11 @@
namespace keel {
[[nodiscard]]
static ox::Result<BaseConverter const*> findConverter(
ox::SpanView<BaseConverter const*> const&converters,
ox::CRStringView srcTypeName,
ox::StringViewCR srcTypeName,
int srcTypeVersion,
ox::CRStringView dstTypeName,
ox::StringViewCR dstTypeName,
int dstTypeVersion) noexcept {
for (auto const&c : converters) {
if (c->matches(srcTypeName, srcTypeVersion, dstTypeName, dstTypeVersion)) {
@@ -27,10 +26,10 @@ static ox::Result<BaseConverter const*> findConverter(
static ox::Result<ox::UPtr<Wrap>> convert(
keel::Context &ctx,
ox::SpanView<BaseConverter const*> const&converters,
ox::Buffer const&srcBuffer,
ox::CRStringView srcTypeName,
ox::BufferView const&srcBuffer,
ox::StringViewCR srcTypeName,
int srcTypeVersion,
ox::CRStringView dstTypeName,
ox::StringViewCR dstTypeName,
int dstTypeVersion) noexcept {
// look for direct converter
auto [c, err] = findConverter(
@@ -55,8 +54,8 @@ static ox::Result<ox::UPtr<Wrap>> convert(
ox::Result<ox::UPtr<Wrap>> convert(
keel::Context &ctx,
ox::Buffer const&srcBuffer,
ox::CRStringView dstTypeName,
ox::BufferView const&srcBuffer,
ox::StringViewCR dstTypeName,
int dstTypeVersion) noexcept {
oxRequire(hdr, readAssetHeader(srcBuffer));
return convert(

View File

@@ -8,12 +8,12 @@
namespace studio {
ClawEditor::ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept:
Editor(path),
m_obj(std::move(obj)) {
ClawEditor::ClawEditor(StudioContext &sctx, ox::StringParam path):
Editor(std::move(path)),
m_obj(sctx.project->loadObj<ox::ModelObject>(itemPath()).unwrapThrow()) {
}
void ClawEditor::draw(studio::StudioContext&) noexcept {
void ClawEditor::draw(StudioContext&) noexcept {
ImGui::BeginChild("PaletteEditor");
static constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
if (ImGui::BeginTable("ObjTree", 3, flags)) {
@@ -93,7 +93,7 @@ void ClawEditor::drawRow(ox::ModelValue const&value) noexcept {
ImGui::Text("%s", val.c_str());
}
void ClawEditor::drawVar(ObjPath &path, ox::CRStringView name, ox::ModelValue const&value) noexcept {
void ClawEditor::drawVar(ObjPath &path, ox::StringViewCR name, ox::ModelValue const&value) noexcept {
using Str = ox::BasicString<100>;
path.push_back(name);
if (value.type() == ox::ModelValue::Type::Object) {

View File

@@ -11,19 +11,19 @@
namespace studio {
class ClawEditor: public studio::Editor {
class ClawEditor: public Editor {
private:
using ObjPath = ox::Vector<ox::StringView, 8>;
ox::ModelObject m_obj;
public:
ClawEditor(ox::CRStringView path, ox::ModelObject obj) noexcept;
ClawEditor(StudioContext &sctx, ox::StringParam path);
void draw(studio::StudioContext&) noexcept final;
void draw(StudioContext&) noexcept final;
private:
static void drawRow(ox::ModelValue const&value) noexcept;
void drawVar(ObjPath &path, ox::CRStringView name, ox::ModelValue const&value) noexcept;
void drawVar(ObjPath &path, ox::StringViewCR name, ox::ModelValue const&value) noexcept;
void drawTree(ObjPath &path, ox::ModelObject const&obj) noexcept;
};

View File

@@ -34,8 +34,8 @@ static void keyEventHandler(turbine::Context &ctx, turbine::Key key, bool down)
}
static ox::Error runApp(
ox::CRStringView appName,
ox::CRStringView projectDataDir,
ox::StringViewCR appName,
ox::StringViewCR projectDataDir,
ox::UPtr<ox::FileSystem> &&fs) noexcept {
oxRequireM(ctx, turbine::init(std::move(fs), appName));
turbine::setWindowTitle(*ctx, keelCtx(*ctx).appName);
@@ -50,8 +50,8 @@ static ox::Error runApp(
}
static ox::Error run(
ox::CRStringView appName,
ox::CRStringView projectDataDir,
ox::StringViewCR appName,
ox::StringViewCR projectDataDir,
int,
char const**) {
// seed UUID generator

View File

@@ -51,7 +51,7 @@ void ProjectExplorer::setModel(ox::UPtr<ProjectTreeModel> &&model) noexcept {
m_treeModel = std::move(model);
}
ox::Error ProjectExplorer::refreshProjectTreeModel(ox::CRStringView) noexcept {
ox::Error ProjectExplorer::refreshProjectTreeModel(ox::StringViewCR) noexcept {
oxRequireM(model, buildProjectTreeModel(*this, "Project", "/", nullptr));
setModel(std::move(model));
return OxError(0);

View File

@@ -23,7 +23,7 @@ class ProjectExplorer: public studio::Widget {
void setModel(ox::UPtr<ProjectTreeModel> &&model) noexcept;
ox::Error refreshProjectTreeModel(ox::CRStringView = {}) noexcept;
ox::Error refreshProjectTreeModel(ox::StringViewCR = {}) noexcept;
[[nodiscard]]
inline ox::FileSystem *romFs() noexcept {

View File

@@ -318,7 +318,7 @@ void StudioUI::handleKeyInput() noexcept {
}
}
ox::Error StudioUI::createOpenProject(ox::CRStringView path) noexcept {
ox::Error StudioUI::createOpenProject(ox::StringViewCR path) noexcept {
std::error_code ec;
std::filesystem::create_directories(toStdStringView(path), ec);
oxReturnError(OxError(ec.value() != 0, "Could not create project directory"));
@@ -346,11 +346,11 @@ ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept {
return m_projectExplorer.refreshProjectTreeModel();
}
ox::Error StudioUI::openFile(ox::CRStringView path) noexcept {
ox::Error StudioUI::openFile(ox::StringViewCR path) noexcept {
return openFileActiveTab(path, true);
}
ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab) noexcept {
ox::Error StudioUI::openFileActiveTab(ox::StringViewCR path, bool makeActiveTab) noexcept {
if (!m_project) {
return OxError(1, "No project open to open a file from");
}
@@ -366,23 +366,17 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
}
oxRequire(ext, studio::fileExt(path));
// create Editor
studio::BaseEditor *editor = nullptr;
if (!m_editorMakers.contains(ext)) {
auto [obj, err] = m_project->loadObj<ox::ModelObject>(path);
if (err) {
return OxError(1, "There is no editor for this file extension");
}
editor = ox::make<ClawEditor>(path, std::move(obj));
} else {
auto const err = m_editorMakers[ext](path).moveTo(editor);
if (err) {
if constexpr(!ox::defines::Debug) {
oxErrf("Could not open Editor: {}\n", toStr(err));
} else {
oxErrf("Could not open Editor: {} ({}:{})\n", err.errCode, err.file, err.line);
}
return err;
BaseEditor *editor = nullptr;
auto const err = m_editorMakers.contains(ext) ?
m_editorMakers[ext](path).moveTo(editor) :
ox::makeCatch<ClawEditor>(m_sctx, path).moveTo(editor);
if (err) {
if constexpr(!ox::defines::Debug) {
oxErrf("Could not open Editor: {}\n", toStr(err));
} else {
oxErrf("Could not open Editor: {} ({}:{})\n", err.errCode, err.file, err.line);
}
return err;
}
editor->closed.connect(this, &StudioUI::closeFile);
m_editors.emplace_back(editor);
@@ -400,7 +394,7 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
return {};
}
ox::Error StudioUI::closeFile(ox::CRStringView path) noexcept {
ox::Error StudioUI::closeFile(ox::StringViewCR path) noexcept {
if (!m_openFiles.contains(path)) {
return {};
}

View File

@@ -83,15 +83,15 @@ class StudioUI: public ox::SignalHandler {
void handleKeyInput() noexcept;
ox::Error createOpenProject(ox::CRStringView path) noexcept;
ox::Error createOpenProject(ox::StringViewCR path) noexcept;
ox::Error openProjectPath(ox::StringParam path) noexcept;
ox::Error openFile(ox::CRStringView path) noexcept;
ox::Error openFile(ox::StringViewCR path) noexcept;
ox::Error openFileActiveTab(ox::CRStringView path, bool makeActiveTab) noexcept;
ox::Error openFileActiveTab(ox::StringViewCR path, bool makeActiveTab) noexcept;
ox::Error closeFile(ox::CRStringView path) noexcept;
ox::Error closeFile(ox::StringViewCR path) noexcept;
};
}

View File

@@ -33,7 +33,7 @@ inline ox::String slashesToPct(ox::StringView str) noexcept {
ox::String configPath(keel::Context const&ctx) noexcept;
template<typename T>
ox::Result<T> readConfig(keel::Context &ctx, ox::CRStringView name) noexcept {
ox::Result<T> readConfig(keel::Context &ctx, ox::StringViewCR name) noexcept {
oxAssert(name != "", "Config type has no TypeName");
auto const path = ox::sfmt("/{}.json", detail::slashesToPct(name));
ox::PassThroughFS fs(configPath(ctx));
@@ -52,7 +52,7 @@ ox::Result<T> readConfig(keel::Context &ctx) noexcept {
}
template<typename T>
ox::Error writeConfig(keel::Context &ctx, ox::CRStringView name, T const&data) noexcept {
ox::Error writeConfig(keel::Context &ctx, ox::StringViewCR name, T const&data) noexcept {
oxAssert(name != "", "Config type has no TypeName");
auto const path = ox::sfmt("/{}.json", detail::slashesToPct(name));
ox::PassThroughFS fs(configPath(ctx));
@@ -76,7 +76,7 @@ ox::Error writeConfig(keel::Context &ctx, T const&data) noexcept {
}
template<typename T, typename Func>
void openConfig(keel::Context &ctx, ox::CRStringView name, Func f) noexcept {
void openConfig(keel::Context &ctx, ox::StringViewCR name, Func f) noexcept {
oxAssert(name != "", "Config type has no TypeName");
auto const [c, err] = readConfig<T>(ctx, name);
oxLogError(err);
@@ -90,7 +90,7 @@ void openConfig(keel::Context &ctx, Func f) noexcept {
}
template<typename T, typename Func>
void editConfig(keel::Context &ctx, ox::CRStringView name, Func f) noexcept {
void editConfig(keel::Context &ctx, ox::StringViewCR name, Func f) noexcept {
oxAssert(name != "", "Config type has no TypeName");
auto [c, err] = readConfig<T>(ctx, name);
oxLogError(err);

View File

@@ -17,7 +17,7 @@ struct FDFilterItem {
String name{};
String spec{};
constexpr FDFilterItem() noexcept = default;
FDFilterItem(ox::CRStringView pName, ox::CRStringView pSpec) noexcept;
FDFilterItem(ox::StringViewCR pName, ox::StringViewCR pSpec) noexcept;
};
ox::Result<ox::String> saveFile(ox::Vector<FDFilterItem> const&exts) noexcept;

View File

@@ -18,7 +18,7 @@ namespace studio {
class ItemMaker;
struct EditorMaker {
using Func = std::function<ox::Result<class BaseEditor*>(ox::CRStringView)>;
using Func = std::function<ox::Result<class BaseEditor*>(ox::StringViewCR)>;
ox::Vector<ox::String> fileTypes;
Func make;
};
@@ -38,7 +38,7 @@ template<typename Editor>
studio::EditorMaker editorMaker(studio::StudioContext &ctx, ox::StringParam ext) noexcept {
return {
{std::move(ext)},
[&ctx](ox::CRStringView path) -> ox::Result<studio::BaseEditor*> {
[&ctx](ox::StringViewCR path) -> ox::Result<studio::BaseEditor*> {
return ox::makeCatch<Editor>(ctx, path);
}
};

View File

@@ -28,7 +28,7 @@ enum class ProjectEvent {
};
[[nodiscard]]
constexpr ox::Result<ox::StringView> fileExt(ox::CRStringView path) noexcept {
constexpr ox::Result<ox::StringView> fileExt(ox::StringViewCR path) noexcept {
auto const extStart = ox::find(path.crbegin(), path.crend(), '.').offset();
if (!extStart) {
return OxError(1, "file path does not have valid extension");
@@ -57,7 +57,7 @@ class Project {
ox::HashMap<ox::String, ox::Vector<ox::String>> m_fileExtFileMap;
public:
explicit Project(keel::Context &ctx, ox::String path, ox::CRStringView projectDataDir);
explicit Project(keel::Context &ctx, ox::String path, ox::StringViewCR projectDataDir);
ox::Error create() noexcept;
@@ -67,14 +67,14 @@ class Project {
[[nodiscard]]
ox::FileSystem &romFs() noexcept;
ox::Error mkdir(ox::CRStringView path) const noexcept;
ox::Error mkdir(ox::StringViewCR path) const noexcept;
/**
* Writes a MetalClaw object to the project at the given path.
*/
template<typename T>
ox::Error writeObj(
ox::CRStringView path,
ox::StringViewCR path,
T const&obj,
ox::ClawFormat fmt) noexcept;
@@ -83,60 +83,63 @@ class Project {
*/
template<typename T>
ox::Error writeObj(
ox::CRStringView path,
ox::StringViewCR path,
T const&obj) noexcept;
template<typename T>
ox::Result<T> loadObj(ox::CRStringView path) const noexcept;
ox::Result<T> loadObj(ox::StringViewCR path) const noexcept;
ox::Result<ox::FileStat> stat(ox::CRStringView path) const noexcept;
ox::Result<ox::FileStat> stat(ox::StringViewCR path) const noexcept;
[[nodiscard]]
bool exists(ox::CRStringView path) const noexcept;
bool exists(ox::StringViewCR path) const noexcept;
template<typename Functor>
ox::Error subscribe(ProjectEvent e, ox::SignalHandler *tgt, Functor &&slot) const noexcept;
[[nodiscard]]
ox::Vector<ox::String> const&fileList(ox::CRStringView ext) noexcept;
ox::Vector<ox::String> const&fileList(ox::StringViewCR ext) noexcept;
ox::Error writeTypeStore() noexcept;
private:
void buildFileIndex() noexcept;
void indexFile(ox::CRStringView path) noexcept;
void indexFile(ox::StringViewCR path) noexcept;
ox::Error writeBuff(ox::CRStringView path, ox::Buffer const&buff) noexcept;
ox::Error writeBuff(ox::StringViewCR path, ox::BufferView const&buff) noexcept;
ox::Result<ox::Buffer> loadBuff(ox::CRStringView path) const noexcept;
ox::Result<ox::Buffer> loadBuff(ox::StringViewCR path) const noexcept;
ox::Error lsProcDir(ox::Vector<ox::String> *paths, ox::CRStringView path) const noexcept;
ox::Error lsProcDir(ox::Vector<ox::String> *paths, ox::StringViewCR path) const noexcept;
ox::Result<ox::Vector<ox::String>> listFiles(ox::CRStringView path = "") const noexcept;
ox::Result<ox::Vector<ox::String>> listFiles(ox::StringViewCR path = "") const noexcept;
// signals
public:
ox::Signal<ox::Error(ProjectEvent, ox::CRStringView)> fileEvent;
ox::Signal<ox::Error(ox::CRStringView)> fileAdded;
ox::Signal<ox::Error(ProjectEvent, ox::StringViewCR)> fileEvent;
ox::Signal<ox::Error(ox::StringViewCR)> fileAdded;
// FileRecognized is triggered for all matching files upon a new
// subscription to a section of the project and upon the addition of a
// file.
ox::Signal<ox::Error(ox::CRStringView)> fileRecognized;
ox::Signal<ox::Error(ox::CRStringView)> fileDeleted;
ox::Signal<ox::Error(ox::StringViewCR)> fileRecognized;
ox::Signal<ox::Error(ox::StringViewCR)> fileDeleted;
ox::Signal<ox::Error(ox::StringView, ox::UUID)> fileUpdated;
};
template<typename T>
ox::Error Project::writeObj(ox::CRStringView path, T const&obj, ox::ClawFormat fmt) noexcept {
ox::Error Project::writeObj(ox::StringViewCR path, T const&obj, ox::ClawFormat fmt) noexcept {
oxRequireM(buff, ox::writeClaw(obj, fmt));
if (fmt == ox::ClawFormat::Organic) {
buff.pop_back();
}
// write to FS
oxReturnError(mkdir(parentDir(path)));
oxReturnError(writeBuff(path, buff));
// write type descriptor
if (m_typeStore.get<T>().error) {
oxReturnError(ox::buildTypeDef(&m_typeStore, &obj));
oxReturnError(ox::buildTypeDef(m_typeStore, obj));
}
oxRequire(desc, m_typeStore.get<T>());
auto const descPath = ox::sfmt("{}/{}", m_typeDescPath, buildTypeId(*desc));
@@ -151,14 +154,14 @@ ox::Error Project::writeObj(ox::CRStringView path, T const&obj, ox::ClawFormat f
}
template<typename T>
ox::Error Project::writeObj(ox::CRStringView path, T const&obj) noexcept {
ox::Error Project::writeObj(ox::StringViewCR path, T const&obj) noexcept {
oxRequire(ext, fileExt(path));
auto const fmt = m_typeFmt[ext].or_value(ox::ClawFormat::Metal);
return writeObj(path, obj, fmt);
}
template<typename T>
ox::Result<T> Project::loadObj(ox::CRStringView path) const noexcept {
ox::Result<T> Project::loadObj(ox::StringViewCR path) const noexcept {
oxRequire(buff, loadBuff(path));
if constexpr(ox::is_same_v<T, ox::ModelObject>) {
return keel::readAsset(m_typeStore, buff);

View File

@@ -11,7 +11,7 @@
namespace studio {
FDFilterItem::FDFilterItem(ox::CRStringView pName, ox::CRStringView pSpec) noexcept {
FDFilterItem::FDFilterItem(ox::StringViewCR pName, ox::StringViewCR pSpec) noexcept {
name.resize(pName.len() + 1);
ox::strncpy(name.data(), pName.data(), pName.len());
spec.resize(pSpec.len() + 1);

View File

@@ -26,7 +26,7 @@ static void generateTypes(ox::TypeStore &ts) noexcept {
}
}
Project::Project(keel::Context &ctx, ox::String path, ox::CRStringView projectDataDir):
Project::Project(keel::Context &ctx, ox::String path, ox::StringViewCR projectDataDir):
m_ctx(ctx),
m_path(std::move(path)),
m_projectDataDir(projectDataDir),
@@ -55,7 +55,7 @@ ox::FileSystem &Project::romFs() noexcept {
return m_fs;
}
ox::Error Project::mkdir(ox::CRStringView path) const noexcept {
ox::Error Project::mkdir(ox::StringViewCR path) const noexcept {
auto const [stat, err] = m_fs.stat(path);
if (err) {
oxReturnError(m_fs.mkdir(path, true));
@@ -65,15 +65,15 @@ ox::Error Project::mkdir(ox::CRStringView path) const noexcept {
ox::Error{} : OxError(1, "path exists as normal file");
}
ox::Result<ox::FileStat> Project::stat(ox::CRStringView path) const noexcept {
ox::Result<ox::FileStat> Project::stat(ox::StringViewCR path) const noexcept {
return m_fs.stat(path);
}
bool Project::exists(ox::CRStringView path) const noexcept {
bool Project::exists(ox::StringViewCR path) const noexcept {
return m_fs.stat(path).error == 0;
}
ox::Vector<ox::String> const&Project::fileList(ox::CRStringView ext) noexcept {
ox::Vector<ox::String> const&Project::fileList(ox::StringViewCR ext) noexcept {
return m_fileExtFileMap[ext];
}
@@ -81,12 +81,10 @@ ox::Error Project::writeTypeStore() noexcept {
// write all descriptors because we don't know which types T depends on
oxReturnError(mkdir(m_typeDescPath));
for (auto const &t: m_typeStore.typeList()) {
oxRequireM(typeOut, ox::writeClaw(*t, ox::ClawFormat::Organic));
// replace garbage last character with new line
*typeOut.back().value = '\n';
oxRequire(typeOut, ox::writeClaw(*t, ox::ClawFormat::Organic));
// write to FS
auto const typePath = ox::sfmt("{}/{}", m_typeDescPath, buildTypeId(*t));
oxReturnError(writeBuff(typePath, typeOut));
oxReturnError(writeBuff(typePath, {typeOut.data(), typeOut.size() - 1}));
}
return {};
}
@@ -106,7 +104,7 @@ void Project::buildFileIndex() noexcept {
}
}
void Project::indexFile(ox::CRStringView path) noexcept {
void Project::indexFile(ox::StringViewCR path) noexcept {
auto const [ext, err] = fileExt(path);
if (err) {
return;
@@ -114,7 +112,7 @@ void Project::indexFile(ox::CRStringView path) noexcept {
m_fileExtFileMap[ext].emplace_back(path);
}
ox::Error Project::writeBuff(ox::CRStringView path, ox::Buffer const&buff) noexcept {
ox::Error Project::writeBuff(ox::StringViewCR path, ox::BufferView const&buff) noexcept {
constexpr auto HdrSz = 40;
ox::Buffer outBuff;
outBuff.reserve(buff.size() + HdrSz);
@@ -135,11 +133,11 @@ ox::Error Project::writeBuff(ox::CRStringView path, ox::Buffer const&buff) noexc
return {};
}
ox::Result<ox::Buffer> Project::loadBuff(ox::CRStringView path) const noexcept {
ox::Result<ox::Buffer> Project::loadBuff(ox::StringViewCR path) const noexcept {
return m_fs.read(path);
}
ox::Error Project::lsProcDir(ox::Vector<ox::String> *paths, ox::CRStringView path) const noexcept {
ox::Error Project::lsProcDir(ox::Vector<ox::String> *paths, ox::StringViewCR path) const noexcept {
oxRequire(files, m_fs.ls(path));
for (auto const&name : files) {
auto fullPath = ox::sfmt("{}/{}", path, name);
@@ -158,7 +156,7 @@ ox::Error Project::lsProcDir(ox::Vector<ox::String> *paths, ox::CRStringView pat
return {};
}
ox::Result<ox::Vector<ox::String>> Project::listFiles(ox::CRStringView path) const noexcept {
ox::Result<ox::Vector<ox::String>> Project::listFiles(ox::StringViewCR path) const noexcept {
ox::Vector<ox::String> paths;
oxReturnError(lsProcDir(&paths, path));
return paths;

View File

@@ -30,7 +30,7 @@ class ClipboardObject: public BaseClipboardObject {
ox::String getClipboardText(Context &ctx) noexcept;
void setClipboardText(Context &ctx, ox::CRStringView text) noexcept;
void setClipboardText(Context &ctx, ox::StringViewCR text) noexcept;
void setClipboardObject(Context &ctx, ox::UPtr<BaseClipboardObject> &&obj) noexcept;

View File

@@ -26,7 +26,7 @@ void removeDrawer(Context &ctx, Drawer *cd) noexcept;
ox::Error initGfx(Context &ctx) noexcept;
void setWindowTitle(Context &ctx, ox::CRStringView title) noexcept;
void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept;
void focusWindow(Context &ctx) noexcept;

View File

@@ -16,7 +16,7 @@ namespace turbine {
using TimeMs = uint64_t;
ox::Result<ContextUPtr> init(ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView appName) noexcept;
ox::Result<ContextUPtr> init(ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept;
ox::Error run(Context &ctx) noexcept;

View File

@@ -12,7 +12,7 @@ ox::String getClipboardText(Context&) noexcept {
return {};
}
void setClipboardText(Context&, ox::CRStringView) noexcept {
void setClipboardText(Context&, ox::StringViewCR) noexcept {
}
}

View File

@@ -24,7 +24,7 @@ ox::Error initGfx(Context&) noexcept {
return {};
}
void setWindowTitle(Context&, ox::CRStringView) noexcept {
void setWindowTitle(Context&, ox::StringViewCR) noexcept {
}
int getScreenWidth(Context&) noexcept {

View File

@@ -57,7 +57,7 @@ static ox::Result<std::size_t> findPreloadSection() noexcept {
}
ox::Result<ContextUPtr> init(
ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView appName) noexcept {
ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept {
auto ctx = ox::make_unique<Context>();
oxReturnError(keel::init(ctx->keelCtx, std::move(fs), appName));
#ifdef OX_BARE_METAL

View File

@@ -16,7 +16,7 @@ ox::String getClipboardText(Context &ctx) noexcept {
return ox::String(glfwGetClipboardString(ctx.window));
}
void setClipboardText(Context &ctx, ox::CRStringView text) noexcept {
void setClipboardText(Context &ctx, ox::StringViewCR text) noexcept {
auto cstr = ox_malloca(text.bytes() + 1, char);
ox::strncpy(cstr.get(), text.data(), text.bytes());
glfwSetClipboardString(ctx.window, cstr.get());

View File

@@ -219,7 +219,7 @@ ox::Error initGfx(Context &ctx) noexcept {
return {};
}
void setWindowTitle(Context &ctx, ox::CRStringView title) noexcept {
void setWindowTitle(Context &ctx, ox::StringViewCR title) noexcept {
auto cstr = ox_malloca(title.bytes() + 1, char);
ox::strncpy(cstr.get(), title.data(), title.bytes());
glfwSetWindowTitle(ctx.window, cstr.get());

View File

@@ -41,7 +41,7 @@ static void draw(GLFWwindow *window, int, int) noexcept {
}
ox::Result<ContextUPtr> init(
ox::UPtr<ox::FileSystem> &&fs, ox::CRStringView appName) noexcept {
ox::UPtr<ox::FileSystem> &&fs, ox::StringViewCR appName) noexcept {
auto ctx = ox::make_unique<Context>();
oxReturnError(keel::init(ctx->keelCtx, std::move(fs), appName));
using namespace std::chrono;