parent
3eccd8e7e7
commit
b7825b84ce
|
@ -11,8 +11,7 @@
|
|||
* @param baseAssets - The relative path to the base texture assets.
|
||||
*/
|
||||
|
||||
LocalSubgame::LocalSubgame(const std::string& baseAssets) :
|
||||
textures(u16vec2(512)),
|
||||
LocalSubgame::LocalSubgame(const std::string& baseAssets) : textures(),
|
||||
|
||||
lua(std::make_unique<LocalLuaParser>(*this)),
|
||||
biomes(std::make_unique<LocalBiomeAtlas>()),
|
||||
|
|
|
@ -51,8 +51,20 @@ AtlasRef TextureAtlas::addBytes(const string& identifier, bool persistent, u16ve
|
|||
|
||||
tilesUsed += tileSize.x * tileSize.y;
|
||||
textures.erase(identifier);
|
||||
AtlasTexture* raw = new AtlasTexture(*this, identifier, pos, size, data);
|
||||
AtlasRef ref = sptr<AtlasTexture>(raw, [this](AtlasTexture* tex) { removeTexture(tex); });
|
||||
AtlasRef ref = sptr<AtlasTexture>(new AtlasTexture(*this, identifier, pos, size, data),
|
||||
[this](AtlasTexture* tex) { removeTexture(tex); });
|
||||
if (persistent) persistentTextures.insert(ref);
|
||||
addTexture(ref);
|
||||
|
||||
return ref;
|
||||
}
|
||||
|
||||
sptr<AtlasTexture> TextureAtlas::addCrop(const string& identifier, bool persistent,
|
||||
u16vec2 offset, u16vec2 size, const sptr<AtlasTexture>& source) {
|
||||
|
||||
textures.erase(identifier);
|
||||
AtlasRef ref = sptr<AtlasTexture>(new AtlasTexture(*this, identifier, offset, size, source),
|
||||
[this](AtlasTexture* tex) { removeTexture(tex); });
|
||||
if (persistent) persistentTextures.insert(ref);
|
||||
addTexture(ref);
|
||||
|
||||
|
@ -64,9 +76,20 @@ AtlasRef TextureAtlas::operator[](const string& identifier) {
|
|||
if (tex->getIdentifier() != "_missing") return tex;
|
||||
|
||||
let data = texBuilder.build(identifier);
|
||||
let texture = addBytes(identifier, false, data.texture->size, data.texture->getBytes());
|
||||
// if (data.tintMask) texture->setTintData(*data.tintInd,
|
||||
// addBytes(identifier + ":tint", false, data.size, *data.tintMask));
|
||||
let texture = (std::holds_alternative<TextureBuilder::Texture::ByteData>(data.texture->data))
|
||||
? addBytes(identifier, false, data.texture->size, data.texture->getBytes())
|
||||
: addCrop(identifier, false, std::get<TextureBuilder::Texture::CropData>(data.texture->data).offset,
|
||||
data.texture->size, std::get<TextureBuilder::Texture::CropData>(data.texture->data).source);
|
||||
|
||||
if (data.tintMask) {
|
||||
let mask = (std::holds_alternative<TextureBuilder::Texture::ByteData>(data.tintMask->second->data))
|
||||
? addBytes(identifier + ":tint", false, data.texture->size, data.tintMask->second->getBytes())
|
||||
: addCrop(identifier + ":tint", false,
|
||||
std::get<TextureBuilder::Texture::CropData>(data.tintMask->second->data).offset,
|
||||
data.texture->size, std::get<TextureBuilder::Texture::CropData>(data.tintMask->second->data).source);
|
||||
texture->setTintData(data.tintMask->first, mask);
|
||||
}
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
|
@ -126,12 +149,13 @@ void TextureAtlas::addTexture(const AtlasRef& tex) {
|
|||
let pos = tex->getPos();
|
||||
let size = tex->getSize();
|
||||
textures.insert({ tex->getIdentifier(), std::weak_ptr(tex) });
|
||||
texture.updateTexture(pos.x, pos.y, size.x, size.y, tex->getBytes().data());
|
||||
if (!tex->isCrop()) texture.updateTexture(pos.x, pos.y, size.x, size.y, tex->getBytes().data());
|
||||
}
|
||||
|
||||
void TextureAtlas::removeTexture(const AtlasTexture* tex) {
|
||||
std::cout << tex->getIdentifier() << std::endl;
|
||||
std::cerr << "Removed " << tex->getIdentifier() << std::endl;
|
||||
textures.erase(tex->getIdentifier());
|
||||
if (tex->isCrop()) return;
|
||||
|
||||
let tilePos = tex->getTilePos();
|
||||
let tileSize = tex->getTileSize();
|
||||
|
|
|
@ -19,7 +19,7 @@ class AtlasTexture;
|
|||
|
||||
class TextureAtlas {
|
||||
public:
|
||||
TextureAtlas() = default;
|
||||
TextureAtlas(): TextureAtlas(uvec2(2048)) {};
|
||||
|
||||
explicit TextureAtlas(uvec2 size);
|
||||
|
||||
|
@ -29,6 +29,9 @@ public:
|
|||
|
||||
sptr<AtlasTexture> addBytes(const string& identifier, bool persistent, u16vec2 size, const vec<u8>& data);
|
||||
|
||||
sptr<AtlasTexture> addCrop(const string& identifier, bool persistent,
|
||||
u16vec2 offset, u16vec2 size, const sptr<AtlasTexture>& source);
|
||||
|
||||
sptr<AtlasTexture> operator[](const string& identifier);
|
||||
|
||||
sptr<AtlasTexture> get(const string& identifier) const;
|
||||
|
@ -41,6 +44,7 @@ public:
|
|||
|
||||
const Texture& getTexture();
|
||||
private:
|
||||
|
||||
void createMissingTexture();
|
||||
|
||||
optional<u16vec2> findAtlasSpace(u16vec2 tileSize);
|
||||
|
|
|
@ -8,14 +8,13 @@ vec<u8>& TextureBuilder::Texture::getBytes() {
|
|||
const vec<u8> sourceBytes = cropData.source->getBytes();
|
||||
const u16 sourceWidth = cropData.source->getSize().x;
|
||||
|
||||
std::cout << "cropping " << cropData.source->getIdentifier() << " to " << size << std::endl;
|
||||
|
||||
vec<u8> newBytes(size.x * size.y * 4);
|
||||
for (u32 i = 0; i < size.x * size.y * 4; i++) newBytes[i] =
|
||||
sourceBytes[(((cropData.offset.x + i / 4) % size.x) +
|
||||
(cropData.offset.y + i / 4 / size.x) * sourceWidth) * 4 + i % 4];
|
||||
for (u32 i = 0; i < size.x * size.y * 4; i++) {
|
||||
newBytes[i] = sourceBytes[(
|
||||
(cropData.offset.x + ((i / 4) % size.x)) +
|
||||
(cropData.offset.y + (i / 4 / size.x)) * sourceWidth) * 4 + i % 4];
|
||||
}
|
||||
|
||||
// data = ByteData(sourceBytes);
|
||||
data = ByteData(newBytes);
|
||||
return get<ByteData>(data).data;
|
||||
}
|
||||
|
@ -53,22 +52,24 @@ void TextureBuilder::Texture::multiply(Texture& texture) {
|
|||
for (u32 i = 0; i < size.x * size.y * 4; i++) data[i] *= mul[i];
|
||||
}
|
||||
|
||||
void TextureBuilder::Texture::stack(Texture& texture) {
|
||||
void TextureBuilder::Texture::stack(Texture& texture, Texture* mask) {
|
||||
if (!mask) mask = &texture;
|
||||
|
||||
let& data = getBytes();
|
||||
const let& otherData = texture.getBytes();
|
||||
const let& maskData = mask->getBytes();
|
||||
for (u32 i = 0; i < size.x * size.y; i++) {
|
||||
const let& oData = texture.getBytes();
|
||||
const f32 factor = oData[i * 4 + 3] / 255.f;
|
||||
data[i * 4] = data[i * 4] * (1 - factor) + oData[i * 4] * factor;
|
||||
data[i * 4 + 1] = data[i * 4 + 1] * (1 - factor) + oData[i * 4 + 1] * factor;
|
||||
data[i * 4 + 2] = data[i * 4 + 2] * (1 - factor) + oData[i * 4 + 2] * factor;
|
||||
data[i * 4 + 3] = std::min(static_cast<u16>(data[i * 4 + 3]) + oData[i * 4 + 3], 255);
|
||||
const f32 factor = maskData[i * 4 + 3] / 255.f;
|
||||
data[i * 4] = data[i * 4] * (1 - factor) + otherData[i * 4] * factor;
|
||||
data[i * 4 + 1] = data[i * 4 + 1] * (1 - factor) + otherData[i * 4 + 1] * factor;
|
||||
data[i * 4 + 2] = data[i * 4 + 2] * (1 - factor) + otherData[i * 4 + 2] * factor;
|
||||
data[i * 4 + 3] = std::min(static_cast<u16>(data[i * 4 + 3]) + otherData[i * 4 + 3], 255);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TextureBuilder::Data TextureBuilder::Data::literal(Context& ctx, string str) {
|
||||
let tex = ctx.atlas.get(str);
|
||||
return Data(tex->getSize(), {}, tex);
|
||||
return Data({}, tex->getSize(), tex);
|
||||
}
|
||||
|
||||
TextureBuilder::Data TextureBuilder::Data::canvas(u16 w, optional<variant<u16, string>> h, optional<string> fill) {
|
||||
|
@ -87,6 +88,9 @@ TextureBuilder::Data TextureBuilder::Data::crop(u16 x, u16 y, u16 w, variant<u16
|
|||
u16 h = std::holds_alternative<u16>(hV) ? std::get<u16>(hV) : w;
|
||||
Data data = std::holds_alternative<Data>(hV) ? std::get<Data>(hV) : *texO;
|
||||
|
||||
if (w + x > data.texture->size.x || h + y > data.texture->size.y)
|
||||
throw std::runtime_error("Invalid crop region.");
|
||||
|
||||
data.texture->crop({ x, y }, { w, h });
|
||||
return data;
|
||||
}
|
||||
|
@ -111,7 +115,13 @@ TextureBuilder::Data TextureBuilder::Data::stack(Data b, Data s1, optional<Data>
|
|||
if (s7) stack.emplace_back(&*s7);
|
||||
if (s8) stack.emplace_back(&*s8);
|
||||
|
||||
for (const Data* s : stack) b.texture->stack(*s->texture.get());
|
||||
for (const Data* s : stack) {
|
||||
b.texture->stack(*s->texture.get());
|
||||
if (s->tintMask) {
|
||||
if (!b.tintMask) b.tintMask = {{ s->tintMask->first, std::make_unique<Texture>(b.texture->size, vec4 {}) }};
|
||||
b.tintMask->second->stack(*s->tintMask->second.get(), s->texture.get());
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "util/StringParser.h"
|
||||
//#include "game/atlas/TextureAtlas.h"
|
||||
|
||||
class TextureAtlas;
|
||||
class AtlasTexture;
|
||||
|
@ -19,6 +18,7 @@ private:
|
|||
|
||||
public:
|
||||
class Texture {
|
||||
public:
|
||||
struct ByteData {
|
||||
ByteData() = default;
|
||||
ByteData(const vec<u8>& data): data(data) {};
|
||||
|
@ -33,7 +33,6 @@ public:
|
|||
sptr<AtlasTexture> source;
|
||||
};
|
||||
|
||||
public:
|
||||
void alpha(f32 factor);
|
||||
|
||||
void crop(u16vec2 pos, u16vec2 size);
|
||||
|
@ -42,7 +41,7 @@ public:
|
|||
|
||||
void multiply(Texture& texture);
|
||||
|
||||
void stack(Texture& texture);
|
||||
void stack(Texture& texture, Texture* mask = nullptr);
|
||||
|
||||
Texture(u16vec2 size, vec4 color):
|
||||
size(size), data(ByteData(vec<u8>(size.x * size.y * 4))) {
|
||||
|
@ -138,13 +137,18 @@ public:
|
|||
|
||||
public:
|
||||
Data() = default;
|
||||
Data(const Data& o): texture(std::move(const_cast<Data&>(o).texture)) {};
|
||||
Data(const Data& o): texture(std::move(const_cast<Data&>(o).texture)),
|
||||
tintMask(std::move(const_cast<Data&>(o).tintMask)) {};
|
||||
|
||||
Data(u16vec2 size, vec4 color): texture(make_unique<Texture>(size, color)) {};
|
||||
Data(u16vec2 size, sptr<AtlasTexture> tex): texture(make_unique<Texture>(size, tex)) {};
|
||||
Data(u16vec2 pos, u16vec2 size, sptr<AtlasTexture> tex): texture(make_unique<Texture>(pos, size, tex)) {};
|
||||
|
||||
Data& operator=(const Data& o) { texture = std::move(const_cast<Data&>(o).texture); return *this; };
|
||||
Data& operator=(const Data& o) {
|
||||
texture = std::move(const_cast<Data&>(o).texture);
|
||||
tintMask = std::move(const_cast<Data&>(o).tintMask);
|
||||
return *this;
|
||||
};
|
||||
|
||||
uptr<Texture> texture = {};
|
||||
optional<std::pair<u32, uptr<Texture>>> tintMask = {};
|
||||
|
|
|
@ -37,6 +37,9 @@ class AtlasTexture {
|
|||
sptr<AtlasTexture> source;
|
||||
};
|
||||
|
||||
AtlasTexture(TextureAtlas& atlas, const string& identifier, uvec2 pos, const variant<ByteData, CropData>& data):
|
||||
identifier(identifier), pos(pos), data(data), atlas(atlas) {}
|
||||
|
||||
public:
|
||||
|
||||
AtlasTexture(const AtlasTexture& o) = delete;
|
||||
|
@ -47,9 +50,6 @@ public:
|
|||
AtlasTexture(TextureAtlas& atlas, const string& identifier, uvec2 pos, uvec2 size, vec<u8> data):
|
||||
AtlasTexture(atlas, identifier, pos, ByteData { size, data }) {}
|
||||
|
||||
AtlasTexture(TextureAtlas& atlas, const string& identifier, uvec2 pos, const variant<ByteData, CropData>& data):
|
||||
identifier(identifier), pos(pos), data(data), atlas(atlas) {}
|
||||
|
||||
/** Returns the texture's identifier. */
|
||||
inline const string& getIdentifier() const {
|
||||
return identifier;
|
||||
|
@ -96,6 +96,11 @@ public:
|
|||
/** Sets the tint information of the texture. */
|
||||
void setTintData(u32 tintInd, const sptr<AtlasTexture>& tintMask);
|
||||
|
||||
/** Returns true if this texture is a crop of another texture. */
|
||||
inline bool isCrop() const {
|
||||
return std::holds_alternative<CropData>(data);
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/** The position of the top-left point of the texture in the texture atlas. */
|
||||
|
|
Loading…
Reference in New Issue