forked from 1b-agent/opencadstudio-upstream
Merge pull request #1332 from ramox81/codex/concentric-constraint-parity
# Conflicts: # src/entities/arc.rs # src/entities/ellipse.rs # src/modules/parametric/mod.rs # src/scene/parametric_solve.rs # src/ui/overlay.rs
This commit is contained in:
commit
16c417f81d
17 files changed
+692
-52
No files matched your search
@@ -3372,6 +3372,88 @@ impl OpenCADStudio {
|
||||
self.commit_undo_delta(i, pd);
|
||||
}
|
||||
}
|
||||
CmdResult::AddConcentricConstraint {
|
||||
first,
|
||||
second,
|
||||
label,
|
||||
} => {
|
||||
use crate::scene::parametric_constraints::ConstraintKind;
|
||||
|
||||
let refs = vec![first, second];
|
||||
if let Err(message) = self.tabs[i].scene.validate_parametric_constraint(
|
||||
ConstraintKind::Concentric,
|
||||
&refs,
|
||||
None,
|
||||
) {
|
||||
self.tabs[i].active_cmd = None;
|
||||
self.tabs[i].snap_result = None;
|
||||
self.command_line.push_error(message);
|
||||
return Task::none();
|
||||
}
|
||||
let scope = self.tabs[i].current_parametric_scope();
|
||||
let duplicate = self.tabs[i]
|
||||
.scene
|
||||
.parametric_constraint_set(scope)
|
||||
.is_some_and(|set| {
|
||||
set.constraints.iter().any(|constraint| {
|
||||
constraint.enabled
|
||||
&& constraint.kind == ConstraintKind::Concentric
|
||||
&& matches!(constraint.refs.as_slice(), [a, b]
|
||||
if (*a == first && *b == second)
|
||||
|| (*a == second && *b == first))
|
||||
})
|
||||
});
|
||||
if duplicate {
|
||||
self.tabs[i].active_cmd = None;
|
||||
self.tabs[i].snap_result = None;
|
||||
self.command_line
|
||||
.push_output("The Concentric constraint already exists.");
|
||||
return Task::none();
|
||||
}
|
||||
let constraints_before = self.tabs[i]
|
||||
.scene
|
||||
.parametric_constraint_set(scope)
|
||||
.cloned()
|
||||
.unwrap_or_else(|| {
|
||||
crate::scene::parametric_constraints::ParametricConstraintSet::new(scope)
|
||||
});
|
||||
let touched = if first.entity == second.entity {
|
||||
vec![first.entity]
|
||||
} else {
|
||||
vec![first.entity, second.entity]
|
||||
};
|
||||
let pending = self.begin_undo(i, label, touched.len(), true);
|
||||
self.tabs[i]
|
||||
.scene
|
||||
.record_undo_parametric_constraints_before(scope, constraints_before);
|
||||
let id = self.tabs[i].scene.parametric_constraint_set_mut(scope).add(
|
||||
ConstraintKind::Concentric,
|
||||
refs,
|
||||
None,
|
||||
);
|
||||
self.tabs[i].scene.note_parametric_constraint_applied(
|
||||
scope,
|
||||
id,
|
||||
self.constraint_bar_display,
|
||||
);
|
||||
let changes = touched
|
||||
.into_iter()
|
||||
.map(|handle| (handle, crate::scene::ChangeKind::Modified))
|
||||
.collect::<Vec<_>>();
|
||||
self.tabs[i].scene.bump_entities_with_initial_parametric_policy(
|
||||
&changes,
|
||||
&[first],
|
||||
true,
|
||||
);
|
||||
self.tabs[i].dirty = true;
|
||||
self.tabs[i].active_cmd = None;
|
||||
self.tabs[i].snap_result = None;
|
||||
self.command_line.push_output("Constraint applied.");
|
||||
self.refresh_properties();
|
||||
if let Some(pd) = pending {
|
||||
self.commit_undo_delta(i, pd);
|
||||
}
|
||||
}
|
||||
CmdResult::AddCoincidentConstraint {
|
||||
first,
|
||||
second,
|
||||
|
||||
+32
-20
@@ -1496,29 +1496,41 @@ impl OpenCADStudio {
|
||||
}
|
||||
}
|
||||
|
||||
"NCONSTRAINT" => {
|
||||
"NCONSTRAINT" | "GCCONCENTRIC" => {
|
||||
use crate::command::CmdResult;
|
||||
use crate::modules::parametric::ConcentricConstraintCommand;
|
||||
|
||||
let handles = self.tabs[i].scene.selected_handles_in_order();
|
||||
if handles.is_empty() {
|
||||
use crate::modules::draw::select::SelectObjectsCommand;
|
||||
let sel = SelectObjectsCommand::new(cmd);
|
||||
self.command_line.push_info(&sel.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(sel));
|
||||
} else if handles.len() != 2 {
|
||||
self.command_line.push_output(
|
||||
"Select exactly two circles/arcs, then run this constraint again.",
|
||||
);
|
||||
let command = ConcentricConstraintCommand::new();
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
} else {
|
||||
use crate::command::CmdResult;
|
||||
use crate::scene::parametric_constraints::{ConstraintKind, ParametricRef};
|
||||
return Some(self.apply_cmd_result(CmdResult::AddParametricConstraint {
|
||||
kind: ConstraintKind::Concentric,
|
||||
refs: vec![
|
||||
ParametricRef::center(handles[0]),
|
||||
ParametricRef::center(handles[1]),
|
||||
],
|
||||
driving_param: None,
|
||||
label: "Concentric constraint",
|
||||
}));
|
||||
let refs = handles
|
||||
.iter()
|
||||
.filter_map(|handle| {
|
||||
let entity = self.tabs[i].scene.document.get_entity(*handle)?;
|
||||
ConcentricConstraintCommand::preselected_reference(entity, *handle)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
if handles.len() == 2 && refs.len() == 2 && refs[0] != refs[1] {
|
||||
return Some(self.apply_cmd_result(CmdResult::AddConcentricConstraint {
|
||||
first: refs[0],
|
||||
second: refs[1],
|
||||
label: "Concentric constraint",
|
||||
}));
|
||||
}
|
||||
self.tabs[i].scene.deselect_all();
|
||||
self.command_line.push_error(
|
||||
"Invalid selection for Concentric. Select a circle, arc, ellipse or polyline arc segment.",
|
||||
);
|
||||
let command = refs
|
||||
.first()
|
||||
.copied()
|
||||
.map(ConcentricConstraintCommand::with_first)
|
||||
.unwrap_or_else(ConcentricConstraintCommand::new);
|
||||
self.command_line.push_info(&command.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(command));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -834,6 +834,23 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
.active_cmd
|
||||
.as_ref()
|
||||
.is_some_and(|cmd| !cmd.needs_entity_pick() && !cmd.is_selection_gathering());
|
||||
let constraint_cursor_badge = if is_paper {
|
||||
None
|
||||
} else {
|
||||
tab.scene.hover_highlight.and_then(|handle| {
|
||||
tab.scene
|
||||
.parametric_constraint_set(tab.current_parametric_scope())
|
||||
.and_then(|set| {
|
||||
set.constraints_touching(handle)
|
||||
.find(|constraint| {
|
||||
constraint.kind
|
||||
== crate::scene::parametric_constraints::ConstraintKind::Concentric
|
||||
})
|
||||
.or_else(|| set.constraints_touching(handle).next())
|
||||
})
|
||||
.map(|constraint| constraint.kind.glyph_symbol().to_string())
|
||||
})
|
||||
};
|
||||
let constraint_glyphs: Vec<(
|
||||
iced::Point,
|
||||
[f32; 2],
|
||||
@@ -912,6 +929,7 @@ bg={bg_ms:.1}ms n={view_count}"
|
||||
constraint_glyphs,
|
||||
self.constraint_glyph_tooltip
|
||||
.map(|kind| crate::t!(kind.label()).into_owned()),
|
||||
constraint_cursor_badge,
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
Reference in new issue
Block a user