Make TORIENT view-aware and fix DYN angle commit

This commit is contained in:
Karim Jerbi committed 2026-06-17 17:05:20 +01:00
1 parent 1e7bd1e9b2
commit 7fc8c5985b
2 files changed
+31 -15

No files matched your search

+4 -1
View File
@@ -1140,7 +1140,10 @@ impl OpenCADStudio {
.iter()
.filter_map(|&h| self.tabs[i].scene.document.get_entity(h).cloned().map(|e| (h, e)))
.collect();
let new_cmd = TorientCommand::new(handles, entities);
let cam_rot = self.tabs[i].scene.camera.borrow().rotation;
let right = cam_rot * glam::Vec3::X;
let view_twist = right.y.atan2(right.x) as f64;
let new_cmd = TorientCommand::new(handles, entities, view_twist);
self.command_line.push_info(&new_cmd.prompt());
self.tabs[i].active_cmd = Some(Box::new(new_cmd));
}
+27 -14
View File
@@ -23,14 +23,16 @@ enum Step {
pub struct TorientCommand {
handles: Vec<Handle>,
entities: Vec<(Handle, EntityType)>,
view_twist: f64,
step: Step,
}
impl TorientCommand {
pub fn new(handles: Vec<Handle>, entities: Vec<(Handle, EntityType)>) -> Self {
pub fn new(handles: Vec<Handle>, entities: Vec<(Handle, EntityType)>, view_twist: f64) -> Self {
Self {
handles,
entities,
view_twist,
step: Step::AngleOrFirstPoint,
}
}
@@ -44,24 +46,24 @@ impl TorientCommand {
match &mut new_entity {
EntityType::Text(text) => {
let angle = new_angle_rad.unwrap_or_else(|| most_readable_angle(text.rotation));
let angle = new_angle_rad.unwrap_or_else(|| most_readable_angle(text.rotation, self.view_twist));
text.rotation = angle;
changed = true;
}
EntityType::MText(mtext) => {
let angle = new_angle_rad.unwrap_or_else(|| most_readable_angle(mtext.rotation as f64));
let angle = new_angle_rad.unwrap_or_else(|| most_readable_angle(mtext.rotation as f64, self.view_twist));
mtext.rotation = angle as f64;
changed = true;
}
EntityType::AttributeDefinition(attdef) => {
let angle = new_angle_rad.unwrap_or_else(|| most_readable_angle(attdef.rotation));
let angle = new_angle_rad.unwrap_or_else(|| most_readable_angle(attdef.rotation, self.view_twist));
attdef.rotation = angle;
changed = true;
}
EntityType::Insert(insert) => {
let mut block_changed = false;
for attr in &mut insert.attributes {
let angle = new_angle_rad.unwrap_or_else(|| most_readable_angle(attr.rotation));
let angle = new_angle_rad.unwrap_or_else(|| most_readable_angle(attr.rotation, self.view_twist));
attr.rotation = angle;
block_changed = true;
}
@@ -85,23 +87,30 @@ impl TorientCommand {
}
}
fn most_readable_angle(mut angle_rad: f64) -> f64 {
fn most_readable_angle(wcs_angle_rad: f64, view_twist: f64) -> f64 {
let two_pi = 2.0 * std::f64::consts::PI;
angle_rad %= two_pi;
if angle_rad < 0.0 {
angle_rad += two_pi;
// Calculate the angle as it appears on screen
let mut screen_angle = (wcs_angle_rad - view_twist) % two_pi;
if screen_angle < 0.0 {
screen_angle += two_pi;
}
// "Most Readable" logic: if upside down (i.e. angle > 90 and <= 270 deg), rotate 180 deg
// "Most Readable" logic: if upside down on screen (angle > 90 and <= 270 deg)
let half_pi = std::f64::consts::PI / 2.0;
let three_half_pi = 3.0 * std::f64::consts::PI / 2.0;
if angle_rad > half_pi + 1e-6 && angle_rad <= three_half_pi + 1e-6 {
angle_rad += std::f64::consts::PI;
angle_rad %= two_pi;
let mut final_wcs_angle = wcs_angle_rad;
if screen_angle > half_pi + 1e-6 && screen_angle <= three_half_pi + 1e-6 {
final_wcs_angle += std::f64::consts::PI;
}
angle_rad
// Normalize final WCS angle
final_wcs_angle %= two_pi;
if final_wcs_angle < 0.0 {
final_wcs_angle += two_pi;
}
final_wcs_angle
}
impl CadCommand for TorientCommand {
@@ -174,4 +183,8 @@ impl CadCommand for TorientCommand {
fn dyn_spec(&self) -> Option<crate::command::DynSpec> {
None
}
fn dyn_commit_as_text(&self) -> bool {
matches!(self.step, Step::AngleOrFirstPoint)
}
}