power_play/src/proto/pp_widgets.c

352 lines
12 KiB
C

////////////////////////////////////////////////////////////
//~ Theme helpers
PP_WidgetTheme PP_GetWidgetTheme(void)
{
PP_WidgetTheme theme = ZI;
theme.font = ResourceKeyFromStore(&PP_Resources, Lit("font/fixedsys.ttf"));
theme.window_background_color = Rgb32(0xff1a1d1e);
theme.window_border_color = Rgb32(0xff343a3b);
theme.window_border = 1;
theme.window_width = 300;
theme.window_padding = theme.window_border - 1;
theme.divider_color = theme.window_border_color;
theme.font_size = 16;
theme.window_title_font_size = 16;
theme.text_padding_x = 3;
theme.text_padding_y = 3;
return theme;
}
void PP_PushWidgetThemeStyles(PP_WidgetTheme theme)
{
UI_Push(Font, theme.font);
UI_Push(FontSize, theme.font_size);
}
////////////////////////////////////////////////////////////
//~ Commands widget
void PP_BeginCommandsWidget(PP_CommandsWidget *widget)
{
ZeroStruct(&widget->build);
widget->build.cp = UI_PushCP(UI_NilKey);
UI_Push(Tag, HashF("commands widget"));
}
UI_Report PP_PushCommandsWidgetItem(PP_CommandsWidget *widget, String name)
{
Arena *frame_arena = UI_FrameArena();
UI_Key key = UI_KeyF("btn%F", FmtSint(widget->build.num_items));
PP_CommandsWidgetItem *item = PushStruct(frame_arena, PP_CommandsWidgetItem);
item->name = name;
item->key = key;
QueuePush(widget->build.first_item, widget->build.last_item, item);
++widget->build.num_items;
return UI_ReportFromKey(key);
}
void PP_EndCommandsWidget(PP_CommandsWidget *widget)
{
PP_WidgetTheme theme = PP_GetWidgetTheme();
Vec2 cursor_pos = UI_CursorPos();
UI_Push(Tag, HashF("commands widget"));
UI_Key titlebar_key = UI_KeyF("title bar");
Vec4 window_background_color = theme.window_background_color;
Vec4 window_border_color = theme.window_border_color;
Vec4 titlebar_color = ZI;
Vec4 titlebar_border_color = ZI;
Vec4 divider_color = theme.divider_color;
{
UI_Report rep = UI_ReportFromKey(titlebar_key);
if (rep.m1_held)
{
widget->pos = SubVec2(cursor_pos, rep.last_m1_offset);
}
window_border_color = BlendSrgb(window_border_color, Rgb(0.5, 0.5, 0.5), rep.hot);
}
UI_Push(BackgroundColor, window_background_color);
UI_Push(BorderColor, window_border_color);
UI_Push(Border, theme.window_border);
// UI_Push(Rounding, UI_RPIX(15));
UI_Push(Rounding, UI_RPIX(15));
UI_Push(Width, UI_PIX(theme.window_width, 0));
UI_Push(Height, UI_SHRINK(0, 0));
UI_Push(ChildLayoutAxis, Axis_Y);
UI_Push(FloatingPos, widget->pos);
UI_SetNext(Flags, UI_BoxFlag_Floating);
UI_PushCP(UI_BuildBoxEx(UI_KeyF("titlebar")));
{
/* Title bar */
UI_PushCP(UI_NilKey);
{
UI_Push(BackgroundColor, titlebar_color);
UI_Push(BorderColor, titlebar_border_color);
UI_Push(Rounding, UI_RPIX(0));
UI_Push(ChildLayoutAxis, Axis_X);
UI_Push(Width, UI_GROW(1, 0));
UI_Push(Height, UI_FNT(2, 1));
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable);
UI_PushCP(UI_BuildBoxEx(titlebar_key));
{
UI_Push(Width, UI_GROW(1, 0));
UI_Push(BorderColor, 0);
/* Left title box */
UI_BuildRow();
/* Title box */
UI_SetNext(FontSize, theme.window_title_font_size);
UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(Width, UI_SHRINK(0, 1));
UI_SetNext(Text, Lit("Commands"));
UI_SetNext(Flags, UI_BoxFlag_DrawText);
UI_BuildBox();
/* Right title box */
UI_BuildRow();
}
UI_PopCP(UI_TopCP());
}
UI_PopCP(UI_TopCP());
}
f32 padding = theme.window_border;
UI_SetNext(Tint, 0);
UI_SetNext(Rounding, 0);
UI_PushCP(UI_BuildRow());
{
UI_BuildSpacer(UI_PIX(padding, 1), Axis_X);
{
UI_SetNext(Tint, 0);
UI_SetNext(Rounding, 0);
UI_SetNext(Width, UI_GROW(1, 0));
UI_PushCP(UI_BuildColumn());
{
for (PP_CommandsWidgetItem *item = widget->build.first_item; item; item = item->next)
{
UI_BuildDivider(UI_PIX(1, 1), theme.divider_color, Axis_Y);
UI_Key btn_key = item->key;
UI_Report btn_rep = UI_ReportFromKey(btn_key);
Vec4 hovered_color = Rgb32(0x103c4c);
Vec4 pressed_color = hovered_color;
pressed_color.w = 0.2;
f32 hot = btn_rep.hot;
f32 active = btn_rep.active;
f32 hovered = btn_rep.hovered;
Vec4 color = theme.window_background_color;
Vec4 border_color = ZI;
color = BlendSrgb(color, hovered_color, hot);
color = BlendSrgb(color, pressed_color, active * hovered);
border_color = BlendSrgb(border_color, Rgb32(0x0078a6), hot);
UI_SetNext(Rounding, 0);
UI_SetNext(Tint, 0);
UI_PushCP(UI_BuildRow());
{
UI_SetNext(BorderColor, border_color);
UI_SetNext(BackgroundColor, color);
UI_SetNext(Rounding, UI_RPIX(5));
UI_SetNext(Width, UI_GROW(1, 0));
UI_SetNext(Height, UI_FNT(1.5, 1));
UI_SetNext(ChildAlignment, UI_Alignment_Left);
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable);
UI_PushCP(UI_BuildRowEx(btn_key));
{
/* Begin spacer */
UI_BuildSpacer(UI_PIX(20, 1), Axis_X);
/* Command label */
UI_BuildLabel(item->name);
/* Middle spacer */
UI_BuildSpacer(UI_GROW(1, 0), Axis_X);
/* Command hotkey button */
UI_SetNext(Text, UI_StringF("Test"));
UI_SetNext(Width, UI_SHRINK(theme.text_padding_x, 1));
UI_SetNext(Height, UI_GROW(1, 0));
UI_SetNext(Rounding, UI_RPIX(0));
UI_SetNext(Border, 0);
UI_SetNext(BackgroundColor, Color_Cyan);
UI_SetNext(ChildAlignment, UI_Alignment_Center);
UI_SetNext(Flags, UI_BoxFlag_DrawText | UI_BoxFlag_Interactable);
UI_PushCP(UI_BuildRow());
{
}
UI_PopCP(UI_TopCP());
/* End spacer */
UI_BuildSpacer(UI_PIX(20, 1), Axis_X);
}
UI_PopCP(UI_TopCP());
}
UI_PopCP(UI_TopCP());
}
}
UI_PopCP(UI_TopCP());
}
UI_BuildSpacer(UI_PIX(padding, 1), Axis_X);
}
UI_PopCP(UI_TopCP());
UI_BuildSpacer(UI_PIX(padding, 1), Axis_Y);
UI_PopCP(widget->build.cp);
}
////////////////////////////////////////////////////////////
//~ Console widget
UI_Key PP_BuildConsoleWidget(b32 minimized)
{
/* TODO: Remove this whole thing */
__prof;
TempArena scratch = BeginScratchNoConflict();
// i32 console_level = minimized ? LogLevel_Success : LogLevel_Debug;
i32 console_level = LogLevel_Debug;
Vec4 colors[LogLevel_Count][2] = ZI;
SetBytes(colors, 0xFF, sizeof(colors));
/* Debug colors */
colors[LogLevel_Debug][0] = Rgb(0.4, 0.1, 0.4);
colors[LogLevel_Debug][1] = Rgb(0.5, 0.2, 0.5);
/* Info colors */
colors[LogLevel_Info][0] = Rgb(0.4, 0.4, 0.4);
colors[LogLevel_Info][1] = Rgb(0.5, 0.5, 0.5);
/* Success colors */
colors[LogLevel_Success][0] = Rgb(0.1, 0.3, 0.1);
colors[LogLevel_Success][1] = Rgb(0.2, 0.4, 0.2);
/* Warning colors */
colors[LogLevel_Warning][0] = Rgb(0.4, 0.4, 0.1);
colors[LogLevel_Warning][1] = Rgb(0.5, 0.5, 0.2);
/* Error colors */
colors[LogLevel_Error][0] = Rgb(0.4, 0.1, 0.1);
colors[LogLevel_Error][1] = Rgb(0.5, 0.2, 0.2);
i64 max_time_ns = I64Max;
i64 fade_time_ns = max_time_ns;
if (minimized)
{
max_time_ns = NsFromSeconds(10);
fade_time_ns = max_time_ns;
}
f32 fade_curve = 0.5;
i64 now_ns = TimeNs();
UI_Key console_box = ZI;
{
UI_SetNext(Border, 0);
if (minimized)
{
UI_SetNext(BackgroundColor, 0);
UI_SetNext(Width, UI_PIX(500, 0));
UI_SetNext(Height, UI_SHRINK(0, 1));
}
else
{
UI_SetNext(BackgroundColor, Rgba(1, 1, 1, 0.02));
UI_SetNext(Width, UI_GROW(1, 0));
UI_SetNext(Height, UI_SHRINK(0, 1));
}
console_box = UI_BuildColumnEx(UI_KeyF("Console box"));
UI_PushCP(console_box);
{
/* Gather display logs */
u64 max = 20;
u64 display_count = 0;
LogEvent *display_logs = PushStructs(scratch.arena, LogEvent, max);
{
b32 done = 0;
if (minimized)
{
max = 5;
}
LogEventsArray logs = GetLogEvents();
for (u64 i = logs.count; i-- > 0 && display_count < max && !done;)
{
LogEvent ev = logs.logs[i];
if (ev.time_ns > (now_ns - max_time_ns))
{
if (ev.level <= console_level)
{
display_logs[display_count] = ev;
++display_count;
}
}
else
{
done = 1;
}
}
}
/* Display logs in reverse */
for (u64 i = display_count; i-- > 0;)
{
LogEvent log = display_logs[i];
f32 opacity = 0.75;
f32 lin = 1.0 - ClampF64((f64)(now_ns - log.time_ns) / (f64)fade_time_ns, 0, 1);
opacity *= PowF32(lin, fade_curve);
String text = log.msg;
if (!minimized)
{
DateTime datetime = log.datetime;
text = StringF(
scratch.arena,
"[%F:%F:%F.%F] %F",
FmtUintZ(datetime.hour, 2),
FmtUintZ(datetime.minute, 2),
FmtUintZ(datetime.second, 2),
FmtUintZ(datetime.milliseconds, 3),
FmtString(text));
}
UI_PushCP(UI_NilKey);
{
Vec4 tint = VEC4(1, 1, 1, opacity);
UI_Push(Tint, tint);
{
Vec4 color = colors[log.level][log.level_id % 2];
UI_Push(BackgroundColor, color);
UI_Push(Width, UI_GROW(1, 0));
UI_Push(Height, UI_FNT(1.5, 1));
UI_Push(BorderColor, Rgb(0.25, 0.25, 0.25));
UI_Push(Rounding, UI_RPIX(0));
UI_Push(Border, 1);
UI_Push(ChildAlignment, UI_Alignment_Left);
UI_PushCP(UI_BuildRow());
{
// UI_SetNext(Height, UI_PIX(100, 0));
UI_BuildSpacer(UI_PIX(10, 0), Axis_X);
UI_Push(BackgroundColor, 0);
UI_Push(Border, 0);
UI_Push(Text, text);
UI_Push(Width, UI_GROW(1, 0));
UI_Push(Height, UI_SHRINK(0, 1));
UI_Push(Flags, UI_BoxFlag_DrawText);
UI_BuildBox();
}
UI_PopCP(UI_TopCP());
}
}
UI_PopCP(UI_TopCP());
}
}
UI_PopCP(UI_TopCP());
}
EndScratch(scratch);
return console_box;
}