From 205f7d49530e6c32ec0a09045d9cb45dcf9b1752 Mon Sep 17 00:00:00 2001 From: quou Date: Wed, 31 Jul 2024 22:12:48 +1000 Subject: GUI + map editor beginnings --- 3de.c | 91 ++++++++++++++++++++--------- Makefile | 3 + config.h | 5 ++ editor.c | 29 ++++++++++ editor.h | 13 +++++ gui.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gui.h | 70 ++++++++++++++++++++++ map.c | 5 ++ map.h | 4 ++ 9 files changed, 390 insertions(+), 28 deletions(-) create mode 100644 editor.c create mode 100644 editor.h create mode 100644 gui.c create mode 100644 gui.h create mode 100644 map.c diff --git a/3de.c b/3de.c index 1e40f91..bf114ec 100644 --- a/3de.c +++ b/3de.c @@ -1,5 +1,7 @@ #include "asset.h" #include "config.h" +#include "editor.h" +#include "gui.h" #include "map.h" #include "maths.h" #include "memory.h" @@ -9,6 +11,25 @@ #include "services.h" #include "tile.h" +static int map_data[] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, +}; + #include void draw_spinny(Renderer* r, Colour c) { @@ -51,28 +72,17 @@ void draw_line(Renderer* r, int x, int y) { ren_line(r, make_red(), s, e); } -void draw_map(Renderer* r, Player* p) { - int data[512] = { - 16, 16, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - }; +void init_map(Map* m) { + int* t = (int*)&m[1], i; + m->w = 16; + m->h = 16; + for (i = 0; i < 0x100; i++) { + t[i] = map_data[i]; + } +} + +void draw_map(Renderer* r, const Player* p, const Map* m) { int pos[2]; - Map* m = (Map*)data; pos[0] = p->p[0]; pos[1] = p->p[2]; ren_map(r, m, pos, p->f, p->l); @@ -81,14 +91,19 @@ void draw_map(Renderer* r, Player* p) { int entrypoint(int argc, const char** argv, Arena* a) { App* app; Renderer r = { 0 }; + GUI g; + Editor e; Heap h; FPS f; char buf[32]; int* depth = 0; - Arena preload; + Arena preload, gui_arena, map_arena; + Map* map; + void* gui_mem; Colour blue = make_aliceblue(); Player p; Services s; + int editing = 0; (void)argc; (void)argv; init_maths(); @@ -102,6 +117,12 @@ int entrypoint(int argc, const char** argv, Arena* a) { arena_alloc(a, asset_preload_memory_size), asset_preload_memory_size ); + init_arena( + &map_arena, + arena_alloc(a, map_memory_size), + map_memory_size + ); + gui_mem = arena_alloc(a, gui_memory_size); app = new_app(&h, 640, 480, "3D Engine"); if (!app) return app->err; init_fps(&f, 20); @@ -115,20 +136,34 @@ int entrypoint(int argc, const char** argv, Arena* a) { s.r = &r; cfg_mouse(app, 0); init_player(&p); + map = arena_alloc(&map_arena, map_size(max_map_w, max_map_h)); + init_map(map); while (app->o) { fps_begin(&f); while (f.now >= f.next) { app_begin(app); - update_player(&p, &s); + init_arena(&gui_arena, gui_mem, gui_memory_size); + gui_begin(&g, app, &gui_arena); + if (app->key_states[key_f12] & key_state_just_pressed) { + editing = !editing; + cfg_mouse(app, editing); + } + if (!editing) + update_player(&p, &s); ren_begin(&r, app->fb, depth, app->w, app->h); - ren_clear(&r); + ren_clearc(&r, make_colour(0xc3c3c3, 0xff)); ren_cleard(&r, f1 * 300); /* draw_line(&r, app->mx, app->my);*/ - push_player_cam(&p); - draw_gun(&r); - draw_map(&r, &p); - pop_player_cam(); + if (editing) { + edit_map(&e, &g, map); + } else { + push_player_cam(&p); + draw_map(&r, &p, map); + draw_gun(&r); + pop_player_cam(); + } /*draw_tri(&r, app->mx, app->my);*/ + gui_end(&g, &r); sprintf(buf, "FPS: %d", app->fps); ren_texts(&r, blue, 3, 3, buf); sprintf(buf, "CAP: %d", f.fps); diff --git a/Makefile b/Makefile index 109b94f..e36d50b 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,9 @@ pack = pack sources = \ 3de.c \ asset.c \ + editor.c \ + gui.c \ + map.c \ maths.c \ memory.c \ plat.c \ diff --git a/config.h b/config.h index 3e4a32d..87a4824 100644 --- a/config.h +++ b/config.h @@ -4,6 +4,8 @@ #define memory_size (1024 * 1024 * 128) #define app_memory_size (1024 * 1024 * 32) #define asset_preload_memory_size (1024 * 1024 * 8) +#define gui_memory_size (1024 * 8) +#define map_memory_size (1024 * 8) #define max_vp_w 2000 #define max_vp_h 2000 @@ -11,4 +13,7 @@ #define max_pc_window_w 5000 #define max_pc_window_h 3000 +#define max_map_w 32 +#define max_map_h 32 + #endif diff --git a/editor.c b/editor.c new file mode 100644 index 0000000..0aae694 --- /dev/null +++ b/editor.c @@ -0,0 +1,29 @@ +#include "editor.h" +#include "asset.h" +#include "gui.h" +#include "map.h" +#include "render.h" + +static GUI_Scroll_State map_ss = { 0 }; + +void draw_map_scrollable( + GUI* g, + Renderer* r, + const Rect* rect, + const GUI_Scroll_State* ss +) { + (void)g; + (void)ss; + ren_texture(r, rect, get_texture(asset_id_floorboards_texture)); +} + +void edit_map(Editor* e, GUI* g, Map* m) { + Rect b = gui_viewport(g); + Rect t = gui_cut_up(&b, gui_text_height() + 4); + (void)e; + (void)m; + gui_btn(g, gui_cut_left(&t, gui_text_width("Load", 4) + 4), "Save"); + gui_btn(g, gui_cut_left(&t, gui_text_width("Save", 4) + 4), "Load"); + gui_scrollable(g, b, &map_ss, draw_map_scrollable); +} + diff --git a/editor.h b/editor.h new file mode 100644 index 0000000..ffe22e5 --- /dev/null +++ b/editor.h @@ -0,0 +1,13 @@ +#ifndef editor_h +#define editor_h + +struct GUI; +struct Map; + +typedef struct { + int pad; +} Editor; + +void edit_map(Editor* e, struct GUI* g, struct Map* m); + +#endif diff --git a/gui.c b/gui.c new file mode 100644 index 0000000..0fe1f69 --- /dev/null +++ b/gui.c @@ -0,0 +1,198 @@ +#include "gui.h" +#include "memory.h" +#include "plat.h" +#include "render.h" +#include "standard.h" + +void* gui_alloc(GUI* g, int size) { + GUI_El* e = arena_alloc(g->a, size); + if (g->prev) + g->prev->next = e; + if (!g->first) + g->first = e; + g->prev = e; + e->next = 0; + return e; +} + +void gui_begin(GUI* g, const App* app, Arena* a) { + g->a = a; + g->app = app; + g->pad = 2; + g->first = 0; + g->cursor[0] = 10; + g->cursor[1] = 10; +} + +void gui_get_layout(GUI* g, Rect* r) { + r->x = g->cursor[0]; + r->y = g->cursor[1]; + g->cursor[1] += r->h; +} + +int gui_text_width(const char* text, int len) { + (void)text; + return len * 10; +} + +int gui_text_height(void) { + return 10; +} + +int mouse_over(const App* app, const Rect* r) { + return + app->mx > r->x && + app->my > r->y && + app->mx < r->x + r->w && + app->my < r->y + r->h; +} + +Rect gui_viewport(GUI* g) { + Rect r = { 0 }; + r.w = g->app->w; + r.h = g->app->h; + return r; +} + +Rect gui_cut_left(Rect* a, int v) { + Rect r = * a; + a->x += v; + a->w -= v; + r.w -= a->w; + return r; +} + +Rect gui_cut_right(Rect* a, int v) { + Rect r = *a; + a->w -= v; + r.x += v; + r.w -= v; + return r; +} + +Rect gui_cut_down(Rect* a, int v) { + Rect r = *a; + a->h -= v; + r.y += v; + r.h -= v; + return r; +} + +Rect gui_cut_up(Rect* a, int v) { + Rect r = * a; + a->y += v; + a->h -= v; + r.h -= a->h; + return r; +} + +int gui_btn(GUI* g, Rect r, const char* text) { + int len = string_len(text); + GUI_Btn* e = gui_alloc(g, sizeof *e); + e->el.type = gui_el_type_btn; + e->el.r = r; + e->text = arena_alloc_aligned(g->a, len + 1, 1); + string_copy(e->text, text); + e->hover = mouse_over(g->app, &e->el.r); + e->active = e->hover && + g->app->mbtn_states[mbtn_left] & key_state_pressed; + return e->hover && + g->app->mbtn_states[mbtn_left] & key_state_just_released; +} + +void gui_scrollable( + GUI* g, + Rect r, + GUI_Scroll_State* state, + GUI_Scrollable_Draw_Fn fn +) { + GUI_Scrollable* e = gui_alloc(g, sizeof *e); + e->el.type = gui_el_type_scrollable; + e->el.r = r; + e->ss = state; + e->draw = fn; +} + +void rect_cfit(Rect* r) { + r->x++; + r->y++; + r->w -= 2; + r->h -= 2; +} + +void draw_container(Renderer* r, const Rect* rect, int active) { + const Colour bg = make_colour(0xc3c3c3, 0xff); + Colour out1 = make_colour(0xffffff, 0xff); + Colour out2 = make_colour(0x000000, 0xff); + Rect t = *rect; + if (active) { + Colour t = out1; + out1 = out2; + out2 = t; + } + ren_rect(r, bg, rect); + t.h = 1; + ren_rect(r, out1, &t); + t.w = 1; + t.h = rect->h; + ren_rect(r, out1, &t); + t.h--; + t.x += rect->w - 1; + t.y++; + ren_rect(r, out2, &t); + t.y = rect->y + rect->h - 1; + t.x = rect->x + 1; + t.w = rect->w - 1; + t.h = 1; + ren_rect(r, out2, &t); +} + +void draw_btn(GUI* g, Renderer* r, const GUI_Btn* btn) { + const Colour txt = make_colour(0x000000, 0xff); + int tp[2]; + Rect rect = btn->el.r; + (void)g; + tp[0] = + rect.x + rect.w / 2 - + gui_text_width(btn->text, string_len(btn->text)) / 2; + tp[1] = + rect.y + rect.h / 2 - + gui_text_height() / 2; + if (btn->active) { + tp[0]++; + tp[1]++; + } + draw_container(r, &rect, btn->active); + rect_cfit(&rect); + ren_clip(r, &rect); + ren_text(r, txt, tp[0], tp[1], btn->text); + ren_clipr(r); +} + +void draw_scrollable( + GUI* g, + Renderer* r, + const GUI_Scrollable* s +) { + Rect rect = s->el.r; + draw_container(r, &s->el.r, 0); + rect_cfit(&rect); + ren_clip(r, &rect); + s->draw(g, r, &rect, s->ss); + ren_clipr(r); +} + +void gui_end(GUI* g, Renderer* r) { + GUI_El* el = g->first; + while (el) { + switch (el->type) { + case gui_el_type_btn: + draw_btn(g, r, (GUI_Btn*)el); + break; + case gui_el_type_scrollable: + draw_scrollable(g, r, (GUI_Scrollable*)el); + break; + } + el = el->next; + } +} diff --git a/gui.h b/gui.h new file mode 100644 index 0000000..50927f4 --- /dev/null +++ b/gui.h @@ -0,0 +1,70 @@ +#ifndef gui_h +#define gui_h + +#include "rect.h" + +struct App; +struct Arena; +struct GUI; +struct Renderer; + +typedef enum { + gui_el_type_btn, + gui_el_type_scrollable +} GUI_El_Type; + +typedef struct GUI_El { + GUI_El_Type type; + struct GUI_El* next; + Rect r; +} GUI_El; + +typedef struct { + GUI_El el; + char* text; + int hover, active; +} GUI_Btn; + +typedef struct { + int x, y; +} GUI_Scroll_State; + +typedef void (*GUI_Scrollable_Draw_Fn)( + struct GUI*, + struct Renderer*, + const Rect*, + const GUI_Scroll_State* +); + +typedef struct { + GUI_El el; + GUI_Scrollable_Draw_Fn draw; + GUI_Scroll_State* ss; +} GUI_Scrollable; + +typedef struct GUI { + const struct App* app; + struct Arena* a; + GUI_El* first, * prev; + int cursor[2], pad; +} GUI; + +int gui_text_width(const char* text, int len); +int gui_text_height(void); + +void gui_begin(GUI* g, const struct App* app, struct Arena* a); +void gui_end(GUI* g, struct Renderer* r); +Rect gui_viewport(GUI* g); +Rect gui_cut_left(Rect* a, int v); +Rect gui_cut_right(Rect* a, int v); +Rect gui_cut_down(Rect* a, int v); +Rect gui_cut_up(Rect* a, int v); +int gui_btn(GUI* g, Rect r, const char* text); +void gui_scrollable( + GUI* g, + Rect r, + GUI_Scroll_State* state, + GUI_Scrollable_Draw_Fn fn +); + +#endif diff --git a/map.c b/map.c new file mode 100644 index 0000000..3313f10 --- /dev/null +++ b/map.c @@ -0,0 +1,5 @@ +#include "map.h" + +int map_size(int w, int h) { + return sizeof(Map) + w * h * sizeof(Map_Tile); +} diff --git a/map.h b/map.h index 6b99d9a..fbd64f1 100644 --- a/map.h +++ b/map.h @@ -5,4 +5,8 @@ typedef struct Map { int w, h; } Map; +typedef unsigned Map_Tile; + +int map_size(int w, int h); + #endif -- cgit v1.2.3-54-g00ecf