forked from 1b-agent/opencadstudio-upstream
feat(viewport): unify in-viewport editing on the model-space path
Replace the leaky paper-projection approach to MSPACE editing with one coordinate adapter that routes all interaction through the viewport's own camera — the exact camera+rect the GPU draws the content with. - Add Scene::viewport_edit_frame(canvas) -> (camera_for_viewport, viewport_screen_rect): the unified adapter. Inside a floating viewport the viewport is the active pane, so snap/pick/grip/preview/DYN run in model space and land on the pixels the GPU draws. Tracks pan/zoom/twist exactly (twist handled by camera_from_view); crop is pixel-preserving so full-rect projection + cursor offset matches. - Route snap-move, click-pick, grip-drag, grip hit-test, grip render, hover (HoverDwellTick), selection (single/box/poly/cycle) and command entity-pick through it via pick_view / cursor_model_point helpers and an edit_cam-aware "active pane = viewport rect" override, so the existing tile offset plumbing just works. Fixes wrong-object hover/selection and stale snap after pan/zoom. - DYN: project anchors with the viewport camera and shift to canvas space so the guide/labels sit correctly (also fixes a latent tiled-model bug). - Separate grid snap from object snap entirely: new Snapper.grid_snap_on flag, Grid removed from the osnap mode set, evaluated independently of the osnap master. Object snap never catches grid; grid corners are picked only when grid snap is on, at lowest priority. Default off. - grip.rs: project_rte + grips_to_screen_rte / find_hit_grip_rte taking (view_rot, eye) so grips project through the composed view. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
4aa8e6681f
commit
a66d873e51
5 files changed
+428
-172
No files matched your search
+22
-5
@@ -3,7 +3,7 @@ use super::document::{DynComponent, DynFieldEntry};
|
||||
use super::helpers::grid_plane_from_camera;
|
||||
use super::history::history_dropdown_labels;
|
||||
use super::{Message, OpenCADStudio};
|
||||
use crate::scene::pick::grip::{grips_to_screen, grips_to_screen_paper};
|
||||
use crate::scene::pick::grip::{grips_to_screen, grips_to_screen_paper, grips_to_screen_rte};
|
||||
use crate::scene::view::viewport_pane::ViewportPane;
|
||||
use crate::scene::{VIEWCUBE_DRAW_PX, VIEWCUBE_PAD};
|
||||
use crate::ui::overlay;
|
||||
@@ -86,9 +86,26 @@ impl OpenCADStudio {
|
||||
// they must use the active tile's screen rectangle (with
|
||||
// its canvas offset) — not the whole canvas — or they
|
||||
// land in the wrong place in a tiled layout.
|
||||
let bounds = tab.scene.active_model_tile_bounds(vw, vh);
|
||||
// Inside a floating viewport the pane is the viewport's own
|
||||
// rect + camera; otherwise the active model tile.
|
||||
let edit_frame = tab.scene.viewport_edit_frame((vw, vh));
|
||||
let bounds = match &edit_frame {
|
||||
Some((_, full)) => *full,
|
||||
None => tab.scene.active_model_tile_bounds(vw, vh),
|
||||
};
|
||||
let sel_h = tab.selected_handle;
|
||||
let screen_grips = if is_paper {
|
||||
// In-viewport grips are model-space; project them with the
|
||||
// viewport camera so they sit on the wire the GPU draws.
|
||||
// Paper entities use the 2-D paper transform; the model tab
|
||||
// uses the model camera.
|
||||
let screen_grips = if let Some((cam, _)) = &edit_frame {
|
||||
grips_to_screen_rte(
|
||||
&tab.selected_grips,
|
||||
cam.view_proj_rte(bounds),
|
||||
cam.eye_f64(),
|
||||
bounds,
|
||||
)
|
||||
} else if is_paper {
|
||||
let cam = tab.scene.camera.borrow();
|
||||
let aspect = if vh > 0.0 { vw / vh } else { 1.0 };
|
||||
let half_h = cam.ortho_size();
|
||||
@@ -388,7 +405,7 @@ impl OpenCADStudio {
|
||||
let bar = viewport_controls(
|
||||
tab.render_mode,
|
||||
self.show_grid,
|
||||
self.snapper.is_on(crate::snap::SnapType::Grid),
|
||||
self.snapper.grid_snap(),
|
||||
true,
|
||||
);
|
||||
// Position the bar at the active model tile's top-left corner so
|
||||
@@ -464,7 +481,7 @@ impl OpenCADStudio {
|
||||
iced::widget::opaque(viewport_controls(
|
||||
vp_mode,
|
||||
self.show_grid,
|
||||
self.snapper.is_on(crate::snap::SnapType::Grid),
|
||||
self.snapper.grid_snap(),
|
||||
false,
|
||||
)),
|
||||
],
|
||||
|
||||
Reference in new issue
Block a user