Add tracking of artifacts for lineTo, close, circle, and extrude

This commit is contained in:
Jonathan Tran
2024-09-16 16:14:35 -04:00
parent 6c8aa799b4
commit b697258ad5
6 changed files with 70 additions and 17 deletions

View File

@ -4,6 +4,7 @@ use std::{collections::HashMap, sync::Arc};
use anyhow::Result;
use async_recursion::async_recursion;
use fnv::FnvHashMap;
use kcmc::{
each_cmd as mcmd,
ok_response::{output::TakeSnapshot, OkModelingCmdResponse},
@ -45,6 +46,16 @@ pub struct ExecState {
/// The current value of the pipe operator returned from the previous
/// expression. If we're not currently in a pipeline, this will be None.
pub pipe_value: Option<KclValue>,
/// Artifacts created by the program. It's safe to use a faster hash
/// algorithm since all keys are UUIDs that we generate.
pub artifacts: FnvHashMap<ArtifactId, Artifact>,
}
impl ExecState {
/// Insert or update artifact by ID.
pub(crate) fn put_artifact(&mut self, id: ArtifactId, value: KclValue) {
self.artifacts.insert(id, Artifact { id, value });
}
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
@ -396,6 +407,21 @@ impl From<Vec<Box<ExtrudeGroup>>> for KclValue {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Deserialize, Serialize, ts_rs::TS, JsonSchema)]
pub struct ArtifactId(uuid::Uuid);
impl ArtifactId {
pub(crate) fn new(id: uuid::Uuid) -> Self {
Self(id)
}
}
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize, ts_rs::TS, JsonSchema)]
pub struct Artifact {
pub id: ArtifactId,
pub value: KclValue,
}
/// A geometry.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)]

View File

@ -15,17 +15,17 @@ use uuid::Uuid;
use crate::{
errors::{KclError, KclErrorDetails},
executor::{
ExecState, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, GeoMeta, KclValue, Path, SketchGroup, SketchGroupSet,
SketchSurface,
ArtifactId, ExecState, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, GeoMeta, KclValue, Path, SketchGroup,
SketchGroupSet, SketchSurface,
},
std::Args,
};
/// Extrudes by a given amount.
pub async fn extrude(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
pub async fn extrude(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (length, sketch_group_set) = args.get_number_sketch_group_set()?;
let result = inner_extrude(length, sketch_group_set, args).await?;
let result = inner_extrude(length, sketch_group_set, exec_state, args).await?;
Ok(result.into())
}
@ -79,7 +79,12 @@ pub async fn extrude(_exec_state: &mut ExecState, args: Args) -> Result<KclValue
#[stdlib {
name = "extrude"
}]
async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args) -> Result<ExtrudeGroupSet, KclError> {
async fn inner_extrude(
length: f64,
sketch_group_set: SketchGroupSet,
exec_state: &mut ExecState,
args: Args,
) -> Result<ExtrudeGroupSet, KclError> {
let id = uuid::Uuid::new_v4();
// Extrude the element(s).
@ -120,7 +125,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
)
.await?;
extrude_groups.push(do_post_extrude(sketch_group.clone(), length, args.clone()).await?);
extrude_groups.push(do_post_extrude(sketch_group.clone(), length, exec_state, args.clone()).await?);
}
Ok(extrude_groups.into())
@ -129,6 +134,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
pub(crate) async fn do_post_extrude(
sketch_group: SketchGroup,
length: f64,
exec_state: &mut ExecState,
args: Args,
) -> Result<Box<ExtrudeGroup>, KclError> {
// Bring the object to the front of the scene.
@ -276,7 +282,7 @@ pub(crate) async fn do_post_extrude(
})
.collect();
Ok(Box::new(ExtrudeGroup {
let extrude_group = Box::new(ExtrudeGroup {
// Ok so you would think that the id would be the id of the extrude group,
// that we passed in to the function, but it's actually the id of the
// sketch group.
@ -288,7 +294,13 @@ pub(crate) async fn do_post_extrude(
start_cap_id,
end_cap_id,
edge_cuts: vec![],
}))
});
exec_state.put_artifact(
ArtifactId::new(extrude_group.id),
KclValue::ExtrudeGroup(extrude_group.clone()),
);
Ok(extrude_group)
}
#[derive(Default)]

View File

@ -50,10 +50,10 @@ impl Default for LoftData {
}
/// Create a 3D surface or solid by interpolating between two or more sketches.
pub async fn loft(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
pub async fn loft(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (sketch_groups, data): (Vec<SketchGroup>, Option<LoftData>) = args.get_sketch_groups_and_data()?;
let extrude_group = inner_loft(sketch_groups, data, args).await?;
let extrude_group = inner_loft(sketch_groups, data, exec_state, args).await?;
Ok(KclValue::ExtrudeGroup(extrude_group))
}
@ -138,6 +138,7 @@ pub async fn loft(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, K
async fn inner_loft(
sketch_groups: Vec<SketchGroup>,
data: Option<LoftData>,
exec_state: &mut ExecState,
args: Args,
) -> Result<Box<ExtrudeGroup>, KclError> {
// Make sure we have at least two sketches.
@ -170,5 +171,5 @@ async fn inner_loft(
.await?;
// Using the first sketch as the base curve, idk we might want to change this later.
do_post_extrude(sketch_groups[0].clone(), 0.0, args).await
do_post_extrude(sketch_groups[0].clone(), 0.0, exec_state, args).await
}

View File

@ -295,7 +295,7 @@ async fn inner_revolve(
}
}
do_post_extrude(sketch_group, 0.0, args).await
do_post_extrude(sketch_group, 0.0, exec_state, args).await
}
#[cfg(test)]

View File

@ -15,7 +15,7 @@ use serde::{Deserialize, Serialize};
use crate::{
ast::types::TagDeclarator,
errors::KclError,
executor::{BasePath, ExecState, GeoMeta, KclValue, Path, SketchGroup, SketchSurface},
executor::{ArtifactId, BasePath, ExecState, GeoMeta, KclValue, Path, SketchGroup, SketchSurface},
std::Args,
};
@ -46,6 +46,11 @@ pub async fn circle(exec_state: &mut ExecState, args: Args) -> Result<KclValue,
args.get_circle_args()?;
let sketch_group = inner_circle(data, sketch_surface_or_group, tag, exec_state, args).await?;
exec_state.put_artifact(
ArtifactId::new(sketch_group.id),
KclValue::new_user_val(sketch_group.meta.clone(), sketch_group.clone()),
);
Ok(KclValue::new_user_val(sketch_group.meta.clone(), sketch_group))
}

View File

@ -16,8 +16,8 @@ use crate::{
ast::types::TagDeclarator,
errors::{KclError, KclErrorDetails},
executor::{
BasePath, ExecState, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d, Point3d,
SketchGroup, SketchGroupSet, SketchSurface, TagEngineInfo, TagIdentifier, UserVal,
ArtifactId, BasePath, ExecState, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d,
Point3d, SketchGroup, SketchGroupSet, SketchSurface, TagEngineInfo, TagIdentifier, UserVal,
},
std::{
utils::{
@ -93,11 +93,16 @@ pub enum StartOrEnd {
}
/// Draw a line to a point.
pub async fn line_to(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
pub async fn line_to(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
args.get_data_and_sketch_group_and_tag()?;
let new_sketch_group = inner_line_to(to, sketch_group, tag, args).await?;
exec_state.put_artifact(
ArtifactId::new(new_sketch_group.id),
KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group.clone()),
);
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
}
@ -1410,10 +1415,14 @@ pub(crate) fn inner_profile_start(sketch_group: SketchGroup) -> Result<[f64; 2],
}
/// Close the current sketch.
pub async fn close(_exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
pub async fn close(exec_state: &mut ExecState, args: Args) -> Result<KclValue, KclError> {
let (sketch_group, tag): (SketchGroup, Option<TagDeclarator>) = args.get_sketch_group_and_optional_tag()?;
let new_sketch_group = inner_close(sketch_group, tag, args).await?;
exec_state.put_artifact(
ArtifactId::new(new_sketch_group.id),
KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group.clone()),
);
Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
}