diff options
Diffstat (limited to 'src/editor/view2d.cpp')
| -rw-r--r-- | src/editor/view2d.cpp | 317 |
1 files changed, 207 insertions, 110 deletions
diff --git a/src/editor/view2d.cpp b/src/editor/view2d.cpp index 92988df..b68846e 100644 --- a/src/editor/view2d.cpp +++ b/src/editor/view2d.cpp @@ -8,8 +8,43 @@ const I32 EDITORVIEW_TITLE_OFFSET = 15; const I32 EDITORVIEW_GUTTERS_OFFSETX = 22; const I32 EDITORVIEW_GUTTERS_OFFSETY = 16; const I32 EDITORVIEW_TOOLBAR_OFFSET = 20; +const I32 EDITOR_POLY_SIDES_RUNTIME_MAX = 256; VEC2 gui_editor_2dview_screen_to_world( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ); +VEC2 gui_editor_2dview_world_to_screen( GUI_EDITOR_2DVIEW* view, VEC2 world ); +F32 gui_editor_2dview_placement_z(); + +VEC3 gui_editor_2dview_plane_to_world3( VEC2 plane, F32 depth ) { + return { plane.x, plane.y, depth }; +} + +void gui_editor_2dview_set_plane( VEC3* v, VEC2 plane ) { + if( !v ) + return; + + v->x = plane.x; + v->y = plane.y; +} + +void gui_editor_2dview_add_plane_delta( VEC3* v, VEC2 delta ) { + if( !v ) + return; + + v->x += delta.x; + v->y += delta.y; +} + +void gui_editor_2dview_snap_plane( VEC3* v ) { + if( !v ) + return; + + v->x = m_snap_to_grid( v->x, editor->grid ); + v->y = m_snap_to_grid( v->y, editor->grid ); +} + +VEC2 gui_editor_2dview_world3_to_screen( GUI_EDITOR_2DVIEW* view, const VEC3& v ) { + return gui_editor_2dview_world_to_screen( view, { v.x, v.y } ); +} F32 gui_editor_2dview_ground_z() { WORLD_MAP* map = editor->map; @@ -177,9 +212,16 @@ void gui_editor_2dview_draw_gizmo( I32 x, I32 y, CLR clr, U8 selected = 0 ) { } I32 gui_editor_2dview_poly_sides() { - I32 sides = (I32)floorf( editor->tool.polysides + 0.5f ); + F32 raw = editor->tool.polysides; + if( !isfinite( raw ) ) + raw = EDITOR_DEFAULT_POLY_SIDES; + + if( raw > (F32)EDITOR_POLY_SIDES_RUNTIME_MAX ) + raw = (F32)EDITOR_POLY_SIDES_RUNTIME_MAX; + + I32 sides = (I32)floorf( raw + 0.5f ); if( sides < EDITOR_POLY_SIDES_MIN ) sides = EDITOR_POLY_SIDES_MIN; - if( sides > EDITOR_POLY_SIDES_MAX ) sides = EDITOR_POLY_SIDES_MAX; + if( sides > EDITOR_POLY_SIDES_RUNTIME_MAX ) sides = EDITOR_POLY_SIDES_RUNTIME_MAX; return sides; } @@ -199,7 +241,7 @@ U8 gui_editor_2dview_is_poly_drag_tool() { } I32 gui_editor_2dview_poly_points( VEC2 start, VEC2 end, I32 sides, U8 regular, VEC2* out_points ) { - if( !out_points || sides < EDITOR_POLY_SIDES_MIN || sides > EDITOR_POLY_SIDES_MAX ) + if( !out_points || sides < EDITOR_POLY_SIDES_MIN ) return 0; F32 minx = start.x < end.x ? start.x : end.x; @@ -246,7 +288,7 @@ struct EDITORVIEW_DRAG_RECT { struct EDITORVIEW_DRAG_SHAPE { EDITORVIEW_DRAG_RECT rect; - VEC2 points[EDITOR_POLY_SIDES_MAX]; + LIST<VEC2> points; I32 pointc; }; @@ -266,13 +308,14 @@ U8 gui_editor_2dview_build_drag_shape( GUI_EDITOR_2DVIEW* view, EDITORVIEW_DRAG_ return 0; I32 sides = gui_editor_2dview_poly_sides(); + out_shape->points.resize( sides ); U8 regular = gui_editor_2dview_poly_keep_regular( sides ); out_shape->pointc = gui_editor_2dview_poly_points( view->poly_start, view->poly_end, sides, regular, - out_shape->points + out_shape->points.data ); return out_shape->pointc >= 3; @@ -371,15 +414,16 @@ void gui_editor_2dview_create_poly_from_drag( GUI_EDITOR_2DVIEW* view ) { MAP_POLYGON newp{}; newp.propid = 0; newp.type = MPT_FLOOR; - F32 placez = gui_editor_2dview_placement_z(); + F32 depth = gui_editor_2dview_placement_z(); F32 invw = 1.f / shape.rect.w; F32 invh = 1.f / shape.rect.h; for( I32 i = 0; i < shape.pointc; ++i ) { VEC2 p = shape.points[i]; + VEC3 world = gui_editor_2dview_plane_to_world3( p, depth ); MAP_VERTEX v{}; - v.pos = { p.x, p.y, placez }; + v.pos = world; v.uv = { ( p.x - shape.rect.minx ) * invw, ( shape.rect.maxy - p.y ) * invh @@ -389,7 +433,9 @@ void gui_editor_2dview_create_poly_from_drag( GUI_EDITOR_2DVIEW* view ) { } map_polygon_calc_bounds( &newp ); + I32 poly_idx = editor->map->polygons.size; editor->map->polygons.push( newp ); + editor_undo_record_create_poly( editor, poly_idx ); gui_editor_2dview_check_bounds_preserve_view( view ); } @@ -399,19 +445,25 @@ void gui_editor_2dview_create_wallpoly_from_drag( GUI_EDITOR_2DVIEW* view ) { return; I32 propid = gui_editor_2dview_find_or_create_wallpoly_propid(); + I32 first_wall_idx = editor->map->walls.size; - F32 basez = gui_editor_2dview_placement_z(); + F32 depth = gui_editor_2dview_placement_z(); F32 wallheight = gui_editor_2dview_wall_height(); for( I32 i = 0; i < shape.pointc; ++i ) { VEC2 p0 = shape.points[i]; VEC2 p1 = shape.points[(i + 1) % shape.pointc]; + VEC3 w0 = gui_editor_2dview_plane_to_world3( p0, depth ); + VEC3 w1 = gui_editor_2dview_plane_to_world3( p1, depth ); MAP_WALL wall{}; - wall.start = { p0.x, p0.y, basez }; - wall.end = { p1.x, p1.y, wallheight }; + wall.start = w0; + wall.end = w1; + wall.end.z = wallheight; wall.propid = propid; editor->map->walls.push( wall ); } + I32 new_wall_count = editor->map->walls.size - first_wall_idx; + editor_undo_record_create_walls( editor, first_wall_idx, new_wall_count ); gui_editor_2dview_check_bounds_preserve_view( view ); } @@ -420,6 +472,10 @@ void gui_editor_2dview_draw_gutters( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { WORLD_MAP* m = editor->map; F32 w = view->w; F32 h = view->h; + F32 min_u = m->mins.x; + F32 max_u = m->maxs.x; + F32 min_v = m->mins.y; + F32 max_v = m->maxs.y; gui_draw_str( x + 2, y, ALIGN_L, FNT_JPN12, ui_clr.txt, "%1.f,%1.f", view->posx, view->posy ); for( U32 i = 1; i <= 5; ++i ) { @@ -428,7 +484,7 @@ void gui_editor_2dview_draw_gutters( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { F32 tp = (tx - x) / w; - F32 scaledx = m->mins.x + (m->maxs.x - m->mins.x) * tp; + F32 scaledx = min_u + ( max_u - min_u ) * tp; if( w > h ) scaledx *= ( w / h ); scaledx /= view->scale; @@ -443,7 +499,7 @@ void gui_editor_2dview_draw_gutters( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { F32 tp = (ty - y) / h; - F32 scaledy = m->mins.y + (m->maxs.y - m->mins.y) * tp; + F32 scaledy = min_v + ( max_v - min_v ) * tp; if( w < h ) scaledy *= h / w; scaledy /= view->scale; @@ -456,19 +512,19 @@ void gui_editor_2dview_draw_gutters( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { void gui_editor_2dview_draw_polygons( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { WORLD_MAP* m = editor->map; - F32 scale = gui_editor_2dview_calc_scale( view ); - F32 xoff = m->mins.x + view->posx; - F32 yoff = m->mins.y + view->posy; - m->polygons.each( fn( MAP_POLYGON* p ) { + SURF_PROPS fallback_props{ .tex = 0, .clr = CLR::WHITE() }; SURF_PROPS* props = polygon_get_props( m, p ); + if( !props ) + props = &fallback_props; if( !editor->wireframe ) { LIST<VERTEX> vertices; p->vertices.each( fn( MAP_VERTEX* v ) { + VEC2 screen = gui_editor_2dview_world3_to_screen( view, v->pos ); VERTEX v2; v2.uv = v->uv; - v2.pos.x = x + (v->pos.x - xoff) * scale; - v2.pos.y = y + (v->pos.y - yoff) * scale; + v2.pos.x = screen.x; + v2.pos.y = screen.y; v2.clr = props->clr; vertices.push( v2 ); } ); @@ -482,11 +538,13 @@ void gui_editor_2dview_draw_polygons( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { for( U32 i = 0; i < p->vertices.size; ++i ) { MAP_VERTEX* v1 = &p->vertices[i]; MAP_VERTEX* v2 = &p->vertices[(i+1) % p->vertices.size]; + VEC2 s0 = gui_editor_2dview_world3_to_screen( view, v1->pos ); + VEC2 s1 = gui_editor_2dview_world3_to_screen( view, v2->pos ); - I32 x0 = x + (I32)( (v1->pos.x - xoff) * scale ); - I32 y0 = y + (I32)( (v1->pos.y - yoff) * scale ); - I32 x1 = x + (I32)( (v2->pos.x - xoff) * scale ); - I32 y1 = y + (I32)( (v2->pos.y - yoff) * scale ); + I32 x0 = (I32)s0.x; + I32 y0 = (I32)s0.y; + I32 x1 = (I32)s1.x; + I32 y1 = (I32)s1.y; gui_draw_line( x0, y0, x1, y1, props->clr ); } @@ -496,8 +554,9 @@ void gui_editor_2dview_draw_polygons( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { return; // draw gizmos p->vertices.each( fn( MAP_VERTEX* v ) { - I32 vx = (I32)( x + (v->pos.x - xoff) * scale ); - I32 vy = (I32)( y + (v->pos.y - yoff) * scale ); + VEC2 screen = gui_editor_2dview_world3_to_screen( view, v->pos ); + I32 vx = (I32)screen.x; + I32 vy = (I32)screen.y; U8 selected = gui_editor_2dview_is_gizmo_active( view, v, EDITOR_SELECT_PVERTEX ) || gui_editor_2dview_is_gizmo_active( view, p, EDITOR_SELECT_POLY ); @@ -509,17 +568,20 @@ void gui_editor_2dview_draw_polygons( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { void gui_editor_2dview_draw_walls( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { WORLD_MAP* m = editor->map; - F32 scale = gui_editor_2dview_calc_scale( view ); - F32 xoff = m->mins.x + view->posx; - F32 yoff = m->mins.y + view->posy; - m->walls.each( fn( MAP_WALL* s ) { + SURF_PROPS fallback_props{ .tex = 0, .clr = CLR::WHITE() }; SURF_PROPS* props = wall_get_props( m, s ); - - I32 x0 = (I32)( x + (s->start.x - xoff) * scale ); - I32 y0 = (I32)( y + (s->start.y - yoff) * scale ); - I32 x1 = (I32)( x + (s->end.x - xoff) * scale ); - I32 y1 = (I32)( y + (s->end.y - yoff) * scale ); + if( !props ) + props = &fallback_props; + VEC3 w0 = { s->start.x, s->start.y, s->start.z }; + VEC3 w1 = { s->end.x, s->end.y, s->end.z }; + VEC2 p0 = gui_editor_2dview_world3_to_screen( view, w0 ); + VEC2 p1 = gui_editor_2dview_world3_to_screen( view, w1 ); + + I32 x0 = (I32)p0.x; + I32 y0 = (I32)p0.y; + I32 x1 = (I32)p1.x; + I32 y1 = (I32)p1.y; gui_draw_line( x0, y0, x1, y1, props->clr ); if( gui_editor_2dview_is_gizmo_active( view, s, EDITOR_SELECT_WALL ) ) { @@ -535,10 +597,14 @@ void gui_editor_2dview_draw_walls( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { // gizmos m->walls.each( fn( MAP_WALL* s ) { - I32 x0 = (I32)( x + (s->start.x - xoff) * scale ); - I32 y0 = (I32)( y + (s->start.y - yoff) * scale ); - I32 x1 = (I32)( x + (s->end.x - xoff) * scale ); - I32 y1 = (I32)( y + (s->end.y - yoff) * scale ); + VEC3 w0 = { s->start.x, s->start.y, s->start.z }; + VEC3 w1 = { s->end.x, s->end.y, s->end.z }; + VEC2 p0 = gui_editor_2dview_world3_to_screen( view, w0 ); + VEC2 p1 = gui_editor_2dview_world3_to_screen( view, w1 ); + I32 x0 = (I32)p0.x; + I32 y0 = (I32)p0.y; + I32 x1 = (I32)p1.x; + I32 y1 = (I32)p1.y; U8 sel = gui_editor_2dview_is_gizmo_active( view, s, EDITOR_SELECT_WALL ); U8 sel1 = gui_editor_2dview_is_gizmo_active( view, &s->start, EDITOR_SELECT_WVERTEX ); @@ -552,19 +618,12 @@ void gui_editor_2dview_draw_walls( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { void gui_editor_2dview_draw_sprites( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { WORLD_MAP* m = editor->map; - F32 scale = gui_editor_2dview_calc_scale( view ); - F32 xoff = m->mins.x + view->posx; - F32 yoff = m->mins.y + view->posy; - m->sprites.each( fn( MAP_SPRITE* s ) { F32 wantedsize = editor->spritesize; F32 aspect = s->size.x / s->size.y; F32 w = (aspect > 1.0f)? wantedsize : wantedsize * aspect; F32 h = (aspect < 1.0f)? wantedsize : wantedsize / aspect; - VEC2 pos = { - (F32)x + (s->pos.x - xoff) * scale, - (F32)y + (s->pos.y - yoff) * scale - }; + VEC2 pos = gui_editor_2dview_world3_to_screen( view, s->pos ); U8 sel= gui_editor_2dview_is_gizmo_active( view, s, EDITOR_SELECT_SPRITE ); if( sel ) { @@ -582,27 +641,18 @@ void gui_editor_2dview_draw_sprites( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { } void gui_editor_2dview_draw_player( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { - WORLD_MAP* m = editor->map; if( !objl->pl ) return; - F32 scale = gui_editor_2dview_calc_scale( view ); - F32 xoff = m->mins.x + view->posx; - F32 yoff = m->mins.y + view->posy; - VEC3 pos = objl->pl->pos; - - VEC2 pos2d = { - (F32)x + (pos.x - xoff) * scale, - (F32)y + (pos.y - yoff) * scale - }; + VEC2 pos2d = gui_editor_2dview_world3_to_screen( view, pos ); F32 yaw = objl->pl->rot.y; VEC2 dir = m_radial_offset( yaw, 20.f ); VEC2 ray = pos2d + dir; - gui_draw_line( (I32)pos2d.x, (I32)pos2d.y, (I32)ray.x, (I32)ray.y, CLR::GREEN() ); + gui_draw_frect( (I32)pos2d.x-4, (I32)pos2d.y-4, 8, 8, CLR::WHITE() ); gui_draw_frect( (I32)pos2d.x-3, (I32)pos2d.y-3, 6, 6, CLR::RED() ); } @@ -610,13 +660,10 @@ void gui_editor_2dview_draw_player( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { void gui_editor_2dview_draw_origin( GUI_EDITOR_2DVIEW* view, I32 x, I32 y ) { WORLD_MAP* m = editor->map; - F32 scale = gui_editor_2dview_calc_scale( view ); - F32 xoff = m->mins.x + view->posx; - F32 yoff = m->mins.y + view->posy; - VEC3 pos = m->startpos; - I32 screenx = (I32)( x + (pos.x - xoff) * scale ); - I32 screeny = (I32)( y + (pos.y - yoff) * scale ); + VEC2 screen = gui_editor_2dview_world3_to_screen( view, pos ); + I32 screenx = (I32)screen.x; + I32 screeny = (I32)screen.y; if( gui_editor_2dview_is_gizmo_active( view, m, EDITOR_SELECT_ORIGIN ) ) { I32 w, h; @@ -758,15 +805,13 @@ void gui_editor_2dview_input_select_onmove( GUI_EDITOR_2DVIEW* view ) { void gui_editor_2dview_input_select_drag_wall( GUI_EDITOR_2DVIEW* view ) { MAP_WALL* s = (MAP_WALL*)view->curdrag; - s->start.x = m_snap_to_grid( s->start.x, editor->grid ); - s->start.y = m_snap_to_grid( s->start.y, editor->grid ); - s->end.x = m_snap_to_grid( s->end.x, editor->grid ); - s->end.y = m_snap_to_grid( s->end.y, editor->grid ); + 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 ) ) { - s->start += mv; - s->end += mv; + gui_editor_2dview_add_plane_delta( &s->start, mv ); + gui_editor_2dview_add_plane_delta( &s->end, mv ); map_check_bounds( editor->map ); gui_editor_2dview_input_select_onmove( view ); @@ -774,13 +819,25 @@ void gui_editor_2dview_input_select_drag_wall( GUI_EDITOR_2DVIEW* view ) { } void gui_editor_2dview_input_select_drag_vertex( GUI_EDITOR_2DVIEW* view ) { - VEC2* v = (VEC2*)view->curdrag; - v->x = m_snap_to_grid( v->x, editor->grid ); - v->y = m_snap_to_grid( v->y, editor->grid ); + if( view->dragtype == EDITOR_SELECT_WVERTEX ) { + VEC3* v = (VEC3*)view->curdrag; + gui_editor_2dview_snap_plane( v ); + + VEC2 mv = gui_editor_2dview_input_get_drag_vec( view ); + if( !is_zero( mv ) ) { + gui_editor_2dview_add_plane_delta( v, mv ); + map_check_bounds( editor->map ); + gui_editor_2dview_input_select_onmove( view ); + } + return; + } + + MAP_VERTEX* v = (MAP_VERTEX*)view->curdrag; + gui_editor_2dview_snap_plane( &v->pos ); VEC2 mv = gui_editor_2dview_input_get_drag_vec( view ); if( !is_zero( mv ) ) { - *v += mv; + gui_editor_2dview_add_plane_delta( &v->pos, mv ); map_check_bounds( editor->map ); gui_editor_2dview_input_select_onmove( view ); @@ -793,11 +850,8 @@ void gui_editor_2dview_input_select_drag_polygon( GUI_EDITOR_2DVIEW* view ) { VEC2 mv = gui_editor_2dview_input_get_drag_vec( view ); if( !is_zero( mv ) ) { p->vertices.each( fn( MAP_VERTEX* v ) { - v->pos.x = m_snap_to_grid( v->pos.x, editor->grid ); - v->pos.y = m_snap_to_grid( v->pos.y, editor->grid ); - - v->pos.x += mv.x; - v->pos.y += mv.y; + gui_editor_2dview_snap_plane( &v->pos ); + gui_editor_2dview_add_plane_delta( &v->pos, mv ); } ); map_polygon_calc_bounds( p ); @@ -809,12 +863,11 @@ void gui_editor_2dview_input_select_drag_polygon( GUI_EDITOR_2DVIEW* view ) { void gui_editor_2dview_input_select_drag_sprite( GUI_EDITOR_2DVIEW* view ) { MAP_SPRITE* s = (MAP_SPRITE*)view->curdrag; - s->pos.x = m_snap_to_grid( s->pos.x, editor->grid ); - s->pos.y = m_snap_to_grid( s->pos.y, editor->grid ); + gui_editor_2dview_snap_plane( &s->pos ); VEC2 mv = gui_editor_2dview_input_get_drag_vec( view ); if( !is_zero( mv ) ) { - s->pos += mv; + gui_editor_2dview_add_plane_delta( &s->pos, mv ); gui_editor_2dview_input_select_onmove( view ); } } @@ -822,12 +875,11 @@ void gui_editor_2dview_input_select_drag_sprite( GUI_EDITOR_2DVIEW* view ) { void gui_editor_2dview_input_select_drag_origin( GUI_EDITOR_2DVIEW* view ) { WORLD_MAP* m = editor->map; - m->startpos.x = m_snap_to_grid( m->startpos.x, editor->grid ); - m->startpos.y = m_snap_to_grid( m->startpos.y, editor->grid ); + gui_editor_2dview_snap_plane( &m->startpos ); VEC2 mv = gui_editor_2dview_input_get_drag_vec( view ); if( !is_zero( mv ) ) { - m->startpos += mv; + gui_editor_2dview_add_plane_delta( &m->startpos, mv ); gui_editor_2dview_input_select_onmove( view ); } } @@ -890,10 +942,10 @@ void gui_editor_2dview_input_select_walls( GUI_EDITOR_2DVIEW* view ) { for( U32 i = 0; i < m->walls.size; ++i ) { MAP_WALL* w = &m->walls[i]; - VEC2 w1 = { w->start.x, w->start.y }; - VEC2 w2 = { w->end.x, w->end.y }; - w1 = gui_editor_2dview_world_to_screen( view, w1 ); - w2 = gui_editor_2dview_world_to_screen( view, w2 ); + VEC3 wp0 = { w->start.x, w->start.y, w->start.z }; + VEC3 wp1 = { w->end.x, w->end.y, w->end.z }; + VEC2 w1 = gui_editor_2dview_world3_to_screen( view, wp0 ); + VEC2 w2 = gui_editor_2dview_world3_to_screen( view, wp1 ); F32 d1 = vec_dist( mpos, w1 ); F32 d2 = vec_dist( mpos, w2 ); @@ -938,8 +990,7 @@ void gui_editor_2dview_input_select_polygons( GUI_EDITOR_2DVIEW* view ) { LIST<VEC2> plist; p->vertices.each( fn( MAP_VERTEX* v ) { - VEC2 world = { v->pos.x, v->pos.y }; - VEC2 screen = gui_editor_2dview_world_to_screen( view, world ); + VEC2 screen = gui_editor_2dview_world3_to_screen( view, v->pos ); F32 d = vec_dist( mpos, screen ); if( d < mindist ) { gui_editor_2dview_select( view, v, EDITOR_SELECT_PVERTEX ); @@ -975,8 +1026,7 @@ void gui_editor_2dview_input_select_sprites( GUI_EDITOR_2DVIEW* view ) { for( U32 i = 0; i < m->sprites.size; ++i ) { MAP_SPRITE* s = &m->sprites[i]; - VEC2 world = { s->pos.x, s->pos.y }; - VEC2 screen = gui_editor_2dview_world_to_screen( view, world ); + VEC2 screen = gui_editor_2dview_world3_to_screen( view, s->pos ); if( mpos.x >= screen.x - hsize && mpos.x <= screen.x + hsize && mpos.y >= screen.y - hsize && mpos.y <= screen.y + hsize ) @@ -1002,8 +1052,7 @@ void gui_editor_2dview_input_select_origin( GUI_EDITOR_2DVIEW* view ) { gui_cursor_pos( &mx, &my ); VEC2 mpos = { (F32)mx, (F32)my }; - VEC2 world = { m->startpos.x, m->startpos.y }; - VEC2 screen = gui_editor_2dview_world_to_screen( view, world ); + VEC2 screen = gui_editor_2dview_world3_to_screen( view, m->startpos ); I32 w, h; gui_draw_get_str_bounds( &w, &h, FNT_JPN12, "(origin)" ); @@ -1097,8 +1146,11 @@ void gui_editor_2dview_input_tool_wall( GUI_EDITOR_2DVIEW* view ) { U8 m1 = gui_mbutton_down( 0 ); if( !m1 ) { if( view->held ) { + if( view->pending_wall_undo_idx >= 0 ) + editor_undo_record_create_walls( editor, view->pending_wall_undo_idx, 1 ); gui_editor_2dview_check_bounds_preserve_view( view ); } + view->pending_wall_undo_idx = -1; view->held = 0; view->curdrag = 0; return; @@ -1109,18 +1161,22 @@ void gui_editor_2dview_input_tool_wall( GUI_EDITOR_2DVIEW* view ) { VEC2 world = gui_editor_2dview_screen_to_world( view, mx, my ); if( !view->held ) { - F32 basez = gui_editor_2dview_placement_z(); + F32 depth = gui_editor_2dview_placement_z(); + VEC3 wp = gui_editor_2dview_plane_to_world3( world, depth ); MAP_WALL neww; neww.start = neww.end = { - m_snap_to_grid( world.x, editor->grid ), - m_snap_to_grid( world.y, editor->grid ), - basez + wp.x, + wp.y, + wp.z }; + gui_editor_2dview_snap_plane( &neww.start ); + gui_editor_2dview_snap_plane( &neww.end ); neww.end.z = gui_editor_2dview_wall_height(); neww.propid = 0; I32 idx = editor->map->walls.size; editor->map->walls.push( neww ); + view->pending_wall_undo_idx = idx; view->curdrag = &editor->map->walls[idx].end; view->held = 1; @@ -1133,8 +1189,8 @@ void gui_editor_2dview_input_tool_wall( GUI_EDITOR_2DVIEW* view ) { VEC3* end = (VEC3*)view->curdrag; if( end ) { - end->x = m_snap_to_grid( world.x, editor->grid ); - end->y = m_snap_to_grid( world.y, editor->grid ); + gui_editor_2dview_set_plane( end, world ); + gui_editor_2dview_snap_plane( end ); } } @@ -1180,13 +1236,15 @@ void gui_editor_2dview_input_tool_sprite( GUI_EDITOR_2DVIEW* view ) { VEC2 world = gui_editor_2dview_screen_to_world( view, mx, my ); if( !view->held ) { + VEC3 wpos = gui_editor_2dview_plane_to_world3( world, gui_editor_2dview_placement_z() ); MAP_SPRITE news; - news.pos = { world.x, world.y, 20.f }; + news.pos = wpos; + gui_editor_2dview_snap_plane( &news.pos ); news.size = { 20.f, 20.f }; news.clr = { 1.f, 1.f, 1.f, 1.f }; news.tex = 0; - I32 idx = editor->map->walls.size; + I32 idx = editor->map->sprites.size; editor->map->sprites.push( news ); view->curdrag = &editor->map->sprites[idx]; view->held = 1; @@ -1289,12 +1347,31 @@ void gui_editor_view2d_delete_obj( GUI_EDITOR_2DVIEW* view ) { void gui_editor_2dview_key_input( GUI_EDITOR_2DVIEW* view ) { static U8 del_held = 0; + static U8 undo_held = 0; + static U8 redo_held = 0; if( kb_down( SDLK_DELETE ) && !input.mouselock ) { if( !del_held ) gui_editor_view2d_delete_obj( view ); del_held = 1; } else del_held = 0; + + U8 ctrl = kb_down( SDLK_LCTRL ) || kb_down( SDLK_RCTRL ); + U8 z = kb_down( SDLK_z ); + if( ctrl && z && !input.mouselock ) { + if( !undo_held ) + editor_undo( editor ); + + undo_held = 1; + } else undo_held = 0; + + U8 r = kb_down( SDLK_r ); + if( ctrl && r && !input.mouselock ) { + if( !redo_held ) + editor_redo( editor ); + + redo_held = 1; + } else redo_held = 0; } void gui_editor_2dview_input_fn( void* ptr ) { @@ -1344,30 +1421,44 @@ void gui_editor_2dview_input_fn( void* ptr ) { } } +static U8 GRID_DEP_LABEL_TAG; +static U8 GRID_DEP_PROPVIEW_TAG; +static U8 GRID_DEP_TOOLVIEW_TAG; + void update_view_settings( GAME_EDITOR* e ) { GAME_EDITOR::EDITOR_GUI* egui = &e->gui; + if( !egui->gridlabel ) + return; sprintf( egui->gridlabel->name, "grid: %1.2f", e->grid ); } +void editor_grid_dependency_update_label( GAME_EDITOR* e ) { + update_view_settings( e ); +} + +void editor_grid_dependency_update_propview( GAME_EDITOR* e ) { + if( e->propgrid && e->gui.props ) + editor_update_properties_column( e ); +} + +void editor_grid_dependency_update_toolview( GAME_EDITOR* e ) { + if( e->gui.tool ) + gui_editor_toolview_update( e->gui.tool ); +} + void grid_increment_cb( void* ) { if( editor->grid < 16.f ) editor->grid *= 2.f; - update_view_settings( editor ); - - if( editor->propgrid ) - editor_update_properties_column( editor ); + editor_notify_grid_change( editor ); } void grid_decrement_cb( void* ) { if( editor->grid > 0.25f ) editor->grid *= 0.5f; - update_view_settings( editor ); - - if( editor->propgrid ) - editor_update_properties_column( editor ); + editor_notify_grid_change( editor ); } void grid_propgrid_cb( void* ) { - editor_update_properties_column( editor ); + editor_notify_grid_change( editor ); } void gui_editor_2dview_create_toolbar( GUI_EDITOR_2DVIEW* view ) { @@ -1375,6 +1466,9 @@ void gui_editor_2dview_create_toolbar( GUI_EDITOR_2DVIEW* view ) { I32 x = 150, y = view->h - 4; editor->gui.gridlabel = gui_label( x, y + 1, "grid: %1.2f", e->grid ); + editor_register_grid_dependency( e, &GRID_DEP_LABEL_TAG, editor_grid_dependency_update_label ); + editor_register_grid_dependency( e, &GRID_DEP_PROPVIEW_TAG, editor_grid_dependency_update_propview ); + editor_register_grid_dependency( e, &GRID_DEP_TOOLVIEW_TAG, editor_grid_dependency_update_toolview ); x += 70; gui_button( x, y, 18, 18, "+", grid_increment_cb ); gui_button( x + 23, y, 18, 18, "-", grid_decrement_cb ); @@ -1383,6 +1477,8 @@ void gui_editor_2dview_create_toolbar( GUI_EDITOR_2DVIEW* view ) { check->cb = grid_propgrid_cb; x += 120; gui_checkbox( x, y, "wireframe", &e->wireframe ); + + editor_notify_grid_change( e ); } GUI_EDITOR_2DVIEW* gui_editor_2dview( I32 x, I32 y, I32 w, I32 h ) { @@ -1401,6 +1497,7 @@ GUI_EDITOR_2DVIEW* gui_editor_2dview( I32 x, I32 y, I32 w, I32 h ) { view->poly_drag = 0; view->poly_start = { 0.f, 0.f }; view->poly_end = { 0.f, 0.f }; + view->pending_wall_undo_idx = -1; GUI_BASE* parent = gui_get_view(); if( !parent ) |
