diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/editor/editor.cpp | 54 | ||||
| -rw-r--r-- | src/editor/editor.h | 25 | ||||
| -rw-r--r-- | src/editor/properties.cpp | 127 | ||||
| -rw-r--r-- | src/editor/texturepicker.cpp | 3 | ||||
| -rw-r--r-- | src/editor/view2d.cpp | 6 | ||||
| -rw-r--r-- | src/game.cpp | 6 | ||||
| -rw-r--r-- | src/gui/base.h | 9 | ||||
| -rw-r--r-- | src/gui/button.cpp | 6 | ||||
| -rw-r--r-- | src/gui/checkbox.cpp | 4 | ||||
| -rw-r--r-- | src/gui/floatinput.cpp | 53 | ||||
| -rw-r--r-- | src/gui/list.cpp | 6 | ||||
| -rw-r--r-- | src/gui/textbox.cpp | 10 | ||||
| -rw-r--r-- | src/gui/vectorinput.cpp | 17 | ||||
| -rw-r--r-- | src/render/gl.cpp | 9 | ||||
| -rw-r--r-- | src/util/allocator.h | 1 | ||||
| -rw-r--r-- | src/util/typedef.h | 2 |
16 files changed, 225 insertions, 113 deletions
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<MAP_ENTITY> 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<GUI_LIST_ENTRY>* 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<PROPVIEW_SELECT> curselect; LIST<EDITOR_PROP*> 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<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 ); 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; diff --git a/src/game.cpp b/src/game.cpp index 523e884..7b526ae 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -224,6 +224,12 @@ void game_on_tick( GAME_DATA* game ) { _profiled } void game_destroy( GAME_DATA *game ) { +#if IS_EDITOR + editor_destroy( game->editor ); +#endif + if( game->state.map ) + map_free( game, game->state.map ); + gl_batch_destroy( game->render.batch_2d ); gl_batch_destroy( game->render.batch_3d ); gl_destroy( game->gl ); diff --git a/src/gui/base.h b/src/gui/base.h index 1a1c4cb..108988d 100644 --- a/src/gui/base.h +++ b/src/gui/base.h @@ -169,10 +169,12 @@ struct GUI_LIST : GUI_BASE { U8 held; GUI_CALLBACK cb; + GUI_CALLBACK pre_cb; }; struct GUI_BUTTON : GUI_BASE { GUI_CALLBACK cb; + GUI_CALLBACK pre_cb; U8 held; void* extra; }; @@ -182,6 +184,7 @@ struct GUI_CHECKBOX : GUI_BASE { U8* pval; GUI_CALLBACK cb; + GUI_CALLBACK pre_cb; }; struct GUI_DROPDOWN : GUI_BASE { @@ -190,6 +193,7 @@ struct GUI_DROPDOWN : GUI_BASE { U8 held; GUI_CALLBACK cb; + GUI_CALLBACK pre_cb; GUI_WINDOW* listwnd; GUI_VIEW* listview; }; @@ -216,6 +220,7 @@ struct GUI_TEXTBOX : GUI_BASE { U8 m1held; GUI_CALLBACK cb; + GUI_CALLBACK pre_cb; }; struct GUI_CONTEXTBOX : GUI_BASE { @@ -243,6 +248,8 @@ struct GUI_FLOATINPUT : GUI_BASE { U8 wraparound; GUI_CALLBACK cb; + GUI_CALLBACK pre_cb; + GUI_CALLBACK release_cb; void* cbextra; }; @@ -261,6 +268,8 @@ struct GUI_VECTORINPUT : GUI_VIEW { LIST<F32> lastchange; GUI_CALLBACK cb; + GUI_CALLBACK pre_cb; + GUI_CALLBACK release_cb; void* cbextra; }; diff --git a/src/gui/button.cpp b/src/gui/button.cpp index e66130b..7cf0524 100644 --- a/src/gui/button.cpp +++ b/src/gui/button.cpp @@ -48,8 +48,10 @@ void gui_button_input_fn( void* ptr ) { // button could be destroyed by callback U8 was_held = btn->held; btn->held = 0; - if( inbounds && was_held ) - btn->cb( btn ); + if( inbounds && was_held ) { + if( btn->pre_cb ) btn->pre_cb( btn ); + if( btn->cb ) btn->cb( btn ); + } return; } diff --git a/src/gui/checkbox.cpp b/src/gui/checkbox.cpp index 02cadc6..97ce804 100644 --- a/src/gui/checkbox.cpp +++ b/src/gui/checkbox.cpp @@ -40,9 +40,9 @@ void gui_checkbox_input_fn( void* ptr ) { U8 was_held = check->held; check->held = 0; if( inbounds && was_held ) { + if( check->pre_cb ) check->pre_cb( check ); *check->pval = !*check->pval; - if( check->cb ) - check->cb( check ); + if( check->cb ) check->cb( check ); } return; diff --git a/src/gui/floatinput.cpp b/src/gui/floatinput.cpp index 095c562..8e3fc2c 100644 --- a/src/gui/floatinput.cpp +++ b/src/gui/floatinput.cpp @@ -169,6 +169,7 @@ void gui_floatinput_input_bound( GUI_FLOATINPUT* input ) { return; F32 oldval = *input->pval; + F32 val = oldval; I32 x = gui_relx( input ); I32 w = gui_floatinput_content_w( input ); @@ -184,9 +185,13 @@ void gui_floatinput_input_bound( GUI_FLOATINPUT* input ) { F32 nval = min + (max - min) * progress; F32 rmn = remainderf( nval, input->step ); - *input->pval = nval - rmn; - if( oldval != *input->pval ) - input->lastchange = *input->pval - oldval; + val = nval - rmn; + if( oldval != val ) { + if( input->pre_cb ) input->pre_cb( input ); + input->lastchange = val - oldval; + *input->pval = val; + if( input->cb ) input->cb( input ); + } } void gui_floatinput_input_unbound( GUI_FLOATINPUT* input ) { @@ -197,22 +202,28 @@ void gui_floatinput_input_unbound( GUI_FLOATINPUT* input ) { gui_cursor_pos( &mx, &my ); F32 oldval = *input->pval; + F32 val = oldval; I32 dx = mx - input->lastmx; if( dx ) - *input->pval += dx * input->step; + val += dx * input->step; F32 min = input->min; F32 max = input->max; - if( isfinite( min ) && *input->pval < min ) - *input->pval = input->wraparound? max : min; - if( isfinite( max ) && *input->pval > max ) - *input->pval = input->wraparound? min : max; + if( isfinite( min ) && val < min ) + val = input->wraparound? max : min; + if( isfinite( max ) && val > max ) + val = input->wraparound? min : max; - F32 rmn = remainderf( *input->pval, input->step ); - *input->pval -= rmn; - if( oldval != *input->pval ) - input->lastchange = *input->pval - oldval; + F32 rmn = remainderf( val, input->step ); + val -= rmn; + + if( val != oldval ) { + if( input->pre_cb ) input->pre_cb( input ); + input->lastchange = val - oldval; + *input->pval = val; + if( input->cb ) input->cb( input ); + } } void gui_floatinput_input_scroll( GUI_FLOATINPUT* input ) { @@ -234,12 +245,12 @@ void gui_floatinput_input_scroll( GUI_FLOATINPUT* input ) { if( isfinite( input->max ) && nval > input->max ) nval = input->wraparound? input->min : input->max; + if( input->pre_cb ) input->pre_cb( input ); F32 rmn = remainderf( nval, input->step ); *input->pval = nval - rmn; input->lastchange = *input->pval - oldval; - if( input->cb ) - input->cb( input ); + if( input->cb ) input->cb( input ); } void gui_floatinput_input_fn( void* ptr ) { @@ -276,11 +287,13 @@ void gui_floatinput_input_fn( void* ptr ) { U8 inc = my < split_y; F32 step = fine ? 0.1f : 1.f; F32 val = *input->pval; + + if( input->pre_cb ) input->pre_cb( input ); *input->pval += inc ? step : -step; gui_floatinput_clamp_and_snap( input ); input->lastchange = *input->pval - val; - if( input->cb ) - input->cb( input ); + if( input->cb ) input->cb( input ); + input->held = 1; } return; @@ -298,6 +311,8 @@ void gui_floatinput_input_fn( void* ptr ) { if( !m1 ) { input->heldoutbounds = 0; + if( input->release_cb && input->held ) + input->release_cb( input ); input->held = 0; return; } @@ -305,17 +320,12 @@ void gui_floatinput_input_fn( void* ptr ) { if( input->heldoutbounds ) return; - F32 oldv = *input->pval; if( !gui_floatinput_is_bound_val( input ) ) gui_floatinput_input_unbound( input ); else gui_floatinput_input_bound( input ); gui_floatinput_clamp_and_snap( input ); - if( input->cb && oldv != *input->pval ) { - input->cb( input ); - } - input->lastmx = mx; } @@ -333,6 +343,7 @@ struct GUI_FLOATINPUT* gui_floatinput( I32 x, I32 y, I32 w, const char* title, F input->lastchange = 0; input->cb = 0; + input->release_cb = 0; input->pval = pval; input->min = min; input->max = max; diff --git a/src/gui/list.cpp b/src/gui/list.cpp index 0a2a3d3..aa0992e 100644 --- a/src/gui/list.cpp +++ b/src/gui/list.cpp @@ -66,10 +66,10 @@ void gui_list_input_fn( void* ptr ) { if( m1 ) { if( !list->held ) { GUI_LIST_ENTRY* e = &list->plist->data[idx]; - *list->pval = e->val; - if( list->cb ) - list->cb( list ); + if( list->pre_cb ) list->pre_cb( list ); + *list->pval = e->val; + if( list->cb ) list->cb( list ); } list->held = 1; } else { diff --git a/src/gui/textbox.cpp b/src/gui/textbox.cpp index 688450b..c367193 100644 --- a/src/gui/textbox.cpp +++ b/src/gui/textbox.cpp @@ -178,18 +178,20 @@ void gui_textbox_handle_repeat( GUI_TEXTBOX* tb ) { if( gui_time() - tb->repeattime > 0.05f ) { U32 len = strlen( tb->value ); if( is_printable_char( tb->heldkey ) && len < (tb->maxlen - 1) ) { + if( tb->pre_cb ) tb->pre_cb( tb ); + if( tb->keys[SDLK_LSHIFT & 0xff] || tb->keys[SDLK_RSHIFT & 0xff] ) tb->value[len] = tb->heldkey + ('a' - 'A'); else tb->value[len] = tb->heldkey; tb->value[++len] = 0; - if( tb->cb ) - tb->cb( tb ); + + if( tb->cb ) tb->cb( tb ); } else if( tb->heldkey == '\b' && len > 0 ) { + if( tb->pre_cb ) tb->pre_cb( tb ); tb->value[--len] = 0; - if( tb->cb ) - tb->cb( tb ); + if( tb->cb ) tb->cb( tb ); } tb->repeattime = gui_time(); diff --git a/src/gui/vectorinput.cpp b/src/gui/vectorinput.cpp index ad28c0d..3e36e31 100644 --- a/src/gui/vectorinput.cpp +++ b/src/gui/vectorinput.cpp @@ -39,6 +39,20 @@ void gui_vectorinput_child_cb( void* ptr ) { parent->cb( parent ); } +void gui_vectorinput_child_pre_cb( void* ptr ) { + GUI_FLOATINPUT* child = (GUI_FLOATINPUT*)ptr; + GUI_VECTORINPUT* parent = (GUI_VECTORINPUT*)child->parent->parent; + if( parent->pre_cb ) + parent->pre_cb( parent ); +} + +void gui_vectorinput_child_release_cb( void* ptr ) { + GUI_FLOATINPUT* child = (GUI_FLOATINPUT*)ptr; + GUI_VECTORINPUT* parent = (GUI_VECTORINPUT*)child->parent->parent; + if( parent->release_cb ) + parent->release_cb( parent ); +} + void __gui_internal_vectorinput_init( GUI_VECTORINPUT *input, I32 x, I32 y, I32 w, @@ -69,6 +83,7 @@ void __gui_internal_vectorinput_init( gui_set_view( input ); input->cb = 0; + input->release_cb = 0; input->pval = pval; input->letters = letters; input->inputview = gui_view( 0, VECTORINPUT_TITLE_OFFSET, w, input->h ); @@ -90,6 +105,8 @@ void __gui_internal_vectorinput_init( input->inputs.push( slider ); slider->cb = gui_vectorinput_child_cb; + slider->pre_cb = gui_vectorinput_child_pre_cb; + slider->release_cb = gui_vectorinput_child_release_cb; } gui_set_view( parent ); diff --git a/src/render/gl.cpp b/src/render/gl.cpp index 6ab2117..7425ff4 100644 --- a/src/render/gl.cpp +++ b/src/render/gl.cpp @@ -241,9 +241,9 @@ void gl_gen_buffers( GL_DATA* gl ) { void gl_destroy( GL_DATA *gl ) { SDL_SetEventFilter( 0, 0 ); - gl->programs.each( fn( GL_SHADER_PROGRAM** it ) { gl_program_destroy( gl, *it ); } ); - gl->fonts.each( fn( GL_FONT** it ) { gl_font_destroy( gl, *it ); } ); - gl->textures.each( fn( GL_TEX2D** it ) { gl_texture_destroy( gl, *it ); } ); + while( gl->programs.size ) { gl_program_destroy( gl, gl->programs.pop() ); } + while( gl->fonts.size ) { gl_font_destroy( gl, gl->fonts.pop() ); } + while( gl->textures.size ) { gl_texture_destroy( gl, gl->textures.pop() ); } if( gl->ctx ) SDL_GL_DeleteContext( gl->ctx ); @@ -407,6 +407,9 @@ void gl_program_destroy( GL_DATA* gl, GL_SHADER_PROGRAM* program ) { if( program->vsh.compiled ) gl_shader_destroy( gl, &program->vsh ); + I32 idx = gl->programs.idx_of( program ); + gl->programs.erase( idx ); + free( program ); } diff --git a/src/util/allocator.h b/src/util/allocator.h index 3cee282..63fc94a 100644 --- a/src/util/allocator.h +++ b/src/util/allocator.h @@ -206,6 +206,7 @@ struct LIST { return &data[size - 1]; } + // does not call copy funcs or constructors template < typename ... IT > void emplace( const T& item, IT&& ... items ) { constexpr U32 nsize = sizeof...( IT ) + 1; diff --git a/src/util/typedef.h b/src/util/typedef.h index 4a28624..fb26b0e 100644 --- a/src/util/typedef.h +++ b/src/util/typedef.h @@ -57,6 +57,6 @@ __defer_t<T> __defer_func( T f ) { #define dlog( ... ) (void)printf( __VA_ARGS__ ) #define ddef( x ) x #else -#define dlog( ... ) {} +#define dlog( ... ) (void)0 #define ddef( x ) #endif |
