sprite layer refactor

This commit is contained in:
jacob 2025-08-01 00:43:21 -05:00
parent 9d8758b2b4
commit f1776dedaf
5 changed files with 625 additions and 666 deletions

View File

@ -239,7 +239,7 @@ void P_AppStartup(String args_str)
AC_StartupReceipt asset_cache_sr = AC_Startup(); AC_StartupReceipt asset_cache_sr = AC_Startup();
TTF_StartupReceipt ttf_sr = TTF_Startup(); TTF_StartupReceipt ttf_sr = TTF_Startup();
F_StartupReceipt font_sr = F_Startup(&asset_cache_sr, &ttf_sr); F_StartupReceipt font_sr = F_Startup(&asset_cache_sr, &ttf_sr);
S_StartupReceipt sprite_sr = sprite_startup(); S_StartupReceipt sprite_sr = S_Startup();
MIX_StartupReceipt mixer_sr = MIX_Startup(); MIX_StartupReceipt mixer_sr = MIX_Startup();
SND_StartupReceipt sound_sr = SND_Startup(&asset_cache_sr); SND_StartupReceipt sound_sr = SND_Startup(&asset_cache_sr);
D_StartupReceipt draw_sr = D_Startup(&font_sr); D_StartupReceipt draw_sr = D_Startup(&font_sr);

View File

@ -36,7 +36,7 @@ void sim_accel_reset(Snapshot *ss, SimAccel *accel)
internal Ent *test_spawn_smg(Ent *parent) internal Ent *test_spawn_smg(Ent *parent)
{ {
Ent *e = sim_ent_alloc_sync_src(parent); Ent *e = sim_ent_alloc_sync_src(parent);
e->sprite = sprite_tag_from_path(Lit("sprite/gun.ase")); e->sprite = S_TagFromPath(Lit("sprite/gun.ase"));
sim_ent_enable_prop(e, SEPROP_ATTACHED); sim_ent_enable_prop(e, SEPROP_ATTACHED);
e->attach_slice = Lit("attach.wep"); e->attach_slice = Lit("attach.wep");
@ -52,7 +52,7 @@ internal Ent *test_spawn_smg(Ent *parent)
internal Ent *test_spawn_launcher(Ent *parent) internal Ent *test_spawn_launcher(Ent *parent)
{ {
Ent *e = sim_ent_alloc_sync_src(parent); Ent *e = sim_ent_alloc_sync_src(parent);
e->sprite = sprite_tag_from_path(Lit("sprite/gun.ase")); e->sprite = S_TagFromPath(Lit("sprite/gun.ase"));
sim_ent_enable_prop(e, SEPROP_ATTACHED); sim_ent_enable_prop(e, SEPROP_ATTACHED);
e->attach_slice = Lit("attach.wep"); e->attach_slice = Lit("attach.wep");
@ -68,7 +68,7 @@ internal Ent *test_spawn_launcher(Ent *parent)
internal Ent *test_spawn_chucker(Ent *parent) internal Ent *test_spawn_chucker(Ent *parent)
{ {
Ent *chucker = sim_ent_alloc_sync_src(parent); Ent *chucker = sim_ent_alloc_sync_src(parent);
chucker->sprite = sprite_tag_from_path(Lit("sprite/gun.ase")); chucker->sprite = S_TagFromPath(Lit("sprite/gun.ase"));
sim_ent_enable_prop(chucker, SEPROP_ATTACHED); sim_ent_enable_prop(chucker, SEPROP_ATTACHED);
chucker->attach_slice = Lit("attach.wep"); chucker->attach_slice = Lit("attach.wep");
@ -119,12 +119,12 @@ internal Ent *test_spawn_employee(Ent *parent)
{ {
sim_ent_enable_prop(e, SEPROP_TEST); sim_ent_enable_prop(e, SEPROP_TEST);
e->sprite = sprite_tag_from_path(Lit("sprite/tim.ase")); e->sprite = S_TagFromPath(Lit("sprite/tim.ase"));
e->mass_unscaled = 10; e->mass_unscaled = 10;
e->inertia_unscaled = 5; e->inertia_unscaled = 5;
} }
//e->sprite = sprite_tag_from_path(Lit("sprite/box_rounded.ase")); //e->sprite = S_TagFromPath(Lit("sprite/box_rounded.ase"));
//e->sprite_span_name = Lit("idle.unarmed"); //e->sprite_span_name = Lit("idle.unarmed");
//e->sprite_span_name = Lit("idle.one_handed"); //e->sprite_span_name = Lit("idle.one_handed");
e->sprite_span_name = Lit("idle.two_handed"); e->sprite_span_name = Lit("idle.two_handed");
@ -255,7 +255,7 @@ internal void test_spawn_entities2(Ent *parent, Vec2 pos)
Xform xf = XformFromTrs(TRS(.t = pos, .r = rot, .s = size)); Xform xf = XformFromTrs(TRS(.t = pos, .r = rot, .s = size));
sim_ent_set_xform(e, xf); sim_ent_set_xform(e, xf);
e->sprite = sprite_tag_from_path(Lit("sprite/tile.ase")); e->sprite = S_TagFromPath(Lit("sprite/tile.ase"));
e->layer = SIM_LAYER_SHOULDERS; e->layer = SIM_LAYER_SHOULDERS;
//e->sprite_tint = Alpha32F(ColorBlue, 0.75); //e->sprite_tint = Alpha32F(ColorBlue, 0.75);
@ -297,7 +297,7 @@ internal void test_spawn_entities2(Ent *parent, Vec2 pos)
Xform xf = XformFromTrs(.t = pos, .r = r, .s = size); Xform xf = XformFromTrs(.t = pos, .r = r, .s = size);
sim_ent_set_xform(e, xf); sim_ent_set_xform(e, xf);
e->sprite = sprite_tag_from_path(Lit("sprite/bullet.ase")); e->sprite = S_TagFromPath(Lit("sprite/bullet.ase"));
e->sprite_collider_slice = Lit("shape"); e->sprite_collider_slice = Lit("shape");
e->layer = SIM_LAYER_SHOULDERS; e->layer = SIM_LAYER_SHOULDERS;
@ -325,7 +325,7 @@ internal void test_spawn_entities3(Ent *parent, Vec2 pos)
Xform xf = XformFromTrs(TRS(.t = pos, .r = r, .s = size)); Xform xf = XformFromTrs(TRS(.t = pos, .r = r, .s = size));
sim_ent_set_xform(e, xf); sim_ent_set_xform(e, xf);
e->sprite = sprite_tag_from_path(Lit("sprite/box.ase")); e->sprite = S_TagFromPath(Lit("sprite/box.ase"));
e->layer = SIM_LAYER_SHOULDERS; e->layer = SIM_LAYER_SHOULDERS;
e->sprite_tint = ColorRed; e->sprite_tint = ColorRed;
@ -348,8 +348,8 @@ internal void test_spawn_entities4(Ent *parent, Vec2 pos)
Xform xf = XformFromTrs(TRS(.t = pos, .r = r, .s = size)); Xform xf = XformFromTrs(TRS(.t = pos, .r = r, .s = size));
sim_ent_set_xform(e, xf); sim_ent_set_xform(e, xf);
//e->sprite = sprite_tag_from_path(Lit("sprite/box.ase")); //e->sprite = S_TagFromPath(Lit("sprite/box.ase"));
e->sprite = sprite_tag_from_path(Lit("sprite/tile.ase")); e->sprite = S_TagFromPath(Lit("sprite/tile.ase"));
e->layer = SIM_LAYER_SHOULDERS; e->layer = SIM_LAYER_SHOULDERS;
sim_ent_enable_prop(e, SEPROP_LIGHT_TEST); sim_ent_enable_prop(e, SEPROP_LIGHT_TEST);
@ -378,14 +378,14 @@ internal void test_spawn_tile(Snapshot *world, Vec2 world_pos)
sim_ent_set_xform(e, xf); sim_ent_set_xform(e, xf);
e->layer = SIM_LAYER_WALLS; e->layer = SIM_LAYER_WALLS;
e->sprite = sprite_tag_from_path(Lit("sprite/tile.ase")); e->sprite = S_TagFromPath(Lit("sprite/tile.ase"));
e->sprite_tint = ColorRed; e->sprite_tint = ColorRed;
{ {
S_Scope *scope = sprite_scope_begin(); S_Scope *scope = S_BeginScope();
S_Sheet *sheet = sprite_sheet_from_tag_await(scope, e->sprite); S_Sheet *sheet = S_SheetFromTagAwait(scope, e->sprite);
e->sprite_local_xform = XformFromTrs(.s = DivVec2(sheet->frame_size, PIXELS_PER_UNIT)); e->sprite_local_xform = XformFromTrs(.s = DivVec2(sheet->frame_size, PIXELS_PER_UNIT));
sprite_scope_end(scope); S_EndScope(scope);
} }
sim_ent_enable_prop(e, SEPROP_SOLID); sim_ent_enable_prop(e, SEPROP_SOLID);
@ -748,7 +748,7 @@ internal PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
{ {
Xform xf = XformFromTrs(TRS(.t = point, .r = RandF64FromState(&step_ctx->rand, 0, Tau))); Xform xf = XformFromTrs(TRS(.t = point, .r = RandF64FromState(&step_ctx->rand, 0, Tau)));
Ent *decal = sim_ent_alloc_sync_src(root); Ent *decal = sim_ent_alloc_sync_src(root);
decal->sprite = sprite_tag_from_path(Lit("sprite/blood.ase")); decal->sprite = S_TagFromPath(Lit("sprite/blood.ase"));
decal->sprite_tint = Rgba32F(1, 1, 1, 0.25f); decal->sprite_tint = Rgba32F(1, 1, 1, 0.25f);
decal->layer = SIM_LAYER_FLOOR_DECALS; decal->layer = SIM_LAYER_FLOOR_DECALS;
sim_ent_set_xform(decal, xf); sim_ent_set_xform(decal, xf);
@ -858,7 +858,7 @@ void sim_step(SimStepCtx *ctx)
world->sim_time_ns += world->sim_dt_ns; world->sim_time_ns += world->sim_dt_ns;
f32 sim_dt = SecondsFromNs(world->sim_dt_ns); f32 sim_dt = SecondsFromNs(world->sim_dt_ns);
S_Scope *sprite_frame_scope = sprite_scope_begin(); S_Scope *sprite_frame_scope = S_BeginScope();
Ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID); Ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
root->owner = world->client->player_id; root->owner = world->client->player_id;
@ -1166,13 +1166,13 @@ void sim_step(SimStepCtx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
Ent *ent = &world->ents[ent_index]; Ent *ent = &world->ents[ent_index];
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (sprite_tag_is_nil(ent->sprite)) continue; if (S_IsTagNil(ent->sprite)) continue;
S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite); S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, ent->sprite);
/* Update animation */ /* Update animation */
{ {
S_SheetSpan span = sprite_sheet_get_span(sheet, ent->sprite_span_name); S_Span span = S_SpanFromName(sheet, ent->sprite_span_name);
if (ent->animation_last_frame_change_time_ns == 0) { if (ent->animation_last_frame_change_time_ns == 0) {
ent->animation_last_frame_change_time_ns = SecondsFromNs(world->sim_time_ns); ent->animation_last_frame_change_time_ns = SecondsFromNs(world->sim_time_ns);
} }
@ -1184,7 +1184,7 @@ void sim_step(SimStepCtx *ctx)
} }
if (span.end > span.start) { if (span.end > span.start) {
S_SheetFrame frame = sprite_sheet_get_frame(sheet, frame_index); S_Frame frame = S_FrameFromIndex(sheet, frame_index);
while (time_in_frame > frame.duration) { while (time_in_frame > frame.duration) {
time_in_frame -= frame.duration; time_in_frame -= frame.duration;
++frame_index; ++frame_index;
@ -1192,7 +1192,7 @@ void sim_step(SimStepCtx *ctx)
/* Loop animation */ /* Loop animation */
frame_index = span.start; frame_index = span.start;
} }
frame = sprite_sheet_get_frame(sheet, frame_index); frame = S_FrameFromIndex(sheet, frame_index);
ent->animation_last_frame_change_time_ns = world->sim_time_ns; ent->animation_last_frame_change_time_ns = world->sim_time_ns;
} }
} }
@ -1203,7 +1203,7 @@ void sim_step(SimStepCtx *ctx)
#if 0 #if 0
/* Update sprite local xform */ /* Update sprite local xform */
{ {
S_SheetSlice slice = sprite_sheet_get_slice(sheet, Lit("pivot"), ent->animation_frame); S_Slice slice = S_SliceFromNameIndex(sheet, Lit("pivot"), ent->animation_frame);
Vec2 sprite_size = DivVec2(sheet->frame_size, (f32)PIXELS_PER_UNIT); Vec2 sprite_size = DivVec2(sheet->frame_size, (f32)PIXELS_PER_UNIT);
Vec2 dir = MulVec2Vec2(sprite_size, slice.dir); Vec2 dir = MulVec2Vec2(sprite_size, slice.dir);
@ -1221,7 +1221,7 @@ void sim_step(SimStepCtx *ctx)
if (ent->sprite_collider_slice.len > 0) { if (ent->sprite_collider_slice.len > 0) {
Xform cxf = ent->sprite_local_xform; Xform cxf = ent->sprite_local_xform;
S_SheetSlice slice = sprite_sheet_get_slice(sheet, ent->sprite_collider_slice, ent->animation_frame); S_Slice slice = S_SliceFromNameIndex(sheet, ent->sprite_collider_slice, ent->animation_frame);
ent->local_collider = CLD_ShapeFromQuad(MulXformQuad(cxf, QuadFromRect(slice.rect))); ent->local_collider = CLD_ShapeFromQuad(MulXformQuad(cxf, QuadFromRect(slice.rect)));
} }
@ -1272,11 +1272,11 @@ void sim_step(SimStepCtx *ctx)
Ent *parent = sim_ent_from_id(world, ent->parent); Ent *parent = sim_ent_from_id(world, ent->parent);
S_Tag parent_sprite = parent->sprite; S_Tag parent_sprite = parent->sprite;
S_Sheet *parent_sheet = sprite_sheet_from_tag_await(sprite_frame_scope, parent_sprite); S_Sheet *parent_sheet = S_SheetFromTagAwait(sprite_frame_scope, parent_sprite);
Xform parent_sprite_xf = parent->sprite_local_xform; Xform parent_sprite_xf = parent->sprite_local_xform;
S_SheetSlice attach_slice = sprite_sheet_get_slice(parent_sheet, ent->attach_slice, parent->animation_frame); S_Slice attach_slice = S_SliceFromNameIndex(parent_sheet, ent->attach_slice, parent->animation_frame);
Vec2 attach_pos = MulXformV2(parent_sprite_xf, attach_slice.center); Vec2 attach_pos = MulXformV2(parent_sprite_xf, attach_slice.center);
Vec2 attach_dir = MulXformBasisV2(parent_sprite_xf, attach_slice.dir); Vec2 attach_dir = MulXformBasisV2(parent_sprite_xf, attach_slice.dir);
@ -1350,9 +1350,9 @@ void sim_step(SimStepCtx *ctx)
if (primary_triggered) { if (primary_triggered) {
S_Tag sprite = ent->sprite; S_Tag sprite = ent->sprite;
u32 animation_frame = ent->animation_frame; u32 animation_frame = ent->animation_frame;
S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite); S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, sprite);
Xform sprite_local_xform = ent->sprite_local_xform; Xform sprite_local_xform = ent->sprite_local_xform;
S_SheetSlice out_slice = sprite_sheet_get_slice(sheet, Lit("out"), animation_frame); S_Slice out_slice = S_SliceFromNameIndex(sheet, Lit("out"), animation_frame);
Vec2 rel_pos = MulXformV2(sprite_local_xform, out_slice.center); Vec2 rel_pos = MulXformV2(sprite_local_xform, out_slice.center);
Vec2 rel_dir = MulXformBasisV2(sprite_local_xform, out_slice.dir); Vec2 rel_dir = MulXformBasisV2(sprite_local_xform, out_slice.dir);
@ -1375,7 +1375,7 @@ void sim_step(SimStepCtx *ctx)
bullet->local_collider.points[0] = VEC2(0, 0); bullet->local_collider.points[0] = VEC2(0, 0);
bullet->local_collider.count = 1; bullet->local_collider.count = 1;
#else #else
bullet->sprite = sprite_tag_from_path(Lit("sprite/bullet.ase")); bullet->sprite = S_TagFromPath(Lit("sprite/bullet.ase"));
bullet->sprite_collider_slice = Lit("shape"); bullet->sprite_collider_slice = Lit("shape");
#endif #endif
} }
@ -1397,9 +1397,9 @@ void sim_step(SimStepCtx *ctx)
if (primary_triggered) { if (primary_triggered) {
S_Tag sprite = ent->sprite; S_Tag sprite = ent->sprite;
u32 animation_frame = ent->animation_frame; u32 animation_frame = ent->animation_frame;
S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, sprite); S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, sprite);
Xform sprite_local_xform = ent->sprite_local_xform; Xform sprite_local_xform = ent->sprite_local_xform;
S_SheetSlice out_slice = sprite_sheet_get_slice(sheet, Lit("out"), animation_frame); S_Slice out_slice = S_SliceFromNameIndex(sheet, Lit("out"), animation_frame);
Vec2 rel_pos = MulXformV2(sprite_local_xform, out_slice.center); Vec2 rel_pos = MulXformV2(sprite_local_xform, out_slice.center);
Vec2 rel_dir = MulXformBasisV2(sprite_local_xform, out_slice.dir); Vec2 rel_dir = MulXformBasisV2(sprite_local_xform, out_slice.dir);
@ -1559,8 +1559,8 @@ void sim_step(SimStepCtx *ctx)
Vec2 sprite_hold_pos; Vec2 sprite_hold_pos;
Vec2 sprite_hold_dir; Vec2 sprite_hold_dir;
{ {
S_Sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite); S_Sheet *sheet = S_SheetFromTagAwait(sprite_frame_scope, ent->sprite);
S_SheetSlice slice = sprite_sheet_get_slice(sheet, Lit("attach.wep"), ent->animation_frame); S_Slice slice = S_SliceFromNameIndex(sheet, Lit("attach.wep"), ent->animation_frame);
sprite_hold_pos = slice.center; sprite_hold_pos = slice.center;
sprite_hold_dir = slice.dir; sprite_hold_dir = slice.dir;
} }
@ -1940,7 +1940,7 @@ void sim_step(SimStepCtx *ctx)
* End frame * End frame
* ========================== */ * ========================== */
sprite_scope_end(sprite_frame_scope); S_EndScope(sprite_frame_scope);
EndScratch(scratch); EndScratch(scratch);
} }

File diff suppressed because it is too large Load Diff

View File

@ -20,23 +20,23 @@ Struct(S_Texture)
}; };
//////////////////////////////// ////////////////////////////////
//~ Sheet //~ Sheet types
Struct(S_SheetFrame) Struct(S_Frame)
{ {
u32 index; u32 index;
f64 duration; f64 duration;
ClipRect clip; ClipRect clip;
}; };
Struct(S_SheetSpan) Struct(S_Span)
{ {
String name; String name;
u32 start; u32 start;
u32 end; u32 end;
}; };
Struct(S_SheetSlice) Struct(S_Slice)
{ {
/* If 1, this slice was not copied over from another frame in the sprite sheet */ /* If 1, this slice was not copied over from another frame in the sprite sheet */
b32 original; b32 original;
@ -55,10 +55,10 @@ Struct(S_SheetSlice)
Vec2 dir_px; Vec2 dir_px;
}; };
Struct(S_SheetSliceArray) Struct(S_SliceArray)
{ {
u64 count; u64 count;
S_SheetSlice *slices; S_Slice *slices;
}; };
Struct(S_SheetSliceGroup) Struct(S_SheetSliceGroup)
@ -68,7 +68,7 @@ Struct(S_SheetSliceGroup)
/* 2d array of slices with length (num frames) * (num slices per frame). /* 2d array of slices with length (num frames) * (num slices per frame).
* Index with [(frame index * num slices per frame) + slice index in frame] */ * Index with [(frame index * num slices per frame) + slice index in frame] */
S_SheetSlice *frame_slices; S_Slice *frame_slices;
}; };
Struct(S_Sheet) Struct(S_Sheet)
@ -79,10 +79,10 @@ Struct(S_Sheet)
Vec2 frame_size; Vec2 frame_size;
u32 frames_count; u32 frames_count;
S_SheetFrame *frames; S_Frame *frames;
u32 spans_count; u32 spans_count;
S_SheetSpan *spans; S_Span *spans;
Dict *spans_dict; Dict *spans_dict;
u32 slice_groups_count; u32 slice_groups_count;
@ -91,7 +91,7 @@ Struct(S_Sheet)
}; };
//////////////////////////////// ////////////////////////////////
//~ Cache //~ Cache types
typedef i32 S_CacheEntryKind; enum typedef i32 S_CacheEntryKind; enum
{ {
@ -165,7 +165,7 @@ Struct(S_Cache)
}; };
/* Represents a reference that can be used to safely access cache entry without it becoming evicted during the reference's lifetime */ /* Represents a reference that can be used to safely access cache entry without it becoming evicted during the reference's lifetime */
Struct(S_Ref) Struct(S_CacheEntryRef)
{ {
S_CacheEntry *e; S_CacheEntry *e;
}; };
@ -174,16 +174,16 @@ Struct(S_Ref)
//~ Scope //~ Scope
/* A cache reference whose lifetime is bound to the scope it was retrieved from */ /* A cache reference whose lifetime is bound to the scope it was retrieved from */
Struct(S_ScopeCacheRef) Struct(S_ScopeCacheEntryRef)
{ {
S_Ref ref; S_CacheEntryRef ref;
S_ScopeCacheRef *next_in_bin; S_ScopeCacheEntryRef *next_in_bin;
}; };
Struct(S_Scope) Struct(S_Scope)
{ {
S_ScopeCacheRef **ref_node_bins; S_ScopeCacheEntryRef **ref_node_bins;
S_ScopeCacheRef *ref_node_pool; S_ScopeCacheEntryRef *ref_node_pool;
u64 num_references; u64 num_references;
S_Scope *next_free; S_Scope *next_free;
}; };
@ -195,7 +195,7 @@ Struct(S_Cmd)
{ {
S_Cmd *next_free; S_Cmd *next_free;
S_Scope *scope; S_Scope *scope;
S_Ref ref; S_CacheEntryRef ref;
S_Tag tag; S_Tag tag;
u8 tag_path_buff[512]; u8 tag_path_buff[512];
}; };
@ -275,146 +275,96 @@ extern S_SharedState S_shared_state;
//~ Startup //~ Startup
Struct(S_StartupReceipt) { i32 _; }; Struct(S_StartupReceipt) { i32 _; };
S_StartupReceipt sprite_startup(void); S_StartupReceipt S_Startup(void);
////////////////////////////////
//~ Shutdown
P_ExitFuncDef(S_Shutdown);
////////////////////////////////
//~ Purple-black image
u32 *S_GeneratePurpleBlackImage(Arena *arena, u32 width, u32 height);
//////////////////////////////// ////////////////////////////////
//~ Tag operations //~ Tag operations
Inline S_Tag sprite_tag_nil(void) { return (S_Tag) { 0 }; } S_Tag S_TagFromPath(String path);
b32 S_IsTagNil(S_Tag tag);
b32 S_EqTag(S_Tag t1, S_Tag t2);
S_Hash S_CacheEntryFromTagHash(u64 tag_hash, S_CacheEntryKind kind);
S_Tag sprite_tag_from_path(String path); ////////////////////////////////
b32 sprite_tag_is_nil(S_Tag tag); //~ Sheet init
b32 sprite_tag_eq(S_Tag t1, S_Tag t2);
S_Sheet S_SheetFromAseResult(Arena *arena, ASE_DecodedSheet ase);
////////////////////////////////
//~ Load job
void S_PushLoadJob(S_CacheEntryRef ref, S_Tag tag);
P_JobDef(S_LoadSpriteJob, job);
////////////////////////////////
//~ Cache load operations
void S_LoadCacheEntryTexture(S_CacheEntryRef ref, S_Tag tag);
void S_LoadCacheEntrySheet(S_CacheEntryRef ref, S_Tag tag);
////////////////////////////////
//~ Ref operations
void S_AddRef(S_CacheEntry *e, i32 amount);
S_ScopeCacheEntryRef *S_EnsureRefUnsafely(S_Scope *scope, S_CacheEntry *e);
S_ScopeCacheEntryRef *S_EnsureRefFromEntryLocked(S_Scope *scope, S_CacheEntry *e, P_Lock *bin_lock);
S_ScopeCacheEntryRef *S_EnsureRefFromRef(S_Scope *scope, S_CacheEntryRef ref);
//////////////////////////////// ////////////////////////////////
//~ Scope operations //~ Scope operations
S_Scope *sprite_scope_begin(void); S_Scope *S_BeginScope(void);
void sprite_scope_end(S_Scope *scope); void S_EndScope(S_Scope *scope);
/* ========================== *
* Texture load
* ========================== */
/* ========================== *
* Cache structs
* ========================== */
/* ========================== *
* Purple-black image
* ========================== */
u32 *generate_purple_black_image(Arena *arena, u32 width, u32 height);
/* ========================== *
* Startup
* ========================== */
S_StartupReceipt sprite_startup(void);
P_ExitFuncDef(sprite_shutdown);
/* ========================== *
* Tag
* ========================== */
S_Tag sprite_tag_from_path(String path);
b32 sprite_tag_is_nil(S_Tag tag);
b32 sprite_tag_eq(S_Tag t1, S_Tag t2);
S_Hash cache_entry_hash_from_tag_hash(u64 tag_hash, S_CacheEntryKind kind);
/* ========================== *
* Load
* ========================== */
S_ScopeCacheRef *scope_ensure_ref_from_ref(S_Scope *scope, S_Ref ref);
void push_load_job(S_Ref ref, S_Tag tag);
void cache_entry_load_texture(S_Ref ref, S_Tag tag);
S_Sheet init_sheet_from_ase_result(Arena *arena, ASE_DecodedSheet ase);
void cache_entry_load_sheet(S_Ref ref, S_Tag tag);
/* ========================== *
* Scope
* ========================== */
void refcount_add(S_CacheEntry *e, i32 amount);
S_ScopeCacheRef *scope_ensure_ref_unsafe(S_Scope *scope, S_CacheEntry *e);
S_ScopeCacheRef *scope_ensure_ref_from_entry(S_Scope *scope, S_CacheEntry *e, P_Lock *bin_lock);
S_ScopeCacheRef *scope_ensure_ref_from_ref(S_Scope *scope, S_Ref ref);
S_Scope *sprite_scope_begin(void);
void sprite_scope_end(S_Scope *scope);
/* ========================== *
* Cache interface
* ========================== */
S_ScopeCacheRef *cache_lookup(S_Scope *scope, S_Hash hash, P_Lock *bin_lock);
S_ScopeCacheRef *cache_entry_from_tag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 force_new);
void *data_from_tag_internal(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await);
/* ========================== *
* Texture
* ========================== */
S_Texture *sprite_texture_from_tag_await(S_Scope *scope, S_Tag tag);
S_Texture *sprite_texture_from_tag_async(S_Scope *scope, S_Tag tag);
void sprite_texture_from_tag_prefetch(S_Scope *scope, S_Tag tag);
/* ========================== *
* Sheet
* ========================== */
S_Sheet *sprite_sheet_from_tag_await(S_Scope *scope, S_Tag tag);
S_Sheet *sprite_sheet_from_tag_async(S_Scope *scope, S_Tag tag);
void sprite_sheet_from_tag_prefetch(S_Scope *scope, S_Tag tag);
S_SheetFrame sprite_sheet_get_frame(S_Sheet *sheet, u32 index);
S_SheetSpan sprite_sheet_get_span(S_Sheet *sheet, String name);
/* Returns first slice with name in frame */
S_SheetSlice sprite_sheet_get_slice(S_Sheet *sheet, String name, u32 frame_index);
/* Returns all slices with name in frame */
S_SheetSliceArray sprite_sheet_get_slices(S_Sheet *sheet, String name, u32 frame_index);
/* ========================== *
* Load job
* ========================== */
P_JobDef(S_SpriteLoadJob, job);
//////////////////////////////// ////////////////////////////////
//~ Resource watch //~ Cache lookup operations
S_ScopeCacheEntryRef *S_EntryFromHashLocked(S_Scope *scope, S_Hash hash, P_Lock *bin_lock);
S_ScopeCacheEntryRef *S_EntryFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 force_new);
void *S_DataFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind, b32 await);
////////////////////////////////
//~ Texture retrieval operations
S_Texture *S_TextureFromTagAwait(S_Scope *scope, S_Tag tag);
S_Texture *S_TextureFromTagAsync(S_Scope *scope, S_Tag tag);
void S_PrefetchTextureFromTag(S_Scope *scope, S_Tag tag);
////////////////////////////////
//~ Sheet retrieval operations
S_Sheet *S_SheetFromTagAwait(S_Scope *scope, S_Tag tag);
S_Sheet *S_SheetFromTagAsync(S_Scope *scope, S_Tag tag);
void S_PrefetchSheetFromTag(S_Scope *scope, S_Tag tag);
////////////////////////////////
//~ Sheet data operations
S_Frame S_FrameFromIndex(S_Sheet *sheet, u32 index);
S_Span S_SpanFromName(S_Sheet *sheet, String name);
S_Slice S_SliceFromNameIndex(S_Sheet *sheet, String name, u32 frame_index);
S_SliceArray S_SlicesFromNameIndex(S_Sheet *sheet, String name, u32 frame_index);
////////////////////////////////
//~ Resource reload
#if RESOURCE_RELOADING #if RESOURCE_RELOADING
void S_ReloadSpriteFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind); void S_ReloadSpriteFromTag(S_Scope *scope, S_Tag tag, S_CacheEntryKind kind);
W_CallbackFuncDef(S_WatchSpriteCallback, name); W_CallbackFuncDef(S_WatchSpriteCallback, name);
#endif #endif
//////////////////////////////// ////////////////////////////////
//~ Evictor job //~ Evictor job
MergesortCompareFuncDef(S_EvictorSortCmp, arg_a, arg_b, udata); MergesortCompareFuncDef(S_EvictorSortCmp, arg_a, arg_b, udata);
P_JobDef(S_EvictorJob, _); P_JobDef(S_EvictorJob, _);

View File

@ -559,7 +559,7 @@ internal void user_update(P_Window *window)
G.real_time_ns += G.real_dt_ns; G.real_time_ns += G.real_dt_ns;
G.screen_size = P_GetWindowSize(window); G.screen_size = P_GetWindowSize(window);
S_Scope *sprite_frame_scope = sprite_scope_begin(); S_Scope *sprite_frame_scope = S_BeginScope();
/* ========================== * /* ========================== *
* Pull latest local sim snapshot * Pull latest local sim snapshot
@ -1161,7 +1161,7 @@ internal void user_update(P_Window *window)
for (u64 sorted_index = 0; sorted_index < sorted_count; ++sorted_index) { for (u64 sorted_index = 0; sorted_index < sorted_count; ++sorted_index) {
Ent *ent = sorted[sorted_index]; Ent *ent = sorted[sorted_index];
if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_is_valid_and_active(ent)) continue;
//if (sprite_tag_is_nil(ent->sprite)) continue; //if (S_IsTagNil(ent->sprite)) continue;
S_Tag sprite = ent->sprite; S_Tag sprite = ent->sprite;
@ -1219,16 +1219,16 @@ internal void user_update(P_Window *window)
#endif #endif
/* Draw sprite */ /* Draw sprite */
if (!sprite_tag_is_nil(sprite)) { if (!S_IsTagNil(sprite)) {
S_Sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite); S_Sheet *sheet = S_SheetFromTagAsync(sprite_frame_scope, sprite);
S_Texture *texture = sprite_texture_from_tag_async(sprite_frame_scope, sprite); S_Texture *texture = S_TextureFromTagAsync(sprite_frame_scope, sprite);
/* TODO: Fade in placeholder if texture isn't loaded */ /* TODO: Fade in placeholder if texture isn't loaded */
if (sheet->loaded && texture->loaded) { if (sheet->loaded && texture->loaded) {
b32 is_light = sim_ent_has_prop(ent, SEPROP_LIGHT_TEST); b32 is_light = sim_ent_has_prop(ent, SEPROP_LIGHT_TEST);
Vec3 emittance = ent->sprite_emittance; Vec3 emittance = ent->sprite_emittance;
u32 tint = ent->sprite_tint; u32 tint = ent->sprite_tint;
S_SheetFrame frame = sprite_sheet_get_frame(sheet, ent->animation_frame); S_Frame frame = S_FrameFromIndex(sheet, ent->animation_frame);
D_MaterialParams params = D_MATERIALPARAMS(.xf = sprite_xform, .texture = texture->gp_texture, .tint = tint, .clip = frame.clip, .is_light = is_light, .light_emittance = emittance); D_MaterialParams params = D_MATERIALPARAMS(.xf = sprite_xform, .texture = texture->gp_texture, .tint = tint, .clip = frame.clip, .is_light = is_light, .light_emittance = emittance);
D_DrawMaterial(G.render_sig, params); D_DrawMaterial(G.render_sig, params);
} }
@ -1238,8 +1238,8 @@ internal void user_update(P_Window *window)
/* TODO: Something better */ /* TODO: Something better */
if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) { if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) {
Vec2I32 chunk_index = ent->tile_chunk_index; Vec2I32 chunk_index = ent->tile_chunk_index;
S_Tag tile_sprite = sprite_tag_from_path(Lit("sprite/tile.ase")); S_Tag tile_sprite = S_TagFromPath(Lit("sprite/tile.ase"));
S_Texture *tile_texture = sprite_texture_from_tag_async(sprite_frame_scope, tile_sprite); S_Texture *tile_texture = S_TextureFromTagAsync(sprite_frame_scope, tile_sprite);
if (tile_texture->loaded) { if (tile_texture->loaded) {
f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT; f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT;
for (i32 tile_y = 0; tile_y < SIM_TILES_PER_CHUNK_SQRT; ++tile_y) { for (i32 tile_y = 0; tile_y < SIM_TILES_PER_CHUNK_SQRT; ++tile_y) {
@ -1286,8 +1286,8 @@ internal void user_update(P_Window *window)
/* Draw focus arrow */ /* Draw focus arrow */
if (ent == local_control || sim_ent_id_eq(ent->id, G.debug_following)) { if (ent == local_control || sim_ent_id_eq(ent->id, G.debug_following)) {
S_Sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite); S_Sheet *sheet = S_SheetFromTagAsync(sprite_frame_scope, ent->sprite);
S_SheetSlice slice = sprite_sheet_get_slice(sheet, Lit("attach.wep"), ent->animation_frame); S_Slice slice = S_SliceFromNameIndex(sheet, Lit("attach.wep"), ent->animation_frame);
Vec2 start = MulXformV2(sprite_xform, slice.center); Vec2 start = MulXformV2(sprite_xform, slice.center);
start = MulXformV2(G.world_to_ui_xf, start); start = MulXformV2(G.world_to_ui_xf, start);
Vec2 end = AddVec2(xf.og, ent->control.focus); Vec2 end = AddVec2(xf.og, ent->control.focus);
@ -1297,8 +1297,8 @@ internal void user_update(P_Window *window)
#if 0 #if 0
/* Draw slices */ /* Draw slices */
if (!sprite_tag_is_nil(ent->sprite)) { if (!S_IsTagNil(ent->sprite)) {
S_Sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, sprite); S_Sheet *sheet = S_SheetFromTagAsync(sprite_frame_scope, sprite);
u32 quad_color = Rgba32F(1, 0, 0.5, 1); u32 quad_color = Rgba32F(1, 0, 0.5, 1);
u32 point_color = Rgba32F(1, 0, 0, 1); u32 point_color = Rgba32F(1, 0, 0, 1);
@ -1309,7 +1309,7 @@ internal void user_update(P_Window *window)
if (StringEndsWith(group->name, Lit(".ray"))) continue; if (StringEndsWith(group->name, Lit(".ray"))) continue;
for (u32 j = 0; j < group->per_frame_count; ++j) { for (u32 j = 0; j < group->per_frame_count; ++j) {
S_SheetSlice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j]; S_Slice slice = group->frame_slices[(ent->animation_frame * group->per_frame_count) + j];
Vec2 center = MulXformV2(sprite_xform, slice.center); Vec2 center = MulXformV2(sprite_xform, slice.center);
center = MulXformV2(G.world_to_ui_xf, center); center = MulXformV2(G.world_to_ui_xf, center);
@ -1690,8 +1690,8 @@ internal void user_update(P_Window *window)
if (!G.debug_camera) { if (!G.debug_camera) {
__profn("Draw crosshair"); __profn("Draw crosshair");
Vec2 crosshair_pos = G.ui_cursor; Vec2 crosshair_pos = G.ui_cursor;
S_Tag crosshair = sprite_tag_from_path(Lit("sprite/crosshair.ase")); S_Tag crosshair = S_TagFromPath(Lit("sprite/crosshair.ase"));
S_Texture *t = sprite_texture_from_tag_async(sprite_frame_scope, crosshair); S_Texture *t = S_TextureFromTagAsync(sprite_frame_scope, crosshair);
Vec2 size = VEC2(t->width, t->height); Vec2 size = VEC2(t->width, t->height);
Xform xf = XformFromTrs(TRS(.t = crosshair_pos, .s = size)); Xform xf = XformFromTrs(TRS(.t = crosshair_pos, .s = size));
D_DrawUiRect(G.render_sig, D_UIRECTPARAMS(.xf = xf, .texture = t->gp_texture)); D_DrawUiRect(G.render_sig, D_UIRECTPARAMS(.xf = xf, .texture = t->gp_texture));
@ -1705,7 +1705,7 @@ internal void user_update(P_Window *window)
P_DisableWindoweCursorClip(G.window); P_DisableWindoweCursorClip(G.window);
P_ShowWindowCursor(G.window); P_ShowWindowCursor(G.window);
} else { } else {
S_Texture *t = sprite_texture_from_tag_async(sprite_frame_scope, sprite_tag_from_path(Lit("sprite/crosshair.ase"))); S_Texture *t = S_TextureFromTagAsync(sprite_frame_scope, S_TagFromPath(Lit("sprite/crosshair.ase")));
Vec2 size = VEC2(t->width, t->height); Vec2 size = VEC2(t->width, t->height);
Rect cursor_clip = RectFromVec2(G.ui_screen_offset, G.ui_size); Rect cursor_clip = RectFromVec2(G.ui_screen_offset, G.ui_size);
cursor_clip.pos = AddVec2(cursor_clip.pos, MulVec2(size, 0.5f)); cursor_clip.pos = AddVec2(cursor_clip.pos, MulVec2(size, 0.5f));
@ -2073,7 +2073,7 @@ internal void user_update(P_Window *window)
* End frame cache scopes * End frame cache scopes
* ========================== */ * ========================== */
sprite_scope_end(sprite_frame_scope); S_EndScope(sprite_frame_scope);
EndScratch(scratch); EndScratch(scratch);
} }