summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--3de.c91
-rw-r--r--Makefile3
-rw-r--r--config.h5
-rw-r--r--editor.c29
-rw-r--r--editor.h13
-rw-r--r--gui.c198
-rw-r--r--gui.h70
-rw-r--r--map.c5
-rw-r--r--map.h4
9 files changed, 390 insertions, 28 deletions
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 <stdio.h>
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