ugui/lib/ugui.c3l/src/ugui_sprite.c3

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)!;
}