Feature fields: a type for each role (Expr, BodyName, FacePick…) (#1273)
Thanks @jijinbei.
This commit is contained in:
1 parent
3333f8a62b
commit
44968dbfe6
59 files changed
+1505
-1043
No files matched your search
+100
-84
@@ -637,7 +637,7 @@ impl Dialog {
|
||||
let preselection: &[Sel] = if matches!(d.kind, Kind::Text(_)) { &[] } else { &s.selection };
|
||||
for sel in preselection {
|
||||
let as_body = match sel {
|
||||
Sel::Face { body, .. } | Sel::Edge { body, .. } | Sel::Vertex { body, .. } => Some(Sel::Body { name: body.clone() }),
|
||||
Sel::Face { body, .. } | Sel::Edge { body, .. } | Sel::Vertex { body, .. } => Some(Sel::Body { name: body.to_string() }),
|
||||
_ => None,
|
||||
};
|
||||
if let Some(b) = as_body
|
||||
@@ -3343,7 +3343,7 @@ pub fn apply_commands(app: &SolveApp, d: &Dialog) -> Result<Vec<(String, Value)>
|
||||
};
|
||||
if let Some(sketch) = original_all
|
||||
&& !d.profile_selection_changed
|
||||
&& let Some(ss) = app.session.world_state().sketch(sketch)
|
||||
&& let Some(ss) = app.session.world_state().sketch(sketch.0)
|
||||
{
|
||||
let mut selected: Vec<usize> = sels(d, 0)
|
||||
.iter()
|
||||
@@ -3483,7 +3483,7 @@ fn dialog_commands(app: &SolveApp, d: &Dialog) -> Result<Vec<(String, Value)>, S
|
||||
_ => None,
|
||||
});
|
||||
let has_all = |id: u64| curves.iter().all(|c| st.sketch(id).is_some_and(|ss| ss.sketch.curve_index(c).is_some()));
|
||||
let sketch = match sketch.or(edited) {
|
||||
let sketch = match sketch.or(edited.map(u64::from)) {
|
||||
Some(id) if has_all(id) => id,
|
||||
_ => curves_sketch(app, &curves, None).ok_or("the curves must be in one sketch")?,
|
||||
};
|
||||
@@ -4248,14 +4248,15 @@ fn emboss_face_sel(s: &Session, component: u64, face: &solidcraft_engine::doc::E
|
||||
let owner = s.doc.model_body_component(body);
|
||||
let world_name = s.doc.world_body_name(&source, &face.body, owner, &face.path);
|
||||
let author = solidcraft_engine::doc::EmbossFace::component_frame(&s.doc, component, &face.author_path).ok()?;
|
||||
let point = solidcraft_engine::doc::apply_point(&author, face.at);
|
||||
let point = solidcraft_engine::doc::apply_point(&author, face.at.0);
|
||||
s.world_state().body(&world_name)?;
|
||||
Some(Sel::Face { body: world_name, index, point })
|
||||
}
|
||||
|
||||
pub(crate) fn plane_sel(s: &Session, pl: &PlaneRef) -> Option<Sel> {
|
||||
match pl {
|
||||
PlaneRef::Origin { name } | PlaneRef::Construction { name } => Some(Sel::Plane { name: name.clone() }),
|
||||
PlaneRef::Origin { name } => Some(Sel::Plane { name: name.clone() }),
|
||||
PlaneRef::Construction { name } => Some(Sel::Plane { name: name.to_string() }),
|
||||
PlaneRef::Custom { plane } | PlaneRef::Face { plane, .. } => face_sel(s, plane.origin),
|
||||
_ => None,
|
||||
}
|
||||
@@ -4299,7 +4300,7 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
FeatureKind::Extrude { sketch, profiles, extent, operation, targets, thin } => {
|
||||
let mut d = start("solid.extrude")?;
|
||||
d.kind = Kind::Extrude {
|
||||
distance: extent.distance.clone(),
|
||||
distance: extent.distance.to_string(),
|
||||
direction: match (extent.direction, &extent.distance2) {
|
||||
(_, Some(_)) => TWO_SIDES,
|
||||
(Direction::Positive, None) => 0,
|
||||
@@ -4309,16 +4310,16 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
operation: op_index(operation),
|
||||
auto_op: false,
|
||||
smart: crate::smart_extrude::Smart { manual_dir: true, ..Default::default() },
|
||||
distance2: extent.distance2.clone().unwrap_or_else(|| "10 mm".into()),
|
||||
taper: extent.taper.clone().unwrap_or_else(|| "0 deg".into()),
|
||||
distance2: extent.distance2.as_deref().map(str::to_string).unwrap_or_else(|| "10 mm".into()),
|
||||
taper: extent.taper.as_deref().map(str::to_string).unwrap_or_else(|| "0 deg".into()),
|
||||
taper_present: extent.taper.is_some(),
|
||||
to_offset: extent.to_offset.clone().unwrap_or_default(),
|
||||
start: extent.start_offset.clone().unwrap_or_default(),
|
||||
to_offset: extent.to_offset.as_deref().map(str::to_string).unwrap_or_default(),
|
||||
start: extent.start_offset.as_deref().map(str::to_string).unwrap_or_default(),
|
||||
all: extent.through_all,
|
||||
thin: thin.is_some(),
|
||||
wall: thin.as_ref().map_or_else(|| "2 mm".into(), |t| t.thickness.clone()),
|
||||
wall: thin.as_ref().map_or_else(|| "2 mm".into(), |t| t.thickness.to_string()),
|
||||
wall_side: thin.as_ref().map_or(0, |t| WALL_SIDES.iter().position(|w| ThinSide::parse(w) == Some(t.side)).unwrap_or(0)),
|
||||
wall2: thin.as_ref().and_then(|t| t.thickness2.clone()).unwrap_or_else(|| "1 mm".into()),
|
||||
wall2: thin.as_ref().and_then(|t| t.thickness2.as_deref().map(str::to_string)).unwrap_or_else(|| "1 mm".into()),
|
||||
};
|
||||
d.extra.insert("convention".into(), json!(extent.convention));
|
||||
// Extent references belong to the extrude's authoring frame, including free
|
||||
@@ -4328,7 +4329,7 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
if let Some(point) = point {
|
||||
set_object(&mut d.inputs, &mut d.active, label, true);
|
||||
if let Some(input) = d.inputs.iter_mut().find(|i| i.label == label) {
|
||||
input.items = vec![Sel::Vertex { body: String::new(), point: solidcraft_engine::doc::apply_point(&frame, point) }];
|
||||
input.items = vec![Sel::Vertex { body: String::new(), point: solidcraft_engine::doc::apply_point(&frame, point.0) }];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4338,9 +4339,9 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
inp.items = thin.curves.iter().map(|id| Sel::SketchCurve { id: id.clone() }).collect();
|
||||
}
|
||||
} else {
|
||||
let items = st.sketch(*sketch).map(|ss| profile_indices(ss, profiles)).unwrap_or_default();
|
||||
let items = st.sketch(sketch.0).map(|ss| profile_indices(ss, profiles)).unwrap_or_default();
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = items.into_iter().map(|index| Sel::Profile { sketch: *sketch, index }).collect();
|
||||
inp.items = items.into_iter().map(|index| Sel::Profile { sketch: sketch.0, index }).collect();
|
||||
}
|
||||
}
|
||||
if !targets.is_empty() {
|
||||
@@ -4353,12 +4354,12 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
let frame = feature_frame(s, f.component);
|
||||
let stored_axis = match axis {
|
||||
AxisRef::Line { origin, dir } => Some(json!({
|
||||
"origin": pt(solidcraft_engine::doc::apply_point(&frame, *origin)),
|
||||
"dir": pt(solidcraft_engine::doc::apply_vector(&frame, *dir))
|
||||
"origin": pt(solidcraft_engine::doc::apply_point(&frame, origin.0)),
|
||||
"dir": pt(solidcraft_engine::doc::apply_vector(&frame, dir.0))
|
||||
})),
|
||||
_ => None,
|
||||
};
|
||||
d.kind = Kind::Revolve { angle: angle.clone(), operation: op_index(operation), axis: stored_axis };
|
||||
d.kind = Kind::Revolve { angle: angle.to_string(), operation: op_index(operation), axis: stored_axis };
|
||||
d.extra.insert("convention".into(), json!(convention));
|
||||
if let Some(a2) = angle2 {
|
||||
d.extra.insert("angle2".into(), json!(a2));
|
||||
@@ -4369,12 +4370,12 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
if let Some(point) = to {
|
||||
set_to_object(&mut d.inputs, &mut d.active, true);
|
||||
if let Some(input) = d.inputs.iter_mut().find(|i| i.label == TO_OBJECT) {
|
||||
input.items = vec![Sel::Vertex { body: String::new(), point: solidcraft_engine::doc::apply_point(&frame, *point) }];
|
||||
input.items = vec![Sel::Vertex { body: String::new(), point: solidcraft_engine::doc::apply_point(&frame, point.0) }];
|
||||
}
|
||||
}
|
||||
let items = st.sketch(*sketch).map(|ss| profile_indices(ss, profiles)).unwrap_or_default();
|
||||
let items = st.sketch(sketch.0).map(|ss| profile_indices(ss, profiles)).unwrap_or_default();
|
||||
if let Some(inp) = d.inputs.get_mut(0) {
|
||||
inp.items = items.into_iter().map(|index| Sel::Profile { sketch: *sketch, index }).collect();
|
||||
inp.items = items.into_iter().map(|index| Sel::Profile { sketch: sketch.0, index }).collect();
|
||||
}
|
||||
let ax = match axis {
|
||||
AxisRef::World { axis } => Some(Sel::Axis { name: axis.to_ascii_uppercase() }),
|
||||
@@ -4400,10 +4401,10 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
if let FeatureKind::Chamfer { distance2: d2, angle: a, flip: f, .. } = &f.kind {
|
||||
if let Some(v) = d2 {
|
||||
*ctype = 1;
|
||||
*distance2 = v.clone();
|
||||
*distance2 = v.to_string();
|
||||
} else if let Some(v) = a {
|
||||
*ctype = 2;
|
||||
*angle = v.clone();
|
||||
*angle = v.to_string();
|
||||
}
|
||||
*flip = *f;
|
||||
}
|
||||
@@ -4446,51 +4447,51 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
FilletStyle::Constant | FilletStyle::Chord | FilletStyle::Curvature => {}
|
||||
}
|
||||
// The start was the first edge's last point: ends swapped.
|
||||
let first_end = edges.first().and_then(|p| edge_sel(s, *p)).and_then(|x| match x {
|
||||
let first_end = edges.first().and_then(|p| edge_sel(s, p.0)).and_then(|x| match x {
|
||||
Sel::Edge { body, index, .. } => {
|
||||
s.world_state().body(&body).and_then(|b| b.mesh().edges.get(index).and_then(|e| e.last().copied()))
|
||||
}
|
||||
_ => None,
|
||||
});
|
||||
let swapped = first_end.is_some_and(|e| e.dist(*start) < 1e-6);
|
||||
let swapped = first_end.is_some_and(|e| e.dist(start.0) < 1e-6);
|
||||
d.extra.insert("swap_ends".into(), json!(swapped));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = edges.iter().filter_map(|p| edge_sel(s, *p)).collect();
|
||||
inp.items = edges.iter().filter_map(|p| edge_sel(s, p.0)).collect();
|
||||
}
|
||||
d
|
||||
}
|
||||
FeatureKind::Shell { faces, thickness, direction, tangent_chain, .. } => {
|
||||
let mut d = start("solid.shell")?;
|
||||
d.kind = Kind::Shell { thickness: thickness.clone() };
|
||||
d.kind = Kind::Shell { thickness: thickness.to_string() };
|
||||
d.extra.insert("tangent_chain".into(), json!(tangent_chain));
|
||||
if !direction.is_empty() && direction != "inside" {
|
||||
d.extra.insert("direction".into(), json!(direction));
|
||||
}
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = faces.iter().filter_map(|p| face_sel(s, *p)).collect();
|
||||
inp.items = faces.iter().filter_map(|p| face_sel(s, p.0)).collect();
|
||||
}
|
||||
d
|
||||
}
|
||||
FeatureKind::Draft { faces, angle, neutral, pull, .. } => {
|
||||
let mut d = start("solid.draft")?;
|
||||
d.kind = Kind::Draft { angle: angle.clone() };
|
||||
d.kind = Kind::Draft { angle: angle.to_string() };
|
||||
if let Some(inp) = d.inputs.get_mut(0) {
|
||||
inp.items = faces.iter().filter_map(|p| face_sel(s, *p)).collect();
|
||||
inp.items = faces.iter().filter_map(|p| face_sel(s, p.0)).collect();
|
||||
}
|
||||
if let Some(inp) = d.inputs.get_mut(1) {
|
||||
inp.items = plane_sel(s, neutral).into_iter().collect();
|
||||
}
|
||||
d.extra.insert("pull".into(), pt3(*pull));
|
||||
d.extra.insert("pull".into(), pt3(pull.0));
|
||||
d
|
||||
}
|
||||
FeatureKind::Hole { position, direction, diameter, depth, hole, points, thread, to } => {
|
||||
let mut d = start("solid.hole")?;
|
||||
let mut k = hole_defaults();
|
||||
if let Kind::Hole { diameter: dia, depth: dep, kind, cb_diameter, cb_depth, cs_diameter, cs_angle, opts } = &mut k {
|
||||
*dia = diameter.clone();
|
||||
*dia = diameter.to_string();
|
||||
opts.all = depth.is_none();
|
||||
opts.angled = matches!(hole, HoleKind::Drilled { .. });
|
||||
opts.multiple = points.is_some();
|
||||
@@ -4499,21 +4500,21 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
opts.thread = th.clone();
|
||||
}
|
||||
if let Some(dd) = depth {
|
||||
*dep = dd.clone();
|
||||
*dep = dd.to_string();
|
||||
}
|
||||
match hole {
|
||||
HoleKind::Counterbore { cb_diameter: a, cb_depth: b } => {
|
||||
*kind = 1;
|
||||
*cb_diameter = a.clone();
|
||||
*cb_depth = b.clone();
|
||||
*cb_diameter = a.to_string();
|
||||
*cb_depth = b.to_string();
|
||||
}
|
||||
HoleKind::Countersink { cs_diameter: a, cs_angle: b } => {
|
||||
*kind = 2;
|
||||
*cs_diameter = a.clone();
|
||||
*cs_angle = b.clone();
|
||||
*cs_diameter = a.to_string();
|
||||
*cs_angle = b.to_string();
|
||||
}
|
||||
HoleKind::Drilled { tip_angle } => {
|
||||
opts.tip_angle = tip_angle.clone();
|
||||
opts.tip_angle = tip_angle.to_string();
|
||||
}
|
||||
HoleKind::Simple => {}
|
||||
}
|
||||
@@ -4531,16 +4532,16 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
}
|
||||
None => {
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = vec![face_sel(s, *position).unwrap_or(Sel::Face { body: String::new(), index: 0, point: *position })];
|
||||
inp.items = vec![face_sel(s, position.0).unwrap_or(Sel::Face { body: String::new(), index: 0, point: position.0 })];
|
||||
}
|
||||
d.extra.insert("direction".into(), pt3(*direction));
|
||||
d.extra.insert("direction".into(), pt3(direction.0));
|
||||
}
|
||||
}
|
||||
if to.is_some() {
|
||||
if let Kind::Hole { opts, .. } = &mut d.kind {
|
||||
opts.all = false;
|
||||
}
|
||||
with_to_object(&mut d, s, *to);
|
||||
with_to_object(&mut d, s, to.map(Vec3::from));
|
||||
}
|
||||
// A hole at every point of a sketch.
|
||||
if points.as_ref().is_some_and(|sp| sp.ids.is_empty()) {
|
||||
@@ -4568,7 +4569,7 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
at: None,
|
||||
};
|
||||
d.extra.insert("base".into(), pt_expr(base));
|
||||
d.extra.insert("axis".into(), pt3(*axis));
|
||||
d.extra.insert("axis".into(), pt3(axis.0));
|
||||
d
|
||||
}
|
||||
FeatureKind::Sphere { center, radius, operation } => {
|
||||
@@ -4593,10 +4594,10 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
let mut d = start("solid.boundary_fill")?;
|
||||
// The cells again, ticked where a stored cell point lies in the same cell.
|
||||
let before = s.model.state_before(f.id);
|
||||
let found = fill_cells(&before, tools);
|
||||
let found = fill_cells(&before, &solidcraft_engine::doc::plain(tools));
|
||||
let filled: Vec<String> =
|
||||
cells.iter().filter_map(|c| found.iter().min_by(|a, b| a.0.dist(*c).total_cmp(&b.0.dist(*c))).map(|x| x.1.clone())).collect();
|
||||
let items: Vec<Sel> = tools.iter().map(|n| Sel::Body { name: n.clone() }).collect();
|
||||
cells.iter().filter_map(|c| found.iter().min_by(|a, b| a.0.dist(c.0).total_cmp(&b.0.dist(c.0))).map(|x| x.1.clone())).collect();
|
||||
let items: Vec<Sel> = tools.iter().map(|n| Sel::Body { name: n.to_string() }).collect();
|
||||
d.kind = Kind::BoundaryFill {
|
||||
operation: op_index(operation),
|
||||
cells: found.into_iter().map(|(p, l)| (p, l.clone(), filled.contains(&l))).collect(),
|
||||
@@ -4614,10 +4615,10 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
let mut d = start("solid.combine")?;
|
||||
d.kind = Kind::Combine { operation: op_index(operation).max(1), keep_tools: *keep_tools };
|
||||
if let Some(inp) = d.inputs.get_mut(0) {
|
||||
inp.items = vec![Sel::Body { name: target.clone() }];
|
||||
inp.items = vec![Sel::Body { name: target.to_string() }];
|
||||
}
|
||||
if let Some(inp) = d.inputs.get_mut(1) {
|
||||
inp.items = tools.iter().map(|n| Sel::Body { name: n.clone() }).collect();
|
||||
inp.items = tools.iter().map(|n| Sel::Body { name: n.to_string() }).collect();
|
||||
}
|
||||
d
|
||||
}
|
||||
@@ -4628,7 +4629,7 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
let as_features = ids.iter().any(|id| !st.bodies.iter().any(|b| b.feature == *id));
|
||||
if let Some(inp) = d.inputs.get_mut(0) {
|
||||
if !bodies.is_empty() {
|
||||
inp.items = bodies.iter().map(|name| Sel::Body { name: name.clone() }).collect();
|
||||
inp.items = bodies.iter().map(|name| Sel::Body { name: name.to_string() }).collect();
|
||||
} else if as_features {
|
||||
inp.accept = selection::FEATURES;
|
||||
inp.label = objects_label(inp.accept);
|
||||
@@ -4647,28 +4648,28 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
let bodies: Vec<Sel> = if copied.is_empty() {
|
||||
st.bodies.iter().filter(|b| ids.contains(&b.feature)).map(|b| Sel::Body { name: b.name.clone() }).collect()
|
||||
} else {
|
||||
copied.iter().map(|name| Sel::Body { name: name.clone() }).collect()
|
||||
copied.iter().map(|name| Sel::Body { name: name.to_string() }).collect()
|
||||
};
|
||||
let mut d = match pattern {
|
||||
PatternKind::Rectangular { dir1, count1, spacing1, dir2, count2, spacing2 } => {
|
||||
let mut d = start("solid.pattern.rectangular")?;
|
||||
d.kind = Kind::PatternRect {
|
||||
count: count1.clone(),
|
||||
spacing: spacing1.clone(),
|
||||
count2: count2.clone().unwrap_or_else(|| "1".into()),
|
||||
spacing2: spacing2.clone().unwrap_or_else(|| "20 mm".into()),
|
||||
count: count1.to_string(),
|
||||
spacing: spacing1.to_string(),
|
||||
count2: count2.as_deref().map(str::to_string).unwrap_or_else(|| "1".into()),
|
||||
spacing2: spacing2.as_deref().map(str::to_string).unwrap_or_else(|| "20 mm".into()),
|
||||
};
|
||||
// Directions along the origin axes show as those axes; others are kept as is.
|
||||
for (i, (key, dir)) in [("dir1", Some(*dir1)), ("dir2", *dir2)].into_iter().enumerate() {
|
||||
let Some(dir) = dir else { continue };
|
||||
match world_axis(dir) {
|
||||
match world_axis(dir.0) {
|
||||
Some(name) => {
|
||||
if let Some(inp) = d.inputs.get_mut(i + 1) {
|
||||
inp.items = vec![Sel::Axis { name }];
|
||||
}
|
||||
}
|
||||
None => {
|
||||
d.extra.insert(key.into(), pt3(dir));
|
||||
d.extra.insert(key.into(), pt3(dir.0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4676,15 +4677,15 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
}
|
||||
PatternKind::Circular { origin, axis, count, angle } => {
|
||||
let mut d = start("solid.pattern.circular")?;
|
||||
d.kind = Kind::PatternCirc { count: count.clone(), angle: angle.clone() };
|
||||
match world_axis(*axis).filter(|_| origin.len() < 1e-9) {
|
||||
d.kind = Kind::PatternCirc { count: count.to_string(), angle: angle.to_string() };
|
||||
match world_axis(axis.0).filter(|_| origin.len() < 1e-9) {
|
||||
Some(name) => {
|
||||
if let Some(inp) = d.inputs.get_mut(1) {
|
||||
inp.items = vec![Sel::Axis { name }];
|
||||
}
|
||||
}
|
||||
None => {
|
||||
d.extra.insert("axis".into(), json!({"origin": pt3(*origin), "dir": pt3(*axis)}));
|
||||
d.extra.insert("axis".into(), json!({"origin": pt3(origin.0), "dir": pt3(axis.0)}));
|
||||
}
|
||||
}
|
||||
d
|
||||
@@ -4712,8 +4713,8 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
inp.items = sections
|
||||
.iter()
|
||||
.flat_map(|sec| {
|
||||
let idx = st.sketch(sec.sketch).map(|ss| profile_indices(ss, &sec.profiles)).unwrap_or_default();
|
||||
idx.into_iter().map(move |index| Sel::Profile { sketch: sec.sketch, index })
|
||||
let idx = st.sketch(sec.sketch.0).map(|ss| profile_indices(ss, &sec.profiles)).unwrap_or_default();
|
||||
idx.into_iter().map(move |index| Sel::Profile { sketch: sec.sketch.0, index })
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
@@ -4729,9 +4730,9 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
if let Some(inp) = d.inputs.get_mut(2) {
|
||||
inp.items = direction.into_iter().collect();
|
||||
}
|
||||
let items = st.sketch(*sketch).map(|ss| profile_indices(ss, profiles)).unwrap_or_default();
|
||||
let items = st.sketch(sketch.0).map(|ss| profile_indices(ss, profiles)).unwrap_or_default();
|
||||
if let Some(inp) = d.inputs.get_mut(0) {
|
||||
inp.items = items.into_iter().map(|index| Sel::Profile { sketch: *sketch, index }).collect();
|
||||
inp.items = items.into_iter().map(|index| Sel::Profile { sketch: sketch.0, index }).collect();
|
||||
}
|
||||
if let Some(inp) = d.inputs.get_mut(1) {
|
||||
inp.items = path.iter().map(|id| Sel::SketchCurve { id: id.clone() }).collect();
|
||||
@@ -4743,7 +4744,7 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
}
|
||||
FeatureKind::ConstructionPlane { plane: PlaneRef::Offset { base, distance } } => {
|
||||
let mut d = start("construct.plane.offset")?;
|
||||
d.kind = Kind::OffsetPlane { offset: distance.clone() };
|
||||
d.kind = Kind::OffsetPlane { offset: distance.to_string() };
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = plane_sel(s, base).into_iter().collect();
|
||||
}
|
||||
@@ -4760,7 +4761,7 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
d.kind = Kind::PathPlane { t: t.clone(), sketch };
|
||||
d.kind = Kind::PathPlane { t: t.to_string(), sketch };
|
||||
if let Some(input) = d.inputs.first_mut() {
|
||||
input.items = vec![item];
|
||||
}
|
||||
@@ -4768,7 +4769,7 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
}
|
||||
FeatureKind::ConstructionPlane { plane: PlaneRef::AtAngle { base, axis_origin, axis_dir, angle } } => {
|
||||
let mut d = start("construct.plane.at_angle")?;
|
||||
d.kind = Kind::AnglePlane { angle: angle.clone() };
|
||||
d.kind = Kind::AnglePlane { angle: angle.to_string() };
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = plane_sel(s, base).into_iter().collect();
|
||||
}
|
||||
@@ -4787,11 +4788,11 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
FeatureKind::Split { body, plane, tool } => {
|
||||
let mut d = start("solid.split_body")?;
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = vec![Sel::Body { name: body.clone() }];
|
||||
inp.items = vec![Sel::Body { name: body.to_string() }];
|
||||
}
|
||||
if let Some(inp) = d.inputs.get_mut(1) {
|
||||
inp.items = match tool {
|
||||
Some(t) => face_sel(s, t.point).into_iter().collect(),
|
||||
Some(t) => face_sel(s, t.point.0).into_iter().collect(),
|
||||
None => plane_sel(s, plane).into_iter().collect(),
|
||||
};
|
||||
}
|
||||
@@ -4799,11 +4800,11 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
}
|
||||
FeatureKind::Scale { bodies, origin, factor, factors } => {
|
||||
let mut d = start("solid.scale")?;
|
||||
d.kind = Kind::Scale { factor: factor.clone() };
|
||||
d.kind = Kind::Scale { factor: factor.to_string() };
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = bodies.iter().map(|n| Sel::Body { name: n.clone() }).collect();
|
||||
inp.items = bodies.iter().map(|n| Sel::Body { name: n.to_string() }).collect();
|
||||
}
|
||||
d.extra.insert("origin".into(), pt3(*origin));
|
||||
d.extra.insert("origin".into(), pt3(origin.0));
|
||||
if let Some(f) = factors {
|
||||
d.extra.insert("factors".into(), json!(f));
|
||||
}
|
||||
@@ -4811,9 +4812,9 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
}
|
||||
FeatureKind::OffsetFace { faces, distance, body } => {
|
||||
let mut d = start("solid.offset_face")?;
|
||||
d.kind = Kind::OffsetFaces { distance: distance.clone() };
|
||||
d.kind = Kind::OffsetFaces { distance: distance.to_string() };
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = faces.iter().filter_map(|p| face_sel(s, *p)).collect();
|
||||
inp.items = faces.iter().filter_map(|p| face_sel(s, p.0)).collect();
|
||||
}
|
||||
if let Some(b) = body {
|
||||
d.extra.insert("body".into(), json!(b));
|
||||
@@ -4825,23 +4826,26 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
if *modeled {
|
||||
d.extra.insert("modeled".into(), json!(true));
|
||||
}
|
||||
d.kind = Kind::Thread { designation: designation.clone().unwrap_or_default(), length: length.clone().unwrap_or_default() };
|
||||
d.kind = Kind::Thread {
|
||||
designation: designation.clone().unwrap_or_default(),
|
||||
length: length.as_deref().map(str::to_string).unwrap_or_default(),
|
||||
};
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = face_sel(s, *face).into_iter().collect();
|
||||
inp.items = face_sel(s, face.0).into_iter().collect();
|
||||
}
|
||||
d
|
||||
}
|
||||
FeatureKind::BoundingSolid { bodies, margin } => {
|
||||
let mut d = start("solid.bounding_solid")?;
|
||||
d.kind = Kind::Stock { margin: margin.clone() };
|
||||
d.kind = Kind::Stock { margin: margin.to_string() };
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = bodies.iter().map(|n| Sel::Body { name: n.clone() }).collect();
|
||||
inp.items = bodies.iter().map(|n| Sel::Body { name: n.to_string() }).collect();
|
||||
}
|
||||
d
|
||||
}
|
||||
FeatureKind::Pipe { path, diameter, wall, operation, targets, .. } => {
|
||||
let mut d = start("solid.pipe")?;
|
||||
d.kind = Kind::Pipe { diameter: diameter.clone(), wall: wall.clone().unwrap_or_default() };
|
||||
d.kind = Kind::Pipe { diameter: diameter.to_string(), wall: wall.as_deref().map(str::to_string).unwrap_or_default() };
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = path.iter().map(|id| Sel::SketchCurve { id: id.clone() }).collect();
|
||||
}
|
||||
@@ -4853,10 +4857,10 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
}
|
||||
FeatureKind::Emboss { sketch, profiles, depth, deboss, targets, face } => {
|
||||
let mut d = start("solid.emboss")?;
|
||||
d.kind = Kind::Emboss { depth: depth.clone(), deboss: *deboss };
|
||||
let items = st.sketch(*sketch).map(|ss| profile_indices(ss, profiles)).unwrap_or_default();
|
||||
d.kind = Kind::Emboss { depth: depth.to_string(), deboss: *deboss };
|
||||
let items = st.sketch(sketch.0).map(|ss| profile_indices(ss, profiles)).unwrap_or_default();
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = items.into_iter().map(|index| Sel::Profile { sketch: *sketch, index }).collect();
|
||||
inp.items = items.into_iter().map(|index| Sel::Profile { sketch: sketch.0, index }).collect();
|
||||
}
|
||||
if !targets.is_empty() {
|
||||
d.extra.insert("targets".into(), json!(targets));
|
||||
@@ -4870,7 +4874,12 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
}
|
||||
FeatureKind::Rib { curves, thickness, depth, flip, web, .. } => {
|
||||
let mut d = start(if *web { "solid.web" } else { "solid.rib" })?;
|
||||
d.kind = Kind::Rib { web: *web, thickness: thickness.clone(), depth: depth.clone().unwrap_or_default(), flip: *flip };
|
||||
d.kind = Kind::Rib {
|
||||
web: *web,
|
||||
thickness: thickness.to_string(),
|
||||
depth: depth.as_deref().map(str::to_string).unwrap_or_default(),
|
||||
flip: *flip,
|
||||
};
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = curves.iter().map(|id| Sel::SketchCurve { id: id.clone() }).collect();
|
||||
}
|
||||
@@ -4879,7 +4888,7 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
FeatureKind::ReplaceFace { faces, target, body } => {
|
||||
let mut d = start("solid.replace_face")?;
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = faces.iter().filter_map(|p| face_sel(s, *p)).collect();
|
||||
inp.items = faces.iter().filter_map(|p| face_sel(s, p.0)).collect();
|
||||
}
|
||||
if let Some(inp) = d.inputs.get_mut(1) {
|
||||
inp.items = plane_sel(s, target).into_iter().collect();
|
||||
@@ -4892,13 +4901,20 @@ pub fn for_feature(app: &SolveApp, id: u64, marker: Option<usize>) -> Option<Dia
|
||||
FeatureKind::Remove { bodies } => {
|
||||
let mut d = start("solid.remove")?;
|
||||
if let Some(inp) = d.inputs.first_mut() {
|
||||
inp.items = bodies.iter().map(|n| Sel::Body { name: n.clone() }).collect();
|
||||
inp.items = bodies.iter().map(|n| Sel::Body { name: n.to_string() }).collect();
|
||||
}
|
||||
d
|
||||
}
|
||||
FeatureKind::Move { bodies, translate, rotate_axis, angle, copy } => {
|
||||
let mut d = start("solid.move")?;
|
||||
crate::dialogs_move::for_feature(&mut d, bodies, translate, *rotate_axis, angle.as_ref(), *copy);
|
||||
crate::dialogs_move::for_feature(
|
||||
&mut d,
|
||||
&solidcraft_engine::doc::plain(bodies),
|
||||
translate,
|
||||
rotate_axis.map(Vec3::from),
|
||||
angle.as_ref(),
|
||||
*copy,
|
||||
);
|
||||
d
|
||||
}
|
||||
other => {
|
||||
|
||||
Reference in new issue
Block a user