Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 129 additions & 4 deletions rust/kcl-lib/src/execution/artifact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ impl CodeRef {
#[serde(rename_all = "camelCase")]
pub struct CompositeSolid {
pub id: ArtifactId,
/// Whether this artifact has been used in a subsequent operation
pub consumed: bool,
pub sub_type: CompositeSolidSubType,
/// Constituent solids of the composite solid.
pub solid_ids: Vec<ArtifactId>,
Expand Down Expand Up @@ -122,6 +124,8 @@ pub struct Path {
pub id: ArtifactId,
pub plane_id: ArtifactId,
pub seg_ids: Vec<ArtifactId>,
/// Whether this artifact has been used in a subsequent operation
pub consumed: bool,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sweep_id: Option<ArtifactId>,
#[serde(default, skip_serializing_if = "Option::is_none")]
Expand Down Expand Up @@ -167,6 +171,8 @@ pub struct Sweep {
pub edge_ids: Vec<ArtifactId>,
pub code_ref: CodeRef,
pub method: kittycad_modeling_cmds::shared::ExtrudeMethod,
/// Whether this artifact has been used in a subsequent operation
pub consumed: bool,
}

#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, ts_rs::TS)]
Expand Down Expand Up @@ -351,6 +357,9 @@ pub struct Helix {
/// add axes to the graph.
pub axis_id: Option<ArtifactId>,
pub code_ref: CodeRef,
pub sweep_id: Option<ArtifactId>,
/// Whether this artifact has been used in a subsequent operation
pub consumed: bool,
}

#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
Expand Down Expand Up @@ -459,7 +468,7 @@ impl Artifact {
Artifact::SweepEdge(_) => Some(new),
Artifact::EdgeCut(a) => a.merge(new),
Artifact::EdgeCutEdge(_) => Some(new),
Artifact::Helix(_) => Some(new),
Artifact::Helix(a) => a.merge(new),
}
}
}
Expand All @@ -472,6 +481,7 @@ impl CompositeSolid {
merge_ids(&mut self.solid_ids, new.solid_ids);
merge_ids(&mut self.tool_ids, new.tool_ids);
merge_opt_id(&mut self.composite_solid_id, new.composite_solid_id);
self.consumed = new.consumed;

None
}
Expand Down Expand Up @@ -499,6 +509,7 @@ impl Path {
merge_opt_id(&mut self.composite_solid_id, new.composite_solid_id);
merge_opt_id(&mut self.inner_path_id, new.inner_path_id);
merge_opt_id(&mut self.outer_path_id, new.outer_path_id);
self.consumed = new.consumed;

None
}
Expand All @@ -525,6 +536,7 @@ impl Sweep {
};
merge_ids(&mut self.surface_ids, new.surface_ids);
merge_ids(&mut self.edge_ids, new.edge_ids);
self.consumed = new.consumed;

None
}
Expand Down Expand Up @@ -566,6 +578,19 @@ impl EdgeCut {
}
}

impl Helix {
fn merge(&mut self, new: Artifact) -> Option<Artifact> {
let Artifact::Helix(new) = new else {
return Some(new);
};
merge_opt_id(&mut self.axis_id, new.axis_id);
merge_opt_id(&mut self.sweep_id, new.sweep_id);
self.consumed = new.consumed;

None
}
}

#[derive(Debug, Clone, Default, PartialEq, Serialize, ts_rs::TS)]
#[ts(export_to = "Artifact.ts")]
#[serde(rename_all = "camelCase")]
Expand Down Expand Up @@ -768,6 +793,7 @@ fn merge_ids(base: &mut Vec<ArtifactId>, new: Vec<ArtifactId>) {
}
}

/// Merge optional Artifact ID
fn merge_opt_id(base: &mut Option<ArtifactId>, new: Option<ArtifactId>) {
// Always use the new one, even if it clears it.
*base = new;
Expand Down Expand Up @@ -851,6 +877,7 @@ fn artifacts_to_update(
Some(Artifact::Plane(Plane { path_ids, .. })) => path_ids.clone(),
_ => Vec::new(),
};
// Create an entirely new plane
return Ok(vec![Artifact::Plane(Plane {
id: entity_id.into(),
path_ids,
Expand All @@ -877,6 +904,7 @@ fn artifacts_to_update(
composite_solid_id: None,
inner_path_id: None,
outer_path_id: None,
consumed: false,
}));
let plane = artifacts.get(&ArtifactId::new(*current_plane_id));
if let Some(Artifact::Plane(plane)) = plane {
Expand Down Expand Up @@ -998,6 +1026,7 @@ fn artifacts_to_update(
composite_solid_id: None,
inner_path_id: None,
outer_path_id: None,
consumed: false,
}
};

Expand All @@ -1024,8 +1053,7 @@ fn artifacts_to_update(
| ModelingCmd::TwistExtrude(kcmc::TwistExtrude { target, .. })
| ModelingCmd::Revolve(kcmc::Revolve { target, .. })
| ModelingCmd::RevolveAboutEdge(kcmc::RevolveAboutEdge { target, .. })
| ModelingCmd::ExtrudeToReference(kcmc::ExtrudeToReference { target, .. })
| ModelingCmd::Sweep(kcmc::Sweep { target, .. }) => {
| ModelingCmd::ExtrudeToReference(kcmc::ExtrudeToReference { target, .. }) => {
// Determine the resulting method from the specific command, if provided
let method = match cmd {
ModelingCmd::Extrude(kcmc::Extrude { extrude_method, .. }) => *extrude_method,
Expand All @@ -1046,7 +1074,6 @@ fn artifacts_to_update(
ModelingCmd::TwistExtrude(_) => SweepSubType::ExtrusionTwist,
ModelingCmd::Revolve(_) => SweepSubType::Revolve,
ModelingCmd::RevolveAboutEdge(_) => SweepSubType::RevolveAboutEdge,
ModelingCmd::Sweep(_) => SweepSubType::Sweep,
_ => internal_error!(range, "Sweep-like command variant not handled: id={id:?}, cmd={cmd:?}",),
};
let mut return_arr = Vec::new();
Expand All @@ -1059,22 +1086,76 @@ fn artifacts_to_update(
edge_ids: Vec::new(),
code_ref,
method,
consumed: false,
}));
let path = artifacts.get(&target);
if let Some(Artifact::Path(path)) = path {
let mut new_path = path.clone();
new_path.sweep_id = Some(id);
new_path.consumed = true;
return_arr.push(Artifact::Path(new_path));
if let Some(inner_path_id) = path.inner_path_id
&& let Some(inner_path_artifact) = artifacts.get(&inner_path_id)
&& let Artifact::Path(mut inner_path_artifact) = inner_path_artifact.clone()
{
inner_path_artifact.sweep_id = Some(id);
inner_path_artifact.consumed = true;
return_arr.push(Artifact::Path(inner_path_artifact))
}
}
return Ok(return_arr);
}
ModelingCmd::Sweep(kcmc::Sweep { target, trajectory, .. }) => {
// Determine the resulting method from the specific command, if provided
let method = kittycad_modeling_cmds::shared::ExtrudeMethod::Merge;
let sub_type = SweepSubType::Sweep;
let mut return_arr = Vec::new();
let target = ArtifactId::from(target);
let trajectory = ArtifactId::from(trajectory);
return_arr.push(Artifact::Sweep(Sweep {
id,
sub_type,
path_id: target,
surface_ids: Vec::new(),
edge_ids: Vec::new(),
code_ref,
method,
consumed: false,
}));
let path = artifacts.get(&target);
if let Some(Artifact::Path(path)) = path {
let mut new_path = path.clone();
new_path.sweep_id = Some(id);
new_path.consumed = true;
return_arr.push(Artifact::Path(new_path));
if let Some(inner_path_id) = path.inner_path_id
&& let Some(inner_path_artifact) = artifacts.get(&inner_path_id)
&& let Artifact::Path(mut inner_path_artifact) = inner_path_artifact.clone()
{
inner_path_artifact.sweep_id = Some(id);
inner_path_artifact.consumed = true;
return_arr.push(Artifact::Path(inner_path_artifact))
}
}
if let Some(trajectory_artifact) = artifacts.get(&trajectory) {
match trajectory_artifact {
Artifact::Path(path) => {
let mut new_path = path.clone();
new_path.sweep_id = Some(id);
new_path.consumed = true;
return_arr.push(Artifact::Path(new_path));
}
Artifact::Helix(helix) => {
let mut new_helix = helix.clone();
new_helix.sweep_id = Some(id);
new_helix.consumed = true;
return_arr.push(Artifact::Helix(new_helix));
}
_ => {}
}
};
return Ok(return_arr);
}
ModelingCmd::Loft(loft_cmd) => {
let Some(OkModelingCmdResponse::Loft(_)) = response else {
return Ok(Vec::new());
Expand All @@ -1095,11 +1176,13 @@ fn artifacts_to_update(
edge_ids: Vec::new(),
code_ref,
method: kittycad_modeling_cmds::shared::ExtrudeMethod::Merge,
consumed: false,
}));
for section_id in &loft_cmd.section_ids {
let path = artifacts.get(&ArtifactId::new(*section_id));
if let Some(Artifact::Path(path)) = path {
let mut new_path = path.clone();
new_path.consumed = true;
new_path.sweep_id = Some(id);
return_arr.push(Artifact::Path(new_path));
}
Expand Down Expand Up @@ -1382,11 +1465,24 @@ fn artifacts_to_update(
}
return Ok(return_arr);
}
ModelingCmd::EntityMakeHelix(cmd) => {
let cylinder_id = ArtifactId::new(cmd.cylinder_id);
let return_arr = vec![Artifact::Helix(Helix {
id,
axis_id: Some(cylinder_id),
code_ref,
sweep_id: None,
consumed: false,
})];
return Ok(return_arr);
}
ModelingCmd::EntityMakeHelixFromParams(_) => {
let return_arr = vec![Artifact::Helix(Helix {
id,
axis_id: None,
code_ref,
sweep_id: None,
consumed: false,
})];
return Ok(return_arr);
}
Expand All @@ -1396,6 +1492,8 @@ fn artifacts_to_update(
id,
axis_id: Some(edge_id),
code_ref,
sweep_id: None,
consumed: false,
})];
// We could add the reverse graph edge connecting from the edge to
// the helix here, but it's not useful right now.
Expand All @@ -1407,13 +1505,15 @@ fn artifacts_to_update(
let outer_path = artifacts.get(&ArtifactId::new(solid2d_add_hole.object_id));
if let Some(Artifact::Path(path)) = outer_path {
let mut new_path = path.clone();
new_path.consumed = true;
new_path.inner_path_id = Some(ArtifactId::new(solid2d_add_hole.hole_id));
return_arr.push(Artifact::Path(new_path));
}
// Add the outer to the hole.
let inner_solid2d = artifacts.get(&ArtifactId::new(solid2d_add_hole.hole_id));
if let Some(Artifact::Path(path)) = inner_solid2d {
let mut new_path = path.clone();
new_path.consumed = true;
new_path.outer_path_id = Some(ArtifactId::new(solid2d_add_hole.object_id));
return_arr.push(Artifact::Path(new_path));
}
Expand Down Expand Up @@ -1493,6 +1593,7 @@ fn artifacts_to_update(
// Create the composite solid
return_arr.push(Artifact::CompositeSolid(CompositeSolid {
id: *solid_id,
consumed: false,
sub_type,
solid_ids: solid_ids.clone(),
tool_ids: tool_ids.clone(),
Expand All @@ -1507,11 +1608,23 @@ fn artifacts_to_update(
Artifact::CompositeSolid(comp) => {
let mut new_comp = comp.clone();
new_comp.composite_solid_id = Some(*solid_id);
new_comp.consumed = true;
return_arr.push(Artifact::CompositeSolid(new_comp));
}
Artifact::Path(path) => {
let mut new_path = path.clone();
new_path.composite_solid_id = Some(*solid_id);

// We want to mark any sweeps of the path used in this operation
// as consumed. The path itself is already consumed by sweeping
if let Some(sweep_id) = new_path.sweep_id
&& let Some(Artifact::Sweep(sweep)) = artifacts.get(&sweep_id)
{
let mut new_sweep = sweep.clone();
new_sweep.consumed = true;
return_arr.push(Artifact::Sweep(new_sweep));
}

return_arr.push(Artifact::Path(new_path));
}
_ => {}
Expand All @@ -1526,11 +1639,23 @@ fn artifacts_to_update(
Artifact::CompositeSolid(comp) => {
let mut new_comp = comp.clone();
new_comp.composite_solid_id = Some(*solid_id);
new_comp.consumed = true;
return_arr.push(Artifact::CompositeSolid(new_comp));
}
Artifact::Path(path) => {
let mut new_path = path.clone();
new_path.composite_solid_id = Some(*solid_id);

// We want to mark any sweeps of the path used in this operation
// as consumed. The path itself is already consumed by sweeping
if let Some(sweep_id) = new_path.sweep_id
&& let Some(Artifact::Sweep(sweep)) = artifacts.get(&sweep_id)
{
let mut new_sweep = sweep.clone();
new_sweep.consumed = true;
return_arr.push(Artifact::Sweep(new_sweep));
}

return_arr.push(Artifact::Path(new_path));
}
_ => {}
Expand Down
Loading
Loading