From 96b27fe9841e537614962e273ef9f0802365ea6d Mon Sep 17 00:00:00 2001 From: quou Date: Tue, 31 Dec 2024 23:38:11 +1100 Subject: ui stuf and things hmm m mmm m シ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.cpp | 4 +++ app.hpp | 3 ++ c2.cpp | 9 +++++- debugger.cpp | 34 +++++++++++++++++++++ qstd/Makefile | 2 +- qstd/plat.c | 40 ++++++++++++++++++++++-- qstd/plat.h | 5 +++ ui.cpp | 97 ++++++++++++++++++++++++++++++++++++++++++----------------- ui.hpp | 5 +++ 9 files changed, 166 insertions(+), 33 deletions(-) diff --git a/app.cpp b/app.cpp index 95f730b..0f57a71 100644 --- a/app.cpp +++ b/app.cpp @@ -515,6 +515,7 @@ int WinMain( #endif void App::init(const char* name) { + dt = 0.0f; internal = (App_Internal*)arena_alloc( arena, sizeof *internal @@ -536,6 +537,7 @@ void App::destroy() { void App::begin() { int j; + begin_t = get_time(); for (j = 0; j < key_count; j++) key_states[j] &= ~( key_state_just_pressed | key_state_just_released @@ -548,6 +550,8 @@ void App::begin() { } void App::end() { + end_t = get_time(); + dt = (float)((double)(end_t - begin_t) / 1000000000.0); internal->end(this); } diff --git a/app.hpp b/app.hpp index 3e2ef23..9a660cf 100644 --- a/app.hpp +++ b/app.hpp @@ -4,6 +4,7 @@ #define app_memory_size (1024 * 1024 * 32) #include +#include struct Arena; @@ -102,11 +103,13 @@ struct App_Internal; struct App { Arena* arena; + float dt; int running, w, h; int mx, my; int scrollx, scrolly; unsigned char key_states[key_count]; unsigned char mbtn_states[mbtn_count]; + uint64_t begin_t, end_t; App_Internal* internal; template diff --git a/c2.cpp b/c2.cpp index d356ada..fb2aa38 100644 --- a/c2.cpp +++ b/c2.cpp @@ -9,6 +9,7 @@ extern "C" { } #include #include +#include #define video_arena_size (1024 * 1024 * 16) #define asset_arena_size (1024 * 1024 * 4) @@ -138,6 +139,7 @@ extern "C" int entrypoint() { ui->layout(app->w, app->h); auto toolbar = ui->create_element(ui->root); register_debuggers(ui, toolbar); + auto fps_label = ui->create_element(ui->root, ""); while (app->running) { Arena frame_arena; init_arena(&frame_arena, per_frame, per_frame_memory_size); @@ -145,6 +147,11 @@ extern "C" int entrypoint() { app->begin(); dev->begin_frame(); + if (frame % 10 == 0) { + char buf[32]; + sprintf(buf, "FPS: %g", 1.0f / app->dt); + fps_label->set_text(buf); + } ui->update(&frame_arena); { @@ -246,7 +253,7 @@ extern "C" int entrypoint() { ctx.debug_pop(); r += 10; - rot += 0.05f; + rot += 5.0f * app->dt; frame++; dev->present(); app->end(); diff --git a/debugger.cpp b/debugger.cpp index 6a71e15..6cda856 100644 --- a/debugger.cpp +++ b/debugger.cpp @@ -11,6 +11,14 @@ struct Vram_Debugger : UI::Modal { } }; +struct Device_Debugger : UI::Modal { + UI::Element* enable_btn; + + Device_Debugger(UI* ui, UI::Element* parent): + UI::Modal(ui, parent, "Device debugger") { + } +}; + void create_vram_debugger( UI* ui, UI::Element* parent, @@ -28,6 +36,23 @@ void create_vram_debugger( ui->create_element(window->contents, "Hello, I'm the VRAM debugger!"); } +void create_device_debugger( + UI* ui, + UI::Element* parent, + UI::Element* button +) { + auto window = ui->create_element(parent); + window->enable_btn = button; + window->handler = [](UI::Element* e, const UI::Message& m) { + if (m.type == UI::Message::Type::destroy) { + auto window = (Device_Debugger*)e; + window->enable_btn->enable(); + } + return 0; + }; + ui->create_element(window->contents, "Hello, I'm the device debugger!"); +} + void register_debuggers(UI* ui, UI::Toolbar* toolbar) { auto btnvram = ui->create_element(toolbar, "VRAM Debugger"); btnvram->handler = [](UI::Element* e, const UI::Message& m) { @@ -37,4 +62,13 @@ void register_debuggers(UI* ui, UI::Toolbar* toolbar) { } return 0; }; + auto btndevice = ui->create_element(toolbar, "Device Debugger"); + btndevice->handler = [](UI::Element* e, const UI::Message& m) { + if (m.type == UI::Message::Type::click) { + e->disable(); + create_device_debugger(e->ui, e->ui->root, e); + } + return 0; + }; } + diff --git a/qstd/Makefile b/qstd/Makefile index c4b088b..7e3f0f1 100644 --- a/qstd/Makefile +++ b/qstd/Makefile @@ -2,7 +2,7 @@ target = libqstd.a includes = -I../qstd defines = -Dplat_x86 -Dplat_posix -Dallocation_default_alignment=8 -cflags = -std=c90 -pedantic -Wall -Wextra $(DEBUG_COMPILE_FLAG) $(includes) $(defines) +cflags = -std=gnu90 -pedantic -Wall -Wextra $(DEBUG_COMPILE_FLAG) $(includes) $(defines) lflags = $(DEBUG_LINK_FLAG) objects = plat.o memory.o str.o pack.o diff --git a/qstd/plat.c b/qstd/plat.c index 7f07b96..15e0265 100644 --- a/qstd/plat.c +++ b/qstd/plat.c @@ -1,15 +1,21 @@ #include "plat.h" #ifdef plat_posix +#ifndef _POSIX_SOURCE #define _POSIX_SOURCE +#endif +#ifndef _GNU_SOURCE #define _GNU_SOURCE +#endif +#include #include +#include +#include #include #include +#include #include -#include -#include extern int isatty(int); extern int fileno(FILE*); @@ -83,6 +89,34 @@ void pbreak(int code) { #endif } +static clockid_t global_clock; +static unsigned long global_freq; +static int time_init = 0; + +void init_timer(void) { + struct timespec ts; + global_clock = CLOCK_REALTIME; + global_freq = 1000000000; + time_init = 1; +#if defined(_POSIX_MONOTONIC_CLOCK) + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { + global_clock = CLOCK_MONOTONIC; + } +#else + (void)ts; +#endif +} + +uint64_t get_time(void) { + struct timespec ts; + if (!time_init) + init_timer(); + clock_gettime(global_clock, &ts); + return + (uint64_t)ts.tv_sec * global_freq + + (uint64_t)ts.tv_nsec; +} + #endif #ifdef plat_win @@ -153,4 +187,4 @@ void pbreak(int code) { } -#endif \ No newline at end of file +#endif diff --git a/qstd/plat.h b/qstd/plat.h index 27521fa..b3715a3 100644 --- a/qstd/plat.h +++ b/qstd/plat.h @@ -1,6 +1,8 @@ #ifndef plat_h #define plat_h +#include + #ifdef assert #undef assert #endif @@ -29,4 +31,7 @@ void print_err(const char* fmt, ...); void print_war(const char* fmt, ...); void pbreak(int code); +uint64_t get_time(void); + + #endif diff --git a/ui.cpp b/ui.cpp index 2ed1c7b..8a292c7 100644 --- a/ui.cpp +++ b/ui.cpp @@ -644,7 +644,7 @@ UI::Element* UI::alloc_element(size_t size) { UI::Element::Element(UI* ui, Element* parent): ui(ui), - parent(parent), + parent(0), children(0), next(0), handler(0), @@ -723,6 +723,8 @@ void UI::Element::enable() { } void UI::Element::add_child(Element* ch) { + assert(ch->parent == 0); + assert(ch->next == 0); if (!children) children = ch; else { @@ -730,6 +732,7 @@ void UI::Element::add_child(Element* ch) { for (; child && child->next; child = child->next); child->next = ch; } + ch->parent = this; ui->layout_dirty = true; } @@ -743,6 +746,8 @@ void UI::Element::remove_child(Element* ch) { prev->next = ch->next; else children = ch->next; + ch->next = 0; + ch->parent = 0; } void UI::Element::message(const Message& msg) { @@ -760,8 +765,6 @@ UI::Rect UI::Container::layout(const Rect& avail) { Rect used = avail; used.w = used.h = 0; bound = avail; - clip = avail; - clip.clip(ui->area); for (child = children; child; child = child->next) { int h; Rect r = child->layout(area); @@ -772,7 +775,17 @@ UI::Rect UI::Container::layout(const Rect& avail) { used.h += h; } bound = used; - return used; + bound.clip(avail); + clip = bound; + clip.clip(ui->area); + if (clip.x == 0 && clip.y == 0 && clip.w == 300 && clip.h == 80) { + return bound; + } + return bound; +} + +void UI::Container::on_render() { + ui->mesh.set_clip(clip); } UI::Toolbar::Toolbar(UI* ui, Element* parent): @@ -801,12 +814,8 @@ UI::Rect UI::Toolbar::layout(const Rect& avail) { void UI::Toolbar::on_render() { ui->mesh.set_clip(clip); - ui->mesh.add_rect( - ui, - bound.x, - bound.y, - bound.w, - bound.h, + ui->draw_container( + bound, 0xa7a7a7 ); } @@ -837,19 +846,20 @@ UI::Rect UI::Button::layout(const Rect& avail) { void UI::Button::on_render() { Colour tc = 0x000000; + int toff[] = { 0, 0 }; if (flags & Flags::disabled) tc = 0x4f4f4f; - if (this == ui->hovered) - ui->draw_container(bound, 0xf0f8ff); - else if (this == ui->hot) + if (this == ui->hot) { + toff[0] = 1; + toff[1] = 1; ui->draw_containeri(bound, 0xffffff); - else + } else ui->draw_container(bound, 0xffffff); ui->mesh.set_clip(clip); ui->mesh.add_text( ui, - bound.x + ui_padding, - bound.y + ui_padding, + bound.x + ui_padding + toff[0], + bound.y + ui_padding + toff[1], text, tc ); @@ -890,30 +900,43 @@ void UI::Label::on_render() { ); } -static int drag_handler(UI::Modal* modal, const UI::Message& msg) { - if (msg.type == UI::Message::Type::activate) { - const App& app = *modal->ui->app; - const UI::Rect& tb = modal->title_bar->bound; - modal->dragging = true; - modal->drag_offset[0] = app.mx - tb.x; - modal->drag_offset[1] = app.my - tb.y; +void UI::Label::set_text(const char* s) { + heap_free(ui->heap, text); + text = dup_stringh(ui->heap, s); + ui->layout_dirty = 1; +} + +static int title_handler(UI::Modal* modal, const UI::Message& msg) { + switch (msg.type) { + case UI::Message::Type::activate: { + const App& app = *modal->ui->app; + const UI::Rect& tb = modal->title_bar->bound; + modal->dragging = true; + modal->drag_offset[0] = app.mx - tb.x; + modal->drag_offset[1] = app.my - tb.y; + modal->bring_to_front(); + } break; + case UI::Message::Type::deactivate: + modal->dragging = false; + break; + default: return 0; } - if (msg.type == UI::Message::Type::deactivate) - modal->dragging = false; return 0; }; UI::Modal::Modal(UI* ui, Element* parent, const char* text): Element(ui, parent), dragging(false) { + pos[0] = 0; + pos[1] = 0; contents = ui->create_element(this); title_bar = ui->create_element(contents); title_bar->handler = [](Element* e, const Message& m) { - return drag_handler((Modal*)e->parent->parent, m); + return title_handler((Modal*)e->parent->parent, m); }; close = ui->create_element