sprite layer refactor
This commit is contained in:
parent
938f4e701c
commit
82c81a6280
@ -21,13 +21,13 @@ if not exist meta.exe (
|
|||||||
)
|
)
|
||||||
|
|
||||||
::- Program build
|
::- Program build
|
||||||
if not "%norun%"=="1" (
|
if not "%nobuild%"=="1" (
|
||||||
echo ======== Build ========
|
echo ======== Build ========
|
||||||
%program_build_cmd%
|
%program_build_cmd%
|
||||||
set "rc=!errorlevel!"
|
set "rc=!errorlevel!"
|
||||||
if !rc! NEQ 0 (
|
if !rc! NEQ 0 (
|
||||||
if !rc! EQU %meta_rebuild_code% (
|
|
||||||
del meta.exe
|
del meta.exe
|
||||||
|
if !rc! EQU %meta_rebuild_code% (
|
||||||
goto meta_build
|
goto meta_build
|
||||||
)
|
)
|
||||||
exit /b !rc!
|
exit /b !rc!
|
||||||
|
|||||||
@ -791,6 +791,12 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
|||||||
ASE_Header ase_header;
|
ASE_Header ase_header;
|
||||||
BB_ReadBytes(&br, StringFromStruct(&ase_header));
|
BB_ReadBytes(&br, StringFromStruct(&ase_header));
|
||||||
|
|
||||||
|
if (ase_header.magic != 0xA5E0)
|
||||||
|
{
|
||||||
|
ASE_PushError(arena, &result.errors, Lit("Not a valid aseprite file"));
|
||||||
|
goto abort;
|
||||||
|
}
|
||||||
|
|
||||||
u64 frame_width = ase_header.width;
|
u64 frame_width = ase_header.width;
|
||||||
u64 frame_height = ase_header.height;
|
u64 frame_height = ase_header.height;
|
||||||
|
|
||||||
@ -801,13 +807,13 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
|||||||
ASE_MakeDimensionsSquareish(&ase_header, &frames_x, &frames_y, &image_width, &image_height);
|
ASE_MakeDimensionsSquareish(&ase_header, &frames_x, &frames_y, &image_width, &image_height);
|
||||||
|
|
||||||
u32 num_frames = 0;
|
u32 num_frames = 0;
|
||||||
ASE_Frame *frame_head = 0;
|
ASE_Frame *first_frame = 0;
|
||||||
|
|
||||||
u32 num_spans = 0;
|
u32 num_spans = 0;
|
||||||
ASE_Span *span_head = 0;
|
ASE_Span *first_span = 0;
|
||||||
|
|
||||||
u32 num_slice_keys = 0;
|
u32 num_slice_keys = 0;
|
||||||
ASE_SliceKey *slice_key_head = 0;
|
ASE_SliceKey *first_slice_key = 0;
|
||||||
|
|
||||||
//- Iterate frames
|
//- Iterate frames
|
||||||
for (u16 i = 0; i < ase_header.frames; ++i)
|
for (u16 i = 0; i < ase_header.frames; ++i)
|
||||||
@ -823,8 +829,8 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ASE_Frame *frame = PushStruct(arena, ASE_Frame);
|
ASE_Frame *frame = PushStruct(arena, ASE_Frame);
|
||||||
frame->next = frame_head;
|
frame->next = first_frame;
|
||||||
frame_head = frame;
|
first_frame = frame;
|
||||||
|
|
||||||
frame->index = i;
|
frame->index = i;
|
||||||
frame->duration = frame_header.frame_duration_ms / 1000.0;
|
frame->duration = frame_header.frame_duration_ms / 1000.0;
|
||||||
@ -872,8 +878,8 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
|||||||
for (u16 k = 0; k < frame_span_count; ++k)
|
for (u16 k = 0; k < frame_span_count; ++k)
|
||||||
{
|
{
|
||||||
ASE_Span *span = PushStruct(arena, ASE_Span);
|
ASE_Span *span = PushStruct(arena, ASE_Span);
|
||||||
span->next = span_head;
|
span->next = first_span;
|
||||||
span_head = span;
|
first_span = span;
|
||||||
|
|
||||||
span->start = BB_ReadUBits(&br, 16);
|
span->start = BB_ReadUBits(&br, 16);
|
||||||
span->end = BB_ReadUBits(&br, 16);
|
span->end = BB_ReadUBits(&br, 16);
|
||||||
@ -892,8 +898,8 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
|||||||
case ASE_ChunkKind_Slice:
|
case ASE_ChunkKind_Slice:
|
||||||
{
|
{
|
||||||
ASE_SliceKey *slice_key = PushStruct(arena, ASE_SliceKey);
|
ASE_SliceKey *slice_key = PushStruct(arena, ASE_SliceKey);
|
||||||
slice_key->next = slice_key_head;
|
slice_key->next = first_slice_key;
|
||||||
slice_key_head = slice_key;
|
first_slice_key = slice_key;
|
||||||
|
|
||||||
u32 num_slices = BB_ReadUBits(&br, 32);
|
u32 num_slices = BB_ReadUBits(&br, 32);
|
||||||
slice_key->num_slices = num_slices;
|
slice_key->num_slices = num_slices;
|
||||||
@ -908,8 +914,8 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
|||||||
for (u32 k = 0; k < num_slices; ++k)
|
for (u32 k = 0; k < num_slices; ++k)
|
||||||
{
|
{
|
||||||
ASE_Slice *slice = PushStruct(arena, ASE_Slice);
|
ASE_Slice *slice = PushStruct(arena, ASE_Slice);
|
||||||
slice->next = slice_key->slice_head;
|
slice->next = slice_key->first_slice;
|
||||||
slice_key->slice_head = slice;
|
slice_key->first_slice = slice;
|
||||||
|
|
||||||
u32 start = BB_ReadUBits(&br, 32);
|
u32 start = BB_ReadUBits(&br, 32);
|
||||||
i32 x = BB_ReadIBits(&br, 32);
|
i32 x = BB_ReadIBits(&br, 32);
|
||||||
@ -952,9 +958,11 @@ ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded)
|
|||||||
result.num_frames = num_frames;
|
result.num_frames = num_frames;
|
||||||
result.num_spans = num_spans;
|
result.num_spans = num_spans;
|
||||||
result.num_slice_keys = num_slice_keys;
|
result.num_slice_keys = num_slice_keys;
|
||||||
result.frame_head = frame_head;
|
result.first_frame = first_frame;
|
||||||
result.span_head = span_head;
|
result.first_span = first_span;
|
||||||
result.slice_key_head = slice_key_head;
|
result.first_slice_key = first_slice_key;
|
||||||
|
|
||||||
|
abort:
|
||||||
|
|
||||||
if (result.errors.count <= 0)
|
if (result.errors.count <= 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -34,7 +34,7 @@ Struct(ASE_SliceKey)
|
|||||||
{
|
{
|
||||||
String name;
|
String name;
|
||||||
u32 num_slices;
|
u32 num_slices;
|
||||||
ASE_Slice *slice_head;
|
ASE_Slice *first_slice;
|
||||||
ASE_SliceKey *next;
|
ASE_SliceKey *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -70,9 +70,9 @@ Struct(ASE_DecodedSheet)
|
|||||||
u32 num_frames;
|
u32 num_frames;
|
||||||
u32 num_spans;
|
u32 num_spans;
|
||||||
u32 num_slice_keys;
|
u32 num_slice_keys;
|
||||||
ASE_Frame *frame_head;
|
ASE_Frame *first_frame;
|
||||||
ASE_Span *span_head;
|
ASE_Span *first_span;
|
||||||
ASE_SliceKey *slice_key_head;
|
ASE_SliceKey *first_slice_key;
|
||||||
ASE_ErrorList errors;
|
ASE_ErrorList errors;
|
||||||
b32 success;
|
b32 success;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -279,35 +279,35 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t);
|
|||||||
|
|
||||||
//- Singly linked list stack (first & next pointers)
|
//- Singly linked list stack (first & next pointers)
|
||||||
|
|
||||||
#define StackPush_N(f,n,next) ((n)->next=(f), (f)=(n))
|
#define StackPushN(f,n,next) ((n)->next=(f), (f)=(n))
|
||||||
#define StackPop_N(f,next) ((f)=(f)->next)
|
#define StackPopN(f,next) ((f)=(f)->next)
|
||||||
#define StackPush(f,n) StackPush_N(f,n,next)
|
#define StackPush(f,n) StackPushN(f,n,next)
|
||||||
#define StackPop(f) StackPop_N(f,next)
|
#define StackPop(f) StackPopN(f,next)
|
||||||
|
|
||||||
//- Singly linked list queue (first, last, & next pointers)
|
//- Singly linked list queue (first, last, & next pointers)
|
||||||
|
|
||||||
#define QueuePush_NZ(nil,f,l,n,next) (CheckNil(nil,f) ? \
|
#define QueuePushNZ(nil,f,l,n,next) (CheckNil(nil,f) ? \
|
||||||
((f)=(l)=(n),SetNil(nil,(n)->next)) : \
|
((f)=(l)=(n),SetNil(nil,(n)->next)) : \
|
||||||
((l)->next=(n),(l)=(n),SetNil(nil,(n)->next)))
|
((l)->next=(n),(l)=(n),SetNil(nil,(n)->next)))
|
||||||
|
|
||||||
#define QueuePushFront_NZ(nil,f,l,n,next) (CheckNil(nil,f) ? \
|
#define QueuePushFrontNZ(nil,f,l,n,next) (CheckNil(nil,f) ? \
|
||||||
((f)=(l)=(n),SetNil(nil,(n)->next)) : \
|
((f)=(l)=(n),SetNil(nil,(n)->next)) : \
|
||||||
((n)->next=(f),(f)=(n)))
|
((n)->next=(f),(f)=(n)))
|
||||||
|
|
||||||
#define QueuePop_NZ(nil,f,l,next) ((f)==(l) ? \
|
#define QueuePopNZ(nil,f,l,next) ((f)==(l) ? \
|
||||||
(SetNil(nil,f),SetNil(nil,l)) : \
|
(SetNil(nil,f),SetNil(nil,l)) : \
|
||||||
((f)=(f)->next))
|
((f)=(f)->next))
|
||||||
|
|
||||||
#define QueuePush_N(f,l,n,next) QueuePush_NZ(0,f,l,n,next)
|
#define QueuePushN(f,l,n,next) QueuePushNZ(0,f,l,n,next)
|
||||||
#define QueuePushFront_N(f,l,n,next) QueuePushFront_NZ(0,f,l,n,next)
|
#define QueuePushFrontN(f,l,n,next) QueuePushFrontNZ(0,f,l,n,next)
|
||||||
#define QueuePop_N(f,l,next) QueuePop_NZ(0,f,l,next)
|
#define QueuePopN(f,l,next) QueuePopNZ(0,f,l,next)
|
||||||
#define QueuePush(f,l,n) QueuePush_NZ(0,f,l,n,next)
|
#define QueuePush(f,l,n) QueuePushNZ(0,f,l,n,next)
|
||||||
#define QueuePushFront(f,l,n) QueuePushFront_NZ(0,f,l,n,next)
|
#define QueuePushFront(f,l,n) QueuePushFrontNZ(0,f,l,n,next)
|
||||||
#define QueuePop(f,l) QueuePop_NZ(0,f,l,next)
|
#define QueuePop(f,l) QueuePopNZ(0,f,l,next)
|
||||||
|
|
||||||
//- Doubly linked list (first, last, next, & prev pointers)
|
//- Doubly linked list (first, last, next, & prev pointers)
|
||||||
|
|
||||||
#define DllInsert_NPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \
|
#define DllInsertNPZ(nil,f,l,p,n,next,prev) (CheckNil(nil,f) ? \
|
||||||
((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) : \
|
((f) = (l) = (n), SetNil(nil,(n)->next), SetNil(nil,(n)->prev)) : \
|
||||||
CheckNil(nil,p) ? \
|
CheckNil(nil,p) ? \
|
||||||
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) : \
|
((n)->next = (f), (f)->prev = (n), (f) = (n), SetNil(nil,(n)->prev)) : \
|
||||||
@ -315,23 +315,23 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t);
|
|||||||
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) : \
|
((l)->next = (n), (n)->prev = (l), (l) = (n), SetNil(nil, (n)->next)) : \
|
||||||
(((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p))))
|
(((!CheckNil(nil,p) && CheckNil(nil,(p)->next)) ? (0) : ((p)->next->prev = (n))), ((n)->next = (p)->next), ((p)->next = (n)), ((n)->prev = (p))))
|
||||||
|
|
||||||
#define DllRemove_NPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)), \
|
#define DllRemoveNPZ(nil,f,l,n,next,prev) (((n) == (f) ? (f) = (n)->next : (0)), \
|
||||||
((n) == (l) ? (l) = (l)->prev : (0)), \
|
((n) == (l) ? (l) = (l)->prev : (0)), \
|
||||||
(CheckNil(nil,(n)->prev) ? (0) : \
|
(CheckNil(nil,(n)->prev) ? (0) : \
|
||||||
((n)->prev->next = (n)->next)), \
|
((n)->prev->next = (n)->next)), \
|
||||||
(CheckNil(nil,(n)->next) ? (0) : \
|
(CheckNil(nil,(n)->next) ? (0) : \
|
||||||
((n)->next->prev = (n)->prev)))
|
((n)->next->prev = (n)->prev)))
|
||||||
|
|
||||||
#define DllPushBack_NPZ(nil,f,l,n,next,prev) DllInsert_NPZ(nil,f,l,l,n,next,prev)
|
#define DllPushBackNPZ(nil,f,l,n,next,prev) DllInsertNPZ(nil,f,l,l,n,next,prev)
|
||||||
#define DllPushFront_NPZ(nil,f,l,n,next,prev) DllInsert_NPZ(nil,l,f,f,n,prev,next)
|
#define DllPushFrontNPZ(nil,f,l,n,next,prev) DllInsertNPZ(nil,l,f,f,n,prev,next)
|
||||||
#define DllInsert_NP(f,l,p,n,next,prev) DllInsert_NPZ(0,f,l,p,n,next,prev)
|
#define DllInsertNP(f,l,p,n,next,prev) DllInsertNPZ(0,f,l,p,n,next,prev)
|
||||||
#define DllPushBack_NP(f,l,n,next,prev) DllPushBack_NPZ(0,f,l,n,next,prev)
|
#define DllPushBackNP(f,l,n,next,prev) DllPushBackNPZ(0,f,l,n,next,prev)
|
||||||
#define DllPushFront_NP(f,l,n,next,prev) DllPushFront_NPZ(0,f,l,n,next,prev)
|
#define DllPushFrontNP(f,l,n,next,prev) DllPushFrontNPZ(0,f,l,n,next,prev)
|
||||||
#define DllRemove_NP(f,l,n,next,prev) DllRemove_NPZ(0,f,l,n,next,prev)
|
#define DllRemoveNP(f,l,n,next,prev) DllRemoveNPZ(0,f,l,n,next,prev)
|
||||||
#define DllInsert(f,l,p,n) DllInsert_NPZ(0,f,l,p,n,next,prev)
|
#define DllInsert(f,l,p,n) DllInsertNPZ(0,f,l,p,n,next,prev)
|
||||||
#define DllPushBack(f,l,n) DllPushBack_NPZ(0,f,l,n,next,prev)
|
#define DllPushBack(f,l,n) DllPushBackNPZ(0,f,l,n,next,prev)
|
||||||
#define DllPushFront(f,l,n) DllPushFront_NPZ(0,f,l,n,next,prev)
|
#define DllPushFront(f,l,n) DllPushFrontNPZ(0,f,l,n,next,prev)
|
||||||
#define DllRemove(f,l,n) DllRemove_NPZ(0,f,l,n,next,prev)
|
#define DllRemove(f,l,n) DllRemoveNPZ(0,f,l,n,next,prev)
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Color helper macros
|
//~ Color helper macros
|
||||||
|
|||||||
@ -29,7 +29,7 @@ Struct(TempArena)
|
|||||||
|
|
||||||
#define ScratchArenasPerCtx 2
|
#define ScratchArenasPerCtx 2
|
||||||
|
|
||||||
Struct(ArenaCtx)
|
Struct(FiberArenaCtx)
|
||||||
{
|
{
|
||||||
Arena *perm_arena;
|
Arena *perm_arena;
|
||||||
Arena *scratch_arenas[ScratchArenasPerCtx];
|
Arena *scratch_arenas[ScratchArenasPerCtx];
|
||||||
@ -40,7 +40,7 @@ Struct(ArenaCtx)
|
|||||||
|
|
||||||
Struct(SharedArenaCtx)
|
Struct(SharedArenaCtx)
|
||||||
{
|
{
|
||||||
ArenaCtx arena_contexts[MaxFibers];
|
FiberArenaCtx arena_contexts[MaxFibers];
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SharedArenaCtx shared_arena_ctx;
|
extern SharedArenaCtx shared_arena_ctx;
|
||||||
@ -176,12 +176,12 @@ Inline void EndTempArena(TempArena temp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Arena ctx operations
|
//~ Fiber arena ctx operations
|
||||||
|
|
||||||
Inline ArenaCtx *ArenaCtxFromFiberId(i16 fiber_id)
|
Inline FiberArenaCtx *FiberArenaCtxFromId(i16 fiber_id)
|
||||||
{
|
{
|
||||||
SharedArenaCtx *g = &shared_arena_ctx;
|
SharedArenaCtx *g = &shared_arena_ctx;
|
||||||
ArenaCtx *ctx = &g->arena_contexts[fiber_id];
|
FiberArenaCtx *ctx = &g->arena_contexts[fiber_id];
|
||||||
if (!ctx->perm_arena)
|
if (!ctx->perm_arena)
|
||||||
{
|
{
|
||||||
__profn("Initialize fiber arena ctx");
|
__profn("Initialize fiber arena ctx");
|
||||||
@ -194,7 +194,7 @@ Inline ArenaCtx *ArenaCtxFromFiberId(i16 fiber_id)
|
|||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define PermArena (ArenaCtxFromFiberId(FiberId())->perm_arena)
|
#define PermArena() (FiberArenaCtxFromId(FiberId())->perm_arena)
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Scratch helpers
|
//~ Scratch helpers
|
||||||
@ -215,7 +215,7 @@ Inline TempArena BeginScratch(Arena *potential_conflict)
|
|||||||
/* Use `BeginScratchNoConflict` if no conflicts are present */
|
/* Use `BeginScratchNoConflict` if no conflicts are present */
|
||||||
Assert(potential_conflict != 0);
|
Assert(potential_conflict != 0);
|
||||||
|
|
||||||
ArenaCtx *ctx = ArenaCtxFromFiberId(FiberId());
|
FiberArenaCtx *ctx = FiberArenaCtxFromId(FiberId());
|
||||||
Arena *scratch_arena = ctx->scratch_arenas[0];
|
Arena *scratch_arena = ctx->scratch_arenas[0];
|
||||||
if (scratch_arena == potential_conflict)
|
if (scratch_arena == potential_conflict)
|
||||||
{
|
{
|
||||||
@ -239,7 +239,7 @@ Inline TempArena BeginScratch(Arena *potential_conflict)
|
|||||||
|
|
||||||
Inline TempArena BeginScratchNoConflict_(void)
|
Inline TempArena BeginScratchNoConflict_(void)
|
||||||
{
|
{
|
||||||
ArenaCtx *ctx = ArenaCtxFromFiberId(FiberId());
|
FiberArenaCtx *ctx = FiberArenaCtxFromId(FiberId());
|
||||||
Arena *scratch_arena = ctx->scratch_arenas[0];
|
Arena *scratch_arena = ctx->scratch_arenas[0];
|
||||||
TempArena temp = BeginTempArena(scratch_arena);
|
TempArena temp = BeginTempArena(scratch_arena);
|
||||||
return temp;
|
return temp;
|
||||||
|
|||||||
@ -140,10 +140,10 @@ void BB_WriteAlignToNextByte(BB_Writer *bw)
|
|||||||
bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7;
|
bw->cur_bit += (8 - (bw->cur_bit & 7)) & 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BB_WriteAlign(BB_Writer *bw, u64 align)
|
void BB_WriteAlignByte(BB_Writer *bw, u64 align)
|
||||||
{
|
{
|
||||||
BB_WriteAlignToNextByte(bw);
|
BB_WriteAlignToNextByte(bw);
|
||||||
BB_WriteDebugMagic(bw, BB_DebugMagicKind_Align, align);
|
BB_WriteDebugMagic(bw, BB_DebugMagicKind_AlignByte, align);
|
||||||
if (align > 0)
|
if (align > 0)
|
||||||
{
|
{
|
||||||
u64 new_pos = (bw->cur_bit >> 3);
|
u64 new_pos = (bw->cur_bit >> 3);
|
||||||
@ -471,10 +471,10 @@ void BB_ReadAlignToNextByte(BB_Reader *br)
|
|||||||
br->cur_bit += (8 - (br->cur_bit & 7)) & 7;
|
br->cur_bit += (8 - (br->cur_bit & 7)) & 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BB_ReadAlign(BB_Reader *br, u64 align)
|
void BB_ReadAlignByte(BB_Reader *br, u64 align)
|
||||||
{
|
{
|
||||||
BB_ReadAlignToNextByte(br);
|
BB_ReadAlignToNextByte(br);
|
||||||
BB_ReadDebugMagic(br, BB_DebugMagicKind_Align, align);
|
BB_ReadDebugMagic(br, BB_DebugMagicKind_AlignByte, align);
|
||||||
if (align > 0)
|
if (align > 0)
|
||||||
{
|
{
|
||||||
u64 new_pos = (br->cur_bit >> 3);
|
u64 new_pos = (br->cur_bit >> 3);
|
||||||
|
|||||||
@ -47,7 +47,7 @@ Struct(BB_Reader)
|
|||||||
/* Magic numbers inserted to verify read/write type & length */
|
/* Magic numbers inserted to verify read/write type & length */
|
||||||
Enum(BB_DebugMagicKind)
|
Enum(BB_DebugMagicKind)
|
||||||
{
|
{
|
||||||
BB_DebugMagicKind_Align = 0x20A4,
|
BB_DebugMagicKind_AlignByte = 0x20A4,
|
||||||
BB_DebugMagicKind_AlignToNextByte = 0x379A,
|
BB_DebugMagicKind_AlignToNextByte = 0x379A,
|
||||||
BB_DebugMagicKind_UBits = 0xCB4A,
|
BB_DebugMagicKind_UBits = 0xCB4A,
|
||||||
BB_DebugMagicKind_IBits = 0xB30D,
|
BB_DebugMagicKind_IBits = 0xB30D,
|
||||||
@ -90,7 +90,7 @@ b32 BB_CheckWriterOverflowBits(BB_Writer *bw, u64 num_bits);
|
|||||||
|
|
||||||
//- Align
|
//- Align
|
||||||
void BB_WriteAlignToNextByte(BB_Writer *bw);
|
void BB_WriteAlignToNextByte(BB_Writer *bw);
|
||||||
void BB_WriteAlign(BB_Writer *bw, u64 align);
|
void BB_WriteAlignByte(BB_Writer *bw, u64 align);
|
||||||
|
|
||||||
//- Bits
|
//- Bits
|
||||||
void BB_WriteUBitsNoMagic(BB_Writer *bw, u64 value, u8 num_bits);
|
void BB_WriteUBitsNoMagic(BB_Writer *bw, u64 value, u8 num_bits);
|
||||||
@ -144,7 +144,7 @@ b32 BB_CheckReaderOverflowBits(BB_Reader *br, u64 num_bits);
|
|||||||
|
|
||||||
//- Align
|
//- Align
|
||||||
void BB_ReadAlignToNextByte(BB_Reader *br);
|
void BB_ReadAlignToNextByte(BB_Reader *br);
|
||||||
void BB_ReadAlign(BB_Reader *br, u64 align);
|
void BB_ReadAlignByte(BB_Reader *br, u64 align);
|
||||||
|
|
||||||
//- Bits
|
//- Bits
|
||||||
u64 BB_ReadUBitsNoMagic(BB_Reader *br, u8 num_bits);
|
u64 BB_ReadUBitsNoMagic(BB_Reader *br, u8 num_bits);
|
||||||
|
|||||||
@ -5,8 +5,10 @@ SharedResourceState shared_resource_state = ZI;
|
|||||||
|
|
||||||
void InitBaseResources(String archive)
|
void InitBaseResources(String archive)
|
||||||
{
|
{
|
||||||
|
if (archive.len > 0)
|
||||||
|
{
|
||||||
SharedResourceState *g = &shared_resource_state;
|
SharedResourceState *g = &shared_resource_state;
|
||||||
if (archive.len <= 0) return;
|
Arena *perm = PermArena();
|
||||||
|
|
||||||
BB_Buff bb = BB_BuffFromString(archive);
|
BB_Buff bb = BB_BuffFromString(archive);
|
||||||
BB_Reader br = BB_ReaderFromBuff(&bb);
|
BB_Reader br = BB_ReaderFromBuff(&bb);
|
||||||
@ -23,16 +25,17 @@ void InitBaseResources(String archive)
|
|||||||
u64 data_start = BB_ReadUBits(&br, 64);
|
u64 data_start = BB_ReadUBits(&br, 64);
|
||||||
u64 data_len = BB_ReadUBits(&br, 64);
|
u64 data_len = BB_ReadUBits(&br, 64);
|
||||||
|
|
||||||
ResourceEntry *entry = PushStruct(PermArena, ResourceEntry);
|
ResourceEntry *entry = PushStruct(perm, ResourceEntry);
|
||||||
entry->name = STRING(name_len, archive.text + name_start);
|
entry->name = STRING(name_len, archive.text + name_start);
|
||||||
entry->data = STRING(data_len, archive.text + data_start);
|
entry->data = STRING(data_len, archive.text + data_start);
|
||||||
entry->hash = HashFnv64(Fnv64Basis, entry->name);
|
entry->hash = HashFnv64(Fnv64Basis, entry->name);
|
||||||
|
|
||||||
ResourceEntryBin *bin = &g->bins[entry->hash % NumResourceEntryBins];
|
ResourceEntryBin *bin = &g->bins[entry->hash % NumResourceEntryBins];
|
||||||
QueuePush_N(bin->first, bin->last, entry, next_in_bin);
|
QueuePushN(bin->first, bin->last, entry, next_in_bin);
|
||||||
QueuePush_N(g->first_entry, g->last_entry, entry, next);
|
QueuePushN(g->first_entry, g->last_entry, entry, next);
|
||||||
}
|
}
|
||||||
g->entries_count = num_entries;
|
g->entries_count = num_entries;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
|
|||||||
@ -477,8 +477,9 @@ void StartupMeta(void)
|
|||||||
|
|
||||||
//- Generate archive file
|
//- Generate archive file
|
||||||
String arc_out_file = F_GetFull(arena, Lit("resources.arc"));
|
String arc_out_file = F_GetFull(arena, Lit("resources.arc"));
|
||||||
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
EchoLine(Lit("[Building ARC]"));
|
EchoLine(Lit("[Creating archive]"));
|
||||||
Struct(EntryNode)
|
Struct(EntryNode)
|
||||||
{
|
{
|
||||||
EntryNode *next;
|
EntryNode *next;
|
||||||
@ -555,14 +556,15 @@ void StartupMeta(void)
|
|||||||
String file_data = F_DataFromFile(arena, en->file_name);
|
String file_data = F_DataFromFile(arena, en->file_name);
|
||||||
|
|
||||||
/* Write name */
|
/* Write name */
|
||||||
BB_WriteAlign(&bw, 64);
|
BB_WriteAlignByte(&bw, 64);
|
||||||
u64 name_start = BB_GetNumBytesWritten(&bw) + 1;
|
u64 name_start = BB_GetNumBytesWritten(&bw) + 1;
|
||||||
BB_WriteString(&bw, en->entry_name);
|
BB_WriteString(&bw, en->entry_name);
|
||||||
u64 name_len = BB_GetNumBytesWritten(&bw) - name_start;
|
u64 name_len = BB_GetNumBytesWritten(&bw) - name_start;
|
||||||
|
|
||||||
/* Write data */
|
/* Write data */
|
||||||
BB_WriteAlign(&bw, 64);
|
BB_WriteAlignByte(&bw, 64);
|
||||||
u64 data_start = BB_GetNumBytesWritten(&bw) + 1;
|
/* FIXME: Why no +1 here? */
|
||||||
|
u64 data_start = BB_GetNumBytesWritten(&bw);
|
||||||
BB_WriteBytes(&bw, file_data);
|
BB_WriteBytes(&bw, file_data);
|
||||||
u64 data_len = BB_GetNumBytesWritten(&bw) - data_start;
|
u64 data_len = BB_GetNumBytesWritten(&bw) - data_start;
|
||||||
|
|
||||||
@ -601,7 +603,7 @@ void StartupMeta(void)
|
|||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
{
|
{
|
||||||
EchoLine(Lit("[Compiling RC]"));
|
EchoLine(Lit("[Compiling RC]"));
|
||||||
String cmd = StringF(arena, "rc -nologo -fo %F %F", FmtString(res_out_file), FmtString(rc_out_file));
|
String cmd = StringF(arena, "cmd /c rc.exe -nologo -fo %F %F", FmtString(res_out_file), FmtString(rc_out_file));
|
||||||
OS_CommandResult result = OS_RunCommand(arena, cmd);
|
OS_CommandResult result = OS_RunCommand(arena, cmd);
|
||||||
String output = TrimWhitespace(result.output);
|
String output = TrimWhitespace(result.output);
|
||||||
EchoLine(F_GetFileName(rc_out_file));
|
EchoLine(F_GetFileName(rc_out_file));
|
||||||
@ -618,7 +620,7 @@ void StartupMeta(void)
|
|||||||
{
|
{
|
||||||
EchoLine(Lit("[Compiling C]"));
|
EchoLine(Lit("[Compiling C]"));
|
||||||
String cmd = StringF(arena,
|
String cmd = StringF(arena,
|
||||||
"cl /c %F -Fo:%F %F %F %F %F",
|
"cmd /c cl.exe /c %F -Fo:%F %F %F %F %F",
|
||||||
FmtString(c_out_file),
|
FmtString(c_out_file),
|
||||||
FmtString(c_out_obj_file),
|
FmtString(c_out_obj_file),
|
||||||
FmtString(StringFromList(arena, flags_msvc, Lit(" "))),
|
FmtString(StringFromList(arena, flags_msvc, Lit(" "))),
|
||||||
@ -640,7 +642,7 @@ void StartupMeta(void)
|
|||||||
{
|
{
|
||||||
EchoLine(Lit("[Linking]"));
|
EchoLine(Lit("[Linking]"));
|
||||||
String cmd = StringF(arena,
|
String cmd = StringF(arena,
|
||||||
"link %F %F /OUT:%F %F %F",
|
"cmd /c link.exe %F %F /OUT:%F %F %F",
|
||||||
FmtString(c_out_obj_file),
|
FmtString(c_out_obj_file),
|
||||||
FmtString(res_out_file),
|
FmtString(res_out_file),
|
||||||
FmtString(exe_file),
|
FmtString(exe_file),
|
||||||
|
|||||||
@ -56,7 +56,7 @@ M_TokenFile *M_PushTokenFile(Arena *arena, M_TokenFileList *l, String name, Stri
|
|||||||
tf->name = name;
|
tf->name = name;
|
||||||
tf->data = data;
|
tf->data = data;
|
||||||
M_PushToken(arena, tf, Lit(""), M_TokenKind_Eol);
|
M_PushToken(arena, tf, Lit(""), M_TokenKind_Eol);
|
||||||
QueuePush_NZ(&M_NilTokenFile, l->first, l->last, tf, next);
|
QueuePushNZ(&M_NilTokenFile, l->first, l->last, tf, next);
|
||||||
++l->count;
|
++l->count;
|
||||||
return tf;
|
return tf;
|
||||||
}
|
}
|
||||||
@ -72,7 +72,7 @@ M_Token *M_PushToken(Arena *arena, M_TokenFile *file, String s, M_TokenKind kind
|
|||||||
{
|
{
|
||||||
t->file = file;
|
t->file = file;
|
||||||
}
|
}
|
||||||
QueuePush_NZ(&M_NilToken, file->first_token, file->last_token, t, next);
|
QueuePushNZ(&M_NilToken, file->first_token, file->last_token, t, next);
|
||||||
++file->tokens_count;
|
++file->tokens_count;
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
@ -81,6 +81,8 @@ M_TokenFileList M_TokensFromSrcDirs(Arena *arena, StringList src_dirs)
|
|||||||
{
|
{
|
||||||
TempArena scratch = BeginScratch(arena);
|
TempArena scratch = BeginScratch(arena);
|
||||||
M_TokenFileList result = ZI;
|
M_TokenFileList result = ZI;
|
||||||
|
result.first = &M_NilTokenFile;
|
||||||
|
result.last = &M_NilTokenFile;
|
||||||
|
|
||||||
/* Build token file list from src dirs */
|
/* Build token file list from src dirs */
|
||||||
Dict *dedup_dict = InitDict(scratch.arena, 1021);
|
Dict *dedup_dict = InitDict(scratch.arena, 1021);
|
||||||
@ -206,7 +208,7 @@ M_Layer *M_PushLayer(Arena *arena, M_LayerList *list, M_TokenFile *file)
|
|||||||
*layer = M_NilLayer;
|
*layer = M_NilLayer;
|
||||||
layer->valid = 1;
|
layer->valid = 1;
|
||||||
layer->file = file;
|
layer->file = file;
|
||||||
QueuePush_NZ(&M_NilLayer, list->first, list->last, layer, next);
|
QueuePushNZ(&M_NilLayer, list->first, list->last, layer, next);
|
||||||
++list->count;
|
++list->count;
|
||||||
return layer;
|
return layer;
|
||||||
}
|
}
|
||||||
@ -223,7 +225,7 @@ M_Entry *M_PushEntry(Arena *arena, M_Layer *l, M_EntryKind kind, M_Token *entry_
|
|||||||
e->arg_tokens[i] = args[i];
|
e->arg_tokens[i] = args[i];
|
||||||
}
|
}
|
||||||
e->args_count = args_count;
|
e->args_count = args_count;
|
||||||
QueuePush_NZ(&M_NilEntry, l->first, l->last, e, next);
|
QueuePushNZ(&M_NilEntry, l->first, l->last, e, next);
|
||||||
++l->count;
|
++l->count;
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -81,12 +81,6 @@ Enum(M_EntryKind)
|
|||||||
M_EntryKind_EmbedDir,
|
M_EntryKind_EmbedDir,
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(M_EntryKindMatch)
|
|
||||||
{
|
|
||||||
char *match_cstr;
|
|
||||||
u64 max_args;
|
|
||||||
};
|
|
||||||
|
|
||||||
Global Readonly char *M_entry_kind_rules[] = {
|
Global Readonly char *M_entry_kind_rules[] = {
|
||||||
[M_EntryKind_Layer] = "@Layer",
|
[M_EntryKind_Layer] = "@Layer",
|
||||||
[M_EntryKind_Dep] = "@Dep",
|
[M_EntryKind_Dep] = "@Dep",
|
||||||
|
|||||||
@ -370,8 +370,3 @@ String P_GetClipboardText(Arena *arena);
|
|||||||
|
|
||||||
void P_SleepPrecise(i64 sleep_time_ns);
|
void P_SleepPrecise(i64 sleep_time_ns);
|
||||||
void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns);
|
void P_SleepFrame(i64 last_frame_time_ns, i64 target_dt_ns);
|
||||||
|
|
||||||
////////////////////////////////
|
|
||||||
//~ @hookdecl Entry point (implemented per application)
|
|
||||||
|
|
||||||
void P_AppStartup(String args_str);
|
|
||||||
|
|||||||
@ -50,12 +50,187 @@ JobDef(S_LoadTextureJob, sig, _)
|
|||||||
JobDef(S_LoadSheetJob, sig, _)
|
JobDef(S_LoadSheetJob, sig, _)
|
||||||
{
|
{
|
||||||
TempArena scratch = BeginScratchNoConflict();
|
TempArena scratch = BeginScratchNoConflict();
|
||||||
|
Arena *perm = PermArena();
|
||||||
S_Entry *entry = sig->entry;
|
S_Entry *entry = sig->entry;
|
||||||
Resource resource = entry->resource;
|
Resource resource = entry->resource;
|
||||||
b32 success = 1;
|
b32 success = 1;
|
||||||
S_Sheet *sheet = &entry->sheet;
|
S_Sheet *sheet = &entry->sheet;
|
||||||
sheet->valid = 1;
|
sheet->valid = 1;
|
||||||
|
|
||||||
|
String name = NameFromResource(resource);
|
||||||
|
String data = DataFromResource(resource);
|
||||||
|
|
||||||
|
ASE_DecodedSheet decoded = ASE_DecodeSheet(scratch.arena, data);
|
||||||
|
success = decoded.success;
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Vec2 image_size = decoded.image_size;
|
||||||
|
Vec2 frame_size = decoded.frame_size;
|
||||||
|
Vec2 frame_center = MulVec2(decoded.frame_size, 0.5f);
|
||||||
|
|
||||||
|
sheet->image_size = image_size;
|
||||||
|
sheet->frame_size = frame_size;
|
||||||
|
|
||||||
|
/* Init frames */
|
||||||
|
sheet->frames_count = decoded.num_frames;
|
||||||
|
sheet->frames = PushStructs(perm, S_Frame, sheet->frames_count);
|
||||||
|
for (ASE_Frame *src = decoded.first_frame; src; src = src->next)
|
||||||
|
{
|
||||||
|
S_Frame *dst = &sheet->frames[src->index];
|
||||||
|
dst->index = src->index;
|
||||||
|
dst->duration = src->duration;
|
||||||
|
dst->clip.p0.x = src->x1;
|
||||||
|
dst->clip.p0.y = src->y1;
|
||||||
|
dst->clip.p1.x = src->x2;
|
||||||
|
dst->clip.p1.y = src->y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init spans */
|
||||||
|
sheet->spans_count = decoded.num_spans;
|
||||||
|
sheet->span_bins_count = MaxU32(AlignU64Pow2(sheet->spans_count * 2), 1);
|
||||||
|
sheet->spans = PushStructs(perm, S_Span, sheet->spans_count);
|
||||||
|
sheet->span_bins = PushStructs(perm, S_SpanBin, sheet->span_bins_count);
|
||||||
|
{
|
||||||
|
i32 span_index = 0;
|
||||||
|
for (ASE_Span *src = decoded.first_span; src; src = src->next)
|
||||||
|
{
|
||||||
|
S_Span *dst = &sheet->spans[span_index];
|
||||||
|
dst->hash = HashFnv64(Fnv64Basis, src->name);
|
||||||
|
dst->name = PushString(perm, src->name);
|
||||||
|
dst->start = src->start;
|
||||||
|
dst->end = src->end;
|
||||||
|
/* Insert span into bin */
|
||||||
|
{
|
||||||
|
S_SpanBin *bin = &sheet->span_bins[dst->hash % sheet->span_bins_count];
|
||||||
|
QueuePushN(bin->first, bin->last, dst, next_in_bin);
|
||||||
|
}
|
||||||
|
++span_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init slice groups */
|
||||||
|
sheet->slice_groups_count = decoded.num_slice_keys;
|
||||||
|
sheet->slice_group_bins_count = MaxU32(AlignU64Pow2(sheet->slice_groups_count * 2), 1);
|
||||||
|
sheet->slice_groups = PushStructs(perm, S_SliceGroup, sheet->slice_groups_count);
|
||||||
|
sheet->slice_group_bins = PushStructs(perm, S_SliceGroupBin, sheet->slice_group_bins_count);
|
||||||
|
{
|
||||||
|
i32 group_index = 0;
|
||||||
|
for (ASE_SliceKey *src_group = decoded.first_slice_key; src_group; src_group = src_group->next)
|
||||||
|
{
|
||||||
|
S_SliceGroup *dst_group = &sheet->slice_groups[group_index];
|
||||||
|
dst_group->hash = HashFnv64(Fnv64Basis, src_group->name);
|
||||||
|
dst_group->name = PushString(perm, src_group->name);
|
||||||
|
|
||||||
|
/* Init slices */
|
||||||
|
dst_group->slices = PushStructs(perm, S_Slice, sheet->frames_count);
|
||||||
|
{
|
||||||
|
/* Fill is_original slices */
|
||||||
|
for (ASE_Slice *src_slice = src_group->first_slice; src_slice; src_slice = src_slice->next)
|
||||||
|
{
|
||||||
|
f32 x1_px = src_slice->x1;
|
||||||
|
f32 y1_px = src_slice->y1;
|
||||||
|
f32 x2_px = src_slice->x2;
|
||||||
|
f32 y2_px = src_slice->y2;
|
||||||
|
f32 width_px = x2_px - x1_px;
|
||||||
|
f32 height_px = y2_px - y1_px;
|
||||||
|
|
||||||
|
f32 x1 = (x1_px - frame_center.x) / frame_size.x;
|
||||||
|
f32 y1 = (y1_px - frame_center.y) / frame_size.y;
|
||||||
|
f32 x2 = (x2_px - frame_center.x) / frame_size.x;
|
||||||
|
f32 y2 = (y2_px - frame_center.y) / frame_size.y;
|
||||||
|
f32 width = x2 - x1;
|
||||||
|
f32 height = y2 - y1;
|
||||||
|
|
||||||
|
/* Rect */
|
||||||
|
Rect rect_px = RectFromScalar(x1_px, y1_px, width_px, height_px);
|
||||||
|
Rect rect = RectFromScalar(x1, y1, width, height);
|
||||||
|
|
||||||
|
/* Center */
|
||||||
|
Vec2 center_px = VEC2(x1_px + (width_px * 0.5f), y1_px + (height_px * 0.5f));
|
||||||
|
Vec2 center = VEC2(x1 + (width * 0.5f), y1 + (height * 0.5f));
|
||||||
|
|
||||||
|
/* Dir */
|
||||||
|
Vec2 dir_px = VEC2(center_px.x, -1);
|
||||||
|
Vec2 dir = VEC2(0, -1);
|
||||||
|
|
||||||
|
S_Slice *dst_slice = &dst_group->slices[src_slice->start];
|
||||||
|
dst_slice->is_original = 1;
|
||||||
|
dst_slice->rect_px = rect_px;
|
||||||
|
dst_slice->center_px = center_px;
|
||||||
|
dst_slice->dir_px = dir_px;
|
||||||
|
dst_slice->rect = rect;
|
||||||
|
dst_slice->center = center;
|
||||||
|
dst_slice->dir = dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy slices forward into frames without a slice */
|
||||||
|
{
|
||||||
|
S_Slice *origin = 0;
|
||||||
|
for (u32 frame_index = 0; frame_index < sheet->frames_count; ++frame_index)
|
||||||
|
{
|
||||||
|
S_Slice *slice = &dst_group->slices[frame_index];
|
||||||
|
if (slice->is_original)
|
||||||
|
{
|
||||||
|
origin = slice;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*slice = *origin;
|
||||||
|
slice->is_original = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Insert group into bin */
|
||||||
|
{
|
||||||
|
S_SliceGroupBin *bin = &sheet->slice_group_bins[dst_group->hash % sheet->slice_group_bins_count];
|
||||||
|
QueuePushN(bin->first, bin->last, dst_group, next_in_bin);
|
||||||
|
}
|
||||||
|
++group_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init slice ray directions */
|
||||||
|
{
|
||||||
|
String ray_suffix = Lit(".ray");
|
||||||
|
for (u32 slice_group_index = 0; slice_group_index < sheet->slice_groups_count; ++slice_group_index)
|
||||||
|
{
|
||||||
|
S_SliceGroup *group = &sheet->slice_groups[slice_group_index];
|
||||||
|
if (StringEndsWith(group->name, ray_suffix))
|
||||||
|
{
|
||||||
|
String point_slice_group_name = group->name;
|
||||||
|
point_slice_group_name.len -= ray_suffix.len;
|
||||||
|
u64 point_slice_group_hash = HashFnv64(Fnv64Basis, point_slice_group_name);
|
||||||
|
S_SliceGroupBin *bin = &sheet->slice_group_bins[point_slice_group_hash % sheet->slice_group_bins_count];
|
||||||
|
S_SliceGroup *point_slice_group = bin->first;
|
||||||
|
for (; point_slice_group; point_slice_group = point_slice_group->next_in_bin)
|
||||||
|
{
|
||||||
|
if (point_slice_group->hash == point_slice_group_hash)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (point_slice_group)
|
||||||
|
{
|
||||||
|
for (u32 frame_index = 0; frame_index < sheet->frames_count; ++frame_index)
|
||||||
|
{
|
||||||
|
S_Slice *point_slice = &point_slice_group->slices[frame_index];
|
||||||
|
S_Slice *ray_slice = &group->slices[frame_index];
|
||||||
|
Vec2 ray_end = ray_slice->center_px;
|
||||||
|
Vec2 ray_end_norm = ray_slice->center;
|
||||||
|
point_slice->dir_px = SubVec2(ray_end, point_slice->center_px);
|
||||||
|
point_slice->dir = SubVec2(ray_end_norm, point_slice->center);
|
||||||
|
point_slice->has_dir = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sheet->loaded = 1;
|
||||||
AddCounter(&entry->sheet_load_counter, -1);
|
AddCounter(&entry->sheet_load_counter, -1);
|
||||||
EndScratch(scratch);
|
EndScratch(scratch);
|
||||||
}
|
}
|
||||||
@ -63,6 +238,7 @@ JobDef(S_LoadSheetJob, sig, _)
|
|||||||
////////////////////////////////
|
////////////////////////////////
|
||||||
//~ Cache
|
//~ Cache
|
||||||
|
|
||||||
|
/* TODO: Per-fiber L1 cache */
|
||||||
S_Entry *S_FetchEntry(Resource resource, JobPool pool, S_FetchFlag flags)
|
S_Entry *S_FetchEntry(Resource resource, JobPool pool, S_FetchFlag flags)
|
||||||
{
|
{
|
||||||
S_SharedState *g = &S_shared_state;
|
S_SharedState *g = &S_shared_state;
|
||||||
@ -78,36 +254,35 @@ S_Entry *S_FetchEntry(Resource resource, JobPool pool, S_FetchFlag flags)
|
|||||||
{
|
{
|
||||||
if (entry->resource.hash == resource.hash)
|
if (entry->resource.hash == resource.hash)
|
||||||
{
|
{
|
||||||
entry = entry;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unlock(&lock);
|
Unlock(&lock);
|
||||||
}
|
}
|
||||||
/* Entry not found, re-check & create */
|
/* Entry not found: lock, re-search, & create */
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
Lock lock = LockE(&bin->mutex);
|
Lock lock = LockE(&bin->mutex);
|
||||||
{
|
{
|
||||||
/* Re-check */
|
/* Re-search */
|
||||||
entry = bin->first;
|
entry = bin->first;
|
||||||
for (; entry; entry = entry->next_in_bin)
|
for (; entry; entry = entry->next_in_bin)
|
||||||
{
|
{
|
||||||
if (entry->resource.hash == resource.hash)
|
if (entry->resource.hash == resource.hash)
|
||||||
{
|
{
|
||||||
entry = entry;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Create */
|
/* Create */
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
entry = PushStruct(PermArena, S_Entry);
|
Arena *perm = PermArena();
|
||||||
|
entry = PushStruct(perm, S_Entry);
|
||||||
entry->resource = resource;
|
entry->resource = resource;
|
||||||
AddCounter(&entry->texture_load_counter, 1);
|
AddCounter(&entry->texture_load_counter, 1);
|
||||||
AddCounter(&entry->sheet_load_counter, 1);
|
AddCounter(&entry->sheet_load_counter, 1);
|
||||||
QueuePush_N(bin->first, bin->last, entry, next_in_bin);
|
QueuePushN(bin->first, bin->last, entry, next_in_bin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Unlock(&lock);
|
Unlock(&lock);
|
||||||
@ -174,17 +349,73 @@ S_Sheet *S_SheetFromResourceAsync(Resource resource)
|
|||||||
S_Span S_SpanFromName(S_Sheet *sheet, String name)
|
S_Span S_SpanFromName(S_Sheet *sheet, String name)
|
||||||
{
|
{
|
||||||
S_Span result = ZI;
|
S_Span result = ZI;
|
||||||
|
u32 bins_count = sheet->span_bins_count;
|
||||||
|
if (bins_count > 0)
|
||||||
|
{
|
||||||
|
u64 name_hash = HashFnv64(Fnv64Basis, name);
|
||||||
|
S_SpanBin *bin = &sheet->span_bins[name_hash % bins_count];
|
||||||
|
S_Span *span = bin->first;
|
||||||
|
for (; span; span = span->next_in_bin)
|
||||||
|
{
|
||||||
|
if (span->hash == name_hash)
|
||||||
|
{
|
||||||
|
result = *span;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
S_Frame S_FrameFromIndex(S_Sheet *sheet, u64 index)
|
S_Frame S_FrameFromIndex(S_Sheet *sheet, u64 index)
|
||||||
{
|
{
|
||||||
S_Frame result = ZI;
|
S_Frame result = ZI;
|
||||||
|
if (sheet->frames_count > 0)
|
||||||
|
{
|
||||||
|
result = sheet->frames[index % sheet->frames_count];
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
S_Slice S_SliceFromName(S_Sheet *sheet, String name, u64 frame_index)
|
S_Slice S_SliceFromName(S_Sheet *sheet, String name, u64 frame_index)
|
||||||
{
|
{
|
||||||
S_Slice result = ZI;
|
S_Slice result = ZI;
|
||||||
|
b32 match = 0;
|
||||||
|
|
||||||
|
u32 bins_count = sheet->slice_group_bins_count;
|
||||||
|
if (bins_count > 0 && sheet->frames_count > 0)
|
||||||
|
{
|
||||||
|
u64 name_hash = HashFnv64(Fnv64Basis, name);
|
||||||
|
S_SliceGroupBin *bin = &sheet->slice_group_bins[name_hash % bins_count];
|
||||||
|
S_SliceGroup *group = bin->first;
|
||||||
|
for (; group; group = group->next_in_bin)
|
||||||
|
{
|
||||||
|
if (group->hash == name_hash)
|
||||||
|
{
|
||||||
|
result = group->slices[frame_index % sheet->frames_count];
|
||||||
|
match = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return 'pivot' by default */
|
||||||
|
if (!match)
|
||||||
|
{
|
||||||
|
if (EqString(name, Lit("pivot")))
|
||||||
|
{
|
||||||
|
/* 'pivot' slice does not exist, return center */
|
||||||
|
result.center = VEC2(0, 0);
|
||||||
|
result.center_px = MulVec2(sheet->frame_size, 0.5f);
|
||||||
|
result.dir_px = VEC2(result.center_px.x, 0);
|
||||||
|
result.dir = VEC2(0, -0.5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = S_SliceFromName(sheet, Lit("pivot"), frame_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -24,18 +24,26 @@ Struct(S_Frame)
|
|||||||
|
|
||||||
Struct(S_Span)
|
Struct(S_Span)
|
||||||
{
|
{
|
||||||
|
S_Span *next_in_bin;
|
||||||
|
u64 hash;
|
||||||
String name;
|
String name;
|
||||||
u32 start;
|
u32 start;
|
||||||
u32 end;
|
u32 end;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Struct(S_SpanBin)
|
||||||
|
{
|
||||||
|
S_Span *first;
|
||||||
|
S_Span *last;
|
||||||
|
};
|
||||||
|
|
||||||
Struct(S_Slice)
|
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 is_original;
|
||||||
|
|
||||||
/* If 1, the slice has a corresponding '.ray' slice affecting the 'dir' fields */
|
/* If 1, the slice has a corresponding '.ray' slice affecting the 'dir' fields */
|
||||||
b32 has_ray;
|
b32 has_dir;
|
||||||
|
|
||||||
/* Values are in the range -0.5 (top / left edge) -> +0.5 (bottom / right edge) */
|
/* Values are in the range -0.5 (top / left edge) -> +0.5 (bottom / right edge) */
|
||||||
Rect rect;
|
Rect rect;
|
||||||
@ -48,20 +56,18 @@ Struct(S_Slice)
|
|||||||
Vec2 dir_px;
|
Vec2 dir_px;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_SliceArray)
|
Struct(S_SliceGroup)
|
||||||
{
|
{
|
||||||
u64 count;
|
S_SliceGroup *next_in_bin;
|
||||||
|
u64 hash;
|
||||||
|
String name;
|
||||||
S_Slice *slices;
|
S_Slice *slices;
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_SheetSliceGroup)
|
Struct(S_SliceGroupBin)
|
||||||
{
|
{
|
||||||
String name;
|
S_SliceGroup *first;
|
||||||
u64 per_frame_count;
|
S_SliceGroup *last;
|
||||||
|
|
||||||
/* 2d array of slices with length (num frames) * (num slices per frame).
|
|
||||||
* Index with [(frame index * num slices per frame) + slice index in frame] */
|
|
||||||
S_Slice *frame_slices;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Struct(S_Sheet)
|
Struct(S_Sheet)
|
||||||
@ -76,11 +82,15 @@ Struct(S_Sheet)
|
|||||||
|
|
||||||
u32 spans_count;
|
u32 spans_count;
|
||||||
S_Span *spans;
|
S_Span *spans;
|
||||||
Dict *spans_dict;
|
|
||||||
|
|
||||||
u32 slice_groups_count;
|
u32 slice_groups_count;
|
||||||
S_SheetSliceGroup *slice_groups;
|
S_SliceGroup *slice_groups;
|
||||||
Dict *slice_groups_dict;
|
|
||||||
|
u32 span_bins_count;
|
||||||
|
S_SpanBin *span_bins;
|
||||||
|
|
||||||
|
u32 slice_group_bins_count;
|
||||||
|
S_SliceGroupBin *slice_group_bins;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Readonly S_Sheet S_NilSheet;
|
extern Readonly S_Sheet S_NilSheet;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user