forked from 1b-agent/opencadstudio-upstream
refactor(selection): split 31-field SelectionState into five sub-structs
SelectionState now holds view, gesture, input, menu and orbit sub-structs; all 450 access sites updated mechanically with no behavior change. Deletes three write-only dead fields (box_last, box_last_crossing, poly_last_crossing). Hand-rolled clears in commands and dim_viewport route through the new clear methods; bench fixture updated. Full suite: 1976 passed / 0 failed / 25 ignored.
This commit is contained in:
1 parent
8c2cfa2c8f
commit
7aafd9c710
27 files changed
+512
-469
No files matched your search
@@ -2,9 +2,29 @@ use iced::time::Instant;
|
||||
use iced::Point;
|
||||
|
||||
/// Mouse / selection interaction state for the viewport.
|
||||
///
|
||||
/// Split (#32) into five sub-structs by family so a per-frame clone can copy
|
||||
/// only the family it needs and gesture clears touch one family at a time.
|
||||
/// The `RefCell` around this struct (`Scene::selection`) is untouched.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SelectionState {
|
||||
pub view: SelectionView,
|
||||
pub gesture: SelectionGesture,
|
||||
pub input: SelectionInput,
|
||||
pub menu: SelectionMenu,
|
||||
pub orbit: SelectionOrbit,
|
||||
}
|
||||
|
||||
/// View-dependent snapshot: the canvas size selection geometry is expressed in.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SelectionView {
|
||||
pub vp_size: (f32, f32),
|
||||
}
|
||||
|
||||
/// One box-or-lasso gesture: anchor/current corners, crossing sense, and the
|
||||
/// in-progress polygon. Cleared together by [`SelectionGesture::clear_left`].
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SelectionGesture {
|
||||
pub box_anchor: Option<Point>,
|
||||
/// World point under the box-selection anchor, so the anchor can be
|
||||
/// re-projected to screen when the camera zooms/pans mid-drag instead of
|
||||
@@ -12,14 +32,12 @@ pub struct SelectionState {
|
||||
/// (#234)
|
||||
pub box_anchor_world: Option<glam::DVec3>,
|
||||
pub box_current: Option<Point>,
|
||||
pub box_last: Option<(Point, Point)>,
|
||||
pub box_crossing: bool,
|
||||
/// Set when a Window / Crossing selection keyword fixed the sense of the
|
||||
/// box being drawn. Dragging normally decides it from the direction the
|
||||
/// corner travels, which would immediately overwrite what the user just
|
||||
/// asked for, so that derivation stands down while this holds.
|
||||
pub box_crossing_locked: bool,
|
||||
pub box_last_crossing: bool,
|
||||
/// A preview-only selection marquee `(anchor, current, crossing)` in canvas
|
||||
/// pixels, drawn identically to a real box-selection (green crossing fill /
|
||||
/// blue window fill) but with NO hit-test behaviour. Commands that pick a
|
||||
@@ -29,14 +47,25 @@ pub struct SelectionState {
|
||||
pub poly_active: bool,
|
||||
pub poly_points: Vec<Point>,
|
||||
pub poly_crossing: bool,
|
||||
pub poly_last_crossing: bool,
|
||||
/// Canvas position the right-click context menu is anchored at while it
|
||||
/// is open. `None` = closed. Its rows are rebuilt from app state every
|
||||
/// frame (`ui::popup::context_menu::build_context_menu`).
|
||||
pub context_menu: Option<Point>,
|
||||
/// Transient UI state of the open context menu (expanded submenu,
|
||||
/// keyboard highlight). Reset every time the menu opens.
|
||||
pub context_menu_ui: ContextMenuUi,
|
||||
}
|
||||
|
||||
impl SelectionGesture {
|
||||
/// End the in-progress box/lasso gesture (left-button release path).
|
||||
pub fn clear_left(&mut self) {
|
||||
self.box_anchor = None;
|
||||
self.box_anchor_world = None;
|
||||
self.box_current = None;
|
||||
self.box_crossing = false;
|
||||
self.box_crossing_locked = false;
|
||||
self.poly_active = false;
|
||||
self.poly_points.clear();
|
||||
self.poly_crossing = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Raw button/pointer state: press positions, drag flags, orbit pivot input.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SelectionInput {
|
||||
pub last_move_pos: Option<Point>,
|
||||
pub left_down: bool,
|
||||
pub left_press_pos: Option<Point>,
|
||||
@@ -47,10 +76,6 @@ pub struct SelectionState {
|
||||
pub right_press_time: Option<Instant>,
|
||||
pub right_dragging: bool,
|
||||
pub right_last_pos: Option<Point>,
|
||||
/// World point the current orbit drag revolves around (selection or model
|
||||
/// centre), captured when the drag starts so it stays fixed for the whole
|
||||
/// gesture. `None` when no orbit is in progress. (#229)
|
||||
pub orbit_pivot: Option<glam::DVec3>,
|
||||
/// While a command is active, a right-click acts as Enter; the *next*
|
||||
/// consecutive right-click opens the context menu instead. This tracks
|
||||
/// whether the previous right-click already fired Enter. Reset by any
|
||||
@@ -66,6 +91,52 @@ pub struct SelectionState {
|
||||
pub zoom_dir_out: bool,
|
||||
}
|
||||
|
||||
impl SelectionInput {
|
||||
/// Release the left button (click-commit path).
|
||||
pub fn clear_left_buttons(&mut self) {
|
||||
self.left_down = false;
|
||||
self.left_press_pos = None;
|
||||
self.left_press_time = None;
|
||||
self.left_dragging = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Right-click context-menu state.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SelectionMenu {
|
||||
/// Canvas position the right-click context menu is anchored at while it
|
||||
/// is open. `None` = closed. Its rows are rebuilt from app state every
|
||||
/// frame (`ui::popup::context_menu::build_context_menu`).
|
||||
pub open_at: Option<Point>,
|
||||
/// Transient UI state of the open context menu (expanded submenu,
|
||||
/// keyboard highlight). Reset every time the menu opens.
|
||||
pub ui: ContextMenuUi,
|
||||
}
|
||||
|
||||
impl SelectionMenu {
|
||||
/// Open the context menu at `at`, discarding the previous menu's
|
||||
/// expanded-submenu / highlight state.
|
||||
pub fn open(&mut self, at: Point) {
|
||||
self.open_at = Some(at);
|
||||
self.ui = ContextMenuUi::default();
|
||||
}
|
||||
|
||||
/// Close the context menu (no-op when it is not open).
|
||||
pub fn close(&mut self) {
|
||||
self.open_at = None;
|
||||
self.ui = ContextMenuUi::default();
|
||||
}
|
||||
}
|
||||
|
||||
/// Orbit-drag state.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct SelectionOrbit {
|
||||
/// World point the current orbit drag revolves around (selection or model
|
||||
/// centre), captured when the drag starts so it stays fixed for the whole
|
||||
/// gesture. `None` when no orbit is in progress. (#229)
|
||||
pub pivot: Option<glam::DVec3>,
|
||||
}
|
||||
|
||||
/// Transient state of the open right-click context menu.
|
||||
#[derive(Clone, Default)]
|
||||
pub struct ContextMenuUi {
|
||||
@@ -78,36 +149,12 @@ pub struct ContextMenuUi {
|
||||
}
|
||||
|
||||
impl SelectionState {
|
||||
/// Open the context menu at `at`, discarding the previous menu's
|
||||
/// expanded-submenu / highlight state.
|
||||
pub fn open_context_menu(&mut self, at: Point) {
|
||||
self.context_menu = Some(at);
|
||||
self.context_menu_ui = ContextMenuUi::default();
|
||||
}
|
||||
|
||||
/// Close the context menu (no-op when it is not open).
|
||||
pub fn close_context_menu(&mut self) {
|
||||
self.context_menu = None;
|
||||
self.context_menu_ui = ContextMenuUi::default();
|
||||
}
|
||||
|
||||
/// End every left-button selection gesture without disturbing the previous
|
||||
/// completed-window record or command-owned preview marquee. Grip editing
|
||||
/// owns the left button while engaged and calls this before/after placement
|
||||
/// so a small pointer move cannot also arm a box or lasso selection.
|
||||
pub fn clear_left_selection_gesture(&mut self) {
|
||||
self.left_down = false;
|
||||
self.left_press_pos = None;
|
||||
self.left_press_time = None;
|
||||
self.left_dragging = false;
|
||||
self.box_anchor = None;
|
||||
self.box_anchor_world = None;
|
||||
self.box_current = None;
|
||||
self.box_crossing = false;
|
||||
self.box_crossing_locked = false;
|
||||
self.poly_active = false;
|
||||
self.poly_points.clear();
|
||||
self.poly_crossing = false;
|
||||
self.input.clear_left_buttons();
|
||||
self.gesture.clear_left();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user