forked from 1b-agent/opencadstudio-upstream
feat(ucs): orient text-bearing annotations to the active UCS
New annotations now place their text and reading geometry along the active UCS X axis (identity = world), so they read square to the user's coordinate system instead of world-horizontal: - TEXT / MTEXT: rotation defaults to the UCS X angle (DocumentTab::ucs_rotation_angle, model space only). - Linear dimensions: measure along the UCS axis the span is nearest, and bake the UCS X angle as the text rotation so the value reads square even under a style that forces horizontal text. DIMCONTINUE / DIMBASELINE derive their axis from the base dim's rotation (any angle), not a world H/V test. - LEADER: the MText annotation rotates to the UCS, and the hookline runs along the leader's horizontal_direction (set to UCS X), used by the renderer instead of world horizontal. - MLEADER: context.text_direction = UCS X drives both the text rotation and, in the renderer, the text side and dogleg/landing direction. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
1 parent
0c2a97e17e
commit
33314a5889
10 files changed
+160
-73
No files matched your search
@@ -217,6 +217,17 @@ impl DocumentTab {
|
||||
)
|
||||
}
|
||||
|
||||
/// World-space rotation angle (radians) of the active UCS X axis — the
|
||||
/// default rotation for new text-bearing objects so their text aligns to
|
||||
/// the user's coordinate system. Zero outside model space / with no UCS.
|
||||
pub(super) fn ucs_rotation_angle(&self) -> f64 {
|
||||
if self.scene.current_layout != "Model" {
|
||||
return 0.0;
|
||||
}
|
||||
let (_, x, ..) = self.ucs_xform().axes();
|
||||
(x.y as f64).atan2(x.x as f64)
|
||||
}
|
||||
|
||||
/// Grid origin (render/wire space) and UCS→world rotation for grid snap and
|
||||
/// the grid overlay. Identity / origin-at-zero outside model space.
|
||||
pub(super) fn ucs_grid_basis(&self) -> (glam::Vec3, glam::Mat4) {
|
||||
|
||||
@@ -632,7 +632,7 @@ impl super::OpenCADStudio {
|
||||
let i = self.active_tab;
|
||||
let Some(ed) = self.mtext_editor.take() else { return false };
|
||||
let body_empty = ed.content.text().trim().is_empty();
|
||||
let mt = ed.build_mtext();
|
||||
let mut mt = ed.build_mtext();
|
||||
if body_empty {
|
||||
// Empty content: drop a new entity; leave an edited one untouched.
|
||||
self.refresh_properties();
|
||||
@@ -661,6 +661,8 @@ impl super::OpenCADStudio {
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.tabs[i].dirty = true;
|
||||
} else {
|
||||
// Align new MText to the active UCS (text runs along the UCS X axis).
|
||||
mt.rotation = self.tabs[i].ucs_rotation_angle();
|
||||
self.push_undo_snapshot(i, "MTEXT");
|
||||
self.commit_entity(EntityType::MText(mt));
|
||||
self.tabs[i].dirty = true;
|
||||
|
||||
@@ -225,6 +225,8 @@ impl super::OpenCADStudio {
|
||||
if !cur_style.is_empty() {
|
||||
t.style = cur_style;
|
||||
}
|
||||
// Align new text to the active UCS (baseline along the UCS X axis).
|
||||
t.rotation = self.tabs[i].ucs_rotation_angle();
|
||||
self.push_undo_snapshot(i, "TEXT");
|
||||
self.commit_entity(EntityType::Text(t));
|
||||
self.tabs[i].dirty = true;
|
||||
|
||||
Reference in new issue
Block a user