gfx2d sketch
This commit is contained in:
@@ -1,16 +1,8 @@
|
|||||||
fn_wasm_import void wasm_clear(void);
|
|
||||||
fn_wasm_import void wasm_draw_text(isize str, i32 len, f64 x, f64 y, isize font_str, i32 font_len, i32 font_size, f32 r, f32 g, f32 b, f32 a);
|
|
||||||
fn_wasm_import void wasm_draw_rect(f64 x, f64 y, f64 w, f64 h, f32 r, f32 g, f32 b, f32 a);
|
|
||||||
fn_wasm_import f64 wasm_measure_text(isize str, i32 len, isize font_str, i32 font_len, i32 font_size);
|
|
||||||
fn_wasm_import f64 wasm_get_font_height(isize font_str, i32 font_len, i32 font_size);
|
|
||||||
fn_wasm_import void wasm_set_clip(f64 x, f64 y, f64 w, f64 h);
|
|
||||||
|
|
||||||
glb_wasm_export char wasm_temp_buff1[128] = {[127] = 0x13};
|
glb_wasm_export char wasm_temp_buff1[128] = {[127] = 0x13};
|
||||||
glb_wasm_export i32 wasm_temp_buff1_len = 127;
|
glb_wasm_export i32 wasm_temp_buff1_len = 127;
|
||||||
glb_wasm_export char wasm_temp_buff2[128] = {[127] = 0x13};
|
glb_wasm_export char wasm_temp_buff2[128] = {[127] = 0x13};
|
||||||
glb_wasm_export i32 wasm_temp_buff2_len = 127;
|
glb_wasm_export i32 wasm_temp_buff2_len = 127;
|
||||||
|
|
||||||
glb s8_t font_face = s8_const_lit("open_sans_regular");
|
|
||||||
glb f64 wasm_dpr;
|
glb f64 wasm_dpr;
|
||||||
glb ma_arena_t *wasm_input_text_arena;
|
glb ma_arena_t *wasm_input_text_arena;
|
||||||
glb STACK(app_event_t, 64) wasm_events;
|
glb STACK(app_event_t, 64) wasm_events;
|
||||||
@@ -24,40 +16,7 @@ struct wasm_cached_t {
|
|||||||
} wasm_cached;
|
} wasm_cached;
|
||||||
|
|
||||||
fn void app_update(app_event_t *events, i32 event_count);
|
fn void app_update(app_event_t *events, i32 event_count);
|
||||||
|
fn void app_init(void);
|
||||||
fn void set_clip(r2f64_t rect) {
|
|
||||||
wasm_set_clip(wasm_dpr * rect.min.x, wasm_dpr * rect.min.y, wasm_dpr * (rect.max.x - rect.min.x), wasm_dpr * (rect.max.y - rect.min.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn f64 get_font_height(void) {
|
|
||||||
return wasm_get_font_height((isize) font_face.str, font_face.len, 20*wasm_dpr) / wasm_dpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn f64 measure_text_ex(char *str, i32 len) {
|
|
||||||
return wasm_measure_text((isize)str, len, (isize) font_face.str, font_face.len, 20*wasm_dpr) / wasm_dpr;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn f64 measure_text(char *str) {
|
|
||||||
return measure_text_ex(str, str_len(str));
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void draw_text(v2f64_t pos, v4f32_t color, s8_t string) {
|
|
||||||
wasm_draw_text((isize)string.str, string.len, wasm_dpr * pos.x, wasm_dpr * pos.y, (isize) font_face.str, font_face.len, 20*wasm_dpr, color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void draw_textf(v2f64_t pos, char *str, ...) {
|
|
||||||
char buff[1024];
|
|
||||||
va_list args;
|
|
||||||
va_start(args, str);
|
|
||||||
i32 len = stbsp_vsnprintf(buff, sizeof(buff), str, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
wasm_draw_text((isize)buff, len, wasm_dpr * pos.x, wasm_dpr * pos.y, (isize) font_face.str, font_face.len, 20*wasm_dpr, 0, 0, 0, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void draw_rect(r2f64_t rect, v4f32_t color) {
|
|
||||||
wasm_draw_rect(wasm_dpr * rect.min.x, wasm_dpr * rect.min.y, wasm_dpr * (rect.max.x - rect.min.x), wasm_dpr * (rect.max.y - rect.min.y), color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn void wasm_add_event(app_event_t event) {
|
fn void wasm_add_event(app_event_t event) {
|
||||||
if (wasm_events.len < lengthof(wasm_events.data)) {
|
if (wasm_events.len < lengthof(wasm_events.data)) {
|
||||||
@@ -206,8 +165,6 @@ fn_wasm_export void wasm_update(f64 time, f64 width, f64 height, f64 dpr) {
|
|||||||
}
|
}
|
||||||
wasm_dpr = dpr;
|
wasm_dpr = dpr;
|
||||||
|
|
||||||
wasm_clear();
|
|
||||||
draw_rect(r2f64(0, 0, window_size.x, window_size.y), white_color_global);
|
|
||||||
app_update(wasm_events.data, wasm_events.len);
|
app_update(wasm_events.data, wasm_events.len);
|
||||||
|
|
||||||
wasm_events.len = 0;
|
wasm_events.len = 0;
|
||||||
@@ -218,4 +175,5 @@ fn_wasm_export void wasm_update(f64 time, f64 width, f64 height, f64 dpr) {
|
|||||||
fn_wasm_export void wasm_init(void) {
|
fn_wasm_export void wasm_init(void) {
|
||||||
core_init();
|
core_init();
|
||||||
wasm_input_text_arena = ma_push_arena(&tcx.perm, kib(1));
|
wasm_input_text_arena = ma_push_arena(&tcx.perm, kib(1));
|
||||||
|
app_init();
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@ typedef struct thread_ctx_t thread_ctx_t;
|
|||||||
struct thread_ctx_t {
|
struct thread_ctx_t {
|
||||||
ma_arena_t scratch[3];
|
ma_arena_t scratch[3];
|
||||||
ma_arena_t perm;
|
ma_arena_t perm;
|
||||||
|
ma_arena_t *temp; // application specific arena
|
||||||
logger_t log;
|
logger_t log;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
142
src/gfx2d/gfx2d.c
Normal file
142
src/gfx2d/gfx2d.c
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
fn_wasm_import void wasm_clear(void);
|
||||||
|
fn_wasm_import void wasm_draw_text(isize str, i32 len, f64 x, f64 y, isize font_str, i32 font_len, i32 font_size, f32 r, f32 g, f32 b, f32 a);
|
||||||
|
fn_wasm_import void wasm_draw_rect(f64 x, f64 y, f64 w, f64 h, f32 r, f32 g, f32 b, f32 a);
|
||||||
|
fn_wasm_import f64 wasm_measure_text(isize str, i32 len, isize font_str, i32 font_len, i32 font_size);
|
||||||
|
fn_wasm_import f64 wasm_get_font_height(isize font_str, i32 font_len, i32 font_size);
|
||||||
|
fn_wasm_import void wasm_set_clip(f64 x, f64 y, f64 w, f64 h);
|
||||||
|
|
||||||
|
glb s8_t font_face = s8_const_lit("open_sans_regular");
|
||||||
|
|
||||||
|
|
||||||
|
fn void set_clip(r2f64_t rect) {
|
||||||
|
wasm_set_clip(wasm_dpr * rect.min.x, wasm_dpr * rect.min.y, wasm_dpr * (rect.max.x - rect.min.x), wasm_dpr * (rect.max.y - rect.min.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f64 get_font_height(void) {
|
||||||
|
return wasm_get_font_height((isize) font_face.str, font_face.len, 20*wasm_dpr) / wasm_dpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f64 measure_text_ex(char *str, i32 len) {
|
||||||
|
return wasm_measure_text((isize)str, len, (isize) font_face.str, font_face.len, 20*wasm_dpr) / wasm_dpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn f64 measure_text(char *str) {
|
||||||
|
return measure_text_ex(str, str_len(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void draw_text(v2f64_t pos, v4f32_t color, s8_t string) {
|
||||||
|
wasm_draw_text((isize)string.str, string.len, wasm_dpr * pos.x, wasm_dpr * pos.y, (isize) font_face.str, font_face.len, 20*wasm_dpr, color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void draw_textf(v2f64_t pos, char *str, ...) {
|
||||||
|
char buff[1024];
|
||||||
|
va_list args;
|
||||||
|
va_start(args, str);
|
||||||
|
i32 len = stbsp_vsnprintf(buff, sizeof(buff), str, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
wasm_draw_text((isize)buff, len, wasm_dpr * pos.x, wasm_dpr * pos.y, (isize) font_face.str, font_face.len, 20*wasm_dpr, 0, 0, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void draw_rect(r2f64_t rect, v4f32_t color) {
|
||||||
|
wasm_draw_rect(wasm_dpr * rect.min.x, wasm_dpr * rect.min.y, wasm_dpr * (rect.max.x - rect.min.x), wasm_dpr * (rect.max.y - rect.min.y), color.r * 255.f, color.g * 255.f, color.b * 255.f, color.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
gfx2d_kind_null,
|
||||||
|
gfx2d_kind_clear,
|
||||||
|
gfx2d_kind_draw_rect,
|
||||||
|
gfx2d_kind_draw_text,
|
||||||
|
gfx2d_kind_set_clip,
|
||||||
|
} gfx2d_kind_t;
|
||||||
|
|
||||||
|
typedef struct gfx2d_cmd_t gfx2d_cmd_t;
|
||||||
|
struct gfx2d_cmd_t {
|
||||||
|
gfx2d_kind_t kind;
|
||||||
|
r2f64_t rect;
|
||||||
|
v4f32_t color;
|
||||||
|
s8_t text;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct gfx2d_t gfx2d_t;
|
||||||
|
struct gfx2d_t {
|
||||||
|
ma_arena_t *ma;
|
||||||
|
gfx2d_cmd_t *cmds;
|
||||||
|
i32 cmds_len;
|
||||||
|
app_event_t *ev;
|
||||||
|
};
|
||||||
|
|
||||||
|
void gfx2d_begin(gfx2d_t *gfx, app_event_t *ev) {
|
||||||
|
gfx->ev = ev;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx2d_end(gfx2d_t *gfx) {
|
||||||
|
app_event_t *ev = gfx->ev;
|
||||||
|
r2f64_t window = (r2f64_t){0, 0, ev->window_size.x, ev->window_size.y};
|
||||||
|
for (i32 i = 0; i < gfx->cmds_len; i += 1) {
|
||||||
|
gfx2d_cmd_t *cmd = gfx->cmds + i;
|
||||||
|
|
||||||
|
if (cmd->kind == gfx2d_kind_clear) {
|
||||||
|
wasm_clear();
|
||||||
|
draw_rect(window, cmd->color);
|
||||||
|
} else if (cmd->kind == gfx2d_kind_draw_rect) {
|
||||||
|
draw_rect(cmd->rect, cmd->color);
|
||||||
|
} else if (cmd->kind == gfx2d_kind_draw_text) {
|
||||||
|
draw_text(cmd->rect.min, cmd->color, cmd->text);
|
||||||
|
} else if (cmd->kind == gfx2d_kind_set_clip) {
|
||||||
|
set_clip(cmd->rect);
|
||||||
|
} else {
|
||||||
|
invalid_codepath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx->cmds_len = 0;
|
||||||
|
ma_set0(gfx->ma);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx2d_add_cmd(gfx2d_t *gfx, gfx2d_cmd_t cmd) {
|
||||||
|
gfx2d_cmd_t *c = ma_push_type(gfx->ma, gfx2d_cmd_t);
|
||||||
|
*c = cmd;
|
||||||
|
if (gfx->cmds_len == 0) gfx->cmds = c;
|
||||||
|
gfx->cmds_len += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx2d_clear(gfx2d_t *gfx, v4f32_t color) {
|
||||||
|
gfx2d_add_cmd(gfx, (gfx2d_cmd_t){
|
||||||
|
.kind = gfx2d_kind_clear,
|
||||||
|
.color = color,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx2d_rect(gfx2d_t *gfx, r2f64_t rect, v4f32_t color) {
|
||||||
|
gfx2d_add_cmd(gfx, (gfx2d_cmd_t){
|
||||||
|
.kind = gfx2d_kind_draw_rect,
|
||||||
|
.color = color,
|
||||||
|
.rect = rect,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx2d_set_clip(gfx2d_t *gfx, r2f64_t rect) {
|
||||||
|
gfx2d_add_cmd(gfx, (gfx2d_cmd_t){
|
||||||
|
.kind = gfx2d_kind_set_clip,
|
||||||
|
.rect = rect,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfx2d_text(gfx2d_t *gfx, v2f64_t pos, v4f32_t color, s8_t string) {
|
||||||
|
gfx2d_add_cmd(gfx, (gfx2d_cmd_t){
|
||||||
|
.kind = gfx2d_kind_draw_text,
|
||||||
|
.text = s8_copy(tcx.temp, string),
|
||||||
|
.color = color,
|
||||||
|
.rect.min = pos,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void gfx2d_textf(gfx2d_t *gfx, v2f64_t pos, v4f32_t color, char *str, ...) {
|
||||||
|
S8_FMT(tcx.temp, str, text);
|
||||||
|
gfx2d_add_cmd(gfx, (gfx2d_cmd_t){
|
||||||
|
.kind = gfx2d_kind_draw_text,
|
||||||
|
.text = text,
|
||||||
|
.color = color,
|
||||||
|
.rect.min = pos,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -2,19 +2,37 @@
|
|||||||
#include "core/core_inc.c"
|
#include "core/core_inc.c"
|
||||||
#include "app/app.h"
|
#include "app/app.h"
|
||||||
#include "app/app.c"
|
#include "app/app.c"
|
||||||
// #include "debug.c"
|
#include "gfx2d/gfx2d.c"
|
||||||
#include "ui2.c"
|
#include "ui.c"
|
||||||
|
|
||||||
|
gfx2d_t *gfx2d = NULL;
|
||||||
|
void app_init(void) {
|
||||||
|
tcx.temp = ma_push_arena(&tcx.perm, mib(1));
|
||||||
|
gfx2d = ma_push_type(&tcx.perm, gfx2d_t);
|
||||||
|
gfx2d->ma = ma_push_arena(&tcx.perm, mib(2));
|
||||||
|
}
|
||||||
|
|
||||||
f64 delta_time;
|
|
||||||
void app_update(app_event_t *events, i32 event_count) {
|
void app_update(app_event_t *events, i32 event_count) {
|
||||||
if (event_count) delta_time = events[0].delta_time;
|
|
||||||
draw_textf(v2f64(0,0), "delta time: %f", delta_time);
|
|
||||||
|
|
||||||
|
// @todo: record render commands and replay
|
||||||
for (i32 i = 0; i < event_count; i += 1) {
|
// @todo: ignore render commands
|
||||||
ui_demo(events + i);
|
for (i32 i = 0; i < event_count - 1; i += 1) {
|
||||||
|
ui_demo(gfx2d, events + i);
|
||||||
|
gfx2d->cmds_len = 0;
|
||||||
|
ma_set0(gfx2d->ma);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
app_event_t *ev = &events[event_count - 1];
|
||||||
|
|
||||||
|
gfx2d_begin(gfx2d, ev);
|
||||||
|
gfx2d_clear(gfx2d, white_color_global);
|
||||||
|
ui_demo(gfx2d, ev);
|
||||||
|
// gfx2d_textf(gfx2d, v2f64(0,0), black_color_global, "delta time: %f", ev->delta_time);
|
||||||
|
gfx2d_end(gfx2d);
|
||||||
|
}
|
||||||
|
ma_set0(tcx.temp);
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
ma_scratch_scope(temp) {
|
ma_scratch_scope(temp) {
|
||||||
@@ -32,5 +50,4 @@ void app_update(app_event_t *events, i32 event_count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,280 +1,195 @@
|
|||||||
#if 0
|
v2f64_t ui_calc_text_pos(r2f64_t rect, char *title) {
|
||||||
typedef struct ui_id_t ui_id_t;
|
f64 font_height = get_font_height();
|
||||||
struct ui_id_t {
|
f64 text_width = measure_text(title);
|
||||||
u64 value;
|
|
||||||
|
v2f64_t text_pos = rect.min;
|
||||||
|
{
|
||||||
|
v2f64_t rect_size = r2f64_get_size(rect);
|
||||||
|
v2f64_t offset_to_center = {(rect_size.x - text_width) / 2, (rect_size.y - font_height) / 2};
|
||||||
|
text_pos = v2f64_add(text_pos, offset_to_center);
|
||||||
|
}
|
||||||
|
|
||||||
|
return text_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct ui_signal_t ui_signal_t;
|
||||||
|
struct ui_signal_t {
|
||||||
|
b8 pressed;
|
||||||
|
b8 overlapping;
|
||||||
};
|
};
|
||||||
ui_id_t ui_string_to_id(const char *string) { // FNV HASH (1a?)
|
|
||||||
|
ui_signal_t ui_interact(app_event_t *ev, r2f64_t rect) {
|
||||||
|
ui_signal_t sig = {0};
|
||||||
|
if (r2f64_contains(rect, ev->mouse_pos)) {
|
||||||
|
sig.overlapping = true;
|
||||||
|
if (ev->kind == app_event_kind_mouse_down && ev->mouse_button == app_mouse_button_left) {
|
||||||
|
sig.pressed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sig;
|
||||||
|
}
|
||||||
|
|
||||||
|
b32 ui_button(gfx2d_t *gfx, app_event_t *ev, r2f64_t rect, char *title) {
|
||||||
|
v2f64_t text_pos = ui_calc_text_pos(rect, title);
|
||||||
|
ui_signal_t sig = ui_interact(ev, rect);
|
||||||
|
|
||||||
|
v4f32_t rect_color = secondary_color_global;
|
||||||
|
v4f32_t text_color = black_color_global;
|
||||||
|
if (sig.overlapping) {
|
||||||
|
rect_color = primary_color_global;
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx2d_set_clip(gfx, rect);
|
||||||
|
gfx2d_rect(gfx, rect, rect_color);
|
||||||
|
gfx2d_text(gfx, text_pos, text_color, s8_from_char(title));
|
||||||
|
gfx2d_set_clip(gfx, r2f64(-1000, -1000, 1000000, 1000000));
|
||||||
|
|
||||||
|
return sig.pressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
b32 ui_checkbox(gfx2d_t *gfx, app_event_t *ev, r2f64_t rect, b32 *value, char *title) {
|
||||||
|
v2f64_t text_pos = ui_calc_text_pos(rect, title);
|
||||||
|
ui_signal_t sig = ui_interact(ev, rect);
|
||||||
|
if (sig.pressed) *value = !*value;
|
||||||
|
|
||||||
|
v4f32_t rect_color = secondary_color_global;
|
||||||
|
v4f32_t text_color = black_color_global;
|
||||||
|
if (sig.overlapping) {
|
||||||
|
rect_color = primary_color_global;
|
||||||
|
}
|
||||||
|
if (*value) {
|
||||||
|
rect_color = v4f32_lerp(rect_color, accent2_color_global, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx2d_set_clip(gfx, rect);
|
||||||
|
gfx2d_rect(gfx, rect, rect_color);
|
||||||
|
gfx2d_text(gfx, text_pos, text_color, s8_from_char(title));
|
||||||
|
gfx2d_set_clip(gfx, r2f64(-1000, -1000, 1000000, 1000000));
|
||||||
|
|
||||||
|
return *value;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct ui_id_t ui_id_t;
|
||||||
|
struct ui_id_t { u64 value; };
|
||||||
|
|
||||||
|
ui_id_t ui_string_to_id(const char *string, i32 len) { // FNV HASH (1a?)
|
||||||
u8 *data8 = (u8 *)string;
|
u8 *data8 = (u8 *)string;
|
||||||
u64 hash = (u64)14695981039346656037ULL;
|
u64 hash = (u64)14695981039346656037ULL;
|
||||||
for (u64 i = 0; data8[i]; i++) {
|
for (u64 i = 0; i < len; i++) {
|
||||||
hash = hash ^ (u64)(data8[i]);
|
hash = hash ^ (u64)(data8[i]);
|
||||||
hash = hash * (u64)1099511628211ULL;
|
hash = hash * (u64)1099511628211ULL;
|
||||||
}
|
}
|
||||||
return (ui_id_t){ .value = hash };
|
return (ui_id_t){ .value = hash };
|
||||||
}
|
}
|
||||||
#define ui_location_id() ui_string_to_id(FILE_AND_LINE)
|
#define ui_location_id() ui_string_to_id(FILE_AND_LINE, sizeof(FILE_AND_LINE) - 1)
|
||||||
ui_id_t ui_element_pressed;
|
ui_id_t ui_active_element = {0};
|
||||||
|
|
||||||
typedef enum {
|
void ui_slider(gfx2d_t *gfx, app_event_t *ev, r2f64_t rect, ui_id_t id, f64 *value, char *title) {
|
||||||
cut_left,
|
v2f64_t text_pos = ui_calc_text_pos(rect, title);
|
||||||
cut_right,
|
ui_signal_t sig = ui_interact(ev, rect);
|
||||||
cut_bottom,
|
b32 interacting = false;
|
||||||
cut_top,
|
|
||||||
} cut_t;
|
|
||||||
|
|
||||||
typedef struct rcut_t rcut_t;
|
|
||||||
struct rcut_t {
|
|
||||||
r2f64_t *rect;
|
|
||||||
cut_t cut;
|
|
||||||
};
|
|
||||||
|
|
||||||
rcut_t rcut(r2f64_t *rect, cut_t cut) {
|
|
||||||
return (rcut_t){rect, cut};
|
|
||||||
}
|
|
||||||
|
|
||||||
r2f64_t ui_cut(r2f64_t *rect, f64 value, cut_t cut) {
|
|
||||||
if (cut == cut_left) return r2f64_cut_left(rect, value);
|
|
||||||
else if (cut == cut_right) return r2f64_cut_right(rect, value);
|
|
||||||
else if (cut == cut_bottom) return r2f64_cut_bottom(rect, value);
|
|
||||||
else if (cut == cut_top) return r2f64_cut_top(rect, value);
|
|
||||||
else assert(!"invalid codepath");
|
|
||||||
return (r2f64_t){0};
|
|
||||||
}
|
|
||||||
|
|
||||||
r2f64_t ui_cut2(rcut_t rc, f64 x, f64 y) {
|
|
||||||
f64 cut_value = 0;
|
|
||||||
if (rc.cut == cut_left || rc.cut == cut_right) cut_value = x;
|
|
||||||
else cut_value = y;
|
|
||||||
r2f64_t result = ui_cut(rc.rect, cut_value, rc.cut);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct ui_flags_t ui_flags_t;
|
|
||||||
struct ui_flags_t {
|
|
||||||
b32 draw_text : 1;
|
|
||||||
b32 text_centered : 1;
|
|
||||||
b32 text_y_centered;
|
|
||||||
|
|
||||||
b32 draw_rect : 1;
|
|
||||||
|
|
||||||
b32 checkable : 1;
|
|
||||||
b32 draw_checkbox : 1;
|
|
||||||
b32 draw_checked;
|
|
||||||
|
|
||||||
b32 clickable : 1;
|
|
||||||
b32 slider : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct ui_signal_t ui_signal_t;
|
|
||||||
struct ui_signal_t {
|
|
||||||
b32 pressed : 1;
|
|
||||||
b32 overlapping : 1;
|
|
||||||
b32 interacting : 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO(Karol): Don't use inputs as flags! Use only flags.
|
|
||||||
typedef struct ui_input_t ui_input_t;
|
|
||||||
struct ui_input_t {
|
|
||||||
char *title;
|
|
||||||
b32 *value_b32;
|
|
||||||
f64 *value_f64;
|
|
||||||
ui_id_t id;
|
|
||||||
};
|
|
||||||
|
|
||||||
v2f64_t style_padding = {50, 10};
|
|
||||||
ui_signal_t ui_widget(rcut_t rc, ui_input_t input, ui_flags_t flags) {
|
|
||||||
// Calculate rectangles
|
|
||||||
r2f64_t total_rect = {0};
|
|
||||||
r2f64_t rect = {0};
|
|
||||||
r2f64_t checkbox_rect = {0};
|
|
||||||
{
|
{
|
||||||
v2f64_t size = style_padding;
|
if (sig.pressed) {
|
||||||
f64 font_height = get_font_height();
|
ui_active_element = id;
|
||||||
|
|
||||||
size.y += font_height;
|
|
||||||
if (flags.draw_text) {
|
|
||||||
size.x += measure_text(input.title);
|
|
||||||
}
|
}
|
||||||
|
if (id.value == ui_active_element.value) {
|
||||||
total_rect = ui_cut2(rc, size.x, size.y);
|
interacting = true;
|
||||||
rect = total_rect;
|
|
||||||
if (flags.draw_checkbox) {
|
|
||||||
checkbox_rect = r2f64_cut_left(&rect, size.y);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Solve interactions
|
if (interacting) {
|
||||||
ui_signal_t result = {0};
|
f64 mouse_pos = ev->mouse_pos.x;
|
||||||
{
|
|
||||||
if (r2f64_contains(total_rect, mouse_pos_g)) {
|
|
||||||
result.overlapping = true;
|
|
||||||
if (mouse_button_press_g[app_mouse_button_left]) {
|
|
||||||
ui_element_pressed = input.id;
|
|
||||||
result.pressed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ui_element_pressed.value == input.id.value && mouse_button_down_g[app_mouse_button_left]) {
|
|
||||||
result.interacting = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags.checkable && result.pressed) {
|
|
||||||
*input.value_b32 = !*input.value_b32;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags.slider && result.interacting) {
|
|
||||||
f64 mouse_pos = mouse_pos_g.x;
|
|
||||||
v2f64_t rect_size = r2f64_get_size(rect);
|
|
||||||
*input.value_f64 = (mouse_pos - rect.min.x) / rect_size.x;
|
|
||||||
*input.value_f64 = CLAMP(*input.value_f64, 0, 1.0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clip(total_rect);
|
|
||||||
|
|
||||||
// Draw
|
|
||||||
if (flags.draw_rect) {
|
|
||||||
v4f32_t color = primary_color_global;
|
|
||||||
if (flags.clickable) {
|
|
||||||
if (result.overlapping) color = secondary_color_global;
|
|
||||||
if (flags.draw_checked && input.value_b32[0]) color = accent1_color_global;
|
|
||||||
}
|
|
||||||
draw_rect(rect, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags.slider) {
|
|
||||||
v2f64_t rect_size = r2f64_get_size(rect);
|
v2f64_t rect_size = r2f64_get_size(rect);
|
||||||
r2f64_t rect_split = r2f64_get_left(&rect, rect_size.x * input.value_f64[0]);
|
*value = (mouse_pos - rect.min.x) / rect_size.x;
|
||||||
draw_rect(rect_split, accent1_color_global);
|
*value = CLAMP(*value, 0, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.draw_text) {
|
v2f64_t rect_size = r2f64_get_size(rect);
|
||||||
v2f64_t text_pos = rect.min;
|
r2f64_t slider_rect = r2f64_get_left(&rect, rect_size.x * value[0]);
|
||||||
f64 text_width = measure_text(input.title);
|
|
||||||
f64 font_height = get_font_height();
|
|
||||||
|
|
||||||
v2f64_t rect_size = r2f64_get_size(rect);
|
v4f32_t rect_color = secondary_color_global;
|
||||||
v2f64_t offset_to_center = {(rect_size.x - text_width) / 2, (rect_size.y - font_height) / 2};
|
if (sig.overlapping) rect_color = v4f32_lerp(rect_color, accent2_color_global, 0.2);
|
||||||
if (flags.text_y_centered) {
|
v4f32_t slider_color = accent2_color_global;
|
||||||
text_pos.y += offset_to_center.y;
|
if (sig.overlapping) slider_color = v4f32_lerp(slider_color, accent2_color_global, 0.2);
|
||||||
}
|
v4f32_t text_color = black_color_global;
|
||||||
if (flags.text_centered) {
|
|
||||||
text_pos = v2f64_add(text_pos, offset_to_center);
|
gfx2d_set_clip(gfx, rect);
|
||||||
}
|
gfx2d_rect(gfx, rect, rect_color);
|
||||||
draw_text(text_pos, input.title);
|
gfx2d_rect(gfx, slider_rect, slider_color);
|
||||||
|
gfx2d_text(gfx, text_pos, text_color, s8_from_char(title));
|
||||||
|
gfx2d_set_clip(gfx, r2f64(-1000, -1000, 1000000, 1000000));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ui_demo(gfx2d_t *gfx, app_event_t *ev) {
|
||||||
|
if (ev->kind == app_event_kind_mouse_up) {
|
||||||
|
ui_active_element = (ui_id_t){0};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.draw_checkbox) {
|
r2f64_t window_rect = (r2f64_t){(v2f64_t){0}, ev->window_size};
|
||||||
v4f32_t color = accent1_color_global;
|
r2f64_t top_bar_rect = r2f64_cut_top(&window_rect, get_font_height() + 20);
|
||||||
if (flags.checkable) {
|
gfx2d_rect(gfx, window_rect, primary_color_global);
|
||||||
if (input.value_b32[0]) {
|
|
||||||
color = accent2_color_global;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((flags.checkable || flags.clickable) && result.overlapping) {
|
|
||||||
color = v4f32_lerp(color, v4f32(1,1,1,1), 0.25);
|
|
||||||
}
|
|
||||||
draw_rect(checkbox_rect, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
clip(r2f64(-1000, -1000, 1000000, 1000000));
|
f64 padding = 50;
|
||||||
|
gfx2d_rect(gfx, top_bar_rect, secondary_color_global);
|
||||||
|
|
||||||
return result;
|
static b32 open_file_panel;
|
||||||
}
|
f64 open_file_panel_xsize = 0;
|
||||||
|
|
||||||
b32 ui_button(rcut_t rc, char *title) {
|
|
||||||
ui_signal_t sig = ui_widget(rc, (ui_input_t){.title = title}, (ui_flags_t){.draw_text = true, .text_centered = true, .draw_rect = true, .clickable = true});
|
|
||||||
return sig.pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
b32 ui_checked_button(b32 *value, rcut_t rc, char *title) {
|
|
||||||
ui_widget(rc, (ui_input_t){.title = title, .value_b32 = value}, (ui_flags_t){.draw_rect = true, .draw_text = true, .text_centered = true, .clickable = true, .checkable = true, .draw_checked = true});
|
|
||||||
return *value;
|
|
||||||
}
|
|
||||||
|
|
||||||
b32 ui_checkbox(rcut_t rc, b32 *value, char *title) {
|
|
||||||
ui_widget(rc, (ui_input_t){.value_b32 = value, .title = title}, (ui_flags_t){.draw_checkbox = true, .draw_text = true, .text_y_centered = true, .draw_rect = true, .checkable = true});
|
|
||||||
return *value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui_label(rcut_t rc, char *title) {
|
|
||||||
ui_widget(rc, (ui_input_t){.title = title}, (ui_flags_t){.draw_text = true, .text_centered = true, .draw_rect = true});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui_slider(rcut_t rc, ui_id_t id, f64 *value, char *title) {
|
|
||||||
ui_widget(rc, (ui_input_t){.title = title, .value_f64 = value, .id = id}, (ui_flags_t){.draw_text = true, .text_centered = true, .slider = true, .draw_rect = true, .clickable = true});
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui_begin_frame(void) {
|
|
||||||
if (mouse_button_release_g[app_mouse_button_left]) {
|
|
||||||
ui_element_pressed = (ui_id_t){0};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui_demo(void) {
|
|
||||||
ui_begin_frame();
|
|
||||||
f64 font_height = get_font_height();
|
|
||||||
r2f64_t window_rect = r2f64(0, 0, window_size_g.x, window_size_g.y);
|
|
||||||
{
|
{
|
||||||
draw_rect(window_rect, while_color_global);
|
// ▼▲▶◀
|
||||||
|
char *title = "▶ file";
|
||||||
|
if (open_file_panel) title = "▼ file";
|
||||||
|
open_file_panel_xsize = measure_text(title) + padding*2;
|
||||||
|
r2f64_t rect = r2f64_cut_left(&top_bar_rect, open_file_panel_xsize);
|
||||||
|
if (ui_checkbox(gfx, ev, rect, &open_file_panel, title)) {
|
||||||
|
}
|
||||||
|
r2f64_t gap_rect = r2f64_cut_left(&top_bar_rect, 1);
|
||||||
|
gfx2d_rect(gfx, gap_rect, black_color_global);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (open_file_panel) {
|
||||||
|
f64 item_count = 20;
|
||||||
|
f64 item_size = get_font_height() + 20;
|
||||||
|
r2f64_t panel_rect = r2f64_get_top(&window_rect, item_count * item_size);
|
||||||
|
panel_rect = r2f64_get_left(&panel_rect, open_file_panel_xsize);
|
||||||
|
|
||||||
|
{
|
||||||
|
static f64 slider_value;
|
||||||
|
char buff[64];
|
||||||
|
stbsp_snprintf(buff, sizeof(buff), "%f", slider_value);
|
||||||
|
r2f64_t rect = r2f64_cut_top(&panel_rect, item_size);
|
||||||
|
ui_slider(gfx, ev, rect, ui_location_id(), &slider_value, buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
// {
|
||||||
|
// static char buff[64];
|
||||||
|
// static ui_input_state input;
|
||||||
|
// if (input.buff == NULL) {
|
||||||
|
// input.buff = buff;
|
||||||
|
// input.cap = sizeof(buff);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// r2f64_t rect = r2f64_cut_top(&panel_rect, item_size);
|
||||||
|
// ui_input_text(rect, &input);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static b32 panel_open = true;
|
|
||||||
static b32 cool_rect = false;
|
|
||||||
{
|
{
|
||||||
r2f64_t top_rect = r2f64_cut_top(&window_rect, font_height*2);
|
char *title = "edit";
|
||||||
draw_rect(top_rect, primary_color_global);
|
r2f64_t rect = r2f64_cut_left(&top_bar_rect, measure_text(title) + padding*2);
|
||||||
|
if (ui_button(gfx, ev, rect, title)) {
|
||||||
if (ui_checked_button(&cool_rect, rcut(&top_rect, cut_left), "file")) {
|
|
||||||
draw_rect(window_rect, v4f32(0.5, 0.1, 0.1, 1.0));
|
|
||||||
}
|
|
||||||
if (ui_button(rcut(&top_rect, cut_left), "edit")) {}
|
|
||||||
if (ui_button(rcut(&top_rect, cut_left), "view")) {}
|
|
||||||
if (ui_checked_button(&panel_open, rcut(&top_rect, cut_left), "open panel")) {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
r2f64_t gap_rect = r2f64_cut_left(&top_bar_rect, 1);
|
||||||
|
gfx2d_rect(gfx, gap_rect, black_color_global);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (panel_open) {
|
{
|
||||||
r2f64_t panel_rect = r2f64_cut_left(&window_rect, measure_text("1234567890")*2);
|
char *title = "view";
|
||||||
{
|
r2f64_t rect = r2f64_cut_left(&top_bar_rect, measure_text(title) + padding*2);
|
||||||
v4f32_t color = primary_color_global; color.a = 0.3f;
|
if (ui_button(gfx, ev, rect, title)) {
|
||||||
draw_rect(panel_rect, color);
|
|
||||||
}
|
}
|
||||||
|
r2f64_t gap_rect = r2f64_cut_left(&top_bar_rect, 1);
|
||||||
|
gfx2d_rect(gfx, gap_rect, black_color_global);
|
||||||
|
|
||||||
static f64 value = 0.2f;
|
|
||||||
ui_slider(rcut(&panel_rect, cut_top), ui_location_id(), &value, "value");
|
|
||||||
|
|
||||||
ui_widget(rcut(&panel_rect, cut_top), (ui_input_t){.title = "non centered label"}, (ui_flags_t){.draw_rect = true, .draw_text = true});
|
|
||||||
|
|
||||||
static b32 checkbox_memes;
|
|
||||||
ui_checkbox(rcut(&panel_rect, cut_top), &checkbox_memes, "checkbox");
|
|
||||||
|
|
||||||
|
|
||||||
// TODO(Krzosa): Draw arrows / triangles
|
|
||||||
{
|
|
||||||
f64 font_height = get_font_height();
|
|
||||||
f64 cut_size = font_height + style_padding.y;
|
|
||||||
r2f64_t rect = r2f64_cut_top(&panel_rect, cut_size);
|
|
||||||
|
|
||||||
static int counter;
|
|
||||||
|
|
||||||
if (ui_widget(rcut(&rect, cut_left), (ui_input_t){0}, (ui_flags_t){.draw_checkbox = true, .clickable = true}).pressed) {
|
|
||||||
counter -= 1;
|
|
||||||
}
|
|
||||||
char buff[256];
|
|
||||||
stbsp_snprintf(buff, sizeof(buff), "counter: %d", counter);
|
|
||||||
ui_label(rcut(&rect, cut_left), buff);
|
|
||||||
if (ui_widget(rcut(&rect, cut_left), (ui_input_t){0}, (ui_flags_t){.draw_checkbox = true, .clickable = true}).pressed) {
|
|
||||||
counter += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
v2f64_t ui_calc_text_pos(r2f64_t rect, char *title) {
|
|
||||||
f64 font_height = get_font_height();
|
|
||||||
f64 text_width = measure_text(title);
|
|
||||||
|
|
||||||
v2f64_t text_pos = rect.min;
|
|
||||||
{
|
|
||||||
v2f64_t rect_size = r2f64_get_size(rect);
|
|
||||||
v2f64_t offset_to_center = {(rect_size.x - text_width) / 2, (rect_size.y - font_height) / 2};
|
|
||||||
text_pos = v2f64_add(text_pos, offset_to_center);
|
|
||||||
}
|
|
||||||
|
|
||||||
return text_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct ui_signal_t ui_signal_t;
|
|
||||||
struct ui_signal_t {
|
|
||||||
b8 pressed;
|
|
||||||
b8 overlapping;
|
|
||||||
};
|
|
||||||
|
|
||||||
ui_signal_t ui_interact(app_event_t *ev, r2f64_t rect) {
|
|
||||||
ui_signal_t sig = {0};
|
|
||||||
if (r2f64_contains(rect, ev->mouse_pos)) {
|
|
||||||
sig.overlapping = true;
|
|
||||||
if (ev->kind == app_event_kind_mouse_down && ev->mouse_button == app_mouse_button_left) {
|
|
||||||
sig.pressed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sig;
|
|
||||||
}
|
|
||||||
|
|
||||||
b32 ui_button(app_event_t *ev, r2f64_t rect, char *title) {
|
|
||||||
v2f64_t text_pos = ui_calc_text_pos(rect, title);
|
|
||||||
ui_signal_t sig = ui_interact(ev, rect);
|
|
||||||
|
|
||||||
v4f32_t rect_color = secondary_color_global;
|
|
||||||
v4f32_t text_color = black_color_global;
|
|
||||||
if (sig.overlapping) {
|
|
||||||
rect_color = primary_color_global;
|
|
||||||
}
|
|
||||||
|
|
||||||
set_clip(rect);
|
|
||||||
draw_rect(rect, rect_color);
|
|
||||||
draw_text(text_pos, text_color, s8_from_char(title));
|
|
||||||
set_clip(r2f64(-1000, -1000, 1000000, 1000000));
|
|
||||||
|
|
||||||
return sig.pressed;
|
|
||||||
}
|
|
||||||
|
|
||||||
b32 ui_checkbox(app_event_t *ev, r2f64_t rect, b32 *value, char *title) {
|
|
||||||
v2f64_t text_pos = ui_calc_text_pos(rect, title);
|
|
||||||
ui_signal_t sig = ui_interact(ev, rect);
|
|
||||||
if (sig.pressed) *value = !*value;
|
|
||||||
|
|
||||||
v4f32_t rect_color = secondary_color_global;
|
|
||||||
v4f32_t text_color = black_color_global;
|
|
||||||
if (sig.overlapping) {
|
|
||||||
rect_color = primary_color_global;
|
|
||||||
}
|
|
||||||
if (*value) {
|
|
||||||
rect_color = v4f32_lerp(rect_color, accent2_color_global, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
set_clip(rect);
|
|
||||||
draw_rect(rect, rect_color);
|
|
||||||
draw_text(text_pos, text_color, s8_from_char(title));
|
|
||||||
set_clip(r2f64(-1000, -1000, 1000000, 1000000));
|
|
||||||
|
|
||||||
return *value;
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef struct ui_id_t ui_id_t;
|
|
||||||
struct ui_id_t { u64 value; };
|
|
||||||
|
|
||||||
ui_id_t ui_string_to_id(const char *string, i32 len) { // FNV HASH (1a?)
|
|
||||||
u8 *data8 = (u8 *)string;
|
|
||||||
u64 hash = (u64)14695981039346656037ULL;
|
|
||||||
for (u64 i = 0; i < len; i++) {
|
|
||||||
hash = hash ^ (u64)(data8[i]);
|
|
||||||
hash = hash * (u64)1099511628211ULL;
|
|
||||||
}
|
|
||||||
return (ui_id_t){ .value = hash };
|
|
||||||
}
|
|
||||||
#define ui_location_id() ui_string_to_id(FILE_AND_LINE, sizeof(FILE_AND_LINE) - 1)
|
|
||||||
ui_id_t ui_active_element = {0};
|
|
||||||
|
|
||||||
void ui_slider(app_event_t *ev, r2f64_t rect, ui_id_t id, f64 *value, char *title) {
|
|
||||||
v2f64_t text_pos = ui_calc_text_pos(rect, title);
|
|
||||||
ui_signal_t sig = ui_interact(ev, rect);
|
|
||||||
b32 interacting = false;
|
|
||||||
{
|
|
||||||
if (sig.pressed) {
|
|
||||||
ui_active_element = id;
|
|
||||||
}
|
|
||||||
if (id.value == ui_active_element.value) {
|
|
||||||
interacting = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (interacting) {
|
|
||||||
f64 mouse_pos = ev->mouse_pos.x;
|
|
||||||
v2f64_t rect_size = r2f64_get_size(rect);
|
|
||||||
*value = (mouse_pos - rect.min.x) / rect_size.x;
|
|
||||||
*value = CLAMP(*value, 0, 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
v2f64_t rect_size = r2f64_get_size(rect);
|
|
||||||
r2f64_t slider_rect = r2f64_get_left(&rect, rect_size.x * value[0]);
|
|
||||||
|
|
||||||
v4f32_t rect_color = secondary_color_global;
|
|
||||||
if (sig.overlapping) rect_color = v4f32_lerp(rect_color, accent2_color_global, 0.2);
|
|
||||||
v4f32_t slider_color = accent2_color_global;
|
|
||||||
if (sig.overlapping) slider_color = v4f32_lerp(slider_color, accent2_color_global, 0.2);
|
|
||||||
v4f32_t text_color = black_color_global;
|
|
||||||
|
|
||||||
set_clip(rect);
|
|
||||||
draw_rect(rect, rect_color);
|
|
||||||
draw_rect(slider_rect, slider_color);
|
|
||||||
draw_text(text_pos, text_color, s8_from_char(title));
|
|
||||||
set_clip(r2f64(-1000, -1000, 1000000, 1000000));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ui_demo(app_event_t *ev) {
|
|
||||||
if (ev->kind == app_event_kind_mouse_up) {
|
|
||||||
ui_active_element = (ui_id_t){0};
|
|
||||||
}
|
|
||||||
|
|
||||||
r2f64_t window_rect = (r2f64_t){(v2f64_t){0}, ev->window_size};
|
|
||||||
r2f64_t top_bar_rect = r2f64_cut_top(&window_rect, get_font_height() + 20);
|
|
||||||
draw_rect(window_rect, primary_color_global);
|
|
||||||
|
|
||||||
f64 padding = 50;
|
|
||||||
draw_rect(top_bar_rect, secondary_color_global);
|
|
||||||
|
|
||||||
static b32 open_file_panel;
|
|
||||||
f64 open_file_panel_xsize = 0;
|
|
||||||
{
|
|
||||||
// ▼▲▶◀
|
|
||||||
char *title = "▶ file";
|
|
||||||
if (open_file_panel) title = "▼ file";
|
|
||||||
open_file_panel_xsize = measure_text(title) + padding*2;
|
|
||||||
r2f64_t rect = r2f64_cut_left(&top_bar_rect, open_file_panel_xsize);
|
|
||||||
if (ui_checkbox(ev, rect, &open_file_panel, title)) {
|
|
||||||
}
|
|
||||||
r2f64_t gap_rect = r2f64_cut_left(&top_bar_rect, 1);
|
|
||||||
draw_rect(gap_rect, black_color_global);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (open_file_panel) {
|
|
||||||
f64 item_count = 20;
|
|
||||||
f64 item_size = get_font_height() + 20;
|
|
||||||
r2f64_t panel_rect = r2f64_get_top(&window_rect, item_count * item_size);
|
|
||||||
panel_rect = r2f64_get_left(&panel_rect, open_file_panel_xsize);
|
|
||||||
|
|
||||||
{
|
|
||||||
static f64 slider_value;
|
|
||||||
char buff[64];
|
|
||||||
stbsp_snprintf(buff, sizeof(buff), "%f", slider_value);
|
|
||||||
r2f64_t rect = r2f64_cut_top(&panel_rect, item_size);
|
|
||||||
ui_slider(ev, rect, ui_location_id(), &slider_value, buff);
|
|
||||||
}
|
|
||||||
|
|
||||||
// {
|
|
||||||
// static char buff[64];
|
|
||||||
// static ui_input_state input;
|
|
||||||
// if (input.buff == NULL) {
|
|
||||||
// input.buff = buff;
|
|
||||||
// input.cap = sizeof(buff);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// r2f64_t rect = r2f64_cut_top(&panel_rect, item_size);
|
|
||||||
// ui_input_text(rect, &input);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
char *title = "edit";
|
|
||||||
r2f64_t rect = r2f64_cut_left(&top_bar_rect, measure_text(title) + padding*2);
|
|
||||||
if (ui_button(ev, rect, title)) {
|
|
||||||
}
|
|
||||||
r2f64_t gap_rect = r2f64_cut_left(&top_bar_rect, 1);
|
|
||||||
draw_rect(gap_rect, black_color_global);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
char *title = "view";
|
|
||||||
r2f64_t rect = r2f64_cut_left(&top_bar_rect, measure_text(title) + padding*2);
|
|
||||||
if (ui_button(ev, rect, title)) {
|
|
||||||
}
|
|
||||||
r2f64_t gap_rect = r2f64_cut_left(&top_bar_rect, 1);
|
|
||||||
draw_rect(gap_rect, black_color_global);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user