forked from 1b-agent/opencadstudio-upstream
Make TORIENT view-aware and fix DYN angle commit
This commit is contained in:
1 parent
1e7bd1e9b2
commit
7fc8c5985b
2 files changed
+31
-15
No files matched your search
+4
-1
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user