feat(block-editor): wire Rotation, Alignment and Flip parameter placement

Enable the existing palette rows and BPARAMETER choices. Rotation accepts a
center, picked or numeric radius, and picked or numeric default angle.
Alignment places a tangent direction from its base point. Flip places a
reflection line and state label, with native grip and state expressions.

Extend shared graph append/capacity checks for Flip's additional state node
while preserving existing subgraphs. Keep Polar/Rotation angle labels unique
in either placement order. Add editor graphics, extents and definition
reframing through the existing overlay/history/save paths.

This milestone implements native parameter placement and persistence.
Rotate/Flip action association, reference alignment/grip editing, parameter
property editing and parameter sets remain separate work.

Validation covers command and palette placement, cancellation, local/parent
undo, save/discard, native DWG/DXF objects, existing graph preservation and
the 17 research fixtures. Broader block/dock regressions and editor renders
are also checked.
This commit is contained in:
Karim Jerbi committed 2026-10-15 16:50:47 +01:00
1 parent 6dab5a7229
commit 72c762e944
19 files changed
+1483 -25

No files matched your search

+71 -2
View File
@@ -7,6 +7,66 @@ use codec::{CadDocument, EntityType, Handle};
use iced::Task;
impl OpenCADStudio {
pub(in crate::app) fn handle_place_block_orientation_parameter(
&mut self,
result: crate::command::CmdResult,
) -> Task<Message> {
let crate::command::CmdResult::PlaceBlockOrientationParameter {
document_id,
definition,
kind,
base,
end,
reference,
} = result
else {
unreachable!()
};
let i = self.active_tab;
if self.tabs[i].id != document_id
|| self.tabs[i]
.active_block_edit_session()
.map(|s| s.br_handle)
!= Some(definition)
{
self.command_line.push_error(
crate::t!("The parameter's Block Editor session is no longer active.").as_ref(),
);
return Task::none();
}
let vector = |p: glam::DVec3| codec::types::Vector3::new(p.x, p.y, p.z);
if let Some(error) = self.parameter_placement_error(kind.name()).or_else(|| {
crate::scene::block_orientation_parameter::points_error(
kind,
vector(base),
vector(end),
vector(reference),
)
}) {
self.command_line.push_error(crate::t!(error).as_ref());
return Task::none();
}
self.push_undo_snapshot(i, &format!("{} parameter", kind.name()));
crate::scene::block_orientation_parameter::create(
&mut self.tabs[i].scene.document,
definition,
kind,
vector(base),
vector(end),
vector(reference),
)
.expect("validated parameter placement");
self.tabs[i].scene.bump_geometry();
self.tabs[i].dirty = true;
self.tabs[i].active_cmd = None;
self.tabs[i].scene.clear_preview_wire();
self.finish_pending_history(i);
self.refresh_properties();
self.command_line
.push_output(crate::tf!("{} parameter placed.", crate::t!(kind.name())).as_ref());
Task::none()
}
pub(in crate::app) fn handle_place_block_distance_parameter(
&mut self,
result: crate::command::CmdResult,
@@ -87,10 +147,11 @@ impl OpenCADStudio {
session.br_handle,
)
}
"ROTATION" | "R" | "ALIGNMENT" | "A" | "FLIP" | "F" => crate::scene::block_orientation_parameter::placement_error(&tab.scene.document, session.br_handle, crate::scene::block_orientation_parameter::Kind::parse(kind).unwrap()),
"VISIBILITY" | "V" => {
visibility::placement_error(&tab.scene.document, session.br_handle)
}
_ => Some("Supported parameter types: Point, Linear, Polar, XY, Visibility."),
_ => Some("Supported parameter types: Point, Linear, Polar, XY, Rotation, Alignment, Flip, Visibility."),
}
}
@@ -333,6 +394,14 @@ impl OpenCADStudio {
return Some(Task::none());
};
let parameter_type = cmd.strip_prefix("BPARAMETER").unwrap().trim();
if let Some(kind) =
crate::scene::block_orientation_parameter::Kind::parse(parameter_type)
{
let command = crate::modules::block_editor::orientation_parameter::OrientationParameterCommand::new(self.tabs[i].id,block,kind);
self.command_line.push_info(&command.prompt());
self.tabs[i].active_cmd = Some(Box::new(command));
return Some(Task::none());
}
if let Some(kind) =
crate::scene::block_distance_parameter::Kind::parse(parameter_type)
{
@@ -359,7 +428,7 @@ impl OpenCADStudio {
{
self.command_line.push_error(
crate::t!(
"Supported parameter types: Point, Linear, Polar, XY, Visibility."
"Supported parameter types: Point, Linear, Polar, XY, Rotation, Alignment, Flip, Visibility."
)
.as_ref(),
);