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 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)]
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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)]
|
||||
|
||||
@ -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))
|
||||
}
|
||||
|
||||
|
||||
@ -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))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user