[nostalgia] Add external palettes to tilesheet system
This commit is contained in:
@@ -56,28 +56,34 @@ namespace {
|
||||
return colors.size();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::vector<char> pngToGba(QString argInPath, int argTiles, int argBpp) {
|
||||
QImage src(argInPath);
|
||||
[[nodiscard]] std::unique_ptr<core::NostalgiaGraphic> imgToNg(QString argSrc, int argTiles, int argBpp) {
|
||||
constexpr auto TilePixels = 64;
|
||||
QImage src(argSrc);
|
||||
|
||||
if (src.isNull()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto Pixels = argTiles ? argTiles * TilePixels : src.width() * src.height();
|
||||
if (argTiles == 0) {
|
||||
argTiles = (src.width() * src.height()) / 64;
|
||||
argTiles = Pixels / 64;
|
||||
}
|
||||
const auto Colors = countColors(src, argTiles);
|
||||
if (argBpp != 4 && argBpp != 8) {
|
||||
argBpp = countColors(src, argTiles) > 16 ? 8 : 4;
|
||||
argBpp = Colors > 16 ? 8 : 4;
|
||||
}
|
||||
|
||||
QMap<QRgb, int> colors;
|
||||
const auto imgDataBuffSize = sizeof(core::GbaImageData) + 1 + argTiles * 64;
|
||||
std::vector<char> imgDataBuff(imgDataBuffSize);
|
||||
auto id = new (imgDataBuff.data()) core::GbaImageData;
|
||||
id->header.bpp = argBpp;
|
||||
id->header.tileCount = argTiles;
|
||||
int colorId = 0;
|
||||
auto ng = std::make_unique<core::NostalgiaGraphic>();
|
||||
ng->pal.resize(countColors(src, argTiles));
|
||||
if (argBpp == 4) {
|
||||
ng->tiles.resize(Pixels / 2);
|
||||
} else {
|
||||
ng->tiles.resize(Pixels);
|
||||
}
|
||||
ng->bpp = argBpp;
|
||||
|
||||
int colorIdx = 0;
|
||||
// copy pixels as color ids
|
||||
for (int x = 0; x < src.width(); x++) {
|
||||
for (int y = 0; y < src.height(); y++) {
|
||||
@@ -86,18 +92,18 @@ namespace {
|
||||
const auto c = src.pixel(x, y);
|
||||
// assign color a color id for the palette
|
||||
if (!colors.contains(c)) {
|
||||
colors[c] = colorId;
|
||||
colorId++;
|
||||
colors[c] = colorIdx;
|
||||
colorIdx++;
|
||||
}
|
||||
// set pixel color
|
||||
if (argBpp == 4) {
|
||||
if (destI % 2) { // is odd number pixel
|
||||
id->tiles[destI / 2] |= colors[c] << 4;
|
||||
ng->tiles[destI / 2] |= colors[c] << 4;
|
||||
} else {
|
||||
id->tiles[destI / 2] |= colors[c];
|
||||
ng->tiles[destI / 2] |= colors[c];
|
||||
}
|
||||
} else {
|
||||
id->tiles[destI] = colors[c];
|
||||
ng->tiles[destI] = colors[c];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,10 +112,10 @@ namespace {
|
||||
// store colors in palette with the corresponding color id
|
||||
for (auto key : colors.keys()) {
|
||||
auto colorId = colors[key];
|
||||
id->pal[colorId] = toGbaColor(key);
|
||||
ng->pal[colorId] = toGbaColor(key);
|
||||
}
|
||||
|
||||
return imgDataBuff;
|
||||
return ng;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -11,8 +11,24 @@
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
|
||||
#include <ox/mc/mc.hpp>
|
||||
|
||||
#include <nostalgia/core/gfx.hpp>
|
||||
|
||||
namespace nostalgia {
|
||||
|
||||
[[nodiscard]] std::vector<char> pngToGba(QString argInPath, int argTiles, int argBpp = -1);
|
||||
template<typename T>
|
||||
[[nodiscard]] ox::ValErr<std::vector<uint8_t>> toBuffer(T *data, std::size_t buffSize = ox::units::MB) {
|
||||
std::vector<uint8_t> buff(buffSize);
|
||||
std::size_t sz = 0;
|
||||
oxReturnError(ox::writeMC(buff.data(), buff.size(), data, &sz));
|
||||
if (sz > buffSize) {
|
||||
return OxError(1);
|
||||
}
|
||||
buff.resize(sz);
|
||||
return buff;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::unique_ptr<core::NostalgiaGraphic> imgToNg(QString argInPath, int argTiles, int argBpp = -1);
|
||||
|
||||
}
|
||||
|
@@ -27,12 +27,12 @@ namespace {
|
||||
* @return error
|
||||
* stub for now
|
||||
*/
|
||||
[[nodiscard]] ox::Error pathToInode(std::vector<char>*) {
|
||||
[[nodiscard]] ox::Error pathToInode(std::vector<uint8_t>*) {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
// stub for now
|
||||
[[nodiscard]] ox::Error toMetalClaw(std::vector<char>*) {
|
||||
[[nodiscard]] ox::Error toMetalClaw(std::vector<uint8_t>*) {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace {
|
||||
// do transforms
|
||||
if (endsWith(path, ".claw")) {
|
||||
// load file
|
||||
std::vector<char> buff(stat.size);
|
||||
std::vector<uint8_t> buff(stat.size);
|
||||
oxReturnError(dest->read(path.c_str(), buff.data(), buff.size()));
|
||||
// do transformations
|
||||
oxReturnError(pathToInode(&buff));
|
||||
@@ -63,8 +63,8 @@ namespace {
|
||||
});
|
||||
}
|
||||
|
||||
[[nodiscard]] ox::Error verifyFile(ox::FileSystem32 *fs, const std::string &path, const std::vector<char> &expected) noexcept {
|
||||
std::vector<char> buff(expected.size());
|
||||
[[nodiscard]] ox::Error verifyFile(ox::FileSystem32 *fs, const std::string &path, const std::vector<uint8_t> &expected) noexcept {
|
||||
std::vector<uint8_t> buff(expected.size());
|
||||
oxReturnError(fs->read(path.c_str(), buff.data(), buff.size()));
|
||||
return OxError(buff == expected ? 0 : 1);
|
||||
}
|
||||
@@ -81,15 +81,15 @@ namespace {
|
||||
oxReturnError(dest->mkdir(currentFile.c_str(), true));
|
||||
oxReturnError(copy(src, dest, currentFile + '/'));
|
||||
} else {
|
||||
std::vector<char> buff;
|
||||
std::vector<uint8_t> buff;
|
||||
// do transforms
|
||||
constexpr std::string_view PngExt = ".png";
|
||||
constexpr std::string_view GbagExt = ".ng";
|
||||
if (endsWith(currentFile, PngExt)) {
|
||||
const std::string OldExt = path.substr(path.find_last_of('.'));
|
||||
constexpr std::string_view NgExt = ".ng";
|
||||
if (OldExt != NgExt) {
|
||||
// load file from full path and transform
|
||||
const auto fullPath = src->basePath() + currentFile;
|
||||
buff = pngToGba(fullPath.c_str(), 0, 0);
|
||||
currentFile = currentFile.substr(0, currentFile.size() - PngExt.size()) + GbagExt.data();
|
||||
oxReturnError(toBuffer(imgToNg(fullPath.c_str(), 0, 0).get()).get(&buff));
|
||||
currentFile = currentFile.substr(0, currentFile.size() - OldExt.size()) + NgExt.data();
|
||||
if (!buff.size()) {
|
||||
return OxError(1);
|
||||
}
|
||||
|
Reference in New Issue
Block a user