animation wip
This commit is contained in:
parent
d44a845a8d
commit
b7e2fafc85
1429
src/ase/ase.c
1429
src/ase/ase.c
File diff suppressed because it is too large
Load Diff
427
src/ase/ase.h
427
src/ase/ase.h
@ -1,4 +1,132 @@
|
||||
// DEFLATE decoder based on Handmade Hero's png parser
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Aseprite decode types
|
||||
|
||||
// https://github.com/aseprite/aseprite/blob/main/docs/ase-file-specs.md
|
||||
|
||||
Packed(Struct(ASE_Header)
|
||||
{
|
||||
u32 file_size;
|
||||
u16 magic;
|
||||
u16 frames_count;
|
||||
u16 width;
|
||||
u16 height;
|
||||
u16 color_depth;
|
||||
u32 flags;
|
||||
u16 speed;
|
||||
u8 _0[8];
|
||||
u8 palette_entry;
|
||||
u8 _1[3];
|
||||
u16 colors_count;
|
||||
u8 pixel_width;
|
||||
u8 pixel_height;
|
||||
i16 grid_x;
|
||||
i16 grid_y;
|
||||
u16 grid_width;
|
||||
u16 grid_height;
|
||||
u8 _2[84];
|
||||
});
|
||||
|
||||
Packed(Struct(ASE_FrameHeader)
|
||||
{
|
||||
u32 bytes_count;
|
||||
u16 magic;
|
||||
u16 chunks_count0;
|
||||
u16 frame_duration_ms;
|
||||
u8 _[2];
|
||||
u32 chunks_count1;
|
||||
});
|
||||
|
||||
Enum(ASE_EncodedChunkKind)
|
||||
{
|
||||
ASE_EncodedChunkKind_OldPalette1 = 0x0004,
|
||||
ASE_EncodedChunkKind_OldPalette2 = 0x0011,
|
||||
ASE_EncodedChunkKind_Layer = 0x2004,
|
||||
ASE_EncodedChunkKind_Cel = 0x2005,
|
||||
ASE_EncodedChunkKind_CelExtra = 0x2006,
|
||||
ASE_EncodedChunkKind_ColorProfile = 0x2007,
|
||||
ASE_EncodedChunkKind_ExternalFiles = 0x2008,
|
||||
ASE_EncodedChunkKind_Mask = 0x2016,
|
||||
ASE_EncodedChunkKind_Path = 0x2017,
|
||||
ASE_EncodedChunkKind_Tags = 0x2018,
|
||||
ASE_EncodedChunkKind_Palette = 0x2019,
|
||||
ASE_EncodedChunkKind_Userdata = 0x2020,
|
||||
ASE_EncodedChunkKind_Slice = 0x2022,
|
||||
ASE_EncodedChunkKind_Tileset = 0x2023
|
||||
};
|
||||
|
||||
Enum(ASE_ChunkKind)
|
||||
{
|
||||
ASE_ChunkKind_Layer,
|
||||
ASE_ChunkKind_Cel,
|
||||
ASE_ChunkKind_Tag,
|
||||
};
|
||||
|
||||
Enum(ASE_LayerKind)
|
||||
{
|
||||
ASE_LayerKind_Normal,
|
||||
ASE_LayerKind_Group,
|
||||
ASE_LayerKind_Tilemap,
|
||||
};
|
||||
|
||||
Enum(ASE_LayerFlag)
|
||||
{
|
||||
ASE_LayerFlag_None = 0,
|
||||
ASE_LayerFlag_Visible = (1 << 0),
|
||||
ASE_LayerFlag_Editable = (1 << 1),
|
||||
ASE_LayerFlag_LockMovement = (1 << 2),
|
||||
ASE_LayerFlag_Background = (1 << 3),
|
||||
ASE_LayerFlag_PreferLinkedCels = (1 << 4),
|
||||
ASE_LayerFlag_Collapsed = (1 << 5),
|
||||
ASE_LayerFlag_ReferenceLayer = (1 << 6),
|
||||
};
|
||||
|
||||
Enum(ASE_CelKind)
|
||||
{
|
||||
ASE_CelKind_Raw = 0,
|
||||
ASE_CelKind_Linked = 1,
|
||||
ASE_CelKind_CompressedImage = 2,
|
||||
ASE_CelKind_CompressedTilemap = 3,
|
||||
};
|
||||
|
||||
Struct(ASE_Chunk)
|
||||
{
|
||||
ASE_Chunk *next;
|
||||
|
||||
ASE_ChunkKind kind;
|
||||
|
||||
//- Common
|
||||
f32 opacity;
|
||||
String name;
|
||||
i64 chunk_layer_idx;
|
||||
|
||||
//- Layer
|
||||
struct
|
||||
{
|
||||
ASE_LayerKind kind;
|
||||
ASE_LayerFlag flags;
|
||||
|
||||
ASE_Chunk **cel_chunks;
|
||||
struct ASE_Layer *final;
|
||||
} layer;
|
||||
|
||||
//- Cel
|
||||
struct
|
||||
{
|
||||
ASE_CelKind kind;
|
||||
i64 frame_idx;
|
||||
i64 linked_frame_idx;
|
||||
|
||||
Rng2 bounds;
|
||||
String encoded;
|
||||
} cel;
|
||||
|
||||
//- Tag
|
||||
struct
|
||||
{
|
||||
i64 from;
|
||||
i64 to;
|
||||
} tag;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Inflate types
|
||||
@ -138,21 +266,23 @@ Struct(ASE_Span)
|
||||
ASE_Span *prev;
|
||||
|
||||
String name;
|
||||
i64 start;
|
||||
i64 end;
|
||||
i64 from;
|
||||
i64 to;
|
||||
};
|
||||
|
||||
Struct(ASE_Meta)
|
||||
{
|
||||
i64 frames_count;
|
||||
|
||||
i64 layers_count;
|
||||
ASE_Layer *first_layer;
|
||||
ASE_Layer *last_layer;
|
||||
|
||||
i64 spans_count;
|
||||
ASE_Span *first_span;
|
||||
ASE_Span *last_span;
|
||||
|
||||
i64 layers_count;
|
||||
ASE_Layer *first_layer;
|
||||
ASE_Layer *last_layer;
|
||||
b32 ok;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -184,7 +314,7 @@ u16 ASE_DecodeHuffDict(ASE_HuffDict *huffman, ASE_Bitbuff *bb);
|
||||
void ASE_Inflate(u8 *dst, u8 *encoded);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Meta
|
||||
//~ Decode
|
||||
|
||||
ASE_Meta ASE_DecodeMeta(Arena *arena, String encoded);
|
||||
|
||||
@ -199,286 +329,3 @@ ASE_Image ASE_DecompressImageFromCel(Arena *arena, ASE_Cel *cel);
|
||||
|
||||
u32 ASE_BlendPixel(u32 src, u32 dst, u8 opacity);
|
||||
void ASE_BlendImage(ASE_Image src_img, ASE_Image dst_img);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Query
|
||||
|
||||
// u32 ASE_FirstPixelFromCel(ASE_Cel *cel);
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Rasterize
|
||||
|
||||
// void ASE_RasterizeCel(ASE_Cel *cel, u32 *dst_pixels, Vec2 dst_dims);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Sheet types
|
||||
|
||||
// Struct(ASE_Slice)
|
||||
// {
|
||||
// u32 start;
|
||||
// Rng2I32 rect;
|
||||
// ASE_Slice *next;
|
||||
// };
|
||||
|
||||
// Struct(ASE_Span)
|
||||
// {
|
||||
// String name;
|
||||
// u32 start;
|
||||
// u32 end;
|
||||
// ASE_Span *next;
|
||||
// };
|
||||
|
||||
// Struct(ASE_Frame)
|
||||
// {
|
||||
// u32 index;
|
||||
// Rng2I32 rect;
|
||||
// f64 duration;
|
||||
// ASE_Frame *next;
|
||||
// };
|
||||
|
||||
// Struct(ASE_SliceKey)
|
||||
// {
|
||||
// String name;
|
||||
// u32 slices_count;
|
||||
// ASE_Slice *first_slice;
|
||||
// ASE_SliceKey *next;
|
||||
// };
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Decoder result types
|
||||
|
||||
// Struct(ASE_Error)
|
||||
// {
|
||||
// String msg;
|
||||
// ASE_Error *next;
|
||||
// };
|
||||
|
||||
// Struct(ASE_ErrorList)
|
||||
// {
|
||||
// u64 count;
|
||||
// ASE_Error *first;
|
||||
// ASE_Error *last;
|
||||
// };
|
||||
|
||||
// Struct(ASE_DecodedImage)
|
||||
// {
|
||||
// u32 width;
|
||||
// u32 height;
|
||||
// u32 *pixels; // Array of [width * height] pixels
|
||||
// ASE_ErrorList errors;
|
||||
// b32 ok;
|
||||
// };
|
||||
|
||||
// Struct(ASE_DecodedSheet)
|
||||
// {
|
||||
// Vec2 image_size;
|
||||
// Vec2 frame_size;
|
||||
// u32 frames_count;
|
||||
// u32 spans_count;
|
||||
// u32 slice_keys_count;
|
||||
// ASE_Frame *first_frame;
|
||||
// ASE_Span *first_span;
|
||||
// ASE_SliceKey *first_slice_key;
|
||||
// ASE_ErrorList errors;
|
||||
// b32 ok;
|
||||
// };
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Inflator types
|
||||
|
||||
// #define ASE_HuffBitCount 16
|
||||
|
||||
// Struct(ASE_Bitbuff)
|
||||
// {
|
||||
// u8 *data;
|
||||
// u64 cur_bit;
|
||||
// };
|
||||
|
||||
// Enum(ASE_BlockType)
|
||||
// {
|
||||
// ASE_BlockType_Uncompressed = 0,
|
||||
// ASE_BlockType_CompressedFixed = 1,
|
||||
// ASE_BlockType_CompressedDynamic = 2,
|
||||
// ASE_BlockType_Reserved = 3
|
||||
// };
|
||||
|
||||
// Struct(ASE_HuffEntry)
|
||||
// {
|
||||
// u16 symbol;
|
||||
// u16 bits_used;
|
||||
// };
|
||||
|
||||
// Struct(ASE_HuffDict)
|
||||
// {
|
||||
// u32 max_code_bits;
|
||||
// u32 entries_count;
|
||||
// ASE_HuffEntry *entries;
|
||||
// };
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Header types
|
||||
|
||||
// Packed(Struct(ASE_Header)
|
||||
// {
|
||||
// u32 file_size;
|
||||
// u16 magic;
|
||||
// u16 frames;
|
||||
// u16 width;
|
||||
// u16 height;
|
||||
// u16 color_depth;
|
||||
// u32 flags;
|
||||
// u16 speed;
|
||||
// u32 _1;
|
||||
// u32 _2;
|
||||
// u8 palette_entry;
|
||||
// u8 _3[3];
|
||||
// u16 colors_count;
|
||||
// u8 pixel_width;
|
||||
// u8 pixel_height;
|
||||
// i16 grid_x;
|
||||
// i16 grid_y;
|
||||
// u16 grid_width;
|
||||
// u16 grid_height;
|
||||
// u8 _4[84];
|
||||
// });
|
||||
|
||||
// Packed(Struct(ASE_FrameHeader)
|
||||
// {
|
||||
// u32 bytes;
|
||||
// u16 magic;
|
||||
// u16 chunks_old;
|
||||
// u16 frame_duration_ms;
|
||||
// u8 _[2];
|
||||
// u32 chunks_new;
|
||||
// });
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Image decoder types
|
||||
|
||||
// Enum(ASE_ChunkKind)
|
||||
// {
|
||||
// ASE_ChunkKind_OldPalette1 = 0x0004,
|
||||
// ASE_ChunkKind_OldPalette2 = 0x0011,
|
||||
// ASE_ChunkKind_Layer = 0x2004,
|
||||
// ASE_ChunkKind_Cel = 0x2005,
|
||||
// ASE_ChunkKind_CelExtra = 0x2006,
|
||||
// ASE_ChunkKind_ColorProfile = 0x2007,
|
||||
// ASE_ChunkKind_ExternalFiles = 0x2008,
|
||||
// ASE_ChunkKind_Mask = 0x2016,
|
||||
// ASE_ChunkKind_Path = 0x2017,
|
||||
// ASE_ChunkKind_Tags = 0x2018,
|
||||
// ASE_ChunkKind_Palette = 0x2019,
|
||||
// ASE_ChunkKind_Userdata = 0x2020,
|
||||
// ASE_ChunkKind_Slice = 0x2022,
|
||||
// ASE_ChunkKind_Tileset = 0x2023
|
||||
// };
|
||||
|
||||
// Enum(ASE_CelKind)
|
||||
// {
|
||||
// ASE_CelKind_RawImage = 0,
|
||||
// ASE_CelKind_Linked = 1,
|
||||
// ASE_CelKind_CompressedImage = 2,
|
||||
// ASE_CelKind_CompressedTilemap = 3
|
||||
// };
|
||||
|
||||
// Struct(ASE_Layer)
|
||||
// {
|
||||
// u16 flags;
|
||||
// u16 type;
|
||||
// u16 child_level;
|
||||
// u16 blend_mode;
|
||||
// u8 opacity;
|
||||
// String name;
|
||||
// u32 tileset_index;
|
||||
|
||||
// u32 index;
|
||||
// ASE_Layer *next;
|
||||
// };
|
||||
|
||||
// Struct(ASE_Cel)
|
||||
// {
|
||||
// u16 layer_index;
|
||||
// i16 x_pos;
|
||||
// i16 y_pos;
|
||||
// u8 opacity;
|
||||
// ASE_CelKind type;
|
||||
// i16 z_index;
|
||||
|
||||
// // Linked cel
|
||||
// u16 frame_pos;
|
||||
|
||||
// // Compressed image
|
||||
// u32 width;
|
||||
// u32 height;
|
||||
// u32 *pixels;
|
||||
|
||||
// u16 frame_index;
|
||||
// ASE_Cel *next;
|
||||
// };
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Ase bitbuff helpers
|
||||
|
||||
// u32 ASE_PeekBits(ASE_Bitbuff *bb, u32 nbits);
|
||||
// u32 ASE_ConsumeBits(ASE_Bitbuff *bb, u32 nbits);
|
||||
// void ASE_SkipBits(ASE_Bitbuff *bb, u32 nbits);
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Inflate
|
||||
|
||||
// u32 ASE_ReverseBits(u32 v, u32 bit_count);
|
||||
// ASE_HuffDict ASE_InitHuffDict(Arena *arena, u32 max_code_bits, u32 *bl_counts, u32 bl_counts_count);
|
||||
// u16 ASE_DecodeHuffDict(ASE_HuffDict *huffman, ASE_Bitbuff *bb);
|
||||
// void ASE_Inflate(u8 *dst, u8 *encoded);
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Error helpers
|
||||
|
||||
// void ASE_PushError(Arena *arena, ASE_ErrorList *list, String msg_src);
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Decode helpers
|
||||
|
||||
// u32 ASE_Blend(u32 src, u32 dst, u8 opacity);
|
||||
// void ASE_MakeDimensionsSquareish(ASE_Header *header, u32 *frames_x, u32 *frames_y, u64 *image_width, u64 *image_height);
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Decode image
|
||||
|
||||
// ASE_DecodedImage ASE_DecodeImage(Arena *arena, String encoded);
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
// //~ Decode sheet
|
||||
|
||||
// ASE_DecodedSheet ASE_DecodeSheet(Arena *arena, String encoded);
|
||||
|
||||
@ -372,7 +372,7 @@ void BuildEntryPoint(WaveLaneCtx *lane)
|
||||
PushStringToList(perm, &cp.warnings_msvc, Lit("-W4"));
|
||||
PushStringToList(perm, &cp.warnings_msvc, Lit("-WX"));
|
||||
// PushStringToList(perm, &cp.warnings_msvc, Lit("-we4013")); // function undefined; assuming extern returning int
|
||||
PushStringToList(perm, &cp.warnings_msvc, Lit("-we4668")); // 'X' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
|
||||
PushStringToList(perm, &cp.warnings_msvc, Lit("-we4668")); // X is not defined as a preprocessor macro, replacing with '0' for '#if/#elif'
|
||||
|
||||
// Disable warnings
|
||||
PushStringToList(perm, &cp.warnings_msvc, Lit("-wd4244")); // 'function': conversion from 'int' to 'f32', possible loss of data
|
||||
|
||||
@ -4265,6 +4265,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
}
|
||||
V_TileDesc tile_desc = Zi;
|
||||
{
|
||||
tile_desc.tex_slice_uv = tile_slice.tex_rect_uv;
|
||||
tile_desc.tex = tile_slice.tex;
|
||||
}
|
||||
params.tile_descs[tile_kind] = tile_desc;
|
||||
|
||||
@ -493,7 +493,7 @@ ComputeShader2D(V_ShadeCS, 8, 8)
|
||||
Texture2D<P_TileKind> tiles = G_Dereference<P_TileKind>(params.tiles);
|
||||
RWTexture2D<Vec4> stains = G_Dereference<Vec4>(params.stains);
|
||||
RWTexture2D<f32> drynesses = G_Dereference<f32>(params.drynesses);
|
||||
SamplerState wrap_sampler = G_Dereference(params.pt_wrap_sampler);
|
||||
SamplerState clamp_sampler = G_Dereference(params.pt_clamp_sampler);
|
||||
|
||||
Vec2 shade_pos = SV_DispatchThreadID + Vec2(0.5, 0.5);
|
||||
Vec2 world_pos = mul(params.af.shade_to_world, Vec3(shade_pos, 1));
|
||||
@ -548,7 +548,8 @@ ComputeShader2D(V_ShadeCS, 8, 8)
|
||||
{
|
||||
V_TileDesc tile_desc = params.tile_descs[tile];
|
||||
Texture2D<Vec4> tile_tex = G_Dereference<Vec4>(tile_desc.tex);
|
||||
tile_color = tile_tex.SampleLevel(wrap_sampler, world_pos, 0);
|
||||
Vec2 tile_samp_uv = lerp(tile_desc.tex_slice_uv.p0, tile_desc.tex_slice_uv.p1, frac(world_pos));
|
||||
tile_color = tile_tex.SampleLevel(clamp_sampler, tile_samp_uv, 0);
|
||||
}
|
||||
// Checkered grid
|
||||
else if (tile == P_TileKind_Empty)
|
||||
|
||||
@ -48,6 +48,7 @@ Struct(V_Affines)
|
||||
|
||||
Struct(V_TileDesc)
|
||||
{
|
||||
Rng2 tex_slice_uv;
|
||||
G_Texture2DRef tex;
|
||||
};
|
||||
|
||||
|
||||
@ -108,6 +108,7 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
|
||||
{
|
||||
SPR_SliceEntry *slice = &sheet->slices[slice_idx];
|
||||
slice->bounds = Rng2Empty;
|
||||
Atomic64Set(&slice->atlas_copy_completion_target, I64Max);
|
||||
for (SPR_RayKind ray_kind = 0; ray_kind < SPR_RayKind_COUNT; ++ray_kind)
|
||||
{
|
||||
slice->rays[ray_kind] = XformIdentity;
|
||||
@ -204,33 +205,46 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
|
||||
}
|
||||
|
||||
//- Init spans
|
||||
sheet->span_bins_count = 256;
|
||||
sheet->span_bins = PushStructs(perm, SPR_SpanBin, sheet->span_bins_count);
|
||||
for (ASE_Span *ase_span = sheet->meta.first_span; ase_span; ase_span = ase_span->next)
|
||||
{
|
||||
SPR_SpanKey new_span_key = { .v = HashString(ase_span->name) };
|
||||
SPR_SpanBin *span_bin = &sheet->span_bins[new_span_key.v % sheet->span_bins_count];
|
||||
SPR_SpanEntry *span = 0;
|
||||
for (span = span_bin->first; span; span = span->next_in_bin)
|
||||
sheet->span_bins_count = MaxI64(1, NextPow2U64(sheet->meta.spans_count * 4));
|
||||
sheet->span_bins = PushStructs(perm, SPR_SpanBin, sheet->span_bins_count);
|
||||
for (ASE_Span *ase_span = sheet->meta.first_span; ase_span; ase_span = ase_span->next)
|
||||
{
|
||||
if (span->key.v == new_span_key.v)
|
||||
SPR_SpanKey new_span_key = { .v = HashString(ase_span->name) };
|
||||
SPR_SpanBin *span_bin = &sheet->span_bins[new_span_key.v % sheet->span_bins_count];
|
||||
SPR_SpanEntry *span = 0;
|
||||
for (span = span_bin->first; span; span = span->next_in_bin)
|
||||
{
|
||||
break;
|
||||
if (span->key.v == new_span_key.v)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!span)
|
||||
{
|
||||
span = PushStruct(perm, SPR_SpanEntry);
|
||||
SllQueuePush(sheet->first_span, sheet->last_span, span);
|
||||
SllStackPushN(span_bin->first, span, next_in_bin);
|
||||
span->key = new_span_key;
|
||||
span->from = ase_span->from;
|
||||
span->to = ase_span->to;
|
||||
}
|
||||
}
|
||||
if (!span)
|
||||
|
||||
// Insert nil span
|
||||
{
|
||||
span = PushStruct(perm, SPR_SpanEntry);
|
||||
SPR_SpanBin *span_bin = &sheet->span_bins[0];
|
||||
SPR_SpanEntry *span = PushStruct(perm, SPR_SpanEntry);
|
||||
SllQueuePush(sheet->first_span, sheet->last_span, span);
|
||||
SllStackPushN(span_bin->first, span, next_in_bin);
|
||||
span->key = new_span_key;
|
||||
span->start = ase_span->start;
|
||||
span->end = ase_span->end;
|
||||
span->key = SPR_NilSpanKey;
|
||||
span->from = 0;
|
||||
span->to = sheet->slices_count;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Proper validation
|
||||
sheet->ok = 1;
|
||||
// TODO: More rigorous validation
|
||||
sheet->ok = sheet->meta.ok;
|
||||
}
|
||||
}
|
||||
Unlock(&sheet_bin_lock);
|
||||
@ -263,8 +277,8 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f
|
||||
}
|
||||
if (span)
|
||||
{
|
||||
span_start = span->start;
|
||||
span_end = span->end;
|
||||
span_start = span->from;
|
||||
span_end = span->to;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -86,8 +86,8 @@ Struct(SPR_SpanEntry)
|
||||
SPR_SpanEntry *next_in_bin;
|
||||
SPR_SpanKey key;
|
||||
|
||||
i64 start;
|
||||
i64 end;
|
||||
i64 from;
|
||||
i64 to;
|
||||
};
|
||||
|
||||
Struct(SPR_SpanBin)
|
||||
|
||||
@ -29,8 +29,6 @@
|
||||
|
||||
@IncludeG ui_gpu.gh
|
||||
|
||||
@Bootstrap UI_Bootstrap
|
||||
|
||||
//////////////////////////////
|
||||
//- Impl
|
||||
|
||||
|
||||
204
src/ui/ui_core.c
204
src/ui/ui_core.c
@ -1,12 +1,5 @@
|
||||
UI_Ctx UI = Zi;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Bootstrap
|
||||
|
||||
void UI_Bootstrap(void)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Key helpers
|
||||
|
||||
@ -537,13 +530,11 @@ void UI_SetRawTexture(UI_Key key, G_Texture2DRef tex, Rng2 uv)
|
||||
UI_BoxReports UI_ReportsFromKey(UI_Key key)
|
||||
{
|
||||
UI_BoxReports result = Zi;
|
||||
|
||||
UI_Box *box = UI_BoxFromKey(key);
|
||||
if (box)
|
||||
{
|
||||
result = box->reports;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -629,11 +620,11 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
|
||||
{
|
||||
ControllerEventsArray controller_events = frame->window_frame.controller_events;
|
||||
|
||||
// Locate boxes
|
||||
//- Locate boxes
|
||||
UI_Box *top_hovered_box = 0;
|
||||
UI_Box *active_box = UI_BoxFromKey(prev_frame->active_box);
|
||||
|
||||
// Update cursor pos
|
||||
//- Update cursor pos
|
||||
for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index)
|
||||
{
|
||||
ControllerEvent cev = controller_events.events[cev_index];
|
||||
@ -643,7 +634,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
|
||||
}
|
||||
}
|
||||
|
||||
// Init box reports
|
||||
//- Init box reports
|
||||
for (u64 pre_index = UI.boxes_count; pre_index-- > 0;)
|
||||
{
|
||||
UI_Box *box = prev_frame->boxes_pre[pre_index];
|
||||
@ -690,7 +681,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
|
||||
report->m3.presses = 0;
|
||||
}
|
||||
|
||||
// Update state from controller events
|
||||
//- Update state from controller events
|
||||
i32 mouse_downs = 0;
|
||||
for (u64 cev_index = 0; cev_index < controller_events.count; ++cev_index)
|
||||
{
|
||||
@ -788,7 +779,7 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
|
||||
hot_box = top_hovered_box;
|
||||
}
|
||||
|
||||
// Update box reports
|
||||
//- Update box reports
|
||||
{
|
||||
f32 lower_target = TweakFloat("UI lower blend target", -0.05, -1, 0);
|
||||
f32 upper_target = TweakFloat("UI upper blend target", 1.05, 1, 10);
|
||||
@ -804,9 +795,6 @@ UI_Frame *UI_BeginFrame(UI_FrameFlag frame_flags)
|
||||
f32 target_active = box == active_box ? Inf : lower_target;
|
||||
f64 target_misc = box->desc.misc;
|
||||
|
||||
|
||||
|
||||
|
||||
// TODO: Configurable per-box blend rates
|
||||
f32 exists_blend_rate = (30 * frame->dt);
|
||||
f32 hot_blend_rate = (15 * frame->dt);
|
||||
@ -896,7 +884,6 @@ GC_Run UI_ScaleRun(Arena *arena, GC_Run unscaled_run, Vec2 scale)
|
||||
{
|
||||
GC_RunRect *src = &unscaled_run.rects[rect_idx];
|
||||
GC_RunRect *dst = &result.rects[rect_idx];
|
||||
|
||||
*dst = *src;
|
||||
dst->bounds = MulRng2Vec2(dst->bounds, scale);
|
||||
dst->advance *= scale.x;
|
||||
@ -923,121 +910,116 @@ void UI_EndFrame(UI_Frame *frame, i32 vsync)
|
||||
Rng2 draw_scissor = RNG2(VEC2(0, 0), VEC2(draw_size.x, draw_size.y));
|
||||
|
||||
//////////////////////////////
|
||||
//- Process commands
|
||||
//- Create boxes from build cmds
|
||||
|
||||
for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
||||
{
|
||||
//////////////////////////////
|
||||
//- Create boxes from build cmds
|
||||
|
||||
for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
||||
UI_Cmd cmd = cmd_node->cmd;
|
||||
if (cmd.kind == UI_CmdKind_BuildBox)
|
||||
{
|
||||
UI_Cmd cmd = cmd_node->cmd;
|
||||
if (cmd.kind == UI_CmdKind_BuildBox)
|
||||
UI_Key key = cmd.box.key;
|
||||
UI_Box *box = 0;
|
||||
{
|
||||
UI_Key key = cmd.box.key;
|
||||
UI_Box *box = 0;
|
||||
UI_BoxBin *bin = &UI.box_bins[key.v % countof(UI.box_bins)];
|
||||
for (box = bin->first; box; box = box->next_in_bin)
|
||||
{
|
||||
UI_BoxBin *bin = &UI.box_bins[key.v % countof(UI.box_bins)];
|
||||
for (box = bin->first; box; box = box->next_in_bin)
|
||||
if (UI_MatchKey(box->key, key))
|
||||
{
|
||||
if (UI_MatchKey(box->key, key))
|
||||
{
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Allocate new box
|
||||
if (box == 0)
|
||||
{
|
||||
// Allocate new box
|
||||
if (box == 0)
|
||||
box = UI.first_free_box;
|
||||
i64 old_gen = 0;
|
||||
if (box)
|
||||
{
|
||||
// Allocate new box
|
||||
box = UI.first_free_box;
|
||||
i64 old_gen = 0;
|
||||
if (box)
|
||||
{
|
||||
old_gen = box->gen;
|
||||
SllStackPop(UI.first_free_box);
|
||||
ZeroStruct(box);
|
||||
}
|
||||
else
|
||||
{
|
||||
box = PushStruct(UI.box_arena, UI_Box);
|
||||
}
|
||||
box->key = key;
|
||||
box->old_gen = old_gen;
|
||||
box->gen = old_gen + 1;
|
||||
DllQueuePushNP(bin->first, bin->last, box, next_in_bin, prev_in_bin);
|
||||
++UI.boxes_count;
|
||||
old_gen = box->gen;
|
||||
SllStackPop(UI.first_free_box);
|
||||
ZeroStruct(box);
|
||||
}
|
||||
else
|
||||
{
|
||||
box = PushStruct(UI.box_arena, UI_Box);
|
||||
}
|
||||
box->key = key;
|
||||
box->old_gen = old_gen;
|
||||
box->gen = old_gen + 1;
|
||||
DllQueuePushNP(bin->first, bin->last, box, next_in_bin, prev_in_bin);
|
||||
++UI.boxes_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
//- Update boxes from cmds
|
||||
//////////////////////////////
|
||||
//- Update boxes from cmds
|
||||
|
||||
for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
||||
for (UI_CmdNode *cmd_node = frame->first_cmd_node; cmd_node; cmd_node = cmd_node->next)
|
||||
{
|
||||
UI_Cmd cmd = cmd_node->cmd;
|
||||
switch (cmd.kind)
|
||||
{
|
||||
UI_Cmd cmd = cmd_node->cmd;
|
||||
switch (cmd.kind)
|
||||
case UI_CmdKind_BuildBox:
|
||||
{
|
||||
case UI_CmdKind_BuildBox:
|
||||
UI_Key key = cmd.box.key;
|
||||
if (UI_MatchKey(key, UI_NilKey))
|
||||
{
|
||||
UI_Key key = cmd.box.key;
|
||||
if (UI_MatchKey(key, UI_NilKey))
|
||||
{
|
||||
key = UI_RandKey();
|
||||
}
|
||||
UI_Box *box = UI_BoxFromKey(key);
|
||||
key = UI_RandKey();
|
||||
}
|
||||
UI_Box *box = UI_BoxFromKey(key);
|
||||
|
||||
UI_Box *parent = 0;
|
||||
if (box != UI.root_box)
|
||||
{
|
||||
parent = UI_BoxFromKey(cmd.box.parent);
|
||||
}
|
||||
|
||||
// Update parent
|
||||
if (box->parent)
|
||||
{
|
||||
// Remove from old parent
|
||||
DllQueueRemove(box->parent->first, box->parent->last, box);
|
||||
--box->parent->count;
|
||||
}
|
||||
if (parent)
|
||||
{
|
||||
// Add to new parent
|
||||
DllQueuePush(parent->first, parent->last, box);
|
||||
++parent->count;
|
||||
}
|
||||
box->parent = parent;
|
||||
|
||||
// Update box from cmd
|
||||
{
|
||||
box->desc = cmd.box;
|
||||
String32 codepoints = Zi;
|
||||
if (box->desc.icon != UI_Icon_None)
|
||||
{
|
||||
codepoints.len = 1;
|
||||
codepoints.text = (u32 *)&box->desc.icon;
|
||||
}
|
||||
else
|
||||
{
|
||||
codepoints = String32FromString(scratch.arena, box->desc.text);
|
||||
}
|
||||
box->glyph_run = GC_RunFromString32(frame->arena, codepoints, box->desc.font, box->desc.font_size);
|
||||
}
|
||||
box->last_build_tick = frame->tick;
|
||||
} break;
|
||||
|
||||
case UI_CmdKind_SetRawTexture:
|
||||
UI_Box *parent = 0;
|
||||
if (box != UI.root_box)
|
||||
{
|
||||
UI_Key key = cmd.set_raw_texture.key;
|
||||
UI_Box *box = UI_BoxFromKey(key);
|
||||
if (box)
|
||||
parent = UI_BoxFromKey(cmd.box.parent);
|
||||
}
|
||||
|
||||
// Update parent
|
||||
if (box->parent)
|
||||
{
|
||||
// Remove from old parent
|
||||
DllQueueRemove(box->parent->first, box->parent->last, box);
|
||||
--box->parent->count;
|
||||
}
|
||||
if (parent)
|
||||
{
|
||||
// Add to new parent
|
||||
DllQueuePush(parent->first, parent->last, box);
|
||||
++parent->count;
|
||||
}
|
||||
box->parent = parent;
|
||||
|
||||
// Update box from cmd
|
||||
{
|
||||
box->desc = cmd.box;
|
||||
String32 codepoints = Zi;
|
||||
if (box->desc.icon != UI_Icon_None)
|
||||
{
|
||||
box->raw_texture = cmd.set_raw_texture.tex;
|
||||
box->raw_texture_slice_uv = cmd.set_raw_texture.slice_uv;
|
||||
codepoints.len = 1;
|
||||
codepoints.text = (u32 *)&box->desc.icon;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
else
|
||||
{
|
||||
codepoints = String32FromString(scratch.arena, box->desc.text);
|
||||
}
|
||||
box->glyph_run = GC_RunFromString32(frame->arena, codepoints, box->desc.font, box->desc.font_size);
|
||||
}
|
||||
box->last_build_tick = frame->tick;
|
||||
} break;
|
||||
|
||||
case UI_CmdKind_SetRawTexture:
|
||||
{
|
||||
UI_Key key = cmd.set_raw_texture.key;
|
||||
UI_Box *box = UI_BoxFromKey(key);
|
||||
if (box)
|
||||
{
|
||||
box->raw_texture = cmd.set_raw_texture.tex;
|
||||
box->raw_texture_slice_uv = cmd.set_raw_texture.slice_uv;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -420,11 +420,6 @@ Struct(UI_Ctx)
|
||||
|
||||
extern UI_Ctx UI;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Bootstrap
|
||||
|
||||
void UI_Bootstrap(void);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Key helpers
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user