diff options
| author | aura <nw@moneybot.cc> | 2026-07-28 19:11:34 +0200 |
|---|---|---|
| committer | aura <nw@moneybot.cc> | 2026-07-28 19:11:34 +0200 |
| commit | 86d248ed2b033fe36ce53b0387b2cbdcb69c0b72 (patch) | |
| tree | a70f32a0f44b927a6d137998efa405e330689c0f /src/editor/properties.cpp | |
| parent | 468813b133a6a3ff0b85d3b34f1009cfeae815e4 (diff) | |
finish undo/redo
Diffstat (limited to 'src/editor/properties.cpp')
| -rw-r--r-- | src/editor/properties.cpp | 127 |
1 files changed, 76 insertions, 51 deletions
diff --git a/src/editor/properties.cpp b/src/editor/properties.cpp index 109e622..dc2233d 100644 --- a/src/editor/properties.cpp +++ b/src/editor/properties.cpp @@ -112,7 +112,6 @@ U8 gui_editor_propview_is_selected( GUI_EDITOR_PROPVIEW *e, void *what, U8 selty void gui_editor_propview_sync_props_value( GUI_EDITOR_PROPVIEW* view, EDITOR_PROP* prop ) { void* valuep = eprop_ptr( prop ); - EDITOR_UNDO_ACTION rec{ .type = EDITOR_UNDO_EDITPROPS }; for( auto& it : view->curselect ) { EOBJECT* eobj = (EOBJECT*)it.obj; EDITOR_PROP* otherp = eprop_from_name( eobj, prop->displayname ); @@ -121,26 +120,19 @@ void gui_editor_propview_sync_props_value( GUI_EDITOR_PROPVIEW* view, EDITOR_PRO if( otherp && otherp->type == prop->type ) { void* targetp = eprop_ptr( otherp ); if( targetp != valuep ) { - EDITOR_UNDO_PROPS::CHANGES changes; void* oldval = alloca( prop->size ); memcpy( oldval, targetp, prop->size ); memcpy( targetp, valuep, prop->size ); - - changes.props.push( { prop->hash, prop->size, oldval, targetp } ); - changes.obj = eobj; - rec.props.changes.push( changes ); } } } - - if( rec.props.changes.size ) - editor->undo_actions.push( rec ); } 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; } ); + FNV1A hash = fnv1a( propname ); + EDITOR_PROP** pptr = view->curprops.where( fn( EDITOR_PROP** pptr ) { return (*pptr)->hash == hash; } ); if( !pptr ) return; @@ -151,7 +143,6 @@ void gui_editor_propview_sync_props_fdiff( GUI_EDITOR_PROPVIEW* view, EDITOR_PRO if( !fdiff ) return; - EDITOR_UNDO_ACTION rec{ .type = EDITOR_UNDO_EDITPROPS }; for( auto& it : view->curselect ) { EOBJECT* eobj = (EOBJECT*)it.obj; EDITOR_PROP* otherp = eprop_from_name( eobj, prop->displayname ); @@ -162,21 +153,10 @@ void gui_editor_propview_sync_props_fdiff( GUI_EDITOR_PROPVIEW* view, EDITOR_PRO if( targetp == eprop_ptr( prop ) ) continue; - EDITOR_UNDO_PROPS::CHANGES changes; - F32* oldval = (F32*)alloca( prop->size ); - memcpy( oldval, targetp, prop->size ); - for( U32 i = 0; i < valc; ++i ) targetp[i] += fdiff[i]; - - changes.props.push( { prop->hash, prop->size, oldval, targetp } ); - changes.obj = eobj; - rec.props.changes.push( changes ); } } - - if( rec.props.changes.size ) - editor->undo_actions.push( rec ); } void gui_editor_propview_sync_props_fdiff( GUI_EDITOR_PROPVIEW* view, const char* propname, F32* fdiff, U32 valc ) { @@ -188,6 +168,54 @@ void gui_editor_propview_sync_props_fdiff( GUI_EDITOR_PROPVIEW* view, const char gui_editor_propview_sync_props_fdiff( view, *pptr, fdiff, valc ); } +void gui_editor_propview_undo_eprop_start( GUI_EDITOR_PROPVIEW* view, EDITOR_PROP* prop ) { + view->pending_undo.typemask |= EDITOR_UNDO_EDITPROPS; + for( auto& it : view->curselect ) { + EDITOR_PROP* tprop = eprop_from_hash( (EOBJECT*)it.obj, prop->hash ); + if( !tprop ) continue; + + EDITOR_UNDO_PROPS* undo_props = &view->pending_undo.props; + EDITOR_UNDO_PROPS::CHANGES* change = undo_props->changes.where( fn( EDITOR_UNDO_PROPS::CHANGES* v ) { + return v->obj == (EOBJECT*)it.obj; + } ); + + if( !change ) { + change = undo_props->changes.push( { .obj = (EOBJECT*)it.obj } ); + } + + EDITOR_UNDO_PROPS::PROP_VALUE* propv = change->props.where( fn( EDITOR_UNDO_PROPS::PROP_VALUE* v ) { + return v->hash == prop->hash; + } ); + + if( propv ) { + continue; + } + + propv = change->props.push( { tprop->hash, tprop->size } ); + memcpy( propv->oldval.data, eprop_ptr( tprop ), tprop->size ); + } +} + +void gui_editor_propview_undo_mapprop( GUI_EDITOR_PROPVIEW* view, EDITOR_PROP* prop ) { + view->pending_undo.typemask |= EDITOR_UNDO_CREATE_MAPPROP; + view->pending_undo.mapprop.ref = *(MAP_PROPREF*)eprop_ptr( prop ); +} + +void gui_editor_propview_undo_commit( GUI_EDITOR_PROPVIEW* view ) { + for( auto& it : view->pending_undo.props.changes ) { + EOBJECT* obj = it.obj; + for( auto& it2 : it.props ) { + EDITOR_PROP* tprop = eprop_from_hash( obj, it2.hash ); + if( !tprop ) continue; + + memcpy( it2.newval.data, eprop_ptr( tprop ), tprop->size ); + } + } + + editor_push_undo_action( editor, view->pending_undo ); + view->pending_undo = {}; +} + // todo : int diff struct TEXBTN_CB { @@ -211,26 +239,22 @@ void gui_editor_propview_create_eobj_prop( GUI_EDITOR_PROPVIEW* view, EDITOR_PRO switch( prop->type ) { case EPROP_F32: { GUI_FLOATINPUT* in = gui_floatinput( *x, *y, w, n, (F32*)eprop_ptr( prop ), min, max, step ); in->drawval = val; - 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; + in->pre_cb = cfn( void* ) { gui_editor_propview_undo_eprop_start( view, prop ); }; + in->cb = cfn( void* ) { gui_editor_propview_sync_props_fdiff( editor->gui.props, prop, &in->lastchange, 1 ); }; + in->release_cb = cfn( void* ) { gui_editor_propview_undo_commit( editor->gui.props ); }; *y += (s+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", val ); - 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; - + in->pre_cb = cfn( void* ) { gui_editor_propview_undo_eprop_start( view, prop ); }; + in->cb = cfn( void* ) { gui_editor_propview_sync_props_fdiff( editor->gui.props, prop, in->lastchange.data, in->inputs.size ); }; + in->release_cb = cfn( void* ) { gui_editor_propview_undo_commit( editor->gui.props ); }; *y += (s+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; + case EPROP_CLR: { GUI_COLORINPUT* in = gui_colorinput( *x, *y, w, n, (CLR*)eprop_ptr( prop ) ); + in->pre_cb = cfn( void* ) { gui_editor_propview_undo_eprop_start( view, prop ); }; + in->cb = cfn( void* ) { gui_editor_propview_sync_props_fdiff( editor->gui.props, prop, in->lastchange.data, in->inputs.size ); }; + in->release_cb = cfn( void* ) { gui_editor_propview_undo_commit( editor->gui.props ); }; *y += (s+18); }break; case EPROP_MAPPROP: { @@ -239,18 +263,19 @@ void gui_editor_propview_create_eobj_prop( GUI_EDITOR_PROPVIEW* view, EDITOR_PRO if( val ) gui_label( *x, *y, "prop id: %d", *ref ); else gui_label( *x, *y, "prop id: *" ); - GUI_BUTTON* newprop = gui_button( action2_x, *y, 20, 20, "+", pfn( void* ptr ) { - GUI_BUTTON* btn = (GUI_BUTTON*)ptr; + gui_button( action2_x, *y, 20, 20, "+", cfn( void* ) { 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* ref = (MAP_PROPREF*)eprop_ptr( prop ); + gui_editor_propview_undo_eprop_start( view, prop ); (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_undo_mapprop( view, prop ); + gui_editor_propview_sync_props_value( editor->gui.props, prop ); + gui_editor_propview_undo_commit( view ); gui_editor_propview_update( editor->gui.props ); - } ); newprop->extra = prop; + } ); if( val ) { GUI_BUTTON* goprop = gui_button( action_x, *y, 20, 20, "\x1A", pfn( void* ptr ) { @@ -265,16 +290,15 @@ void gui_editor_propview_create_eobj_prop( GUI_EDITOR_PROPVIEW* view, EDITOR_PRO if( val && *tex ) gui_label( *x, *y, "%s: %s", n, (*tex)->name ); else if( !val ) gui_label( *x, *y, "%s: *", n ); else gui_label( *x, *y, "%s: none", n ); - 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* p ) { - GUI_EDITOR_TEXTUREPICKER* picker = (GUI_EDITOR_TEXTUREPICKER*)p; - gui_editor_propview_sync_props_value( editor->gui.props, (EDITOR_PROP*)picker->cbextra ); + gui_button( action_x, *y, 20, 20, "\x1A", cfn( void* ptr ) { + GUI_EDITOR_TEXTUREPICKER* picker = gui_editor_texturepicker( 200, 100, 400, 400, tex ); + picker->pre_cb = cfn( void* ) { gui_editor_propview_undo_eprop_start( view, prop ); }; + picker->cb = cfn( void* p ) { + gui_editor_propview_sync_props_value( editor->gui.props, prop ); + gui_editor_propview_undo_commit( view ); gui_editor_propview_update( editor->gui.props ); - }; picker->cbextra = prop; - } ); btn->extra = tex; *y += s; + }; + } ); *y += s; } break; case EPROP_VERTEX_LIST: { LIST<MAP_VERTEX>* list = ( LIST<MAP_VERTEX>* )eprop_ptr( prop ); @@ -612,6 +636,7 @@ GUI_EDITOR_PROPVIEW* gui_editor_propview( I32 x, I32 y, I32 w, I32 h ) { view->input_fn = gui_base_input_fn; view->curselect = {}; + view->pending_undo = {}; GUI_VIEW* parent = gui_get_view(); parent->children.push( view ); |
