108 lines
2.5 KiB
Plaintext
108 lines
2.5 KiB
Plaintext
module ugui;
|
|
|
|
import std::core::mem::allocator;
|
|
import std::collections::map;
|
|
import std::io;
|
|
import std::compression::qoi;
|
|
|
|
const usz SRITES_PER_ATLAS = 64;
|
|
|
|
enum SpriteType {
|
|
SPRITE_NORMAL,
|
|
SPRITE_SDF,
|
|
SPRITE_MSDF,
|
|
SPRITE_ANIMATED,
|
|
}
|
|
|
|
struct Sprite {
|
|
Id id;
|
|
SpriteType type;
|
|
ushort u, v;
|
|
ushort w, h;
|
|
}
|
|
|
|
alias SpriteMap = map::HashMap{Id, Sprite};
|
|
|
|
struct SpriteAtlas {
|
|
Id id;
|
|
Atlas atlas;
|
|
SpriteMap sprites;
|
|
bool should_update;
|
|
}
|
|
|
|
// name: some examples are "icons" or "images"
|
|
fn void? SpriteAtlas.init(&this, String name, AtlasType type, ushort width, ushort height)
|
|
{
|
|
// FIXME: for now only R8G8B8A8 format is supported
|
|
if (type != ATLAS_R8G8B8A8) {
|
|
return INVALID_TYPE?;
|
|
}
|
|
|
|
this.id = name.hash();
|
|
this.atlas.new(this.id, AtlasType.ATLAS_R8G8B8A8, width, height)!;
|
|
this.sprites.init(allocator::mem, capacity: SRITES_PER_ATLAS);
|
|
this.should_update = false;
|
|
}
|
|
|
|
fn void? SpriteAtlas.free(&this)
|
|
{
|
|
this.atlas.free();
|
|
this.sprites.free();
|
|
}
|
|
|
|
// FIXME: this should throw an error when a different pixel format than the atlas' is used
|
|
// or convert from the source's pixel format to the atlas'
|
|
fn Sprite*? SpriteAtlas.insert(&this, String name, SpriteType type, char[] pixels, ushort w, ushort h, ushort stride)
|
|
{
|
|
Sprite s;
|
|
s.id = name.hash();
|
|
s.type = type;
|
|
Point uv = this.atlas.place(pixels, w, h, stride)!;
|
|
s.w = w;
|
|
s.h = h;
|
|
s.u = uv.x;
|
|
s.v = uv.y;
|
|
this.sprites.set(s.id, s);
|
|
this.should_update = true;
|
|
return this.sprites.get_ref(s.id);
|
|
}
|
|
|
|
fn Sprite*? SpriteAtlas.get(&this, String name)
|
|
{
|
|
Id id = name.hash();
|
|
return this.sprites.get_ref(id);
|
|
}
|
|
|
|
fn Sprite*? SpriteAtlas.get_by_id(&this, Id id)
|
|
{
|
|
return this.sprites.get_ref(id);
|
|
}
|
|
|
|
macro Rect Sprite.rect(s) => {0,0,s.w,s.h};
|
|
macro Rect Sprite.uv(s) => {s.u,s.v,s.w,s.h};
|
|
|
|
fn void? Ctx.sprite_atlas_create(&ctx, String name, AtlasType type, ushort w, ushort h)
|
|
{
|
|
ctx.sprite_atlas.init(name, type, w, h)!;
|
|
}
|
|
|
|
fn Id Ctx.get_sprite_atlas_id(&ctx, String name)
|
|
{
|
|
return name.hash();
|
|
}
|
|
|
|
fn void? Ctx.import_sprite_memory(&ctx, String name, char[] pixels, ushort w, ushort h, ushort stride, SpriteType type = SPRITE_NORMAL)
|
|
{
|
|
ctx.sprite_atlas.insert(name, type, pixels, w, h, stride)!;
|
|
}
|
|
|
|
fn void? Ctx.import_sprite_file_qoi(&ctx, String name, String path, SpriteType type = SPRITE_NORMAL)
|
|
{
|
|
QOIDesc desc;
|
|
|
|
char[] pixels = qoi::read(allocator::mem, path, &desc, QOIChannels.RGBA)!;
|
|
defer mem::free(pixels);
|
|
|
|
ctx.sprite_atlas.insert(name, type, pixels, (ushort)desc.width, (ushort)desc.height, (ushort)desc.width)!;
|
|
}
|