summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorday <day@national.shitposting.agency>2026-03-16 16:25:49 +0100
committerday <day@national.shitposting.agency>2026-03-16 16:25:49 +0100
commit7f85c9fc75bd62ac09ea4457d3b17f85988fca66 (patch)
tree15248e42bfafc6bd19e50c9010b701057958ff3a
parent872c39b24ecf4063f785ff3e8b2f940acd8c2d59 (diff)
parent991352b0d2767e6bd1a46f554db4ac9d208c13ad (diff)
Merge remote-tracking branch 'origin/master' into obj
-rw-r--r--src/editor/editor.cpp12
-rw-r--r--src/editor/editor.h16
-rw-r--r--src/editor/editor_contextmenu.cpp35
-rw-r--r--src/editor/editor_infobox.cpp2
-rw-r--r--src/editor/editor_menubar.cpp46
-rw-r--r--src/editor/properties.cpp252
-rw-r--r--src/editor/properties.h160
-rw-r--r--src/editor/toolview.cpp20
-rw-r--r--src/game/world/map.cpp52
-rw-r--r--src/game/world/map.h87
-rw-r--r--src/gui/base.h5
-rw-r--r--src/util/allocator.h11
-rw-r--r--src/util/callback.h84
-rw-r--r--src/util/color.h4
-rw-r--r--src/util/config.h25
-rw-r--r--src/util/config/config.cpp13
-rw-r--r--src/util/config/serializers.cpp115
-rw-r--r--src/util/file.h4
-rw-r--r--src/util/input.h3
-rw-r--r--src/util/str_tokenizer.h140
-rw-r--r--src/util/string.h27
-rw-r--r--src/util/vector.h8
22 files changed, 744 insertions, 377 deletions
diff --git a/src/editor/editor.cpp b/src/editor/editor.cpp
index dee5080..ba61961 100644
--- a/src/editor/editor.cpp
+++ b/src/editor/editor.cpp
@@ -56,7 +56,6 @@ static U8 editor_clr_eq( const CLR& a, const CLR& b ) {
static U8 editor_vertex_eq( const MAP_VERTEX& a, const MAP_VERTEX& b ) {
return a.pos == b.pos
- && a.normal == b.normal
&& a.uv == b.uv
&& editor_clr_eq( a.clr, b.clr );
}
@@ -604,15 +603,15 @@ STAT editor_new_map( GAME_EDITOR* e, const char* mapname ) {
WORLD_MAP* m = new WORLD_MAP;
defer( map_free( e->game, m ) );
- strcpy( m->name, mapname );
- strcat( m->name, ".hmap" );
+ m->name = mapname;
+ m->name += ".hmap";
m->startpos = { 10.f, 10.f, 0.f };
m->props.push( { .clr = { 1.f, 1.f, 1.f, 1.f } } );
m->walls.push( {
+ .propid = 0,
.start = { 0 , 0, -40.f },
.end = { 10.f, 0, 80.f },
- .propid = 0
} );
CFG_SECTION* map_cfg = map_serialize( m );
@@ -641,11 +640,10 @@ STAT editor_save_map( GAME_EDITOR* e ) {
if( !serialized ) return STAT_ERR;
defer( cfg_free( serialized ) );
- char full_path[256];
- sprintf( full_path, "../assets/maps/%s", e->map->name );
+ STR full_path = { "../assets/maps/%s", e->map->name.data };
if( !OK( cfg_save( serialized, full_path ) ) ) {
- dlog( "failed to save map %s", full_path );
+ dlog( "failed to save map %s", full_path.data );
return STAT_ERR;
}
diff --git a/src/editor/editor.h b/src/editor/editor.h
index 828f2e4..33396df 100644
--- a/src/editor/editor.h
+++ b/src/editor/editor.h
@@ -66,7 +66,7 @@ enum EditorObjectType_t {
typedef void( *EDITOR_CONTEXTMENU_CALLBACK )( void* data );
struct EDITOR_CONTEXTMENU_ITEM;
-typedef U8( *EDITOR_CONTEXTMENU_ENABLED_CALLBACK )( const EDITOR_CONTEXTMENU_ITEM* item );
+typedef U8( *EDITOR_CONTEXTMENU_ENABLED_CALLBACK )( EDITOR_CONTEXTMENU_ITEM* item );
struct EDITOR_CONTEXTMENU_ITEM {
char text[64]{};
@@ -209,9 +209,6 @@ extern void editor_create_map_view( GAME_EDITOR* e );
extern void editor_update_properties_column( GAME_EDITOR* e );
extern const char* editor_tool_name();
extern void editor_set_view_mode( I32 mode );
-extern void editor_show_contextmenu( I32 x, I32 y, LIST<EDITOR_CONTEXTMENU_ITEM>* items, const char* title = 0 );
-extern void editor_hide_contextmenu();
-extern U8 editor_contextmenu_open();
extern void editor_undo_clear( GAME_EDITOR* e );
extern void editor_undo_record_create_walls( GAME_EDITOR* e, I32 start_idx, I32 count );
extern void editor_undo_record_create_poly( GAME_EDITOR* e, I32 start_idx );
@@ -220,6 +217,17 @@ extern void editor_undo_record_create_entity( GAME_EDITOR* e, I32 start_idx );
extern U8 editor_undo( GAME_EDITOR* e );
extern U8 editor_redo( GAME_EDITOR* e );
+extern void editor_show_contextmenu( I32 x, I32 y, LIST<EDITOR_CONTEXTMENU_ITEM>* items, const char* title = 0 );
+extern void editor_hide_contextmenu();
+extern U8 editor_contextmenu_open();
+extern void editor_contextmenu_set_item(
+ EDITOR_CONTEXTMENU_ITEM* item,
+ const char* text,
+ EDITOR_CONTEXTMENU_CALLBACK cb = 0,
+ void* data = 0,
+ EDITOR_CONTEXTMENU_ENABLED_CALLBACK enabled_cb = 0
+);
+
struct GUI_EDITORWINDOW : GUI_WINDOW {};
struct GUI_EDITOR_3DVIEW : GUI_VIEW {
U8 heldoutbounds;
diff --git a/src/editor/editor_contextmenu.cpp b/src/editor/editor_contextmenu.cpp
index 2b0bb1f..4f9dbe6 100644
--- a/src/editor/editor_contextmenu.cpp
+++ b/src/editor/editor_contextmenu.cpp
@@ -1,6 +1,6 @@
#include "editor_gui_internal.h"
-static U8 editor_contextmenu_item_enabled( const EDITOR_CONTEXTMENU_ITEM* item ) {
+U8 editor_contextmenu_item_enabled( EDITOR_CONTEXTMENU_ITEM* item ) {
if( !item )
return 0;
@@ -10,15 +10,15 @@ static U8 editor_contextmenu_item_enabled( const EDITOR_CONTEXTMENU_ITEM* item )
return item->enabled;
}
-static I32 editor_contextmenu_title_h( const GUI_EDITOR_CONTEXTMENU* menu ) {
+I32 editor_contextmenu_title_h( GUI_EDITOR_CONTEXTMENU* menu ) {
return ( menu && menu->title[0] ) ? 18 : 0;
}
-static I32 editor_contextmenu_row_h() {
+I32 editor_contextmenu_row_h() {
return 20;
}
-static I32 editor_contextmenu_width( LIST<EDITOR_CONTEXTMENU_ITEM>* items, const char* title ) {
+I32 editor_contextmenu_width( LIST<EDITOR_CONTEXTMENU_ITEM>* items, const char* title ) {
I32 width = EDITOR_TOOLBAR_DROPDOWN_W;
if( title && title[0] ) {
I32 text_w = 0;
@@ -38,7 +38,7 @@ static I32 editor_contextmenu_width( LIST<EDITOR_CONTEXTMENU_ITEM>* items, const
return width;
}
-static I32 editor_contextmenu_height( LIST<EDITOR_CONTEXTMENU_ITEM>* items, const char* title ) {
+I32 editor_contextmenu_height( LIST<EDITOR_CONTEXTMENU_ITEM>* items, const char* title ) {
I32 height = 4 + editor_contextmenu_row_h() * ( items ? (I32)items->size : 0 );
if( title && title[0] )
height += 18 + 1;
@@ -52,7 +52,7 @@ static I32 editor_contextmenu_items_y( GUI_EDITOR_CONTEXTMENU* menu ) {
return y;
}
-static I32 editor_contextmenu_hit_test( GUI_EDITOR_CONTEXTMENU* menu, I32 mx, I32 my ) {
+I32 editor_contextmenu_hit_test( GUI_EDITOR_CONTEXTMENU* menu, I32 mx, I32 my ) {
if( !menu || !menu->items )
return -1;
@@ -72,7 +72,7 @@ static I32 editor_contextmenu_hit_test( GUI_EDITOR_CONTEXTMENU* menu, I32 mx, I3
return idx;
}
-static void gui_editor_contextmenu_draw_fn( void* ptr ) {
+void gui_editor_contextmenu_draw_fn( void* ptr ) {
GUI_EDITOR_CONTEXTMENU* menu = (GUI_EDITOR_CONTEXTMENU*)ptr;
if( !menu || !menu->items || !menu->items->size )
return;
@@ -128,7 +128,7 @@ static void gui_editor_contextmenu_draw_fn( void* ptr ) {
}
}
-static void gui_editor_contextmenu_input_fn( void* ptr ) {
+void gui_editor_contextmenu_input_fn( void* ptr ) {
GUI_EDITOR_CONTEXTMENU* menu = (GUI_EDITOR_CONTEXTMENU*)ptr;
if( !menu || !menu->items || !menu->items->size )
return;
@@ -199,6 +199,25 @@ U8 editor_contextmenu_open() {
return editor && editor->gui.contextmenu && editor->gui.contextmenu->enabled;
}
+
+void editor_contextmenu_set_item(
+ EDITOR_CONTEXTMENU_ITEM* item,
+ const char* text,
+ EDITOR_CONTEXTMENU_CALLBACK cb,
+ void* data,
+ EDITOR_CONTEXTMENU_ENABLED_CALLBACK enabled_cb
+) {
+ if( !item )
+ return;
+
+ item->items.clear();
+ snprintf( item->text, sizeof( item->text ), "%s", text ? text : "" );
+ item->cb = cb;
+ item->data = data;
+ item->enabled = 1;
+ item->enabled_cb = enabled_cb;
+}
+
void editor_show_contextmenu( I32 x, I32 y, LIST<EDITOR_CONTEXTMENU_ITEM>* items, const char* title ) {
editor_hide_contextmenu();
if( !editor || !editor->wnd || !items || !items->size )
diff --git a/src/editor/editor_infobox.cpp b/src/editor/editor_infobox.cpp
index 9f9060d..479b59d 100644
--- a/src/editor/editor_infobox.cpp
+++ b/src/editor/editor_infobox.cpp
@@ -100,7 +100,7 @@ static void gui_editor_infobox_draw_assets( GUI_EDITOR_INFOBOX* box, I32 panel_x
I32 text_x = tx + EDITOR_ASSETS_THUMB + 8;
CLR txt = ui_clr.txt;
if( map_entry ) {
- gui_draw_str( text_x, row_y + 7, ALIGN_L, FNT_JPN12, txt, "[map] -> %s", map->name );
+ gui_draw_str( text_x, row_y + 7, ALIGN_L, FNT_JPN12, txt, "[map] -> %s", map->name.data );
} else if( p->tex ) {
gui_draw_str( text_x, row_y + 7, ALIGN_L, FNT_JPN12, txt, "[%d] -> %s", idx - 1, p->tex->name );
} else {
diff --git a/src/editor/editor_menubar.cpp b/src/editor/editor_menubar.cpp
index b89d1c6..cef2650 100644
--- a/src/editor/editor_menubar.cpp
+++ b/src/editor/editor_menubar.cpp
@@ -66,56 +66,38 @@ void editor_raise_header_toolbar( GAME_EDITOR* e ) {
parent->children.push( bar );
}
-static void editor_contextmenu_set_item(
- EDITOR_CONTEXTMENU_ITEM* item,
- const char* text,
- EDITOR_CONTEXTMENU_CALLBACK cb = 0,
- void* data = 0,
- EDITOR_CONTEXTMENU_ENABLED_CALLBACK enabled_cb = 0
-) {
- if( !item )
- return;
-
- item->items.clear();
- snprintf( item->text, sizeof( item->text ), "%s", text ? text : "" );
- item->cb = cb;
- item->data = data;
- item->enabled = 1;
- item->enabled_cb = enabled_cb;
-}
-
-static void editor_contextmenu_save_cb( void* ) {
+void editor_contextmenu_save_cb( void* ) {
if( editor )
editor_save_map( editor );
}
-static void editor_contextmenu_undo_cb( void* ) {
+void editor_contextmenu_undo_cb( void* ) {
if( editor )
editor_undo( editor );
}
-static void editor_contextmenu_redo_cb( void* ) {
+void editor_contextmenu_redo_cb( void* ) {
if( editor )
editor_redo( editor );
}
-static void editor_contextmenu_set_view_mode_cb( void* data ) {
+void editor_contextmenu_set_view_mode_cb( void* data ) {
editor_set_view_mode( (I32)(I64)data );
}
-static void editor_contextmenu_set_tool_cb( void* data ) {
+void editor_contextmenu_set_tool_cb( void* data ) {
editor_settool( (U8)(I64)data );
}
-static U8 editor_contextmenu_undo_enabled( const EDITOR_CONTEXTMENU_ITEM* ) {
+U8 editor_contextmenu_undo_enabled( EDITOR_CONTEXTMENU_ITEM* ) {
return editor && editor->undo_actions.size > 0;
}
-static U8 editor_contextmenu_redo_enabled( const EDITOR_CONTEXTMENU_ITEM* ) {
+U8 editor_contextmenu_redo_enabled( EDITOR_CONTEXTMENU_ITEM* ) {
return editor && editor->redo_actions.size > 0;
}
-static void editor_toolbar_init_entries( GUI_EDITOR_TOOLBAR* bar ) {
+void editor_toolbar_init_entries( GUI_EDITOR_TOOLBAR* bar ) {
if( !bar )
return;
@@ -146,7 +128,7 @@ static void editor_toolbar_init_entries( GUI_EDITOR_TOOLBAR* bar ) {
editor_contextmenu_set_item( &bar->entries[3].items[4], "object", editor_contextmenu_set_tool_cb, (void*)(I64)EDITOR_TOOL_OBJECT );
}
-static I32 editor_toolbar_root_width( const EDITOR_CONTEXTMENU_ITEM* entry ) {
+I32 editor_toolbar_root_width( const EDITOR_CONTEXTMENU_ITEM* entry ) {
if( !entry )
return 44;
@@ -155,7 +137,7 @@ static I32 editor_toolbar_root_width( const EDITOR_CONTEXTMENU_ITEM* entry ) {
return max( 44, text_w + 16 );
}
-static void editor_toolbar_root_rect( GUI_EDITOR_TOOLBAR* bar, I32 idx, I32* rx, I32* ry, I32* rw, I32* rh ) {
+void editor_toolbar_root_rect( GUI_EDITOR_TOOLBAR* bar, I32 idx, I32* rx, I32* ry, I32* rw, I32* rh ) {
I32 x = gui_relx( bar );
I32 y = gui_rely( bar );
I32 cx = x + 8;
@@ -172,11 +154,11 @@ struct EDITOR_TOOLBAR_HIT {
I32 root{-1};
};
-static U8 editor_toolbar_pt_in_rect( I32 mx, I32 my, I32 x, I32 y, I32 w, I32 h ) {
+U8 editor_toolbar_pt_in_rect( I32 mx, I32 my, I32 x, I32 y, I32 w, I32 h ) {
return mx >= x && mx < x + w && my >= y && my < y + h;
}
-static EDITOR_TOOLBAR_HIT editor_toolbar_hit_test( GUI_EDITOR_TOOLBAR* bar, I32 mx, I32 my ) {
+EDITOR_TOOLBAR_HIT editor_toolbar_hit_test( GUI_EDITOR_TOOLBAR* bar, I32 mx, I32 my ) {
EDITOR_TOOLBAR_HIT hit{};
for( I32 i = 0; i < (I32)bar->entries.size; ++i ) {
I32 x = 0, y = 0, w = 0, h = 0;
@@ -190,7 +172,7 @@ static EDITOR_TOOLBAR_HIT editor_toolbar_hit_test( GUI_EDITOR_TOOLBAR* bar, I32
return hit;
}
-static void gui_editor_toolbar_draw_fn( void* ptr ) {
+void gui_editor_toolbar_draw_fn( void* ptr ) {
GUI_EDITOR_TOOLBAR* bar = (GUI_EDITOR_TOOLBAR*)ptr;
I32 x = gui_relx( bar );
I32 y = gui_rely( bar );
@@ -229,7 +211,7 @@ static void gui_editor_toolbar_draw_fn( void* ptr ) {
}
}
-static void gui_editor_toolbar_input_fn( void* ptr ) {
+void gui_editor_toolbar_input_fn( void* ptr ) {
GUI_EDITOR_TOOLBAR* bar = (GUI_EDITOR_TOOLBAR*)ptr;
I32 mx = 0, my = 0;
gui_cursor_pos( &mx, &my );
diff --git a/src/editor/properties.cpp b/src/editor/properties.cpp
index ac21bb0..c9eb991 100644
--- a/src/editor/properties.cpp
+++ b/src/editor/properties.cpp
@@ -1,3 +1,4 @@
+#include "properties.h"
#include "editor.h"
#include "../render/gl.h"
#include "../game/assets.h"
@@ -8,36 +9,36 @@ const I32 PROPVIEW_PAD = 10;
const I32 PROPVIEW_ACTION_BTN_W = 20;
const I32 PROPVIEW_ACTION_BTN_GAP = 5;
-static I32 propview_col_left() {
+I32 propview_col_left() {
return PROPVIEW_PAD;
}
-static I32 propview_col_right( GUI_EDITOR_PROPVIEW* view ) {
+I32 propview_col_right( GUI_EDITOR_PROPVIEW* view ) {
if( !view )
return PROPVIEW_PAD;
return max( PROPVIEW_PAD, view->w - PROPVIEW_PAD );
}
-static I32 propview_input_width( GUI_EDITOR_PROPVIEW* view ) {
+I32 propview_input_width( GUI_EDITOR_PROPVIEW* view ) {
return max( 120, propview_col_right( view ) - propview_col_left() );
}
-static I32 propview_sub_input_x( I32 x ) {
+I32 propview_sub_input_x( I32 x ) {
return x + 10;
}
-static I32 propview_sub_input_width( GUI_EDITOR_PROPVIEW* view, I32 x ) {
- I32 right = propview_col_right( view );
- return max( 100, right - propview_sub_input_x( x ) );
-}
+// I32 propview_sub_input_width( GUI_EDITOR_PROPVIEW* view, I32 x ) {
+// I32 right = propview_col_right( view );
+// return max( 100, right - propview_sub_input_x( x ) );
+// }
-static I32 propview_action_x( GUI_EDITOR_PROPVIEW* view ) {
+I32 propview_action_x( GUI_EDITOR_PROPVIEW* view ) {
I32 right = propview_col_right( view );
return max( propview_col_left(), right - PROPVIEW_ACTION_BTN_W );
}
-static I32 propview_action2_x( GUI_EDITOR_PROPVIEW* view ) {
+I32 propview_action2_x( GUI_EDITOR_PROPVIEW* view ) {
return max(
propview_col_left(),
propview_action_x( view ) - PROPVIEW_ACTION_BTN_W - PROPVIEW_ACTION_BTN_GAP
@@ -66,122 +67,137 @@ void gui_editor_propview_select( GUI_EDITOR_PROPVIEW* view, void* what, U8 selty
gui_editor_propview_update( view );
}
-// returns the subentry height
-I32 gui_editor_propview_surfprops_subentry(
- GUI_EDITOR_PROPVIEW* view,
- I32 x,
- I32 y,
- I32* propid,
- SURF_PROPS* props
-) {
- I32 oldy = y;
- I32 space = 20;
- I32 action_x = propview_action_x( view );
+
+
+void gui_editor_propview_create_eobj_props( GUI_EDITOR_PROPVIEW* view, EOBJECT* e, I32* x, I32* y, I32 w );
+void gui_editor_propview_create_eobj_prop( GUI_EDITOR_PROPVIEW* view, EDITOR_PROP* prop, I32* x, I32* y, I32 w, I32 space ) {
+ F32 action_x = propview_action_x( view );
I32 action2_x = propview_action2_x( view );
- gui_label( x, y, "prop id: %d", *propid );
- GUI_BUTTON* newprop = gui_button( action2_x, y, 20, 20, "+", pfn( void* ptr ) {
- GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
- SURF_PROPS props;
- props.tex = 0;
- props.clr = { 1.f, 1.f, 1.f, 1.f };
-
- editor->map->props.push( props );
- *(U32*)(btn->extra) = editor->map->props.size - 1;
- // Keep the newest prop visible in the assets panel (pixel scroll).
- editor->gui.assets_scroll = ( editor->map->props.size + 1 ) * 28;
- gui_editor_propview_update( editor->gui.props );
- } );
- newprop->extra = propid;
- GUI_BUTTON* goprop = gui_button( action_x, y, 20, 20, "\x1A", pfn( void* ptr ) {
- GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
- gui_editor_propview_select( editor->gui.props, btn->extra, EDITOR_SELECT_SURFPROPS );
- } );
- goprop->extra = props;
+ const char* n = prop->displayname;
+ F32 min = prop->min;
+ F32 max = prop->max;
+ F32 step;
+
+ if( prop->step ) step = prop->step;
+ else step = editor->propgrid ? editor->grid : 0.25f;
+
+ switch( prop->type ) {
+ case EPROP_F32: gui_floatinput( *x, *y, w, n, (F32*)eprop_ptr( prop ), min, max, step ); *y += (space+18); break;
+ case EPROP_VEC2: gui_vectorinput( *x, *y, w, n, (F32*)eprop_ptr( prop ), 2, min, max, step, "xy", "%.03f" ); *y += (space+18); break;
+ case EPROP_VEC3: gui_vectorinput( *x, *y, w, n, (F32*)eprop_ptr( prop ), 3, min, max, step, "xyz", "%.02f" ); *y += (space+18); break;
+ case EPROP_VEC4: gui_vectorinput( *x, *y, w, n, (F32*)eprop_ptr( prop ), 3, min, max, step, "xyzw", "%0.02f" ); *y += (space+18); break;
+ case EPROP_CLR: gui_colorinput( *x, *y, w, n, (CLR*)eprop_ptr( prop ) ); *y += (space+18); break;
+ case EPROP_MAPPROP: {
+ MAP_PROPREF* ref = (MAP_PROPREF*)eprop_ptr( prop );
+ SURF_PROPS* props = map_get_props( editor->map, *ref );
+ gui_label( *x, *y, "prop id: %d", *ref );
+
+ GUI_BUTTON* newprop = gui_button( action2_x, *y, 20, 20, "+", pfn( void* ptr ) {
+ GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
+ SURF_PROPS props{ .tex = 0, .clr = CLR::WHITE() };
+ editor->map->props.push( props );
+
+ ((MAP_PROPREF*)btn->extra)->id = editor->map->props.size - 1;
+ editor->gui.assets_scroll = ( editor->map->props.size + 1 ) * 28;
+ gui_editor_propview_update( editor->gui.props );
+ } ); newprop->extra = ref;
+
+ GUI_BUTTON* goprop = gui_button( action_x, *y, 20, 20, "\x1A", pfn( void* ptr ) {
+ GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
+ gui_editor_propview_select( editor->gui.props, btn->extra, EDITOR_SELECT_SURFPROPS );
+ } ); goprop->extra = props; *y += space;
+
+ *x += 10; gui_editor_propview_create_eobj_props( view, props, x, y, w - 10 ); *x -= 10;
+ } break;
+ case EPROP_TEXTURE: {
+ GL_TEX2D** tex = (GL_TEX2D**)eprop_ptr( prop );
+ if( *tex ) gui_label( *x, *y, "%s: %s", n, (*tex)->name );
+ else gui_label( *x, *y, "%s: none", n );
+ GUI_BUTTON* btn = gui_button( action_x, *y, 20, 20, "\x1A", pfn( void* ptr ) {
+ GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
+ GL_TEX2D** ptex = (GL_TEX2D**)btn->extra;
+ GUI_EDITOR_TEXTUREPICKER* picker = gui_editor_texturepicker( 200, 100, 400, 400, ptex );
+ picker->cb = pfn( void* ) { gui_editor_propview_update( editor->gui.props ); };
+ } ); btn->extra = tex; *y += space;
+ } break;
+ case EPROP_VERTEX_LIST: {
+ LIST<MAP_VERTEX>* list = ( LIST<MAP_VERTEX>* )eprop_ptr( prop );
+ gui_label( *x, *y, "%s : %d", n, list->size ); *y += space;
+ for( U32 i = 0; i < list->size; ++i ) {
+ MAP_VERTEX* v = &list->data[i];
+ gui_label( (*x) + 10, *y, "[%d] -> [%s]", i, to_str( v->pos ).data );
+ GUI_BUTTON* btn = gui_button( action_x, *y, 20, 20, "\x1A", pfn( void* ptr ) {
+ GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
+ gui_editor_propview_select( editor->gui.props, btn->extra, EDITOR_SELECT_PVERTEX );
+ } ); btn->extra = v; *y += space;
+ }
+ } break;
+ default: break;
+ }
+}
- y += space;
+void gui_editor_propview_create_eobj_prop_ro( GUI_EDITOR_PROPVIEW* view, EDITOR_PROP* prop, I32* x, I32* y, I32 w, I32 space ) {
+ STR str = prop->displayname;
+ str += " : [";
+ void* ptr = eprop_ptr( prop );
+
+ switch( prop->type ) {
+ case EPROP_F32: str += to_str( *(F32*)ptr ); break;
+ case EPROP_VEC2: str += to_str( *(VEC2*)ptr ); break;
+ case EPROP_VEC3: str += to_str( *(VEC3*)ptr ); break;
+ case EPROP_VEC4: str += to_str( *(VEC4*)ptr ); break;
+ case EPROP_CLR: str += to_str( *(CLR*)ptr ); break;
+ case EPROP_U32: str += to_str( *(U32*)ptr ); break;
+ case EPROP_U64: str += to_str( *(U64*)ptr ); break;
+ case EPROP_I32: str += to_str( *(I32*)ptr ); break;
+ case EPROP_I64: str += to_str( *(I64*)ptr ); break;
+ case EPROP_STRING: str += to_str( *(CLR*)ptr ); break;
+ }
- if( props->tex )
- gui_label( x + 10, y, "texture: %s", props->tex->name );
- else
- gui_label( x + 10, y, "texture: none" );
+ str += "]";
+ gui_label( *x, *y, str.data );
+ *y += space;
+}
- GUI_BUTTON* btn = gui_button( action_x, y, 20, 20, "\x1A", pfn( void* ptr ) {
- GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
- GL_TEX2D** ptex = (GL_TEX2D**)btn->extra;
- GUI_EDITOR_TEXTUREPICKER* picker = gui_editor_texturepicker( 200, 100, 400, 400, ptex );
- picker->cb = pfn( void* ) { gui_editor_propview_update( editor->gui.props ); };
- } );
+void gui_editor_propview_create_eobj_props( GUI_EDITOR_PROPVIEW* view, EOBJECT* e, I32* x, I32* y, I32 w ) {
+ I32 space = 20;
- btn->extra = &props->tex;
- y += space;
- gui_colorinput(
- propview_sub_input_x( x ),
- y,
- propview_sub_input_width( view, x ),
- "color",
- &props->clr
- ); y += (space+18);
-
- return y - oldy;
+ for( auto& it : e->eprops ) {
+ EDITOR_PROP* eprop = eprop_from_ref( e, it );
+ if( eprop->readonly )
+ gui_editor_propview_create_eobj_prop_ro( view, eprop, x, y, w, space );
+ else
+ gui_editor_propview_create_eobj_prop( view, eprop, x, y, w, space );
+ }
}
void gui_editor_propview_create_wallprops( GUI_EDITOR_PROPVIEW* view ) {
MAP_WALL* s = (MAP_WALL*)view->curselect;
WORLD_MAP* m = editor->map;
- SURF_PROPS* props = wall_get_props( m, s );
I32 x = 10, y = 10;
I32 space = 20;
- F32 step = editor->propgrid? editor->grid : 0.25f;
I32 wall_idx = m->walls.idx_where( fn( MAP_WALL* ms ) {
return s == ms;
} );
gui_label( x, y, "idx: %d", wall_idx ); y += space;
- y += gui_editor_propview_surfprops_subentry( view, x, y, &s->propid, props );
-
- GUI_VECTORINPUT* posinput;
- posinput = gui_vectorinput( x, y, propview_input_width( view ), "start", (F32*)&s->start, 3, -INFINITY, INFINITY, step ); y += (space+18);
- posinput->cb = pfn( void* ) { map_check_bounds( editor->map ); };
- posinput = gui_vectorinput( x, y, propview_input_width( view ), "end", (F32*)&s->end, 3, -INFINITY, INFINITY, step ); y += (space+18);
- posinput->cb = pfn( void* ) { map_check_bounds( editor->map ); };
+ return gui_editor_propview_create_eobj_props( view, s, &x, &y, propview_input_width( view ) );
}
void gui_editor_propview_create_polyprops( GUI_EDITOR_PROPVIEW* view ) {
MAP_POLYGON* p = (MAP_POLYGON*)view->curselect;
WORLD_MAP* m = editor->map;
- SURF_PROPS* props = polygon_get_props( m, p );
-
I32 x = 10, y = 10;
I32 space = 20;
I32 poly_idx = m->polygons.idx_where( fn( MAP_POLYGON* mp ) {
return p == mp;
} );
- I32 action_x = propview_action_x( view );
gui_label( x, y, "idx: %d", poly_idx ); y += space;
- y += gui_editor_propview_surfprops_subentry( view, x, y, &p->propid, props );
-
- gui_label( x, y, "vertices: %d", p->vertices.size ); y += space;
- I32 idx = 0;
- p->vertices.each( fn( MAP_VERTEX* v ) {
- gui_label( x + 10, y, "[%d] -> { %.02f, %.02f, %.02f }", idx, v->pos.x, v->pos.y, v->pos.z );
- GUI_BUTTON* btn = gui_button( action_x, y - 2, 20, 20, "\x1A", pfn( void* ptr ) {
- GUI_EDITOR_PROPVIEW* view = editor->gui.props;
- GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
- MAP_POLYGON* p = (MAP_POLYGON*)view->curselect;
- I64 idx = (I64)btn->extra;
- if( p ) // p100
- gui_editor_propview_select( view, &p->vertices[idx], EDITOR_SELECT_PVERTEX );
- } );
-
- y += space;
- btn->extra = (void*)( (I64)idx++ );
- } );
- gui_label( x, y, "mins: { %1.02f, %1.02f, %1.02f }", p->mins.x, p->mins.y, p->mins.z ); y += space;
- gui_label( x, y, "maxs: { %1.02f, %1.02f, %1.02f }", p->maxs.x, p->maxs.y, p->maxs.z ); y += space;
+ return gui_editor_propview_create_eobj_props( view, p, &x, &y, propview_input_width( view ) );
}
void gui_editor_propview_create_mapprops( GUI_EDITOR_PROPVIEW* view ) {
@@ -192,7 +208,7 @@ void gui_editor_propview_create_mapprops( GUI_EDITOR_PROPVIEW* view ) {
F32 step = editor->propgrid? editor->grid : 0.25f;
- gui_label( x, y, "name: %s", m->name ); y += space;
+ gui_label( x, y, "name: %s", m->name.data ); y += space;
gui_label( x, y, "walls: %d", m->walls.size ); y += space;
gui_label( x, y, "polygons: %d", m->polygons.size ); y += space;
gui_label( x, y, "props: %d", m->props.size ); y += space;
@@ -232,12 +248,10 @@ void gui_editor_propview_create_pvertexprops( GUI_EDITOR_PROPVIEW* view ) {
return vert_idx != -1;
} );
- F32 step = editor->propgrid? editor->grid : 0.25f;
I32 action_x = propview_action_x( view );
gui_label( x, y, "idx: %d", vert_idx ); y += space;
gui_label( x, y, "polygon idx: %d", poly_idx );
-
gui_button( action_x, y - 2, 20, 20, "\x1A", pfn( void* ) {
GUI_EDITOR_PROPVIEW* view = editor->gui.props;
MAP_VERTEX* v = (MAP_VERTEX*)view->curselect;
@@ -249,15 +263,12 @@ void gui_editor_propview_create_pvertexprops( GUI_EDITOR_PROPVIEW* view ) {
if( polygon )
gui_editor_propview_select( view, polygon, EDITOR_SELECT_POLY );
- } );
- y += space;
+ } ); y += space;
- GUI_VECTORINPUT* posinput = gui_vectorinput( x, y, propview_input_width( view ), "position", (F32*)&v->pos, 3, -INFINITY, INFINITY, step ); y += (space+18);
- posinput->cb = pfn( void* ptr ) { map_check_bounds( editor->map ); };
- gui_vectorinput( x, y, propview_input_width( view ), "texture coordinates", (F32*)&v->uv, 2, 0.f, 1.f, 0.005f, "xy", "%.03f" ); y += (space+18);
- gui_colorinput( x, y, propview_input_width( view ), "color", &v->clr ); y += (space+18);
+ return gui_editor_propview_create_eobj_props( view, v, &x, &y, propview_input_width( view ) );
}
+
void gui_editor_propview_create_spriteprops( GUI_EDITOR_PROPVIEW* view ) {
MAP_SPRITE* s = (MAP_SPRITE*)view->curselect;
WORLD_MAP* m = editor->map;
@@ -268,27 +279,9 @@ void gui_editor_propview_create_spriteprops( GUI_EDITOR_PROPVIEW* view ) {
I32 sprite_idx = m->sprites.idx_where( fn( MAP_SPRITE* ms ) {
return ms == s;
} );
- I32 action_x = propview_action_x( view );
-
- F32 step = editor->propgrid? editor->grid : 0.25f;
gui_label( x, y, "idx: %d", sprite_idx ); y += space;
- gui_vectorinput( x, y, propview_input_width( view ), "position", (F32*)&s->pos, 3, -INFINITY, INFINITY, step ); y += (space+18);
- gui_vectorinput( x, y, propview_input_width( view ), "size", (F32*)&s->size, 2, 1.f, INFINITY, 1.f, "wh" ); y += (space+18);
- gui_colorinput( x, y, propview_input_width( view ), "color", &s->clr ); y += (space+18);
- if( s->tex )
- gui_label( x, y, "texture: %s", s->tex->name );
- else
- gui_label( x, y, "texture: none" );
-
- GUI_BUTTON* btn = gui_button( action_x, y, 20, 20, "\x1A", pfn( void* ptr ) {
- GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
- GL_TEX2D** ptex = (GL_TEX2D**)btn->extra;
- GUI_EDITOR_TEXTUREPICKER* picker = gui_editor_texturepicker( 200, 100, 400, 400, ptex );
- picker->cb = pfn( void* ) { gui_editor_propview_update( editor->gui.props ); };
- } );
- btn->extra = &s->tex;
- y += space;
+ return gui_editor_propview_create_eobj_props( view, s, &x, &y, propview_input_width( view ) );
}
void gui_editor_propview_create_surfprops( GUI_EDITOR_PROPVIEW* view ) {
@@ -301,22 +294,9 @@ void gui_editor_propview_create_surfprops( GUI_EDITOR_PROPVIEW* view ) {
I32 i = m->props.idx_where( fn( SURF_PROPS* mp ) { return mp == p; } );
if( i == -1 )
return;
- I32 action_x = propview_action_x( view );
gui_label( x, y, "prop id: %d", i ); y += space;
- if( p->tex )
- gui_label( x, y, "texture: %s", assets_abspath( p->tex->name ) );
- else
- gui_label( x, y, "texture: none" );
- GUI_BUTTON* btn = gui_button( action_x, y, 20, 20, "\x1A", pfn( void* ptr ) {
- GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
- GL_TEX2D** ptex = (GL_TEX2D**)btn->extra;
- GUI_EDITOR_TEXTUREPICKER* picker = gui_editor_texturepicker( 200, 100, 400, 400, ptex );
- picker->cb = pfn( void* ) { gui_editor_propview_update( editor->gui.props ); };
- } );
- btn->extra = &p->tex;
- y += space;
- gui_colorinput( x, y, propview_input_width( view ), "color", &p->clr ); y += (space+18);
+ return gui_editor_propview_create_eobj_props( view, p, &x, &y, propview_input_width( view ) );
}
void gui_editor_propview_create_entprops( GUI_EDITOR_PROPVIEW* view ) {
diff --git a/src/editor/properties.h b/src/editor/properties.h
index 34ac765..d663a6b 100644
--- a/src/editor/properties.h
+++ b/src/editor/properties.h
@@ -1,7 +1,6 @@
#pragma once
#include "../gamedef.h"
-#include <concepts>
#if IS_EDITOR
#include <math.h>
@@ -9,17 +8,46 @@
#define EPROP( _type, name, value, display ) \
_type name = value; \
- EDITOR_PROP name##_prop{ .pdata = &name, .type = eprop_type<_type>(), .displayname = display, .parent = this };
+ EDITOR_PROP name##_prop{ &name, eprop_type<_type>(), display, this, 0 }
+
+#define EPROP_RO( _type, name, value, display ) \
+ _type name = value; \
+ EDITOR_PROP name##_prop{ &name, eprop_type<_type>(), display, this, 1 }
#define EPROP_RANGED( _type, name, value, display, _min, _max ) \
- _type name{ value }; \
- EDITOR_PROP{ \
- .pdata = &name, \
- .type = eprop_type<_type>(), \
- .displayname = display, \
- .parent = this, \
- .min = _min, \
- .max = _max \
+ _type name = value; \
+ EDITOR_PROP name##_prop{ \
+ &name, \
+ eprop_type<_type>(), \
+ display, \
+ this, \
+ _min, \
+ _max, \
+ 0 \
+ }
+
+#define EPROP_STEP( _type, name, value, display, step ) \
+ _type name = value; \
+ EDITOR_PROP name##_prop{ \
+ &name, \
+ eprop_type<_type>(), \
+ display, \
+ step, \
+ this, \
+ 0 \
+ }
+
+#define EPROP_RANGED_STEP( _type, name, value, display, min, max, step ) \
+ _type name = value; \
+ EDITOR_PROP name##_prop{ \
+ &name, \
+ eprop_type<_type>(), \
+ display, \
+ step, \
+ this, \
+ min, \
+ max, \
+ 0 \
}
enum EditorPropType_t {
@@ -34,15 +62,27 @@ enum EditorPropType_t {
EPROP_I64,
EPROP_F32,
EPROP_F64,
+ EPROP_VEC2,
+ EPROP_VEC3,
+ EPROP_VEC4,
+ EPROP_CLR,
+ EPROP_MAPPROP,
EPROP_STRING,
EPROP_OBJ,
EPROP_LIST,
+ EPROP_TEXTURE,
EPROP_TEXTURE_LIST,
+ EPROP_VERTEX,
+ EPROP_VERTEX_LIST
+};
+
+struct EPROP_ENTRY {
+ U64 offset;
};
// editor map object
struct EOBJECT {
- LIST<struct EDITOR_PROP*> eprops{};
+ LIST<EPROP_ENTRY> eprops{};
};
template <typename T>
@@ -50,13 +90,89 @@ concept __eobject_base = __is_base_of(EOBJECT, T);
// editor object property
struct EDITOR_PROP {
- void* pdata;
+ EDITOR_PROP( void* _pdata, U8 _type, STR _displayname, struct EOBJECT* _parent, U8 _readonly = 0 ) {
+ type = _type;
+ displayname = _displayname;
+ min = -INFINITY;
+ max = INFINITY;
+ step = 0;
+ readonly = _readonly;
+
+ U64 _this = (U64)this;
+ U64 pdata = (U64)_pdata;
+ U64 parent = (U64)_parent;
+ U64 offset = _this - parent;
+
+ _parent->eprops.push( { offset } );
+
+ offset = _this - pdata;
+ dataoff = offset;
+ }
+
+ EDITOR_PROP( void* _pdata, U8 _type, STR _displayname, F32 _step, struct EOBJECT* _parent, U8 _readonly = 0 ) {
+ type = _type;
+ displayname = _displayname;
+ min = -INFINITY;
+ max = INFINITY;
+ step = _step;
+ readonly = _readonly;
+
+ U64 _this = (U64)this;
+ U64 pdata = (U64)_pdata;
+ U64 parent = (U64)_parent;
+ U64 offset = _this - parent;
+
+ _parent->eprops.push( { offset } );
+
+ offset = _this - pdata;
+ dataoff = offset;
+ }
+
+ EDITOR_PROP( void* _pdata, U8 _type, STR _displayname, struct EOBJECT* _parent, F32 _min, F32 _max, U8 _readonly = 0 ) {
+ type = _type;
+ displayname = _displayname;
+ min = _min;
+ max = _max;
+ step = 0;
+ readonly = _readonly;
+
+ U64 _this = (U64)this;
+ U64 pdata = (U64)_pdata;
+ U64 parent = (U64)_parent;
+ U64 offset = _this - parent;
+
+ _parent->eprops.push( { offset } );
+
+ offset = _this - pdata;
+ dataoff = offset;
+ }
+
+ EDITOR_PROP( void* _pdata, U8 _type, STR _displayname, F32 _step, struct EOBJECT* _parent, F32 _min, F32 _max, U8 _readonly = 0 ) {
+ type = _type;
+ displayname = _displayname;
+ min = _min;
+ max = _max;
+ step = _step;
+ readonly = _readonly;
+
+ U64 _this = (U64)this;
+ U64 pdata = (U64)_pdata;
+ U64 parent = (U64)_parent;
+ U64 offset = _this - parent;
+
+ _parent->eprops.push( { offset } );
+
+ offset = _this - pdata;
+ dataoff = offset;
+ }
+
+ U64 dataoff;
U8 type;
STR displayname;
F64 min{ -INFINITY };
F64 max{ INFINITY };
- struct EOBJECT* parent;
-
+ F32 step;
+ U8 readonly;
template <typename T> struct __eprop_type {
static const U8 type = EPROP_INVALID;
@@ -72,11 +188,27 @@ struct EDITOR_PROP {
template <> struct __eprop_type<F32> { static const U8 type = EPROP_F32; };
template <> struct __eprop_type<F64> { static const U8 type = EPROP_F64; };
template <> struct __eprop_type<STR> { static const U8 type = EPROP_STRING; };
+ template <> struct __eprop_type<struct CLR> { static const U8 type = EPROP_CLR; };
+ template <> struct __eprop_type<struct VEC2> { static const U8 type = EPROP_VEC2; };
+ template <> struct __eprop_type<struct VEC3> { static const U8 type = EPROP_VEC3; };
+ template <> struct __eprop_type<struct VEC4> { static const U8 type = EPROP_VEC4; };
+ template <> struct __eprop_type<struct MAP_PROPREF> { static const U8 type = EPROP_MAPPROP; };
+ template <> struct __eprop_type<struct GL_TEX2D*> { static const U8 type = EPROP_TEXTURE; };
template <__eobject_base T> struct __eprop_type<T> { static const U8 type = EPROP_OBJ; };
template <typename LT> struct __eprop_type<LIST<LT>> { static const U8 type = EPROP_LIST; };
template <> struct __eprop_type<LIST<struct MAP_TEXTURE_ENTRY*>> { static const U8 type = EPROP_TEXTURE_LIST; };
+ template <> struct __eprop_type<struct MAP_VERTEX> { static const U8 type = EPROP_VERTEX; };
+ template <> struct __eprop_type<LIST<struct MAP_VERTEX>> { static const U8 type = EPROP_VERTEX_LIST; };
};
+inline EDITOR_PROP* eprop_from_ref( EOBJECT* obj, EPROP_ENTRY e ) {
+ return (EDITOR_PROP*)( (U64)obj + e.offset );
+}
+
+inline void* eprop_ptr( EDITOR_PROP* prop ) {
+ return (void*)( (U64)prop - prop->dataoff);
+}
+
template <typename T>
const U8 eprop_type() {
return EDITOR_PROP::__eprop_type<T>::type;
diff --git a/src/editor/toolview.cpp b/src/editor/toolview.cpp
index 25c308d..6bbaa3a 100644
--- a/src/editor/toolview.cpp
+++ b/src/editor/toolview.cpp
@@ -22,11 +22,11 @@ GUI_EDITOR_TOOLVIEW* gui_editor_toolview_from_item_child( GUI_BASE* child ) {
}
I32 gui_editor_toolview_visible_h( GUI_EDITOR_TOOLVIEW* view ) {
- return std::max( 1, view->h - 4 );
+ return max( 1, view->h - 4 );
}
I32 gui_editor_toolview_max_scroll( GUI_EDITOR_TOOLVIEW* view ) {
- return std::max( 0, view->content_h - gui_editor_toolview_visible_h( view ) );
+ return max( 0, view->content_h - gui_editor_toolview_visible_h( view ) );
}
void gui_editor_toolview_clamp_scroll( GUI_EDITOR_TOOLVIEW* view ) {
@@ -34,7 +34,7 @@ void gui_editor_toolview_clamp_scroll( GUI_EDITOR_TOOLVIEW* view ) {
return;
I32 max_scroll = gui_editor_toolview_max_scroll( view );
- view->scroll = std::min( std::max( 0, view->scroll ), max_scroll );
+ view->scroll = min( max( 0, view->scroll ), max_scroll );
if( view->itemview ) {
view->itemview->y = TOOLVIEW_TITLE_OFFSET - view->scroll;
}
@@ -417,17 +417,17 @@ void gui_editor_toolview_draw_scrollbar( GUI_EDITOR_TOOLVIEW* view, I32 x, I32 y
I32 track_x = x + view->w - TOOLVIEW_SCROLLBAR_W - 3;
I32 track_y = y + 2;
- I32 track_h = std::max( 8, h - 4 );
+ I32 track_h = max( 8, h - 4 );
gui_draw_frect( track_x, track_y, TOOLVIEW_SCROLLBAR_W, track_h, ui_clr.bg_alt );
gui_draw_rect( track_x, track_y, TOOLVIEW_SCROLLBAR_W, track_h, ui_clr.border );
I32 visible_h = gui_editor_toolview_visible_h( view );
- I32 thumb_h = std::max( TOOLVIEW_SCROLLBAR_MIN_H, ( track_h * visible_h ) / std::max( 1, view->content_h ) );
- thumb_h = std::min( thumb_h, track_h );
- I32 travel = std::max( 1, track_h - thumb_h );
- I32 thumb_y = track_y + ( travel * view->scroll ) / std::max( 1, max_scroll );
+ I32 thumb_h = max( TOOLVIEW_SCROLLBAR_MIN_H, ( track_h * visible_h ) / max( 1, view->content_h ) );
+ thumb_h = min( thumb_h, track_h );
+ I32 travel = max( 1, track_h - thumb_h );
+ I32 thumb_y = track_y + ( travel * view->scroll ) / max( 1, max_scroll );
- gui_draw_frect( track_x + 1, thumb_y + 1, TOOLVIEW_SCROLLBAR_W - 2, std::max( 1, thumb_h - 2 ), ui_clr.txt );
+ gui_draw_frect( track_x + 1, thumb_y + 1, TOOLVIEW_SCROLLBAR_W - 2, max( 1, thumb_h - 2 ), ui_clr.txt );
}
void gui_editor_toolview_draw_fn( void* ptr ) {
@@ -453,7 +453,7 @@ void gui_editor_toolview_draw_fn( void* ptr ) {
if( max_scroll > 0 )
clip_w -= TOOLVIEW_SCROLLBAR_W + 2;
- gui_draw_push_clip( x + 2, y + 2, std::max( 1, clip_w ), std::max( 1, h - 4 ) );
+ gui_draw_push_clip( x + 2, y + 2, max( 1, clip_w ), max( 1, h - 4 ) );
view->itemview->draw_fn( view->itemview );
gui_draw_pop_clip();
gui_editor_toolview_draw_scrollbar( view, x, y, h );
diff --git a/src/game/world/map.cpp b/src/game/world/map.cpp
index a44f191..7b8060b 100644
--- a/src/game/world/map.cpp
+++ b/src/game/world/map.cpp
@@ -1,4 +1,4 @@
-#include <cfloat>
+#include <float.h>
#include "map.h"
#include "../../game.h"
@@ -83,7 +83,7 @@ STAT map_polygon_verts_from_section( WORLD_MAP* m, MAP_POLYGON* p, CFG_SECTION*
sprintf( vertsec, "%d", i );
CFG_SECTION* v = cfg_section( vertices, vertsec );
if( !v ) {
- dlog( "map_polygon_verts_from_section() : missing vertex %d in polygon with propid %d in map %s\n", i, p->propid, m->name );
+ dlog( "map_polygon_verts_from_section() : missing vertex %d in polygon with propid %d in map %s\n", i, p->propid.id, m->name.data );
continue;
}
@@ -92,7 +92,7 @@ STAT map_polygon_verts_from_section( WORLD_MAP* m, MAP_POLYGON* p, CFG_SECTION*
CFG_CLR* clr = cfg_clr( v, "clr" );
if( !pos ) {
- dlog( "map_polygon_verts_from_section() : missing pos for vertex %d in polygon with propid %d in map %s\n", i, p->propid, m->name );
+ dlog( "map_polygon_verts_from_section() : missing pos for vertex %d in polygon with propid %d in map %s\n", i, p->propid.id, m->name.data );
return STAT_ERR;
}
@@ -104,7 +104,7 @@ STAT map_polygon_verts_from_section( WORLD_MAP* m, MAP_POLYGON* p, CFG_SECTION*
}
if( !p->vertices.size ) {
- dlog( "map_polygon_verts_from_section() : invalid vertex count for polygon with propid %d in map %s\n", p->propid, m->name );
+ dlog( "map_polygon_verts_from_section() : invalid vertex count for polygon with propid %d in map %s\n", p->propid.id, m->name.data );
return STAT_ERR;
}
@@ -126,7 +126,7 @@ void map_polygon_calc_bounds( MAP_POLYGON* p ) {
STAT map_polygons_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* polygons, U32 polyc ) {
if( !polyc ) {
- dlog( "map_polygons_from_section() : no polygons in %s\n", m->name );
+ dlog( "map_polygons_from_section() : no polygons in %s\n", m->name.data );
return STAT_OK;
}
@@ -138,20 +138,20 @@ STAT map_polygons_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* polygon
sprintf( polysec, "%d", i );
CFG_SECTION* p = cfg_section( polygons, polysec );
if( !p ) {
- dlog( "map_polygons_from_section() : missing polygon %d in %s\n", i, m->name );
+ dlog( "map_polygons_from_section() : missing polygon %d in %s\n", i, m->name.data );
continue;
}
CFG_INT* propid = cfg_int( p, "propid" );
if( !propid ) {
- dlog( "map_polygons_from_section() : missing propid for polygon %d in map %s\n", i, m->name );
+ dlog( "map_polygons_from_section() : missing propid for polygon %d in map %s\n", i, m->name.data );
continue;
}
poly.propid = propid->value;
CFG_INT* polytype = cfg_int( p, "type" );
if( !polytype ) {
- dlog( "map_polygons_from_section() : missing polygon type for polygon %d in %s\n", i, m->name );
+ dlog( "map_polygons_from_section() : missing polygon type for polygon %d in %s\n", i, m->name.data );
continue;
}
@@ -159,13 +159,13 @@ STAT map_polygons_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* polygon
CFG_INT* vertc = cfg_int( p, "vertcount" );
if( !vertc || !vertc->value ) {
- dlog( "map_polygons_from_section() : missing vertex count for polygon %d in %s\n", i, m->name );
+ dlog( "map_polygons_from_section() : missing vertex count for polygon %d in %s\n", i, m->name.data );
continue;
}
CFG_SECTION* vertices = cfg_section( p, "vertices" );
if( !vertices ) {
- dlog( "map_polygons_from_section() : missing vertices for polygon %d in %s", i, m->name );
+ dlog( "map_polygons_from_section() : missing vertices for polygon %d in %s", i, m->name.data );
continue;
}
@@ -182,7 +182,7 @@ STAT map_polygons_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* polygon
STAT map_walls_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* walls, U32 wallc ) {
if( !wallc ) {
- dlog( "map_walls_from_section() : no walls in %s\n", m->name );
+ dlog( "map_walls_from_section() : no walls in %s\n", m->name.data );
return STAT_OK;
}
@@ -194,7 +194,7 @@ STAT map_walls_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* walls, U32
sprintf( wallsec, "%d", i );
CFG_SECTION* w = cfg_section( walls, wallsec );
if( !w ) {
- dlog( "map_walls_from_section() : missing wall %d in %s\n", i, m->name );
+ dlog( "map_walls_from_section() : missing wall %d in %s\n", i, m->name.data );
continue;
}
@@ -203,7 +203,7 @@ STAT map_walls_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* walls, U32
CFG_INT* prop = cfg_int( w, "propid" );
if( !start || !end || !prop ) {
- dlog( "map_walls_from_section() : bad wall definition in %s idx %d [%p %p %p]\n", m->name, i, start, end, prop );
+ dlog( "map_walls_from_section() : bad wall definition in %s idx %d [%p %p %p]\n", m->name.data, i, start, end, prop );
continue;
}
@@ -221,7 +221,7 @@ STAT map_walls_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* walls, U32
STAT map_props_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* props, U32 propc ) {
if( !propc ) {
- dlog( "map_props_from_section() : no props in %s\n", m->name );
+ dlog( "map_props_from_section() : no props in %s\n", m->name.data );
return STAT_ERR;
}
@@ -233,7 +233,7 @@ STAT map_props_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* props, U32
sprintf( propsec, "%d", i );
CFG_SECTION* p = cfg_section( props, propsec );
if( !p ) {
- dlog( "map_props_from_section() : missing prop %d in %s\n", i, m->name );
+ dlog( "map_props_from_section() : missing prop %d in %s\n", i, m->name.data );
continue;
}
@@ -261,7 +261,7 @@ STAT map_props_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* props, U32
STAT map_sprites_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* sprites, U32 spritec ) {
if( !spritec ) {
- dlog( "map_sprites_from_section() : no sprites in %s\n", m->name );
+ dlog( "map_sprites_from_section() : no sprites in %s\n", m->name.data );
return STAT_OK;
}
@@ -273,7 +273,7 @@ STAT map_sprites_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* sprites,
sprintf( spritesec, "%d", i );
CFG_SECTION* s = cfg_section( sprites, spritesec );
if( !s ) {
- dlog( "map_sprites_from_section() : missing sprite %d in %s\n", i, m->name );
+ dlog( "map_sprites_from_section() : missing sprite %d in %s\n", i, m->name.data );
continue;
}
@@ -283,7 +283,7 @@ STAT map_sprites_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* sprites,
CFG_VEC2* size = cfg_vec2( s, "size" );
if( !tex || !pos || !size ) {
- dlog( "map_sprites_from_section() : invalid sprite %d in %s\n", i, m->name );
+ dlog( "map_sprites_from_section() : invalid sprite %d in %s\n", i, m->name.data );
continue;
}
@@ -305,7 +305,7 @@ STAT map_sprites_from_section( WORLD_MAP* m, GAME_DATA* g, CFG_SECTION* sprites,
STAT map_entities_from_section( WORLD_MAP* m, GAME_DATA*, CFG_SECTION* entities, U32 entityc ) {
if( !entityc ) {
- dlog( "map_entities_from_section() : no entities in %s\n", m->name );
+ dlog( "map_entities_from_section() : no entities in %s\n", m->name.data );
return STAT_OK;
}
@@ -317,14 +317,14 @@ STAT map_entities_from_section( WORLD_MAP* m, GAME_DATA*, CFG_SECTION* entities,
sprintf( entitysec, "%d", i );
CFG_SECTION* s = cfg_section( entities, entitysec );
if( !s ) {
- dlog( "map_entities_from_section() : missing entity %d in %s\n", i, m->name );
+ dlog( "map_entities_from_section() : missing entity %d in %s\n", i, m->name.data );
continue;
}
CFG_INT* classid = cfg_int( s, "classid" );
CFG_VEC3* pos = cfg_vec3( s, "pos" );
if( !classid || !pos ) {
- dlog( "map_entities_from_section() : invalid entity %d in %s\n", i, m->name );
+ dlog( "map_entities_from_section() : invalid entity %d in %s\n", i, m->name.data );
continue;
}
@@ -380,24 +380,24 @@ void map_gen_skybox( WORLD_MAP* m ) {
VEC3 maxs = m->maxs + VEC3( SKYBOX_OFFSET, SKYBOX_OFFSET, SKYBOX_OFFSET );
m->skybox.walls[0] = {
+ .propid = MAPPROP_SKYBOX,
.start = { mins.x, mins.y, mins.z },
.end = { maxs.x, mins.y, maxs.z - mins.z },
- .propid = MAPPROP_SKYBOX
};
m->skybox.walls[1] = {
+ .propid = MAPPROP_SKYBOX,
.start = { maxs.x, mins.y, mins.z },
.end = { maxs.x, maxs.y, maxs.z - mins.z },
- .propid = MAPPROP_SKYBOX
};
m->skybox.walls[2] = {
+ .propid = MAPPROP_SKYBOX,
.start = { maxs.x, maxs.y, mins.z },
.end = { mins.x, maxs.y, maxs.z - mins.z },
- .propid = MAPPROP_SKYBOX
};
m->skybox.walls[3] = {
+ .propid = MAPPROP_SKYBOX,
.start = { mins.x, maxs.y, mins.z },
.end = { mins.x, mins.y, maxs.z - mins.z },
- .propid = MAPPROP_SKYBOX
};
VEC2 floor[] = {
@@ -496,7 +496,7 @@ WORLD_MAP* map_from_file( GAME_DATA* game, const char* path ) {
WORLD_MAP* m = new WORLD_MAP;
const char* name = file_path_last_of( path );
- strcpy( m->name, name );
+ m->name = name;
CFG_SECTION* s = cfg_section( root, "map" );
if( !s ) { dlog( errstr, "map", path ); delete m; return 0; }
diff --git a/src/game/world/map.h b/src/game/world/map.h
index 2b8a7a5..21bfa1f 100644
--- a/src/game/world/map.h
+++ b/src/game/world/map.h
@@ -6,23 +6,22 @@
#include "../../util/fnv.h"
#include "../../editor/properties.h"
-#include <string.h>
-
enum MapPropId_t {
MAPPROP_SKYBOX = -1,
MAPPROP_CLIPBRUSH = -2,
};
struct SURF_PROPS : public EOBJECT {
- struct GL_TEX2D* tex;
- CLR clr;
+ EPROP( GL_TEX2D*, tex, {}, "texture" );
+ EPROP( CLR, clr, {}, "color" );
};
struct MAP_VERTEX : public EOBJECT {
- VEC3 pos;
- VEC3 normal;
- VEC2 uv;
- CLR clr;
+ EPROP( VEC3, pos, {}, "position" );
+ EPROP_RANGED_STEP( VEC2, uv, {}, "uv", 0.f, 1.f, 0.025f );
+ EPROP( CLR, clr, {}, "color" );
+
+ EPROP_RO( VEC3, normal, {}, "normal" );
};
enum MapPolygonType_t {
@@ -30,23 +29,33 @@ enum MapPolygonType_t {
MPT_CEILING
};
+struct MAP_PROPREF {
+ operator I32&() { return id; }
+ operator I32() const { return id; }
+
+ MAP_PROPREF() {}
+ MAP_PROPREF( U32 id ) : id( id ) {}
+
+ I32 id;
+};
+
struct MAP_POLYGON : public EOBJECT {
- LIST<MAP_VERTEX> vertices;
+ EPROP( MAP_PROPREF, propid, {}, "prop id" );
+ EPROP( LIST<MAP_VERTEX>, vertices, {}, "vertices" );
- VEC3 mins;
- VEC3 maxs;
+ EPROP_RO( VEC3, mins, {}, "mins" );
+ EPROP_RO( VEC3, maxs, {}, "maxs" );
U8 type;
- I32 propid;
};
struct MAP_WALL : public EOBJECT {
- VEC3 start;
- VEC3 end;
+ EPROP( MAP_PROPREF, propid, {}, "prop id" );
- VEC2 uvstart;
- VEC2 uvend;
+ EPROP( VEC3, start, {}, "start pos" );
+ EPROP( VEC3, end, {}, "end pos" );
- I32 propid;
+ EPROP_RANGED_STEP( VEC2, uvstart, {}, "uv start offset", 0.f, 1.f, 0.025f );
+ EPROP_RANGED_STEP( VEC2, uvend, {}, "uv end offset", 0.f, 1.f, 0.025f );
};
struct MAP_TEXTURE_ENTRY {
@@ -56,40 +65,42 @@ struct MAP_TEXTURE_ENTRY {
};
struct MAP_SPRITE : public EOBJECT {
- VEC3 pos;
- VEC2 size;
- CLR clr;
- GL_TEX2D* tex;
+ EPROP( GL_TEX2D*, tex, {}, "texture" );
+ EPROP( VEC3, pos, {}, "position" );
+ EPROP_RANGED( VEC2, size, {}, "size", 0.25f, INFINITY );
+ EPROP( CLR, clr, {}, "color" );
};
-struct MAP_ENTITY {
- VEC3 pos;
- U32 classid;
- LIST<struct OBJECT_PROP*> props;
+struct MAP_ENTITY : public EOBJECT {
+ EPROP( VEC3, pos, {}, "position" );
+ EPROP( U32, classid, {}, "entity class" );
+
+ EPROP( LIST<struct OBJECT_PROP*>, props, {}, "entity properties" );
};
struct MAP_SKYBOX : public EOBJECT {
- SURF_PROPS props;
+ EPROP( SURF_PROPS, props, {}, "skybox surface properties" );
MAP_WALL walls[4];
MAP_POLYGON polygons[2];
};
struct WORLD_MAP : public EOBJECT {
- LIST<MAP_WALL> walls;
- LIST<MAP_POLYGON> polygons;
- LIST<MAP_SPRITE> sprites;
- LIST<MAP_ENTITY> entities;
- LIST<SURF_PROPS> props;
- MAP_SKYBOX skybox;
+ EPROP_RO( STR, name, {}, "name" );
+ EPROP( VEC3, startpos, {}, "spawn position" );
+ EPROP( F32, startang, {}, "spawn angle" );
+
+ EPROP( LIST<MAP_WALL> , walls, {}, "walls" );
+ EPROP( LIST<MAP_POLYGON>, polygons, {}, "polygons" );
+ EPROP( LIST<MAP_SPRITE> , sprites, {}, "sprites" );
+ EPROP( LIST<MAP_ENTITY> , entities, {}, "entities" );
+ EPROP( LIST<SURF_PROPS> , props, {}, "surface properties" );
+
+ EPROP( MAP_SKYBOX, skybox, {}, "skybox" );
F32 w;
F32 h;
- VEC3 mins;
- VEC3 maxs;
- char name[256];
-
- VEC3 startpos;
- F32 startang;
+ EPROP_RO( VEC3, mins, {}, "mins" );
+ EPROP_RO( VEC3, maxs, {}, "maxs" );
struct BSP* bsp{};
diff --git a/src/gui/base.h b/src/gui/base.h
index e62c66a..293de74 100644
--- a/src/gui/base.h
+++ b/src/gui/base.h
@@ -1,6 +1,5 @@
#pragma once
#include "../render/gl_2d.h"
-#include <functional>
// ======================================= [ colorscheme ] ========================================
@@ -46,7 +45,7 @@ extern U8 gui_is_fg_window( struct GUI_BASE* node ); // 1 if pa
// ======================================= [ components ] =========================================
-using GUI_CALLBACK = std::function<void( void* )>;
+using GUI_CALLBACK = FN<void( void* )>;
struct GUI_LIST_ENTRY {
I32 val;
char title[256];
@@ -129,6 +128,8 @@ extern void gui_base_input_fn( void* );
extern void gui_view_draw_fn( void* );
struct GUI_BASE {
+ virtual ~GUI_BASE() = default;
+
I32 x{}, y{};
I32 w{}, h{};
U8 enabled{1};
diff --git a/src/util/allocator.h b/src/util/allocator.h
index 327dfc1..623d227 100644
--- a/src/util/allocator.h
+++ b/src/util/allocator.h
@@ -2,8 +2,7 @@
#include <stdlib.h>
#include <string.h>
-#include <functional>
-#include "typedef.h"
+#include "callback.h"
template <typename T>
struct LIST_ITERATOR {
@@ -19,7 +18,7 @@ struct LIST_ITERATOR {
};
template <typename T>
-using QSORT_FN = std::function< U8( T*, T* ) >;
+using QSORT_FN = FN< U8( T*, T* ) >;
template <typename T>
static U8 qsort_basic_sort( T* t1, T* t2 ) {
@@ -58,8 +57,8 @@ struct LIST {
U32 capacity;
U32 size;
- using ON_EACH_FN = std::function< void(T*) >;
- using ON_SEARCH_FN = std::function< bool(T*) >;
+ using ON_EACH_FN = FN< void(T*) >;
+ using ON_SEARCH_FN = FN< U8(T*) >;
LIST() {
data = (T*)malloc( sizeof( T ) );
@@ -265,6 +264,8 @@ struct LIST {
}
T ret = data[--size];
+ if constexpr( !__is_trivially_destructible(T) )
+ data[size].~T();
if( size < capacity / 4 )
shrink();
diff --git a/src/util/callback.h b/src/util/callback.h
new file mode 100644
index 0000000..a2c9477
--- /dev/null
+++ b/src/util/callback.h
@@ -0,0 +1,84 @@
+#pragma once
+#include "typedef.h"
+
+template <typename T>
+struct FN;
+// voodoo
+template <typename RET, typename... ARGS>
+struct FN<RET(ARGS...)> {
+ template <typename T> struct __strip_ref { using type = T; };
+ template <typename T> struct __strip_ref<T&> { using type = T; };
+ template <typename T> struct __strip_ref<T&&> { using type = T; };
+ template <typename R, typename... A> struct __strip_ref<R(A...)> { using type = R(*)(A...); };
+ template <typename R, typename... A> struct __strip_ref<R(&)(A...)> { using type = R(*)(A...); };
+
+ static const unsigned int BUF_SIZE = 32;
+
+ alignas(8) char buf[BUF_SIZE];
+ void* data;
+ RET( *invoke )( void*, ARGS... );
+ void( *destroy )( void* );
+ void*( *clone )( void*, char* );
+
+ template <typename F>
+ FN(F&& f) {
+ using __stripped = typename __strip_ref<F>::type;
+
+ if constexpr( sizeof(__stripped) <= BUF_SIZE ) {
+ new (buf) __stripped( f );
+ data = buf;
+ destroy = pfn( void* d ) {
+ ( (__stripped*)d )->~__stripped();
+ };
+ clone = pfn( void* d, char* dst ) -> void* {
+ new (dst) __stripped( *(__stripped*)d );
+ return dst;
+ };
+ } else {
+ data = new __stripped( f );
+ destroy = pfn( void* d ) {
+ delete (__stripped*)d;
+ };
+ clone = pfn( void* d, char* dst ) -> void* {
+ return new __stripped( *(__stripped*)d );
+ };
+ }
+
+ invoke = pfn( void* d, ARGS... args ) -> RET {
+ return ( *(__stripped*)d )( args... );
+ };
+ }
+
+ FN( I32&& ) : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {}
+ FN( U32&& ) : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {}
+ FN() : data( 0 ), invoke( 0 ), destroy( 0 ), clone( 0 ) {}
+
+ FN( const FN& other ) : invoke( other.invoke ), destroy( other.destroy ), clone( other.clone ) {
+ if( !other.data ) {
+ data = 0;
+ return;
+ }
+
+ data = other.clone( other.data, buf );
+ }
+
+ FN& operator=( const FN& other ) {
+ if( this == &other ) return *this;
+ if( destroy && data ) destroy( data );
+ invoke = other.invoke;
+ destroy = other.destroy;
+ clone = other.clone;
+ data = other.data ? other.clone( other.data, buf ) : 0;
+ return *this;
+ }
+
+ ~FN() {
+ if( destroy && data ) destroy( data );
+ }
+
+ RET operator()( ARGS... args ) const {
+ return invoke( data, args... );
+ }
+
+ operator bool() const { return !!invoke; }
+};
diff --git a/src/util/color.h b/src/util/color.h
index 526cddc..8b1a259 100644
--- a/src/util/color.h
+++ b/src/util/color.h
@@ -1,5 +1,5 @@
#pragma once
-#include "typedef.h"
+#include "string.h"
#include <math.h>
struct CLR {
@@ -166,3 +166,5 @@ struct CLR {
return *this;
}
};
+
+inline STR to_str( CLR c ) { return STR( "%.02f %.02f %.02f %.02f", c.r, c.g, c.b, c.a ); }
diff --git a/src/util/config.h b/src/util/config.h
index 7973db0..d8c1c2e 100644
--- a/src/util/config.h
+++ b/src/util/config.h
@@ -1,7 +1,7 @@
#pragma once
#include <stdio.h>
-#include "allocator.h"
+#include "string.h"
#include "vector.h"
#include "color.h"
@@ -26,8 +26,8 @@ enum CfgNodeType_t {
// ===================================== [ definitions ] ===========================================
-using CFG_PARSEFN = std::function<void( CFG_PARSER*, CFG_SECTION*, char* )>;
-using CFG_SERIALIZEFN = std::function<void( CFG_SERIALIZER*, CFG_NODE*, char* )>;
+using CFG_PARSEFN = FN<STAT( CFG_PARSER*, CFG_SECTION*, char* )>;
+using CFG_SERIALIZEFN = FN<STR( CFG_SERIALIZER*, CFG_NODE*)>;
struct CFG_TYPE {
U8 type;
@@ -37,7 +37,7 @@ struct CFG_TYPE {
};
struct CFG_NODE {
- char name[64];
+ STR name;
CFG_NODE* parent;
U8 type;
};
@@ -66,14 +66,14 @@ extern STAT cfg_parser_clr( CFG_PARSER* parser, CFG_SECTION* section, char* name
// ====================================== [ serializers ] ==========================================
-extern void cfg_serialize_section( CFG_SERIALIZER* serializer, CFG_NODE* section, char* buf );
-extern void cfg_serialize_bytes( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_str( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_float( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_int( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_vec2( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_vec3( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
-extern void cfg_serialize_clr( CFG_SERIALIZER* serializer, CFG_NODE* node, char* buf );
+extern STR cfg_serialize_section( CFG_SERIALIZER* serializer, CFG_NODE* section );
+extern STR cfg_serialize_bytes( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_str( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_float( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_int( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_vec2( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_vec3( CFG_SERIALIZER* serializer, CFG_NODE* node );
+extern STR cfg_serialize_clr( CFG_SERIALIZER* serializer, CFG_NODE* node );
// ========================================= [ config ] ============================================
@@ -158,6 +158,7 @@ static void cfg_free( CFG_NODE* n ) {
else if( n->type == CFGT_SECTION ) {
CFG_SECTION* s = (CFG_SECTION*)n;
s->children.each( fn( CFG_NODE** child ) { cfg_free( *child ); } );
+ return delete s;
}
delete n;
diff --git a/src/util/config/config.cpp b/src/util/config/config.cpp
index a41e455..00a2512 100644
--- a/src/util/config/config.cpp
+++ b/src/util/config/config.cpp
@@ -30,9 +30,7 @@ inline void trim_whitespace( char* buf ) {
}
inline void init_cfg_node( CFG_NODE* node, const char* name, CFG_NODE* parent, U8 type ) {
- memset( node->name, 0, sizeof(node->name) );
- strcpy( node->name, name );
- node->name[sizeof(node->name) - 1] = '\0';
+ node->name = name;
node->parent = parent;
if( parent )
( (CFG_SECTION*)parent )->children.push( node );
@@ -290,17 +288,12 @@ STAT cfg_save( CFG_SECTION* root, const char* path ) {
if( !f )
return STAT_ERR;
- char* buf = (char*)malloc( 999999 );
- buf[0] = 0;
CFG_SERIALIZER s;
s.tabc = 0;
s.f = f;
- cfg_serialize_section( &s, (CFG_NODE*)root, buf );
- U32 len = strlen( buf );
-
- fwrite( buf, 1, len, f );
- free( buf );
+ STR buf = cfg_serialize_section( &s, (CFG_NODE*)root );
+ fwrite( buf, 1, buf.size, f );
fclose( f );
return STAT_OK;
diff --git a/src/util/config/serializers.cpp b/src/util/config/serializers.cpp
index 01f416c..15ddae0 100644
--- a/src/util/config/serializers.cpp
+++ b/src/util/config/serializers.cpp
@@ -1,109 +1,122 @@
-#include <cstdarg>
-#include <cstdio>
-
#include "../config.h"
-void serialize_node( CFG_SERIALIZER* s, CFG_NODE* n, char* buf ) {
- U32 len = strlen( buf );
- for( U32 i = 0; i < s->tabc * 2; ++i ) buf[i + len] = ' ';
- buf[len + s->tabc * 2] = 0;
- sprintf( buf, "%s%s %s", buf, cfg_types[n->type].def, n->name );
+STR serialize_node( CFG_SERIALIZER* s, CFG_NODE* n ) {
+ STR ret{};
+ for( U32 i = 0; i < s->tabc * 2; ++i ) ret.append( " " );
+ ret.fmt( "%s %s", cfg_types[n->type].def, n->name.data );
+
+ return ret;
}
-void cfg_serialize_section( CFG_SERIALIZER* s, CFG_NODE *n, char *buf ) {
+STR cfg_serialize_section( CFG_SERIALIZER* s, CFG_NODE *n ) {
CFG_SECTION* sec = (CFG_SECTION*)n;
+ STR buf;
if( sec->parent ) {
- serialize_node( s, n, buf );
- strcat( buf, " {\n" );
+ buf += serialize_node( s, n );
+ buf += " {\n";
s->tabc++;
}
- char line[8192];
for( U32 i = 0; i < sec->children.size; ++i ) {
- line[0] = 0;
CFG_NODE* c = sec->children[i];
if( c->type == CFGT_SECTION ) {
- cfg_serialize_section( s, c, buf );
+ buf += cfg_serialize_section( s, c );
continue;
}
- cfg_types[c->type].serializer( s, c, line );
- strcat( buf, line );
- strcat( buf, "\n" );
+ buf += cfg_types[c->type].serializer( s, c );
+ buf += "\n";
}
if( sec->parent ) {
s->tabc--;
- char tabbuf[512] = { 0 };
- for( U32 i = 0 ; i < s->tabc * 2; ++i )
- tabbuf[i] = ' ';
- tabbuf[s->tabc * 2] = 0;
- strcat( buf, tabbuf );
- strcat( buf, "}" );
+ for( U32 i = 0 ; i < s->tabc * 2; ++i ) buf += ' ';
+ buf += "}";
if( sec->parent )
- strcat( buf, "\n" );
+ buf += "\n";
}
+
+ return buf;
}
-void cfg_serialize_bytes( CFG_SERIALIZER* s, CFG_NODE* n, char* buf ) {
+STR cfg_serialize_bytes( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_BYTES* b = (CFG_BYTES*)n;
U32 size = b->size;
U8* bytes = b->bytes;
- serialize_node( s, n, buf );
- sprintf( buf, "%s[%d] = \"", buf, size );
- U32 len = strlen( buf );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( "[%d] = \"", size );
for( U32 i = 0; i < size; ++i ) {
- sprintf( buf + len + i * 2, "%02X", bytes[i] );
+ buf.fmt( "%02X", bytes[i] );
}
-
- sprintf( buf, "%s%s", buf, "\";" );
+ buf += "\";";
+ return buf;
}
-void cfg_serialize_str( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
+STR cfg_serialize_str( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_STR* sn = (CFG_STR*)n;
char* str = sn->str;
- serialize_node( s, n, buf );
- sprintf( buf, "%s[%d] = \"%s\";", buf, sn->len, str );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( "[%d] = \"%s\";", sn->len, str );
+ return buf;
}
-void cfg_serialize_int( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
- CFG_INT* i = (CFG_INT*)n;
- I32 ival = i->value;
+STR cfg_serialize_int( CFG_SERIALIZER* s, CFG_NODE* n ) {
+ CFG_INT* i = (CFG_INT*)n;
+ I32 ival = i->value;
- serialize_node( s, n, buf );
- sprintf( buf, "%s = %d;", buf, ival );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( " = %d;", ival );
+ return buf;
}
-void cfg_serialize_float( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
+STR cfg_serialize_float( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_FLOAT* f = (CFG_FLOAT*)n;
F32 fval = f->value;
- serialize_node( s, n, buf );
- sprintf( buf, "%s = %g;", buf, fval );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( " = %g;", fval );
+ return buf;
}
-void cfg_serialize_vec2( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
+STR cfg_serialize_vec2( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_VEC2* v = (CFG_VEC2*)n;
VEC2 val = v->value;
- serialize_node( s, n, buf );
- sprintf( buf, "%s = { %g, %g };", buf, val.x, val.y );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( " = { %g, %g };", val.x, val.y );
+ return buf;
}
-void cfg_serialize_vec3( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
+STR cfg_serialize_vec3( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_VEC3* v = (CFG_VEC3*)n;
VEC3 val = v->value;
- serialize_node( s, n, buf );
- sprintf( buf, "%s = { %g, %g, %g };", buf, val.x, val.y, val.z );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( " = { %g, %g, %g };", val.x, val.y, val.z );
+ return buf;
}
-void cfg_serialize_clr( CFG_SERIALIZER* s, CFG_NODE* n, char *buf ) {
+STR cfg_serialize_clr( CFG_SERIALIZER* s, CFG_NODE* n ) {
CFG_CLR* v = (CFG_CLR*)n;
CLR val = v->value;
- serialize_node( s, n, buf );
- sprintf( buf, "%s = { %g, %g, %g, %g };", buf, val.r, val.g, val.b, val.a );
+ STR buf{};
+
+ buf += serialize_node( s, n );
+ buf.fmt( " = { %g, %g, %g, %g };", val.r, val.g, val.b, val.a );
+ return buf;
}
diff --git a/src/util/file.h b/src/util/file.h
index 7e4d413..4309e62 100644
--- a/src/util/file.h
+++ b/src/util/file.h
@@ -1,7 +1,7 @@
#pragma once
-#include <cstdlib>
-#include <cstring>
+#include <stdlib.h>
+#include <string.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
diff --git a/src/util/input.h b/src/util/input.h
index 1317f94..af5e258 100644
--- a/src/util/input.h
+++ b/src/util/input.h
@@ -1,7 +1,6 @@
#pragma once
#include <SDL_events.h>
-#include <functional>
#include "vector.h"
#include "allocator.h"
@@ -33,7 +32,7 @@ struct INPUT_KEYBINDS {
U8 crouch = SDL_SCANCODE_LCTRL;
};
-using ON_INPUT_FN = std::function<void( SDL_Event* )>;
+using ON_INPUT_FN = FN<void( SDL_Event* )>;
struct INPUT_DATA {
MOUSE_DATA mouse;
diff --git a/src/util/str_tokenizer.h b/src/util/str_tokenizer.h
new file mode 100644
index 0000000..8a3aebf
--- /dev/null
+++ b/src/util/str_tokenizer.h
@@ -0,0 +1,140 @@
+#pragma once
+
+#include "string.h"
+
+using TOKENIZER_COMPARE_FN = FN<U8( char )>;
+
+struct STR_TOKENIZER {
+ STR str;
+ STR ignored;
+
+ I32 cur;
+ I32 last;
+};
+
+inline STR_TOKENIZER tok_init( STR str, STR whitespace_chars = " \t\n\r" ) {
+ return {
+ .str = str,
+ .ignored = { whitespace_chars },
+ .cur = 0,
+ .last = 0,
+ };
+}
+
+inline STR tok_next( STR_TOKENIZER* t ) {
+ if( t->cur >= t->str.size )
+ return "";
+
+ U8 start = 0;
+ for( I32 i = t->cur; i < t->str.size; i++ ) {
+ U8 c = t->str.data[i];
+ if( i == t->str.size - 1 ) {
+ if( !start )
+ return "";
+
+ STR ret = { (U32)i - t->cur + 1, t->str.data + t->cur };
+ t->last = t->cur;
+ t->cur = i + 1;
+ return ret;
+ }
+
+ for( auto& it : t->ignored ) {
+ if( c == it ) {
+ if( !start ) {
+ t->cur = i + 1;
+ continue;
+ } else {
+ STR ret = { (U32)i - t->cur, t->str.data + t->cur };
+ t->last = t->cur;
+ t->cur = i + 1;
+ return ret;
+ }
+ }
+ }
+
+ start = 1;
+ }
+
+ return "";
+}
+
+inline STR tok_peek( STR_TOKENIZER* t ) {
+ if( t->cur >= t->str.size )
+ return "";
+
+ U8 start = 0;
+ I32 cur = t->cur;
+ for( I32 i = cur; i < t->str.size; i++ ) {
+ U8 c = t->str.data[i];
+ if( i == t->str.size - 1 ) {
+ if( !start )
+ return "";
+
+ STR ret = { (U32)i - cur + 1, t->str.data + cur };
+ return ret;
+ }
+
+ for( auto& it : t->ignored ) {
+ if( c == it ) {
+ if( !start ) {
+ cur = i + 1;
+ continue;
+ } else {
+ STR ret = { (U32)i - cur, t->str.data + cur };
+ return ret;
+ }
+ }
+ }
+
+ start = 1;
+ }
+
+ return "";
+}
+
+
+inline STR tok_next( STR_TOKENIZER* t, STR what ) {
+ if( t->cur >= t->str.size )
+ return "";
+
+ if( !what.size )
+ return "";
+
+ for( I32 i = t->cur; i <= t->str.size - what.size; i++ ) {
+ STR slice = { what.size, t->str.data + i };
+ if( slice == what ) {
+ STR ret = { (U32)i - t->cur, t->str.data + i + what.size };
+ t->last = t->cur;
+ t->cur = i + what.size;
+ return ret;
+ }
+ }
+
+ return "";
+}
+
+inline char tok_nextchar( STR_TOKENIZER* t ) {
+ if( t->cur >= t->str.size )
+ return 0;
+
+ U32 last = t->cur;
+ for( ; t->cur < t->str.size; t->cur++ ) {
+ U8 cont = 0;
+ for( auto& it : t->ignored ) {
+ if( t->str.data[t->cur] == it ) {
+ cont = 1;
+ break;
+ }
+ }
+
+ if( cont )
+ continue;
+ else {
+ t->last = last;
+ t->cur++;
+ return t->str.data[t->cur];
+ }
+ }
+
+ return 0;
+}
diff --git a/src/util/string.h b/src/util/string.h
index 2268a36..672fb5d 100644
--- a/src/util/string.h
+++ b/src/util/string.h
@@ -55,8 +55,6 @@ template <typename CT>
struct __str : public LIST<CT> {
__str() : LIST<CT>() {}
__str( U32 count, const CT* str ) : LIST<CT>() {
- this->data = 0;
- this->capacity = 0;
this->reserve( count * 2 );
memcpy( this->data, str, count );
this->size = count;
@@ -69,8 +67,6 @@ struct __str : public LIST<CT> {
va_copy( args2, args );
U32 c = vsnprintf( 0, 0, fmt, args );
va_end( args );
- this->data = 0;
- this->capacity = 0;
this->reserve( c * 2 );
vsnprintf( this->data, c + 1, fmt, args2 );
this->data[c] = 0;
@@ -89,8 +85,6 @@ struct __str : public LIST<CT> {
if( this->data && this->data != other.data )
free( this->data );
- this->data = 0;
-
if( !other.capacity || !other.size ) {
this->capacity = 1;
this->size = 0;
@@ -116,8 +110,9 @@ struct __str : public LIST<CT> {
__str<CT> operator+( const CT rhs ) { __str<CT> ret = *this; ret.push( rhs ); return ret; }
__str<CT>& operator+=( const __str<CT>& rhs ) { return this->append( rhs ); }
__str<CT>& operator+=( const CT* rhs ) { return this->append( rhs ); }
- __str<CT>& operator+=( const CT rhs ) { this->push( rhs ); return this; }
+ __str<CT>& operator+=( const CT rhs ) { this->push( rhs ); return *this; }
+ operator const CT*() { return this->data; }
operator CT*() { return this->data; }
CT operator[]( U32 i ) {
@@ -128,10 +123,8 @@ struct __str : public LIST<CT> {
if( rhs.size != this->size )
return 0;
- for( U32 i = 0; i < this->size; ++i ) {
- if( this->data[i] != rhs.data[i] )
- return 0;
- }
+ if( !!memcmp( this->data, rhs.data, this->size ) )
+ return 0;
return 1;
}
@@ -165,7 +158,7 @@ struct __str : public LIST<CT> {
__str<CT>& append( const CT* str ) {
U32 len;
for( len = 0; !!str[len]; ++len );
- if( this->size + len > this->capacity )
+ if( this->size + len + 1 >= this->capacity )
this->reserve( this->size + len + 1 );
memcpy( this->data + this->size, str, len * sizeof(CT) );
@@ -179,7 +172,7 @@ struct __str : public LIST<CT> {
if( this->size + len + 1 >= this->capacity )
this->reserve( this->size + len + 1 );
- memcpy( this->data + this->size, str, len * sizeof(CT) );
+ memcpy( this->data + this->size, str.data, len * sizeof(CT) );
this->size += len;
this->data[this->size] = 0;
return *this;
@@ -281,3 +274,11 @@ struct __str : public LIST<CT> {
using STR = __str<char>;
using WSTR = __str<wchar_t>;
+
+inline STR to_str( F32 f ) { return STR( "%.02f", f ); }
+inline STR to_str( F64 f ) { return STR( "%.02g", f ); }
+inline STR to_str( I32 i ) { return STR( "%d", i ); }
+inline STR to_str( I64 i ) { return STR( "%lld", i ); }
+inline STR to_str( U32 u ) { return STR( "%u", u ); }
+inline STR to_str( U64 u ) { return STR( "%llu", u ); }
+inline STR to_str( void* p ) { return STR( "%llx", (U64)p ); }
diff --git a/src/util/vector.h b/src/util/vector.h
index 854b454..eb386ab 100644
--- a/src/util/vector.h
+++ b/src/util/vector.h
@@ -1,7 +1,7 @@
#pragma once
#include <math.h>
-#include "typedef.h"
+#include "string.h"
static const F32 PI = 3.14159265359f;
static const F32 PIRAD = 0.01745329251f;
@@ -13,7 +13,6 @@ struct VEC2 {
VEC2() { x = y = 0.0f; }
VEC2( F32 X, F32 Y ) { x = X; y = Y; }
- VEC2( const F32* v ) { x = v[0]; y = v[1]; }
VEC2( const VEC2& v ) { x = v.x; y = v.y; }
bool operator==( const VEC2& v ) const { return ( x == v.x && y == v.y ); }
@@ -49,7 +48,6 @@ struct VEC3 {
VEC3() { x = y = z = 0.0f; }
VEC3( F32 X, F32 Y, F32 Z ) { x = X; y = Y; z = Z; }
- VEC3( const F32* v ) { x = v[0]; y = v[1]; z = v[2]; }
VEC3( const VEC3& v ) { x = v.x; y = v.y; z = v.z; }
VEC3( const VEC2& v ) { x = v.x; y = v.y; z = 0.f; }
@@ -250,3 +248,7 @@ inline void angle_vectors( const VEC3& angles, VEC3* forward, VEC3* right, VEC3*
up->z = cr * cp;
}
}
+
+inline STR to_str( VEC2 v ) { return STR( "%.02f, %.02f", v.x, v.y ); }
+inline STR to_str( VEC3 v ) { return STR( "%.02f, %.02f, %.02f", v.x, v.y, v.z ); }
+inline STR to_str( VEC4 v ) { return STR( "%.02f, %.02f, %.02f, %.02f", v.x, v.y, v.z, v.w ); }