[nostalgia/core] Add ability to chain converters
This commit is contained in:
parent
1ceb76ee6d
commit
713f5c4bce
@ -61,8 +61,8 @@ struct TileSheet {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet.SubSheet";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
ox::BString<32> name;
|
||||
std::size_t begin = 0;
|
||||
std::size_t size = 0;
|
||||
uint64_t begin = 0;
|
||||
uint64_t size = 0;
|
||||
int rows = 1;
|
||||
int columns = 1;
|
||||
ox::Vector<SubSheet> subsheets;
|
||||
|
@ -23,7 +23,7 @@ ox::Result<AssetRef<T>> readObj(Context *ctx, const ox::FileAddress &file, bool
|
||||
if (err != ox::Error_ClawTypeVersionMismatch && err != ox::Error_ClawTypeMismatch) {
|
||||
return err;
|
||||
}
|
||||
oxReturnError(convert(buff, T::TypeName, T::TypeVersion, &obj));
|
||||
oxReturnError(convert<T>(buff, &obj));
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
|
@ -30,9 +30,8 @@ struct NostalgiaPaletteToPaletteConverter: public Converter<NostalgiaPalette, Pa
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Src>
|
||||
struct ToCompactTileSheetConverter: public Converter<Src, CompactTileSheet> {
|
||||
ox::Error convert(Src *src, CompactTileSheet *dst) noexcept final {
|
||||
struct TileSheetToCompactTileSheetConverter: public Converter<TileSheet, CompactTileSheet> {
|
||||
ox::Error convert(TileSheet *src, CompactTileSheet *dst) noexcept final {
|
||||
dst->bpp = src->bpp;
|
||||
dst->defaultPalette = std::move(src->defaultPalette);
|
||||
dst->pixels = std::move(src->pixels);
|
||||
@ -42,11 +41,10 @@ struct ToCompactTileSheetConverter: public Converter<Src, CompactTileSheet> {
|
||||
|
||||
#ifndef OX_BARE_METAL
|
||||
static const auto converters = [] {
|
||||
ox::Vector<ox::UniquePtr<BaseConverter>, 4> converters;
|
||||
ox::Vector<ox::UniquePtr<BaseConverter>, 3> converters;
|
||||
converters.emplace_back(new NostalgiaGraphicToTileSheetConverter());
|
||||
converters.emplace_back(new NostalgiaPaletteToPaletteConverter());
|
||||
converters.emplace_back(new ToCompactTileSheetConverter<NostalgiaGraphic>());
|
||||
converters.emplace_back(new ToCompactTileSheetConverter<TileSheet>());
|
||||
converters.emplace_back(new TileSheetToCompactTileSheetConverter());
|
||||
return converters;
|
||||
}();
|
||||
|
||||
@ -59,11 +57,25 @@ static auto findConverter(const ox::String &srcTypeName, int srcTypeVersion, con
|
||||
return OxError(1, "Could not find converter");
|
||||
};
|
||||
|
||||
ox::Error convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, void *dstObj) noexcept {
|
||||
ox::Result<ox::Buffer> convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, ox::ClawFormat fmt) noexcept {
|
||||
oxRequire(hdr, ox::readClawHeader(srcBuffer));
|
||||
oxRequire(c, findConverter(hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion));
|
||||
return c->convertRaw(srcBuffer, dstObj);
|
||||
auto [c, err] = findConverter(hdr.typeName, hdr.typeVersion, dstTypeName, dstTypeVersion);
|
||||
if (!err) { // try to chain multiple converters
|
||||
return c->convertBuffToBuff(srcBuffer);
|
||||
}
|
||||
for (const auto &subConverter : converters) {
|
||||
if (!subConverter->dstMatches(dstTypeName, dstTypeVersion)) {
|
||||
continue;
|
||||
}
|
||||
const auto [intermediateBuff, chainErr] =
|
||||
convert(srcBuffer, subConverter->srcTypeName(), subConverter->srcTypeVersion(), fmt);
|
||||
if (!chainErr) {
|
||||
return subConverter->convertBuffToBuff(intermediateBuff, fmt);
|
||||
}
|
||||
}
|
||||
return OxError(1, "Could not convert between types");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -17,14 +17,42 @@ namespace nostalgia::core {
|
||||
struct BaseConverter {
|
||||
virtual ~BaseConverter() noexcept = default;
|
||||
|
||||
virtual ox::String srcTypeName() noexcept = 0;
|
||||
|
||||
virtual int srcTypeVersion() noexcept = 0;
|
||||
|
||||
virtual bool srcMatches(const ox::String &srcTypeName, int srcTypeVersion) noexcept = 0;
|
||||
|
||||
virtual bool dstMatches(const ox::String &dstTypeName, int dstTypeVersion) noexcept = 0;
|
||||
|
||||
virtual bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept = 0;
|
||||
|
||||
virtual ox::Error convertRaw(const ox::Buffer &pV1Buff, void *pV2) noexcept = 0;
|
||||
|
||||
virtual ox::Result<ox::Buffer> convertBuffToBuff(const ox::Buffer &srcBuff, ox::ClawFormat dstFmt = ox::ClawFormat::Metal) noexcept = 0;
|
||||
};
|
||||
|
||||
template<typename SrcType, typename DstType>
|
||||
struct Converter: public BaseConverter{
|
||||
bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept override {
|
||||
ox::String srcTypeName() noexcept final {
|
||||
return SrcType::TypeName;
|
||||
}
|
||||
|
||||
int srcTypeVersion() noexcept final {
|
||||
return SrcType::TypeVersion;
|
||||
}
|
||||
|
||||
bool srcMatches(const ox::String &srcTypeName, int srcTypeVersion) noexcept final {
|
||||
return srcTypeName == DstType::TypeName
|
||||
&& srcTypeVersion == DstType::TypeVersion;
|
||||
}
|
||||
|
||||
bool dstMatches(const ox::String &dstTypeName, int dstTypeVersion) noexcept final {
|
||||
return dstTypeName == DstType::TypeName
|
||||
&& dstTypeVersion == DstType::TypeVersion;
|
||||
}
|
||||
|
||||
bool matches(const ox::String &srcTypeName, int srcTypeVersion, const ox::String &dstTypeName, int dstTypeVersion) noexcept final {
|
||||
return srcTypeName == SrcType::TypeName
|
||||
&& dstTypeName == DstType::TypeName
|
||||
&& srcTypeVersion == SrcType::TypeVersion
|
||||
@ -40,26 +68,26 @@ struct Converter: public BaseConverter{
|
||||
auto dst = static_cast<DstType*>(pV2);
|
||||
return convert(&src, dst);
|
||||
}
|
||||
|
||||
ox::Result<ox::Buffer> convertBuffToBuff(const ox::Buffer &srcBuff, ox::ClawFormat dstFmt) noexcept final {
|
||||
DstType dst;
|
||||
oxReturnError(convertRaw(srcBuff, &dst));
|
||||
oxRequireM(out, ox::writeClaw(&dst, dstFmt));
|
||||
return out;
|
||||
}
|
||||
};
|
||||
|
||||
ox::Error convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, void *dstObj) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Error convert(const ox::Buffer &srcBuffer, T *dstObj) noexcept {
|
||||
return convert((srcBuffer, T::TypeName, T::TypeVersion, &dstObj));
|
||||
}
|
||||
ox::Result<ox::Buffer> convert(const ox::Buffer &srcBuffer, const ox::String &dstTypeName, int dstTypeVersion, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept;
|
||||
|
||||
template<typename T>
|
||||
ox::Result<ox::Buffer> convert(const ox::Buffer &srcBuffer, ox::ClawFormat fmt = ox::ClawFormat::Metal) noexcept {
|
||||
T dstObj;
|
||||
oxReturnError(convert(srcBuffer, T::TypeName, T::TypeVersion, &dstObj));
|
||||
return ox::writeClaw(&dstObj, fmt);
|
||||
return convert(srcBuffer, T::TypeName, T::TypeVersion, fmt);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ox::Error convert(ox::Buffer *buff) noexcept {
|
||||
return convert<T>(*buff).moveTo(buff);
|
||||
|
||||
ox::Error convert(const ox::Buffer &buff, T *outObj) noexcept {
|
||||
oxRequireM(outBuff, convert<T>(buff));
|
||||
return ox::readClaw<T>(outBuff).moveTo(outObj);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ static ox::Error doTransformations(ox::FileSystem *dest, const ox::String &fileP
|
||||
// load file
|
||||
oxRequireM(buff, dest->read(filePath.c_str()));
|
||||
if (filePath.endsWith(".ng")) {
|
||||
oxReturnError(core::convert<core::CompactTileSheet>(&buff));
|
||||
oxReturnError(core::convert<core::CompactTileSheet>(buff).moveTo(&buff));
|
||||
}
|
||||
// do transformations
|
||||
oxReturnError(pathToInode(buff).moveTo(&buff));
|
||||
|
Loading…
x
Reference in New Issue
Block a user