From 86d248ed2b033fe36ce53b0387b2cbdcb69c0b72 Mon Sep 17 00:00:00 2001 From: aura Date: Tue, 28 Jul 2026 19:11:34 +0200 Subject: finish undo/redo --- src/editor/editor.cpp | 54 ++++++++++++------ src/editor/editor.h | 25 +++++++-- src/editor/properties.cpp | 127 ++++++++++++++++++++++++++----------------- src/editor/texturepicker.cpp | 3 + src/editor/view2d.cpp | 6 +- 5 files changed, 138 insertions(+), 77 deletions(-) (limited to 'src/editor') diff --git a/src/editor/editor.cpp b/src/editor/editor.cpp index 72ca4d2..2e76039 100644 --- a/src/editor/editor.cpp +++ b/src/editor/editor.cpp @@ -32,7 +32,7 @@ void editor_clear_gui_state_refs( GAME_EDITOR* e ) { e->gui.header_viewtype = 0; } -void editor_push_undo_action( GAME_EDITOR* e, const EDITOR_UNDO_ACTION& action ) { +void editor_push_undo_action( GAME_EDITOR* e, EDITOR_UNDO_ACTION action ) { if( !e ) return; @@ -267,7 +267,7 @@ void editor_undo_record_create_walls( GAME_EDITOR* e, I32 start_idx, I32 count ) return; EDITOR_UNDO_ACTION action{}; - action.type = EDITOR_UNDO_CREATE_WALLS; + action.typemask = EDITOR_UNDO_CREATE_WALLS; action.create.start_idx = start_idx; for( I32 i = 0; i < count; ++i ) action.create.walls.push( map->walls[start_idx + i] ); @@ -284,7 +284,7 @@ void editor_undo_record_create_poly( GAME_EDITOR* e, I32 start_idx ) { return; EDITOR_UNDO_ACTION action{ - .type = EDITOR_UNDO_CREATE_POLY, + .typemask = EDITOR_UNDO_CREATE_POLY, .create = { .start_idx = start_idx } }; action.create.polys.push( map->polygons[start_idx] ); @@ -301,7 +301,7 @@ void editor_undo_record_create_sprite( GAME_EDITOR* e, I32 start_idx ) { return; EDITOR_UNDO_ACTION action = { - .type = EDITOR_UNDO_CREATE_SPRITES, + .typemask = EDITOR_UNDO_CREATE_SPRITES, .create = { .start_idx = start_idx } }; @@ -319,7 +319,7 @@ void editor_undo_record_create_entity( GAME_EDITOR* e, I32 start_idx ) { return; EDITOR_UNDO_ACTION action{ - .type = EDITOR_UNDO_CREATE_ENTITIES, + .typemask = EDITOR_UNDO_CREATE_ENTITIES, .create = { .start_idx = start_idx } }; action.create.entities.push( map->entities[start_idx] ); @@ -334,7 +334,7 @@ void editor_undo_record_change_prop( GAME_EDITOR* e, FNV1A hash, void* oldv, voi if( !e || !e->map ) return; - EDITOR_UNDO_ACTION rec{ .type = EDITOR_UNDO_EDITPROPS }; + EDITOR_UNDO_ACTION rec{ .typemask = EDITOR_UNDO_EDITPROPS }; for( auto e : e->gui.props->curselect ) { EDITOR_UNDO_PROPS::CHANGES changes{}; @@ -344,16 +344,16 @@ void editor_undo_record_change_prop( GAME_EDITOR* e, FNV1A hash, void* oldv, voi rec.props.changes.push( changes ); } - e->undo_actions.push( rec ); + editor_push_undo_action( e, rec ); } -U8 editor_apply_undo_action_reverse_create( GAME_EDITOR* e, EDITOR_UNDO_ACTION& action ) { +U8 editor_apply_undo_action_reverse_create( GAME_EDITOR* e, EDITOR_UNDO_ACTION action ) { WORLD_MAP* map = e->map; U8 clear_props_select = 0; U8 clear_view_select = 0; U8 clear_view_drag = 0; - switch( action.type ) { + switch( action.typemask ) { case EDITOR_UNDO_CREATE_WALLS: { I32 count = (I32)action.create.walls.size; for( I32 i = count - 1; i >= 0; --i ) { @@ -444,7 +444,7 @@ U8 editor_apply_undo_action_reverse_create( GAME_EDITOR* e, EDITOR_UNDO_ACTION& return 1; } -U8 editor_apply_undo_action_reverse_props( GAME_EDITOR* e, EDITOR_UNDO_ACTION& action ) { +U8 editor_apply_undo_action_reverse_props( GAME_EDITOR* e, EDITOR_UNDO_ACTION action ) { EDITOR_UNDO_PROPS* c = &action.props; for( auto it : c->changes ) { @@ -464,17 +464,37 @@ U8 editor_apply_undo_action_reverse_props( GAME_EDITOR* e, EDITOR_UNDO_ACTION& a return 1; } +U8 editor_apply_undo_action_reverse_mapprop( GAME_EDITOR* e, EDITOR_UNDO_ACTION action ) { + if( !e->map ) + return 0; + + if( action.mapprop.ref.id > e->map->props.size ) { + dlog( "editor_apply_undo_action_reverse_mapprop() : warn: attempted to remove non-existent prop %x\n", action.mapprop.ref.id ); + return 0; + } + + // todo : replace with proper slots + e->map->props.erase( action.mapprop.ref.id ); + editor_update_properties_column( e ); + return 1; +} + U8 editor_apply_undo_action_reverse( GAME_EDITOR* e, EDITOR_UNDO_ACTION& action ) { if( !e || !e->map ) return 0; - if( action.type == EDITOR_UNDO_EDITPROPS ) - return editor_apply_undo_action_reverse_props( e, action ); + U8 ret = 0; + if( action.typemask & EDITOR_UNDO_EDITPROPS ) + ret |= editor_apply_undo_action_reverse_props( e, action ); + if( action.typemask & EDITOR_UNDO_CREATE_MAPPROP ) + ret |= editor_apply_undo_action_reverse_mapprop( e, action ); + if( action.typemask & EDITOR_UNDO_CREATE_EOBJ ) + ret |= editor_apply_undo_action_reverse_create( e, action ); - return editor_apply_undo_action_reverse_create( e, action ); + return ret; } -U8 editor_apply_undo_action_forward_props( GAME_EDITOR* e, EDITOR_UNDO_ACTION& action ) { +U8 editor_apply_undo_action_forward_props( GAME_EDITOR* e, EDITOR_UNDO_ACTION action ) { EDITOR_UNDO_PROPS* c = &action.props; for( auto it : c->changes ) { @@ -494,9 +514,9 @@ U8 editor_apply_undo_action_forward_props( GAME_EDITOR* e, EDITOR_UNDO_ACTION& a return 1; } -U8 editor_apply_undo_action_forward_create( GAME_EDITOR* e, EDITOR_UNDO_ACTION& action ) { +U8 editor_apply_undo_action_forward_create( GAME_EDITOR* e, EDITOR_UNDO_ACTION action ) { WORLD_MAP* map = e->map; - switch( action.type ) { + switch( action.typemask ) { case EDITOR_UNDO_CREATE_WALLS: { if( !action.create.walls.size ) return 0; @@ -542,7 +562,7 @@ U8 editor_apply_undo_action_forward( GAME_EDITOR* e, EDITOR_UNDO_ACTION& action if( !e || !e->map ) return 0; - if( action.type == EDITOR_UNDO_EDITPROPS ) + if( action.typemask == EDITOR_UNDO_EDITPROPS ) return editor_apply_undo_action_forward_props( e, action ); return editor_apply_undo_action_forward_create( e, action ); diff --git a/src/editor/editor.h b/src/editor/editor.h index b506d9c..3d27951 100644 --- a/src/editor/editor.h +++ b/src/editor/editor.h @@ -36,11 +36,16 @@ enum EditorSelectType_t { enum EditorActionType_t { EDITOR_UNDO_NONE = 0, - EDITOR_UNDO_CREATE_WALLS = 1, - EDITOR_UNDO_CREATE_POLY = 2, - EDITOR_UNDO_CREATE_SPRITES = 3, - EDITOR_UNDO_CREATE_ENTITIES = 4, - EDITOR_UNDO_EDITPROPS = 5 + EDITOR_UNDO_CREATE_WALLS = 1 << 1, + EDITOR_UNDO_CREATE_POLY = 1 << 2, + EDITOR_UNDO_CREATE_SPRITES = 1 << 3, + EDITOR_UNDO_CREATE_ENTITIES = 1 << 4, + EDITOR_UNDO_EDITPROPS = 1 << 5, + EDITOR_UNDO_CREATE_MAPPROP = 1 << 6, + + + + EDITOR_UNDO_CREATE_EOBJ = EDITOR_UNDO_CREATE_WALLS | EDITOR_UNDO_CREATE_POLY | EDITOR_UNDO_CREATE_SPRITES | EDITOR_UNDO_CREATE_ENTITIES, }; enum EditorInfoBoxType_t { @@ -140,10 +145,15 @@ struct EDITOR_UNDO_CREATE { LIST entities{}; }; +struct EDITOR_UNDO_MAPPROP { + MAP_PROPREF ref; +}; + struct EDITOR_UNDO_ACTION { - U8 type; + U64 typemask; EDITOR_UNDO_PROPS props; EDITOR_UNDO_CREATE create; + EDITOR_UNDO_MAPPROP mapprop; }; struct GAME_EDITOR { @@ -247,6 +257,7 @@ extern LIST* editor_get_map_list( GAME_EDITOR* e ); extern void editor_load_map_cb( void* ); extern void editor_new_map_cb( void* ); +extern void editor_push_undo_action( GAME_EDITOR* e, EDITOR_UNDO_ACTION action ); extern void editor_create_map_view( GAME_EDITOR* e ); extern void editor_update_properties_column( GAME_EDITOR* e ); extern const char* editor_tool_name(); @@ -317,6 +328,7 @@ struct GUI_EDITOR_PROPVIEW : GUI_VIEW { LIST curselect; LIST curprops; GUI_VIEW* itemview; + EDITOR_UNDO_ACTION pending_undo; }; struct GUI_EDITOR_TOOLVIEW : GUI_VIEW { @@ -348,6 +360,7 @@ struct GUI_EDITOR_TEXTUREPICKER : GUI_WINDOW { GUI_LABEL* densitylabel; GUI_CALLBACK cb; + GUI_CALLBACK pre_cb; void* cbextra; }; 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* list = ( LIST* )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 ); diff --git a/src/editor/texturepicker.cpp b/src/editor/texturepicker.cpp index 621f0c2..1152ef7 100644 --- a/src/editor/texturepicker.cpp +++ b/src/editor/texturepicker.cpp @@ -192,6 +192,9 @@ void gui_editor_textureview_accept( GUI_EDITOR_TEXTUREPICKER* wnd ) { gl_texture_destroy( _gui.batch->gl, tex ); } ); + if( wnd->pre_cb ) + wnd->pre_cb( wnd ); + if( !isnone ) { if( map_add_texture_ref( editor->map, wnd->curselect ) == STAT_ALREADYEXISTS ) { const char* name = assets_abspath( wnd->curselect->name ); diff --git a/src/editor/view2d.cpp b/src/editor/view2d.cpp index cca83d1..fe82c08 100644 --- a/src/editor/view2d.cpp +++ b/src/editor/view2d.cpp @@ -1047,8 +1047,8 @@ void gui_editor_2dview_input_select_ondrop( GUI_EDITOR_2DVIEW* view ) { gui_editor_propview_select( editor->gui.props, view->curdrag, view->dragtype, !input.keys[SDL_SCANCODE_LCTRL] ); if( view->pending_undo_props.changes.size ) { - EDITOR_UNDO_ACTION rec{ .type = EDITOR_UNDO_EDITPROPS, .props = view->pending_undo_props }; - editor->undo_actions.push( rec ); + EDITOR_UNDO_ACTION rec{ .typemask = EDITOR_UNDO_EDITPROPS, .props = view->pending_undo_props }; + editor_push_undo_action( editor, rec ); view->pending_undo_props = {}; } @@ -1109,7 +1109,7 @@ void gui_editor_2dview_input_select_drag( GUI_EDITOR_2DVIEW* view ) { return; } - EDITOR_UNDO_ACTION rec{ .type = EDITOR_UNDO_EDITPROPS }; + EDITOR_UNDO_ACTION rec{ .typemask = EDITOR_UNDO_EDITPROPS }; EDITOR_UNDO_PROPS::CHANGES changes{ .obj = (EOBJECT*)view->curdrag }; if( !gui_editor_2dview_input_select_drag_obj( view, view->curdrag, view->dragtype ) ) { view->oldmx = mx; -- cgit v1.2.3