[nostalgia/core] Add ability to chain converters
This commit is contained in:
		@@ -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));
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user