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 anyhow::Result;
use async_recursion::async_recursion; use async_recursion::async_recursion;
use fnv::FnvHashMap;
use kcmc::{ use kcmc::{
each_cmd as mcmd, each_cmd as mcmd,
ok_response::{output::TakeSnapshot, OkModelingCmdResponse}, ok_response::{output::TakeSnapshot, OkModelingCmdResponse},
@ -45,6 +46,16 @@ pub struct ExecState {
/// The current value of the pipe operator returned from the previous /// The current value of the pipe operator returned from the previous
/// expression. If we're not currently in a pipeline, this will be None. /// expression. If we're not currently in a pipeline, this will be None.
pub pipe_value: Option<KclValue>, 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)] #[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. /// A geometry.
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)] #[derive(Debug, Clone, Deserialize, Serialize, PartialEq, ts_rs::TS, JsonSchema)]
#[ts(export)] #[ts(export)]

View File

@ -15,17 +15,17 @@ use uuid::Uuid;
use crate::{ use crate::{
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
executor::{ executor::{
ExecState, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, GeoMeta, KclValue, Path, SketchGroup, SketchGroupSet, ArtifactId, ExecState, ExtrudeGroup, ExtrudeGroupSet, ExtrudeSurface, GeoMeta, KclValue, Path, SketchGroup,
SketchSurface, SketchGroupSet, SketchSurface,
}, },
std::Args, std::Args,
}; };
/// Extrudes by a given amount. /// 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 (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()) Ok(result.into())
} }
@ -79,7 +79,12 @@ pub async fn extrude(_exec_state: &mut ExecState, args: Args) -> Result<KclValue
#[stdlib { #[stdlib {
name = "extrude" 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(); let id = uuid::Uuid::new_v4();
// Extrude the element(s). // Extrude the element(s).
@ -120,7 +125,7 @@ async fn inner_extrude(length: f64, sketch_group_set: SketchGroupSet, args: Args
ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}), ModelingCmd::SketchModeDisable(mcmd::SketchModeDisable {}),
) )
.await?; .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()) 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( pub(crate) async fn do_post_extrude(
sketch_group: SketchGroup, sketch_group: SketchGroup,
length: f64, length: f64,
exec_state: &mut ExecState,
args: Args, args: Args,
) -> Result<Box<ExtrudeGroup>, KclError> { ) -> Result<Box<ExtrudeGroup>, KclError> {
// Bring the object to the front of the scene. // Bring the object to the front of the scene.
@ -276,7 +282,7 @@ pub(crate) async fn do_post_extrude(
}) })
.collect(); .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, // 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 // that we passed in to the function, but it's actually the id of the
// sketch group. // sketch group.
@ -288,7 +294,13 @@ pub(crate) async fn do_post_extrude(
start_cap_id, start_cap_id,
end_cap_id, end_cap_id,
edge_cuts: vec![], edge_cuts: vec![],
})) });
exec_state.put_artifact(
ArtifactId::new(extrude_group.id),
KclValue::ExtrudeGroup(extrude_group.clone()),
);
Ok(extrude_group)
} }
#[derive(Default)] #[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. /// 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 (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)) 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( async fn inner_loft(
sketch_groups: Vec<SketchGroup>, sketch_groups: Vec<SketchGroup>,
data: Option<LoftData>, data: Option<LoftData>,
exec_state: &mut ExecState,
args: Args, args: Args,
) -> Result<Box<ExtrudeGroup>, KclError> { ) -> Result<Box<ExtrudeGroup>, KclError> {
// Make sure we have at least two sketches. // Make sure we have at least two sketches.
@ -170,5 +171,5 @@ async fn inner_loft(
.await?; .await?;
// Using the first sketch as the base curve, idk we might want to change this later. // 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)] #[cfg(test)]

View File

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

View File

@ -16,8 +16,8 @@ use crate::{
ast::types::TagDeclarator, ast::types::TagDeclarator,
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
executor::{ executor::{
BasePath, ExecState, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d, Point3d, ArtifactId, BasePath, ExecState, ExtrudeGroup, Face, GeoMeta, KclValue, Path, Plane, PlaneType, Point2d,
SketchGroup, SketchGroupSet, SketchSurface, TagEngineInfo, TagIdentifier, UserVal, Point3d, SketchGroup, SketchGroupSet, SketchSurface, TagEngineInfo, TagIdentifier, UserVal,
}, },
std::{ std::{
utils::{ utils::{
@ -93,11 +93,16 @@ pub enum StartOrEnd {
} }
/// Draw a line to a point. /// 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>) = let (to, sketch_group, tag): ([f64; 2], SketchGroup, Option<TagDeclarator>) =
args.get_data_and_sketch_group_and_tag()?; args.get_data_and_sketch_group_and_tag()?;
let new_sketch_group = inner_line_to(to, sketch_group, tag, args).await?; 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)) 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. /// 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 (sketch_group, tag): (SketchGroup, Option<TagDeclarator>) = args.get_sketch_group_and_optional_tag()?;
let new_sketch_group = inner_close(sketch_group, tag, args).await?; 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)) Ok(KclValue::new_user_val(new_sketch_group.meta.clone(), new_sketch_group))
} }