eco2d/code/game/source/debug_ui.c

228 lines
7.3 KiB
C
Raw Normal View History

2021-05-13 12:17:44 +00:00
#include "debug_ui.h"
#include "raylib.h"
typedef enum {
DITEM_RAW,
DITEM_TEXT,
DITEM_BUTTON,
DITEM_SLIDER,
DITEM_LIST,
DITEM_END,
DITEM_FORCE_UINT8 = UINT8_MAX
} debug_kind;
typedef struct {
float x, y;
} debug_draw_result;
#define DBG_FONT_SIZE 22
#define DBG_FONT_SPACING DBG_FONT_SIZE * 1.2f
#define DBG_START_XPOS 15
#define DBG_START_YPOS 200
#define DBG_LIST_XPOS_OFFSET 10
#define DBG_SHADOW_OFFSET_XPOS 1
#define DBG_SHADOW_OFFSET_YPOS 1
static uint8_t is_shadow_rendered;
typedef struct debug_item {
debug_kind kind;
char const *name;
float name_width;
union {
union {
char const *text;
uint64_t val;
};
struct {
struct debug_item *items;
uint8_t is_collapsed;
} list;
void (*on_click)(void);
};
debug_draw_result (*proc)(struct debug_item*, float, float);
} debug_item;
typedef enum {
DAREA_OUTSIDE,
DAREA_HOVER,
DAREA_HELD,
DAREA_PRESS,
DAREA_FORCE_UINT8 = UINT8_MAX
} debug_area_status;
debug_area_status check_mouse_area(float xpos, float ypos, float w, float h);
bool is_btn_pressed(float xpos, float ypos, float w, float h, Color *color);
void UIDrawText(const char *text, float posX, float posY, int fontSize, Color color);
int UIMeasureText(const char *text, int fontSize);
#include "debug_ui_widgets.c"
2021-05-13 12:36:07 +00:00
#include "debug_ui_actions.c"
2021-05-13 12:17:44 +00:00
static debug_item items[] = {
{
.kind = DITEM_LIST,
.name = "general",
.list = {
.items = (debug_item[]) {
{ .kind = DITEM_TEXT, .name = "delta time", .proc = DrawDeltaTime },
{ .kind = DITEM_TEXT, .name = "random literal", .text = "hello", .proc = DrawLiteral },
{ .kind = DITEM_TEXT, .name = "zoom", .proc = DrawZoom },
{ .kind = DITEM_END },
}
}
},
{
.kind = DITEM_LIST,
.name = "profilers",
.list = {
.items = (debug_item[]) {
{ .kind = DITEM_RAW, .val = PROF_MAIN_LOOP, .proc = DrawProfilerDelta },
2021-05-13 14:37:53 +00:00
{ .kind = DITEM_TEXT, .name = "unmesasured time", .proc = DrawUnmeasuredTime },
2021-05-13 12:17:44 +00:00
{ .kind = DITEM_RAW, .val = PROF_WORLD_WRITE, .proc = DrawProfilerDelta },
{ .kind = DITEM_RAW, .val = PROF_RENDER, .proc = DrawProfilerDelta },
2021-05-13 13:44:08 +00:00
{ .kind = DITEM_RAW, .val = PROF_UPDATE_SYSTEMS, .proc = DrawProfilerDelta },
2021-05-13 12:17:44 +00:00
{ .kind = DITEM_RAW, .val = PROF_ENTITY_LERP, .proc = DrawProfilerDelta },
2021-05-13 13:44:08 +00:00
{ .kind = DITEM_RAW, .val = PROF_ENTITY_REMOVAL, .proc = DrawProfilerDelta },
2021-05-13 12:17:44 +00:00
{ .kind = DITEM_END },
},
//.is_collapsed = 1
}
},
2021-05-13 12:36:07 +00:00
{
.kind = DITEM_BUTTON,
.name = "exit game",
.on_click = ActExitGame,
},
2021-05-13 12:17:44 +00:00
{.kind = DITEM_END},
};
debug_draw_result debug_draw_list(debug_item *list, float xpos, float ypos, bool is_shadow) {
is_shadow_rendered = is_shadow;
for (debug_item *it = list; it->kind != DITEM_END; it += 1) {
switch (it->kind) {
case DITEM_LIST: {
// NOTE(zaklaus): calculate and cache name width for future use
if (it->name_width == 0) {
it->name_width = UIMeasureText(it->name, DBG_FONT_SIZE);
}
Color color = RAYWHITE;
if (is_btn_pressed(xpos, ypos, it->name_width, DBG_FONT_SIZE, &color)) {
it->list.is_collapsed = !it->list.is_collapsed;
}
UIDrawText(it->name, xpos, ypos, DBG_FONT_SIZE, color);
ypos += DBG_FONT_SPACING;
if (it->list.is_collapsed) break;
debug_draw_result res = debug_draw_list(it->list.items, xpos+DBG_LIST_XPOS_OFFSET, ypos, is_shadow);
ypos = res.y;
}break;
case DITEM_TEXT: {
char const *text = TextFormat("%s: ", it->name);
if (it->name_width == 0) {
it->name_width = UIMeasureText(text, DBG_FONT_SIZE);
}
UIDrawText(text, xpos, ypos, DBG_FONT_SIZE, RAYWHITE);
assert(it->proc);
debug_draw_result res = it->proc(it, xpos + it->name_width, ypos);
ypos = res.y;
}break;
case DITEM_RAW: {
assert(it->proc);
debug_draw_result res = it->proc(it, xpos, ypos);
ypos = res.y;
}break;
2021-05-13 12:36:07 +00:00
case DITEM_BUTTON: {
assert(it->on_click);
char const *text = TextFormat("> %s", it->name);
if (it->name_width == 0) {
it->name_width = UIMeasureText(text, DBG_FONT_SIZE);
}
Color color = RAYWHITE;
if (is_btn_pressed(xpos, ypos, it->name_width, DBG_FONT_SIZE, &color)) {
it->on_click();
}
debug_draw_result res = DrawColoredText(xpos, ypos, text, color);
ypos = res.y;
}break;
2021-05-13 12:17:44 +00:00
default: {
}break;
}
}
return (debug_draw_result){xpos, ypos};
}
void debug_draw(void) {
debug_draw_list(items, DBG_START_XPOS+DBG_SHADOW_OFFSET_XPOS, DBG_START_YPOS+DBG_SHADOW_OFFSET_YPOS, 1); // NOTE(zaklaus): draw shadow
debug_draw_list(items, DBG_START_XPOS, DBG_START_YPOS, 0);
}
debug_area_status check_mouse_area(float xpos, float ypos, float w, float h) {
if (is_shadow_rendered) return DAREA_OUTSIDE;
bool is_inside = CheckCollisionPointRec(GetMousePosition(), (Rectangle){xpos, ypos, w, h});
if (is_inside) {
return IsMouseButtonReleased(MOUSE_LEFT_BUTTON) ? DAREA_PRESS : IsMouseButtonDown(MOUSE_LEFT_BUTTON) ? DAREA_HELD : DAREA_HOVER;
}
return DAREA_OUTSIDE;
}
bool is_btn_pressed(float xpos, float ypos, float w, float h, Color *color) {
assert(color);
*color = RAYWHITE;
debug_area_status area = check_mouse_area(xpos, ypos, w, h);
if (area == DAREA_PRESS) {
*color = RED;
return true;
} else if (area == DAREA_HOVER) {
*color = YELLOW;
} else if (area == DAREA_HELD) {
*color = RED;
}
return false;
}
static inline
void UIDrawText(const char *text, float posX, float posY, int fontSize, Color color) {
// Check if default font has been loaded
if (GetFontDefault().texture.id != 0) {
Vector2 position = { (float)posX , (float)posY };
int defaultFontSize = 10; // Default Font chars height in pixel
int new_spacing = fontSize/defaultFontSize;
DrawTextEx(GetFontDefault(), text, position, (float)fontSize , (float)new_spacing , is_shadow_rendered ? BLACK : color);
}
}
static inline
int UIMeasureText(const char *text, int fontSize) {
Vector2 vec = { 0.0f, 0.0f };
// Check if default font has been loaded
if (GetFontDefault().texture.id != 0) {
int defaultFontSize = 10; // Default Font chars height in pixel
int new_spacing = fontSize/defaultFontSize;
vec = MeasureTextEx(GetFontDefault(), text, (float)fontSize, (float)new_spacing);
}
return (int)vec.x;
}