fn void mt_ui_colors(ma_arena_t *arena, sb8_t *c, sb8_t *h) { ast_t *table = mtt_parse(arena, __FILE__, S8_CODE( { name color } { rect_color `v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.2f, 0.95f, 1.0f})` } { rect_hot_color `v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.5f, 0.95f, 1.0f})` } { rect_active_color `v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.5f, 0.95f, 1.0f})` } { border_color `v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.2f, 0.70f, 1.0f})` } { text_color `v4f32_hsla_to_rgba((v4f32_t){0.0f, 0.2f, 0.70f, 1.0f})` } { text_hot_color `v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.4f, 0.70f, 1.0f})` } { text_active_color `v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.5f, 0.70f, 1.0f})` } { focused_rect_color `v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.6f, 0.95f, 1.0f})` } { scroller_color `v4f32_hsla_to_rgba((v4f32_t){0.1f, 0.6f, 0.95f, 1.0f})` } )); mtt_serial_enum(c, h, table, s8_lit("ui_color")); sb8_stmtf(c, "gb v4f32_t ui_color_table[] = {"); for (ast_t *it = table->first; it; it = it->next) { mt_stmtf(c, it, "{0},"); } sb8_stmtf(c, "};\n"); sb8_stmtf(c, "fn void ui_init_colors(void) {"); for (ast_t *it = table->first; it; it = it->next) { mt_stmtf(c, it, "ui_color_table[ui_color_@name] = @color;"); } sb8_stmtf(c, "}\n"); } fn void mt_ui_stacks(ma_arena_t *arena, sb8_t *c, sb8_t *h) { ast_t *table = mtt_parse(arena, __FILE__, S8_CODE( // skip = don't include in ui_box_t as field { type name skip init } { ui_id_t id 1 `ui_idf("root")` } { ui_lop_t lop 1 ui_lop_cut_top } { f32 border_thickness 0 1.0f } { ui_text_align_t text_align 0 ui_text_align_left } { f32 required_size 0 x } { f32 padding 0 x } { f32 string_pos_offset 0 0 } { v4f32_t background_color 0 `ui_color_table[ui_color_rect_color]` } { v4f32_t bg_hot_color 0 `ui_color_table[ui_color_rect_hot_color]` } { v4f32_t bg_active_color 0 `ui_color_table[ui_color_rect_active_color]` } { v4f32_t border_color 0 `ui_color_table[ui_color_border_color]` } { v4f32_t text_color 0 `ui_color_table[ui_color_text_color]` } { v4f32_t text_hot_color 0 `ui_color_table[ui_color_text_hot_color]` } { v4f32_t text_active_color 0 `ui_color_table[ui_color_text_active_color]` } )); /////////////////////////////// // create `stack` and `node` columns for (ast_t *it = table->first; it; it = it->next) { s8_t type = mtts(it, "type"); if (s8_ends_with(type, s8_lit("_t"), false)) { type = s8_chop(type, 2); } s8_t ui_type = type; if (!s8_starts_with(ui_type, s8_lit("ui_"), false)) { ui_type = s8_printf(arena, "ui_%S", ui_type); } s8_t node = s8_printf(arena, "%S_node_t", ui_type); s8_t stack = s8_printf(arena, "%S_stack", mtts(it, "name")); mt_ast_append(it, mt_kv(arena, s8_lit("node"), node)); mt_ast_append(it, mt_kv(arena, s8_lit("stack"), stack)); } /////////////////////////////// // generate types for (ast_t *it = table->first; it; it = it->next) { for (ast_t *prev = table->first; prev != it; prev = prev->next) { if (s8_are_equal(mtts(it, "type"), mtts(prev, "type"))) goto type_already_gened; } mt_stmtf(h, it, "typedef struct @node @node; struct @node { @type value; @node *next; };"); type_already_gened:; } /////////////////////////////// // generate field embeds sb8_stmtf(h, "#define UI_DECL_BOX_MEMBERS \\"); for (ast_t *it = table->first; it; it = it->next) { if (mtt(it, "skip")->integer) continue; mt_stmtf(h, it, "@type @name;\\"); } sb8_printf(h, "\n"); sb8_stmtf(h, "#define UI_DECL_STACKS \\"); for (ast_t *it = table->first; it; it = it->next) { mt_stmtf(h, it, "@node *@stack;\\"); } sb8_printf(h, "\n"); /////////////////////////////// // generate stack functions for (ast_t *it = table->first; it; it = it->next) { mt_sbprintf(c, it, "fn void ui_push_@name(@type v) { @node *n = ma_push_type(tcx.temp, @node); n->value = v; SLLS_PUSH(ui->@stack, n); }\n" "fn void ui_pop_@name(void) { SLLS_POP(ui->@stack); }\n" "fn @type ui_top_@name(void) { return ui->@stack->value; }\n" "#define ui_set_@name(x) defer_block(ui_push_@name(x), ui_pop_@name())\n"); } /////////////////////////////// // generate init stack functions sb8_stmtf(c, "fn void ui_assert_stacks_are_null(void) {"); for (ast_t *it = table->first; it; it = it->next) { mt_stmtf(c, it, "assert(ui->@stack == NULL);"); } sb8_stmtf(c, "}"); sb8_stmtf(c, "fn void ui_push_init_values(void) {"); for (ast_t *it = table->first; it; it = it->next) { if (s8_are_equal(mtts(it, "init"), s8_lit("x"))) { continue; } mt_stmtf(c, it, "ui_push_@name(@init);"); } sb8_stmtf(c, "}"); sb8_stmtf(c, "fn void ui_pop_init_values(void) {"); for (ast_t *it = table->first; it; it = it->next) { if (s8_are_equal(mtts(it, "init"), s8_lit("x"))) { continue; } mt_stmtf(c, it, "ui_pop_@name();"); } sb8_stmtf(c, "}"); sb8_stmtf(c, "fn void ui_box_fill_with_colors(ui_box_t *box) {"); for (ast_t *it = table->first; it; it = it->next) { if (!s8_ends_with(mtts(it, "name"), s8_lit("_color"), false)) { continue; } mt_stmtf(c, it, "box->@name = ui_top_@name();"); } sb8_stmtf(c, "}"); } fn void mt_ui(ma_arena_t *arena) { sb8_t *h = sb8_serial_begin(arena); sb8_t *c = sb8_serial_begin(arena); sb8_printf(h, "// automatically generated using: " __FILE__ "\n"); sb8_printf(c, "// automatically generated using: " __FILE__ "\n"); mt_ui_colors(arena, c, h); mt_ui_stacks(arena, c, h); os_write_file(mt_cpath(arena), sb8_serial_end(arena, c)); os_write_file(mt_hpath(arena), sb8_serial_end(arena, h)); }