Track artifact commands and operations per-module (#7426)

* Change so that operations are stored per module

* Refactor so that all modeling commands go through ExecState

* Remove unneeded PartialOrd implementations

* Remove artifact_commands from KclError since it was only for debugging

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
Jonathan Tran
2025-06-10 21:30:48 -04:00
committed by GitHub
parent 851ea28bd3
commit 9a549ff379
479 changed files with 11575323 additions and 11565198 deletions

View File

@ -18,8 +18,8 @@ use crate::{
errors::{KclError, KclErrorDetails},
execution::{
types::{ArrayLen, NumericType, PrimitiveType, RuntimeType, UnitLen},
BasePath, ExecState, Face, GeoMeta, KclValue, Path, Plane, PlaneInfo, Point2d, Sketch, SketchSurface, Solid,
TagEngineInfo, TagIdentifier,
BasePath, ExecState, Face, GeoMeta, KclValue, ModelingCmdMeta, Path, Plane, PlaneInfo, Point2d, Sketch,
SketchSurface, Solid, TagEngineInfo, TagIdentifier,
},
parsing::ast::types::TagNode,
std::{
@ -133,19 +133,20 @@ async fn inner_involute_circular(
) -> Result<Sketch, KclError> {
let id = exec_state.next_uuid();
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::CircularInvolute {
start_radius: LengthUnit(start_radius.to_mm()),
end_radius: LengthUnit(end_radius.to_mm()),
angle: Angle::from_degrees(angle.to_degrees()),
reverse: reverse.unwrap_or_default(),
},
}),
)
.await?;
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from_args_id(&args, id),
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::CircularInvolute {
start_radius: LengthUnit(start_radius.to_mm()),
end_radius: LengthUnit(end_radius.to_mm()),
angle: Angle::from_degrees(angle.to_degrees()),
reverse: reverse.unwrap_or_default(),
},
}),
)
.await?;
let from = sketch.current_pen_position()?;
@ -284,17 +285,18 @@ async fn straight_line(
};
let id = exec_state.next_uuid();
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Line {
end: KPoint2d::from(point_to_mm(point.clone())).with_z(0.0).map(LengthUnit),
relative: !is_absolute,
},
}),
)
.await?;
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from_args_id(&args, id),
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Line {
end: KPoint2d::from(point_to_mm(point.clone())).with_z(0.0).map(LengthUnit),
relative: !is_absolute,
},
}),
)
.await?;
let end = if is_absolute {
point_to_len_unit(point, from.units)
@ -507,19 +509,20 @@ async fn inner_angled_line_length(
let id = exec_state.next_uuid();
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Line {
end: KPoint2d::from(untyped_point_to_mm(delta, from.units))
.with_z(0.0)
.map(LengthUnit),
relative,
},
}),
)
.await?;
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from_args_id(&args, id),
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Line {
end: KPoint2d::from(untyped_point_to_mm(delta, from.units))
.with_z(0.0)
.map(LengthUnit),
relative,
},
}),
)
.await?;
let current_path = Path::ToPoint {
base: BasePath {
@ -874,18 +877,19 @@ async fn make_sketch_plane_from_orientation(
let clobber = false;
let size = LengthUnit(60.0);
let hide = Some(true);
args.batch_modeling_cmd(
plane.id,
ModelingCmd::from(mcmd::MakePlane {
clobber,
origin: plane.info.origin.into(),
size,
x_axis: plane.info.x_axis.into(),
y_axis: plane.info.y_axis.into(),
hide,
}),
)
.await?;
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from_args_id(args, plane.id),
ModelingCmd::from(mcmd::MakePlane {
clobber,
origin: plane.info.origin.into(),
size,
x_axis: plane.info.x_axis.into(),
y_axis: plane.info.y_axis.into(),
hide,
}),
)
.await?;
Ok(Box::new(plane))
}
@ -917,20 +921,22 @@ pub(crate) async fn inner_start_profile(
SketchSurface::Face(face) => {
// Flush the batch for our fillets/chamfers if there are any.
// If we do not do these for sketch on face, things will fail with face does not exist.
args.flush_batch_for_solids(exec_state, &[(*face.solid).clone()])
exec_state
.flush_batch_for_solids((&args).into(), &[(*face.solid).clone()])
.await?;
}
SketchSurface::Plane(plane) if !plane.is_standard() => {
// Hide whatever plane we are sketching on.
// This is especially helpful for offset planes, which would be visible otherwise.
args.batch_end_cmd(
exec_state.next_uuid(),
ModelingCmd::from(mcmd::ObjectVisible {
object_id: plane.id,
hidden: true,
}),
)
.await?;
exec_state
.batch_end_cmd(
(&args).into(),
ModelingCmd::from(mcmd::ObjectVisible {
object_id: plane.id,
hidden: true,
}),
)
.await?;
}
_ => {}
}
@ -938,42 +944,47 @@ pub(crate) async fn inner_start_profile(
let enable_sketch_id = exec_state.next_uuid();
let path_id = exec_state.next_uuid();
let move_pen_id = exec_state.next_uuid();
args.batch_modeling_cmds(&[
// Enter sketch mode on the surface.
// We call this here so you can reuse the sketch surface for multiple sketches.
ModelingCmdReq {
cmd: ModelingCmd::from(mcmd::EnableSketchMode {
animated: false,
ortho: false,
entity_id: sketch_surface.id(),
adjust_camera: false,
planar_normal: if let SketchSurface::Plane(plane) = &sketch_surface {
// We pass in the normal for the plane here.
let normal = plane.info.x_axis.axes_cross_product(&plane.info.y_axis);
Some(normal.into())
} else {
None
let disable_sketch_id = exec_state.next_uuid();
exec_state
.batch_modeling_cmds(
(&args).into(),
&[
// Enter sketch mode on the surface.
// We call this here so you can reuse the sketch surface for multiple sketches.
ModelingCmdReq {
cmd: ModelingCmd::from(mcmd::EnableSketchMode {
animated: false,
ortho: false,
entity_id: sketch_surface.id(),
adjust_camera: false,
planar_normal: if let SketchSurface::Plane(plane) = &sketch_surface {
// We pass in the normal for the plane here.
let normal = plane.info.x_axis.axes_cross_product(&plane.info.y_axis);
Some(normal.into())
} else {
None
},
}),
cmd_id: enable_sketch_id.into(),
},
}),
cmd_id: enable_sketch_id.into(),
},
ModelingCmdReq {
cmd: ModelingCmd::from(mcmd::StartPath::default()),
cmd_id: path_id.into(),
},
ModelingCmdReq {
cmd: ModelingCmd::from(mcmd::MovePathPen {
path: path_id.into(),
to: KPoint2d::from(point_to_mm(at.clone())).with_z(0.0).map(LengthUnit),
}),
cmd_id: move_pen_id.into(),
},
ModelingCmdReq {
cmd: ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable::default()),
cmd_id: exec_state.next_uuid().into(),
},
])
.await?;
ModelingCmdReq {
cmd: ModelingCmd::from(mcmd::StartPath::default()),
cmd_id: path_id.into(),
},
ModelingCmdReq {
cmd: ModelingCmd::from(mcmd::MovePathPen {
path: path_id.into(),
to: KPoint2d::from(point_to_mm(at.clone())).with_z(0.0).map(LengthUnit),
}),
cmd_id: move_pen_id.into(),
},
ModelingCmdReq {
cmd: ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable::default()),
cmd_id: disable_sketch_id.into(),
},
],
)
.await?;
// Convert to the units of the module. This is what the frontend expects.
let units = exec_state.length_unit();
@ -1077,7 +1088,11 @@ pub(crate) async fn inner_close(
let id = exec_state.next_uuid();
args.batch_modeling_cmd(id, ModelingCmd::from(mcmd::ClosePath { path_id: sketch.id }))
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from_args_id(&args, id),
ModelingCmd::from(mcmd::ClosePath { path_id: sketch.id }),
)
.await?;
let current_path = Path::ToPoint {
@ -1178,26 +1193,27 @@ pub async fn absolute_arc(
tag: Option<TagNode>,
) -> Result<Sketch, KclError> {
// The start point is taken from the path you are extending.
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::ArcTo {
end: kcmc::shared::Point3d {
x: LengthUnit(end_absolute[0].to_mm()),
y: LengthUnit(end_absolute[1].to_mm()),
z: LengthUnit(0.0),
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from_args_id(args, id),
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::ArcTo {
end: kcmc::shared::Point3d {
x: LengthUnit(end_absolute[0].to_mm()),
y: LengthUnit(end_absolute[1].to_mm()),
z: LengthUnit(0.0),
},
interior: kcmc::shared::Point3d {
x: LengthUnit(interior_absolute[0].to_mm()),
y: LengthUnit(interior_absolute[1].to_mm()),
z: LengthUnit(0.0),
},
relative: false,
},
interior: kcmc::shared::Point3d {
x: LengthUnit(interior_absolute[0].to_mm()),
y: LengthUnit(interior_absolute[1].to_mm()),
z: LengthUnit(0.0),
},
relative: false,
},
}),
)
.await?;
}),
)
.await?;
let start = [from.x, from.y];
let end = point_to_len_unit(end_absolute, from.units);
@ -1252,20 +1268,21 @@ pub async fn relative_arc(
}
let ccw = a_start < a_end;
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Arc {
start: a_start,
end: a_end,
center: KPoint2d::from(untyped_point_to_mm(center, from.units)).map(LengthUnit),
radius: LengthUnit(from.units.adjust_to(radius, UnitLen::Mm).0),
relative: false,
},
}),
)
.await?;
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from_args_id(args, id),
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Arc {
start: a_start,
end: a_end,
center: KPoint2d::from(untyped_point_to_mm(center, from.units)).map(LengthUnit),
radius: LengthUnit(from.units.adjust_to(radius, UnitLen::Mm).0),
relative: false,
},
}),
)
.await?;
let current_path = Path::Arc {
base: BasePath {
@ -1421,17 +1438,18 @@ async fn inner_tangential_arc_radius_angle(
radius.to_length_units(from.units),
);
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::TangentialArc {
radius: LengthUnit(radius.to_mm()),
offset,
},
}),
)
.await?;
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from_args_id(&args, id),
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::TangentialArc {
radius: LengthUnit(radius.to_mm()),
offset,
},
}),
)
.await?;
(center, to, ccw)
}
};
@ -1521,7 +1539,9 @@ async fn inner_tangential_arc_to_point(
point
};
let id = exec_state.next_uuid();
args.batch_modeling_cmd(id, tan_arc_to(&sketch, delta)).await?;
exec_state
.batch_modeling_cmd(ModelingCmdMeta::from_args_id(&args, id), tan_arc_to(&sketch, delta))
.await?;
let current_path = Path::TangentialArcTo {
base: BasePath {
@ -1609,37 +1629,39 @@ async fn inner_bezier_curve(
from.y + end[1].to_length_units(from.units),
];
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Bezier {
control1: KPoint2d::from(point_to_mm(control1)).with_z(0.0).map(LengthUnit),
control2: KPoint2d::from(point_to_mm(control2)).with_z(0.0).map(LengthUnit),
end: KPoint2d::from(point_to_mm(delta)).with_z(0.0).map(LengthUnit),
relative: true,
},
}),
)
.await?;
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from_args_id(&args, id),
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Bezier {
control1: KPoint2d::from(point_to_mm(control1)).with_z(0.0).map(LengthUnit),
control2: KPoint2d::from(point_to_mm(control2)).with_z(0.0).map(LengthUnit),
end: KPoint2d::from(point_to_mm(delta)).with_z(0.0).map(LengthUnit),
relative: true,
},
}),
)
.await?;
to
}
// Absolute
(None, None, None, Some(control1), Some(control2), Some(end)) => {
let to = [end[0].to_length_units(from.units), end[1].to_length_units(from.units)];
args.batch_modeling_cmd(
id,
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Bezier {
control1: KPoint2d::from(point_to_mm(control1)).with_z(0.0).map(LengthUnit),
control2: KPoint2d::from(point_to_mm(control2)).with_z(0.0).map(LengthUnit),
end: KPoint2d::from(point_to_mm(end)).with_z(0.0).map(LengthUnit),
relative: false,
},
}),
)
.await?;
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from_args_id(&args, id),
ModelingCmd::from(mcmd::ExtendPath {
path: sketch.id.into(),
segment: PathSegment::Bezier {
control1: KPoint2d::from(point_to_mm(control1)).with_z(0.0).map(LengthUnit),
control2: KPoint2d::from(point_to_mm(control2)).with_z(0.0).map(LengthUnit),
end: KPoint2d::from(point_to_mm(end)).with_z(0.0).map(LengthUnit),
relative: false,
},
}),
)
.await?;
to
}
_ => {
@ -1699,25 +1721,27 @@ async fn inner_subtract_2d(
args: Args,
) -> Result<Sketch, KclError> {
for hole_sketch in tool {
args.batch_modeling_cmd(
exec_state.next_uuid(),
ModelingCmd::from(mcmd::Solid2dAddHole {
object_id: sketch.id,
hole_id: hole_sketch.id,
}),
)
.await?;
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from(&args),
ModelingCmd::from(mcmd::Solid2dAddHole {
object_id: sketch.id,
hole_id: hole_sketch.id,
}),
)
.await?;
// suggestion (mike)
// we also hide the source hole since its essentially "consumed" by this operation
args.batch_modeling_cmd(
exec_state.next_uuid(),
ModelingCmd::from(mcmd::ObjectVisible {
object_id: hole_sketch.id,
hidden: true,
}),
)
.await?;
exec_state
.batch_modeling_cmd(
ModelingCmdMeta::from(&args),
ModelingCmd::from(mcmd::ObjectVisible {
object_id: hole_sketch.id,
hidden: true,
}),
)
.await?;
}
Ok(sketch)