Fix sketchOnFace point&click for booleans (#6713)
* fix bool sketchOnFace * fix chamfer test * add test * Kurt composite attempt (#6722) * composite attempt * Add forward edge to CSG artifacts in artifact graph * Fix comment * Move the doc comments above the attributes * Fix to update the correct field of Path * Update output --------- Co-authored-by: Jonathan Tran <jonnytran@gmail.com> * use rust defined composite solid edges instead * Update src/hooks/useEngineConnectionSubscriptions.ts Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com> * Revert PNG screenshots * Fix TS formatting --------- Co-authored-by: Jonathan Tran <jonnytran@gmail.com> Co-authored-by: graphite-app[bot] <96075541+graphite-app[bot]@users.noreply.github.com>
This commit is contained in:
@ -241,6 +241,12 @@ export class ToolbarFixture {
|
|||||||
async openFeatureTreePane() {
|
async openFeatureTreePane() {
|
||||||
return this.openPane(this.featureTreeId)
|
return this.openPane(this.featureTreeId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async waitForFeatureTreeToBeBuilt() {
|
||||||
|
await this.openFeatureTreePane()
|
||||||
|
await expect(this.page.getByText('Building feature tree')).not.toBeVisible()
|
||||||
|
await this.closeFeatureTreePane()
|
||||||
|
}
|
||||||
async closeFeatureTreePane() {
|
async closeFeatureTreePane() {
|
||||||
await this.closePane(this.featureTreeId)
|
await this.closePane(this.featureTreeId)
|
||||||
}
|
}
|
||||||
|
@ -244,6 +244,7 @@ test.describe('Point-and-click tests', () => {
|
|||||||
await scene.moveCameraTo(cameraPos, cameraTarget)
|
await scene.moveCameraTo(cameraPos, cameraTarget)
|
||||||
|
|
||||||
await test.step('check chamfer selection changes cursor position', async () => {
|
await test.step('check chamfer selection changes cursor position', async () => {
|
||||||
|
await toolbar.waitForFeatureTreeToBeBuilt()
|
||||||
await expect(async () => {
|
await expect(async () => {
|
||||||
// sometimes initial click doesn't register
|
// sometimes initial click doesn't register
|
||||||
await clickChamfer()
|
await clickChamfer()
|
||||||
@ -283,6 +284,7 @@ test.describe('Point-and-click tests', () => {
|
|||||||
highlightedCode: '',
|
highlightedCode: '',
|
||||||
diagnostics: [],
|
diagnostics: [],
|
||||||
})
|
})
|
||||||
|
await toolbar.waitForFeatureTreeToBeBuilt()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
test('works on all edge selections and can break up multi edges in a chamfer array', async ({
|
test('works on all edge selections and can break up multi edges in a chamfer array', async ({
|
||||||
@ -402,6 +404,7 @@ test.describe('Point-and-click tests', () => {
|
|||||||
await test.step('verify at the end of the test that final code is what is expected', async () => {
|
await test.step('verify at the end of the test that final code is what is expected', async () => {
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
`@settings(defaultLengthUnit = in)
|
`@settings(defaultLengthUnit = in)
|
||||||
|
|
||||||
sketch001 = startSketchOn(XZ)
|
sketch001 = startSketchOn(XZ)
|
||||||
|> startProfile(at = [75.8, 317.2]) // [$startCapTag, $EndCapTag]
|
|> startProfile(at = [75.8, 317.2]) // [$startCapTag, $EndCapTag]
|
||||||
|> angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001)
|
|> angledLine(angle = 0, length = 268.43, tag = $rectangleSegmentA001)
|
||||||
@ -414,18 +417,11 @@ extrude001 = extrude(sketch001, length = 100)
|
|||||||
|> chamfer(length = 30, tags = [seg01], tag = $seg04)
|
|> chamfer(length = 30, tags = [seg01], tag = $seg04)
|
||||||
|> chamfer(length = 30, tags = [getNextAdjacentEdge(seg02)], tag = $seg05)
|
|> chamfer(length = 30, tags = [getNextAdjacentEdge(seg02)], tag = $seg05)
|
||||||
|> chamfer(length = 30, tags = [getNextAdjacentEdge(yo)], tag = $seg06)
|
|> chamfer(length = 30, tags = [getNextAdjacentEdge(yo)], tag = $seg06)
|
||||||
sketch005 = startSketchOn(extrude001, face = seg06)
|
sketch002 = startSketchOn(extrude001, face = seg03)
|
||||||
profile004=startProfile(sketch005, at = [-23.43,19.69])
|
profile001 = startProfile(sketch002, at = [205.96, 254.59])
|
||||||
|> angledLine(angle = 0, length = 9.1, tag = $rectangleSegmentA005)
|
|> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002)
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA005) - 90, length = 84.07)
|
|> angledLine(angle = segAng(rectangleSegmentA002) - 90, length = 105.26)
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA005), length = -segLen(rectangleSegmentA005))
|
|> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002))
|
||||||
|> line(endAbsolute=[profileStartX(%), profileStartY(%)])
|
|
||||||
|> close()
|
|
||||||
sketch004 = startSketchOn(extrude001, face = seg05)
|
|
||||||
profile003 = startProfile(sketch004, at = [82.57, 322.96])
|
|
||||||
|> angledLine(angle = 0, length = 11.16, tag = $rectangleSegmentA004)
|
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA004) - 90, length = 103.07)
|
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA004), length = -segLen(rectangleSegmentA004))
|
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
sketch003 = startSketchOn(extrude001, face = seg04)
|
sketch003 = startSketchOn(extrude001, face = seg04)
|
||||||
@ -435,11 +431,18 @@ profile002 = startProfile(sketch003, at = [-209.64, 255.28])
|
|||||||
|> angledLine(angle = segAng(rectangleSegmentA003), length = -segLen(rectangleSegmentA003))
|
|> angledLine(angle = segAng(rectangleSegmentA003), length = -segLen(rectangleSegmentA003))
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
sketch002 = startSketchOn(extrude001, face = seg03)
|
sketch004 = startSketchOn(extrude001, face = seg05)
|
||||||
profile001 = startProfile(sketch002, at = [205.96, 254.59])
|
profile003 = startProfile(sketch004, at = [82.57, 322.96])
|
||||||
|> angledLine(angle = 0, length = 11.39, tag = $rectangleSegmentA002)
|
|> angledLine(angle = 0, length = 11.16, tag = $rectangleSegmentA004)
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA002) - 90, length = 105.26)
|
|> angledLine(angle = segAng(rectangleSegmentA004) - 90, length = 103.07)
|
||||||
|> angledLine(angle = segAng(rectangleSegmentA002), length = -segLen(rectangleSegmentA002))
|
|> angledLine(angle = segAng(rectangleSegmentA004), length = -segLen(rectangleSegmentA004))
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|
|> close()
|
||||||
|
sketch005 = startSketchOn(extrude001, face = seg06)
|
||||||
|
profile004 = startProfile(sketch005, at = [-23.43, 19.69])
|
||||||
|
|> angledLine(angle = 0, length = 9.1, tag = $rectangleSegmentA005)
|
||||||
|
|> angledLine(angle = segAng(rectangleSegmentA005) - 90, length = 84.07)
|
||||||
|
|> angledLine(angle = segAng(rectangleSegmentA005), length = -segLen(rectangleSegmentA005))
|
||||||
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)])
|
||||||
|> close()
|
|> close()
|
||||||
`,
|
`,
|
||||||
|
@ -1260,6 +1260,97 @@ profile001 = startProfile(sketch001, at = [299.72, 230.82])
|
|||||||
}).toPass({ timeout: 40_000, intervals: [1_000] })
|
}).toPass({ timeout: 40_000, intervals: [1_000] })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('sketch on face of a boolean works', async ({
|
||||||
|
page,
|
||||||
|
homePage,
|
||||||
|
scene,
|
||||||
|
cmdBar,
|
||||||
|
toolbar,
|
||||||
|
editor,
|
||||||
|
}) => {
|
||||||
|
await page.setBodyDimensions({ width: 1000, height: 500 })
|
||||||
|
|
||||||
|
await page.addInitScript(async () => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'persistCode',
|
||||||
|
`@settings(defaultLengthUnit = mm)
|
||||||
|
|
||||||
|
myVar = 50
|
||||||
|
sketch001 = startSketchOn(XZ)
|
||||||
|
profile001 = circle(sketch001, center = [myVar, 43.9], radius = 41.05)
|
||||||
|
extrude001 = extrude(profile001, length = 200)
|
||||||
|
|> translate(x = 3.14, y = 3.14, z = -50.154)
|
||||||
|
sketch002 = startSketchOn(XY)
|
||||||
|
profile002 = startProfile(sketch002, at = [72.2, -52.05])
|
||||||
|
|> angledLine(angle = 0, length = 181.26, tag = $rectangleSegmentA001)
|
||||||
|
|> angledLine(angle = segAng(rectangleSegmentA001) - 90, length = 21.54)
|
||||||
|
|> angledLine(angle = segAng(rectangleSegmentA001), length = -segLen(rectangleSegmentA001), tag = $mySeg)
|
||||||
|
|> line(endAbsolute = [profileStartX(%), profileStartY(%)], tag = $seg01)
|
||||||
|
|> close()
|
||||||
|
|
||||||
|
extrude002 = extrude(profile002, length = 151)
|
||||||
|
|> chamfer(
|
||||||
|
%,
|
||||||
|
length = 15,
|
||||||
|
tags = [mySeg],
|
||||||
|
tag = $seg02,
|
||||||
|
)
|
||||||
|
solid001 = subtract([extrude001], tools = [extrude002])
|
||||||
|
`
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const [selectChamferFaceClk] = scene.makeMouseHelpers(671, 283)
|
||||||
|
const [circleCenterClk] = scene.makeMouseHelpers(700, 272)
|
||||||
|
const [circleRadiusClk] = scene.makeMouseHelpers(694, 264)
|
||||||
|
|
||||||
|
await test.step('Setup', async () => {
|
||||||
|
await homePage.goToModelingScene()
|
||||||
|
await scene.settled(cmdBar)
|
||||||
|
|
||||||
|
await scene.moveCameraTo(
|
||||||
|
{ x: 180, y: -75, z: 116 },
|
||||||
|
{ x: 67, y: -114, z: -15 }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('sketch on chamfer face that is part of a boolean', async () => {
|
||||||
|
await toolbar.startSketchPlaneSelection()
|
||||||
|
await selectChamferFaceClk()
|
||||||
|
|
||||||
|
await expect
|
||||||
|
.poll(async () => {
|
||||||
|
const lineBtn = page.getByRole('button', { name: 'line Line' })
|
||||||
|
return lineBtn.getAttribute('aria-pressed')
|
||||||
|
})
|
||||||
|
.toBe('true')
|
||||||
|
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
'startSketchOn(solid001, face = seg02)'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
await test.step('verify sketching still works', async () => {
|
||||||
|
await toolbar.circleBtn.click()
|
||||||
|
await expect
|
||||||
|
.poll(async () => {
|
||||||
|
const circleBtn = page.getByRole('button', { name: 'circle Circle' })
|
||||||
|
return circleBtn.getAttribute('aria-pressed')
|
||||||
|
})
|
||||||
|
.toBe('true')
|
||||||
|
|
||||||
|
await circleCenterClk()
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
'profile003 = circle(sketch003, center'
|
||||||
|
)
|
||||||
|
|
||||||
|
await circleRadiusClk()
|
||||||
|
await editor.expectEditor.toContain(
|
||||||
|
'profile003 = circle(sketch003, center = [119.41, -56.05], radius = 1.82)'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test('Can sketch on face when user defined function was used in the sketch', async ({
|
test('Can sketch on face when user defined function was used in the sketch', async ({
|
||||||
page,
|
page,
|
||||||
homePage,
|
homePage,
|
||||||
|
@ -150,6 +150,10 @@ pub struct CompositeSolid {
|
|||||||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||||
pub tool_ids: Vec<ArtifactId>,
|
pub tool_ids: Vec<ArtifactId>,
|
||||||
pub code_ref: CodeRef,
|
pub code_ref: CodeRef,
|
||||||
|
/// This is the ID of the composite solid that this is part of, if any, as a
|
||||||
|
/// composite solid can be used as input for another composite solid.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub composite_solid_id: Option<ArtifactId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, ts_rs::TS)]
|
#[derive(Debug, Clone, Copy, Serialize, PartialEq, Eq, ts_rs::TS)]
|
||||||
@ -182,6 +186,10 @@ pub struct Path {
|
|||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub solid2d_id: Option<ArtifactId>,
|
pub solid2d_id: Option<ArtifactId>,
|
||||||
pub code_ref: CodeRef,
|
pub code_ref: CodeRef,
|
||||||
|
/// This is the ID of the composite solid that this is part of, if any, as
|
||||||
|
/// this can be used as input for another composite solid.
|
||||||
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
|
pub composite_solid_id: Option<ArtifactId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
#[derive(Debug, Clone, Serialize, PartialEq, ts_rs::TS)]
|
||||||
@ -585,6 +593,7 @@ impl CompositeSolid {
|
|||||||
};
|
};
|
||||||
merge_ids(&mut self.solid_ids, new.solid_ids);
|
merge_ids(&mut self.solid_ids, new.solid_ids);
|
||||||
merge_ids(&mut self.tool_ids, new.tool_ids);
|
merge_ids(&mut self.tool_ids, new.tool_ids);
|
||||||
|
merge_opt_id(&mut self.composite_solid_id, new.composite_solid_id);
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -609,6 +618,7 @@ impl Path {
|
|||||||
merge_opt_id(&mut self.sweep_id, new.sweep_id);
|
merge_opt_id(&mut self.sweep_id, new.sweep_id);
|
||||||
merge_ids(&mut self.seg_ids, new.seg_ids);
|
merge_ids(&mut self.seg_ids, new.seg_ids);
|
||||||
merge_opt_id(&mut self.solid2d_id, new.solid2d_id);
|
merge_opt_id(&mut self.solid2d_id, new.solid2d_id);
|
||||||
|
merge_opt_id(&mut self.composite_solid_id, new.composite_solid_id);
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -921,6 +931,7 @@ fn artifacts_to_update(
|
|||||||
sweep_id: None,
|
sweep_id: None,
|
||||||
solid2d_id: None,
|
solid2d_id: None,
|
||||||
code_ref,
|
code_ref,
|
||||||
|
composite_solid_id: None,
|
||||||
}));
|
}));
|
||||||
let plane = artifacts.get(&ArtifactId::new(*current_plane_id));
|
let plane = artifacts.get(&ArtifactId::new(*current_plane_id));
|
||||||
if let Some(Artifact::Plane(plane)) = plane {
|
if let Some(Artifact::Plane(plane)) = plane {
|
||||||
@ -1359,20 +1370,59 @@ fn artifacts_to_update(
|
|||||||
.for_each(|id| new_solid_ids.push(id)),
|
.for_each(|id| new_solid_ids.push(id)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let return_arr = new_solid_ids
|
|
||||||
.into_iter()
|
|
||||||
.map(|solid_id| {
|
|
||||||
Artifact::CompositeSolid(CompositeSolid {
|
|
||||||
id: solid_id,
|
|
||||||
sub_type,
|
|
||||||
solid_ids: solid_ids.clone(),
|
|
||||||
tool_ids: tool_ids.clone(),
|
|
||||||
code_ref: code_ref.clone(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
// TODO: Should we add the reverse graph edges?
|
let mut return_arr = Vec::new();
|
||||||
|
|
||||||
|
// Create the new composite solids and update their linked artifacts
|
||||||
|
for solid_id in &new_solid_ids {
|
||||||
|
// Create the composite solid
|
||||||
|
return_arr.push(Artifact::CompositeSolid(CompositeSolid {
|
||||||
|
id: *solid_id,
|
||||||
|
sub_type,
|
||||||
|
solid_ids: solid_ids.clone(),
|
||||||
|
tool_ids: tool_ids.clone(),
|
||||||
|
code_ref: code_ref.clone(),
|
||||||
|
composite_solid_id: None,
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Update the artifacts that were used as input for this composite solid
|
||||||
|
for input_id in &solid_ids {
|
||||||
|
if let Some(artifact) = artifacts.get(input_id) {
|
||||||
|
match artifact {
|
||||||
|
Artifact::CompositeSolid(comp) => {
|
||||||
|
let mut new_comp = comp.clone();
|
||||||
|
new_comp.composite_solid_id = Some(*solid_id);
|
||||||
|
return_arr.push(Artifact::CompositeSolid(new_comp));
|
||||||
|
}
|
||||||
|
Artifact::Path(path) => {
|
||||||
|
let mut new_path = path.clone();
|
||||||
|
new_path.composite_solid_id = Some(*solid_id);
|
||||||
|
return_arr.push(Artifact::Path(new_path));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the tool artifacts if this is a subtract operation
|
||||||
|
for tool_id in &tool_ids {
|
||||||
|
if let Some(artifact) = artifacts.get(tool_id) {
|
||||||
|
match artifact {
|
||||||
|
Artifact::CompositeSolid(comp) => {
|
||||||
|
let mut new_comp = comp.clone();
|
||||||
|
new_comp.composite_solid_id = Some(*solid_id);
|
||||||
|
return_arr.push(Artifact::CompositeSolid(new_comp));
|
||||||
|
}
|
||||||
|
Artifact::Path(path) => {
|
||||||
|
let mut new_path = path.clone();
|
||||||
|
new_path.composite_solid_id = Some(*solid_id);
|
||||||
|
return_arr.push(Artifact::Path(new_path));
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(return_arr);
|
return Ok(return_arr);
|
||||||
}
|
}
|
||||||
|
@ -92,10 +92,14 @@ impl Artifact {
|
|||||||
/// the graph.
|
/// the graph.
|
||||||
pub(crate) fn child_ids(&self) -> Vec<ArtifactId> {
|
pub(crate) fn child_ids(&self) -> Vec<ArtifactId> {
|
||||||
match self {
|
match self {
|
||||||
Artifact::CompositeSolid(_) => {
|
Artifact::CompositeSolid(a) => {
|
||||||
// Note: Don't include these since they're parents: solid_ids,
|
// Note: Don't include these since they're parents: solid_ids,
|
||||||
// tool_ids.
|
// tool_ids.
|
||||||
Vec::new()
|
let mut ids = Vec::new();
|
||||||
|
if let Some(composite_solid_id) = a.composite_solid_id {
|
||||||
|
ids.push(composite_solid_id);
|
||||||
|
}
|
||||||
|
ids
|
||||||
}
|
}
|
||||||
Artifact::Plane(a) => a.path_ids.clone(),
|
Artifact::Plane(a) => a.path_ids.clone(),
|
||||||
Artifact::Path(a) => {
|
Artifact::Path(a) => {
|
||||||
@ -107,6 +111,9 @@ impl Artifact {
|
|||||||
if let Some(solid2d_id) = a.solid2d_id {
|
if let Some(solid2d_id) = a.solid2d_id {
|
||||||
ids.push(solid2d_id);
|
ids.push(solid2d_id);
|
||||||
}
|
}
|
||||||
|
if let Some(composite_solid_id) = a.composite_solid_id {
|
||||||
|
ids.push(composite_solid_id);
|
||||||
|
}
|
||||||
ids
|
ids
|
||||||
}
|
}
|
||||||
Artifact::Segment(a) => {
|
Artifact::Segment(a) => {
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 68 KiB |
@ -57,14 +57,14 @@ flowchart LR
|
|||||||
3 --- 11
|
3 --- 11
|
||||||
3 --- 13
|
3 --- 13
|
||||||
3 ---- 16
|
3 ---- 16
|
||||||
3 <--x 17
|
3 --- 17
|
||||||
4 --- 6
|
4 --- 6
|
||||||
4 --- 7
|
4 --- 7
|
||||||
4 --- 9
|
4 --- 9
|
||||||
4 --- 12
|
4 --- 12
|
||||||
4 --- 14
|
4 --- 14
|
||||||
4 ---- 15
|
4 ---- 15
|
||||||
4 <--x 17
|
4 --- 17
|
||||||
5 --- 24
|
5 --- 24
|
||||||
5 x--> 26
|
5 x--> 26
|
||||||
5 --- 35
|
5 --- 35
|
||||||
|
@ -317,84 +317,84 @@ flowchart LR
|
|||||||
13 --- 67
|
13 --- 67
|
||||||
13 --- 73
|
13 --- 73
|
||||||
13 ---- 90
|
13 ---- 90
|
||||||
13 <--x 106
|
13 --- 106
|
||||||
14 --- 27
|
14 --- 27
|
||||||
14 --- 45
|
14 --- 45
|
||||||
14 --- 50
|
14 --- 50
|
||||||
14 --- 65
|
14 --- 65
|
||||||
14 --- 74
|
14 --- 74
|
||||||
14 ---- 92
|
14 ---- 92
|
||||||
14 <--x 101
|
14 --- 101
|
||||||
15 --- 32
|
15 --- 32
|
||||||
15 --- 48
|
15 --- 48
|
||||||
15 --- 51
|
15 --- 51
|
||||||
15 --- 71
|
15 --- 71
|
||||||
15 --- 75
|
15 --- 75
|
||||||
15 ---- 93
|
15 ---- 93
|
||||||
15 <--x 99
|
15 --- 99
|
||||||
16 --- 29
|
16 --- 29
|
||||||
16 --- 40
|
16 --- 40
|
||||||
16 --- 56
|
16 --- 56
|
||||||
16 --- 69
|
16 --- 69
|
||||||
16 --- 76
|
16 --- 76
|
||||||
16 ---- 96
|
16 ---- 96
|
||||||
16 <--x 100
|
16 --- 100
|
||||||
17 --- 26
|
17 --- 26
|
||||||
17 --- 44
|
17 --- 44
|
||||||
17 --- 52
|
17 --- 52
|
||||||
17 --- 63
|
17 --- 63
|
||||||
17 --- 77
|
17 --- 77
|
||||||
17 ---- 95
|
17 ---- 95
|
||||||
17 <--x 105
|
17 --- 105
|
||||||
18 --- 28
|
18 --- 28
|
||||||
18 --- 47
|
18 --- 47
|
||||||
18 --- 58
|
18 --- 58
|
||||||
18 --- 64
|
18 --- 64
|
||||||
18 --- 78
|
18 --- 78
|
||||||
18 ---- 94
|
18 ---- 94
|
||||||
18 <--x 102
|
18 --- 102
|
||||||
19 --- 35
|
19 --- 35
|
||||||
19 --- 41
|
19 --- 41
|
||||||
19 --- 57
|
19 --- 57
|
||||||
19 --- 66
|
19 --- 66
|
||||||
19 --- 79
|
19 --- 79
|
||||||
19 ---- 89
|
19 ---- 89
|
||||||
19 <--x 98
|
19 --- 98
|
||||||
20 --- 34
|
20 --- 34
|
||||||
20 --- 42
|
20 --- 42
|
||||||
20 --- 55
|
20 --- 55
|
||||||
20 --- 68
|
20 --- 68
|
||||||
20 --- 80
|
20 --- 80
|
||||||
20 ---- 87
|
20 ---- 87
|
||||||
20 <--x 104
|
20 --- 104
|
||||||
21 --- 30
|
21 --- 30
|
||||||
21 --- 39
|
21 --- 39
|
||||||
21 --- 60
|
21 --- 60
|
||||||
21 --- 70
|
21 --- 70
|
||||||
21 --- 81
|
21 --- 81
|
||||||
21 ---- 91
|
21 ---- 91
|
||||||
21 <--x 103
|
21 --- 103
|
||||||
22 --- 25
|
22 --- 25
|
||||||
22 --- 46
|
22 --- 46
|
||||||
22 --- 54
|
22 --- 54
|
||||||
22 --- 72
|
22 --- 72
|
||||||
22 --- 82
|
22 --- 82
|
||||||
22 ---- 88
|
22 ---- 88
|
||||||
22 <--x 104
|
22 --- 104
|
||||||
23 --- 36
|
23 --- 36
|
||||||
23 --- 37
|
23 --- 37
|
||||||
23 --- 49
|
23 --- 49
|
||||||
23 --- 62
|
23 --- 62
|
||||||
23 --- 83
|
23 --- 83
|
||||||
23 ---- 86
|
23 ---- 86
|
||||||
23 <--x 107
|
23 --- 107
|
||||||
24 --- 33
|
24 --- 33
|
||||||
24 --- 43
|
24 --- 43
|
||||||
24 --- 53
|
24 --- 53
|
||||||
24 --- 61
|
24 --- 61
|
||||||
24 --- 84
|
24 --- 84
|
||||||
24 ---- 85
|
24 ---- 85
|
||||||
24 <--x 97
|
24 --- 97
|
||||||
25 --- 120
|
25 --- 120
|
||||||
25 x--> 158
|
25 x--> 158
|
||||||
25 --- 193
|
25 --- 193
|
||||||
@ -755,16 +755,16 @@ flowchart LR
|
|||||||
96 --- 273
|
96 --- 273
|
||||||
96 --- 274
|
96 --- 274
|
||||||
96 --- 275
|
96 --- 275
|
||||||
97 <--x 98
|
97 --- 98
|
||||||
99 x--> 97
|
99 --- 97
|
||||||
98 <--x 103
|
98 --- 103
|
||||||
105 x--> 99
|
105 --- 99
|
||||||
104 x--> 100
|
104 --- 100
|
||||||
100 <--x 107
|
100 --- 107
|
||||||
101 <--x 102
|
101 --- 102
|
||||||
103 x--> 101
|
103 --- 101
|
||||||
106 x--> 105
|
106 --- 105
|
||||||
107 x--> 106
|
107 --- 106
|
||||||
182 <--x 108
|
182 <--x 108
|
||||||
230 <--x 108
|
230 <--x 108
|
||||||
231 <--x 108
|
231 <--x 108
|
||||||
|
@ -608,7 +608,7 @@ flowchart LR
|
|||||||
83 --- 246
|
83 --- 246
|
||||||
83 --- 289
|
83 --- 289
|
||||||
90 --- 159
|
90 --- 159
|
||||||
90 x--> 193
|
90 x--> 192
|
||||||
90 --- 226
|
90 --- 226
|
||||||
90 --- 271
|
90 --- 271
|
||||||
104 --- 151
|
104 --- 151
|
||||||
@ -910,7 +910,7 @@ flowchart LR
|
|||||||
211 <--x 191
|
211 <--x 191
|
||||||
212 <--x 191
|
212 <--x 191
|
||||||
213 <--x 191
|
213 <--x 191
|
||||||
226 <--x 192
|
226 <--x 193
|
||||||
239 <--x 195
|
239 <--x 195
|
||||||
240 <--x 195
|
240 <--x 195
|
||||||
241 <--x 195
|
241 <--x 195
|
||||||
|
@ -709,6 +709,7 @@ flowchart LR
|
|||||||
115 --- 179
|
115 --- 179
|
||||||
115 x--> 228
|
115 x--> 228
|
||||||
115 --- 256
|
115 --- 256
|
||||||
|
115 x--> 307
|
||||||
115 --- 308
|
115 --- 308
|
||||||
164 <--x 116
|
164 <--x 116
|
||||||
116 --- 184
|
116 --- 184
|
||||||
|
@ -45,11 +45,11 @@ flowchart LR
|
|||||||
3 --- 8
|
3 --- 8
|
||||||
3 --- 11
|
3 --- 11
|
||||||
3 ---- 12
|
3 ---- 12
|
||||||
3 <--x 14
|
3 --- 14
|
||||||
4 --- 9
|
4 --- 9
|
||||||
4 --- 10
|
4 --- 10
|
||||||
4 ---- 13
|
4 ---- 13
|
||||||
4 <--x 14
|
4 --- 14
|
||||||
5 --- 18
|
5 --- 18
|
||||||
5 x--> 21
|
5 x--> 21
|
||||||
5 --- 25
|
5 --- 25
|
||||||
|
@ -57,14 +57,14 @@ flowchart LR
|
|||||||
3 --- 11
|
3 --- 11
|
||||||
3 --- 13
|
3 --- 13
|
||||||
3 ---- 16
|
3 ---- 16
|
||||||
3 <--x 17
|
3 --- 17
|
||||||
4 --- 6
|
4 --- 6
|
||||||
4 --- 7
|
4 --- 7
|
||||||
4 --- 9
|
4 --- 9
|
||||||
4 --- 12
|
4 --- 12
|
||||||
4 --- 14
|
4 --- 14
|
||||||
4 ---- 15
|
4 ---- 15
|
||||||
4 <--x 17
|
4 --- 17
|
||||||
5 --- 24
|
5 --- 24
|
||||||
5 x--> 26
|
5 x--> 26
|
||||||
5 --- 35
|
5 --- 35
|
||||||
|
@ -57,14 +57,14 @@ flowchart LR
|
|||||||
3 --- 11
|
3 --- 11
|
||||||
3 --- 13
|
3 --- 13
|
||||||
3 ---- 16
|
3 ---- 16
|
||||||
3 <--x 17
|
3 --- 17
|
||||||
4 --- 6
|
4 --- 6
|
||||||
4 --- 7
|
4 --- 7
|
||||||
4 --- 9
|
4 --- 9
|
||||||
4 --- 12
|
4 --- 12
|
||||||
4 --- 14
|
4 --- 14
|
||||||
4 ---- 15
|
4 ---- 15
|
||||||
4 <--x 17
|
4 --- 17
|
||||||
5 --- 24
|
5 --- 24
|
||||||
5 x--> 26
|
5 x--> 26
|
||||||
5 --- 35
|
5 --- 35
|
||||||
|
@ -34,6 +34,7 @@ import type {
|
|||||||
ExtrudeFacePlane,
|
ExtrudeFacePlane,
|
||||||
} from '@src/machines/modelingMachine'
|
} from '@src/machines/modelingMachine'
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
|
import { findAllChildrenAndOrderByPlaceInCode } from '@src/lang/modifyAst/boolean'
|
||||||
import { localModuleSafePathSplit } from '@src/lib/paths'
|
import { localModuleSafePathSplit } from '@src/lib/paths'
|
||||||
|
|
||||||
export function useEngineConnectionSubscriptions() {
|
export function useEngineConnectionSubscriptions() {
|
||||||
@ -148,7 +149,7 @@ export function useEngineConnectionSubscriptions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sceneInfra.modelingSend({
|
sceneInfra.modelingSend({
|
||||||
type: 'Select default plane',
|
type: 'Select sketch plane',
|
||||||
data: {
|
data: {
|
||||||
type: 'defaultPlane',
|
type: 'defaultPlane',
|
||||||
planeId: planeId,
|
planeId: planeId,
|
||||||
@ -165,7 +166,7 @@ export function useEngineConnectionSubscriptions() {
|
|||||||
const planeInfo =
|
const planeInfo =
|
||||||
await sceneEntitiesManager.getFaceDetails(planeOrFaceId)
|
await sceneEntitiesManager.getFaceDetails(planeOrFaceId)
|
||||||
sceneInfra.modelingSend({
|
sceneInfra.modelingSend({
|
||||||
type: 'Select default plane',
|
type: 'Select sketch plane',
|
||||||
data: {
|
data: {
|
||||||
type: 'offsetPlane',
|
type: 'offsetPlane',
|
||||||
zAxis: [
|
zAxis: [
|
||||||
@ -194,7 +195,7 @@ export function useEngineConnectionSubscriptions() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Artifact is likely an extrusion face
|
// Artifact is likely an sweep face
|
||||||
const faceId = planeOrFaceId
|
const faceId = planeOrFaceId
|
||||||
const extrusion = getSweepFromSuspectedSweepSurface(
|
const extrusion = getSweepFromSuspectedSweepSurface(
|
||||||
faceId,
|
faceId,
|
||||||
@ -318,15 +319,31 @@ export function useEngineConnectionSubscriptions() {
|
|||||||
}
|
}
|
||||||
: { type: 'wall' }
|
: { type: 'wall' }
|
||||||
|
|
||||||
|
if (err(extrusion)) {
|
||||||
|
return Promise.reject(
|
||||||
|
new Error(`Extrusion is not a valid artifact: ${extrusion}`)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const lastChild =
|
||||||
|
findAllChildrenAndOrderByPlaceInCode(
|
||||||
|
{ type: 'sweep', ...extrusion },
|
||||||
|
kclManager.artifactGraph
|
||||||
|
)[0] || null
|
||||||
|
const lastChildCodeRef =
|
||||||
|
lastChild?.type === 'compositeSolid'
|
||||||
|
? lastChild.codeRef.range
|
||||||
|
: null
|
||||||
|
|
||||||
const extrudePathToNode = !err(extrusion)
|
const extrudePathToNode = !err(extrusion)
|
||||||
? getNodePathFromSourceRange(
|
? getNodePathFromSourceRange(
|
||||||
kclManager.ast,
|
kclManager.ast,
|
||||||
extrusion.codeRef.range
|
lastChildCodeRef || extrusion.codeRef.range
|
||||||
)
|
)
|
||||||
: []
|
: []
|
||||||
|
|
||||||
sceneInfra.modelingSend({
|
sceneInfra.modelingSend({
|
||||||
type: 'Select default plane',
|
type: 'Select sketch plane',
|
||||||
data: {
|
data: {
|
||||||
type: 'extrudeFace',
|
type: 'extrudeFace',
|
||||||
zAxis: [z_axis.x, z_axis.y, z_axis.z],
|
zAxis: [z_axis.x, z_axis.y, z_axis.z],
|
||||||
|
@ -461,7 +461,8 @@ export function sketchOnExtrudedFace(
|
|||||||
|
|
||||||
const expressionIndex = Math.max(
|
const expressionIndex = Math.max(
|
||||||
sketchPathToNode[1][0] as number,
|
sketchPathToNode[1][0] as number,
|
||||||
extrudePathToNode[1][0] as number
|
extrudePathToNode[1][0] as number,
|
||||||
|
node.body.length - 1
|
||||||
)
|
)
|
||||||
_node.body.splice(expressionIndex + 1, 0, newSketch)
|
_node.body.splice(expressionIndex + 1, 0, newSketch)
|
||||||
const newpathToNode: PathToNode = [
|
const newpathToNode: PathToNode = [
|
||||||
|
@ -211,6 +211,13 @@ export function findAllChildrenAndOrderByPlaceInCode(
|
|||||||
pushToSomething(currentId, current?.segIds)
|
pushToSomething(currentId, current?.segIds)
|
||||||
} else if (current?.type === 'sweep') {
|
} else if (current?.type === 'sweep') {
|
||||||
pushToSomething(currentId, current?.surfaceIds)
|
pushToSomething(currentId, current?.surfaceIds)
|
||||||
|
const path = artifactGraph.get(current.pathId)
|
||||||
|
if (path && path.type === 'path') {
|
||||||
|
const compositeSolidId = path.compositeSolidId
|
||||||
|
if (compositeSolidId) {
|
||||||
|
result.push(compositeSolidId)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (current?.type === 'wall' || current?.type === 'cap') {
|
} else if (current?.type === 'wall' || current?.type === 'cap') {
|
||||||
pushToSomething(currentId, current?.pathIds)
|
pushToSomething(currentId, current?.pathIds)
|
||||||
} else if (current?.type === 'segment') {
|
} else if (current?.type === 'segment') {
|
||||||
|
@ -305,7 +305,7 @@ export type ModelingMachineEvent =
|
|||||||
}
|
}
|
||||||
| { type: 'Sketch On Face' }
|
| { type: 'Sketch On Face' }
|
||||||
| {
|
| {
|
||||||
type: 'Select default plane'
|
type: 'Select sketch plane'
|
||||||
data: DefaultPlane | ExtrudeFacePlane | OffsetPlane
|
data: DefaultPlane | ExtrudeFacePlane | OffsetPlane
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
@ -4255,7 +4255,7 @@ export const modelingMachine = setup({
|
|||||||
|
|
||||||
exit: ['hide default planes', 'set selection filter to defaults'],
|
exit: ['hide default planes', 'set selection filter to defaults'],
|
||||||
on: {
|
on: {
|
||||||
'Select default plane': {
|
'Select sketch plane': {
|
||||||
target: 'animating to plane',
|
target: 'animating to plane',
|
||||||
actions: ['reset sketch metadata'],
|
actions: ['reset sketch metadata'],
|
||||||
},
|
},
|
||||||
@ -4268,7 +4268,7 @@ export const modelingMachine = setup({
|
|||||||
id: 'animate-to-face',
|
id: 'animate-to-face',
|
||||||
|
|
||||||
input: ({ event }) => {
|
input: ({ event }) => {
|
||||||
if (event.type !== 'Select default plane') return undefined
|
if (event.type !== 'Select sketch plane') return undefined
|
||||||
return event.data
|
return event.data
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user