697 lines
22 KiB
C
697 lines
22 KiB
C
|
|
||
|
#define sloth_test_assert(c) if (!(c)) { do{ *((volatile int*)0) = 0xFFFF; }while(0); }
|
||
|
|
||
|
#define sloth_r32_equals(a,b) (fabsf((a) - (b)) < 0.001f)
|
||
|
|
||
|
Sloth_U32
|
||
|
sloth_test_string_len(char* s)
|
||
|
{
|
||
|
char* at = s;
|
||
|
while (*at != 0) at++;
|
||
|
return (Sloth_U32)(at - s);
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
sloth_test_strings_equal(char* a, char* b)
|
||
|
{
|
||
|
Sloth_U32 a_len = sloth_test_string_len(a);
|
||
|
Sloth_U32 b_len = sloth_test_string_len(b);
|
||
|
if (a_len != b_len) return false;
|
||
|
for (Sloth_U32 i = 0; i < a_len; i++) {
|
||
|
if (a[i] != b[i]) return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
static Sloth_U32 sloth_test_widget_order_count = 0;
|
||
|
void
|
||
|
sloth_test_widget_order(Sloth_Ctx* ctx, Sloth_Widget* widget, Sloth_U8* user_data)
|
||
|
{
|
||
|
Sloth_ID* ids = (Sloth_ID*)user_data;
|
||
|
Sloth_ID id_at = ids[sloth_test_widget_order_count++];
|
||
|
sloth_test_assert(sloth_ids_equal(widget->id, id_at));
|
||
|
}
|
||
|
|
||
|
// Naive string sizing
|
||
|
Sloth_V2
|
||
|
sloth_test_get_text_size(Sloth_Widget* widget)
|
||
|
{
|
||
|
Sloth_V2 result = {
|
||
|
.x = widget->text_len * 14,
|
||
|
.y = 14,
|
||
|
};
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
// The error this is trying to catch takes place across three frames
|
||
|
// Frame 1: all widgets are drawn
|
||
|
// Frame 2: a widget early in teh tree is removed
|
||
|
// Frame 3: a widget late in the tree is removed
|
||
|
// importantly, this widget comes after a widget that
|
||
|
// has children. ie. The tree must look like:
|
||
|
// root
|
||
|
// <removed on frame 1>
|
||
|
// widget
|
||
|
// child
|
||
|
// <removed on frame 2>
|
||
|
void
|
||
|
sloth_test_multi_frame_removal_frame(Sloth_Ctx* sloth, int num_to_remove)
|
||
|
{
|
||
|
Sloth_Widget_Desc d = {};
|
||
|
sloth_frame_prepare(sloth);
|
||
|
|
||
|
sloth_push_widget(sloth, d, "Root"); // root
|
||
|
{
|
||
|
if (num_to_remove < 1) {
|
||
|
sloth_push_widget(sloth, d, "remove 1");
|
||
|
sloth_pop_widget(sloth);
|
||
|
}
|
||
|
|
||
|
sloth_push_widget(sloth, d, "bar_bounds_inner");
|
||
|
{
|
||
|
sloth_push_widget(sloth, d, "fg_bar");
|
||
|
sloth_pop_widget(sloth);
|
||
|
}
|
||
|
sloth_pop_widget(sloth);
|
||
|
|
||
|
if (num_to_remove < 2) {
|
||
|
sloth_push_widget(sloth, d, "remove 2");
|
||
|
sloth_pop_widget(sloth);
|
||
|
}
|
||
|
}
|
||
|
sloth_pop_widget(sloth);
|
||
|
|
||
|
sloth_frame_advance(sloth);
|
||
|
}
|
||
|
void
|
||
|
sloth_test_multi_frame_removal_frame_b(Sloth_Ctx* sloth, int num_to_remove)
|
||
|
{
|
||
|
Sloth_Widget_Desc d = {};
|
||
|
sloth_frame_prepare(sloth);
|
||
|
|
||
|
sloth_push_widget(sloth, d, "Root"); // root
|
||
|
{
|
||
|
if (num_to_remove < 1) {
|
||
|
sloth_push_widget(sloth, d, "remove 1");
|
||
|
sloth_pop_widget(sloth);
|
||
|
}
|
||
|
|
||
|
sloth_push_widget(sloth, d, "a");
|
||
|
{
|
||
|
sloth_push_widget(sloth, d, "bar_bounds_inner");
|
||
|
{
|
||
|
sloth_push_widget(sloth, d, "fg_bar");
|
||
|
sloth_pop_widget(sloth);
|
||
|
}
|
||
|
sloth_pop_widget(sloth);
|
||
|
|
||
|
if (num_to_remove < 2) {
|
||
|
sloth_push_widget(sloth, d, "remove 2");
|
||
|
sloth_pop_widget(sloth);
|
||
|
}
|
||
|
}
|
||
|
sloth_pop_widget(sloth);
|
||
|
}
|
||
|
sloth_pop_widget(sloth);
|
||
|
|
||
|
sloth_frame_advance(sloth);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
sloth_test_multi_frame_removal()
|
||
|
{
|
||
|
Sloth_Ctx sloth = {};
|
||
|
sloth_test_multi_frame_removal_frame(&sloth, 0);
|
||
|
sloth_test_multi_frame_removal_frame(&sloth, 1);
|
||
|
sloth_test_multi_frame_removal_frame(&sloth, 2);
|
||
|
sloth_ctx_free(&sloth);
|
||
|
|
||
|
sloth = (Sloth_Ctx){};
|
||
|
sloth_test_multi_frame_removal_frame_b(&sloth, 0);
|
||
|
sloth_test_multi_frame_removal_frame_b(&sloth, 1);
|
||
|
sloth_test_multi_frame_removal_frame_b(&sloth, 2);
|
||
|
sloth_ctx_free(&sloth);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
sloth_tests()
|
||
|
{
|
||
|
|
||
|
sloth_test_assert(sloth_is_pow2(2048));
|
||
|
sloth_test_assert(!sloth_is_pow2(1920));
|
||
|
|
||
|
// ID Creation Tests
|
||
|
char test_id_str[] = "Test id##53";
|
||
|
int test_id_str_len = (sizeof(test_id_str) / sizeof(char)) - 1;
|
||
|
|
||
|
Sloth_ID_Result id0 = sloth_make_id(test_id_str);
|
||
|
sloth_test_assert(id0.id.value != 0);
|
||
|
sloth_test_assert(id0.display_len == test_id_str_len - 4);
|
||
|
|
||
|
Sloth_ID_Result id1 = sloth_make_id_len(11, "Test id##53");
|
||
|
sloth_test_assert(id0.id.value == id1.id.value);
|
||
|
|
||
|
Sloth_ID_Result id2 = sloth_make_id_f("Test id###%d", 53);
|
||
|
sloth_test_assert(id2.id.value != 0);
|
||
|
sloth_test_assert(id2.id.value != id0.id.value);
|
||
|
sloth_test_assert(id2.display_len == 7);
|
||
|
|
||
|
// Vectors
|
||
|
Sloth_V2 va = { 25, 32.1f };
|
||
|
Sloth_V2 vb = { 19, 18.1f };
|
||
|
|
||
|
Sloth_V2 rv0 = sloth_v2_add(va, vb);
|
||
|
sloth_test_assert(sloth_r32_equals(rv0.x, 44));
|
||
|
sloth_test_assert(sloth_r32_equals(rv0.y, 50.2f));
|
||
|
|
||
|
Sloth_V2 rv1 = sloth_v2_sub(va, vb);
|
||
|
sloth_test_assert(sloth_r32_equals(rv1.x, 6));
|
||
|
sloth_test_assert(sloth_r32_equals(rv1.y, 14));
|
||
|
|
||
|
Sloth_V2 rv2 = sloth_v2_mulf(va, 2);
|
||
|
sloth_test_assert(sloth_r32_equals(rv2.x, 50));
|
||
|
sloth_test_assert(sloth_r32_equals(rv2.y, 64.2f));
|
||
|
|
||
|
// Rects
|
||
|
// baseline rect
|
||
|
Sloth_Rect rect0 = {
|
||
|
.value_min = { 0, 0 },
|
||
|
.value_max = { 100, 100 },
|
||
|
};
|
||
|
// overlaps rect0 to right and top
|
||
|
Sloth_Rect rect1 = {
|
||
|
.value_min = { 50, 50 },
|
||
|
.value_max = { 150, 150 },
|
||
|
};
|
||
|
// overlaps rect1 to the left and bottom
|
||
|
Sloth_Rect rect2 = {
|
||
|
.value_min = { -50, -50 },
|
||
|
.value_max = { 50, 50 },
|
||
|
};
|
||
|
// no overlap with rect0 to the left and bottom
|
||
|
Sloth_Rect rect3 = {
|
||
|
.value_min = { -250, -250 },
|
||
|
.value_max = { -200, -200 }
|
||
|
};
|
||
|
// no overlap with rect0 to the right and top
|
||
|
Sloth_Rect rect4 = {
|
||
|
.value_min = { 250, 250 },
|
||
|
.value_max = { 200, 200 }
|
||
|
};
|
||
|
// contains rect0
|
||
|
Sloth_Rect rect5 = {
|
||
|
.value_min = { -50, -50 },
|
||
|
.value_max = { 200, 200 }
|
||
|
};
|
||
|
|
||
|
Sloth_Rect rr0 = sloth_rect_union(rect0, rect1);
|
||
|
sloth_test_assert(rr0.value_min.x == 50 && rr0.value_min.y == 50);
|
||
|
sloth_test_assert(rr0.value_max.x == 100 && rr0.value_max.y == 100);
|
||
|
|
||
|
Sloth_Rect rr1 = sloth_rect_union(rect0, rect2);
|
||
|
sloth_test_assert(rr1.value_min.x == 0 && rr1.value_min.y == 0);
|
||
|
sloth_test_assert(rr1.value_max.x == 50 && rr1.value_max.y == 50);
|
||
|
|
||
|
Sloth_Rect rr2 = sloth_rect_union(rect0, rect3);
|
||
|
sloth_test_assert(rr2.value_min.x == 0 && rr2.value_min.y == 0);
|
||
|
sloth_test_assert(rr2.value_max.x == 0 && rr2.value_max.y == 0);
|
||
|
|
||
|
Sloth_Rect rr3 = sloth_rect_union(rect0, rect4);
|
||
|
sloth_test_assert(rr3.value_min.x == 0 && rr3.value_min.y == 0);
|
||
|
sloth_test_assert(rr3.value_max.x == 0 && rr3.value_max.y == 0);
|
||
|
|
||
|
Sloth_Rect rr4 = sloth_rect_union(rect0, rect5);
|
||
|
sloth_test_assert(rr4.value_min.x == 0 && rr4.value_min.y == 0);
|
||
|
sloth_test_assert(rr4.value_max.x == 100 && rr4.value_max.y == 100);
|
||
|
|
||
|
// contained by rect0
|
||
|
Sloth_V2 rectp0 = { 25, 25 };
|
||
|
// not contained by rect0 to the right and top
|
||
|
Sloth_V2 rectp1 = { 150, 150 };
|
||
|
// not contained by rect0 to the left and bottom
|
||
|
Sloth_V2 rectp2 = { -25, -25 };
|
||
|
|
||
|
sloth_test_assert(sloth_rect_contains(rect0, rectp0));
|
||
|
sloth_test_assert(!sloth_rect_contains(rect0, rectp1));
|
||
|
sloth_test_assert(!sloth_rect_contains(rect0, rectp2));
|
||
|
|
||
|
// Hashtable Tests
|
||
|
{
|
||
|
Sloth_Hashtable table = {};
|
||
|
sloth_hashtable_add(&table, 256, (Sloth_U8*)1);
|
||
|
sloth_hashtable_add(&table, 394, (Sloth_U8*)2);
|
||
|
sloth_hashtable_add(&table, 81932, (Sloth_U8*)3);
|
||
|
|
||
|
// this should force chaining
|
||
|
sloth_hashtable_add(&table, table.cap + 256, (Sloth_U8*)4);
|
||
|
|
||
|
Sloth_U64 v0 = (Sloth_U64)sloth_hashtable_get(&table, 256);
|
||
|
sloth_test_assert(v0 == 1);
|
||
|
Sloth_U64 v1 = (Sloth_U64)sloth_hashtable_get(&table, 394);
|
||
|
sloth_test_assert(v1 == 2);
|
||
|
Sloth_U64 v2 = (Sloth_U64)sloth_hashtable_get(&table, 81932);
|
||
|
sloth_test_assert(v2 == 3);
|
||
|
Sloth_U64 v3 = (Sloth_U64)sloth_hashtable_get(&table, table.cap + 256);
|
||
|
sloth_test_assert(v3 == 4);
|
||
|
|
||
|
// getting a value that's not present
|
||
|
Sloth_U64 vi = (Sloth_U64)sloth_hashtable_get(&table, 3333);
|
||
|
sloth_test_assert(vi == 0);
|
||
|
|
||
|
Sloth_Bool r0 = sloth_hashtable_rem(&table, 256);
|
||
|
sloth_test_assert(r0);
|
||
|
v0 = (Sloth_U64)sloth_hashtable_get(&table, 256);
|
||
|
sloth_test_assert(v0 == 0);
|
||
|
}
|
||
|
|
||
|
{ // Arena Tests
|
||
|
|
||
|
Sloth_Arena arena = {};
|
||
|
Sloth_U32* array_0 = sloth_arena_push_array(&arena, Sloth_U32, 32);
|
||
|
for (Sloth_U32 i = 0; i < 32; i++) array_0[i] = i;
|
||
|
sloth_test_assert(array_0 != 0);
|
||
|
|
||
|
Sloth_Arena_Loc old_at = sloth_arena_at(&arena);
|
||
|
sloth_test_assert(old_at.bucket_at == sizeof(Sloth_U32) * 32);
|
||
|
|
||
|
Sloth_U32* array_1 = sloth_arena_push_array(&arena, Sloth_U32, 32);
|
||
|
for (Sloth_U32 i = 0; i < 32; i++) array_1[i] = (i + 32);
|
||
|
sloth_test_assert(array_1 >= (array_0 + 32));
|
||
|
sloth_test_assert(array_1 != 0);
|
||
|
sloth_test_assert(array_0[31] == 31);
|
||
|
sloth_test_assert(array_1[0] == 32);
|
||
|
|
||
|
// testing memory reuse after popping
|
||
|
sloth_arena_pop(&arena, old_at);
|
||
|
// test that in debug mode, popped memory is cleared
|
||
|
// NOTE: that if we aren't in debug mode, sloth_test_assert evaluates to
|
||
|
// nothing, so the test won't run
|
||
|
for (Sloth_U32 i = 0; i < 32; i++) sloth_test_assert(array_1[i] == 0);
|
||
|
|
||
|
Sloth_U32* array_1b = sloth_arena_push_array(&arena, Sloth_U32, 32);
|
||
|
sloth_test_assert(array_1 == array_1b);
|
||
|
|
||
|
// testing memory reuse after clearing
|
||
|
sloth_arena_clear(&arena);
|
||
|
Sloth_U32* array_0b = sloth_arena_push_array(&arena, Sloth_U32, 32);
|
||
|
sloth_test_assert(array_0 == array_0b);
|
||
|
|
||
|
sloth_arena_free(&arena);
|
||
|
sloth_test_assert(!arena.buckets);
|
||
|
sloth_test_assert(!arena.buckets_len);
|
||
|
sloth_test_assert(!arena.buckets_cap);
|
||
|
sloth_test_assert(!arena.bucket_cap);
|
||
|
sloth_test_assert(!arena.curr_bucket_len);
|
||
|
}
|
||
|
|
||
|
{ // Gamma correction
|
||
|
Sloth_R32 r_in = 0.2f;
|
||
|
Sloth_R32 g_in = 0.5f;
|
||
|
Sloth_R32 b_in = 0.9f;
|
||
|
Sloth_R32 a_in = 0.1f;
|
||
|
Sloth_U32 color = (((Sloth_U32)(r_in * 255) << 24) |
|
||
|
((Sloth_U32)(g_in * 255) << 16) |
|
||
|
((Sloth_U32)(b_in * 255) << 8) |
|
||
|
((Sloth_U32)(a_in * 255)));
|
||
|
|
||
|
// gamma = 1, no change
|
||
|
Sloth_U32 color_out0 = sloth_color_apply_gamma(color, 1);
|
||
|
sloth_assert(color_out0 == color);
|
||
|
|
||
|
// gamma = 2.2, verify changes
|
||
|
Sloth_U32 color_out1 = sloth_color_apply_gamma(color, 2.2f);
|
||
|
Sloth_R32 r = (Sloth_R32)((color_out1 >> 24) & 0xFF) / 255.0f;
|
||
|
Sloth_R32 g = (Sloth_R32)((color_out1 >> 16) & 0xFF) / 255.0f;
|
||
|
Sloth_R32 b = (Sloth_R32)((color_out1 >> 8) & 0xFF) / 255.0f;
|
||
|
Sloth_R32 a = (Sloth_R32)((color_out1 ) & 0xFF) / 255.0f;
|
||
|
|
||
|
Sloth_R32 delta_r = fabsf(r - powf(r_in, 2.2f));
|
||
|
Sloth_R32 delta_g = fabsf(g - powf(g_in, 2.2f));
|
||
|
Sloth_R32 delta_b = fabsf(b - powf(b_in, 2.2f));
|
||
|
Sloth_R32 delta_a = fabsf(a - powf(a_in, 2.2f));
|
||
|
|
||
|
sloth_assert(delta_r < 0.01f);
|
||
|
sloth_assert(delta_g < 0.01f);
|
||
|
sloth_assert(delta_b < 0.01f);
|
||
|
sloth_assert(delta_a < 0.01f);
|
||
|
}
|
||
|
|
||
|
{ // Atlas Tests
|
||
|
Sloth_U32 test_icon[] = {
|
||
|
0xFFFFFFFF, 0x000000FF, 0xFFFFFFFF, 0x000000FF,
|
||
|
0x000000FF, 0xFFFFFFFF, 0x000000FF, 0xFFFFFFFF,
|
||
|
0xFFFFFFFF, 0x000000FF, 0xFFFFFFFF, 0x000000FF,
|
||
|
0x000000FF, 0xFFFFFFFF, 0x000000FF, 0xFFFFFFFF,
|
||
|
};
|
||
|
|
||
|
Sloth_Glyph_Atlas atlas = {};
|
||
|
sloth_glyph_atlas_resize(&atlas, 32);
|
||
|
|
||
|
Sloth_Glyph_Desc gd0 = {
|
||
|
.family = 1,
|
||
|
.id = 25,
|
||
|
.data = (Sloth_U8*)test_icon,
|
||
|
.width = 4,
|
||
|
.height = 4,
|
||
|
.stride = 4,
|
||
|
.format = Sloth_GlyphData_RGBA8,
|
||
|
};
|
||
|
Sloth_Glyph_ID id_0 = sloth_glyph_atlas_register(&atlas, gd0);
|
||
|
Sloth_U32 last_glyph = atlas.last_glyph;
|
||
|
sloth_test_assert(atlas.glyphs_table.used == 1);
|
||
|
|
||
|
// testing adding the same glyph a second time.
|
||
|
Sloth_Glyph_ID id_01 = sloth_glyph_atlas_register(&atlas, gd0);
|
||
|
sloth_test_assert(id_01.value == id_0.value);
|
||
|
sloth_test_assert(atlas.last_glyph == last_glyph);
|
||
|
sloth_test_assert(atlas.glyphs_table.used == 1); // no sprite was added
|
||
|
|
||
|
Sloth_Glyph_Desc gd2 = gd0;
|
||
|
gd2.id = 26;
|
||
|
Sloth_Glyph_ID id_2 = sloth_glyph_atlas_register(&atlas, gd2);
|
||
|
sloth_test_assert(id_2.value != 0);
|
||
|
|
||
|
Sloth_Glyph_Desc gd3 = gd0;
|
||
|
gd3.id = 27;
|
||
|
Sloth_Glyph_ID id_3 = sloth_glyph_atlas_register(&atlas, gd3);
|
||
|
sloth_test_assert(id_3.value != 0);
|
||
|
|
||
|
Sloth_Glyph_Desc gd4 = gd0;
|
||
|
gd4.id = 28;
|
||
|
Sloth_Glyph_ID id_4 = sloth_glyph_atlas_register(&atlas, gd4);
|
||
|
sloth_test_assert(id_4.value != 0);
|
||
|
sloth_test_assert(id_4.family == gd0.family);
|
||
|
sloth_test_assert(id_4.id[0] == 28 && id_4.id[1] == 0 && id_4.id[2] == 0);
|
||
|
|
||
|
Sloth_Glyph_Desc gd5 = gd0;
|
||
|
gd5.id = 29;
|
||
|
Sloth_Glyph_ID id_5 = sloth_glyph_atlas_register(&atlas, gd5);
|
||
|
sloth_test_assert(id_5.value != 0);
|
||
|
sloth_test_assert(id_5.family == 1);
|
||
|
sloth_test_assert(id_5.id[0] == 29 && id_5.id[1] == 0 && id_5.id[2] == 0);
|
||
|
|
||
|
sloth_glyph_atlas_free(&atlas);
|
||
|
|
||
|
// Glyph ID Tests
|
||
|
Sloth_Glyph_ID g_id = sloth_make_glyph_id(24, 'G');
|
||
|
Sloth_Glyph_ID newline_id = sloth_make_glyph_id(32, '\n');
|
||
|
Sloth_Glyph_ID space_id = sloth_make_glyph_id(127, ' ');
|
||
|
sloth_test_assert(sloth_glyph_id_matches_charcode(g_id, 'G'));
|
||
|
sloth_test_assert(sloth_glyph_id_matches_charcode(newline_id, '\n'));
|
||
|
sloth_test_assert(sloth_glyph_id_matches_charcode(space_id, ' '));
|
||
|
}
|
||
|
|
||
|
{ // Sloth_Size tests
|
||
|
|
||
|
// see @Maintenance tag in Sloth_Size_Box if this fails
|
||
|
Sloth_Size_Box b = {
|
||
|
.left = sloth_size_pixels(0),
|
||
|
.right = sloth_size_pixels(5),
|
||
|
.top = sloth_size_pixels(10),
|
||
|
.bottom = sloth_size_pixels(15),
|
||
|
};
|
||
|
|
||
|
// testing to make sure left corresponds to E[Axis_X].min
|
||
|
// and so on
|
||
|
sloth_test_assert(b.E[Sloth_Axis_X].min.value == 0);
|
||
|
sloth_test_assert(b.E[Sloth_Axis_X].max.value == 5);
|
||
|
sloth_test_assert(b.E[Sloth_Axis_Y].min.value == 10);
|
||
|
sloth_test_assert(b.E[Sloth_Axis_Y].max.value == 15);
|
||
|
}
|
||
|
|
||
|
// Widget Tree Construction
|
||
|
{
|
||
|
Sloth_Ctx sloth = {
|
||
|
.per_frame_memory.name = "pfm",
|
||
|
.scratch.name = "scratch",
|
||
|
};
|
||
|
|
||
|
Sloth_Widget_Desc d = {}; // these tests don't depend on the desc at all
|
||
|
Sloth_ID ids0_preorder[] = {
|
||
|
sloth_make_id_f("Root").id,
|
||
|
sloth_make_id_f("W1").id,
|
||
|
sloth_make_id_f("W11").id,
|
||
|
sloth_make_id_f("W12").id,
|
||
|
sloth_make_id_f("W2").id,
|
||
|
sloth_make_id_f("W3").id,
|
||
|
sloth_make_id_f("W31").id
|
||
|
};
|
||
|
Sloth_ID ids0_postorder[] = {
|
||
|
sloth_make_id_f("W11").id,
|
||
|
sloth_make_id_f("W12").id,
|
||
|
sloth_make_id_f("W1").id,
|
||
|
sloth_make_id_f("W2").id,
|
||
|
sloth_make_id_f("W31").id,
|
||
|
sloth_make_id_f("W3").id,
|
||
|
sloth_make_id_f("Root").id,
|
||
|
};
|
||
|
printf("Frame 1\n");
|
||
|
sloth_frame_prepare(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "Root"); // root
|
||
|
sloth_push_widget(&sloth, d, "W1");
|
||
|
sloth_push_widget(&sloth, d, "W11"); sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W12"); sloth_pop_widget(&sloth);
|
||
|
sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W2"); sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W3");
|
||
|
sloth_push_widget(&sloth, d, "W31"); sloth_pop_widget(&sloth);
|
||
|
sloth_pop_widget(&sloth);
|
||
|
sloth_pop_widget(&sloth); // root - won't pop
|
||
|
|
||
|
// walking the tree
|
||
|
sloth_test_assert(sloth.widget_tree_root != 0);
|
||
|
sloth_test_assert(sloth.widget_tree_depth_max == 3);
|
||
|
sloth_test_widget_order_count = 0; // reset test
|
||
|
sloth_tree_walk_preorder(&sloth, sloth_test_widget_order, (Sloth_U8*)&ids0_preorder);
|
||
|
sloth_test_widget_order_count = 0; // reset test
|
||
|
sloth_tree_walk_postorder(&sloth, sloth_test_widget_order, (Sloth_U8*)&ids0_postorder);
|
||
|
//sloth_widget_tree_print(&sloth);
|
||
|
|
||
|
sloth_frame_advance(&sloth);
|
||
|
printf("Frame 2\n");
|
||
|
sloth_frame_prepare(&sloth);
|
||
|
|
||
|
// Same Frame as above
|
||
|
sloth_push_widget(&sloth, d, "Root"); // root
|
||
|
sloth_push_widget(&sloth, d, "W1");
|
||
|
sloth_push_widget(&sloth, d, "W11"); sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W12"); sloth_pop_widget(&sloth);
|
||
|
sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W2"); sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W3");
|
||
|
sloth_push_widget(&sloth, d, "W31"); sloth_pop_widget(&sloth);
|
||
|
sloth_pop_widget(&sloth);
|
||
|
sloth_pop_widget(&sloth); // root - won't pop
|
||
|
|
||
|
// walking the tree
|
||
|
sloth_test_assert(sloth.widget_tree_root != 0);
|
||
|
sloth_test_widget_order_count = 0; // reset test
|
||
|
sloth_tree_walk_preorder(&sloth, sloth_test_widget_order, (Sloth_U8*)&ids0_preorder);
|
||
|
|
||
|
sloth_frame_advance(&sloth);
|
||
|
sloth_frame_prepare(&sloth);
|
||
|
|
||
|
// Different frame from above
|
||
|
Sloth_ID ids1[] = {
|
||
|
sloth_make_id_f("Root").id,
|
||
|
sloth_make_id_f("W1").id,
|
||
|
sloth_make_id_f("W11").id,
|
||
|
sloth_make_id_f("W13").id,
|
||
|
sloth_make_id_f("W14").id,
|
||
|
sloth_make_id_f("W12").id,
|
||
|
sloth_make_id_f("W2").id,
|
||
|
sloth_make_id_f("W21").id,
|
||
|
sloth_make_id_f("W3").id,
|
||
|
};
|
||
|
sloth_push_widget(&sloth, d, "Root"); // root
|
||
|
sloth_push_widget(&sloth, d, "W1");
|
||
|
sloth_push_widget(&sloth, d, "W11"); sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W13"); sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W14"); sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W12"); sloth_pop_widget(&sloth);
|
||
|
sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W2");
|
||
|
sloth_push_widget(&sloth, d, "W21"); sloth_pop_widget(&sloth);
|
||
|
sloth_pop_widget(&sloth);
|
||
|
sloth_push_widget(&sloth, d, "W3");
|
||
|
// old child should get freed
|
||
|
sloth_pop_widget(&sloth);
|
||
|
sloth_pop_widget(&sloth); // root - won't pop
|
||
|
|
||
|
sloth_test_widget_order_count = 0; // reset test
|
||
|
sloth_tree_walk_preorder(&sloth, sloth_test_widget_order, (Sloth_U8*)&ids1);
|
||
|
|
||
|
sloth_ctx_free(&sloth);
|
||
|
}
|
||
|
|
||
|
|
||
|
// Widget Tree - Removing Expected Next Sibling
|
||
|
sloth_test_multi_frame_removal();
|
||
|
|
||
|
// Widget Sizing
|
||
|
{
|
||
|
Sloth_Ctx sloth = {
|
||
|
};
|
||
|
|
||
|
sloth_frame_prepare(&sloth);
|
||
|
|
||
|
Sloth_Widget_Desc ele_desc;
|
||
|
Sloth_Widget_Desc root_desc = {
|
||
|
.layout = {
|
||
|
.width = sloth_size_pixels(800),
|
||
|
.height = sloth_size_pixels(900),
|
||
|
//.margin.top = sloth_size_pixels(32),
|
||
|
.direction = Sloth_LayoutDirection_TopDown,
|
||
|
},
|
||
|
.style.color_bg = 0x333333FF,
|
||
|
};
|
||
|
sloth_push_widget(&sloth, root_desc, "root");
|
||
|
ele_desc = (Sloth_Widget_Desc){
|
||
|
.layout = {
|
||
|
.width = sloth_size_pixels(850),
|
||
|
.height = sloth_size_pixels(200),
|
||
|
},
|
||
|
.style.color_bg = 0xFFFFFFFF,
|
||
|
};
|
||
|
sloth_push_widget(&sloth, ele_desc, "ele0"); sloth_pop_widget(&sloth);
|
||
|
ele_desc.style.color_bg = 0xFF00FFFF;
|
||
|
sloth_push_widget(&sloth, ele_desc, "ele1"); sloth_pop_widget(&sloth);
|
||
|
sloth_pop_widget(&sloth);
|
||
|
|
||
|
printf("==/==\n");
|
||
|
sloth_frame_advance(&sloth);
|
||
|
sloth_frame_prepare(&sloth);
|
||
|
|
||
|
Sloth_Widget* root = sloth.widget_tree_next_child;
|
||
|
sloth_test_assert(root->cached->offset.x == 0 && root->cached->offset.y == 0);
|
||
|
sloth_test_assert(root->cached->dim.x == 800 && root->cached->dim.y == 900);
|
||
|
|
||
|
Sloth_Widget* ele0 = root->child_first;
|
||
|
sloth_test_assert(ele0->cached->offset.x == 0 && ele0->cached->offset.y == 0);
|
||
|
sloth_test_assert(ele0->cached->dim.x == 800 && ele0->cached->dim.y == 200);
|
||
|
|
||
|
Sloth_Widget* ele1 = ele0->sibling_next;
|
||
|
sloth_test_assert(ele1->cached->offset.x == 0 && ele1->cached->offset.y == 200);
|
||
|
sloth_test_assert(ele1->cached->dim.x == 800 && ele1->cached->dim.y == 200);
|
||
|
|
||
|
sloth_ctx_free(&sloth);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
sloth_test_button_f(Sloth_Ctx* sloth, char* fmt, ...)
|
||
|
{
|
||
|
Sloth_Widget_Desc desc = {
|
||
|
.layout = {
|
||
|
.width = sloth_size_text_content(),
|
||
|
.height = sloth_size_text_content(),
|
||
|
.margin = {
|
||
|
.left = sloth_size_pixels(12),
|
||
|
.right = sloth_size_pixels(12),
|
||
|
.top = sloth_size_pixels(0),
|
||
|
.bottom = sloth_size_pixels(8),
|
||
|
},
|
||
|
},
|
||
|
.style = {
|
||
|
.color_bg = 0x333333FF,
|
||
|
.color_text = 0xFFFFFFFF,
|
||
|
.color_outline = 0xFFFFFFFF,
|
||
|
.outline_thickness = 1,
|
||
|
.text_style = Sloth_TextStyle_Align_Center,
|
||
|
},
|
||
|
};
|
||
|
va_list args; va_start(args, fmt);
|
||
|
Sloth_Widget_Result r = sloth_push_widget_v(sloth, desc, fmt, args);
|
||
|
va_end(args);
|
||
|
sloth_pop_widget(sloth);
|
||
|
|
||
|
if (r.clicked) {
|
||
|
r.widget->style.color_bg = 0xFFFFFFFF;
|
||
|
r.widget->style.color_text = 0x333333FF;
|
||
|
}
|
||
|
|
||
|
return r.clicked;
|
||
|
}
|
||
|
|
||
|
Sloth_R32
|
||
|
sloth_test_slider_f(Sloth_Ctx* sloth, Sloth_R32 min, Sloth_R32 max, Sloth_R32 v, char* fmt, ...)
|
||
|
{
|
||
|
Sloth_Widget_Desc desc = {
|
||
|
.layout = {
|
||
|
.width = sloth_size_pixels(128),
|
||
|
.height = sloth_size_pixels(32),
|
||
|
},
|
||
|
.style = {
|
||
|
.color_bg = 0x333333FF,
|
||
|
.color_outline = 0xFFFFFFFF,
|
||
|
.outline_thickness = 1,
|
||
|
},
|
||
|
.input.flags = Sloth_WidgetInput_Draggable
|
||
|
};
|
||
|
|
||
|
va_list args; va_start(args, fmt);
|
||
|
Sloth_Widget_Result r = sloth_push_widget_v(sloth, desc, fmt, args);
|
||
|
va_end(args);
|
||
|
|
||
|
// background text
|
||
|
Sloth_Widget_Desc bg_text_desc = {
|
||
|
.layout = {
|
||
|
.width = sloth_size_percent_parent(1),
|
||
|
.height = sloth_size_percent_parent(1),
|
||
|
.position = {
|
||
|
.kind= Sloth_LayoutPosition_FixedInParent,
|
||
|
.left = sloth_size_pixels(0),
|
||
|
.top = sloth_size_pixels(0),
|
||
|
},
|
||
|
.margin.left = sloth_size_pixels(8),
|
||
|
},
|
||
|
.style = {
|
||
|
.color_text = 0xFFFFFFFF,
|
||
|
.text_style = Sloth_TextStyle_NoWrapText
|
||
|
},
|
||
|
.input.flags = Sloth_WidgetInput_DoNotCaptureMouse,
|
||
|
};
|
||
|
sloth_push_widget_f(sloth, bg_text_desc, "%f###%d_bg", v, r.widget->id.value);
|
||
|
sloth_pop_widget(sloth);
|
||
|
|
||
|
// slider bar
|
||
|
Sloth_R32 pct = (v - min) / (max - min);
|
||
|
Sloth_Widget_Desc slider_desc = {
|
||
|
.layout = {
|
||
|
.width = sloth_size_percent_parent(pct),
|
||
|
.height = sloth_size_percent_parent(1),
|
||
|
.margin.left = sloth_size_pixels(8),
|
||
|
},
|
||
|
.style = {
|
||
|
.color_bg = 0x00FFFFFF,
|
||
|
.color_text = 0x000000FF,
|
||
|
.text_style = Sloth_TextStyle_NoWrapText
|
||
|
},
|
||
|
.input.flags = Sloth_WidgetInput_DoNotCaptureMouse
|
||
|
};
|
||
|
Sloth_Widget_Result rs = sloth_push_widget_f(sloth, slider_desc, "%f###%d_slider", v, r.widget->id.value);
|
||
|
//printf("%d\n", r.widget->id.value);
|
||
|
sloth_pop_widget(sloth);
|
||
|
|
||
|
sloth_pop_widget(sloth);
|
||
|
|
||
|
|
||
|
if (r.clicked) {
|
||
|
rs.widget->style.color_bg = 0xFFFFFFFF;
|
||
|
}
|
||
|
|
||
|
Sloth_R32 result = v;
|
||
|
if (r.held) {
|
||
|
Sloth_R32 width = sloth_rect_dim(r.widget->cached->bounds).x;
|
||
|
Sloth_R32 init_pct = (sloth->mouse_down_pos.x - r.widget->cached->bounds.value_min.x) / width;
|
||
|
Sloth_R32 dx = r.drag_offset_pixels.x;
|
||
|
Sloth_R32 px = dx / width;
|
||
|
result = ((px + init_pct) * (max - min)) + min;
|
||
|
result = Sloth_Max(min, Sloth_Min(max, result));
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|