summaryrefslogtreecommitdiff
path: root/src/editor/view2d.cpp
diff options
context:
space:
mode:
authoraura <nw@moneybot.cc>2026-07-27 11:55:57 +0200
committeraura <nw@moneybot.cc>2026-07-27 11:55:57 +0200
commit372f23024163e0fab57a847ddda41f06857efd7e (patch)
treeca57dd38a583387a7bbcc970b7d359731df0f4bf /src/editor/view2d.cpp
parent452e3619450ab9e7d22886445f61cc90272e4d60 (diff)
undo/redo props - WIP
Diffstat (limited to 'src/editor/view2d.cpp')
-rw-r--r--src/editor/view2d.cpp180
1 files changed, 137 insertions, 43 deletions
diff --git a/src/editor/view2d.cpp b/src/editor/view2d.cpp
index c4738dd..cca83d1 100644
--- a/src/editor/view2d.cpp
+++ b/src/editor/view2d.cpp
@@ -4,7 +4,6 @@
#include "../render/gl_2d.h"
#include "../game/object.h"
#include "../game/objlist.h"
-#include "../game/world/bsp.h"
const I32 EDITORVIEW_TITLE_OFFSET = 15;
const I32 EDITORVIEW_GUTTERS_OFFSETX = 22;
@@ -839,36 +838,9 @@ VEC2 gui_editor_2dview_input_get_drag_vec( GUI_EDITOR_2DVIEW* view ) {
}
U8 gui_editor_2dview_input_select_drag_obj( GUI_EDITOR_2DVIEW* view, void* obj, U8 seltype );
-U8 gui_editor_2dview_move_group( GUI_EDITOR_2DVIEW* view ) {
- U8 update = 0;
- if( view->dragtype == EDITOR_SELECT_WVERTEX || view->dragtype == EDITOR_SELECT_PVERTEX )
- return update;
-
- GUI_EDITOR_PROPVIEW* props = editor->gui.props;
- // update all selected objects
- for( auto& it : props->curselect ) {
- if( it.obj == view->curdrag ) {
- update = 1;
- continue;
- }
+U8 gui_editor_2dview_drag_group( GUI_EDITOR_2DVIEW* view );
- // special case where a wall is selected but we are dragging one of its vertices
- if( props->curselect.size == 1 && it.seltype == EDITOR_SELECT_WALL ) {
- MAP_WALL* w = (MAP_WALL*)it.obj;
- if( &w->start == view->curdrag || &w->end == view->curdrag ) {
- update = 1;
- continue;
- }
- }
-
- if( gui_editor_2dview_input_select_drag_obj( view, it.obj, it.seltype ) )
- update = 1;
- }
-
- return update;
-}
-
-void gui_editor_2dview_input_select_onmove( GUI_EDITOR_2DVIEW* view ) {
+void gui_editor_2dview_input_select_onmove( GUI_EDITOR_2DVIEW* view, EDITOR_UNDO_PROPS* undo ) {
I32 mx, my;
gui_cursor_pos( &mx, &my );
@@ -883,7 +855,7 @@ void gui_editor_2dview_input_select_onmove( GUI_EDITOR_2DVIEW* view ) {
GUI_EDITOR_PROPVIEW* props = editor->gui.props;
U8 update = !is_zero( gui_editor_2dview_input_get_drag_vec( view ) );
if( update && gui_editor_propview_is_selected( props, view->curdrag, view->dragtype ) ) {
- if( gui_editor_2dview_move_group( view ) )
+ if( gui_editor_2dview_drag_group( view ) )
gui_editor_propview_update( props );
}
@@ -894,45 +866,109 @@ void gui_editor_2dview_input_select_onmove( GUI_EDITOR_2DVIEW* view ) {
view->dragmoved = 1;
}
-void gui_editor_2dview_input_select_drag_wall( GUI_EDITOR_2DVIEW* view, MAP_WALL* s ) {
+void gui_editor_2dview_set_undo_prop( GUI_EDITOR_2DVIEW* view, EOBJECT* target, FNV1A hash, U32 size, void* oldv, void* newv = 0 ) {
+ if( !target )
+ return;
+
+ EDITOR_UNDO_PROPS::CHANGES* target_change = view->pending_undo_props.changes.where(
+ [&]( EDITOR_UNDO_PROPS::CHANGES* c ) { return c->obj == target; }
+ );
+
+ if( !target_change ) {
+ target_change = view->pending_undo_props.changes.push( { .obj = target } );
+ }
+
+ EDITOR_UNDO_PROPS::PROP_VALUE* target_prop = target_change->props.where(
+ [&]( EDITOR_UNDO_PROPS::PROP_VALUE* p ) { return p->hash == hash; }
+ );
+
+ if( !target_prop ) {
+ target_prop = target_change->props.push( { hash, size } );
+ memcpy( target_prop->oldval.data, oldv, size );
+ }
+
+ if( target_prop->size != size ) {
+ return dlog( "gui_editor_2dview_set_undo_prop() : prop size mismatch" );
+ }
+
+ if( newv )
+ memcpy( target_prop->newval.data, newv, size );
+}
+
+void gui_editor_2dview_input_select_drag_wall(
+ GUI_EDITOR_2DVIEW* view,
+ MAP_WALL* s
+) {
gui_editor_2dview_snap_plane( &s->start );
gui_editor_2dview_snap_plane( &s->end );
VEC2 mv = gui_editor_2dview_input_get_drag_vec( view );
if( !is_zero( mv ) ) {
+ VEC3 olds = s->start;
+ VEC3 olde = s->end;
gui_editor_2dview_add_plane_delta( &s->start, mv );
gui_editor_2dview_add_plane_delta( &s->end, mv );
+
+ EDITOR_PROP* sprop = eprop_from_ptr( s, &s->start );
+ EDITOR_PROP* eprop = eprop_from_ptr( s, &s->end );
+
+ gui_editor_2dview_set_undo_prop( view, s, sprop->hash, sprop->size, &olds, &s->start );
+ gui_editor_2dview_set_undo_prop( view, s, eprop->hash, eprop->size, &olde, &s->end );
+
map_check_bounds( editor->map );
}
}
-void gui_editor_2dview_input_select_drag_pos( GUI_EDITOR_2DVIEW* view, VEC3* v ) {
+void gui_editor_2dview_input_select_drag_wallpos(
+ GUI_EDITOR_2DVIEW* view,
+ VEC3* v
+) {
gui_editor_2dview_snap_plane( v );
VEC2 mv = gui_editor_2dview_input_get_drag_vec( view );
if( !is_zero( mv ) ) {
+ VEC3 oldv = *v;
gui_editor_2dview_add_plane_delta( v, mv );
map_check_bounds( editor->map );
+
+ // giga hack
+ EDITOR_PROP* p = (EDITOR_PROP*)( (U64)v + sizeof(VEC3) );
+ MAP_WALL* s = (MAP_WALL*)( (U64)v - p->parentoff );
+ gui_editor_2dview_set_undo_prop( view, s, p->hash, p->size, &oldv, v );
}
}
-void gui_editor_2dview_input_select_drag_vertex( GUI_EDITOR_2DVIEW* view, MAP_VERTEX* v ) {
+void gui_editor_2dview_input_select_drag_vertex(
+ GUI_EDITOR_2DVIEW* view,
+ MAP_VERTEX* v
+) {
gui_editor_2dview_snap_plane( &v->pos );
VEC2 mv = gui_editor_2dview_input_get_drag_vec( view );
if( !is_zero( mv ) ) {
+ VEC3 oldv = v->pos;
gui_editor_2dview_add_plane_delta( &v->pos, mv );
map_check_bounds( editor->map );
+
+ EDITOR_PROP* p = eprop_from_ptr( v, &v->pos );
+ gui_editor_2dview_set_undo_prop( view, v, p->hash, p->size, &oldv, &v->pos );
}
}
-void gui_editor_2dview_input_select_drag_polygon( GUI_EDITOR_2DVIEW* view, MAP_POLYGON* p ) {
+void gui_editor_2dview_input_select_drag_polygon(
+ GUI_EDITOR_2DVIEW* view,
+ MAP_POLYGON* p
+) {
VEC2 mv = gui_editor_2dview_input_get_drag_vec( view );
if( !is_zero( mv ) ) {
p->vertices.each( fn( MAP_VERTEX* v ) {
+ VEC3 oldv = v->pos;
gui_editor_2dview_snap_plane( &v->pos );
gui_editor_2dview_add_plane_delta( &v->pos, mv );
+
+ EDITOR_PROP* p = eprop_from_ptr( v, &v->pos );
+ gui_editor_2dview_set_undo_prop( view, v, p->hash, p->size, &oldv, &v->pos );
} );
map_polygon_calc_bounds( p );
@@ -940,31 +976,51 @@ void gui_editor_2dview_input_select_drag_polygon( GUI_EDITOR_2DVIEW* view, MAP_P
}
}
-void gui_editor_2dview_input_select_drag_sprite( GUI_EDITOR_2DVIEW* view, MAP_SPRITE* s ) {
+void gui_editor_2dview_input_select_drag_sprite(
+ GUI_EDITOR_2DVIEW* view,
+ MAP_SPRITE* s
+) {
gui_editor_2dview_snap_plane( &s->pos );
VEC2 mv = gui_editor_2dview_input_get_drag_vec( view );
if( !is_zero( mv ) ) {
+ VEC3 oldv = s->pos;
gui_editor_2dview_add_plane_delta( &s->pos, mv );
+
+ EDITOR_PROP* p = eprop_from_ptr( s, &s->pos );
+ gui_editor_2dview_set_undo_prop( view, s, p->hash, p->size, &oldv, &s->pos );
}
}
-
-void gui_editor_2dview_input_select_drag_entity( GUI_EDITOR_2DVIEW* view, MAP_ENTITY* e ) {
+void gui_editor_2dview_input_select_drag_entity(
+ GUI_EDITOR_2DVIEW* view,
+ MAP_ENTITY* e
+) {
gui_editor_2dview_snap_plane( &e->pos );
VEC2 mv = gui_editor_2dview_input_get_drag_vec( view );
if( !is_zero( mv ) ) {
+ VEC3 oldv = e->pos;
gui_editor_2dview_add_plane_delta( &e->pos, mv );
+
+ EDITOR_PROP* p = eprop_from_ptr( e, &e->pos );
+ gui_editor_2dview_set_undo_prop( view, e, p->hash, p->size, &oldv, &e->pos );
}
}
-void gui_editor_2dview_input_select_drag_origin( GUI_EDITOR_2DVIEW* view, WORLD_MAP* m ) {
+void gui_editor_2dview_input_select_drag_origin(
+ GUI_EDITOR_2DVIEW* view,
+ WORLD_MAP* m
+) {
gui_editor_2dview_snap_plane( &m->startpos );
VEC2 mv = gui_editor_2dview_input_get_drag_vec( view );
if( !is_zero( mv ) ) {
+ VEC3 oldv = m->startpos;
gui_editor_2dview_add_plane_delta( &m->startpos, mv );
+
+ EDITOR_PROP* p = eprop_from_ptr( m, &m->startpos );
+ gui_editor_2dview_set_undo_prop( view, m, p->hash, p->size, &oldv, &m->startpos );
}
}
@@ -980,7 +1036,7 @@ U8 gui_editor_2dview_input_select_drag_obj( GUI_EDITOR_2DVIEW* view, void* obj,
case EDITOR_SELECT_SPRITE: gui_editor_2dview_input_select_drag_sprite( view, (MAP_SPRITE*)p ); return 1;
case EDITOR_SELECT_ORIGIN: gui_editor_2dview_input_select_drag_origin( view, (WORLD_MAP*)p ); return 1;
case EDITOR_SELECT_PVERTEX: gui_editor_2dview_input_select_drag_vertex( view, (MAP_VERTEX*)p ); return 1;
- case EDITOR_SELECT_WVERTEX: gui_editor_2dview_input_select_drag_pos( view, (VEC3*)p ); return 1;
+ case EDITOR_SELECT_WVERTEX: gui_editor_2dview_input_select_drag_wallpos( view, (VEC3*)p ); return 1;
}
return 0;
@@ -990,9 +1046,45 @@ void gui_editor_2dview_input_select_ondrop( GUI_EDITOR_2DVIEW* view ) {
if( !view->dragmoved )
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 );
+ view->pending_undo_props = {};
+ }
+
view->curdrag = 0;
}
+U8 gui_editor_2dview_drag_group( GUI_EDITOR_2DVIEW* view ) {
+ U8 update = 0;
+ if( view->dragtype == EDITOR_SELECT_WVERTEX || view->dragtype == EDITOR_SELECT_PVERTEX )
+ return update;
+
+ GUI_EDITOR_PROPVIEW* props = editor->gui.props;
+ // update all selected objects
+ for( auto& it : props->curselect ) {
+ if( it.obj == view->curdrag ) {
+ update = 1;
+ continue;
+ }
+
+ // special case where a wall is selected but we are dragging one of its vertices
+ if( props->curselect.size == 1 && it.seltype == EDITOR_SELECT_WALL ) {
+ MAP_WALL* w = (MAP_WALL*)it.obj;
+ if( &w->start == view->curdrag || &w->end == view->curdrag ) {
+ update = 1;
+ continue;
+ }
+ }
+
+ if( gui_editor_2dview_input_select_drag_obj( view, it.obj, it.seltype ) ) {
+ update = 1;
+ }
+ }
+
+ return update;
+}
+
void gui_editor_2dview_input_select_drag( GUI_EDITOR_2DVIEW* view ) {
U8 m1 = gui_mbutton_down( 0 );
I32 mx, my;
@@ -1017,15 +1109,17 @@ void gui_editor_2dview_input_select_drag( GUI_EDITOR_2DVIEW* view ) {
return;
}
+ EDITOR_UNDO_ACTION rec{ .type = 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;
view->oldmy = my;
return;
}
- VEC2 mv = gui_editor_2dview_input_get_drag_vec( view );
- if( !is_zero( mv ) ) {
- gui_editor_2dview_input_select_onmove( view );
+ if( !is_zero( gui_editor_2dview_input_get_drag_vec( view ) ) ) {
+ gui_editor_2dview_input_select_onmove( view, &rec.props );
+ rec.props.changes.push( changes );
}
}