fix(dyn-input): correct Y coordinate, label by prompt type — #27
DYN overlay artık ekran-yukarı için world Y'yi (w.y) gösteriyor; eskiden w.z kullanıldığı için Z-up sahnede top/3D görünümde Y hep 0 görünüyordu (#27). Ayrıca overlay etiketi aktif komutun o anki sorusuna göre biçimleniyor: yeni DynField (Point / Distance / Angle) trait metodu eklendi. CIRCLE yarıçap adımında 'd=...', ROTATE açı adımında '<...°', diğer nokta adımlarında koordinat / polar (d + açı) gösteriliyor. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
874226bd43
commit
1fc73ba8b0
4 changed files with 72 additions and 11 deletions
|
|
@ -2,6 +2,7 @@ use super::document::DocumentTab;
|
||||||
use super::helpers::grid_plane_from_camera;
|
use super::helpers::grid_plane_from_camera;
|
||||||
use super::history::history_dropdown_labels;
|
use super::history::history_dropdown_labels;
|
||||||
use super::{Message, OpenCADStudio};
|
use super::{Message, OpenCADStudio};
|
||||||
|
use crate::command::DynField;
|
||||||
use crate::scene::grip::{grips_to_screen, grips_to_screen_paper};
|
use crate::scene::grip::{grips_to_screen, grips_to_screen_paper};
|
||||||
use crate::scene::paper_canvas::PaperCanvas;
|
use crate::scene::paper_canvas::PaperCanvas;
|
||||||
use crate::scene::viewport_pane::{PaperViewportPane, ViewportPane};
|
use crate::scene::viewport_pane::{PaperViewportPane, ViewportPane};
|
||||||
|
|
@ -463,18 +464,40 @@ impl OpenCADStudio {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Dynamic input overlay — shown when a command is active and DYN is on.
|
// Dynamic input overlay — shown when a command is active and DYN is on.
|
||||||
|
// The label adapts to what the command is currently asking for:
|
||||||
|
// a point shows coordinates (or polar distance+angle once a base
|
||||||
|
// point exists); a radius/length prompt shows a single distance;
|
||||||
|
// an angle prompt shows degrees.
|
||||||
let dyn_input_overlay: Option<Element<'_, Message>> =
|
let dyn_input_overlay: Option<Element<'_, Message>> =
|
||||||
if self.dyn_input && tab.active_cmd.is_some() {
|
if self.dyn_input && tab.active_cmd.is_some() {
|
||||||
let w = tab.last_cursor_world;
|
let w = tab.last_cursor_world;
|
||||||
let label = if let Some(base) = self.last_point {
|
let field = tab
|
||||||
// Show relative distance + angle when we have a base point.
|
.active_cmd
|
||||||
let dx = (w.x - base.x) as f64;
|
.as_ref()
|
||||||
let dy = (w.z - base.z) as f64;
|
.map(|c| c.dyn_field())
|
||||||
let dist = (dx * dx + dy * dy).sqrt();
|
.unwrap_or(DynField::Point);
|
||||||
let ang = dy.atan2(dx).to_degrees();
|
// World is Z-up: the drawing plane is X/Y, so screen "up"
|
||||||
format!("d={:.3} <{:.1}°", dist, ang)
|
// maps to world Y — use w.y, not w.z (issue #27).
|
||||||
} else {
|
let label = match (field, self.last_point) {
|
||||||
format!("X:{:.3} Y:{:.3}", w.x, w.z)
|
(DynField::Distance, Some(base)) => {
|
||||||
|
let dx = (w.x - base.x) as f64;
|
||||||
|
let dy = (w.y - base.y) as f64;
|
||||||
|
format!("d={:.3}", (dx * dx + dy * dy).sqrt())
|
||||||
|
}
|
||||||
|
(DynField::Angle, Some(base)) => {
|
||||||
|
let dx = (w.x - base.x) as f64;
|
||||||
|
let dy = (w.y - base.y) as f64;
|
||||||
|
format!("<{:.1}°", dy.atan2(dx).to_degrees().rem_euclid(360.0))
|
||||||
|
}
|
||||||
|
(_, Some(base)) => {
|
||||||
|
// Point with a base: polar distance + angle.
|
||||||
|
let dx = (w.x - base.x) as f64;
|
||||||
|
let dy = (w.y - base.y) as f64;
|
||||||
|
let dist = (dx * dx + dy * dy).sqrt();
|
||||||
|
let ang = dy.atan2(dx).to_degrees().rem_euclid(360.0);
|
||||||
|
format!("d={:.3} <{:.1}°", dist, ang)
|
||||||
|
}
|
||||||
|
(_, None) => format!("X:{:.3} Y:{:.3}", w.x, w.y),
|
||||||
};
|
};
|
||||||
Some(overlay::dynamic_input_overlay(
|
Some(overlay::dynamic_input_overlay(
|
||||||
tab.last_cursor_screen,
|
tab.last_cursor_screen,
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,23 @@ pub enum CmdResult {
|
||||||
AttreqNeeded { block_name: String },
|
AttreqNeeded { block_name: String },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// What kind of value the active command is currently asking for. Drives
|
||||||
|
/// the dynamic-input overlay so the tooltip shows the relevant quantity
|
||||||
|
/// (coordinates for a point pick, a single length for a radius/distance
|
||||||
|
/// prompt, degrees for an angle prompt).
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||||
|
pub enum DynField {
|
||||||
|
/// A position — X/Y coordinates (or distance+angle relative to the
|
||||||
|
/// last point). The default for every command step.
|
||||||
|
#[default]
|
||||||
|
Point,
|
||||||
|
/// A single linear distance (radius, length, offset) measured from
|
||||||
|
/// the last point.
|
||||||
|
Distance,
|
||||||
|
/// An angle, shown in degrees, measured from the last point.
|
||||||
|
Angle,
|
||||||
|
}
|
||||||
|
|
||||||
// ── Trait ─────────────────────────────────────────────────────────────────
|
// ── Trait ─────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
/// An interactive CAD command that collects user input step-by-step.
|
/// An interactive CAD command that collects user input step-by-step.
|
||||||
|
|
@ -316,6 +333,14 @@ pub trait CadCommand: Send {
|
||||||
/// that need to read/modify it (e.g. DIMTEDIT, MLEADERADD, MLEADERREMOVE).
|
/// that need to read/modify it (e.g. DIMTEDIT, MLEADERADD, MLEADERREMOVE).
|
||||||
/// Default: no-op.
|
/// Default: no-op.
|
||||||
fn inject_picked_entity(&mut self, _entity: acadrust::EntityType) {}
|
fn inject_picked_entity(&mut self, _entity: acadrust::EntityType) {}
|
||||||
|
|
||||||
|
/// What the command is asking for at this step, used to label the
|
||||||
|
/// dynamic-input overlay. Default is a point pick; commands waiting
|
||||||
|
/// on a radius/length return `Distance` and angle prompts return
|
||||||
|
/// `Angle`.
|
||||||
|
fn dyn_field(&self) -> DynField {
|
||||||
|
DynField::Point
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Autocomplete registry ─────────────────────────────────────────────────
|
// ── Autocomplete registry ─────────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
use acadrust::types::Vector3;
|
use acadrust::types::Vector3;
|
||||||
use acadrust::{Circle, EntityType};
|
use acadrust::{Circle, EntityType};
|
||||||
|
|
||||||
use crate::command::{CadCommand, CmdResult, TangentObject};
|
use crate::command::{CadCommand, CmdResult, DynField, TangentObject};
|
||||||
use crate::modules::home::defaults;
|
use crate::modules::home::defaults;
|
||||||
use crate::modules::IconKind;
|
use crate::modules::IconKind;
|
||||||
use crate::scene::wire_model::WireModel;
|
use crate::scene::wire_model::WireModel;
|
||||||
|
|
@ -183,6 +183,12 @@ impl CadCommand for CircleCommand {
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
fn dyn_field(&self) -> DynField {
|
||||||
|
match self.step {
|
||||||
|
StepCR::Center => DynField::Point,
|
||||||
|
StepCR::Radius(_) => DynField::Distance,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Command: Center, Diameter ──────────────────────────────────────────────
|
// ── Command: Center, Diameter ──────────────────────────────────────────────
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
use acadrust::Handle;
|
use acadrust::Handle;
|
||||||
use glam::Vec3;
|
use glam::Vec3;
|
||||||
|
|
||||||
use crate::command::{CadCommand, CmdResult, EntityTransform};
|
use crate::command::{CadCommand, CmdResult, DynField, EntityTransform};
|
||||||
use crate::modules::home::defaults;
|
use crate::modules::home::defaults;
|
||||||
use crate::modules::{IconKind, ModuleEvent, ToolDef};
|
use crate::modules::{IconKind, ModuleEvent, ToolDef};
|
||||||
use crate::scene::wire_model::WireModel;
|
use crate::scene::wire_model::WireModel;
|
||||||
|
|
@ -187,4 +187,11 @@ impl CadCommand for RotateCommand {
|
||||||
));
|
));
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dyn_field(&self) -> DynField {
|
||||||
|
match self.step {
|
||||||
|
Step::Angle { .. } => DynField::Angle,
|
||||||
|
_ => DynField::Point,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue