Feature walks: generate them from field roles with #[derive(Walk)] (#1251)
The three walks over a feature (expressions, references, geometry) are generated from FeatureKind by #[derive(Walk)] in a new proc-macro crate, solidcraft-derive, from #[walk(...)] attributes written next to each field. The hand-written walks in params.rs, feature_refs.rs and feature_geometry.rs are gone; Ruled Surface and Extend have their attributes, and the three golden walk records are unchanged. Co-authored-by: jijinbei <jijinbei@users.noreply.github.com>
This commit is contained in:
1 parent
a026a69182
commit
464a6dfad4
13 files changed
+998
-937
No files matched your search
@@ -1,12 +1,12 @@
|
||||
//! References from a feature to the rest of the design: the sketches it is built from (by id),
|
||||
//! the features it names (patterned and mirrored features, the construction plane a plane is
|
||||
//! built on) and the bodies it works on (by name). One walk, written once for `&` and `&mut`,
|
||||
//! behind `input_sketches`, `remap_refs` and `remap_bodies`. Every variant is listed, so a new
|
||||
//! one has to say what it refers to.
|
||||
//! built on) and the bodies it works on (by name). The walk (`crate::walk`) is behind
|
||||
//! `input_sketches`, `remap_refs` and `remap_bodies`.
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::{FeatureKind, PatternKind, PlaneRef};
|
||||
use crate::FeatureKind;
|
||||
use crate::walk::Walk;
|
||||
|
||||
/// A reference a feature holds: `S` is `&u64` or `&mut u64` (a sketch id), `N` is `&String` or
|
||||
/// `&mut String` (a feature or body name).
|
||||
@@ -16,228 +16,7 @@ pub(crate) enum Ref<S, N> {
|
||||
Body(N),
|
||||
}
|
||||
|
||||
/// The construction plane a plane is built on (through offsets and angles), for `&` and `&mut`
|
||||
/// (`$m` is `mut` or nothing). Nesting is capped like every walk over a plane.
|
||||
macro_rules! plane_walk {
|
||||
($name:ident $(, $m:tt)?) => {
|
||||
fn $name<'a>(mut p: &'a $($m)? PlaneRef, f: &mut impl FnMut(Ref<&'a $($m)? u64, &'a $($m)? String>)) {
|
||||
for _ in 0..64 {
|
||||
match p {
|
||||
PlaneRef::Offset { base, .. } | PlaneRef::AtAngle { base, .. } => p = base,
|
||||
PlaneRef::Construction { name } => return f(Ref::Feature(name)),
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
plane_walk!(plane_refs);
|
||||
plane_walk!(plane_refs_mut, mut);
|
||||
|
||||
/// Every reference of a feature, written once for `&` and `&mut`: `$plane` is the matching plane
|
||||
/// walk, `$m` is `mut` or nothing.
|
||||
macro_rules! feature_walk {
|
||||
($name:ident, $plane:ident $(, $m:tt)?) => {
|
||||
pub(crate) fn $name<'a>(&'a $($m)? self, f: &mut impl FnMut(Ref<&'a $($m)? u64, &'a $($m)? String>)) {
|
||||
use Ref::{Body as B, Feature as F, Sketch as S};
|
||||
match self {
|
||||
FeatureKind::Sketch { plane, .. } | FeatureKind::ConstructionPlane { plane } => $plane(plane, f),
|
||||
FeatureKind::Extrude { sketch, targets, .. } | FeatureKind::Revolve { sketch, targets, .. } => {
|
||||
f(S(sketch));
|
||||
for b in targets {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::Emboss { sketch, targets, face, .. } => {
|
||||
f(S(sketch));
|
||||
if let Some(face) = face {
|
||||
f(B(& $($m)? face.body));
|
||||
}
|
||||
for b in targets {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::SurfaceExtrude { sketch, .. }
|
||||
| FeatureKind::SurfaceRevolve { sketch, .. }
|
||||
| FeatureKind::Rib { sketch, .. }
|
||||
| FeatureKind::SheetBase { sketch, .. }
|
||||
| FeatureKind::SheetContour { sketch, .. } => f(S(sketch)),
|
||||
FeatureKind::SurfaceSweep { sketch, path_sketch, .. } => {
|
||||
f(S(sketch));
|
||||
f(S(path_sketch));
|
||||
}
|
||||
FeatureKind::SurfaceLoft { sections } => {
|
||||
for s in sections {
|
||||
f(S(& $($m)? s.sketch));
|
||||
}
|
||||
}
|
||||
FeatureKind::Sweep { sketch, path_sketch, targets, .. } => {
|
||||
f(S(sketch));
|
||||
f(S(path_sketch));
|
||||
for b in targets {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::Pipe { path_sketch, targets, .. } => {
|
||||
f(S(path_sketch));
|
||||
for b in targets {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::Loft { sections, targets, .. } => {
|
||||
for s in sections {
|
||||
f(S(& $($m)? s.sketch));
|
||||
}
|
||||
for b in targets {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::Coil { targets, .. } => {
|
||||
for b in targets {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::Hole { points, .. } => {
|
||||
if let Some(p) = points {
|
||||
f(S(& $($m)? p.sketch));
|
||||
}
|
||||
}
|
||||
FeatureKind::Pattern { features, pattern, bodies } => {
|
||||
for n in features {
|
||||
f(F(n));
|
||||
}
|
||||
if let PatternKind::Path { path_sketch, .. } = pattern {
|
||||
f(S(path_sketch));
|
||||
}
|
||||
for b in bodies {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::Mirror { features, plane, bodies, .. } => {
|
||||
for n in features {
|
||||
f(F(n));
|
||||
}
|
||||
$plane(plane, f);
|
||||
for b in bodies {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::Split { body, plane, tool } | FeatureKind::SurfaceTrim { body, plane, tool, .. } => {
|
||||
f(B(body));
|
||||
$plane(plane, f);
|
||||
if let Some(t) = tool {
|
||||
f(B(& $($m)? t.body));
|
||||
}
|
||||
}
|
||||
FeatureKind::SplitFace { body, plane, tool, sketch, .. } => {
|
||||
$plane(plane, f);
|
||||
if let Some(s) = sketch {
|
||||
f(S(s));
|
||||
}
|
||||
if let Some(b) = body {
|
||||
f(B(b));
|
||||
}
|
||||
if let Some(t) = tool {
|
||||
f(B(& $($m)? t.body));
|
||||
}
|
||||
}
|
||||
FeatureKind::Draft { neutral: plane, body, .. } | FeatureKind::ReplaceFace { target: plane, body, .. } => {
|
||||
$plane(plane, f);
|
||||
if let Some(b) = body {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::SheetFold { sketch, body, .. } | FeatureKind::Patch { sketch, body, .. } => {
|
||||
if let Some(s) = sketch {
|
||||
f(S(s));
|
||||
}
|
||||
if let Some(b) = body {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::Fillet { body, .. }
|
||||
| FeatureKind::Chamfer { body, .. }
|
||||
| FeatureKind::Shell { body, .. }
|
||||
| FeatureKind::OffsetFace { body, .. }
|
||||
| FeatureKind::DeleteFace { body, .. }
|
||||
| FeatureKind::SheetFlange { body, .. }
|
||||
| FeatureKind::SheetHem { body, .. }
|
||||
| FeatureKind::SheetPerforate { body, .. }
|
||||
| FeatureKind::SheetUnfold { body, .. }
|
||||
| FeatureKind::Boss { body, .. }
|
||||
| FeatureKind::Lip { body, .. }
|
||||
| FeatureKind::SnapFit { body, .. }
|
||||
| FeatureKind::Rest { body, .. }
|
||||
| FeatureKind::SurfaceOffset { body, .. } => {
|
||||
if let Some(b) = body {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::SurfaceUntrim { face, .. } => f(B(& $($m)? face.body)),
|
||||
FeatureKind::SurfaceExtend { body, up_to, .. } => {
|
||||
f(B(body));
|
||||
match up_to {
|
||||
Some(crate::ExtendTo::Plane(plane)) => $plane(plane, f),
|
||||
Some(crate::ExtendTo::Face(t)) => f(B(& $($m)? t.body)),
|
||||
Some(crate::ExtendTo::Bounds) | None => {}
|
||||
}
|
||||
}
|
||||
FeatureKind::SheetConvert { body, .. }
|
||||
| FeatureKind::SurfaceRuled { body, .. }
|
||||
| FeatureKind::Unstitch { body, .. }
|
||||
| FeatureKind::ReverseNormal { body, .. }
|
||||
| FeatureKind::MeshConvert { body, .. } => f(B(body)),
|
||||
FeatureKind::Combine { target, tools, .. } => {
|
||||
f(B(target));
|
||||
for b in tools {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::Thicken { bodies, targets, .. } => {
|
||||
for b in bodies {
|
||||
f(B(b));
|
||||
}
|
||||
for b in targets {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::BodyTransfer { bodies, .. }
|
||||
| FeatureKind::Scale { bodies, .. }
|
||||
| FeatureKind::BoundingSolid { bodies, .. }
|
||||
| FeatureKind::Align { bodies, .. }
|
||||
| FeatureKind::Remove { bodies }
|
||||
| FeatureKind::Stitch { bodies, .. }
|
||||
| FeatureKind::Move { bodies, .. } => {
|
||||
for b in bodies {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
FeatureKind::BoundaryFill { tools, .. } => {
|
||||
for b in tools {
|
||||
f(B(b));
|
||||
}
|
||||
}
|
||||
// Construction axes and points refer to geometry, which copies remap on their own
|
||||
// (`Feature::remap_clone`).
|
||||
FeatureKind::ConstructionAxis { .. }
|
||||
| FeatureKind::ConstructionPoint { .. }
|
||||
| FeatureKind::Box { .. }
|
||||
| FeatureKind::Cylinder { .. }
|
||||
| FeatureKind::Sphere { .. }
|
||||
| FeatureKind::Torus { .. }
|
||||
| FeatureKind::Thread { .. }
|
||||
| FeatureKind::Import { .. }
|
||||
| FeatureKind::MeshImport { .. } => {}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl FeatureKind {
|
||||
feature_walk!(walk_refs, plane_refs);
|
||||
feature_walk!(walk_refs_mut, plane_refs_mut, mut);
|
||||
|
||||
/// Sketches the feature is built from (profiles, paths, points): deleting one of them
|
||||
/// deletes the feature.
|
||||
pub fn input_sketches(&self) -> Vec<u64> {
|
||||
|
||||
Reference in new issue
Block a user