Squashed 'deps/nostalgia/' changes from e7a66390..a0c81463
a0c81463 [nostalgia/core/studio] East const some function args d5b232f5 [olympic/studio] Fix array bounds issue c79fe3be [buildcore] Make CMake configure failure trigger failed return code 1df4e780 [olympic/studio] Add new project menu, make file creation open file ffbdb09c [olympic/turbine/glfw] Add shift key support b35a956e [olympic/studio] Cleanup unused expression d3847caa [olympic/studio] Make Project::writeObj only write descriptor if it does not already exist or if debug build ae066a91 [olympic/studio] Fix Project::writeObj to ensure parent directory of file exists 67543af8 [ox/oc] Remove some unnecessary code 6b774ec2 [ox/oc] Fix array writing to write all values 4b9758f4 [nostalgia/core] Move most TileSheet member functions out of class bf12b15f [nostalgia/sample_project] Update some tilesheets to version 4 format a7328eb5 [nostalgia/core/studio] Reduce indent for Subsheet editor b52124a0 [nostalgia/core/studio] Revert new subsheet index increment to happen after index assignment eae9972f [nostalgia/sample_project] Add missing type descriptors d83e3929 [nostalgia/core] Cleanup, revert CompactTileSheet version to 1 e2d0a784 [olympic/keel] Cleanup f0882142 [nostalgia/core/studio] Change TileSheets to back to MC 6a2954f8 [nostalgia/core] Remove id from TileSheetV3::Subsheet, add TileSheetV4 9c19655c [nostalgia/core] Fix build, add SubSheet ID to SubSheet Editor view 087c834b [nostalgia/core/studio] Fix Add SubSheet to increment idIt before using it 79bdbf2e [nostalgia/core] Add id to TileSheetV3::SubSheet model 2bdc3def [nostalgia/core/opengl] Implement flip X and flip Y for BG tiles git-subtree-dir: deps/nostalgia git-subtree-split: a0c8146396a9e9c0dc48a2564f4e9870a212ed59
This commit is contained in:
@@ -48,8 +48,8 @@ struct BgTile {
|
||||
static constexpr auto TypeVersion = 1;
|
||||
unsigned tileIdx = 0;
|
||||
unsigned palBank = 0;
|
||||
unsigned horizontalFlip = false;
|
||||
unsigned verticalFlip = false;
|
||||
unsigned flipX = false;
|
||||
unsigned flipY = false;
|
||||
};
|
||||
|
||||
oxModelBegin(BgTile)
|
||||
|
@@ -61,7 +61,7 @@ struct TileSheetV2 {
|
||||
|
||||
using SubSheetId = int32_t;
|
||||
|
||||
struct TileSheet {
|
||||
struct TileSheetV3 {
|
||||
using SubSheetIdx = ox::Vector<std::size_t, 4>;
|
||||
|
||||
struct SubSheet {
|
||||
@@ -73,119 +73,20 @@ struct TileSheet {
|
||||
int rows = 0;
|
||||
ox::Vector<SubSheet> subsheets;
|
||||
ox::Vector<uint8_t> pixels;
|
||||
|
||||
constexpr SubSheet() noexcept = default;
|
||||
constexpr SubSheet(SubSheet const&other) noexcept = default;
|
||||
SubSheet(SubSheet &&other) noexcept;
|
||||
SubSheet(
|
||||
inline SubSheet(
|
||||
SubSheetId pId,
|
||||
ox::CRStringView pName,
|
||||
int pColumns,
|
||||
int pRows,
|
||||
int bpp) noexcept;
|
||||
SubSheet(
|
||||
SubSheetId pId,
|
||||
ox::CRStringView pName,
|
||||
int pColumns,
|
||||
int pRows,
|
||||
ox::Vector<uint8_t> pPixels) noexcept;
|
||||
|
||||
constexpr SubSheet &operator=(const SubSheet &other) noexcept = default;
|
||||
|
||||
SubSheet &operator=(SubSheet &&other) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
std::size_t idx(ox::Point const&pt) const noexcept;
|
||||
|
||||
/**
|
||||
* Reads all pixels of this sheet or its children into the given pixel list
|
||||
* @param pixels
|
||||
*/
|
||||
void readPixelsTo(ox::Vector<uint8_t> *pPixels, int8_t pBpp) const noexcept;
|
||||
|
||||
/**
|
||||
* Reads all pixels of this sheet or its children into the given pixel list
|
||||
* @param pixels
|
||||
*/
|
||||
void readPixelsTo(ox::Vector<uint8_t> *pPixels) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t size() const noexcept {
|
||||
return static_cast<std::size_t>(columns) * static_cast<std::size_t>(rows);
|
||||
int bpp) noexcept:
|
||||
id(pId),
|
||||
name(pName),
|
||||
columns(pColumns),
|
||||
rows(pRows),
|
||||
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
std::size_t unusedPixels() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel4Bpp(std::size_t idx) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel8Bpp(std::size_t idx) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel(int8_t pBpp, std::size_t idx) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel4Bpp(const ox::Point &pt) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel8Bpp(const ox::Point &pt) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel(int8_t pBpp, const ox::Point &pt) const noexcept;
|
||||
|
||||
constexpr auto walkPixels(int8_t pBpp, auto callback) const noexcept {
|
||||
if (pBpp == 4) {
|
||||
const auto pixelCnt = ox::min<std::size_t>(static_cast<std::size_t>(columns * rows * PixelsPerTile) / 2,
|
||||
pixels.size());
|
||||
//oxAssert(pixels.size() == pixelCnt, "Pixel count does not match rows and columns");
|
||||
for (std::size_t i = 0; i < pixelCnt; ++i) {
|
||||
const auto colorIdx1 = static_cast<uint8_t>(pixels[i] & 0xF);
|
||||
const auto colorIdx2 = static_cast<uint8_t>(pixels[i] >> 4);
|
||||
callback(i * 2 + 0, colorIdx1);
|
||||
callback(i * 2 + 1, colorIdx2);
|
||||
}
|
||||
} else {
|
||||
const auto pixelCnt = ox::min<std::size_t>(
|
||||
static_cast<std::size_t>(columns * rows * PixelsPerTile),
|
||||
pixels.size());
|
||||
for (std::size_t i = 0; i < pixelCnt; ++i) {
|
||||
const auto p = pixels[i];
|
||||
callback(i, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setPixel(int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept;
|
||||
|
||||
void setPixel(int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept;
|
||||
|
||||
ox::Error setPixelCount(int8_t pBpp, std::size_t cnt) noexcept;
|
||||
|
||||
/**
|
||||
* Gets a count of the pixels in this sheet, and not that of its children.
|
||||
* @param pBpp bits per pixel, need for knowing how to count the pixels
|
||||
* @return a count of the pixels in this sheet
|
||||
*/
|
||||
[[nodiscard]]
|
||||
unsigned pixelCnt(int8_t pBpp) const noexcept;
|
||||
|
||||
/**
|
||||
* Gets the offset in tiles of the desired subsheet.
|
||||
*/
|
||||
ox::Result<unsigned> getTileOffset(
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
int8_t pBpp,
|
||||
std::size_t pIt = 0,
|
||||
unsigned pCurrentTotal = 0) const noexcept;
|
||||
|
||||
ox::Result<SubSheetId> getIdFor(
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
std::size_t pIt = 0) const noexcept;
|
||||
|
||||
ox::Result<ox::StringView> getNameFor(SubSheetId pId) const noexcept;
|
||||
|
||||
};
|
||||
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet";
|
||||
@@ -195,86 +96,185 @@ struct TileSheet {
|
||||
ox::FileAddress defaultPalette;
|
||||
SubSheet subsheet{0, "Root", 1, 1, bpp};
|
||||
|
||||
};
|
||||
|
||||
struct TileSheet {
|
||||
using SubSheetIdx = ox::Vector<std::size_t, 4>;
|
||||
|
||||
struct SubSheet {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet.SubSheet";
|
||||
static constexpr auto TypeVersion = 4;
|
||||
SubSheetId id = 0;
|
||||
ox::String name;
|
||||
int columns = 0;
|
||||
int rows = 0;
|
||||
ox::Vector<SubSheet> subsheets;
|
||||
ox::Vector<uint8_t> pixels;
|
||||
|
||||
constexpr SubSheet() noexcept = default;
|
||||
inline SubSheet(
|
||||
SubSheetId pId,
|
||||
ox::CRStringView pName,
|
||||
int pColumns,
|
||||
int pRows,
|
||||
int bpp) noexcept:
|
||||
id(pId),
|
||||
name(pName),
|
||||
columns(pColumns),
|
||||
rows(pRows),
|
||||
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
|
||||
}
|
||||
inline SubSheet(
|
||||
SubSheetId pId,
|
||||
ox::CRStringView pName,
|
||||
int pColumns,
|
||||
int pRows,
|
||||
ox::Vector<uint8_t> pPixels) noexcept:
|
||||
id(pId),
|
||||
name(pName),
|
||||
columns(pColumns),
|
||||
rows(pRows),
|
||||
pixels(std::move(pPixels)) {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t size() const noexcept {
|
||||
return static_cast<std::size_t>(columns) * static_cast<std::size_t>(rows);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.TileSheet";
|
||||
static constexpr auto TypeVersion = 4;
|
||||
int8_t bpp = 4;
|
||||
SubSheetId idIt = 0;
|
||||
ox::FileAddress defaultPalette;
|
||||
SubSheet subsheet{0, "Root", 1, 1, bpp};
|
||||
|
||||
constexpr TileSheet() noexcept = default;
|
||||
TileSheet(TileSheet const&other) noexcept = default;
|
||||
inline TileSheet(TileSheet &&other) noexcept:
|
||||
bpp(other.bpp),
|
||||
idIt(other.idIt),
|
||||
defaultPalette(std::move(other.defaultPalette)),
|
||||
subsheet(std::move(other.subsheet)) {
|
||||
}
|
||||
|
||||
TileSheet &operator=(TileSheet const&other) noexcept;
|
||||
|
||||
TileSheet &operator=(TileSheet &&other) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
SubSheetIdx validateSubSheetIdx(
|
||||
SubSheetIdx const&pIdx,
|
||||
std::size_t pIdxIt,
|
||||
const SubSheet *pSubsheet) noexcept;
|
||||
|
||||
/**
|
||||
* validateSubSheetIdx takes a SubSheetIdx and moves the index to the
|
||||
* preceding or parent sheet if the current corresponding sheet does
|
||||
* not exist.
|
||||
* @param idx SubSheetIdx to validate and correct
|
||||
* @return a valid version of idx
|
||||
*/
|
||||
[[nodiscard]]
|
||||
SubSheetIdx validateSubSheetIdx(const SubSheetIdx &idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static SubSheet const&getSubSheet(
|
||||
SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
const SubSheet *pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static SubSheet &getSubSheet(
|
||||
SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
SubSheet *pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
const SubSheet &getSubSheet(SubSheetIdx const&idx) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
SubSheet &getSubSheet(SubSheetIdx const&idx) noexcept;
|
||||
|
||||
ox::Error addSubSheet(SubSheetIdx const&idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
static ox::Error rmSubSheet(
|
||||
SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
SubSheet *pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Error rmSubSheet(SubSheetIdx const&idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel4Bpp(
|
||||
ox::Point const&pt,
|
||||
SubSheetIdx const&subsheetIdx) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel8Bpp(
|
||||
ox::Point const&pt,
|
||||
SubSheetIdx const&subsheetIdx) const noexcept;
|
||||
|
||||
ox::Result<SubSheetId> getIdFor(ox::CRStringView path) const noexcept;
|
||||
|
||||
ox::Result<unsigned> getTileOffset(ox::CRStringView pNamePath) const noexcept;
|
||||
|
||||
ox::Result<ox::StringView> getNameFor(SubSheetId pId) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Vector<uint8_t> pixels() const noexcept;
|
||||
|
||||
};
|
||||
|
||||
using TileSheetV3 = TileSheet;
|
||||
[[nodiscard]]
|
||||
std::size_t idx(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, std::size_t idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, ox::Point const&pt) noexcept;
|
||||
|
||||
constexpr void walkPixels(TileSheet::SubSheet const&ss, int8_t pBpp, auto callback) noexcept {
|
||||
if (pBpp == 4) {
|
||||
const auto pixelCnt = ox::min<std::size_t>(
|
||||
static_cast<std::size_t>(ss.columns * ss.rows * PixelsPerTile) / 2,
|
||||
ss.pixels.size());
|
||||
//oxAssert(pixels.size() == pixelCnt, "Pixel count does not match rows and columns");
|
||||
for (std::size_t i = 0; i < pixelCnt; ++i) {
|
||||
const auto colorIdx1 = static_cast<uint8_t>(ss.pixels[i] & 0xF);
|
||||
const auto colorIdx2 = static_cast<uint8_t>(ss.pixels[i] >> 4);
|
||||
callback(i * 2 + 0, colorIdx1);
|
||||
callback(i * 2 + 1, colorIdx2);
|
||||
}
|
||||
} else {
|
||||
const auto pixelCnt = ox::min<std::size_t>(
|
||||
static_cast<std::size_t>(ss.columns * ss.rows * PixelsPerTile),
|
||||
ss.pixels.size());
|
||||
for (std::size_t i = 0; i < pixelCnt; ++i) {
|
||||
const auto p = ss.pixels[i];
|
||||
callback(i, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept;
|
||||
|
||||
void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept;
|
||||
|
||||
ox::Error setPixelCount(TileSheet::SubSheet &ss, int8_t pBpp, std::size_t cnt) noexcept;
|
||||
|
||||
/**
|
||||
* Gets a count of the pixels in this sheet, and not that of its children.
|
||||
* @param pBpp bits per pixel, need for knowing how to count the pixels
|
||||
* @return a count of the pixels in this sheet
|
||||
*/
|
||||
[[nodiscard]]
|
||||
unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept;
|
||||
|
||||
/**
|
||||
* validateSubSheetIdx takes a SubSheetIdx and moves the index to the
|
||||
* preceding or parent sheet if the current corresponding sheet does
|
||||
* not exist.
|
||||
* @param idx SubSheetIdx to validate and correct
|
||||
* @return a valid version of idx
|
||||
*/
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheetIdx validateSubSheetIdx(TileSheet const&ts, TileSheet::SubSheetIdx const&idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheet const&getSubSheet(
|
||||
TileSheet::SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
TileSheet::SubSheet const&pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheet &getSubSheet(
|
||||
TileSheet::SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
TileSheet::SubSheet &pSubsheet) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheet const&getSubSheet(TileSheet const&ts, TileSheet::SubSheetIdx const&idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheet &getSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept;
|
||||
|
||||
ox::Error addSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept;
|
||||
|
||||
ox::Error rmSubSheet(
|
||||
TileSheet &ts,
|
||||
TileSheet::SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
TileSheet::SubSheet &pSubsheet) noexcept;
|
||||
|
||||
ox::Error rmSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel4Bpp(
|
||||
TileSheet const&ts,
|
||||
ox::Point const&pt,
|
||||
TileSheet::SubSheetIdx const&subsheetIdx) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
uint8_t getPixel8Bpp(
|
||||
TileSheet const&ts,
|
||||
ox::Point const&pt,
|
||||
TileSheet::SubSheetIdx const&subsheetIdx) noexcept;
|
||||
|
||||
ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::CRStringView path) noexcept;
|
||||
|
||||
ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::CRStringView 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;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Vector<uint8_t> pixels(TileSheet &ts) noexcept;
|
||||
|
||||
using TileSheetV4 = TileSheet;
|
||||
|
||||
struct CompactTileSheet {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.core.CompactTileSheet";
|
||||
@@ -294,9 +294,9 @@ oxModelBegin(TileSheetV1)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheetV2::SubSheet)
|
||||
oxModelField(name);
|
||||
oxModelField(rows);
|
||||
oxModelField(columns);
|
||||
oxModelField(name)
|
||||
oxModelField(rows)
|
||||
oxModelField(columns)
|
||||
oxModelField(subsheets)
|
||||
oxModelField(pixels)
|
||||
oxModelEnd()
|
||||
@@ -308,9 +308,9 @@ oxModelBegin(TileSheetV2)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheetV3::SubSheet)
|
||||
oxModelField(name);
|
||||
oxModelField(rows);
|
||||
oxModelField(columns);
|
||||
oxModelField(name)
|
||||
oxModelField(rows)
|
||||
oxModelField(columns)
|
||||
oxModelField(subsheets)
|
||||
oxModelField(pixels)
|
||||
oxModelEnd()
|
||||
@@ -322,6 +322,22 @@ oxModelBegin(TileSheetV3)
|
||||
oxModelField(subsheet)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheetV4::SubSheet)
|
||||
oxModelField(id)
|
||||
oxModelField(name)
|
||||
oxModelField(rows)
|
||||
oxModelField(columns)
|
||||
oxModelField(subsheets)
|
||||
oxModelField(pixels)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(TileSheetV4)
|
||||
oxModelField(bpp)
|
||||
oxModelField(idIt)
|
||||
oxModelField(defaultPalette)
|
||||
oxModelField(subsheet)
|
||||
oxModelEnd()
|
||||
|
||||
oxModelBegin(CompactTileSheet)
|
||||
oxModelField(bpp)
|
||||
oxModelField(defaultPalette)
|
||||
|
@@ -289,8 +289,8 @@ void setBgTile(Context&, uint_t bgIdx, int column, int row, BgTile const&tile) n
|
||||
// see Tonc 9.3
|
||||
MEM_BG_MAP[bgIdx][tileIdx] =
|
||||
static_cast<uint16_t>(tile.tileIdx & 0b1'1111'1111) |
|
||||
static_cast<uint16_t>(tile.horizontalFlip << 0xa) |
|
||||
static_cast<uint16_t>(tile.verticalFlip << 0xb) |
|
||||
static_cast<uint16_t>(tile.flipX << 0xa) |
|
||||
static_cast<uint16_t>(tile.flipY << 0xb) |
|
||||
static_cast<uint16_t>(tile.palBank << 0xc);
|
||||
}
|
||||
|
||||
|
@@ -18,7 +18,8 @@ class KeelModule: public keel::Module {
|
||||
private:
|
||||
NostalgiaPaletteToPaletteConverter m_nostalgiaPaletteToPaletteConverter;
|
||||
TileSheetV1ToTileSheetV2Converter m_tileSheetV1ToTileSheetV2Converter;
|
||||
TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetConverter;
|
||||
TileSheetV2ToTileSheetV3Converter m_tileSheetV2ToTileSheetV3Converter;
|
||||
TileSheetV3ToTileSheetV4Converter m_tileSheetV3ToTileSheetV4Converter;
|
||||
TileSheetToCompactTileSheetConverter m_tileSheetToCompactTileSheetConverter;
|
||||
|
||||
public:
|
||||
@@ -32,18 +33,20 @@ class KeelModule: public keel::Module {
|
||||
return {
|
||||
keel::generateTypeDesc<TileSheetV1>,
|
||||
keel::generateTypeDesc<TileSheetV2>,
|
||||
keel::generateTypeDesc<TileSheet>,
|
||||
keel::generateTypeDesc<TileSheetV3>,
|
||||
keel::generateTypeDesc<TileSheetV4>,
|
||||
keel::generateTypeDesc<CompactTileSheet>,
|
||||
keel::generateTypeDesc<Palette>,
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Vector<const keel::BaseConverter*> converters() const noexcept final {
|
||||
ox::Vector<keel::BaseConverter const*> converters() const noexcept final {
|
||||
return {
|
||||
&m_nostalgiaPaletteToPaletteConverter,
|
||||
&m_tileSheetV1ToTileSheetV2Converter,
|
||||
&m_tileSheetV2ToTileSheetConverter,
|
||||
&m_tileSheetV2ToTileSheetV3Converter,
|
||||
&m_tileSheetV3ToTileSheetV4Converter,
|
||||
&m_tileSheetToCompactTileSheetConverter,
|
||||
};
|
||||
}
|
||||
@@ -54,11 +57,12 @@ class KeelModule: public keel::Module {
|
||||
// convert tilesheets to CompactTileSheets
|
||||
[](keel::Context &ctx, ox::Buffer &buff) -> ox::Error {
|
||||
oxRequire(hdr, keel::readAssetHeader(buff));
|
||||
const auto typeId = ox::buildTypeId(
|
||||
auto const typeId = ox::buildTypeId(
|
||||
hdr.clawHdr.typeName, hdr.clawHdr.typeVersion, hdr.clawHdr.typeParams);
|
||||
if (typeId == ox::buildTypeId<TileSheetV1>() ||
|
||||
typeId == ox::buildTypeId<TileSheetV2>() ||
|
||||
typeId == ox::buildTypeId<TileSheet>()) {
|
||||
typeId == ox::buildTypeId<TileSheetV2>() ||
|
||||
typeId == ox::buildTypeId<TileSheetV3>() ||
|
||||
typeId == ox::buildTypeId<TileSheetV4>()) {
|
||||
oxReturnError(keel::convertBuffToBuff<core::CompactTileSheet>(
|
||||
ctx, buff, ox::ClawFormat::Metal).moveTo(buff));
|
||||
}
|
||||
|
@@ -53,13 +53,41 @@ ox::Error TileSheetV2ToTileSheetV3Converter::convert(
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
void TileSheetV3ToTileSheetV4Converter::convertSubsheet(
|
||||
TileSheetV3::SubSheet &src,
|
||||
TileSheetV4::SubSheet &dst,
|
||||
SubSheetId &idIt) noexcept {
|
||||
dst.id = idIt;
|
||||
dst.name = std::move(src.name);
|
||||
dst.columns = src.columns;
|
||||
dst.rows = src.rows;
|
||||
dst.pixels = std::move(src.pixels);
|
||||
++idIt;
|
||||
dst.subsheets.resize(src.subsheets.size());
|
||||
for (auto i = 0u; i < src.subsheets.size(); ++i) {
|
||||
convertSubsheet(src.subsheets[i], dst.subsheets[i], idIt);
|
||||
}
|
||||
}
|
||||
|
||||
ox::Error TileSheetV3ToTileSheetV4Converter::convert(
|
||||
keel::Context&,
|
||||
TileSheetV3 &src,
|
||||
TileSheetV4 &dst) const noexcept {
|
||||
dst.bpp = src.bpp;
|
||||
dst.idIt = src.idIt;
|
||||
dst.defaultPalette = std::move(src.defaultPalette);
|
||||
convertSubsheet(src.subsheet, dst.subsheet, dst.idIt);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error TileSheetToCompactTileSheetConverter::convert(
|
||||
keel::Context&,
|
||||
TileSheet &src,
|
||||
CompactTileSheet &dst) const noexcept {
|
||||
dst.bpp = src.bpp;
|
||||
dst.defaultPalette = std::move(src.defaultPalette);
|
||||
dst.pixels = src.pixels();
|
||||
dst.pixels = pixels(src);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@@ -25,11 +25,19 @@ class TileSheetV1ToTileSheetV2Converter: public keel::Converter<TileSheetV1, Til
|
||||
};
|
||||
|
||||
class TileSheetV2ToTileSheetV3Converter: public keel::Converter<TileSheetV2, TileSheetV3> {
|
||||
static void convertSubsheet(
|
||||
TileSheetV2::SubSheet &src,
|
||||
TileSheetV3::SubSheet &dst,
|
||||
SubSheetId &idIt) noexcept;
|
||||
ox::Error convert(keel::Context&, TileSheetV2 &src, TileSheetV3 &dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetV3ToTileSheetV4Converter: public keel::Converter<TileSheetV3, TileSheetV4> {
|
||||
static void convertSubsheet(
|
||||
TileSheetV2::SubSheet &src,
|
||||
TileSheetV3::SubSheet &dst,
|
||||
TileSheetV3::SubSheet &src,
|
||||
TileSheetV4::SubSheet &dst,
|
||||
SubSheetId &idIt) noexcept;
|
||||
ox::Error convert(keel::Context&, TileSheetV2 &src, TileSheetV3 &dst) const noexcept final;
|
||||
ox::Error convert(keel::Context&, TileSheetV3 &src, TileSheetV4 &dst) const noexcept final;
|
||||
};
|
||||
|
||||
class TileSheetToCompactTileSheetConverter: public keel::Converter<TileSheet, CompactTileSheet> {
|
||||
|
@@ -152,6 +152,8 @@ static void setTileBufferObject(
|
||||
float textureTileIdx,
|
||||
float priority,
|
||||
float palOffset,
|
||||
bool flipX,
|
||||
bool flipY,
|
||||
float *vbo,
|
||||
GLuint *ebo) noexcept {
|
||||
// don't worry, this memcpy gets optimized to something much more ideal
|
||||
@@ -162,11 +164,15 @@ static void setTileBufferObject(
|
||||
x -= 1.0f;
|
||||
y += 1.0f - ymod;
|
||||
auto const prif = priority * PriorityScale;
|
||||
float const L = flipX ? 1 : 0;
|
||||
float const R = flipX ? 0 : 1;
|
||||
float const T = flipY ? 1 : 0;
|
||||
float const B = flipY ? 0 : 1;
|
||||
ox::Array<float, BgVertexVboLength> const vertices {
|
||||
x, y, prif, 0, 1, textureTileIdx, palOffset, // bottom left
|
||||
x + xmod, y, prif, 1, 1, textureTileIdx, palOffset, // bottom right
|
||||
x + xmod, y + ymod, prif, 1, 0, textureTileIdx, palOffset, // top right
|
||||
x, y + ymod, prif, 0, 0, textureTileIdx, palOffset, // top left
|
||||
x, y, prif, L, B, textureTileIdx, palOffset, // bottom left
|
||||
x + xmod, y, prif, R, B, textureTileIdx, palOffset, // bottom right
|
||||
x + xmod, y + ymod, prif, R, T, textureTileIdx, palOffset, // top right
|
||||
x, y + ymod, prif, L, T, textureTileIdx, palOffset, // top left
|
||||
};
|
||||
memcpy(vbo, vertices.data(), sizeof(vertices));
|
||||
ox::Array<GLuint, BgVertexEboLength> const elms {
|
||||
@@ -197,6 +203,8 @@ static void initBackgroundBufferObjects(glutils::BufferSet &bs) noexcept {
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
vbo,
|
||||
ebo);
|
||||
}
|
||||
@@ -612,6 +620,8 @@ void setBgTile(
|
||||
static_cast<float>(tile.tileIdx),
|
||||
bg.priority,
|
||||
static_cast<float>(tile.palBank * 16),
|
||||
tile.flipX,
|
||||
tile.flipY,
|
||||
vbo,
|
||||
ebo);
|
||||
cbb.updated = true;
|
||||
|
@@ -10,7 +10,7 @@ AddSubSheetCommand::AddSubSheetCommand(
|
||||
TileSheet &img,
|
||||
TileSheet::SubSheetIdx parentIdx) noexcept:
|
||||
m_img(img), m_parentIdx(std::move(parentIdx)) {
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
auto &parent = getSubSheet(m_img, m_parentIdx);
|
||||
if (!parent.subsheets.empty()) {
|
||||
auto idx = m_parentIdx;
|
||||
idx.emplace_back(parent.subsheets.size());
|
||||
@@ -25,7 +25,7 @@ AddSubSheetCommand::AddSubSheetCommand(
|
||||
}
|
||||
|
||||
void AddSubSheetCommand::redo() noexcept {
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
auto &parent = getSubSheet(m_img, m_parentIdx);
|
||||
if (m_addedSheets.size() < 2) {
|
||||
auto i = parent.subsheets.size();
|
||||
parent.subsheets.emplace_back(m_img.idIt++, ox::sfmt("Subsheet {}", i), 1, 1, m_img.bpp);
|
||||
@@ -38,7 +38,7 @@ void AddSubSheetCommand::redo() noexcept {
|
||||
}
|
||||
|
||||
void AddSubSheetCommand::undo() noexcept {
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
auto &parent = getSubSheet(m_img, m_parentIdx);
|
||||
if (parent.subsheets.size() == 2) {
|
||||
auto s = parent.subsheets[0];
|
||||
parent.rows = s.rows;
|
||||
@@ -47,7 +47,7 @@ void AddSubSheetCommand::undo() noexcept {
|
||||
parent.subsheets.clear();
|
||||
} else {
|
||||
for (auto idx = m_addedSheets.rbegin(); idx != m_addedSheets.rend(); ++idx) {
|
||||
oxLogError(m_img.rmSubSheet(*idx));
|
||||
oxLogError(rmSubSheet(m_img, *idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -31,27 +31,27 @@ CutPasteCommand::CutPasteCommand(
|
||||
m_commandId(commandId),
|
||||
m_img(img),
|
||||
m_subSheetIdx(std::move(subSheetIdx)) {
|
||||
const auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
const auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
|
||||
for (const auto &p : cb.pixels()) {
|
||||
const auto dstPt = p.pt + dstStart;
|
||||
if (dstPt.x <= dstEnd.x && dstPt.y <= dstEnd.y) {
|
||||
const auto idx = subsheet.idx(dstPt);
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), p.colorIdx, subsheet.getPixel(m_img.bpp, idx));
|
||||
const auto idx = core::idx(subsheet, dstPt);
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), p.colorIdx, getPixel(subsheet, m_img.bpp, idx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CutPasteCommand::redo() noexcept {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
|
||||
for (const auto &c : m_changes) {
|
||||
subsheet.setPixel(m_img.bpp, c.idx, static_cast<uint8_t>(c.newPalIdx));
|
||||
setPixel(subsheet, m_img.bpp, c.idx, static_cast<uint8_t>(c.newPalIdx));
|
||||
}
|
||||
}
|
||||
|
||||
void CutPasteCommand::undo() noexcept {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
|
||||
for (const auto &c : m_changes) {
|
||||
subsheet.setPixel(m_img.bpp, c.idx, static_cast<uint8_t>(c.oldPalIdx));
|
||||
setPixel(subsheet, m_img.bpp, c.idx, static_cast<uint8_t>(c.oldPalIdx));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ core::DeleteTilesCommand::DeleteTilesCommand(
|
||||
m_deletedPixels.resize(m_deleteSz);
|
||||
// copy pixels to be erased
|
||||
{
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &s = getSubSheet(m_img, m_idx);
|
||||
auto &p = s.pixels;
|
||||
auto dst = m_deletedPixels.data();
|
||||
auto src = p.data() + m_deletePos;
|
||||
@@ -29,7 +29,7 @@ core::DeleteTilesCommand::DeleteTilesCommand(
|
||||
}
|
||||
|
||||
void core::DeleteTilesCommand::redo() noexcept {
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &s = getSubSheet(m_img, m_idx);
|
||||
auto &p = s.pixels;
|
||||
auto srcPos = m_deletePos + m_deleteSz;
|
||||
const auto src = p.data() + srcPos;
|
||||
@@ -40,7 +40,7 @@ void core::DeleteTilesCommand::redo() noexcept {
|
||||
}
|
||||
|
||||
void DeleteTilesCommand::undo() noexcept {
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &s = getSubSheet(m_img, m_idx);
|
||||
auto &p = s.pixels;
|
||||
const auto src = p.data() + m_deletePos;
|
||||
const auto dst1 = p.data() + m_deletePos + m_deleteSz;
|
||||
|
@@ -14,8 +14,8 @@ DrawCommand::DrawCommand(
|
||||
m_img(img),
|
||||
m_subSheetIdx(std::move(subSheetIdx)),
|
||||
m_palIdx(palIdx) {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), subsheet.getPixel(m_img.bpp, idx));
|
||||
auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, m_img.bpp, idx));
|
||||
}
|
||||
|
||||
DrawCommand::DrawCommand(
|
||||
@@ -26,22 +26,22 @@ DrawCommand::DrawCommand(
|
||||
m_img(img),
|
||||
m_subSheetIdx(std::move(subSheetIdx)),
|
||||
m_palIdx(palIdx) {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
|
||||
for (const auto idx : idxList) {
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), subsheet.getPixel(m_img.bpp, idx));
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, m_img.bpp, idx));
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawCommand::append(std::size_t idx) noexcept {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
if (m_changes.back().value->idx != idx && subsheet.getPixel(m_img.bpp, idx) != m_palIdx) {
|
||||
auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
|
||||
if (m_changes.back().value->idx != idx && getPixel(subsheet, m_img.bpp, idx) != m_palIdx) {
|
||||
// duplicate entries are bad
|
||||
auto existing = ox::find_if(m_changes.cbegin(), m_changes.cend(), [idx](const auto &c) {
|
||||
return c.idx == idx;
|
||||
});
|
||||
if (existing == m_changes.cend()) {
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), subsheet.getPixel(m_img.bpp, idx));
|
||||
subsheet.setPixel(m_img.bpp, idx, static_cast<uint8_t>(m_palIdx));
|
||||
m_changes.emplace_back(static_cast<uint32_t>(idx), getPixel(subsheet, m_img.bpp, idx));
|
||||
setPixel(subsheet, m_img.bpp, idx, static_cast<uint8_t>(m_palIdx));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -57,16 +57,16 @@ bool DrawCommand::append(const ox::Vector<std::size_t> &idxList) noexcept {
|
||||
}
|
||||
|
||||
void DrawCommand::redo() noexcept {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
|
||||
for (const auto &c : m_changes) {
|
||||
subsheet.setPixel(m_img.bpp, c.idx, static_cast<uint8_t>(m_palIdx));
|
||||
setPixel(subsheet, m_img.bpp, c.idx, static_cast<uint8_t>(m_palIdx));
|
||||
}
|
||||
}
|
||||
|
||||
void DrawCommand::undo() noexcept {
|
||||
auto &subsheet = m_img.getSubSheet(m_subSheetIdx);
|
||||
auto &subsheet = getSubSheet(m_img, m_subSheetIdx);
|
||||
for (const auto &c : m_changes) {
|
||||
subsheet.setPixel(m_img.bpp, c.idx, static_cast<uint8_t>(c.oldPalIdx));
|
||||
setPixel(subsheet, m_img.bpp, c.idx, static_cast<uint8_t>(c.oldPalIdx));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -19,7 +19,7 @@ core::InsertTilesCommand::InsertTilesCommand(
|
||||
m_deletedPixels.resize(m_insertCnt);
|
||||
// copy pixels to be erased
|
||||
{
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &s = getSubSheet(m_img, m_idx);
|
||||
auto &p = s.pixels;
|
||||
auto dst = m_deletedPixels.data();
|
||||
auto src = p.data() + p.size() - m_insertCnt;
|
||||
@@ -29,7 +29,7 @@ core::InsertTilesCommand::InsertTilesCommand(
|
||||
}
|
||||
|
||||
void InsertTilesCommand::redo() noexcept {
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &s = getSubSheet(m_img, m_idx);
|
||||
auto &p = s.pixels;
|
||||
auto dstPos = m_insertPos + m_insertCnt;
|
||||
const auto dst = p.data() + dstPos;
|
||||
@@ -39,7 +39,7 @@ void InsertTilesCommand::redo() noexcept {
|
||||
}
|
||||
|
||||
void InsertTilesCommand::undo() noexcept {
|
||||
auto &s = m_img.getSubSheet(m_idx);
|
||||
auto &s = getSubSheet(m_img, m_idx);
|
||||
auto &p = s.pixels;
|
||||
const auto srcIdx = m_insertPos + m_insertCnt;
|
||||
const auto src = p.data() + srcIdx;
|
||||
|
@@ -11,17 +11,17 @@ core::RmSubSheetCommand::RmSubSheetCommand(TileSheet &img, TileSheet::SubSheetId
|
||||
m_idx(std::move(idx)),
|
||||
m_parentIdx(m_idx) {
|
||||
m_parentIdx.pop_back();
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
auto &parent = getSubSheet(m_img, m_parentIdx);
|
||||
m_sheet = parent.subsheets[*m_idx.back().value];
|
||||
}
|
||||
|
||||
void RmSubSheetCommand::redo() noexcept {
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
auto &parent = getSubSheet(m_img, m_parentIdx);
|
||||
oxLogError(parent.subsheets.erase(*m_idx.back().value).error);
|
||||
}
|
||||
|
||||
void RmSubSheetCommand::undo() noexcept {
|
||||
auto &parent = m_img.getSubSheet(m_parentIdx);
|
||||
auto &parent = getSubSheet(m_img, m_parentIdx);
|
||||
auto i = *m_idx.back().value;
|
||||
parent.subsheets.insert(i, m_sheet);
|
||||
}
|
||||
|
@@ -14,22 +14,22 @@ core::UpdateSubSheetCommand::UpdateSubSheetCommand(
|
||||
int rows) noexcept:
|
||||
m_img(img),
|
||||
m_idx(std::move(idx)),
|
||||
m_sheet(m_img.getSubSheet(m_idx)),
|
||||
m_sheet(getSubSheet(m_img, m_idx)),
|
||||
m_newName(std::move(name)),
|
||||
m_newCols(cols),
|
||||
m_newRows(rows) {
|
||||
}
|
||||
|
||||
void UpdateSubSheetCommand::redo() noexcept {
|
||||
auto &sheet = m_img.getSubSheet(m_idx);
|
||||
auto &sheet = getSubSheet(m_img, m_idx);
|
||||
sheet.name = m_newName;
|
||||
sheet.columns = m_newCols;
|
||||
sheet.rows = m_newRows;
|
||||
oxLogError(sheet.setPixelCount(m_img.bpp, static_cast<std::size_t>(PixelsPerTile * m_newCols * m_newRows)));
|
||||
oxLogError(setPixelCount(sheet, m_img.bpp, static_cast<std::size_t>(PixelsPerTile * m_newCols * m_newRows)));
|
||||
}
|
||||
|
||||
void UpdateSubSheetCommand::undo() noexcept {
|
||||
auto &sheet = m_img.getSubSheet(m_idx);
|
||||
auto &sheet = getSubSheet(m_img, m_idx);
|
||||
sheet = m_sheet;
|
||||
}
|
||||
|
||||
|
@@ -191,7 +191,7 @@ void TileSheetEditorImGui::draw(turbine::Context&) noexcept {
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("-", btnSize)) {
|
||||
const auto &activeSubsheetIdx = m_model.activeSubSheetIdx();
|
||||
if (activeSubsheetIdx.size() > 0) {
|
||||
if (!activeSubsheetIdx.empty()) {
|
||||
m_model.rmSubsheet(activeSubsheetIdx);
|
||||
}
|
||||
}
|
||||
@@ -205,12 +205,13 @@ void TileSheetEditorImGui::draw(turbine::Context&) noexcept {
|
||||
}
|
||||
TileSheet::SubSheetIdx path;
|
||||
static constexpr auto flags = ImGuiTableFlags_RowBg | ImGuiTableFlags_NoBordersInBody;
|
||||
if (ImGui::BeginTable("Subsheets", 3, flags)) {
|
||||
if (ImGui::BeginTable("Subsheets", 4, flags)) {
|
||||
ImGui::TableSetupColumn("Subsheet", ImGuiTableColumnFlags_NoHide);
|
||||
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 25);
|
||||
ImGui::TableSetupColumn("Columns", ImGuiTableColumnFlags_WidthFixed, 50);
|
||||
ImGui::TableSetupColumn("Rows", ImGuiTableColumnFlags_WidthFixed, 50);
|
||||
ImGui::TableHeadersRow();
|
||||
drawSubsheetSelector(&m_view.img().subsheet, &path);
|
||||
drawSubsheetSelector(m_view.img().subsheet, path);
|
||||
ImGui::EndTable();
|
||||
}
|
||||
}
|
||||
@@ -221,31 +222,34 @@ void TileSheetEditorImGui::draw(turbine::Context&) noexcept {
|
||||
m_exportMenu.draw();
|
||||
}
|
||||
|
||||
void TileSheetEditorImGui::drawSubsheetSelector(TileSheet::SubSheet *subsheet, TileSheet::SubSheetIdx *path) {
|
||||
void TileSheetEditorImGui::drawSubsheetSelector(TileSheet::SubSheet &subsheet, TileSheet::SubSheetIdx &path) {
|
||||
constexpr auto indentReduce = 14;
|
||||
ImGui::TableNextRow(0, 5);
|
||||
using Str = ox::BasicString<100>;
|
||||
auto pathStr = ox::join<Str>("##", *path).value;
|
||||
auto lbl = ox::sfmt<Str>("{}##{}", subsheet->name, pathStr);
|
||||
const auto rowSelected = *path == m_model.activeSubSheetIdx();
|
||||
auto pathStr = ox::join<Str>("##", path).value;
|
||||
auto lbl = ox::sfmt<Str>("{}##{}", subsheet.name, pathStr);
|
||||
const auto rowSelected = path == m_model.activeSubSheetIdx();
|
||||
const auto flags = ImGuiTreeNodeFlags_SpanFullWidth
|
||||
| ImGuiTreeNodeFlags_OpenOnArrow
|
||||
| ImGuiTreeNodeFlags_DefaultOpen
|
||||
| (subsheet->subsheets.empty() ? ImGuiTreeNodeFlags_Leaf : 0)
|
||||
| (subsheet.subsheets.empty() ? ImGuiTreeNodeFlags_Leaf : 0)
|
||||
| (rowSelected ? ImGuiTreeNodeFlags_Selected : 0);
|
||||
ImGui::TableNextColumn();
|
||||
const auto open = ImGui::TreeNodeEx(lbl.c_str(), flags);
|
||||
ImGui::SameLine();
|
||||
if (ImGui::IsItemClicked()) {
|
||||
m_model.setActiveSubsheet(*path);
|
||||
m_model.setActiveSubsheet(path);
|
||||
}
|
||||
if (ImGui::IsMouseDoubleClicked(0) && ImGui::IsItemHovered()) {
|
||||
showSubsheetEditor();
|
||||
}
|
||||
if (subsheet->subsheets.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", subsheet.id);
|
||||
if (subsheet.subsheets.empty()) {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", subsheet->columns);
|
||||
ImGui::Text("%d", subsheet.columns);
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%d", subsheet->rows);
|
||||
ImGui::Text("%d", subsheet.rows);
|
||||
} else {
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("--");
|
||||
@@ -253,12 +257,14 @@ void TileSheetEditorImGui::drawSubsheetSelector(TileSheet::SubSheet *subsheet, T
|
||||
ImGui::Text("--");
|
||||
}
|
||||
if (open) {
|
||||
for (auto i = 0ul; auto &child : subsheet->subsheets) {
|
||||
path->push_back(i);
|
||||
for (auto i = 0ul; auto &child : subsheet.subsheets) {
|
||||
path.push_back(i);
|
||||
ImGui::PushID(static_cast<int>(i));
|
||||
drawSubsheetSelector(&child, path);
|
||||
ImGui::Indent(-indentReduce);
|
||||
drawSubsheetSelector(child, path);
|
||||
ImGui::Indent(indentReduce);
|
||||
ImGui::PopID();
|
||||
path->pop_back();
|
||||
path.pop_back();
|
||||
++i;
|
||||
}
|
||||
ImGui::TreePop();
|
||||
|
@@ -83,7 +83,7 @@ class TileSheetEditorImGui: public studio::Editor {
|
||||
|
||||
void draw(turbine::Context&) noexcept override;
|
||||
|
||||
void drawSubsheetSelector(TileSheet::SubSheet*, TileSheet::SubSheetIdx *path);
|
||||
void drawSubsheetSelector(TileSheet::SubSheet&, TileSheet::SubSheetIdx &path);
|
||||
|
||||
[[nodiscard]]
|
||||
static ox::Vec2 clickPos(ImVec2 const&winPos, ox::Vec2 clickPos) noexcept;
|
||||
|
@@ -47,8 +47,8 @@ void TileSheetEditorModel::cut() {
|
||||
for (int y = m_selectionBounds.y; y <= m_selectionBounds.y2(); ++y) {
|
||||
for (int x = m_selectionBounds.x; x <= m_selectionBounds.x2(); ++x) {
|
||||
auto pt = ox::Point(x, y);
|
||||
const auto idx = s->idx(pt);
|
||||
const auto c = s->getPixel(m_img.bpp, idx);
|
||||
const auto idx = core::idx(*s, pt);
|
||||
const auto c = getPixel(*s, m_img.bpp, idx);
|
||||
pt.x -= m_selectionBounds.x;
|
||||
pt.y -= m_selectionBounds.y;
|
||||
cb->addPixel(pt, c);
|
||||
@@ -67,8 +67,8 @@ void TileSheetEditorModel::copy() {
|
||||
for (int x = m_selectionBounds.x; x <= m_selectionBounds.x2(); ++x) {
|
||||
auto pt = ox::Point(x, y);
|
||||
const auto s = activeSubSheet();
|
||||
const auto idx = s->idx(pt);
|
||||
const auto c = s->getPixel(m_img.bpp, idx);
|
||||
const auto idx = core::idx(*s, pt);
|
||||
const auto c = getPixel(*s, m_img.bpp, idx);
|
||||
pt.x -= m_selectionBounds.x;
|
||||
pt.y -= m_selectionBounds.y;
|
||||
cb->addPixel(pt, c);
|
||||
@@ -115,14 +115,14 @@ ox::Error TileSheetEditorModel::setPalette(ox::StringView path) noexcept {
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::drawCommand(ox::Point const&pt, std::size_t palIdx) noexcept {
|
||||
const auto &activeSubSheet = m_img.getSubSheet(m_activeSubsSheetIdx);
|
||||
const auto &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
|
||||
if (pt.x >= activeSubSheet.columns * TileWidth || pt.y >= activeSubSheet.rows * TileHeight) {
|
||||
return;
|
||||
}
|
||||
const auto idx = activeSubSheet.idx(pt);
|
||||
const auto idx = core::idx(activeSubSheet, pt);
|
||||
if (m_ongoingDrawCommand) {
|
||||
m_updated = m_updated || m_ongoingDrawCommand->append(idx);
|
||||
} else if (activeSubSheet.getPixel(m_img.bpp, idx) != palIdx) {
|
||||
} else if (getPixel(activeSubSheet, m_img.bpp, idx) != palIdx) {
|
||||
pushCommand(ox::make<DrawCommand>(m_img, m_activeSubsSheetIdx, idx, static_cast<int>(palIdx)));
|
||||
}
|
||||
}
|
||||
@@ -147,7 +147,7 @@ void TileSheetEditorModel::deleteTiles(TileSheet::SubSheetIdx const&idx, std::si
|
||||
pushCommand(ox::make<DeleteTilesCommand>(m_img, idx, tileIdx, tileCnt));
|
||||
}
|
||||
|
||||
ox::Error TileSheetEditorModel::updateSubsheet(TileSheet::SubSheetIdx const&idx, const ox::StringView &name, int cols, int rows) noexcept {
|
||||
ox::Error TileSheetEditorModel::updateSubsheet(TileSheet::SubSheetIdx const&idx, ox::StringView const&name, int cols, int rows) noexcept {
|
||||
pushCommand(ox::make<UpdateSubSheetCommand>(m_img, idx, ox::String(name), cols, rows));
|
||||
return {};
|
||||
}
|
||||
@@ -158,16 +158,16 @@ void TileSheetEditorModel::setActiveSubsheet(TileSheet::SubSheetIdx const&idx) n
|
||||
}
|
||||
|
||||
void TileSheetEditorModel::fill(ox::Point const&pt, int palIdx) noexcept {
|
||||
const auto &s = m_img.getSubSheet(m_activeSubsSheetIdx);
|
||||
const auto &s = getSubSheet(m_img, m_activeSubsSheetIdx);
|
||||
// build idx list
|
||||
ox::Array<bool, PixelsPerTile> updateMap = {};
|
||||
const auto oldColor = s.getPixel(m_img.bpp, pt);
|
||||
const auto oldColor = getPixel(s, m_img.bpp, pt);
|
||||
if (pt.x >= s.columns * TileWidth || pt.y >= s.rows * TileHeight) {
|
||||
return;
|
||||
}
|
||||
getFillPixels(updateMap.data(), pt, oldColor);
|
||||
ox::Vector<std::size_t> idxList;
|
||||
auto i = s.idx(pt) / PixelsPerTile * PixelsPerTile;
|
||||
auto i = core::idx(s, pt) / PixelsPerTile * PixelsPerTile;
|
||||
for (auto u : updateMap) {
|
||||
if (u) {
|
||||
idxList.emplace_back(i);
|
||||
@@ -177,7 +177,7 @@ void TileSheetEditorModel::fill(ox::Point const&pt, int palIdx) noexcept {
|
||||
// do updates to sheet
|
||||
if (m_ongoingDrawCommand) {
|
||||
m_updated = m_updated || m_ongoingDrawCommand->append(idxList);
|
||||
} else if (s.getPixel(m_img.bpp, pt) != palIdx) {
|
||||
} else if (getPixel(s, m_img.bpp, pt) != palIdx) {
|
||||
pushCommand(ox::make<DrawCommand>(m_img, m_activeSubsSheetIdx, idxList, palIdx));
|
||||
}
|
||||
}
|
||||
@@ -213,7 +213,7 @@ bool TileSheetEditorModel::updated() const noexcept {
|
||||
return m_updated;
|
||||
}
|
||||
|
||||
ox::Error TileSheetEditorModel::markUpdatedCmdId(const studio::UndoCommand *cmd) noexcept {
|
||||
ox::Error TileSheetEditorModel::markUpdatedCmdId(studio::UndoCommand const*cmd) noexcept {
|
||||
m_updated = true;
|
||||
const auto cmdId = cmd->commandId();
|
||||
if (static_cast<CommandId>(cmdId) == CommandId::PaletteChange) {
|
||||
@@ -221,7 +221,7 @@ ox::Error TileSheetEditorModel::markUpdatedCmdId(const studio::UndoCommand *cmd)
|
||||
paletteChanged.emit();
|
||||
}
|
||||
auto tsCmd = dynamic_cast<const TileSheetCommand*>(cmd);
|
||||
auto idx = m_img.validateSubSheetIdx(tsCmd->subsheetIdx());
|
||||
auto idx = validateSubSheetIdx(m_img, tsCmd->subsheetIdx());
|
||||
if (idx != m_activeSubsSheetIdx) {
|
||||
setActiveSubsheet(idx);
|
||||
}
|
||||
@@ -239,7 +239,7 @@ void TileSheetEditorModel::ackUpdate() noexcept {
|
||||
|
||||
ox::Error TileSheetEditorModel::saveFile() noexcept {
|
||||
const auto sctx = applicationData<studio::StudioContext>(m_ctx);
|
||||
return sctx->project->writeObj(m_path, m_img);
|
||||
return sctx->project->writeObj(m_path, m_img, ox::ClawFormat::Metal);
|
||||
}
|
||||
|
||||
bool TileSheetEditorModel::pixelSelected(std::size_t idx) const noexcept {
|
||||
@@ -267,16 +267,16 @@ void TileSheetEditorModel::getFillPixels(bool *pixels, ox::Point const&pt, int o
|
||||
const auto tile = tileIdx(pt);
|
||||
// mark pixels to update
|
||||
pixels[idx % PixelsPerTile] = true;
|
||||
if (!pixels[leftIdx % PixelsPerTile] && tile == tileIdx(leftPt) && activeSubSheet.getPixel(m_img.bpp, leftIdx) == oldColor) {
|
||||
if (!pixels[leftIdx % PixelsPerTile] && tile == tileIdx(leftPt) && getPixel(activeSubSheet, m_img.bpp, leftIdx) == oldColor) {
|
||||
getFillPixels(pixels, leftPt, oldColor);
|
||||
}
|
||||
if (!pixels[rightIdx % PixelsPerTile] && tile == tileIdx(rightPt) && activeSubSheet.getPixel(m_img.bpp, rightIdx) == oldColor) {
|
||||
if (!pixels[rightIdx % PixelsPerTile] && tile == tileIdx(rightPt) && getPixel(activeSubSheet, m_img.bpp, rightIdx) == oldColor) {
|
||||
getFillPixels(pixels, rightPt, oldColor);
|
||||
}
|
||||
if (!pixels[topIdx % PixelsPerTile] && tile == tileIdx(topPt) && activeSubSheet.getPixel(m_img.bpp, topIdx) == oldColor) {
|
||||
if (!pixels[topIdx % PixelsPerTile] && tile == tileIdx(topPt) && getPixel(activeSubSheet, m_img.bpp, topIdx) == oldColor) {
|
||||
getFillPixels(pixels, topPt, oldColor);
|
||||
}
|
||||
if (!pixels[bottomIdx % PixelsPerTile] && tile == tileIdx(bottomPt) && activeSubSheet.getPixel(m_img.bpp, bottomIdx) == oldColor) {
|
||||
if (!pixels[bottomIdx % PixelsPerTile] && tile == tileIdx(bottomPt) && getPixel(activeSubSheet, m_img.bpp, bottomIdx) == oldColor) {
|
||||
getFillPixels(pixels, bottomPt, oldColor);
|
||||
}
|
||||
}
|
||||
|
@@ -61,31 +61,31 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
|
||||
ox::Error setPalette(ox::StringView path) noexcept;
|
||||
|
||||
void drawCommand(const ox::Point &pt, std::size_t palIdx) noexcept;
|
||||
void drawCommand(ox::Point const&pt, std::size_t palIdx) noexcept;
|
||||
|
||||
void endDrawCommand() noexcept;
|
||||
|
||||
void addSubsheet(const TileSheet::SubSheetIdx &parentIdx) noexcept;
|
||||
void addSubsheet(TileSheet::SubSheetIdx const&parentIdx) noexcept;
|
||||
|
||||
void rmSubsheet(const TileSheet::SubSheetIdx &idx) noexcept;
|
||||
void rmSubsheet(TileSheet::SubSheetIdx const&idx) noexcept;
|
||||
|
||||
void insertTiles(const TileSheet::SubSheetIdx &idx, std::size_t tileIdx, std::size_t tileCnt) noexcept;
|
||||
void insertTiles(TileSheet::SubSheetIdx const&idx, std::size_t tileIdx, std::size_t tileCnt) noexcept;
|
||||
|
||||
void deleteTiles(const TileSheet::SubSheetIdx &idx, std::size_t tileIdx, std::size_t tileCnt) noexcept;
|
||||
void deleteTiles(TileSheet::SubSheetIdx const&idx, std::size_t tileIdx, std::size_t tileCnt) noexcept;
|
||||
|
||||
ox::Error updateSubsheet(const TileSheet::SubSheetIdx &idx, const ox::StringView &name, int cols, int rows) noexcept;
|
||||
ox::Error updateSubsheet(TileSheet::SubSheetIdx const&idx, ox::StringView const&name, int cols, int rows) noexcept;
|
||||
|
||||
void setActiveSubsheet(const TileSheet::SubSheetIdx&) noexcept;
|
||||
void setActiveSubsheet(TileSheet::SubSheetIdx const&) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
const TileSheet::SubSheet *activeSubSheet() const noexcept {
|
||||
auto &activeSubSheet = m_img.getSubSheet(m_activeSubsSheetIdx);
|
||||
auto &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
|
||||
return &activeSubSheet;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
TileSheet::SubSheet *activeSubSheet() noexcept {
|
||||
auto &activeSubSheet = m_img.getSubSheet(m_activeSubsSheetIdx);
|
||||
auto &activeSubSheet = getSubSheet(m_img, m_activeSubsSheetIdx);
|
||||
return &activeSubSheet;
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
[[nodiscard]]
|
||||
bool updated() const noexcept;
|
||||
|
||||
ox::Error markUpdatedCmdId(const studio::UndoCommand *cmd) noexcept;
|
||||
ox::Error markUpdatedCmdId(studio::UndoCommand const*cmd) noexcept;
|
||||
|
||||
ox::Error markUpdated() noexcept;
|
||||
|
||||
@@ -118,10 +118,9 @@ class TileSheetEditorModel: public ox::SignalHandler {
|
||||
|
||||
bool pixelSelected(std::size_t idx) const noexcept;
|
||||
|
||||
protected:
|
||||
private:
|
||||
void getFillPixels(bool *pixels, ox::Point const&pt, int oldColor) const noexcept;
|
||||
|
||||
private:
|
||||
void pushCommand(studio::UndoCommand *cmd) noexcept;
|
||||
|
||||
};
|
||||
|
@@ -13,7 +13,7 @@ namespace nostalgia::core {
|
||||
|
||||
TileSheetEditorView::TileSheetEditorView(turbine::Context &ctx, ox::StringView path, studio::UndoStack &undoStack):
|
||||
m_model(ctx, path, undoStack),
|
||||
m_pixelsDrawer(&m_model) {
|
||||
m_pixelsDrawer(m_model) {
|
||||
// build shaders
|
||||
oxThrowError(m_pixelsDrawer.buildShader());
|
||||
oxThrowError(m_pixelGridDrawer.buildShader());
|
||||
|
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
TileSheetPixels::TileSheetPixels(TileSheetEditorModel *model) noexcept: m_model(model) {
|
||||
TileSheetPixels::TileSheetPixels(TileSheetEditorModel &model) noexcept: m_model(model) {
|
||||
}
|
||||
|
||||
void TileSheetPixels::setPixelSizeMod(float sm) noexcept {
|
||||
@@ -94,15 +94,15 @@ void TileSheetPixels::setPixelBufferObject(
|
||||
|
||||
void TileSheetPixels::setBufferObjects(ox::Vec2 const&paneSize) noexcept {
|
||||
// set buffer lengths
|
||||
const auto subSheet = m_model->activeSubSheet();
|
||||
const auto pal = m_model->pal();
|
||||
const auto subSheet = m_model.activeSubSheet();
|
||||
const auto pal = m_model.pal();
|
||||
const auto width = subSheet->columns * TileWidth;
|
||||
const auto height = subSheet->rows * TileHeight;
|
||||
const auto pixels = static_cast<unsigned>(width * height);
|
||||
m_bufferSet.vertices.resize(pixels * VertexVboLength);
|
||||
m_bufferSet.elements.resize(pixels * VertexEboLength);
|
||||
// set pixels
|
||||
subSheet->walkPixels(m_model->img().bpp, [&](std::size_t i, uint8_t p) {
|
||||
walkPixels(*subSheet, m_model.img().bpp, [&](std::size_t i, uint8_t p) {
|
||||
auto color = pal->color(p);
|
||||
const auto pt = idxToPt(static_cast<int>(i), subSheet->columns);
|
||||
const auto fx = static_cast<float>(pt.x);
|
||||
@@ -115,7 +115,7 @@ void TileSheetPixels::setBufferObjects(ox::Vec2 const&paneSize) noexcept {
|
||||
if (i * VertexEboLength + VertexEboLength > m_bufferSet.elements.size()) {
|
||||
return;
|
||||
}
|
||||
if (m_model->pixelSelected(i)) {
|
||||
if (m_model.pixelSelected(i)) {
|
||||
const auto r = red16(color) / 2;
|
||||
const auto g = (green16(color) + 20) / 2;
|
||||
const auto b = (blue16(color) + 31) / 2;
|
||||
|
@@ -43,10 +43,10 @@ class TileSheetPixels {
|
||||
float m_pixelSizeMod = 1;
|
||||
glutils::GLProgram m_shader;
|
||||
glutils::BufferSet m_bufferSet;
|
||||
const class TileSheetEditorModel *m_model = nullptr;
|
||||
const class TileSheetEditorModel &m_model;
|
||||
|
||||
public:
|
||||
explicit TileSheetPixels(class TileSheetEditorModel *model) noexcept;
|
||||
explicit TileSheetPixels(class TileSheetEditorModel &model) noexcept;
|
||||
|
||||
void setPixelSizeMod(float sm) noexcept;
|
||||
|
||||
|
@@ -10,133 +10,47 @@
|
||||
|
||||
namespace nostalgia::core {
|
||||
|
||||
TileSheet::SubSheet::SubSheet(SubSheet &&other) noexcept:
|
||||
id (other.id),
|
||||
name (std::move(other.name)),
|
||||
columns (other.columns),
|
||||
rows (other.rows),
|
||||
subsheets(std::move(other.subsheets)),
|
||||
pixels (std::move(other.pixels)) {
|
||||
other.name = "";
|
||||
other.columns = {};
|
||||
other.rows = {};
|
||||
std::size_t idx(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept {
|
||||
return ptToIdx(pt, ss.columns);
|
||||
}
|
||||
|
||||
TileSheet::SubSheet::SubSheet(
|
||||
SubSheetId pId,
|
||||
ox::CRStringView pName,
|
||||
int pColumns,
|
||||
int pRows,
|
||||
int bpp) noexcept:
|
||||
id(pId),
|
||||
name(pName),
|
||||
columns(pColumns),
|
||||
rows(pRows),
|
||||
pixels(static_cast<std::size_t>(columns * rows * PixelsPerTile) / (bpp == 4 ? 2u : 1u)) {
|
||||
}
|
||||
|
||||
TileSheet::SubSheet::SubSheet(
|
||||
SubSheetId pId,
|
||||
ox::CRStringView pName,
|
||||
int pColumns,
|
||||
int pRows,
|
||||
ox::Vector<uint8_t> pPixels) noexcept:
|
||||
id(pId),
|
||||
name(pName),
|
||||
columns(pColumns),
|
||||
rows(pRows),
|
||||
pixels(std::move(pPixels)) {
|
||||
}
|
||||
|
||||
TileSheet::SubSheet &TileSheet::SubSheet::operator=(TileSheet::SubSheet &&other) noexcept {
|
||||
name = std::move(other.name);
|
||||
columns = other.columns;
|
||||
rows = other.rows;
|
||||
subsheets = std::move(other.subsheets);
|
||||
pixels = std::move(other.pixels);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::size_t TileSheet::SubSheet::idx(ox::Point const&pt) const noexcept {
|
||||
return ptToIdx(pt, columns);
|
||||
}
|
||||
|
||||
void TileSheet::SubSheet::readPixelsTo(ox::Vector<uint8_t> *pPixels, int8_t pBpp) const noexcept {
|
||||
if (!subsheets.empty()) {
|
||||
for (auto &s: subsheets) {
|
||||
s.readPixelsTo(pPixels);
|
||||
}
|
||||
} else {
|
||||
if (pBpp == 4) {
|
||||
for (auto p: this->pixels) {
|
||||
pPixels->emplace_back(static_cast<uint8_t>(p & 0b1111));
|
||||
pPixels->emplace_back(static_cast<uint8_t>(p >> 4));
|
||||
}
|
||||
} else {
|
||||
for (auto p: this->pixels) {
|
||||
pPixels->emplace_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TileSheet::SubSheet::readPixelsTo(ox::Vector<uint8_t> *pPixels) const noexcept {
|
||||
if (!subsheets.empty()) {
|
||||
for (auto &s: subsheets) {
|
||||
s.readPixelsTo(pPixels);
|
||||
}
|
||||
} else {
|
||||
for (auto p : this->pixels) {
|
||||
pPixels->emplace_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::size_t TileSheet::SubSheet::unusedPixels() const noexcept {
|
||||
std::size_t childrenSize = 0;
|
||||
for (auto &c : subsheets) {
|
||||
childrenSize += c.size();
|
||||
}
|
||||
return size() - childrenSize;
|
||||
}
|
||||
|
||||
uint8_t TileSheet::SubSheet::getPixel4Bpp(std::size_t idx) const noexcept {
|
||||
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept {
|
||||
if (idx & 1) {
|
||||
return this->pixels[idx / 2] >> 4;
|
||||
return ss.pixels[idx / 2] >> 4;
|
||||
} else {
|
||||
return this->pixels[idx / 2] & 0b0000'1111;
|
||||
return ss.pixels[idx / 2] & 0b0000'1111;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t TileSheet::SubSheet::getPixel8Bpp(std::size_t idx) const noexcept {
|
||||
return this->pixels[idx];
|
||||
uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, std::size_t idx) noexcept {
|
||||
return ss.pixels[idx];
|
||||
}
|
||||
|
||||
uint8_t TileSheet::SubSheet::getPixel(int8_t pBpp, std::size_t idx) const noexcept {
|
||||
uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, std::size_t idx) noexcept {
|
||||
if (pBpp == 4) {
|
||||
return getPixel4Bpp(idx);
|
||||
return getPixel4Bpp(ss, idx);
|
||||
} else {
|
||||
return getPixel8Bpp(idx);
|
||||
return getPixel8Bpp(ss, idx);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t TileSheet::SubSheet::getPixel4Bpp(ox::Point const&pt) const noexcept {
|
||||
const auto idx = ptToIdx(pt, columns);
|
||||
return getPixel4Bpp(idx);
|
||||
uint8_t getPixel4Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept {
|
||||
const auto idx = ptToIdx(pt, ss.columns);
|
||||
return getPixel4Bpp(ss, idx);
|
||||
}
|
||||
|
||||
uint8_t TileSheet::SubSheet::getPixel8Bpp(ox::Point const&pt) const noexcept {
|
||||
const auto idx = ptToIdx(pt, columns);
|
||||
return getPixel8Bpp(idx);
|
||||
uint8_t getPixel8Bpp(TileSheet::SubSheet const&ss, ox::Point const&pt) noexcept {
|
||||
const auto idx = ptToIdx(pt, ss.columns);
|
||||
return getPixel8Bpp(ss, idx);
|
||||
}
|
||||
|
||||
uint8_t TileSheet::SubSheet::getPixel(int8_t pBpp, ox::Point const&pt) const noexcept {
|
||||
const auto idx = ptToIdx(pt, columns);
|
||||
return getPixel(pBpp, idx);
|
||||
uint8_t getPixel(TileSheet::SubSheet const&ss, int8_t pBpp, ox::Point const&pt) noexcept {
|
||||
const auto idx = ptToIdx(pt, ss.columns);
|
||||
return getPixel(ss, pBpp, idx);
|
||||
}
|
||||
|
||||
void TileSheet::SubSheet::setPixel(int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept {
|
||||
auto &pixel = this->pixels[static_cast<std::size_t>(idx / 2)];
|
||||
void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, uint64_t idx, uint8_t palIdx) noexcept {
|
||||
auto &pixel = ss.pixels[static_cast<std::size_t>(idx / 2)];
|
||||
if (pBpp == 4) {
|
||||
if (idx & 1) {
|
||||
pixel = static_cast<uint8_t>((pixel & 0b0000'1111) | (palIdx << 4));
|
||||
@@ -148,72 +62,35 @@ void TileSheet::SubSheet::setPixel(int8_t pBpp, uint64_t idx, uint8_t palIdx) no
|
||||
}
|
||||
}
|
||||
|
||||
void TileSheet::SubSheet::setPixel(int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept {
|
||||
const auto idx = ptToIdx(pt, columns);
|
||||
setPixel(pBpp, idx, palIdx);
|
||||
void setPixel(TileSheet::SubSheet &ss, int8_t pBpp, ox::Point const&pt, uint8_t palIdx) noexcept {
|
||||
const auto idx = ptToIdx(pt, ss.columns);
|
||||
setPixel(ss, pBpp, idx, palIdx);
|
||||
}
|
||||
|
||||
ox::Error TileSheet::SubSheet::setPixelCount(int8_t pBpp, std::size_t cnt) noexcept {
|
||||
ox::Error setPixelCount(TileSheet::SubSheet &ss, int8_t pBpp, std::size_t cnt) noexcept {
|
||||
switch (pBpp) {
|
||||
case 4:
|
||||
pixels.resize(cnt / 2);
|
||||
ss.pixels.resize(cnt / 2);
|
||||
return OxError(0);
|
||||
case 8:
|
||||
pixels.resize(cnt);
|
||||
ss.pixels.resize(cnt);
|
||||
return OxError(0);
|
||||
default:
|
||||
return OxError(1, "Invalid pBpp used for TileSheet::SubSheet::setPixelCount");
|
||||
}
|
||||
}
|
||||
|
||||
unsigned TileSheet::SubSheet::pixelCnt(int8_t pBpp) const noexcept {
|
||||
const auto pixelsSize = static_cast<unsigned>(pixels.size());
|
||||
unsigned pixelCnt(TileSheet::SubSheet const&ss, int8_t pBpp) noexcept {
|
||||
const auto pixelsSize = static_cast<unsigned>(ss.pixels.size());
|
||||
return pBpp == 4 ? pixelsSize * 2 : pixelsSize;
|
||||
}
|
||||
|
||||
ox::Result<unsigned> TileSheet::SubSheet::getTileOffset(
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
int8_t pBpp,
|
||||
std::size_t pIt,
|
||||
unsigned pCurrentTotal) const noexcept {
|
||||
// pIt == pNamePath.size() - 1 &&
|
||||
if (name != pNamePath[pIt]) {
|
||||
return OxError(2, "Wrong branch");
|
||||
ox::Result<ox::StringView> getNameFor(TileSheet::SubSheet const&ss, SubSheetId pId) noexcept {
|
||||
if (ss.id == pId) {
|
||||
return ox::StringView(ss.name);
|
||||
}
|
||||
if (pIt == pNamePath.size() - 1) {
|
||||
return pCurrentTotal;
|
||||
}
|
||||
for (auto &sub : subsheets) {
|
||||
auto [offset, err] = sub.getTileOffset(
|
||||
pNamePath, pBpp, pIt + 1, pCurrentTotal);
|
||||
if (!err) {
|
||||
return offset;
|
||||
}
|
||||
pCurrentTotal += sub.pixelCnt(pBpp) / PixelsPerTile;
|
||||
}
|
||||
return OxError(1, "SubSheet not found");
|
||||
}
|
||||
|
||||
ox::Result<SubSheetId> TileSheet::SubSheet::getIdFor(
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
std::size_t pIt) const noexcept {
|
||||
for (auto &sub : subsheets) {
|
||||
if (sub.name == pNamePath[pIt]) {
|
||||
if (pIt == pNamePath.size()) {
|
||||
return id;
|
||||
}
|
||||
return getIdFor(pNamePath, pIt + 1);
|
||||
}
|
||||
}
|
||||
return OxError(1, "SubSheet not found");
|
||||
}
|
||||
|
||||
ox::Result<ox::StringView> TileSheet::SubSheet::getNameFor(SubSheetId pId) const noexcept {
|
||||
if (id == pId) {
|
||||
return ox::StringView(name);
|
||||
}
|
||||
for (const auto &sub : subsheets) {
|
||||
const auto [name, err] = sub.getNameFor(pId);
|
||||
for (const auto &sub : ss.subsheets) {
|
||||
const auto [name, err] = getNameFor(sub, pId);
|
||||
if (!err) {
|
||||
return name;
|
||||
}
|
||||
@@ -222,138 +99,181 @@ ox::Result<ox::StringView> TileSheet::SubSheet::getNameFor(SubSheetId pId) const
|
||||
}
|
||||
|
||||
|
||||
TileSheet &TileSheet::operator=(TileSheet const&other) noexcept {
|
||||
if (this != &other) {
|
||||
bpp = other.bpp;
|
||||
idIt = other.idIt;
|
||||
defaultPalette = other.defaultPalette;
|
||||
subsheet = other.subsheet;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
TileSheet &TileSheet::operator=(TileSheet &&other) noexcept {
|
||||
bpp = other.bpp;
|
||||
idIt = other.idIt;
|
||||
defaultPalette = std::move(other.defaultPalette);
|
||||
subsheet = std::move(other.subsheet);
|
||||
return *this;
|
||||
}
|
||||
|
||||
TileSheet::SubSheetIdx TileSheet::validateSubSheetIdx(
|
||||
const SubSheetIdx &pIdx,
|
||||
TileSheet::SubSheetIdx validateSubSheetIdx(
|
||||
TileSheet::SubSheetIdx const&pIdx,
|
||||
std::size_t pIdxIt,
|
||||
const SubSheet *pSubsheet) noexcept {
|
||||
TileSheet::SubSheet const&pSubsheet) noexcept {
|
||||
if (pIdxIt == pIdx.size()) {
|
||||
return pIdx;
|
||||
}
|
||||
const auto currentIdx = pIdx[pIdxIt];
|
||||
if (pSubsheet->subsheets.size() <= currentIdx) {
|
||||
if (pSubsheet.subsheets.size() <= currentIdx) {
|
||||
auto out = pIdx;
|
||||
if (!pSubsheet->subsheets.empty()) {
|
||||
*out.back().value = pSubsheet->subsheets.size() - 1;
|
||||
if (!pSubsheet.subsheets.empty()) {
|
||||
*out.back().value = pSubsheet.subsheets.size() - 1;
|
||||
} else {
|
||||
out.pop_back();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
return validateSubSheetIdx(pIdx, pIdxIt + 1, &pSubsheet->subsheets[pIdx[pIdxIt]]);
|
||||
return validateSubSheetIdx(pIdx, pIdxIt + 1, pSubsheet.subsheets[pIdx[pIdxIt]]);
|
||||
}
|
||||
|
||||
TileSheet::SubSheetIdx TileSheet::validateSubSheetIdx(const SubSheetIdx &idx) noexcept {
|
||||
return validateSubSheetIdx(idx, 0, &subsheet);
|
||||
TileSheet::SubSheetIdx validateSubSheetIdx(TileSheet const&ts, TileSheet::SubSheetIdx const&idx) noexcept {
|
||||
return validateSubSheetIdx(idx, 0, ts.subsheet);
|
||||
}
|
||||
|
||||
const TileSheet::SubSheet &TileSheet::getSubSheet(
|
||||
const TileSheet::SubSheet &getSubSheet(
|
||||
TileSheet::SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
SubSheet const*pSubsheet) noexcept {
|
||||
TileSheet::SubSheet const&pSubsheet) noexcept {
|
||||
if (idxIt == idx.size()) {
|
||||
return *pSubsheet;
|
||||
return pSubsheet;
|
||||
}
|
||||
const auto currentIdx = idx[idxIt];
|
||||
if (pSubsheet->subsheets.size() < currentIdx) {
|
||||
return *pSubsheet;
|
||||
if (pSubsheet.subsheets.size() < currentIdx) {
|
||||
return pSubsheet;
|
||||
}
|
||||
return getSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[currentIdx]);
|
||||
return getSubSheet(idx, idxIt + 1, pSubsheet.subsheets[currentIdx]);
|
||||
}
|
||||
|
||||
TileSheet::SubSheet &TileSheet::getSubSheet(
|
||||
TileSheet::SubSheet &getSubSheet(
|
||||
TileSheet::SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
TileSheet::SubSheet *pSubsheet) noexcept {
|
||||
TileSheet::SubSheet &pSubsheet) noexcept {
|
||||
if (idxIt == idx.size()) {
|
||||
return *pSubsheet;
|
||||
return pSubsheet;
|
||||
}
|
||||
return getSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[idx[idxIt]]);
|
||||
return getSubSheet(idx, idxIt + 1, pSubsheet.subsheets[idx[idxIt]]);
|
||||
}
|
||||
|
||||
const TileSheet::SubSheet &TileSheet::getSubSheet(TileSheet::SubSheetIdx const&idx) const noexcept {
|
||||
return getSubSheet(idx, 0, &subsheet);
|
||||
TileSheet::SubSheet const&getSubSheet(TileSheet const&ts, TileSheet::SubSheetIdx const&idx) noexcept {
|
||||
return core::getSubSheet(idx, 0, ts.subsheet);
|
||||
}
|
||||
|
||||
TileSheet::SubSheet &TileSheet::getSubSheet(TileSheet::SubSheetIdx const&idx) noexcept {
|
||||
return getSubSheet(idx, 0, &subsheet);
|
||||
TileSheet::SubSheet &getSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept {
|
||||
return core::getSubSheet(idx, 0, ts.subsheet);
|
||||
}
|
||||
|
||||
ox::Error TileSheet::addSubSheet(TileSheet::SubSheetIdx const&idx) noexcept {
|
||||
auto &parent = getSubSheet(idx);
|
||||
ox::Error addSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept {
|
||||
auto &parent = getSubSheet(ts, idx);
|
||||
if (parent.subsheets.size() < 2) {
|
||||
parent.subsheets.emplace_back(idIt++, ox::sfmt("Subsheet {}", parent.subsheets.size()), 1, 1, bpp);
|
||||
parent.subsheets.emplace_back(++ts.idIt, ox::sfmt("Subsheet {}", parent.subsheets.size()), 1, 1, ts.bpp);
|
||||
} else {
|
||||
parent.subsheets.emplace_back(idIt++, "Subsheet 0", parent.columns, parent.rows, bpp);
|
||||
parent.subsheets.emplace_back(idIt++, "Subsheet 1", 1, 1, bpp);
|
||||
parent.subsheets.emplace_back(++ts.idIt, "Subsheet 0", parent.columns, parent.rows, ts.bpp);
|
||||
parent.subsheets.emplace_back(++ts.idIt, "Subsheet 1", 1, 1, ts.bpp);
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
ox::Error TileSheet::rmSubSheet(
|
||||
SubSheetIdx const&idx,
|
||||
ox::Error rmSubSheet(
|
||||
TileSheet &ts,
|
||||
TileSheet::SubSheetIdx const&idx,
|
||||
std::size_t idxIt,
|
||||
SubSheet *pSubsheet) noexcept {
|
||||
TileSheet::SubSheet &pSubsheet) noexcept {
|
||||
if (idxIt == idx.size() - 1) {
|
||||
return pSubsheet->subsheets.erase(idx[idxIt]).error;
|
||||
return pSubsheet.subsheets.erase(idx[idxIt]).error;
|
||||
}
|
||||
return rmSubSheet(idx, idxIt + 1, &pSubsheet->subsheets[idx[idxIt]]);
|
||||
return rmSubSheet(ts, idx, idxIt + 1, pSubsheet.subsheets[idx[idxIt]]);
|
||||
}
|
||||
|
||||
ox::Error TileSheet::rmSubSheet(TileSheet::SubSheetIdx const&idx) noexcept {
|
||||
return rmSubSheet(idx, 0, &subsheet);
|
||||
ox::Error rmSubSheet(TileSheet &ts, TileSheet::SubSheetIdx const&idx) noexcept {
|
||||
return rmSubSheet(ts, idx, 0, ts.subsheet);
|
||||
}
|
||||
|
||||
uint8_t TileSheet::getPixel4Bpp(
|
||||
uint8_t getPixel4Bpp(
|
||||
TileSheet const&ts,
|
||||
ox::Point const&pt,
|
||||
TileSheet::SubSheetIdx const&subsheetIdx) const noexcept {
|
||||
oxAssert(bpp == 4, "TileSheet::getPixel4Bpp: wrong bpp");
|
||||
auto &s = this->getSubSheet(subsheetIdx);
|
||||
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);
|
||||
return s.getPixel4Bpp(idx);
|
||||
return getPixel4Bpp(s, idx);
|
||||
}
|
||||
|
||||
uint8_t TileSheet::getPixel8Bpp(
|
||||
uint8_t getPixel8Bpp(
|
||||
TileSheet const&ts,
|
||||
ox::Point const&pt,
|
||||
TileSheet::SubSheetIdx const&subsheetIdx) const noexcept {
|
||||
oxAssert(bpp == 8, "TileSheet::getPixel8Bpp: wrong bpp");
|
||||
auto &s = this->getSubSheet(subsheetIdx);
|
||||
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);
|
||||
return s.getPixel8Bpp(idx);
|
||||
return getPixel8Bpp(s, idx);
|
||||
}
|
||||
|
||||
ox::Result<SubSheetId> TileSheet::getIdFor(ox::CRStringView path) const noexcept {
|
||||
return subsheet.getIdFor(ox::split<8>(path, '.'));
|
||||
static ox::Result<SubSheetId> getIdFor(
|
||||
TileSheet::SubSheet const&ss,
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
std::size_t pIt = 0) noexcept {
|
||||
for (auto &sub : ss.subsheets) {
|
||||
if (sub.name == pNamePath[pIt]) {
|
||||
if (pIt == pNamePath.size()) {
|
||||
return ss.id;
|
||||
}
|
||||
return getIdFor(ss, pNamePath, pIt + 1);
|
||||
}
|
||||
}
|
||||
return OxError(1, "SubSheet not found");
|
||||
}
|
||||
|
||||
ox::Result<unsigned> TileSheet::getTileOffset(ox::CRStringView pNamePath) const noexcept {
|
||||
return subsheet.getTileOffset(ox::split<8>(pNamePath, '.'), bpp);
|
||||
ox::Result<SubSheetId> getIdFor(TileSheet const&ts, ox::CRStringView path) noexcept {
|
||||
return getIdFor(ts.subsheet, ox::split<8>(path, '.'));
|
||||
}
|
||||
|
||||
ox::Result<ox::StringView> TileSheet::getNameFor(SubSheetId pId) const noexcept {
|
||||
return subsheet.getNameFor(pId);
|
||||
/**
|
||||
* Gets the offset in tiles of the desired subsheet.
|
||||
*/
|
||||
static ox::Result<unsigned> getTileOffset(
|
||||
TileSheet::SubSheet const&ss,
|
||||
ox::SpanView<ox::StringView> const&pNamePath,
|
||||
int8_t pBpp,
|
||||
std::size_t pIt = 0,
|
||||
unsigned pCurrentTotal = 0) noexcept {
|
||||
// pIt == pNamePath.size() - 1 &&
|
||||
if (ss.name != pNamePath[pIt]) {
|
||||
return OxError(2, "Wrong branch");
|
||||
}
|
||||
if (pIt == pNamePath.size() - 1) {
|
||||
return pCurrentTotal;
|
||||
}
|
||||
for (auto &sub : ss.subsheets) {
|
||||
auto [offset, err] = getTileOffset(
|
||||
sub, pNamePath, pBpp, pIt + 1, pCurrentTotal);
|
||||
if (!err) {
|
||||
return offset;
|
||||
}
|
||||
pCurrentTotal += pixelCnt(sub, pBpp) / PixelsPerTile;
|
||||
}
|
||||
return OxError(1, "SubSheet not found");
|
||||
}
|
||||
|
||||
ox::Vector<uint8_t> TileSheet::pixels() const noexcept {
|
||||
ox::Result<unsigned> getTileOffset(TileSheet const&ts, ox::CRStringView pNamePath) noexcept {
|
||||
return core::getTileOffset(ts.subsheet, ox::split<8>(pNamePath, '.'), ts.bpp);
|
||||
}
|
||||
|
||||
ox::Result<ox::StringView> getNameFor(TileSheet &ts, SubSheetId pId) noexcept {
|
||||
return core::getNameFor(ts.subsheet, pId);
|
||||
}
|
||||
|
||||
ox::Result<ox::StringView> getNameFor(TileSheet const&ts, SubSheetId pId) noexcept {
|
||||
return core::getNameFor(ts.subsheet, pId);
|
||||
}
|
||||
|
||||
static void readPixelsTo(TileSheet::SubSheet &ss, ox::Vector<uint8_t> &pPixels) noexcept {
|
||||
if (!ss.subsheets.empty()) {
|
||||
for (auto &s: ss.subsheets) {
|
||||
readPixelsTo(s, pPixels);
|
||||
}
|
||||
} else {
|
||||
for (auto p : ss.pixels) {
|
||||
pPixels.emplace_back(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ox::Vector<uint8_t> pixels(TileSheet &ts) noexcept {
|
||||
ox::Vector<uint8_t> out;
|
||||
subsheet.readPixelsTo(&out);
|
||||
readPixelsTo(ts.subsheet, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
@@ -42,7 +42,7 @@ struct TileDoc {
|
||||
if (subsheetId > -1) {
|
||||
return subsheetId;
|
||||
}
|
||||
return ts.getIdFor(subsheetPath);
|
||||
return getIdFor(ts, subsheetPath);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@@ -50,7 +50,7 @@ struct TileDoc {
|
||||
core::TileSheet const&ts) const noexcept {
|
||||
// prefer the already present path
|
||||
if (!subsheetPath.len()) {
|
||||
return ts.getNameFor(subsheetId);
|
||||
return core::getNameFor(ts, subsheetId);
|
||||
}
|
||||
return ox::StringView(subsheetPath);
|
||||
}
|
||||
|
@@ -54,7 +54,7 @@ ox::Error SceneDocToSceneStaticConverter::convert(
|
||||
auto dstTile = dstLayer.tile(tileIdx);
|
||||
dstTile.tileType = srcTile.type;
|
||||
oxRequire(path, srcTile.getSubsheetPath(*ts));
|
||||
oxRequire(mapIdx, ts->getTileOffset(path));
|
||||
oxRequire(mapIdx, getTileOffset(*ts, path));
|
||||
dstTile.tileMapIdx = static_cast<uint16_t>(mapIdx);
|
||||
setLayerAttachments(layerIdx, srcTile, dstTile);
|
||||
++tileIdx;
|
||||
|
Reference in New Issue
Block a user