#include <alias/cpp.h>
#include <alias/ash.h>
#include <alias/data_structure/vector.h>
#include <alias/log.h>
#include <alias/ui.h>
#include <stdio.h>
#define MAX_SCOPES 32
struct scope {
alias_R font_size;
alias_Color font_color;
uint32_t shape;
alias_R args[8];
alias_R flex;
alias_R total_flex;
alias_R alignment;
void (*begin_child)(alias_ui *);
void (*end_child)(alias_ui *);
void (*end_scope)(alias_ui *);
void (*align)(alias_ui *, float x, float y);
};
struct shape {
alias_R x, y, w, h;
};
struct alias_ui {
alias_ash_Program layout_program;
alias_ash_Program render_program;
alias_MemoryCB *mcb;
alias_ui_Output *output;
uint32_t scope_index_p1;
struct scope scopes[MAX_SCOPES];
alias_Vector(uint8_t) memory;
alias_ui_TextSizeFn text_size;
alias_ui_TextDrawFn text_draw;
uint32_t max_num_vertexes;
uint32_t max_num_indexes;
uint32_t max_num_groups;
};
static struct scope *_scope(alias_ui *ui) { return ui->scope_index_p1 > 0 ? &ui->scopes[ui->scope_index_p1 - 1] : NULL; }
static inline void _begin_child(alias_ui *ui) {
struct scope *s = _scope(ui);
if(s && s->begin_child) {
s->begin_child(ui);
}
}
static inline void _end_child(alias_ui *ui) {
struct scope *s = _scope(ui);
if(s->end_child) {
s->end_child(ui);
}
}
static inline void _begin_scope(alias_ui *ui, void (*begin_child)(alias_ui *), void (*end_child)(alias_ui *), void (*end_scope)(alias_ui *)) {
struct scope *p = _scope(ui);
struct scope *s = &ui->scopes[ui->scope_index_p1++];
s->font_size = p ? p->font_size : 10;
s->font_color = p ? p->font_color : alias_Color_WHITE;
s->flex = alias_R_ZERO;
s->total_flex = alias_R_ZERO;
s->begin_child = begin_child;
s->end_child = end_child;
s->end_scope = end_scope;
s->alignment = 0.5f;
s->align = NULL;
}
static inline void _end_scope(alias_ui *ui) {
struct scope *s = _scope(ui);
if(s) {
ui->scope_index_p1--;
if(s->end_scope) {
s->end_scope(ui);
}
}
}
static inline uint32_t _alloc(alias_ui *ui, uint32_t size) {
alias_Vector_space_for(&ui->memory, ui->mcb, size);
uint32_t result = ui->memory.length;
ui->memory.length += size;
return result;
}
static inline void *_mem(alias_ui *ui, uint32_t position) { return ui->memory.data + position; }
#define SHAPE(X) ((struct shape *)(ui->memory.data + (X)))
static void _layout_shape_set_x(alias_ash *ash) {
alias_ui *ui = (alias_ui *)ash->user_data;
uint32_t ptr = alias_ash_pop(ash);
SHAPE(ptr)->x = alias_ash_pop_R(ash);
}
static void _layout_shape_set_y(alias_ash *ash) {
alias_ui *ui = (alias_ui *)ash->user_data;
uint32_t ptr = alias_ash_pop(ash);
SHAPE(ptr)->y = alias_ash_pop_R(ash);
}
static void _layout_shape_set_w(alias_ash *ash) {
alias_ui *ui = (alias_ui *)ash->user_data;
uint32_t ptr = alias_ash_pop(ash);
SHAPE(ptr)->w = alias_ash_pop_R(ash);
}
static void _layout_shape_set_h(alias_ash *ash) {
alias_ui *ui = (alias_ui *)ash->user_data;
uint32_t ptr = alias_ash_pop(ash);
SHAPE(ptr)->h = alias_ash_pop_R(ash);
}
static void _render_shape_get_x(alias_ash *ash) {
alias_ui *ui = (alias_ui *)ash->user_data;
uint32_t ptr = alias_ash_pop(ash);
alias_ash_push_R(ash, SHAPE(ptr)->x);
}
static void _render_shape_get_y(alias_ash *ash) {
alias_ui *ui = (alias_ui *)ash->user_data;
uint32_t ptr = alias_ash_pop(ash);
alias_ash_push_R(ash, SHAPE(ptr)->y);
}
static void _render_shape_get_w(alias_ash *ash) {
alias_ui *ui = (alias_ui *)ash->user_data;
uint32_t ptr = alias_ash_pop(ash);
alias_ash_push_R(ash, SHAPE(ptr)->w);
}
static void _render_shape_get_h(alias_ash *ash) {
alias_ui *ui = (alias_ui *)ash->user_data;
uint32_t ptr = alias_ash_pop(ash);
alias_ash_push_R(ash, SHAPE(ptr)->h);
}
static void _textv_layout(alias_ash *ash);
static void _textv_render(alias_ash *ash);
static int _emit_point(alias_ui *ui, float x, float y, float r, float g, float b, float a, float s, float t) {
float xy[] = {x, y};
float rgba[] = {r, g, b, a};
float st[] = {s, t};
alias_memory_SubBuffer_write(&ui->output->xy_sub_buffer, ui->output->num_vertexes, 1, alias_memory_Format_Float32, 0, xy);
alias_memory_SubBuffer_write(&ui->output->rgba_sub_buffer, ui->output->num_vertexes, 1, alias_memory_Format_Float32, 0, rgba);
alias_memory_SubBuffer_write(&ui->output->st_sub_buffer, ui->output->num_vertexes, 1, alias_memory_Format_Float32, 0, st);
return ui->output->num_vertexes++;
}
static void _emit_triangle(alias_ui *ui, int p1, int p2, int p3) {
int p[] = {p1, p2, p3};
alias_memory_SubBuffer_write(&ui->output->index_sub_buffer, ui->output->num_indexes, 3, alias_memory_Format_Sint32, 0, p);
ui->output->num_indexes += 3;
}
void alias_ui_SetTexture(alias_ui *ui, uint32_t texture_id) {
if(ui->output->groups[ui->output->num_groups - 1].texture_id != texture_id) {
if(ui->output->groups[ui->output->num_groups - 1].index != ui->output->num_indexes) {
ui->output->groups[ui->output->num_groups - 1].length = ui->output->num_indexes - ui->output->groups[ui->output->num_groups - 1].index;
ui->output->num_groups++;
}
ui->output->groups[ui->output->num_groups - 1].texture_id = texture_id;
ui->output->groups[ui->output->num_groups - 1].index = ui->output->num_indexes;
}
}
static void _set_texture(alias_ash *ash) {
uint32_t texture_id = alias_ash_pop(ash);
alias_ui *ui = (alias_ui *)ash->user_data;
alias_ui_SetTexture(ui, texture_id);
}
static void _rect_fill_c(alias_ash *ash) {
float a = alias_ash_pop_R(ash);
float b = alias_ash_pop_R(ash);
float g = alias_ash_pop_R(ash);
float r = alias_ash_pop_R(ash);
float h = alias_ash_pop_R(ash);
float w = alias_ash_pop_R(ash);
float y = alias_ash_pop_R(ash);
float x = alias_ash_pop_R(ash);
alias_ui *ui = (alias_ui *)ash->user_data;
int p1 = _emit_point(ui, x, y, r, g, b, a, 0, 0);
int p2 = _emit_point(ui, x + w, y, r, g, b, a, 1, 0);
int p3 = _emit_point(ui, x + w, y + h, r, g, b, a, 1, 1);
int p4 = _emit_point(ui, x, y + h, r, g, b, a, 0, 1);
_emit_triangle(ui, p2, p1, p3);
_emit_triangle(ui, p3, p1, p4);
}
static void _rect_fill_st(alias_ash *ash) {
float t1 = alias_ash_pop_R(ash);
float s1 = alias_ash_pop_R(ash);
float t0 = alias_ash_pop_R(ash);
float s0 = alias_ash_pop_R(ash);
float h = alias_ash_pop_R(ash);
float w = alias_ash_pop_R(ash);
float y = alias_ash_pop_R(ash);
float x = alias_ash_pop_R(ash);
alias_ui *ui = (alias_ui *)ash->user_data;
int p1 = _emit_point(ui, x, y, 1, 1, 1, 1, s0, t0);
int p2 = _emit_point(ui, x + w, y, 1, 1, 1, 1, s1, t0);
int p3 = _emit_point(ui, x + w, y + h, 1, 1, 1, 1, s1, t1);
int p4 = _emit_point(ui, x, y + h, 1, 1, 1, 1, s0, t1);
_emit_triangle(ui, p2, p1, p3);
_emit_triangle(ui, p3, p1, p4);
}
void alias_ui_EmitRect(alias_ui *ui, float x, float y, float w, float h, float s0, float t0, float s1, float t1, float r, float g, float b, float a) {
int p1 = _emit_point(ui, x, y, r, g, b, a, s0, t0);
int p2 = _emit_point(ui, x + w, y, r, g, b, a, s1, t0);
int p3 = _emit_point(ui, x + w, y + h, r, g, b, a, s1, t1);
int p4 = _emit_point(ui, x, y + h, r, g, b, a, s0, t1);
_emit_triangle(ui, p2, p1, p3);
_emit_triangle(ui, p3, p1, p4);
}
static void _standard_library(alias_ash_Program *program, alias_MemoryCB *mcb) {
ALIAS_ASH_EMIT(program, mcb,
fn(dip ,
swap, r_push, call, r_pop)
,
fn(dip2 ,
rot, r_push, r_push, call, r_pop, r_pop)
,
fn(keep ,
swap, dup, r_push, call, r_pop)
,
fn(f2_zip ,
r_push ,
rot, swap ,
r_at, call ,
irot ,
r_pop, call ,
swap)
,
fn(f2_add ,
(f_add), f2_zip)
,
fn(f2_sub ,
(f_sub), f2_zip)
,
fn(f2_min ,
(f_min), f2_zip)
,
fn(f2_max ,
(f_max), f2_zip)
,
fn(fit ,
f2_min, f2_max)
,
fn(loose_constraint ,
f(0), dup, swap2));
}
alias_ui_Result alias_ui_initialize(alias_MemoryCB *mcb, alias_ui **ui_ptr) {
alias_ui *ui = alias_malloc(mcb, sizeof(*ui), alignof(*ui));
if(ui == NULL) {
return alias_ui_ErrorOutOfMemory;
}
alias_ash_Program_initialize(&ui->layout_program);
alias_ash_Program_begin_library(&ui->layout_program, mcb);
alias_ash_Program_define_cfun(&ui->layout_program, mcb, "setx", _layout_shape_set_x);
alias_ash_Program_define_cfun(&ui->layout_program, mcb, "sety", _layout_shape_set_y);
alias_ash_Program_define_cfun(&ui->layout_program, mcb, "setw", _layout_shape_set_w);
alias_ash_Program_define_cfun(&ui->layout_program, mcb, "seth", _layout_shape_set_h);
alias_ash_Program_define_cfun(&ui->layout_program, mcb, "textv_layout", _textv_layout);
_standard_library(&ui->layout_program, mcb);
alias_ash_Program_end_library(&ui->layout_program);
alias_ash_Program_initialize(&ui->render_program);
alias_ash_Program_begin_library(&ui->render_program, mcb);
alias_ash_Program_define_cfun(&ui->render_program, mcb, "getx", _render_shape_get_x);
alias_ash_Program_define_cfun(&ui->render_program, mcb, "gety", _render_shape_get_y);
alias_ash_Program_define_cfun(&ui->render_program, mcb, "getw", _render_shape_get_w);
alias_ash_Program_define_cfun(&ui->render_program, mcb, "geth", _render_shape_get_h);
alias_ash_Program_define_cfun(&ui->render_program, mcb, "textv_render", _textv_render);
alias_ash_Program_define_cfun(&ui->render_program, mcb, "set_texture", _set_texture);
alias_ash_Program_define_cfun(&ui->render_program, mcb, "rect_fill_c", _rect_fill_c);
alias_ash_Program_define_cfun(&ui->render_program, mcb, "rect_fill_st", _rect_fill_st);
_standard_library(&ui->render_program, mcb);
alias_ash_Program_end_library(&ui->render_program);
alias_memory_clear(&ui->memory, sizeof(ui->memory));
*ui_ptr = ui;
return alias_ui_Success;
}
alias_ui_Result alias_ui_free(alias_ui *ui, alias_MemoryCB *mcb) {
(void)ui;
(void)mcb;
return alias_ui_Success;
}
alias_ui_Result alias_ui_begin_frame(alias_ui *ui, alias_MemoryCB *mcb, const alias_ui_Input *input) {
ui->mcb = mcb;
alias_ash_Program_begin_shader(&ui->layout_program, mcb);
alias_ash_Program_begin_shader(&ui->render_program, mcb);
alias_Vector_clear(&ui->memory);
alias_ash_Program *lp = &ui->layout_program;
ALIAS_ASH_EMIT(lp, ui->mcb, f(input->screen_size.width), f(input->screen_size.height), dup2);
ALIAS_ASH_EMIT(&ui->render_program, ui->mcb, f(0), dup, f(input->screen_size.width), f(input->screen_size.height));
ui->scope_index_p1 = 0;
_begin_scope(ui, NULL, NULL, NULL);
ui->text_size = input->text_size;
ui->text_draw = input->text_draw;
ui->max_num_groups = 0;
ui->max_num_indexes = 0;
ui->max_num_vertexes = 0;
return alias_ui_Success;
}
static inline void _align_fractions_end_child(alias_ui *ui) {
struct scope *scope = _scope(ui);
uint32_t shape = scope->shape;
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
over2 ,
over2 ,
rot, swap, f_sub, f(scope->args[1]), f_mul, irot, f_sub, f(scope->args[0]), f_mul, swap, i(shape), sety ,
i(shape), setx ,
i(shape), seth ,
i(shape), setw
);
_end_scope(ui);
_end_child(ui);
}
void alias_ui_align_fractions(alias_ui *ui, float x, float y) {
if(_scope(ui)->align != NULL) {
_scope(ui)->align(ui, x, y);
return;
}
_begin_child(ui);
_begin_scope(ui, NULL, _align_fractions_end_child, NULL);
struct scope *scope = _scope(ui);
uint32_t shape = _alloc(ui, sizeof(struct shape));
scope->shape = shape;
scope->args[0] = x;
scope->args[1] = y;
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
swap2,
drop2
,
dup2, loose_constraint);
ALIAS_ASH_EMIT(&ui->render_program,
ui->mcb
,
drop2 ,
i(shape), getx ,
i(shape), gety ,
f2_add ,
i(shape), getw ,
i(shape), geth );
}
static inline void _override_size_end_child(alias_ui *ui) {
ALIAS_ASH_EMIT(&ui->layout_program, ui->mcb, drop2);
_end_scope(ui);
_end_child(ui);
}
void alias_ui_override_size(alias_ui *ui, alias_R width, alias_R height) {
_begin_child(ui);
_begin_scope(ui, NULL, _override_size_end_child, NULL);
ALIAS_ASH_EMIT(&ui->layout_program, ui->mcb,
f(width), f(height), fit,
dup2, f(0), dup, swap2);
}
static inline void _override_width_end_child(alias_ui *ui) {
ALIAS_ASH_EMIT(&ui->layout_program, ui->mcb, nip);
_end_scope(ui);
_end_child(ui);
}
void alias_ui_override_width(alias_ui *ui, alias_R width) {
_begin_child(ui);
_begin_scope(ui, NULL, _override_width_end_child, NULL);
ALIAS_ASH_EMIT(&ui->layout_program, ui->mcb,
(nip, f(0), swap, f(width), irot), dip2, nip, f(width), swap);
}
static inline void _override_height_end_child(alias_ui *ui) {
ALIAS_ASH_EMIT(&ui->layout_program, ui->mcb, drop, swap);
_end_scope(ui);
_end_child(ui);
}
void alias_ui_override_height(alias_ui *ui, alias_R height) {
_begin_child(ui);
_begin_scope(ui, NULL, _override_height_end_child, NULL);
ALIAS_ASH_EMIT(&ui->layout_program, ui->mcb,
drop, (drop, f(height), swap, f(0)), dip, f(height));
}
static inline void _vertical_begin_child(alias_ui *ui) {
int shape = _alloc(ui, sizeof(struct shape));
_scope(ui)->shape = shape;
ALIAS_ASH_EMIT(&ui->layout_program, ui->mcb,
i(5), pick, i(5), pick, i(5), pick, i(5), pick, i(4), pick, f_sub);
ALIAS_ASH_EMIT(&ui->render_program, ui->mcb,
i(3), pick, f(_scope(ui)->alignment), i(3), pick, i(shape), getw, f_sub, f_mul, f_add, i(3), pick, i(shape), gety, f_add, i(shape), getw, i(shape), geth);
_scope(ui)->alignment = 0.5f;
}
static inline void _vertical_end_child(alias_ui *ui) {
int shape = _scope(ui)->shape;
ALIAS_ASH_EMIT(&ui->layout_program, ui->mcb,
dup, i(shape), seth, swap, dup, i(shape), setw, r_push, over, i(shape), sety, f_add, swap, r_pop, f_max, swap );
}
static inline void _vertical_end_scope(alias_ui *ui) {
ALIAS_ASH_EMIT(&ui->layout_program, ui->mcb,
fit);
ALIAS_ASH_EMIT(&ui->render_program, ui->mcb,
drop2, drop2);
_end_child(ui);
}
static inline void _vertical_align(alias_ui *ui, float x, float y) {
(void)y;
_scope(ui)->alignment = x;
}
void alias_ui_begin_vertical(alias_ui *ui) {
_begin_child(ui);
_begin_scope(ui, _vertical_begin_child, _vertical_end_child, _vertical_end_scope);
_scope(ui)->align = _vertical_align;
_scope(ui)->alignment = 0.5f;
ALIAS_ASH_EMIT(&ui->layout_program, ui->mcb,
i(0), dup);
}
static inline void _horizontal_begin_child(alias_ui *ui) {
int shape = _alloc(ui, sizeof(struct shape));
_scope(ui)->shape = shape;
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
i(5), pick, i(5), pick, i(5), pick, i(4), pick, f_sub, i(5), pick);
ALIAS_ASH_EMIT(&ui->render_program,
ui->mcb
,
i(3), pick ,
i(shape), getx ,
f_add ,
i(3), pick ,
f(_scope(ui)->alignment) ,
i(3), pick ,
i(shape), geth ,
f_sub, f_mul, f_add ,
i(shape), getw, i(shape), geth);
_scope(ui)->alignment = 0.5f;
}
static inline void _horizontal_end_child(alias_ui *ui) {
int shape = _scope(ui)->shape;
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
dup, i(shape), seth ,
swap, dup, i(shape), setw ,
r_push ,
i(2), pick, i(shape), setx ,
f_max ,
swap, r_pop ,
f_add, swap );
}
static inline void _horizontal_end_scope(alias_ui *ui) {
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
fit);
ALIAS_ASH_EMIT(&ui->render_program,
ui->mcb
,
drop2, drop2);
_end_child(ui);
}
static inline void _horizontal_align(alias_ui *ui, float x, float y) {
(void)x;
_scope(ui)->alignment = y;
}
void alias_ui_begin_horizontal(alias_ui *ui) {
_begin_child(ui);
_begin_scope(ui, _horizontal_begin_child, _horizontal_end_child, _horizontal_end_scope);
_scope(ui)->align = _horizontal_align;
_scope(ui)->alignment = 0.5f;
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
i(0), dup);
}
static inline void _stack_begin_child(alias_ui *ui) {
int shape = _alloc(ui, sizeof(struct shape));
_scope(ui)->shape = shape;
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
f(0), dup, i(5), pick, i(5), pick);
ALIAS_ASH_EMIT(&ui->render_program,
ui->mcb
,
over2, i(shape), getw, i(shape), geth);
}
static inline void _stack_end_child(alias_ui *ui) {
int shape = _scope(ui)->shape;
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
dup, i(shape), seth, swap, dup, i(shape), setw, swap, f2_max);
}
static inline void _stack_end_scope(alias_ui *ui) {
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
fit);
ALIAS_ASH_EMIT(&ui->render_program,
ui->mcb
,
drop2, drop2);
_end_child(ui);
}
void alias_ui_begin_stack(alias_ui *ui) {
_begin_child(ui);
_begin_scope(ui, _stack_begin_child, _stack_end_child, _stack_end_scope);
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
i(0), dup);
}
void alias_ui_end(alias_ui *ui) { _end_scope(ui); }
void alias_ui_stats(alias_ui *ui, uint32_t *num_vertexes, uint32_t *num_indexes, uint32_t *num_groups) {
*num_vertexes = ui->max_num_vertexes;
*num_indexes = ui->max_num_indexes;
*num_groups = ui->max_num_groups;
}
void alias_ui_font_size(alias_ui *ui, alias_R size) { _scope(ui)->font_size = size; }
void alias_ui_font_color(alias_ui *ui, alias_Color color) { _scope(ui)->font_color = color; }
static void _textv_layout(alias_ash *ash) {
float size = alias_ash_pop_R(ash);
uint32_t text = alias_ash_pop(ash);
float maxh = alias_ash_pop_R(ash);
float maxw = alias_ash_pop_R(ash);
float minh = alias_ash_pop_R(ash);
float minw = alias_ash_pop_R(ash);
float w, h;
alias_ui *ui = (alias_ui *)ash->user_data;
ui->text_size(ui, _mem(ui, text), size, maxw, &w, &h);
alias_ash_push_R(ash, alias_max(minw, alias_min(maxw, w)));
alias_ash_push_R(ash, alias_max(minh, alias_min(maxh, h)));
}
static void _textv_render(alias_ash *ash) {
float a = alias_ash_pop_R(ash);
float b = alias_ash_pop_R(ash);
float g = alias_ash_pop_R(ash);
float r = alias_ash_pop_R(ash);
float size = alias_ash_pop_R(ash);
uint32_t text = alias_ash_pop(ash);
float h = alias_ash_pop_R(ash);
float w = alias_ash_pop_R(ash);
float y = alias_ash_pop_R(ash);
float x = alias_ash_pop_R(ash);
(void)h;
alias_ui *ui = (alias_ui *)ash->user_data;
ui->text_draw(ui, _mem(ui, text), x, y, w, size, (alias_Color){r, g, b, a});
}
void alias_ui_textv(alias_ui *ui, const char *format, va_list ap) {
uint32_t text;
size_t length;
{
va_list ap2;
va_copy(ap2, ap);
length = vsnprintf(NULL, 0, 0, format, ap2);
va_end(ap2);
text = _alloc(ui, length + 1);
vsnprintf(_mem(ui, text), length + 1, length + 1, format, ap);
}
_begin_child(ui);
ui->max_num_vertexes += 4 * length;
ui->max_num_indexes += 6 * length;
ui->max_num_groups++;
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
i(text), f(_scope(ui)->font_size), textv_layout);
ALIAS_ASH_EMIT(&ui->render_program,
ui->mcb
,
i(text), f(_scope(ui)->font_size), f(_scope(ui)->font_color.r), f(_scope(ui)->font_color.g), f(_scope(ui)->font_color.b),
f(_scope(ui)->font_color.a), textv_render);
_end_child(ui);
}
void alias_ui_fill(alias_ui *ui, alias_Color color) {
_begin_child(ui);
ui->max_num_vertexes += 4;
ui->max_num_indexes += 6;
ui->max_num_groups++;
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
swap2, drop2);
ALIAS_ASH_EMIT(&ui->render_program,
ui->mcb
,
i(0), set_texture, f(color.r), f(color.g), f(color.b), f(color.a), rect_fill_c);
_end_child(ui);
}
void alias_ui_image(alias_ui *ui, alias_R width, alias_R height, alias_R s0, alias_R t0, alias_R s1, alias_R t1, uint32_t texture_id) {
_begin_child(ui);
ui->max_num_vertexes += 4;
ui->max_num_indexes += 6;
ui->max_num_groups++;
ALIAS_ASH_EMIT(&ui->layout_program,
ui->mcb
,
f(width), f(height), fit);
ALIAS_ASH_EMIT(&ui->render_program,
ui->mcb
,
i(texture_id), set_texture, f(s0), f(t0), f(s1), f(t1), rect_fill_st);
_end_child(ui);
}
alias_ui_Result alias_ui_end_frame(alias_ui *ui, alias_MemoryCB *mcb, alias_ui_Output *output) {
_end_scope(ui);
ui->output = output;
alias_ash_Program_end_shader(&ui->layout_program, mcb);
alias_ash_Program_end_shader(&ui->render_program, mcb);
alias_ash ash;
ash.user_data = ui;
alias_ash_initialize(&ash, &ui->layout_program);
while(alias_ash_step(&ash))
;
if(output->num_groups > 0) {
output->groups[output->num_groups - 1].length = output->num_indexes - output->groups[output->num_groups - 1].index;
}
output->groups[output->num_groups].index = output->num_indexes;
output->groups[output->num_groups].length = 0;
output->groups[output->num_groups].texture_id = 0;
output->num_groups++;
alias_ash_initialize(&ash, &ui->render_program);
while(alias_ash_step(&ash))
;
output->groups[output->num_groups - 1].length = output->num_indexes - output->groups[output->num_groups - 1].index;
if(output->groups[output->num_groups - 1].length == 0) {
output->num_groups--;
}
return alias_ui_Success;
}