diff --git a/src/app/commands.rs b/src/app/commands.rs index 0a23a8563..4f347f201 100644 --- a/src/app/commands.rs +++ b/src/app/commands.rs @@ -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)); } diff --git a/src/modules/draw/modify/torient.rs b/src/modules/draw/modify/torient.rs index 6e3f41ff3..d0359940a 100644 --- a/src/modules/draw/modify/torient.rs +++ b/src/modules/draw/modify/torient.rs @@ -23,14 +23,16 @@ enum Step { pub struct TorientCommand { handles: Vec, entities: Vec<(Handle, EntityType)>, + view_twist: f64, step: Step, } impl TorientCommand { - pub fn new(handles: Vec, entities: Vec<(Handle, EntityType)>) -> Self { + pub fn new(handles: Vec, 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 { None } + + fn dyn_commit_as_text(&self) -> bool { + matches!(self.step, Step::AngleOrFirstPoint) + } }