From 8f5bffd74a629d1e2e080bd90353dd193510fb80 Mon Sep 17 00:00:00 2001 From: Hakan Seven Date: Tue, 1 Sep 2026 22:51:42 +0300 Subject: [PATCH] fix(pyramid): preserve displayed construction values --- src/modules/model/primitive_cmd.rs | 25 ++++++++++++-- src/scene/model/solid_history.rs | 54 ++++++++++++++++-------------- 2 files changed, 51 insertions(+), 28 deletions(-) diff --git a/src/modules/model/primitive_cmd.rs b/src/modules/model/primitive_cmd.rs index c0bfcdc6a..c862fe8e9 100644 --- a/src/modules/model/primitive_cmd.rs +++ b/src/modules/model/primitive_cmd.rs @@ -1058,6 +1058,17 @@ impl PrimitiveCommand { } } + fn set_pyramid_type(&mut self, kind: PyramidType) { + let displayed_top = pyramid_circumradius_to_display( + self.pyramid_top_radius, + self.pyramid_type, + self.pyramid_sides, + ); + self.pyramid_type = kind; + self.pyramid_top_radius = + pyramid_display_to_circumradius(displayed_top, kind, self.pyramid_sides); + } + fn pyramid_set_base_from_point(&mut self, point: DVec3) -> bool { let Some(frame) = self.pyramid_frame else { return false; @@ -1410,11 +1421,11 @@ impl PrimitiveCommand { return Some(CmdResult::NeedPoint); } PyramidStep::BaseRadius if matches!(upper.as_str(), "I" | "INSCRIBED") => { - self.pyramid_type = PyramidType::Inscribed; + self.set_pyramid_type(PyramidType::Inscribed); return Some(CmdResult::NeedPoint); } PyramidStep::BaseRadius if matches!(upper.as_str(), "C" | "CIRCUMSCRIBED") => { - self.pyramid_type = PyramidType::Circumscribed; + self.set_pyramid_type(PyramidType::Circumscribed); return Some(CmdResult::NeedPoint); } PyramidStep::Height => { @@ -1445,7 +1456,17 @@ impl PrimitiveCommand { if !(3..=32).contains(&sides) { return None; } + let displayed_top = pyramid_circumradius_to_display( + self.pyramid_top_radius, + self.pyramid_type, + self.pyramid_sides, + ); self.pyramid_sides = sides; + self.pyramid_top_radius = pyramid_display_to_circumradius( + displayed_top, + self.pyramid_type, + self.pyramid_sides, + ); self.pyramid_defaults.sides = sides; self.pyramid_step = PyramidStep::BaseCenter; return Some(CmdResult::NeedPoint); diff --git a/src/scene/model/solid_history.rs b/src/scene/model/solid_history.rs index 409ba1b04..a0b5a1879 100644 --- a/src/scene/model/solid_history.rs +++ b/src/scene/model/solid_history.rs @@ -983,11 +983,11 @@ fn apply_pyramid_geometry_property( } else { value.top_radius * factor }; - value.radius = if next_inscribed { base_display } else { base_display / factor }; - value.top_radius = if next_inscribed { top_display } else { top_display / factor }; let Some(current) = matrix(value.base.transform) else { return Some(false); }; + value.radius = if next_inscribed { base_display } else { base_display / factor }; + value.top_radius = if next_inscribed { top_display } else { top_display / factor }; let half = std::f64::consts::PI / value.sides.clamp(3, 32) as f64; let delta = if next_inscribed { half } else { -half }; value.base.transform = @@ -1049,6 +1049,27 @@ fn apply_pyramid_geometry_property( Some(true) } +fn set_pyramid_sides(value: &mut SolidHistoryPyramid, sides: i32) -> bool { + if !(3..=32).contains(&sides) || sides == value.sides { + return false; + } + if !pyramid_is_inscribed(value) { + let Some(current) = matrix(value.base.transform) else { + return false; + }; + let old_factor = pyramid_apothem_factor(value.sides); + let new_factor = pyramid_apothem_factor(sides); + value.radius = value.radius * old_factor / new_factor; + value.top_radius = value.top_radius * old_factor / new_factor; + let old_half = std::f64::consts::PI / value.sides.clamp(3, 32) as f64; + let new_half = std::f64::consts::PI / sides as f64; + value.base.transform = + (current * glam::DMat4::from_rotation_z(old_half - new_half)).to_cols_array(); + } + value.sides = sides; + true +} + pub fn apply_primitive_property( operation: &mut SolidHistoryOperation, field: &str, @@ -1261,28 +1282,7 @@ pub fn apply_primitive_property( if (number - rounded).abs() > 1e-9 { return false; } - let sides = rounded as i32; - if !(3..=32).contains(&sides) { - return false; - } - if sides == value.sides { - return false; - } - if !pyramid_is_inscribed(value) { - let old_factor = pyramid_apothem_factor(value.sides); - let new_factor = pyramid_apothem_factor(sides); - value.radius = value.radius * old_factor / new_factor; - value.top_radius = value.top_radius * old_factor / new_factor; - let Some(current) = matrix(value.base.transform) else { - return false; - }; - let old_half = std::f64::consts::PI / value.sides.clamp(3, 32) as f64; - let new_half = std::f64::consts::PI / sides as f64; - value.base.transform = (current - * glam::DMat4::from_rotation_z(old_half - new_half)) - .to_cols_array(); - } - value.sides = sides; + return set_pyramid_sides(value, rounded as i32); } _ => return false, }, @@ -1756,8 +1756,10 @@ pub fn apply_primitive_grip( GRIP_HEIGHT => value.height = local.z.max(1e-6), GRIP_SIDES => { let angle = local.y.atan2(local.x).rem_euclid(std::f64::consts::TAU); - value.sides = (angle.to_degrees() / 5.0).round() as i32; - value.sides = value.sides.clamp(3, 32); + let sides = ((angle.to_degrees() / 5.0).round() as i32).clamp(3, 32); + if !set_pyramid_sides(value, sides) { + return false; + } } _ => return false, },