Add tracking of artifacts for lineTo, close, circle, and extrude
This commit is contained in:
@ -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)]
|
||||||
|
|||||||
@ -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)]
|
||||||
|
|||||||
@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)]
|
||||||
|
|||||||
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user