summaryrefslogtreecommitdiff
path: root/src/editor/properties.cpp
diff options
context:
space:
mode:
authornavewindre <boneyaard@gmail.com>2025-09-03 20:10:09 +0200
committernavewindre <boneyaard@gmail.com>2025-09-03 20:10:09 +0200
commitf8b92ce3aa08b1445c9f956d8166830946562d12 (patch)
tree94e63a5aec9f8f52b577f56799e0c9201fd976a5 /src/editor/properties.cpp
a
Diffstat (limited to 'src/editor/properties.cpp')
-rw-r--r--src/editor/properties.cpp348
1 files changed, 348 insertions, 0 deletions
diff --git a/src/editor/properties.cpp b/src/editor/properties.cpp
new file mode 100644
index 0000000..ebae177
--- /dev/null
+++ b/src/editor/properties.cpp
@@ -0,0 +1,348 @@
+#include "editor.h"
+#include "../render/gl.h"
+#include "../game/assets.h"
+
+const I32 PROPVIEW_TITLE_OFFSET = 15;
+
+void gui_editor_propview_select( GUI_EDITOR_PROPVIEW* view, void* what, U8 seltype ) {
+ if( !editor->map )
+ return;
+
+ if( seltype == EDITOR_SELECT_WVERTEX ) {
+ MAP_WALL* s = editor->map->walls.where( fn( MAP_WALL* s ) {
+ return ( &s->start == what || &s->end == what );
+ } );
+
+ if( !s )
+ return gui_editor_propview_select( view, editor->map, EDITOR_SELECT_ORIGIN );
+
+ view->curselect = s;
+ view->seltype = EDITOR_SELECT_WALL;
+ return gui_editor_propview_update( view );
+ }
+
+ view->curselect = what;
+ view->seltype = seltype;
+ gui_editor_propview_update( view );
+}
+
+// returns the subentry height
+I32 gui_editor_propview_surfprops_subentry( I32 x, I32 y, I32* propid, SURF_PROPS* props ) {
+ I32 oldy = y;
+ I32 space = 20;
+ gui_label( x, y, "prop id: %d", *propid );
+ GUI_BUTTON* newprop = gui_button( x + 235, 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;
+ gui_editor_propview_update( editor->gui.props );
+ } );
+ newprop->extra = propid;
+ GUI_BUTTON* goprop = gui_button( x + 260, 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;
+
+ if( props->tex )
+ gui_label( x + 10, y, "texture: %s", props->tex->name );
+ else
+ gui_label( x + 10, y, "texture: none" );
+
+ GUI_BUTTON* btn = gui_button( x + 260, 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 = &props->tex;
+ y += space;
+ gui_colorinput( x + 10, y, 270, "color", &props->clr ); y += (space+18);
+
+ return y - oldy;
+}
+
+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( x, y, &s->propid, props );
+
+ GUI_VECTORINPUT* posinput;
+ posinput = gui_vectorinput( x, y, 280, "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, 280, "end", (F32*)&s->end, 3, -INFINITY, INFINITY, step ); y += (space+18);
+ posinput->cb = pfn( void* ) { map_check_bounds( editor->map ); };
+}
+
+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;
+ } );
+
+ gui_label( x, y, "idx: %d", poly_idx ); y += space;
+ y += gui_editor_propview_surfprops_subentry( 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( x + 260, 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;
+}
+
+void gui_editor_propview_create_mapprops( GUI_EDITOR_PROPVIEW* view ) {
+ WORLD_MAP* m = (WORLD_MAP*)view->curselect;
+
+ I32 x = 10, y = 10;
+ I32 space = 20;
+
+ F32 step = editor->propgrid? editor->grid : 0.25f;
+
+ gui_label( x, y, "name: %s", m->name ); 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;
+ I32 i = 0;
+ m->props.each( fn( SURF_PROPS* p ) {
+ if( p->tex )
+ gui_label( x + 10, y, "[%d] -> %s", i++, assets_abspath( p->tex->name ) );
+ else
+ gui_label( x + 10, y, "[%d] -> { %.02f, %.02f, %.02f, %.02f }", i++, p->clr.r, p->clr.g, p->clr.b, p->clr.a );
+
+ GUI_BUTTON* btn = gui_button( x + 260, 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 );
+ } );
+ btn->extra = p;
+ y += space;
+ } );
+ gui_label( x, y, "sprites: %d", m->sprites.size ); y += space;
+ gui_label( x, y, "loaded textures: %d", m->textures.size ); y += space;
+ gui_vectorinput( x, y, 280, "spawn position", (F32*)&m->startpos, 3, -INFINITY, INFINITY, step ); y += (space+18);
+ GUI_FLOATINPUT* ang = gui_floatinput( x, y, 280, "spawn angle", &m->startang, -180.f, 180.f, 1.f ); y += (space+18);
+ ang->wraparound = 1;
+}
+
+void gui_editor_propview_create_pvertexprops( GUI_EDITOR_PROPVIEW* view ) {
+ MAP_VERTEX* v = (MAP_VERTEX*)view->curselect;
+ WORLD_MAP* m = editor->map;
+
+ I32 x = 10, y = 10;
+ I32 space = 20;
+
+ I32 vert_idx = -1;
+ I32 poly_idx = m->polygons.idx_where( fn( MAP_POLYGON* p ) {
+ vert_idx = p->vertices.idx_where( fn( MAP_VERTEX* pv ) { return (pv == v); } );
+ return vert_idx != -1;
+ } );
+
+ F32 step = editor->propgrid? editor->grid : 0.25f;
+
+ gui_label( x, y, "idx: %d", vert_idx ); y += space;
+ gui_label( x, y, "polygon idx: %d", poly_idx );
+
+ gui_button( x + 260, y - 2, 20, 20, "\x1A", pfn( void* ) {
+ GUI_EDITOR_PROPVIEW* view = editor->gui.props;
+ MAP_VERTEX* v = (MAP_VERTEX*)view->curselect;
+ WORLD_MAP* m = editor->map;
+ MAP_POLYGON* polygon = m->polygons.where( fn( MAP_POLYGON* p ) {
+ I32 vert_idx = p->vertices.idx_where( fn( MAP_VERTEX* pv ) { return (pv == v); } );
+ return vert_idx != -1;
+ } );
+
+ if( polygon )
+ gui_editor_propview_select( view, polygon, EDITOR_SELECT_POLY );
+ } );
+ y += space;
+
+ GUI_VECTORINPUT* posinput = gui_vectorinput( x, y, 280, "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, 280, "texture coordinates", (F32*)&v->uv, 2, 0.f, 1.f, 0.005f, "xy", "%.03f" ); y += (space+18);
+ gui_colorinput( x, y, 280, "color", &v->clr ); y += (space+18);
+}
+
+void gui_editor_propview_create_spriteprops( GUI_EDITOR_PROPVIEW* view ) {
+ MAP_SPRITE* s = (MAP_SPRITE*)view->curselect;
+ WORLD_MAP* m = editor->map;
+
+ I32 x = 10, y = 10;
+ I32 space = 20;
+
+ I32 sprite_idx = m->sprites.idx_where( fn( MAP_SPRITE* ms ) {
+ return ms == s;
+ } );
+
+ F32 step = editor->propgrid? editor->grid : 0.25f;
+
+ gui_label( x, y, "idx: %d", sprite_idx ); y += space;
+ gui_vectorinput( x, y, 280, "position", (F32*)&s->pos, 3, -INFINITY, INFINITY, step ); y += (space+18);
+ gui_vectorinput( x, y, 280, "size", (F32*)&s->size, 2, 1.f, INFINITY, 1.f, "wh" ); y += (space+18);
+ gui_colorinput( x, y, 280, "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( x + 260, 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;
+}
+
+void gui_editor_propview_create_surfprops( GUI_EDITOR_PROPVIEW* view ) {
+ SURF_PROPS* p = (SURF_PROPS*)view->curselect;
+ WORLD_MAP* m = editor->map;
+
+ I32 x = 10, y = 10;
+ I32 space = 20;
+
+ I32 i = m->props.idx_where( fn( SURF_PROPS* mp ) { return mp == p; } );
+ if( i == -1 )
+ return;
+
+ 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( x + 260, 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, 280, "color", &p->clr ); y += (space+18);
+}
+
+void gui_editor_propview_create_entprops( GUI_EDITOR_PROPVIEW* view ) {
+
+}
+
+void gui_editor_propview_update( GUI_EDITOR_PROPVIEW* view ) {
+ if( !editor->map ) return;
+
+ GUI_VIEW* target = gui_get_view();
+ defer({ if( target ) gui_set_view( target ); });
+
+ gui_empty_children( view->itemview );
+ gui_set_view( view->itemview );
+ view->itemview->initheld = 1;
+
+ switch( view->seltype ) {
+ case EDITOR_SELECT_WALL: gui_editor_propview_create_wallprops( view ); break;
+ case EDITOR_SELECT_POLY: gui_editor_propview_create_polyprops( view ); break;
+ case EDITOR_SELECT_ORIGIN: gui_editor_propview_create_mapprops( view ); break;
+ case EDITOR_SELECT_ENT: gui_editor_propview_create_entprops( view ); break;
+ case EDITOR_SELECT_PVERTEX: gui_editor_propview_create_pvertexprops( view ); break;
+ case EDITOR_SELECT_SPRITE: gui_editor_propview_create_spriteprops( view ); break;
+ case EDITOR_SELECT_SURFPROPS: gui_editor_propview_create_surfprops( view ); break;
+ default: break;
+ }
+}
+
+void gui_editor_propview_get_title( GUI_EDITOR_PROPVIEW* view, char* buf ) {
+ switch( view->seltype ) {
+ case EDITOR_SELECT_NONE: sprintf( buf, "properties: " ); break;
+ case EDITOR_SELECT_POLY: sprintf( buf, "polygon properties: " ); break;
+ case EDITOR_SELECT_ORIGIN: sprintf( buf, "map [%s] properties: ", editor->map->name ); break;
+ case EDITOR_SELECT_ENT: sprintf( buf, "entity properties: " ); break;
+ case EDITOR_SELECT_SPRITE: sprintf( buf, "sprite properties: " ); break;
+ case EDITOR_SELECT_PVERTEX: sprintf( buf, "vertex properties: " ); break;
+ case EDITOR_SELECT_SURFPROPS: sprintf( buf, "surface properties: " ); break;
+ case EDITOR_SELECT_WVERTEX:
+ case EDITOR_SELECT_WALL: sprintf( buf, "wall properties: " ); break;
+ }
+}
+
+void gui_editor_propview_draw_fn( void* ptr ) {
+ if( !editor->map ) return;
+
+ GUI_EDITOR_PROPVIEW* view = (GUI_EDITOR_PROPVIEW*)ptr;
+
+ I32 x = gui_relx( view );
+ I32 y = gui_rely( view );
+ I32 w = view->w;
+ I32 h = view->h;
+
+ char title[64];
+ gui_editor_propview_get_title( view, title );
+ gui_draw_str( x, y, ALIGN_L, FNT_JPN12, ui_clr.txt, title );
+ y += PROPVIEW_TITLE_OFFSET;
+
+ CLR col = gui_is_fg_window( view )? ui_clr.border : ui_clr.border_inactive;
+ gui_draw_frect( x, y, w, h, col );
+ gui_draw_frect( x+1, y+1, w-2, h-2, ui_clr.bg_sec );
+
+ view->itemview->draw_fn( view->itemview );
+}
+
+GUI_EDITOR_PROPVIEW* gui_editor_propview( I32 x, I32 y, I32 w, I32 h ) {
+ if( !gui_check_target() ) return 0;
+
+ GUI_EDITOR_PROPVIEW* view = new GUI_EDITOR_PROPVIEW;
+ view->x = x;
+ view->y = y;
+ view->w = w;
+ view->h = h;
+ view->xbound = view->w;
+ view->ybound = view->h + PROPVIEW_TITLE_OFFSET;
+ strcpy( view->name, "EDITOR_PROP_VIEW" );
+ view->draw_fn = gui_editor_propview_draw_fn;
+ view->input_fn = gui_base_input_fn;
+
+ view->curselect = 0;
+ view->seltype = 0;
+
+ GUI_VIEW* parent = gui_get_view();
+ parent->children.push( view );
+ view->parent = parent;
+
+ gui_set_view( view );
+ view->itemview = gui_view( 0, PROPVIEW_TITLE_OFFSET, w, h );
+
+ gui_set_view( parent );
+ return view;
+}