summaryrefslogtreecommitdiff
path: root/src/editor/properties.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/editor/properties.cpp')
-rw-r--r--src/editor/properties.cpp221
1 files changed, 184 insertions, 37 deletions
diff --git a/src/editor/properties.cpp b/src/editor/properties.cpp
index c9eb991..0cc0e56 100644
--- a/src/editor/properties.cpp
+++ b/src/editor/properties.cpp
@@ -45,30 +45,106 @@ I32 propview_action2_x( GUI_EDITOR_PROPVIEW* view ) {
);
}
-void gui_editor_propview_select( GUI_EDITOR_PROPVIEW* view, void* what, U8 seltype ) {
+void gui_editor_propview_select( GUI_EDITOR_PROPVIEW* view, void* what, U8 seltype, U8 clearall ) {
+ using PROPSELECT = GUI_EDITOR_PROPVIEW::PROPVIEW_SELECT;
if( !editor->map )
return;
+ view->curprops.clear();
+ if( clearall )
+ view->curselect.clear();
+
+ PROPSELECT sel{
+ .obj = what,
+ .seltype = seltype
+ };
+
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 );
+ return gui_editor_propview_select( view, editor->map, EDITOR_SELECT_ORIGIN, 1 );
- view->curselect = s;
- view->seltype = EDITOR_SELECT_WALL;
- return gui_editor_propview_update( view );
+ sel.obj = s;
+ sel.seltype = EDITOR_SELECT_WALL;
}
- view->curselect = what;
- view->seltype = seltype;
+ if( view->curselect.idx_where( fn( PROPSELECT* p ) { return p->obj == sel.obj; } ) != -1 )
+ return;
+
+ view->curselect.push( sel );
gui_editor_propview_update( view );
}
+U8 gui_editor_propview_is_selected( GUI_EDITOR_PROPVIEW *e, void *what, U8 seltype ) {
+ for( auto& it : e->curselect ) {
+ if( it.obj == what && it.seltype == seltype )
+ return 1;
+ }
+ return 0;
+}
+
+void gui_editor_propview_sync_props_value( GUI_EDITOR_PROPVIEW* view, EDITOR_PROP* prop ) {
+ void* valuep = eprop_ptr( prop );
+ for( auto& it : view->curselect ) {
+ EOBJECT* eobj = (EOBJECT*)it.obj;
+ EDITOR_PROP* otherp = eprop_from_name( eobj, prop->displayname );
+ if( otherp == prop ) continue;
+
+ if( otherp && otherp->type == prop->type ) {
+ void* targetp = eprop_ptr( otherp );
+ if( targetp != valuep )
+ memcpy( targetp, valuep, prop->size );
+ }
+ }
+}
+
+void gui_editor_propview_sync_props_value( GUI_EDITOR_PROPVIEW* view, const char* propname ) {
+ if( view->curselect.size < 2 ) return;
+ EDITOR_PROP** pptr = view->curprops.where( fn( EDITOR_PROP** pptr ) { return (*pptr)->displayname == propname; } );
+ if( !pptr )
+ return;
+ gui_editor_propview_sync_props_value( view, *pptr );
+}
+
+void gui_editor_propview_sync_props_fdiff( GUI_EDITOR_PROPVIEW* view, EDITOR_PROP* prop, F32* fdiff, U32 valc ) {
+ for( auto& it : view->curselect ) {
+ EOBJECT* eobj = (EOBJECT*)it.obj;
+ EDITOR_PROP* otherp = eprop_from_name( eobj, prop->displayname );
+ if( otherp == prop ) continue;
+
+ if( otherp && otherp->type == prop->type ) {
+ F32* targetp = (F32*)eprop_ptr( otherp );
+ if( targetp == eprop_ptr( prop ) )
+ continue;
+
+ for( U32 i = 0; i < valc; ++i )
+ targetp[i] += fdiff[i];
+ }
+ }
+}
+
+void gui_editor_propview_sync_props_fdiff( GUI_EDITOR_PROPVIEW* view, const char* propname, F32* fdiff, U32 valc ) {
+ if( view->curselect.size < 2 ) return;
+ EDITOR_PROP** pptr = view->curprops.where( fn( EDITOR_PROP** pptr ) { return (*pptr)->displayname == propname; } );
+ if( !pptr )
+ return;
+
+ gui_editor_propview_sync_props_fdiff( view, *pptr, fdiff, valc );
+}
+
+// todo : int diff
+
+struct TEXBTN_CB {
+ EDITOR_PROP* prop;
+ GL_TEX2D** texp;
+};
+
+void gui_editor_propview_create_eobj_prop_ro( GUI_EDITOR_PROPVIEW* view, EDITOR_PROP* prop, I32* x, I32* y, I32 w, I32 space );
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 );
@@ -82,11 +158,29 @@ void gui_editor_propview_create_eobj_prop( GUI_EDITOR_PROPVIEW* view, EDITOR_PRO
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_F32: { GUI_FLOATINPUT* in = gui_floatinput( *x, *y, w, n, (F32*)eprop_ptr( prop ), min, max, step );
+ in->cb = pfn( void* ptr ) {
+ GUI_FLOATINPUT* fin = (GUI_FLOATINPUT*)ptr;
+ gui_editor_propview_sync_props_fdiff( editor->gui.props, (EDITOR_PROP*)fin->cbextra, &fin->lastchange, 1 );
+ }; in->cbextra = prop;
+ *y += (space+18);
+ } break;
+ case EPROP_VEC2: case EPROP_VEC3: case EPROP_VEC4: { U32 c = prop->type - EPROP_VEC2 + 2;
+ GUI_VECTORINPUT* in = gui_vectorinput( *x, *y, w, n, (F32*)eprop_ptr( prop ), c, min, max, step, "xyzw", c == 2 ? "%.03f" : "%0.02f" );
+ in->cb = pfn( void* ptr ) {
+ GUI_VECTORINPUT* vin = (GUI_VECTORINPUT*)ptr;
+ gui_editor_propview_sync_props_fdiff( editor->gui.props, (EDITOR_PROP*)vin->cbextra, vin->lastchange.data, vin->inputs.size );
+ }; in->cbextra = prop;
+
+ *y += (space+18);
+ } break;
+ case EPROP_CLR: { GUI_COLORINPUT* cin = gui_colorinput( *x, *y, w, n, (CLR*)eprop_ptr( prop ) );
+ cin->cb = pfn( void* ptr ) {
+ GUI_COLORINPUT* cin = (GUI_COLORINPUT*)ptr;
+ gui_editor_propview_sync_props_fdiff( editor->gui.props, (EDITOR_PROP*)cin->cbextra, cin->lastchange.data, cin->inputs.size );
+ }; cin->cbextra = 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 );
@@ -96,11 +190,14 @@ void gui_editor_propview_create_eobj_prop( GUI_EDITOR_PROPVIEW* view, EDITOR_PRO
GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
SURF_PROPS props{ .tex = 0, .clr = CLR::WHITE() };
editor->map->props.push( props );
+ EDITOR_PROP* eprop = (EDITOR_PROP*)btn->extra;
+ MAP_PROPREF* ref = (MAP_PROPREF*)eprop_ptr( eprop );
- ((MAP_PROPREF*)btn->extra)->id = editor->map->props.size - 1;
+ (ref)->id = editor->map->props.size - 1;
editor->gui.assets_scroll = ( editor->map->props.size + 1 ) * 28;
+ gui_editor_propview_sync_props_value( editor->gui.props, eprop );
gui_editor_propview_update( editor->gui.props );
- } ); newprop->extra = ref;
+ } ); newprop->extra = prop;
GUI_BUTTON* goprop = gui_button( action_x, *y, 20, 20, "\x1A", pfn( void* ptr ) {
GUI_BUTTON* btn = (GUI_BUTTON*)ptr;
@@ -113,11 +210,15 @@ void gui_editor_propview_create_eobj_prop( GUI_EDITOR_PROPVIEW* view, EDITOR_PRO
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( action_x, *y, 20, 20, "\x1A", cfn( 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 ); };
+ picker->cb = pfn( void* p ) {
+ GUI_EDITOR_TEXTUREPICKER* picker = (GUI_EDITOR_TEXTUREPICKER*)p;
+ gui_editor_propview_sync_props_value( editor->gui.props, (EDITOR_PROP*)picker->cbextra );
+ gui_editor_propview_update( editor->gui.props );
+ }; picker->cbextra = prop;
} ); btn->extra = tex; *y += space;
} break;
case EPROP_VERTEX_LIST: {
@@ -132,7 +233,7 @@ void gui_editor_propview_create_eobj_prop( GUI_EDITOR_PROPVIEW* view, EDITOR_PRO
} ); btn->extra = v; *y += space;
}
} break;
- default: break;
+ default: return gui_editor_propview_create_eobj_prop_ro( view, prop, x, y, w, space ); break;
}
}
@@ -152,6 +253,7 @@ void gui_editor_propview_create_eobj_prop_ro( GUI_EDITOR_PROPVIEW* view, EDITOR_
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;
+ default: str += STR("UNIMPL_TYPE : ") + to_str( prop->type ); return;
}
str += "]";
@@ -172,7 +274,7 @@ void gui_editor_propview_create_eobj_props( GUI_EDITOR_PROPVIEW* view, EOBJECT*
}
void gui_editor_propview_create_wallprops( GUI_EDITOR_PROPVIEW* view ) {
- MAP_WALL* s = (MAP_WALL*)view->curselect;
+ MAP_WALL* s = (MAP_WALL*)view->curselect.data[0].obj;
WORLD_MAP* m = editor->map;
I32 x = 10, y = 10;
@@ -187,7 +289,7 @@ void gui_editor_propview_create_wallprops( GUI_EDITOR_PROPVIEW* view ) {
}
void gui_editor_propview_create_polyprops( GUI_EDITOR_PROPVIEW* view ) {
- MAP_POLYGON* p = (MAP_POLYGON*)view->curselect;
+ MAP_POLYGON* p = (MAP_POLYGON*)view->curselect.data[0].obj;
WORLD_MAP* m = editor->map;
I32 x = 10, y = 10;
I32 space = 20;
@@ -201,7 +303,7 @@ void gui_editor_propview_create_polyprops( GUI_EDITOR_PROPVIEW* view ) {
}
void gui_editor_propview_create_mapprops( GUI_EDITOR_PROPVIEW* view ) {
- WORLD_MAP* m = (WORLD_MAP*)view->curselect;
+ WORLD_MAP* m = (WORLD_MAP*)view->curselect.data[0].obj;
I32 x = 10, y = 10;
I32 space = 20;
@@ -236,7 +338,7 @@ void gui_editor_propview_create_mapprops( GUI_EDITOR_PROPVIEW* view ) {
}
void gui_editor_propview_create_pvertexprops( GUI_EDITOR_PROPVIEW* view ) {
- MAP_VERTEX* v = (MAP_VERTEX*)view->curselect;
+ MAP_VERTEX* v = (MAP_VERTEX*)view->curselect.data[0].obj;
WORLD_MAP* m = editor->map;
I32 x = 10, y = 10;
@@ -254,7 +356,7 @@ void gui_editor_propview_create_pvertexprops( GUI_EDITOR_PROPVIEW* view ) {
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;
+ MAP_VERTEX* v = (MAP_VERTEX*)view->curselect.data[0].obj;
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); } );
@@ -270,7 +372,7 @@ void gui_editor_propview_create_pvertexprops( GUI_EDITOR_PROPVIEW* view ) {
void gui_editor_propview_create_spriteprops( GUI_EDITOR_PROPVIEW* view ) {
- MAP_SPRITE* s = (MAP_SPRITE*)view->curselect;
+ MAP_SPRITE* s = (MAP_SPRITE*)view->curselect.data[0].obj;
WORLD_MAP* m = editor->map;
I32 x = 10, y = 10;
@@ -285,7 +387,7 @@ void gui_editor_propview_create_spriteprops( GUI_EDITOR_PROPVIEW* view ) {
}
void gui_editor_propview_create_surfprops( GUI_EDITOR_PROPVIEW* view ) {
- SURF_PROPS* p = (SURF_PROPS*)view->curselect;
+ SURF_PROPS* p = (SURF_PROPS*)view->curselect.data[0].obj;
WORLD_MAP* m = editor->map;
I32 x = 10, y = 10;
@@ -300,7 +402,7 @@ void gui_editor_propview_create_surfprops( GUI_EDITOR_PROPVIEW* view ) {
}
void gui_editor_propview_create_entprops( GUI_EDITOR_PROPVIEW* view ) {
- MAP_ENTITY* e = (MAP_ENTITY*)view->curselect;
+ MAP_ENTITY* e = (MAP_ENTITY*)view->curselect.data[0].obj;
WORLD_MAP* m = editor->map;
I32 x = 10, y = 10;
@@ -317,6 +419,41 @@ void gui_editor_propview_create_entprops( GUI_EDITOR_PROPVIEW* view ) {
gui_vectorinput( x, y, propview_input_width( view ), "position", (F32*)&e->pos, 3, -INFINITY, INFINITY, step ); y += (space+18);
}
+void gui_editor_propview_filter_props( GUI_EDITOR_PROPVIEW* view ) {
+ if( view->curselect.size < 2 ) return view->curprops.clear();
+
+ EOBJECT* first = (EOBJECT*)view->curselect.data[0].obj;
+ for( auto& it : first->eprops ) {
+ U8 add = 1;
+ EDITOR_PROP* prop = eprop_from_ref( first, it );
+ for( U32 i = 1; i < view->curselect.size; ++i ) {
+ EOBJECT* obj = (EOBJECT*)view->curselect.data[i].obj;
+ if( !eprop_from_name( obj, prop->displayname ) ) {
+ add = 0;
+ break;
+ }
+ }
+
+ if( add )
+ view->curprops.push( prop );
+ }
+}
+
+void gui_editor_propview_create_groupprops( GUI_EDITOR_PROPVIEW* view ) {
+ if( !view->curprops.size )
+ gui_editor_propview_filter_props( view );
+
+ I32 x = 10, y = 10, w = propview_input_width( view );
+ U32 space = 20;
+
+ for( auto& it : view->curprops ) {
+ if( it->readonly )
+ gui_editor_propview_create_eobj_prop_ro( view, it, &x, &y, w, space );
+ else
+ gui_editor_propview_create_eobj_prop( view, it, &x, &y, w, space );
+ }
+}
+
void gui_editor_propview_update( GUI_EDITOR_PROPVIEW* view ) {
if( !editor->map ) return;
@@ -327,20 +464,31 @@ void gui_editor_propview_update( GUI_EDITOR_PROPVIEW* view ) {
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;
+ if( !view->curselect.size )
+ return;
+
+ if( view->curselect.size > 1 ) {
+ gui_editor_propview_create_groupprops( view );
+ } else {
+ switch( view->curselect.data->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 ) {
+ if( view->curselect.size > 1 ) {
+ sprintf( buf, "group properties" ); return;
+ }
+
+ switch( view->curselect.data->seltype ) {
case EDITOR_SELECT_NONE: sprintf( buf, "properties" ); break;
case EDITOR_SELECT_POLY: sprintf( buf, "polygon properties" ); break;
case EDITOR_SELECT_ORIGIN: sprintf( buf, "properties" ); break;
@@ -389,8 +537,7 @@ GUI_EDITOR_PROPVIEW* gui_editor_propview( I32 x, I32 y, I32 w, I32 h ) {
view->draw_fn = gui_editor_propview_draw_fn;
view->input_fn = gui_base_input_fn;
- view->curselect = 0;
- view->seltype = 0;
+ view->curselect = {};
GUI_VIEW* parent = gui_get_view();
parent->children.push( view );