Compare commits
2 Commits
v1.0.2
...
kurt-flang
Author | SHA1 | Date | |
---|---|---|---|
46bac7bb03 | |||
ab966423ac |
@ -1733,7 +1733,7 @@ profile003 = startProfile(sketch001, at = [206.63, -56.73])
|
|||||||
await page.waitForTimeout(600)
|
await page.waitForTimeout(600)
|
||||||
})
|
})
|
||||||
|
|
||||||
const codeFromTangentialArc = ` |> tangentialArc(end = [-10.82, 144.95])`
|
const codeFromTangentialArc = ` |> tangentialArc(endAbsolute = [39.49, 88.22])`
|
||||||
await test.step('check that tangential tool does not snap to other profile starts', async () => {
|
await test.step('check that tangential tool does not snap to other profile starts', async () => {
|
||||||
await toolbar.selectTangentialArc()
|
await toolbar.selectTangentialArc()
|
||||||
await page.waitForTimeout(1000)
|
await page.waitForTimeout(1000)
|
||||||
@ -1755,7 +1755,7 @@ profile003 = startProfile(sketch001, at = [206.63, -56.73])
|
|||||||
// check pixel is now gray at tanArcLocation to verify code has executed
|
// check pixel is now gray at tanArcLocation to verify code has executed
|
||||||
await scene.expectPixelColor([26, 26, 26], tanArcLocation, 15)
|
await scene.expectPixelColor([26, 26, 26], tanArcLocation, 15)
|
||||||
await editor.expectEditor.not.toContain(
|
await editor.expectEditor.not.toContain(
|
||||||
`tangentialArc(end = [-10.82, 144.95])`
|
`tangentialArc(endAbsolute = [39.49, 88.22])`
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -1955,7 +1955,7 @@ profile003 = startProfile(sketch001, at = [206.63, -56.73])
|
|||||||
|
|
||||||
await endArcStartLine()
|
await endArcStartLine()
|
||||||
await editor.expectEditor.toContain(
|
await editor.expectEditor.toContain(
|
||||||
`|> tangentialArc(end = [2.98, -7.52])`
|
`|> tangentialArc(endAbsolute = [16.61, 4.14])`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add a three-point arc segment
|
// Add a three-point arc segment
|
||||||
@ -3181,7 +3181,7 @@ test.describe('Redirecting to home page and back to the original file should cle
|
|||||||
sketch001 = startSketchOn(XZ)
|
sketch001 = startSketchOn(XZ)
|
||||||
profile001 = startProfile(sketch001, at = [0, 0])
|
profile001 = startProfile(sketch001, at = [0, 0])
|
||||||
|> line(end = [191.39, 191.39])
|
|> line(end = [191.39, 191.39])
|
||||||
|> tangentialArc(end = [95.69, -95.7], tag = $seg01)
|
|> tangentialArc(endAbsolute = [287.08, 95.69], tag = $seg01)
|
||||||
|> angledLine(angle = tangentToEnd(seg01), length = 135.34)
|
|> angledLine(angle = tangentToEnd(seg01), length = 135.34)
|
||||||
|> arc(interiorAbsolute = [191.39, -95.69], endAbsolute = [287.08, -95.69], tag = $seg02)
|
|> arc(interiorAbsolute = [191.39, -95.69], endAbsolute = [287.08, -95.69], tag = $seg02)
|
||||||
|> angledLine(angle = tangentToEnd(seg02) + turns::HALF_TURN, length = 270.67)
|
|> angledLine(angle = tangentToEnd(seg02) + turns::HALF_TURN, length = 270.67)
|
||||||
|
@ -375,22 +375,22 @@ test.describe(
|
|||||||
await expect(u.codeLocator).toHaveText(code)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
|
|
||||||
await toolbar.selectTangentialArc()
|
await toolbar.selectTangentialArc()
|
||||||
await page.waitForTimeout(200)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
// click to continue profile
|
// click to continue profile
|
||||||
await page.mouse.click(813, 392)
|
await page.mouse.click(813, 392)
|
||||||
await page.waitForTimeout(300)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
||||||
|
|
||||||
code += `
|
code += `
|
||||||
|> tangentialArc(end = [184.31, 184.31])`
|
|> tangentialArc(endAbsolute = [551.2, -62.01])`
|
||||||
await expect(u.codeLocator).toHaveText(code)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
|
|
||||||
// click tangential arc tool again to unequip it
|
// click tangential arc tool again to unequip it
|
||||||
// it will be available directly in the toolbar since it was last equipped
|
// it will be available directly in the toolbar since it was last equipped
|
||||||
await toolbar.tangentialArcBtn.click()
|
await toolbar.tangentialArcBtn.click()
|
||||||
await page.waitForTimeout(1000)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
// screen shot should show the sketch
|
// screen shot should show the sketch
|
||||||
await expect(page).toHaveScreenshot({
|
await expect(page).toHaveScreenshot({
|
||||||
@ -472,20 +472,20 @@ test.describe(
|
|||||||
await expect(u.codeLocator).toHaveText(code)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
|
|
||||||
await toolbar.selectTangentialArc()
|
await toolbar.selectTangentialArc()
|
||||||
await page.waitForTimeout(200)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
// click to continue profile
|
// click to continue profile
|
||||||
await page.mouse.click(813, 392)
|
await page.mouse.click(813, 392)
|
||||||
await page.waitForTimeout(300)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
await page.mouse.click(startXPx + PUR * 30, 500 - PUR * 20)
|
||||||
|
|
||||||
code += `
|
code += `
|
||||||
|> tangentialArc(end = [184.31, 184.31])`
|
|> tangentialArc(endAbsolute = [551.2, -62.01])`
|
||||||
await expect(u.codeLocator).toHaveText(code)
|
await expect(u.codeLocator).toHaveText(code)
|
||||||
|
|
||||||
await toolbar.tangentialArcBtn.click()
|
await toolbar.tangentialArcBtn.click()
|
||||||
await page.waitForTimeout(1000)
|
await page.waitForTimeout(100)
|
||||||
|
|
||||||
// screen shot should show the sketch
|
// screen shot should show the sketch
|
||||||
await expect(page).toHaveScreenshot({
|
await expect(page).toHaveScreenshot({
|
||||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
@ -61,7 +61,7 @@ test.describe('Test network related behaviors', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Expect the network to be down
|
// Expect the network to be down
|
||||||
await expect(networkToggle).toContainText('Problem')
|
await expect(networkToggle).toContainText('Network health (Offline)')
|
||||||
|
|
||||||
// Click the network widget
|
// Click the network widget
|
||||||
await networkWidget.click()
|
await networkWidget.click()
|
||||||
@ -156,7 +156,8 @@ test.describe('Test network related behaviors', () => {
|
|||||||
|
|
||||||
// Expect the network to be down
|
// Expect the network to be down
|
||||||
await networkToggle.hover()
|
await networkToggle.hover()
|
||||||
await expect(networkToggle).toContainText('Problem')
|
|
||||||
|
await expect(networkToggle).toContainText('Network health (Offline)')
|
||||||
|
|
||||||
// Ensure we are not in sketch mode
|
// Ensure we are not in sketch mode
|
||||||
await expect(
|
await expect(
|
||||||
|
@ -364,11 +364,6 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chrome devtools protocol session only works in Chromium
|
|
||||||
const browserType = page.context().browser()?.browserType().name()
|
|
||||||
const cdpSession =
|
|
||||||
browserType !== 'chromium' ? null : await page.context().newCDPSession(page)
|
|
||||||
|
|
||||||
const util = {
|
const util = {
|
||||||
waitForAuthSkipAppStart: () => waitForAuthAndLsp(page),
|
waitForAuthSkipAppStart: () => waitForAuthAndLsp(page),
|
||||||
waitForPageLoad: () => waitForPageLoad(page),
|
waitForPageLoad: () => waitForPageLoad(page),
|
||||||
@ -489,15 +484,9 @@ export async function getUtils(page: Page, test_?: typeof test) {
|
|||||||
emulateNetworkConditions: async (
|
emulateNetworkConditions: async (
|
||||||
networkOptions: Protocol.Network.emulateNetworkConditionsParameters
|
networkOptions: Protocol.Network.emulateNetworkConditionsParameters
|
||||||
) => {
|
) => {
|
||||||
if (cdpSession === null) {
|
return networkOptions.offline
|
||||||
// Use a fail safe if we can't simulate disconnect (on Safari)
|
? page.evaluate('window.engineCommandManager.offline()')
|
||||||
return page.evaluate('window.engineCommandManager.tearDown()')
|
: page.evaluate('window.engineCommandManager.online()')
|
||||||
}
|
|
||||||
|
|
||||||
return cdpSession?.send(
|
|
||||||
'Network.emulateNetworkConditions',
|
|
||||||
networkOptions
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
toNormalizedCode(text: string) {
|
toNormalizedCode(text: string) {
|
||||||
|
@ -7,17 +7,13 @@
|
|||||||
// Import parameters
|
// Import parameters
|
||||||
import pipeInnerDiameter, pipeOuterDiameter, pipeLength from "parameters.kcl"
|
import pipeInnerDiameter, pipeOuterDiameter, pipeLength from "parameters.kcl"
|
||||||
|
|
||||||
// Create a function to make the pipe. Export
|
|
||||||
export fn pipe() {
|
|
||||||
// Create the pipe base
|
// Create the pipe base
|
||||||
pipeBase = startSketchOn(XZ)
|
pipeBase = startSketchOn(XZ)
|
||||||
|> circle(%, center = [0, 0], radius = pipeOuterDiameter / 2)
|
|> circle(%, center = [0, 0], radius = pipeOuterDiameter / 2)
|
||||||
|> extrude(%, length = pipeLength)
|
|> extrude(%, length = pipeLength)
|
||||||
|
|
||||||
// Extrude a hole through the length of the pipe
|
// Extrude a hole through the length of the pipe
|
||||||
pipe = startSketchOn(pipeBase, face = END)
|
startSketchOn(pipeBase, face = END)
|
||||||
|> circle(center = [0, 0], radius = pipeInnerDiameter / 2)
|
|> circle(center = [0, 0], radius = pipeInnerDiameter / 2)
|
||||||
|> extrude(%, length = -pipeLength)
|
|> extrude(%, length = -pipeLength)
|
||||||
|> appearance(color = "#a24ed0")
|
|> appearance(color = "#a24ed0")
|
||||||
return pipe
|
|
||||||
}
|
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
// Import parameters
|
// Import parameters
|
||||||
import pipeDiameter, mountingHoleDiameter, mountingHolePlacementDiameter, flangeDiameter, flangeTotalThickness, flangeBackHeight, flangeFrontHeight, flangeBaseThickness, flangeBackDiameter, flangeFrontDiameter from "parameters.kcl"
|
import pipeDiameter, mountingHoleDiameter, mountingHolePlacementDiameter, flangeDiameter, flangeTotalThickness, flangeBackHeight, flangeFrontHeight, flangeBaseThickness, flangeBackDiameter, flangeFrontDiameter from "parameters.kcl"
|
||||||
|
|
||||||
// Create a function to create the flange. We must create a function since we are using multiple flanges.
|
|
||||||
export fn flange() {
|
|
||||||
// Sketch the mounting hole pattern
|
// Sketch the mounting hole pattern
|
||||||
mountingHoles = startSketchOn(XY)
|
mountingHoles = startSketchOn(XY)
|
||||||
|> circle(%, center = [0, mountingHolePlacementDiameter / 2], radius = mountingHoleDiameter / 2)
|
|> circle(%, center = [0, mountingHolePlacementDiameter / 2], radius = mountingHoleDiameter / 2)
|
||||||
@ -35,10 +33,7 @@ export fn flange() {
|
|||||||
|> extrude(%, length = flangeFrontHeight)
|
|> extrude(%, length = flangeFrontHeight)
|
||||||
|
|
||||||
// Create the circular cut in the center for the pipe
|
// Create the circular cut in the center for the pipe
|
||||||
pipeCut = startSketchOn(flangeFront, face = END)
|
startSketchOn(flangeFront, face = END)
|
||||||
|> circle(%, center = [0, 0], radius = pipeDiameter / 2)
|
|> circle(%, center = [0, 0], radius = pipeDiameter / 2)
|
||||||
|> extrude(%, length = -flangeTotalThickness)
|
|> extrude(%, length = -flangeTotalThickness)
|
||||||
|> appearance(%, color = "#bab0b0")
|
|> appearance(%, color = "#bab0b0")
|
||||||
|
|
||||||
return pipeCut
|
|
||||||
}
|
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
// Import parameters
|
// Import parameters
|
||||||
import boltDiameter, boltLength, boltHeadLength, boltHeadDiameter, boltHexDrive, boltHexFlatLength, boltThreadLength from "parameters.kcl"
|
import boltDiameter, boltLength, boltHeadLength, boltHeadDiameter, boltHexDrive, boltHexFlatLength, boltThreadLength from "parameters.kcl"
|
||||||
|
|
||||||
// Create a function to make a the bolt
|
|
||||||
export fn bolt() {
|
|
||||||
// Create the head of the cap screw
|
// Create the head of the cap screw
|
||||||
boltHead = startSketchOn(XZ)
|
boltHead = startSketchOn(XZ)
|
||||||
|> circle(center = [0, 0], radius = boltHeadDiameter / 2, tag = $topEdge)
|
|> circle(center = [0, 0], radius = boltHeadDiameter / 2, tag = $topEdge)
|
||||||
@ -30,10 +28,7 @@ export fn bolt() {
|
|||||||
|> extrude(length = -boltHeadLength * 0.75)
|
|> extrude(length = -boltHeadLength * 0.75)
|
||||||
|
|
||||||
// create the body of the bolt
|
// create the body of the bolt
|
||||||
boltBody = startSketchOn(boltHead, face = END)
|
startSketchOn(boltHead, face = END)
|
||||||
|> circle(center = [0, 0], radius = boltDiameter / 2, tag = $filletEdge)
|
|> circle(center = [0, 0], radius = boltDiameter / 2, tag = $filletEdge)
|
||||||
|> extrude(length = boltLength)
|
|> extrude(length = boltLength)
|
||||||
|> appearance(color = "#4dd043", metalness = 90, roughness = 90)
|
|> appearance(color = "#4dd043", metalness = 90, roughness = 90)
|
||||||
|
|
||||||
return boltBody
|
|
||||||
}
|
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
// Import parameters
|
// Import parameters
|
||||||
import hexNutDiameter, hexNutFlatToFlat, hexNutThickness, hexNutFlatLength from "parameters.kcl"
|
import hexNutDiameter, hexNutFlatToFlat, hexNutThickness, hexNutFlatLength from "parameters.kcl"
|
||||||
|
|
||||||
// Create a function to make the hex nut. Must be a function since multiple hex nuts are used
|
|
||||||
export fn hexNut() {
|
|
||||||
// Create the base of the hex nut
|
// Create the base of the hex nut
|
||||||
hexNutBase = startSketchOn(XY)
|
hexNutBase = startSketchOn(XY)
|
||||||
|> startProfile(at = [
|
|> startProfile(at = [
|
||||||
@ -24,10 +22,7 @@ export fn hexNut() {
|
|||||||
|> extrude(length = hexNutThickness)
|
|> extrude(length = hexNutThickness)
|
||||||
|
|
||||||
// Create the hole in the center of the hex nut
|
// Create the hole in the center of the hex nut
|
||||||
hexNut = startSketchOn(hexNutBase, face = END)
|
startSketchOn(hexNutBase, face = END)
|
||||||
|> circle(center = [0, 0], radius = hexNutDiameter / 2)
|
|> circle(center = [0, 0], radius = hexNutDiameter / 2)
|
||||||
|> extrude(%, length = -hexNutThickness)
|
|> extrude(%, length = -hexNutThickness)
|
||||||
|> appearance(%, color = "#4edfd5")
|
|> appearance(%, color = "#4edfd5")
|
||||||
|
|
||||||
return hexNut
|
|
||||||
}
|
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
// Import parameters
|
// Import parameters
|
||||||
import washerInnerDia, washerOuterDia, washerThickness from "parameters.kcl"
|
import washerInnerDia, washerOuterDia, washerThickness from "parameters.kcl"
|
||||||
|
|
||||||
// Create a function to make the washer. Must be a function since multiple washers are used.
|
|
||||||
export fn washer() {
|
|
||||||
// Create the base of the washer
|
// Create the base of the washer
|
||||||
washerBase = startSketchOn(XY)
|
washerBase = startSketchOn(XY)
|
||||||
|> circle(center = [0, 0], radius = washerOuterDia / 2)
|
|> circle(center = [0, 0], radius = washerOuterDia / 2)
|
||||||
@ -19,6 +17,3 @@ export fn washer() {
|
|||||||
|> circle(center = [0, 0], radius = washerInnerDia / 2)
|
|> circle(center = [0, 0], radius = washerInnerDia / 2)
|
||||||
|> extrude(%, length = -washerThickness)
|
|> extrude(%, length = -washerThickness)
|
||||||
|> appearance(%, color = "#ee4f4f")
|
|> appearance(%, color = "#ee4f4f")
|
||||||
|
|
||||||
return washer
|
|
||||||
}
|
|
||||||
|
@ -9,16 +9,19 @@ import * from "parameters.kcl"
|
|||||||
|
|
||||||
// Import parts
|
// Import parts
|
||||||
import "9472k188-gasket.kcl" as gasket
|
import "9472k188-gasket.kcl" as gasket
|
||||||
import flange from "68095k348-flange.kcl"
|
import "68095k348-flange.kcl" as flange
|
||||||
import washer from "98017a257-washer.kcl"
|
import "98017a257-washer.kcl" as washer
|
||||||
import bolt from "91251a404-bolt.kcl"
|
import "91251a404-bolt.kcl" as bolt
|
||||||
import hexNut from "95479a127-hex-nut.kcl"
|
import "95479a127-hex-nut.kcl" as hexNut
|
||||||
import pipe from "1120t74-pipe.kcl"
|
import "1120t74-pipe.kcl" as pipe
|
||||||
|
|
||||||
// Place flanges
|
// Place flange clone
|
||||||
flange()
|
rotate(
|
||||||
flange()
|
clone(flange),
|
||||||
|> rotate(axis = [0, 1, 0], angle = 180)
|
roll = 180,
|
||||||
|
pitch = 0,
|
||||||
|
yaw = 0,
|
||||||
|
)
|
||||||
|> translate(x = 0, y = 0, z = flangeBackHeight * 2 + gasketThickness)
|
|> translate(x = 0, y = 0, z = flangeBackHeight * 2 + gasketThickness)
|
||||||
|
|
||||||
// Place gasket between the flanges
|
// Place gasket between the flanges
|
||||||
@ -26,7 +29,7 @@ gasket
|
|||||||
|> translate(x = 0, y = 0, z = -flangeBackHeight - gasketThickness)
|
|> translate(x = 0, y = 0, z = -flangeBackHeight - gasketThickness)
|
||||||
|
|
||||||
// Place eight washers (four front, four back)
|
// Place eight washers (four front, four back)
|
||||||
washer()
|
washer
|
||||||
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = flangeBaseThickness)
|
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = flangeBaseThickness)
|
||||||
|> patternCircular3d(
|
|> patternCircular3d(
|
||||||
%,
|
%,
|
||||||
@ -44,7 +47,8 @@ washer()
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Place four bolts
|
// Place four bolts
|
||||||
bolt()
|
|
||||||
|
bolt
|
||||||
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = flangeBaseThickness + washerThickness)
|
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = flangeBaseThickness + washerThickness)
|
||||||
|> rotate(roll = 90, pitch = 0, yaw = 0)
|
|> rotate(roll = 90, pitch = 0, yaw = 0)
|
||||||
|> patternCircular3d(
|
|> patternCircular3d(
|
||||||
@ -57,7 +61,7 @@ bolt()
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Place four hex nuts
|
// Place four hex nuts
|
||||||
hexNut()
|
hexNut
|
||||||
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = -(flangeBackHeight * 2 + gasketThickness + flangeBaseThickness + washerThickness + hexNutThickness))
|
|> translate(x = mountingHolePlacementDiameter / 2, y = 0, z = -(flangeBackHeight * 2 + gasketThickness + flangeBaseThickness + washerThickness + hexNutThickness))
|
||||||
|> patternCircular3d(
|
|> patternCircular3d(
|
||||||
%,
|
%,
|
||||||
@ -69,9 +73,8 @@ hexNut()
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Place both pieces of pipe
|
// Place both pieces of pipe
|
||||||
pipe()
|
rotate(
|
||||||
|> rotate(
|
pipe,
|
||||||
%,
|
|
||||||
roll = -90,
|
roll = -90,
|
||||||
pitch = 0,
|
pitch = 0,
|
||||||
yaw = 0,
|
yaw = 0,
|
||||||
@ -83,16 +86,13 @@ pipe()
|
|||||||
z = flangeBaseThickness + flangeFrontHeight - 0.5,
|
z = flangeBaseThickness + flangeFrontHeight - 0.5,
|
||||||
global = true,
|
global = true,
|
||||||
)
|
)
|
||||||
|
rotate(
|
||||||
pipe()
|
clone(pipe),
|
||||||
|> rotate(
|
roll = 180,
|
||||||
%,
|
|
||||||
roll = 90,
|
|
||||||
pitch = 0,
|
pitch = 0,
|
||||||
yaw = 0,
|
yaw = 0,
|
||||||
)
|
)
|
||||||
|> translate(
|
|> translate(
|
||||||
%,
|
|
||||||
x = 0,
|
x = 0,
|
||||||
y = 0,
|
y = 0,
|
||||||
z = -(flangeBackHeight * 2 + gasketThickness + flangeBaseThickness + flangeFrontHeight - 0.5),
|
z = -(flangeBackHeight * 2 + gasketThickness + flangeBaseThickness + flangeFrontHeight - 0.5),
|
||||||
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 75 KiB |
@ -652,19 +652,19 @@ flowchart LR
|
|||||||
84 --- 144
|
84 --- 144
|
||||||
84 --- 237
|
84 --- 237
|
||||||
86 --- 168
|
86 --- 168
|
||||||
86 x--> 188
|
86 x--> 189
|
||||||
86 --- 212
|
86 --- 212
|
||||||
86 --- 256
|
86 --- 256
|
||||||
88 --- 169
|
88 --- 169
|
||||||
88 x--> 188
|
88 x--> 189
|
||||||
88 --- 213
|
88 --- 213
|
||||||
88 --- 257
|
88 --- 257
|
||||||
90 --- 167
|
90 --- 167
|
||||||
90 x--> 188
|
90 x--> 189
|
||||||
90 --- 214
|
90 --- 214
|
||||||
90 --- 258
|
90 --- 258
|
||||||
92 --- 170
|
92 --- 170
|
||||||
92 x--> 188
|
92 x--> 189
|
||||||
92 --- 215
|
92 --- 215
|
||||||
92 --- 259
|
92 --- 259
|
||||||
119 --- 133
|
119 --- 133
|
||||||
@ -946,10 +946,10 @@ flowchart LR
|
|||||||
218 <--x 186
|
218 <--x 186
|
||||||
219 <--x 186
|
219 <--x 186
|
||||||
194 <--x 187
|
194 <--x 187
|
||||||
212 <--x 189
|
212 <--x 188
|
||||||
213 <--x 189
|
213 <--x 188
|
||||||
214 <--x 189
|
214 <--x 188
|
||||||
215 <--x 189
|
215 <--x 188
|
||||||
220 <--x 268
|
220 <--x 268
|
||||||
223 <--x 267
|
223 <--x 267
|
||||||
```
|
```
|
||||||
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 83 KiB |
@ -87,20 +87,20 @@ flowchart LR
|
|||||||
27 --- 4
|
27 --- 4
|
||||||
8 --- 20
|
8 --- 20
|
||||||
8 x--> 25
|
8 x--> 25
|
||||||
8 --- 29
|
8 --- 30
|
||||||
8 --- 35
|
8 --- 36
|
||||||
9 --- 21
|
9 --- 21
|
||||||
9 x--> 25
|
9 x--> 25
|
||||||
9 --- 33
|
9 --- 33
|
||||||
9 --- 39
|
9 --- 39
|
||||||
10 --- 22
|
10 --- 22
|
||||||
10 x--> 25
|
10 x--> 25
|
||||||
10 --- 30
|
10 --- 31
|
||||||
10 --- 36
|
10 --- 37
|
||||||
11 --- 23
|
11 --- 23
|
||||||
11 x--> 25
|
11 x--> 25
|
||||||
11 --- 31
|
11 --- 29
|
||||||
11 --- 37
|
11 --- 35
|
||||||
12 --- 24
|
12 --- 24
|
||||||
12 x--> 25
|
12 x--> 25
|
||||||
12 --- 32
|
12 --- 32
|
||||||
@ -132,18 +132,18 @@ flowchart LR
|
|||||||
18 --- 34
|
18 --- 34
|
||||||
19 --- 28
|
19 --- 28
|
||||||
19 --- 34
|
19 --- 34
|
||||||
20 --- 29
|
20 --- 30
|
||||||
20 --- 35
|
20 --- 36
|
||||||
36 <--x 20
|
37 <--x 20
|
||||||
21 --- 33
|
21 --- 33
|
||||||
35 <--x 21
|
35 <--x 21
|
||||||
21 --- 39
|
21 --- 39
|
||||||
22 --- 30
|
22 --- 31
|
||||||
22 --- 36
|
22 --- 37
|
||||||
37 <--x 22
|
38 <--x 22
|
||||||
23 --- 31
|
23 --- 29
|
||||||
23 --- 37
|
23 --- 35
|
||||||
38 <--x 23
|
36 <--x 23
|
||||||
24 --- 32
|
24 --- 32
|
||||||
24 --- 38
|
24 --- 38
|
||||||
39 <--x 24
|
39 <--x 24
|
||||||
|
@ -366,114 +366,114 @@ flowchart LR
|
|||||||
11 ---- 74
|
11 ---- 74
|
||||||
26 --- 75
|
26 --- 75
|
||||||
26 x--> 108
|
26 x--> 108
|
||||||
26 --- 130
|
26 --- 114
|
||||||
26 --- 162
|
26 --- 146
|
||||||
27 --- 76
|
27 --- 76
|
||||||
27 x--> 108
|
27 x--> 108
|
||||||
27 --- 116
|
27 --- 139
|
||||||
27 --- 148
|
27 --- 171
|
||||||
28 --- 77
|
28 --- 77
|
||||||
28 x--> 108
|
28 x--> 108
|
||||||
28 --- 139
|
28 --- 135
|
||||||
28 --- 171
|
28 --- 167
|
||||||
29 --- 78
|
29 --- 78
|
||||||
29 x--> 108
|
29 x--> 108
|
||||||
29 --- 135
|
29 --- 133
|
||||||
29 --- 167
|
29 --- 165
|
||||||
30 --- 79
|
30 --- 79
|
||||||
30 x--> 108
|
30 x--> 108
|
||||||
30 --- 128
|
30 --- 121
|
||||||
30 --- 160
|
30 --- 153
|
||||||
31 --- 80
|
31 --- 80
|
||||||
31 x--> 108
|
31 x--> 108
|
||||||
31 --- 123
|
31 --- 115
|
||||||
31 --- 155
|
31 --- 147
|
||||||
32 --- 81
|
32 --- 81
|
||||||
32 x--> 108
|
32 x--> 108
|
||||||
32 --- 127
|
32 --- 129
|
||||||
32 --- 159
|
32 --- 161
|
||||||
33 --- 82
|
33 --- 82
|
||||||
33 x--> 108
|
33 x--> 108
|
||||||
33 --- 132
|
33 --- 131
|
||||||
33 --- 164
|
33 --- 163
|
||||||
34 --- 83
|
34 --- 83
|
||||||
34 x--> 108
|
34 x--> 108
|
||||||
34 --- 133
|
34 --- 138
|
||||||
34 --- 165
|
34 --- 170
|
||||||
35 --- 84
|
35 --- 84
|
||||||
35 x--> 108
|
35 x--> 108
|
||||||
35 --- 121
|
35 --- 119
|
||||||
35 --- 153
|
35 --- 151
|
||||||
36 --- 85
|
36 --- 85
|
||||||
36 x--> 108
|
36 x--> 108
|
||||||
36 --- 137
|
36 --- 125
|
||||||
36 --- 169
|
36 --- 157
|
||||||
37 --- 86
|
37 --- 86
|
||||||
37 x--> 108
|
37 x--> 108
|
||||||
37 --- 115
|
37 --- 117
|
||||||
37 --- 147
|
37 --- 149
|
||||||
38 --- 87
|
38 --- 87
|
||||||
38 x--> 108
|
38 x--> 108
|
||||||
38 --- 120
|
38 --- 122
|
||||||
38 --- 152
|
38 --- 154
|
||||||
39 --- 88
|
39 --- 88
|
||||||
39 x--> 108
|
39 x--> 108
|
||||||
39 --- 124
|
39 --- 113
|
||||||
39 --- 156
|
39 --- 145
|
||||||
40 --- 89
|
40 --- 89
|
||||||
40 x--> 108
|
40 x--> 108
|
||||||
40 --- 134
|
40 --- 124
|
||||||
40 --- 166
|
40 --- 156
|
||||||
41 --- 90
|
41 --- 90
|
||||||
41 x--> 108
|
41 x--> 108
|
||||||
41 --- 136
|
41 --- 134
|
||||||
41 --- 168
|
41 --- 166
|
||||||
42 --- 91
|
42 --- 91
|
||||||
42 x--> 108
|
42 x--> 108
|
||||||
42 --- 122
|
42 --- 132
|
||||||
42 --- 154
|
42 --- 164
|
||||||
43 --- 92
|
43 --- 92
|
||||||
43 x--> 108
|
43 x--> 108
|
||||||
43 --- 114
|
43 --- 120
|
||||||
43 --- 146
|
43 --- 152
|
||||||
44 --- 93
|
44 --- 93
|
||||||
44 x--> 108
|
44 x--> 108
|
||||||
44 --- 113
|
44 --- 118
|
||||||
44 --- 145
|
44 --- 150
|
||||||
45 --- 94
|
45 --- 94
|
||||||
45 x--> 108
|
45 x--> 108
|
||||||
45 --- 131
|
45 --- 137
|
||||||
45 --- 163
|
45 --- 169
|
||||||
46 --- 95
|
46 --- 95
|
||||||
46 x--> 108
|
46 x--> 108
|
||||||
46 --- 117
|
46 --- 130
|
||||||
46 --- 149
|
46 --- 162
|
||||||
47 --- 96
|
47 --- 96
|
||||||
47 x--> 108
|
47 x--> 108
|
||||||
47 --- 125
|
47 --- 126
|
||||||
47 --- 157
|
47 --- 158
|
||||||
48 --- 97
|
48 --- 97
|
||||||
48 x--> 108
|
48 x--> 108
|
||||||
48 --- 119
|
48 --- 128
|
||||||
48 --- 151
|
48 --- 160
|
||||||
49 --- 98
|
49 --- 98
|
||||||
49 x--> 108
|
49 x--> 108
|
||||||
49 --- 126
|
49 --- 127
|
||||||
49 --- 158
|
49 --- 159
|
||||||
50 --- 99
|
50 --- 99
|
||||||
50 x--> 108
|
50 x--> 108
|
||||||
50 --- 118
|
50 --- 136
|
||||||
50 --- 150
|
50 --- 168
|
||||||
51 --- 100
|
51 --- 100
|
||||||
51 x--> 108
|
51 x--> 108
|
||||||
51 --- 129
|
51 --- 116
|
||||||
51 --- 161
|
51 --- 148
|
||||||
52 --- 101
|
52 --- 101
|
||||||
52 x--> 108
|
52 x--> 108
|
||||||
52 --- 138
|
52 --- 123
|
||||||
52 --- 170
|
52 --- 155
|
||||||
61 --- 102
|
61 --- 102
|
||||||
61 x--> 110
|
61 x--> 109
|
||||||
61 --- 140
|
61 --- 140
|
||||||
61 --- 172
|
61 --- 172
|
||||||
63 --- 103
|
63 --- 103
|
||||||
@ -594,87 +594,87 @@ flowchart LR
|
|||||||
74 --- 174
|
74 --- 174
|
||||||
74 --- 175
|
74 --- 175
|
||||||
74 --- 176
|
74 --- 176
|
||||||
75 --- 130
|
75 --- 114
|
||||||
75 --- 162
|
75 --- 146
|
||||||
163 <--x 75
|
147 <--x 75
|
||||||
76 --- 116
|
76 --- 139
|
||||||
76 --- 148
|
145 <--x 76
|
||||||
149 <--x 76
|
76 --- 171
|
||||||
77 --- 139
|
77 --- 135
|
||||||
145 <--x 77
|
77 --- 167
|
||||||
77 --- 171
|
168 <--x 77
|
||||||
78 --- 135
|
78 --- 133
|
||||||
78 --- 167
|
78 --- 165
|
||||||
168 <--x 78
|
166 <--x 78
|
||||||
79 --- 128
|
79 --- 121
|
||||||
79 --- 160
|
79 --- 153
|
||||||
161 <--x 79
|
154 <--x 79
|
||||||
80 --- 123
|
80 --- 115
|
||||||
80 --- 155
|
80 --- 147
|
||||||
156 <--x 80
|
148 <--x 80
|
||||||
81 --- 127
|
81 --- 129
|
||||||
81 --- 159
|
81 --- 161
|
||||||
160 <--x 81
|
162 <--x 81
|
||||||
82 --- 132
|
82 --- 131
|
||||||
82 --- 164
|
82 --- 163
|
||||||
165 <--x 82
|
164 <--x 82
|
||||||
83 --- 133
|
83 --- 138
|
||||||
83 --- 165
|
83 --- 170
|
||||||
166 <--x 83
|
171 <--x 83
|
||||||
84 --- 121
|
84 --- 119
|
||||||
84 --- 153
|
84 --- 151
|
||||||
154 <--x 84
|
152 <--x 84
|
||||||
85 --- 137
|
85 --- 125
|
||||||
85 --- 169
|
85 --- 157
|
||||||
170 <--x 85
|
158 <--x 85
|
||||||
86 --- 115
|
86 --- 117
|
||||||
86 --- 147
|
86 --- 149
|
||||||
148 <--x 86
|
150 <--x 86
|
||||||
87 --- 120
|
87 --- 122
|
||||||
87 --- 152
|
87 --- 154
|
||||||
153 <--x 87
|
155 <--x 87
|
||||||
88 --- 124
|
88 --- 113
|
||||||
88 --- 156
|
88 --- 145
|
||||||
157 <--x 88
|
146 <--x 88
|
||||||
89 --- 134
|
89 --- 124
|
||||||
89 --- 166
|
89 --- 156
|
||||||
167 <--x 89
|
157 <--x 89
|
||||||
90 --- 136
|
90 --- 134
|
||||||
90 --- 168
|
90 --- 166
|
||||||
169 <--x 90
|
167 <--x 90
|
||||||
91 --- 122
|
91 --- 132
|
||||||
91 --- 154
|
91 --- 164
|
||||||
155 <--x 91
|
165 <--x 91
|
||||||
92 --- 114
|
92 --- 120
|
||||||
92 --- 146
|
92 --- 152
|
||||||
147 <--x 92
|
153 <--x 92
|
||||||
93 --- 113
|
93 --- 118
|
||||||
93 --- 145
|
93 --- 150
|
||||||
146 <--x 93
|
151 <--x 93
|
||||||
94 --- 131
|
94 --- 137
|
||||||
94 --- 163
|
94 --- 169
|
||||||
164 <--x 94
|
170 <--x 94
|
||||||
95 --- 117
|
95 --- 130
|
||||||
95 --- 149
|
95 --- 162
|
||||||
150 <--x 95
|
163 <--x 95
|
||||||
96 --- 125
|
96 --- 126
|
||||||
96 --- 157
|
96 --- 158
|
||||||
158 <--x 96
|
159 <--x 96
|
||||||
97 --- 119
|
97 --- 128
|
||||||
97 --- 151
|
97 --- 160
|
||||||
152 <--x 97
|
161 <--x 97
|
||||||
98 --- 126
|
98 --- 127
|
||||||
98 --- 158
|
98 --- 159
|
||||||
159 <--x 98
|
160 <--x 98
|
||||||
99 --- 118
|
99 --- 136
|
||||||
99 --- 150
|
99 --- 168
|
||||||
151 <--x 99
|
169 <--x 99
|
||||||
100 --- 129
|
100 --- 116
|
||||||
100 --- 161
|
100 --- 148
|
||||||
162 <--x 100
|
149 <--x 100
|
||||||
101 --- 138
|
101 --- 123
|
||||||
101 --- 170
|
101 --- 155
|
||||||
171 <--x 101
|
156 <--x 101
|
||||||
102 --- 140
|
102 --- 140
|
||||||
102 --- 172
|
102 --- 172
|
||||||
103 --- 144
|
103 --- 144
|
||||||
@ -689,7 +689,7 @@ flowchart LR
|
|||||||
106 --- 141
|
106 --- 141
|
||||||
106 --- 173
|
106 --- 173
|
||||||
174 <--x 106
|
174 <--x 106
|
||||||
140 <--x 109
|
140 <--x 110
|
||||||
141 <--x 111
|
141 <--x 111
|
||||||
142 <--x 111
|
142 <--x 111
|
||||||
143 <--x 111
|
143 <--x 111
|
||||||
|
@ -582,48 +582,48 @@ flowchart LR
|
|||||||
46 --- 226
|
46 --- 226
|
||||||
72 --- 112
|
72 --- 112
|
||||||
72 x--> 151
|
72 x--> 151
|
||||||
72 --- 167
|
72 --- 163
|
||||||
72 --- 201
|
72 --- 197
|
||||||
73 --- 113
|
73 --- 113
|
||||||
73 x--> 151
|
73 x--> 151
|
||||||
73 --- 169
|
73 --- 164
|
||||||
73 --- 203
|
73 --- 198
|
||||||
74 --- 114
|
74 --- 114
|
||||||
74 x--> 151
|
74 x--> 151
|
||||||
74 --- 168
|
74 --- 168
|
||||||
74 --- 202
|
74 --- 202
|
||||||
75 --- 115
|
75 --- 115
|
||||||
75 x--> 151
|
75 x--> 151
|
||||||
75 --- 166
|
75 --- 165
|
||||||
75 --- 200
|
75 --- 199
|
||||||
76 --- 116
|
76 --- 116
|
||||||
76 x--> 151
|
76 x--> 151
|
||||||
76 --- 165
|
76 --- 162
|
||||||
76 --- 199
|
76 --- 196
|
||||||
77 --- 117
|
77 --- 117
|
||||||
77 x--> 151
|
77 x--> 151
|
||||||
77 --- 161
|
77 --- 161
|
||||||
77 --- 195
|
77 --- 195
|
||||||
78 --- 118
|
78 --- 118
|
||||||
78 x--> 151
|
78 x--> 151
|
||||||
78 --- 162
|
78 --- 167
|
||||||
78 --- 196
|
78 --- 201
|
||||||
79 --- 119
|
79 --- 119
|
||||||
79 x--> 151
|
79 x--> 151
|
||||||
79 --- 163
|
79 --- 170
|
||||||
79 --- 197
|
79 --- 204
|
||||||
80 --- 120
|
80 --- 120
|
||||||
80 x--> 151
|
80 x--> 151
|
||||||
80 --- 170
|
80 --- 160
|
||||||
80 --- 204
|
80 --- 194
|
||||||
81 --- 121
|
81 --- 121
|
||||||
81 x--> 151
|
81 x--> 151
|
||||||
81 --- 160
|
81 --- 169
|
||||||
81 --- 194
|
81 --- 203
|
||||||
82 --- 122
|
82 --- 122
|
||||||
82 x--> 151
|
82 x--> 151
|
||||||
82 --- 164
|
82 --- 166
|
||||||
82 --- 198
|
82 --- 200
|
||||||
84 --- 123
|
84 --- 123
|
||||||
84 x--> 145
|
84 x--> 145
|
||||||
84 --- 171
|
84 --- 171
|
||||||
@ -756,39 +756,39 @@ flowchart LR
|
|||||||
109 --- 107
|
109 --- 107
|
||||||
111 --- 159
|
111 --- 159
|
||||||
111 --- 193
|
111 --- 193
|
||||||
112 --- 167
|
112 --- 163
|
||||||
112 --- 201
|
112 --- 197
|
||||||
202 <--x 112
|
198 <--x 112
|
||||||
113 --- 169
|
113 --- 164
|
||||||
113 --- 203
|
113 --- 198
|
||||||
204 <--x 113
|
199 <--x 113
|
||||||
114 --- 168
|
114 --- 168
|
||||||
114 --- 202
|
114 --- 202
|
||||||
203 <--x 114
|
203 <--x 114
|
||||||
115 --- 166
|
115 --- 165
|
||||||
115 --- 200
|
115 --- 199
|
||||||
201 <--x 115
|
200 <--x 115
|
||||||
116 --- 165
|
116 --- 162
|
||||||
116 --- 199
|
116 --- 196
|
||||||
200 <--x 116
|
197 <--x 116
|
||||||
117 --- 161
|
117 --- 161
|
||||||
117 --- 195
|
117 --- 195
|
||||||
196 <--x 117
|
196 <--x 117
|
||||||
118 --- 162
|
118 --- 167
|
||||||
118 --- 196
|
118 --- 201
|
||||||
197 <--x 118
|
202 <--x 118
|
||||||
119 --- 163
|
119 --- 170
|
||||||
119 --- 197
|
194 <--x 119
|
||||||
198 <--x 119
|
119 --- 204
|
||||||
120 --- 170
|
120 --- 160
|
||||||
194 <--x 120
|
120 --- 194
|
||||||
120 --- 204
|
195 <--x 120
|
||||||
121 --- 160
|
121 --- 169
|
||||||
121 --- 194
|
121 --- 203
|
||||||
195 <--x 121
|
204 <--x 121
|
||||||
122 --- 164
|
122 --- 166
|
||||||
122 --- 198
|
122 --- 200
|
||||||
199 <--x 122
|
201 <--x 122
|
||||||
123 --- 171
|
123 --- 171
|
||||||
123 --- 205
|
123 --- 205
|
||||||
124 --- 186
|
124 --- 186
|
||||||
|
@ -177,72 +177,72 @@ flowchart LR
|
|||||||
2 ---- 34
|
2 ---- 34
|
||||||
17 --- 35
|
17 --- 35
|
||||||
17 x--> 52
|
17 x--> 52
|
||||||
17 --- 58
|
17 --- 67
|
||||||
17 --- 75
|
17 --- 84
|
||||||
18 --- 36
|
18 --- 36
|
||||||
18 x--> 52
|
18 x--> 52
|
||||||
18 --- 66
|
18 --- 65
|
||||||
18 --- 83
|
18 --- 82
|
||||||
19 --- 37
|
19 --- 37
|
||||||
19 x--> 52
|
19 x--> 52
|
||||||
19 --- 60
|
19 --- 55
|
||||||
19 --- 77
|
19 --- 72
|
||||||
20 --- 38
|
20 --- 38
|
||||||
20 x--> 52
|
20 x--> 52
|
||||||
20 --- 61
|
20 --- 61
|
||||||
20 --- 78
|
20 --- 78
|
||||||
21 --- 39
|
21 --- 39
|
||||||
21 x--> 52
|
21 x--> 52
|
||||||
21 --- 67
|
21 --- 69
|
||||||
21 --- 84
|
21 --- 86
|
||||||
22 --- 40
|
22 --- 40
|
||||||
22 x--> 52
|
22 x--> 52
|
||||||
22 --- 63
|
22 --- 63
|
||||||
22 --- 80
|
22 --- 80
|
||||||
23 --- 41
|
23 --- 41
|
||||||
23 x--> 52
|
23 x--> 52
|
||||||
23 --- 56
|
23 --- 60
|
||||||
23 --- 73
|
23 --- 77
|
||||||
24 --- 42
|
24 --- 42
|
||||||
24 x--> 52
|
24 x--> 52
|
||||||
24 --- 54
|
24 --- 54
|
||||||
24 --- 71
|
24 --- 71
|
||||||
25 --- 43
|
25 --- 43
|
||||||
25 x--> 52
|
25 x--> 52
|
||||||
25 --- 70
|
25 --- 66
|
||||||
25 --- 87
|
25 --- 83
|
||||||
26 --- 44
|
26 --- 44
|
||||||
26 x--> 52
|
26 x--> 52
|
||||||
26 --- 68
|
26 --- 57
|
||||||
26 --- 85
|
26 --- 74
|
||||||
27 --- 45
|
27 --- 45
|
||||||
27 x--> 52
|
27 x--> 52
|
||||||
27 --- 65
|
27 --- 64
|
||||||
27 --- 82
|
27 --- 81
|
||||||
28 --- 46
|
28 --- 46
|
||||||
28 x--> 52
|
28 x--> 52
|
||||||
28 --- 62
|
28 --- 58
|
||||||
28 --- 79
|
28 --- 75
|
||||||
29 --- 47
|
29 --- 47
|
||||||
29 x--> 52
|
29 x--> 52
|
||||||
29 --- 57
|
29 --- 59
|
||||||
29 --- 74
|
29 --- 76
|
||||||
30 --- 48
|
30 --- 48
|
||||||
30 x--> 52
|
30 x--> 52
|
||||||
30 --- 55
|
30 --- 56
|
||||||
30 --- 72
|
30 --- 73
|
||||||
31 --- 49
|
31 --- 49
|
||||||
31 x--> 52
|
31 x--> 52
|
||||||
31 --- 64
|
31 --- 62
|
||||||
31 --- 81
|
31 --- 79
|
||||||
32 --- 50
|
32 --- 50
|
||||||
32 x--> 52
|
32 x--> 52
|
||||||
32 --- 69
|
32 --- 70
|
||||||
32 --- 86
|
32 --- 87
|
||||||
33 --- 51
|
33 --- 51
|
||||||
33 x--> 52
|
33 x--> 52
|
||||||
33 --- 59
|
33 --- 68
|
||||||
33 --- 76
|
33 --- 85
|
||||||
34 --- 35
|
34 --- 35
|
||||||
34 --- 36
|
34 --- 36
|
||||||
34 --- 37
|
34 --- 37
|
||||||
@ -296,57 +296,57 @@ flowchart LR
|
|||||||
34 --- 85
|
34 --- 85
|
||||||
34 --- 86
|
34 --- 86
|
||||||
34 --- 87
|
34 --- 87
|
||||||
35 --- 58
|
35 --- 67
|
||||||
74 <--x 35
|
83 <--x 35
|
||||||
35 --- 75
|
35 --- 84
|
||||||
36 --- 66
|
36 --- 65
|
||||||
82 <--x 36
|
81 <--x 36
|
||||||
36 --- 83
|
36 --- 82
|
||||||
37 --- 60
|
37 --- 55
|
||||||
76 <--x 37
|
71 <--x 37
|
||||||
37 --- 77
|
37 --- 72
|
||||||
38 --- 61
|
38 --- 61
|
||||||
77 <--x 38
|
77 <--x 38
|
||||||
38 --- 78
|
38 --- 78
|
||||||
39 --- 67
|
39 --- 69
|
||||||
83 <--x 39
|
85 <--x 39
|
||||||
39 --- 84
|
39 --- 86
|
||||||
40 --- 63
|
40 --- 63
|
||||||
79 <--x 40
|
79 <--x 40
|
||||||
40 --- 80
|
40 --- 80
|
||||||
41 --- 56
|
41 --- 60
|
||||||
72 <--x 41
|
76 <--x 41
|
||||||
41 --- 73
|
41 --- 77
|
||||||
42 --- 54
|
42 --- 54
|
||||||
42 --- 71
|
42 --- 71
|
||||||
87 <--x 42
|
87 <--x 42
|
||||||
43 --- 70
|
43 --- 66
|
||||||
86 <--x 43
|
82 <--x 43
|
||||||
43 --- 87
|
43 --- 83
|
||||||
44 --- 68
|
44 --- 57
|
||||||
84 <--x 44
|
73 <--x 44
|
||||||
44 --- 85
|
44 --- 74
|
||||||
45 --- 65
|
45 --- 64
|
||||||
81 <--x 45
|
80 <--x 45
|
||||||
45 --- 82
|
45 --- 81
|
||||||
46 --- 62
|
46 --- 58
|
||||||
78 <--x 46
|
74 <--x 46
|
||||||
46 --- 79
|
46 --- 75
|
||||||
47 --- 57
|
47 --- 59
|
||||||
73 <--x 47
|
75 <--x 47
|
||||||
47 --- 74
|
47 --- 76
|
||||||
48 --- 55
|
48 --- 56
|
||||||
71 <--x 48
|
72 <--x 48
|
||||||
48 --- 72
|
48 --- 73
|
||||||
49 --- 64
|
49 --- 62
|
||||||
80 <--x 49
|
78 <--x 49
|
||||||
49 --- 81
|
49 --- 79
|
||||||
50 --- 69
|
50 --- 70
|
||||||
85 <--x 50
|
86 <--x 50
|
||||||
50 --- 86
|
50 --- 87
|
||||||
51 --- 59
|
51 --- 68
|
||||||
75 <--x 51
|
84 <--x 51
|
||||||
51 --- 76
|
51 --- 85
|
||||||
54 <--x 53
|
54 <--x 53
|
||||||
55 <--x 53
|
55 <--x 53
|
||||||
56 <--x 53
|
56 <--x 53
|
||||||
|
@ -59,23 +59,14 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"filename": "68095k348-flange.kcl"
|
"filename": "68095k348-flange.kcl"
|
||||||
},
|
},
|
||||||
"selector": {
|
"selector": {
|
||||||
"type": "List",
|
"type": "None",
|
||||||
"items": [
|
"alias": {
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": {
|
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "flange",
|
"name": "flange",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
|
||||||
"start": 0,
|
|
||||||
"type": "ImportItem"
|
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "ImportStatement",
|
"type": "ImportStatement",
|
||||||
@ -89,23 +80,14 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"filename": "98017a257-washer.kcl"
|
"filename": "98017a257-washer.kcl"
|
||||||
},
|
},
|
||||||
"selector": {
|
"selector": {
|
||||||
"type": "List",
|
"type": "None",
|
||||||
"items": [
|
"alias": {
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": {
|
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "washer",
|
"name": "washer",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
|
||||||
"start": 0,
|
|
||||||
"type": "ImportItem"
|
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "ImportStatement",
|
"type": "ImportStatement",
|
||||||
@ -119,23 +101,14 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"filename": "91251a404-bolt.kcl"
|
"filename": "91251a404-bolt.kcl"
|
||||||
},
|
},
|
||||||
"selector": {
|
"selector": {
|
||||||
"type": "List",
|
"type": "None",
|
||||||
"items": [
|
"alias": {
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": {
|
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "bolt",
|
"name": "bolt",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
|
||||||
"start": 0,
|
|
||||||
"type": "ImportItem"
|
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "ImportStatement",
|
"type": "ImportStatement",
|
||||||
@ -149,23 +122,14 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"filename": "95479a127-hex-nut.kcl"
|
"filename": "95479a127-hex-nut.kcl"
|
||||||
},
|
},
|
||||||
"selector": {
|
"selector": {
|
||||||
"type": "List",
|
"type": "None",
|
||||||
"items": [
|
"alias": {
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": {
|
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "hexNut",
|
"name": "hexNut",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
|
||||||
"start": 0,
|
|
||||||
"type": "ImportItem"
|
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "ImportStatement",
|
"type": "ImportStatement",
|
||||||
@ -179,91 +143,24 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"filename": "1120t74-pipe.kcl"
|
"filename": "1120t74-pipe.kcl"
|
||||||
},
|
},
|
||||||
"selector": {
|
"selector": {
|
||||||
"type": "List",
|
"type": "None",
|
||||||
"items": [
|
"alias": {
|
||||||
{
|
|
||||||
"alias": null,
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": {
|
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "pipe",
|
"name": "pipe",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
|
||||||
"start": 0,
|
|
||||||
"type": "ImportItem"
|
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "ImportStatement",
|
"type": "ImportStatement",
|
||||||
"type": "ImportStatement"
|
"type": "ImportStatement"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"expression": {
|
|
||||||
"callee": {
|
|
||||||
"abs_path": false,
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": {
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": "flange",
|
|
||||||
"start": 0,
|
|
||||||
"type": "Identifier"
|
|
||||||
},
|
|
||||||
"path": [],
|
|
||||||
"start": 0,
|
|
||||||
"type": "Name"
|
|
||||||
},
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"start": 0,
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"unlabeled": null
|
|
||||||
},
|
|
||||||
"preComments": [
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"// Place flanges"
|
|
||||||
],
|
|
||||||
"start": 0,
|
|
||||||
"type": "ExpressionStatement",
|
|
||||||
"type": "ExpressionStatement"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"expression": {
|
"expression": {
|
||||||
"body": [
|
"body": [
|
||||||
{
|
|
||||||
"callee": {
|
|
||||||
"abs_path": false,
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": {
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": "flange",
|
|
||||||
"start": 0,
|
|
||||||
"type": "Identifier"
|
|
||||||
},
|
|
||||||
"path": [],
|
|
||||||
"start": 0,
|
|
||||||
"type": "Name"
|
|
||||||
},
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"start": 0,
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"unlabeled": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"arguments": [
|
"arguments": [
|
||||||
{
|
{
|
||||||
@ -271,62 +168,7 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"label": {
|
"label": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"name": "axis",
|
"name": "roll",
|
||||||
"start": 0,
|
|
||||||
"type": "Identifier"
|
|
||||||
},
|
|
||||||
"arg": {
|
|
||||||
"commentStart": 0,
|
|
||||||
"elements": [
|
|
||||||
{
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"raw": "0",
|
|
||||||
"start": 0,
|
|
||||||
"type": "Literal",
|
|
||||||
"type": "Literal",
|
|
||||||
"value": {
|
|
||||||
"value": 0.0,
|
|
||||||
"suffix": "None"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"raw": "1",
|
|
||||||
"start": 0,
|
|
||||||
"type": "Literal",
|
|
||||||
"type": "Literal",
|
|
||||||
"value": {
|
|
||||||
"value": 1.0,
|
|
||||||
"suffix": "None"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"raw": "0",
|
|
||||||
"start": 0,
|
|
||||||
"type": "Literal",
|
|
||||||
"type": "Literal",
|
|
||||||
"value": {
|
|
||||||
"value": 0.0,
|
|
||||||
"suffix": "None"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"end": 0,
|
|
||||||
"start": 0,
|
|
||||||
"type": "ArrayExpression",
|
|
||||||
"type": "ArrayExpression"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "LabeledArg",
|
|
||||||
"label": {
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": "angle",
|
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Identifier"
|
"type": "Identifier"
|
||||||
},
|
},
|
||||||
@ -342,6 +184,50 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"suffix": "None"
|
"suffix": "None"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "pitch",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "0",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 0.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "LabeledArg",
|
||||||
|
"label": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "yaw",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"arg": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"raw": "0",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Literal",
|
||||||
|
"type": "Literal",
|
||||||
|
"value": {
|
||||||
|
"value": 0.0,
|
||||||
|
"suffix": "None"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"callee": {
|
"callee": {
|
||||||
@ -364,7 +250,44 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "CallExpressionKw",
|
"type": "CallExpressionKw",
|
||||||
"type": "CallExpressionKw",
|
"type": "CallExpressionKw",
|
||||||
"unlabeled": null
|
"unlabeled": {
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "clone",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"start": 0,
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "flange",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
|
"type": "Name"
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"arguments": [
|
"arguments": [
|
||||||
@ -510,7 +433,7 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"end": 0,
|
"end": 0,
|
||||||
"nonCodeMeta": {
|
"nonCodeMeta": {
|
||||||
"nonCodeNodes": {
|
"nonCodeNodes": {
|
||||||
"2": [
|
"1": [
|
||||||
{
|
{
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
@ -530,6 +453,11 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"type": "PipeExpression",
|
"type": "PipeExpression",
|
||||||
"type": "PipeExpression"
|
"type": "PipeExpression"
|
||||||
},
|
},
|
||||||
|
"preComments": [
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"// Place flange clone"
|
||||||
|
],
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "ExpressionStatement",
|
"type": "ExpressionStatement",
|
||||||
"type": "ExpressionStatement"
|
"type": "ExpressionStatement"
|
||||||
@ -717,7 +645,6 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"expression": {
|
"expression": {
|
||||||
"body": [
|
"body": [
|
||||||
{
|
{
|
||||||
"callee": {
|
|
||||||
"abs_path": false,
|
"abs_path": false,
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
@ -730,15 +657,9 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
},
|
},
|
||||||
"path": [],
|
"path": [],
|
||||||
"start": 0,
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
"type": "Name"
|
"type": "Name"
|
||||||
},
|
},
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"start": 0,
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"unlabeled": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"arguments": [
|
"arguments": [
|
||||||
{
|
{
|
||||||
@ -1351,7 +1272,6 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"expression": {
|
"expression": {
|
||||||
"body": [
|
"body": [
|
||||||
{
|
{
|
||||||
"callee": {
|
|
||||||
"abs_path": false,
|
"abs_path": false,
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
@ -1364,15 +1284,9 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
},
|
},
|
||||||
"path": [],
|
"path": [],
|
||||||
"start": 0,
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
"type": "Name"
|
"type": "Name"
|
||||||
},
|
},
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"start": 0,
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"unlabeled": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"arguments": [
|
"arguments": [
|
||||||
{
|
{
|
||||||
@ -1846,7 +1760,6 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"expression": {
|
"expression": {
|
||||||
"body": [
|
"body": [
|
||||||
{
|
{
|
||||||
"callee": {
|
|
||||||
"abs_path": false,
|
"abs_path": false,
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
@ -1859,15 +1772,9 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
},
|
},
|
||||||
"path": [],
|
"path": [],
|
||||||
"start": 0,
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
"type": "Name"
|
"type": "Name"
|
||||||
},
|
},
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"start": 0,
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"unlabeled": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"arguments": [
|
"arguments": [
|
||||||
{
|
{
|
||||||
@ -2349,29 +2256,6 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"end": 0,
|
"end": 0,
|
||||||
"expression": {
|
"expression": {
|
||||||
"body": [
|
"body": [
|
||||||
{
|
|
||||||
"callee": {
|
|
||||||
"abs_path": false,
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": {
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": "pipe",
|
|
||||||
"start": 0,
|
|
||||||
"type": "Identifier"
|
|
||||||
},
|
|
||||||
"path": [],
|
|
||||||
"start": 0,
|
|
||||||
"type": "Name"
|
|
||||||
},
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"start": 0,
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"unlabeled": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"arguments": [
|
"arguments": [
|
||||||
{
|
{
|
||||||
@ -2470,11 +2354,20 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"type": "CallExpressionKw",
|
"type": "CallExpressionKw",
|
||||||
"type": "CallExpressionKw",
|
"type": "CallExpressionKw",
|
||||||
"unlabeled": {
|
"unlabeled": {
|
||||||
|
"abs_path": false,
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "pipe",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "PipeSubstitution",
|
"type": "Identifier"
|
||||||
"type": "PipeSubstitution"
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
|
"type": "Name"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -2657,29 +2550,6 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"end": 0,
|
"end": 0,
|
||||||
"expression": {
|
"expression": {
|
||||||
"body": [
|
"body": [
|
||||||
{
|
|
||||||
"callee": {
|
|
||||||
"abs_path": false,
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": {
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"name": "pipe",
|
|
||||||
"start": 0,
|
|
||||||
"type": "Identifier"
|
|
||||||
},
|
|
||||||
"path": [],
|
|
||||||
"start": 0,
|
|
||||||
"type": "Name"
|
|
||||||
},
|
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"start": 0,
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"type": "CallExpressionKw",
|
|
||||||
"unlabeled": null
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"arguments": [
|
"arguments": [
|
||||||
{
|
{
|
||||||
@ -2694,12 +2564,12 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"arg": {
|
"arg": {
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"raw": "90",
|
"raw": "180",
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "Literal",
|
"type": "Literal",
|
||||||
"type": "Literal",
|
"type": "Literal",
|
||||||
"value": {
|
"value": {
|
||||||
"value": 90.0,
|
"value": 180.0,
|
||||||
"suffix": "None"
|
"suffix": "None"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2770,11 +2640,42 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"type": "CallExpressionKw",
|
"type": "CallExpressionKw",
|
||||||
"type": "CallExpressionKw",
|
"type": "CallExpressionKw",
|
||||||
"unlabeled": {
|
"unlabeled": {
|
||||||
|
"callee": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "clone",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name"
|
||||||
|
},
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "PipeSubstitution",
|
"type": "CallExpressionKw",
|
||||||
"type": "PipeSubstitution"
|
"type": "CallExpressionKw",
|
||||||
|
"unlabeled": {
|
||||||
|
"abs_path": false,
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": {
|
||||||
|
"commentStart": 0,
|
||||||
|
"end": 0,
|
||||||
|
"name": "pipe",
|
||||||
|
"start": 0,
|
||||||
|
"type": "Identifier"
|
||||||
|
},
|
||||||
|
"path": [],
|
||||||
|
"start": 0,
|
||||||
|
"type": "Name",
|
||||||
|
"type": "Name"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -3009,13 +2910,7 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
"start": 0,
|
"start": 0,
|
||||||
"type": "CallExpressionKw",
|
"type": "CallExpressionKw",
|
||||||
"type": "CallExpressionKw",
|
"type": "CallExpressionKw",
|
||||||
"unlabeled": {
|
"unlabeled": null
|
||||||
"commentStart": 0,
|
|
||||||
"end": 0,
|
|
||||||
"start": 0,
|
|
||||||
"type": "PipeSubstitution",
|
|
||||||
"type": "PipeSubstitution"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
@ -3111,7 +3006,7 @@ description: Result of parsing pipe-flange-assembly.kcl
|
|||||||
],
|
],
|
||||||
"nonCodeMeta": {
|
"nonCodeMeta": {
|
||||||
"nonCodeNodes": {
|
"nonCodeNodes": {
|
||||||
"13": [
|
"9": [
|
||||||
{
|
{
|
||||||
"commentStart": 0,
|
"commentStart": 0,
|
||||||
"end": 0,
|
"end": 0,
|
||||||
|
@ -3,13 +3,29 @@ source: kcl-lib/src/simulation_tests.rs
|
|||||||
description: Variables in memory after executing pipe-flange-assembly.kcl
|
description: Variables in memory after executing pipe-flange-assembly.kcl
|
||||||
---
|
---
|
||||||
{
|
{
|
||||||
|
"__mod_bolt": {
|
||||||
|
"type": "Module",
|
||||||
|
"value": 5
|
||||||
|
},
|
||||||
|
"__mod_flange": {
|
||||||
|
"type": "Module",
|
||||||
|
"value": 3
|
||||||
|
},
|
||||||
"__mod_gasket": {
|
"__mod_gasket": {
|
||||||
"type": "Module",
|
"type": "Module",
|
||||||
"value": 2
|
"value": 2
|
||||||
},
|
},
|
||||||
"bolt": {
|
"__mod_hexNut": {
|
||||||
"type": "Function",
|
"type": "Module",
|
||||||
"value": null
|
"value": 6
|
||||||
|
},
|
||||||
|
"__mod_pipe": {
|
||||||
|
"type": "Module",
|
||||||
|
"value": 7
|
||||||
|
},
|
||||||
|
"__mod_washer": {
|
||||||
|
"type": "Module",
|
||||||
|
"value": 4
|
||||||
},
|
},
|
||||||
"boltDiameter": {
|
"boltDiameter": {
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
@ -107,10 +123,6 @@ description: Variables in memory after executing pipe-flange-assembly.kcl
|
|||||||
"type": "TagIdentifier",
|
"type": "TagIdentifier",
|
||||||
"value": "filletEdge"
|
"value": "filletEdge"
|
||||||
},
|
},
|
||||||
"flange": {
|
|
||||||
"type": "Function",
|
|
||||||
"value": null
|
|
||||||
},
|
|
||||||
"flangeBackDiameter": {
|
"flangeBackDiameter": {
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
"value": 3.62,
|
"value": 3.62,
|
||||||
@ -241,10 +253,6 @@ description: Variables in memory after executing pipe-flange-assembly.kcl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hexNut": {
|
|
||||||
"type": "Function",
|
|
||||||
"value": null
|
|
||||||
},
|
|
||||||
"hexNutDiameter": {
|
"hexNutDiameter": {
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
"value": 0.625,
|
"value": 0.625,
|
||||||
@ -323,10 +331,6 @@ description: Variables in memory after executing pipe-flange-assembly.kcl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pipe": {
|
|
||||||
"type": "Function",
|
|
||||||
"value": null
|
|
||||||
},
|
|
||||||
"pipeDiameter": {
|
"pipeDiameter": {
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
"value": 2.44,
|
"value": 2.44,
|
||||||
@ -379,10 +383,6 @@ description: Variables in memory after executing pipe-flange-assembly.kcl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"washer": {
|
|
||||||
"type": "Function",
|
|
||||||
"value": null
|
|
||||||
},
|
|
||||||
"washerInnerDia": {
|
"washerInnerDia": {
|
||||||
"type": "Number",
|
"type": "Number",
|
||||||
"value": 0.64,
|
"value": 0.64,
|
||||||
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 75 KiB |
@ -112,8 +112,8 @@ flowchart LR
|
|||||||
8 --- 20
|
8 --- 20
|
||||||
8 ---- 25
|
8 ---- 25
|
||||||
12 <--x 32
|
12 <--x 32
|
||||||
12 --- 33
|
12 <--x 33
|
||||||
12 <--x 34
|
12 --- 34
|
||||||
13 --- 31
|
13 --- 31
|
||||||
13 x--> 35
|
13 x--> 35
|
||||||
13 --- 39
|
13 --- 39
|
||||||
|
@ -889,7 +889,7 @@ flowchart LR
|
|||||||
99 --- 265
|
99 --- 265
|
||||||
99 --- 314
|
99 --- 314
|
||||||
106 --- 181
|
106 --- 181
|
||||||
106 x--> 213
|
106 x--> 212
|
||||||
106 --- 260
|
106 --- 260
|
||||||
106 --- 309
|
106 --- 309
|
||||||
126 --- 194
|
126 --- 194
|
||||||
@ -1227,7 +1227,7 @@ flowchart LR
|
|||||||
251 <--x 209
|
251 <--x 209
|
||||||
252 <--x 209
|
252 <--x 209
|
||||||
253 <--x 209
|
253 <--x 209
|
||||||
260 <--x 212
|
260 <--x 213
|
||||||
261 <--x 214
|
261 <--x 214
|
||||||
262 <--x 214
|
262 <--x 214
|
||||||
263 <--x 214
|
263 <--x 214
|
||||||
|
@ -114,6 +114,9 @@ export function App() {
|
|||||||
// by the Projects view.
|
// by the Projects view.
|
||||||
billingActor.send({ type: BillingTransition.Update, apiToken: authToken })
|
billingActor.send({ type: BillingTransition.Update, apiToken: authToken })
|
||||||
|
|
||||||
|
// Tell engineStream to wait for dependencies to start streaming.
|
||||||
|
engineStreamActor.send({ type: EngineStreamTransition.WaitForDependencies })
|
||||||
|
|
||||||
// When leaving the modeling scene, cut the engine stream.
|
// When leaving the modeling scene, cut the engine stream.
|
||||||
return () => {
|
return () => {
|
||||||
// When leaving the modeling scene, cut the engine stream.
|
// When leaving the modeling scene, cut the engine stream.
|
||||||
|
@ -1107,11 +1107,7 @@ export class SceneEntities {
|
|||||||
(lastSegment.type === 'TangentialArc' && segmentName !== 'line') ||
|
(lastSegment.type === 'TangentialArc' && segmentName !== 'line') ||
|
||||||
segmentName === 'tangentialArc'
|
segmentName === 'tangentialArc'
|
||||||
) {
|
) {
|
||||||
if (snappedPoint[0] === 0 || snappedPoint[1] === 0) {
|
|
||||||
resolvedFunctionName = 'tangentialArcTo'
|
|
||||||
} else {
|
|
||||||
resolvedFunctionName = 'tangentialArc'
|
resolvedFunctionName = 'tangentialArc'
|
||||||
}
|
|
||||||
} else if (snappedToTangent) {
|
} else if (snappedToTangent) {
|
||||||
// Generate tag for previous arc segment and use it for the angle of angledLine:
|
// Generate tag for previous arc segment and use it for the angle of angledLine:
|
||||||
// |> tangentialArc(endAbsolute = [5, -10], tag = $arc001)
|
// |> tangentialArc(endAbsolute = [5, -10], tag = $arc001)
|
||||||
@ -3588,7 +3584,8 @@ export class SceneEntities {
|
|||||||
})
|
})
|
||||||
|
|
||||||
if (!resp) {
|
if (!resp) {
|
||||||
return Promise.reject('no response')
|
console.warn('No response')
|
||||||
|
return {} as Models['GetSketchModePlane_type']
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isArray(resp)) {
|
if (isArray(resp)) {
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { isPlaywright } from '@src/lib/isPlaywright'
|
|
||||||
import { useAppState } from '@src/AppState'
|
import { useAppState } from '@src/AppState'
|
||||||
import { ClientSideScene } from '@src/clientSideScene/ClientSideSceneComp'
|
import { ClientSideScene } from '@src/clientSideScene/ClientSideSceneComp'
|
||||||
import { ViewControlContextMenu } from '@src/components/ViewControlMenu'
|
import { ViewControlContextMenu } from '@src/components/ViewControlMenu'
|
||||||
@ -52,8 +51,10 @@ export const EngineStream = (props: {
|
|||||||
const last = useRef<number>(Date.now())
|
const last = useRef<number>(Date.now())
|
||||||
|
|
||||||
const [firstPlay, setFirstPlay] = useState(true)
|
const [firstPlay, setFirstPlay] = useState(true)
|
||||||
const [isRestartRequestStarting, setIsRestartRequestStarting] =
|
const [goRestart, setGoRestart] = useState(false)
|
||||||
useState(false)
|
const [timeoutId, setTimeoutId] = useState<
|
||||||
|
ReturnType<typeof setTimeout> | undefined
|
||||||
|
>(undefined)
|
||||||
const [attemptTimes, setAttemptTimes] = useState<[number, number]>([
|
const [attemptTimes, setAttemptTimes] = useState<[number, number]>([
|
||||||
0,
|
0,
|
||||||
TIME_1_SECOND,
|
TIME_1_SECOND,
|
||||||
@ -85,18 +86,21 @@ export const EngineStream = (props: {
|
|||||||
const streamIdleMode = settings.app.streamIdleMode.current
|
const streamIdleMode = settings.app.streamIdleMode.current
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Will cause a useEffect loop if not checked for.
|
||||||
|
if (engineStreamState.context.videoRef.current !== null) return
|
||||||
engineStreamActor.send({
|
engineStreamActor.send({
|
||||||
type: EngineStreamTransition.SetVideoRef,
|
type: EngineStreamTransition.SetVideoRef,
|
||||||
videoRef: { current: videoRef.current },
|
videoRef: { current: videoRef.current },
|
||||||
})
|
})
|
||||||
}, [videoRef.current])
|
}, [videoRef.current, engineStreamState])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (engineStreamState.context.canvasRef.current !== null) return
|
||||||
engineStreamActor.send({
|
engineStreamActor.send({
|
||||||
type: EngineStreamTransition.SetCanvasRef,
|
type: EngineStreamTransition.SetCanvasRef,
|
||||||
canvasRef: { current: canvasRef.current },
|
canvasRef: { current: canvasRef.current },
|
||||||
})
|
})
|
||||||
}, [canvasRef.current])
|
}, [canvasRef.current, engineStreamState])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
engineStreamActor.send({
|
engineStreamActor.send({
|
||||||
@ -131,24 +135,6 @@ export const EngineStream = (props: {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// Only try to start the stream if we're stopped or think we're done
|
|
||||||
// waiting for dependencies.
|
|
||||||
if (
|
|
||||||
!(
|
|
||||||
engineStreamState.value === EngineStreamState.WaitingForDependencies ||
|
|
||||||
engineStreamState.value === EngineStreamState.Stopped
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
// Don't bother trying to connect if the auth token is empty.
|
|
||||||
// We have the checks in the machine but this can cause a hot loop.
|
|
||||||
if (!engineStreamState.context.authToken) return
|
|
||||||
|
|
||||||
startOrReconfigureEngine()
|
|
||||||
}, [engineStreamState, setAppState])
|
|
||||||
|
|
||||||
// I would inline this but it needs to be a function for removeEventListener.
|
// I would inline this but it needs to be a function for removeEventListener.
|
||||||
const play = () => {
|
const play = () => {
|
||||||
engineStreamActor.send({
|
engineStreamActor.send({
|
||||||
@ -174,12 +160,13 @@ export const EngineStream = (props: {
|
|||||||
console.log('scene is ready, execute kcl')
|
console.log('scene is ready, execute kcl')
|
||||||
const kmp = kclManager.executeCode().catch(trap)
|
const kmp = kclManager.executeCode().catch(trap)
|
||||||
|
|
||||||
if (!firstPlay) return
|
|
||||||
|
|
||||||
setFirstPlay(false)
|
|
||||||
// Reset the restart timeouts
|
// Reset the restart timeouts
|
||||||
setAttemptTimes([0, TIME_1_SECOND])
|
setAttemptTimes([0, TIME_1_SECOND])
|
||||||
|
|
||||||
|
console.log(firstPlay)
|
||||||
|
if (!firstPlay) return
|
||||||
|
|
||||||
|
setFirstPlay(false)
|
||||||
console.log('firstPlay true, zoom to fit')
|
console.log('firstPlay true, zoom to fit')
|
||||||
kmp
|
kmp
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
@ -211,51 +198,76 @@ export const EngineStream = (props: {
|
|||||||
// We do a back-off restart, using a fibonacci sequence, since it
|
// We do a back-off restart, using a fibonacci sequence, since it
|
||||||
// has a nice retry time curve (somewhat quick then exponential)
|
// has a nice retry time curve (somewhat quick then exponential)
|
||||||
const attemptRestartIfNecessary = () => {
|
const attemptRestartIfNecessary = () => {
|
||||||
if (isRestartRequestStarting) return
|
// Timeout already set.
|
||||||
setIsRestartRequestStarting(true)
|
if (timeoutId) return
|
||||||
|
|
||||||
|
setTimeoutId(
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
engineStreamState.context.videoRef.current?.pause()
|
engineStreamState.context.videoRef.current?.pause()
|
||||||
engineCommandManager.tearDown()
|
engineCommandManager.tearDown()
|
||||||
startOrReconfigureEngine()
|
startOrReconfigureEngine()
|
||||||
setFirstPlay(false)
|
setFirstPlay(true)
|
||||||
setIsRestartRequestStarting(false)
|
|
||||||
|
setTimeoutId(undefined)
|
||||||
|
setGoRestart(false)
|
||||||
}, attemptTimes[0] + attemptTimes[1])
|
}, attemptTimes[0] + attemptTimes[1])
|
||||||
|
)
|
||||||
setAttemptTimes([attemptTimes[1], attemptTimes[0] + attemptTimes[1]])
|
setAttemptTimes([attemptTimes[1], attemptTimes[0] + attemptTimes[1]])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Poll that we're connected. If not, send a reset signal.
|
const onOffline = () => {
|
||||||
// Do not restart if we're in idle mode.
|
if (
|
||||||
const connectionCheckIntervalId = setInterval(() => {
|
!(
|
||||||
// SKIP DURING TESTS BECAUSE IT WILL MESS WITH REUSING THE
|
EngineConnectionStateType.Disconnected ===
|
||||||
// ELECTRON INSTANCE.
|
engineCommandManager.engineConnection?.state.type ||
|
||||||
if (isPlaywright()) {
|
EngineConnectionStateType.Disconnecting ===
|
||||||
|
engineCommandManager.engineConnection?.state.type
|
||||||
|
)
|
||||||
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
engineStreamActor.send({ type: EngineStreamTransition.Stop })
|
||||||
// Don't try try to restart if we're already connected!
|
|
||||||
const hasEngineConnectionInst = engineCommandManager.engineConnection
|
|
||||||
const isDisconnected =
|
|
||||||
engineCommandManager.engineConnection?.state.type ===
|
|
||||||
EngineConnectionStateType.Disconnected
|
|
||||||
const inIdleMode = engineStreamState.value === EngineStreamState.Paused
|
|
||||||
if ((hasEngineConnectionInst && !isDisconnected) || inIdleMode) return
|
|
||||||
|
|
||||||
attemptRestartIfNecessary()
|
attemptRestartIfNecessary()
|
||||||
}, TIME_1_SECOND)
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
!goRestart &&
|
||||||
|
engineStreamState.value === EngineStreamState.WaitingForDependencies
|
||||||
|
) {
|
||||||
|
setGoRestart(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (goRestart && !timeoutId) {
|
||||||
|
attemptRestartIfNecessary()
|
||||||
|
}
|
||||||
|
|
||||||
engineCommandManager.addEventListener(
|
engineCommandManager.addEventListener(
|
||||||
EngineCommandManagerEvents.EngineRestartRequest,
|
EngineCommandManagerEvents.EngineRestartRequest,
|
||||||
attemptRestartIfNecessary
|
attemptRestartIfNecessary
|
||||||
)
|
)
|
||||||
return () => {
|
|
||||||
clearInterval(connectionCheckIntervalId)
|
|
||||||
|
|
||||||
|
engineCommandManager.addEventListener(
|
||||||
|
EngineCommandManagerEvents.Offline,
|
||||||
|
onOffline
|
||||||
|
)
|
||||||
|
|
||||||
|
return () => {
|
||||||
engineCommandManager.removeEventListener(
|
engineCommandManager.removeEventListener(
|
||||||
EngineCommandManagerEvents.EngineRestartRequest,
|
EngineCommandManagerEvents.EngineRestartRequest,
|
||||||
attemptRestartIfNecessary
|
attemptRestartIfNecessary
|
||||||
)
|
)
|
||||||
|
engineCommandManager.removeEventListener(
|
||||||
|
EngineCommandManagerEvents.Offline,
|
||||||
|
onOffline
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, [engineStreamState, attemptTimes, isRestartRequestStarting])
|
}, [
|
||||||
|
engineStreamState,
|
||||||
|
attemptTimes,
|
||||||
|
goRestart,
|
||||||
|
timeoutId,
|
||||||
|
engineCommandManager.engineConnection?.state.type,
|
||||||
|
])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// If engineStreamMachine is already reconfiguring, bail.
|
// If engineStreamMachine is already reconfiguring, bail.
|
||||||
@ -269,7 +281,7 @@ export const EngineStream = (props: {
|
|||||||
const canvas = engineStreamState.context.canvasRef?.current
|
const canvas = engineStreamState.context.canvasRef?.current
|
||||||
if (!canvas) return
|
if (!canvas) return
|
||||||
|
|
||||||
new ResizeObserver(() => {
|
const observer = new ResizeObserver(() => {
|
||||||
// Prevents:
|
// Prevents:
|
||||||
// `Uncaught ResizeObserver loop completed with undelivered notifications`
|
// `Uncaught ResizeObserver loop completed with undelivered notifications`
|
||||||
window.requestAnimationFrame(() => {
|
window.requestAnimationFrame(() => {
|
||||||
@ -280,13 +292,19 @@ export const EngineStream = (props: {
|
|||||||
if (
|
if (
|
||||||
(Math.abs(video.width - window.innerWidth) > 4 ||
|
(Math.abs(video.width - window.innerWidth) > 4 ||
|
||||||
Math.abs(video.height - window.innerHeight) > 4) &&
|
Math.abs(video.height - window.innerHeight) > 4) &&
|
||||||
!engineStreamState.matches(EngineStreamState.WaitingToPlay)
|
engineStreamState.matches(EngineStreamState.Playing)
|
||||||
) {
|
) {
|
||||||
timeoutStart.current = Date.now()
|
timeoutStart.current = Date.now()
|
||||||
startOrReconfigureEngine()
|
startOrReconfigureEngine()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}).observe(document.body)
|
})
|
||||||
|
|
||||||
|
observer.observe(document.body)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
observer.disconnect()
|
||||||
|
}
|
||||||
}, [engineStreamState.value])
|
}, [engineStreamState.value])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -345,8 +363,21 @@ export const EngineStream = (props: {
|
|||||||
timeoutStart.current = null
|
timeoutStart.current = null
|
||||||
} else if (timeoutStart.current) {
|
} else if (timeoutStart.current) {
|
||||||
const elapsed = Date.now() - timeoutStart.current
|
const elapsed = Date.now() - timeoutStart.current
|
||||||
if (elapsed >= IDLE_TIME_MS) {
|
// Don't pause if we're already disconnected.
|
||||||
|
if (
|
||||||
|
// It's unnecessary to once again setup an event listener for
|
||||||
|
// offline/online to capture this state, when this state already
|
||||||
|
// exists on the window.navigator object. In hindsight it makes
|
||||||
|
// me (lee) regret we set React state variables such as
|
||||||
|
// isInternetConnected in other files when we could check this
|
||||||
|
// object instead.
|
||||||
|
engineCommandManager.engineConnection?.state.type ===
|
||||||
|
EngineConnectionStateType.ConnectionEstablished &&
|
||||||
|
elapsed >= IDLE_TIME_MS &&
|
||||||
|
engineStreamState.value === EngineStreamState.Playing
|
||||||
|
) {
|
||||||
timeoutStart.current = null
|
timeoutStart.current = null
|
||||||
|
console.log('PAUSING')
|
||||||
engineStreamActor.send({ type: EngineStreamTransition.Pause })
|
engineStreamActor.send({ type: EngineStreamTransition.Pause })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,7 +388,7 @@ export const EngineStream = (props: {
|
|||||||
return () => {
|
return () => {
|
||||||
window.cancelAnimationFrame(frameId)
|
window.cancelAnimationFrame(frameId)
|
||||||
}
|
}
|
||||||
}, [modelingMachineState])
|
}, [modelingMachineState, engineStreamState.value])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!streamIdleMode) return
|
if (!streamIdleMode) return
|
||||||
@ -370,9 +401,18 @@ export const EngineStream = (props: {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (engineStreamState.value === EngineStreamState.Paused) {
|
engineStreamActor.send({
|
||||||
startOrReconfigureEngine()
|
type: EngineStreamTransition.Resume,
|
||||||
}
|
modelingMachineActorSend,
|
||||||
|
settings: settingsEngine,
|
||||||
|
setAppState,
|
||||||
|
onMediaStream(mediaStream: MediaStream) {
|
||||||
|
engineStreamActor.send({
|
||||||
|
type: EngineStreamTransition.SetMediaStream,
|
||||||
|
mediaStream,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
timeoutStart.current = Date.now()
|
timeoutStart.current = Date.now()
|
||||||
}
|
}
|
||||||
@ -471,7 +511,11 @@ export const EngineStream = (props: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sendSelectEventToEngine(e)
|
sendSelectEventToEngine(e)
|
||||||
.then(({ entity_id }) => {
|
.then((result) => {
|
||||||
|
if (!result) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const { entity_id } = result
|
||||||
if (!entity_id) {
|
if (!entity_id) {
|
||||||
// No entity selected. This is benign
|
// No entity selected. This is benign
|
||||||
return
|
return
|
||||||
|
@ -21,7 +21,6 @@ import {
|
|||||||
filterOperations,
|
filterOperations,
|
||||||
getOperationIcon,
|
getOperationIcon,
|
||||||
getOperationLabel,
|
getOperationLabel,
|
||||||
getOperationVariableName,
|
|
||||||
stdLibMap,
|
stdLibMap,
|
||||||
} from '@src/lib/operations'
|
} from '@src/lib/operations'
|
||||||
import { editorManager, kclManager, rustContext } from '@src/lib/singletons'
|
import { editorManager, kclManager, rustContext } from '@src/lib/singletons'
|
||||||
@ -237,7 +236,6 @@ const VisibilityToggle = (props: VisibilityToggleProps) => {
|
|||||||
const OperationItemWrapper = ({
|
const OperationItemWrapper = ({
|
||||||
icon,
|
icon,
|
||||||
name,
|
name,
|
||||||
variableName,
|
|
||||||
visibilityToggle,
|
visibilityToggle,
|
||||||
menuItems,
|
menuItems,
|
||||||
errors,
|
errors,
|
||||||
@ -248,7 +246,6 @@ const OperationItemWrapper = ({
|
|||||||
}: React.HTMLAttributes<HTMLButtonElement> & {
|
}: React.HTMLAttributes<HTMLButtonElement> & {
|
||||||
icon: CustomIconName
|
icon: CustomIconName
|
||||||
name: string
|
name: string
|
||||||
variableName?: string
|
|
||||||
visibilityToggle?: VisibilityToggleProps
|
visibilityToggle?: VisibilityToggleProps
|
||||||
customSuffix?: JSX.Element
|
customSuffix?: JSX.Element
|
||||||
menuItems?: ComponentProps<typeof ContextMenu>['items']
|
menuItems?: ComponentProps<typeof ContextMenu>['items']
|
||||||
@ -267,15 +264,8 @@ const OperationItemWrapper = ({
|
|||||||
className={`reset flex-1 flex items-center gap-2 text-left text-base ${selectable ? 'border-transparent dark:border-transparent' : 'border-none cursor-default'} ${className}`}
|
className={`reset flex-1 flex items-center gap-2 text-left text-base ${selectable ? 'border-transparent dark:border-transparent' : 'border-none cursor-default'} ${className}`}
|
||||||
>
|
>
|
||||||
<CustomIcon name={icon} className="w-5 h-5 block" />
|
<CustomIcon name={icon} className="w-5 h-5 block" />
|
||||||
<div className="flex items-baseline align-baseline">
|
<div className="flex items-baseline">
|
||||||
<div className="mr-2">
|
<div className="mr-2">{name}</div>
|
||||||
{name}
|
|
||||||
{variableName && (
|
|
||||||
<span className="ml-2 opacity-50 text-[11px] font-semibold">
|
|
||||||
{variableName}
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{customSuffix && customSuffix}
|
{customSuffix && customSuffix}
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
@ -300,11 +290,6 @@ const OperationItem = (props: {
|
|||||||
}) => {
|
}) => {
|
||||||
const kclContext = useKclContext()
|
const kclContext = useKclContext()
|
||||||
const name = getOperationLabel(props.item)
|
const name = getOperationLabel(props.item)
|
||||||
|
|
||||||
const variableName = useMemo(() => {
|
|
||||||
return getOperationVariableName(props.item, kclContext.ast)
|
|
||||||
}, [props.item, kclContext.ast])
|
|
||||||
|
|
||||||
const errors = useMemo(() => {
|
const errors = useMemo(() => {
|
||||||
return kclContext.diagnostics.filter(
|
return kclContext.diagnostics.filter(
|
||||||
(diag) =>
|
(diag) =>
|
||||||
@ -514,7 +499,6 @@ const OperationItem = (props: {
|
|||||||
<OperationItemWrapper
|
<OperationItemWrapper
|
||||||
icon={getOperationIcon(props.item)}
|
icon={getOperationIcon(props.item)}
|
||||||
name={name}
|
name={name}
|
||||||
variableName={variableName}
|
|
||||||
menuItems={menuItems}
|
menuItems={menuItems}
|
||||||
onClick={selectOperation}
|
onClick={selectOperation}
|
||||||
onDoubleClick={enterEditFlow}
|
onDoubleClick={enterEditFlow}
|
||||||
|
@ -78,18 +78,19 @@ export function useNetworkStatus() {
|
|||||||
}, [hasIssues, internetConnected, ping])
|
}, [hasIssues, internetConnected, ping])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const onlineCallback = () => {
|
|
||||||
setInternetConnected(true)
|
|
||||||
}
|
|
||||||
const offlineCallback = () => {
|
const offlineCallback = () => {
|
||||||
setInternetConnected(false)
|
setInternetConnected(false)
|
||||||
setSteps(structuredClone(initialConnectingTypeGroupState))
|
setSteps(structuredClone(initialConnectingTypeGroupState))
|
||||||
}
|
}
|
||||||
window.addEventListener('online', onlineCallback)
|
engineCommandManager.addEventListener(
|
||||||
window.addEventListener('offline', offlineCallback)
|
EngineCommandManagerEvents.Offline,
|
||||||
|
offlineCallback
|
||||||
|
)
|
||||||
return () => {
|
return () => {
|
||||||
window.removeEventListener('online', onlineCallback)
|
engineCommandManager.removeEventListener(
|
||||||
window.removeEventListener('offline', offlineCallback)
|
EngineCommandManagerEvents.Offline,
|
||||||
|
offlineCallback
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
@ -139,6 +140,8 @@ export function useNetworkStatus() {
|
|||||||
if (
|
if (
|
||||||
engineConnectionState.type === EngineConnectionStateType.Connecting
|
engineConnectionState.type === EngineConnectionStateType.Connecting
|
||||||
) {
|
) {
|
||||||
|
setInternetConnected(true)
|
||||||
|
|
||||||
const groups = Object.values(nextSteps)
|
const groups = Object.values(nextSteps)
|
||||||
for (let group of groups) {
|
for (let group of groups) {
|
||||||
for (let step of group) {
|
for (let step of group) {
|
||||||
@ -168,6 +171,10 @@ export function useNetworkStatus() {
|
|||||||
|
|
||||||
if (engineConnectionState.value.type === DisconnectingType.Error) {
|
if (engineConnectionState.value.type === DisconnectingType.Error) {
|
||||||
setError(engineConnectionState.value.value)
|
setError(engineConnectionState.value.value)
|
||||||
|
} else if (
|
||||||
|
engineConnectionState.value.type === DisconnectingType.Quit
|
||||||
|
) {
|
||||||
|
return structuredClone(initialConnectingTypeGroupState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ export type ToolTip =
|
|||||||
| 'yLineTo'
|
| 'yLineTo'
|
||||||
| 'angledLineThatIntersects'
|
| 'angledLineThatIntersects'
|
||||||
| 'tangentialArc'
|
| 'tangentialArc'
|
||||||
| 'tangentialArcTo'
|
|
||||||
| 'circle'
|
| 'circle'
|
||||||
| 'circleThreePoint'
|
| 'circleThreePoint'
|
||||||
| 'arcTo'
|
| 'arcTo'
|
||||||
@ -45,7 +44,6 @@ export const toolTips: Array<ToolTip> = [
|
|||||||
'yLineTo',
|
'yLineTo',
|
||||||
'angledLineThatIntersects',
|
'angledLineThatIntersects',
|
||||||
'tangentialArc',
|
'tangentialArc',
|
||||||
'tangentialArcTo',
|
|
||||||
'circleThreePoint',
|
'circleThreePoint',
|
||||||
'arc',
|
'arc',
|
||||||
'arcTo',
|
'arcTo',
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { TEST } from '@src/env'
|
|
||||||
import type { Models } from '@kittycad/lib'
|
import type { Models } from '@kittycad/lib'
|
||||||
import { VITE_KC_API_WS_MODELING_URL, VITE_KC_DEV_TOKEN } from '@src/env'
|
import { VITE_KC_API_WS_MODELING_URL, VITE_KC_DEV_TOKEN } from '@src/env'
|
||||||
import { jsAppSettings } from '@src/lib/settings/settingsUtils'
|
import { jsAppSettings } from '@src/lib/settings/settingsUtils'
|
||||||
@ -83,6 +82,9 @@ export enum ConnectionError {
|
|||||||
TooManyConnections,
|
TooManyConnections,
|
||||||
Outage,
|
Outage,
|
||||||
|
|
||||||
|
// Observed to happen on a local network outage.
|
||||||
|
PeerConnectionRemoteDisconnected,
|
||||||
|
|
||||||
// An unknown error is the most severe because it has not been classified
|
// An unknown error is the most severe because it has not been classified
|
||||||
// or encountered before.
|
// or encountered before.
|
||||||
Unknown,
|
Unknown,
|
||||||
@ -107,6 +109,8 @@ export const CONNECTION_ERROR_TEXT: Record<ConnectionError, string> = {
|
|||||||
'There are too many open engine connections associated with your account.',
|
'There are too many open engine connections associated with your account.',
|
||||||
[ConnectionError.Outage]:
|
[ConnectionError.Outage]:
|
||||||
'We seem to be experiencing an outage. Please visit [status.zoo.dev](https://status.zoo.dev) for updates.',
|
'We seem to be experiencing an outage. Please visit [status.zoo.dev](https://status.zoo.dev) for updates.',
|
||||||
|
[ConnectionError.PeerConnectionRemoteDisconnected]:
|
||||||
|
'The remote end has disconnected.',
|
||||||
[ConnectionError.Unknown]:
|
[ConnectionError.Unknown]:
|
||||||
'An unexpected error occurred. Please report this to us.',
|
'An unexpected error occurred. Please report this to us.',
|
||||||
}
|
}
|
||||||
@ -226,6 +230,9 @@ export enum EngineConnectionEvents {
|
|||||||
Opened = 'opened', // (engineConnection: EngineConnection) => void
|
Opened = 'opened', // (engineConnection: EngineConnection) => void
|
||||||
Closed = 'closed', // (engineConnection: EngineConnection) => void
|
Closed = 'closed', // (engineConnection: EngineConnection) => void
|
||||||
NewTrack = 'new-track', // (track: NewTrackArgs) => void
|
NewTrack = 'new-track', // (track: NewTrackArgs) => void
|
||||||
|
|
||||||
|
// A general offline state.
|
||||||
|
Offline = 'offline',
|
||||||
}
|
}
|
||||||
|
|
||||||
function toRTCSessionDescriptionInit(
|
function toRTCSessionDescriptionInit(
|
||||||
@ -674,9 +681,20 @@ class EngineConnection extends EventTarget {
|
|||||||
|
|
||||||
// The remote end broke up with us! :(
|
// The remote end broke up with us! :(
|
||||||
case 'disconnected':
|
case 'disconnected':
|
||||||
|
this.state = {
|
||||||
|
type: EngineConnectionStateType.Disconnecting,
|
||||||
|
value: {
|
||||||
|
type: DisconnectingType.Error,
|
||||||
|
value: {
|
||||||
|
error: ConnectionError.PeerConnectionRemoteDisconnected,
|
||||||
|
context: event,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
this.dispatchEvent(
|
this.dispatchEvent(
|
||||||
new CustomEvent(EngineConnectionEvents.RestartRequest, {})
|
new CustomEvent(EngineConnectionEvents.Offline, {})
|
||||||
)
|
)
|
||||||
|
this.disconnectAll()
|
||||||
break
|
break
|
||||||
case 'closed':
|
case 'closed':
|
||||||
this.pc?.removeEventListener('icecandidate', this.onIceCandidate)
|
this.pc?.removeEventListener('icecandidate', this.onIceCandidate)
|
||||||
@ -847,7 +865,6 @@ class EngineConnection extends EventTarget {
|
|||||||
'message',
|
'message',
|
||||||
this.onDataChannelMessage
|
this.onDataChannelMessage
|
||||||
)
|
)
|
||||||
this.disconnectAll()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.unreliableDataChannel?.addEventListener(
|
this.unreliableDataChannel?.addEventListener(
|
||||||
@ -866,7 +883,6 @@ class EngineConnection extends EventTarget {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
this.disconnectAll()
|
|
||||||
}
|
}
|
||||||
this.unreliableDataChannel?.addEventListener(
|
this.unreliableDataChannel?.addEventListener(
|
||||||
'error',
|
'error',
|
||||||
@ -956,6 +972,9 @@ class EngineConnection extends EventTarget {
|
|||||||
this.onNetworkStatusReady
|
this.onNetworkStatusReady
|
||||||
)
|
)
|
||||||
|
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent(EngineConnectionEvents.Offline, {})
|
||||||
|
)
|
||||||
this.disconnectAll()
|
this.disconnectAll()
|
||||||
}
|
}
|
||||||
this.websocket.addEventListener('close', this.onWebSocketClose)
|
this.websocket.addEventListener('close', this.onWebSocketClose)
|
||||||
@ -974,8 +993,6 @@ class EngineConnection extends EventTarget {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.disconnectAll()
|
|
||||||
}
|
}
|
||||||
this.websocket.addEventListener('error', this.onWebSocketError)
|
this.websocket.addEventListener('error', this.onWebSocketError)
|
||||||
|
|
||||||
@ -1331,6 +1348,9 @@ export enum EngineCommandManagerEvents {
|
|||||||
|
|
||||||
// the whole scene is ready (settings loaded)
|
// the whole scene is ready (settings loaded)
|
||||||
SceneReady = 'scene-ready',
|
SceneReady = 'scene-ready',
|
||||||
|
|
||||||
|
// we're offline
|
||||||
|
Offline = 'offline',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1380,6 +1400,7 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
* This is compared to the {@link outSequence} number to determine if we should ignore
|
* This is compared to the {@link outSequence} number to determine if we should ignore
|
||||||
* any out-of-order late responses in the unreliable channel.
|
* any out-of-order late responses in the unreliable channel.
|
||||||
*/
|
*/
|
||||||
|
keepForcefulOffline = false
|
||||||
inSequence = 1
|
inSequence = 1
|
||||||
engineConnection?: EngineConnection
|
engineConnection?: EngineConnection
|
||||||
commandLogs: CommandLog[] = []
|
commandLogs: CommandLog[] = []
|
||||||
@ -1453,13 +1474,8 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private onOffline = () => {
|
private onEngineOffline = () => {
|
||||||
console.log('Browser reported network is offline')
|
this.dispatchEvent(new CustomEvent(EngineCommandManagerEvents.Offline, {}))
|
||||||
if (TEST) {
|
|
||||||
console.warn('DURING TESTS ENGINECONNECTION.ONOFFLINE WILL DO NOTHING.')
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.onEngineConnectionRestartRequest()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
idleMode: boolean = false
|
idleMode: boolean = false
|
||||||
@ -1494,6 +1510,11 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
if (settings) {
|
if (settings) {
|
||||||
this.settings = settings
|
this.settings = settings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.keepForcefulOffline) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (width === 0 || height === 0) {
|
if (width === 0 || height === 0) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -1509,8 +1530,6 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('offline', this.onOffline)
|
|
||||||
|
|
||||||
let additionalSettings = this.settings.enableSSAO ? '&post_effect=ssao' : ''
|
let additionalSettings = this.settings.enableSSAO ? '&post_effect=ssao' : ''
|
||||||
additionalSettings +=
|
additionalSettings +=
|
||||||
'&show_grid=' + (this.settings.showScaleGrid ? 'true' : 'false')
|
'&show_grid=' + (this.settings.showScaleGrid ? 'true' : 'false')
|
||||||
@ -1537,6 +1556,11 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
this.onEngineConnectionRestartRequest as EventListener
|
this.onEngineConnectionRestartRequest as EventListener
|
||||||
)
|
)
|
||||||
|
|
||||||
|
this.engineConnection.addEventListener(
|
||||||
|
EngineConnectionEvents.Offline,
|
||||||
|
this.onEngineOffline as EventListener
|
||||||
|
)
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||||
this.onEngineConnectionOpened = async () => {
|
this.onEngineConnectionOpened = async () => {
|
||||||
console.log('onEngineConnectionOpened')
|
console.log('onEngineConnectionOpened')
|
||||||
@ -1552,9 +1576,9 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
// Let's restart.
|
// Let's restart.
|
||||||
console.warn("shit's gone south")
|
console.warn("shit's gone south")
|
||||||
console.warn(e)
|
console.warn(e)
|
||||||
this.engineConnection?.dispatchEvent(
|
// this.engineConnection?.dispatchEvent(
|
||||||
new CustomEvent(EngineConnectionEvents.RestartRequest, {})
|
// new CustomEvent(EngineConnectionEvents.RestartRequest, {})
|
||||||
)
|
// )
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1597,23 +1621,7 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
console.log('camControlsCameraChange')
|
console.log('camControlsCameraChange')
|
||||||
this._camControlsCameraChange()
|
this._camControlsCameraChange()
|
||||||
|
|
||||||
// We should eventually only have 1 restoral call.
|
|
||||||
if (this.idleMode) {
|
|
||||||
await this.sceneInfra?.camControls.restoreRemoteCameraStateAndTriggerSync()
|
await this.sceneInfra?.camControls.restoreRemoteCameraStateAndTriggerSync()
|
||||||
} else {
|
|
||||||
// NOTE: This code is old. It uses the old hack to restore camera.
|
|
||||||
console.log('call default_camera_get_settings')
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
||||||
await this.sendSceneCommand({
|
|
||||||
// CameraControls subscribes to default_camera_get_settings response events
|
|
||||||
// firing this at connection ensure the camera's are synced initially
|
|
||||||
type: 'modeling_cmd_req',
|
|
||||||
cmd_id: uuidv4(),
|
|
||||||
cmd: {
|
|
||||||
type: 'default_camera_get_settings',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
setIsStreamReady(true)
|
setIsStreamReady(true)
|
||||||
|
|
||||||
@ -1877,8 +1885,6 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
tearDown(opts?: { idleMode: boolean }) {
|
tearDown(opts?: { idleMode: boolean }) {
|
||||||
this.idleMode = opts?.idleMode ?? false
|
this.idleMode = opts?.idleMode ?? false
|
||||||
|
|
||||||
window.removeEventListener('offline', this.onOffline)
|
|
||||||
|
|
||||||
if (this.engineConnection) {
|
if (this.engineConnection) {
|
||||||
for (const [cmdId, pending] of Object.entries(this.pendingCommands)) {
|
for (const [cmdId, pending] of Object.entries(this.pendingCommands)) {
|
||||||
pending.reject([
|
pending.reject([
|
||||||
@ -1928,7 +1934,26 @@ export class EngineCommandManager extends EventTarget {
|
|||||||
this.engineCommandManager.engineConnection = null
|
this.engineCommandManager.engineConnection = null
|
||||||
}
|
}
|
||||||
this.engineConnection = undefined
|
this.engineConnection = undefined
|
||||||
|
|
||||||
|
// It is possible all connections never even started, but we still want
|
||||||
|
// to signal to the whole application we are "offline".
|
||||||
|
this.dispatchEvent(new CustomEvent(EngineCommandManagerEvents.Offline, {}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
offline() {
|
||||||
|
this.keepForcefulOffline = true
|
||||||
|
this.tearDown()
|
||||||
|
console.log('offline')
|
||||||
|
}
|
||||||
|
|
||||||
|
online() {
|
||||||
|
this.keepForcefulOffline = false
|
||||||
|
this.dispatchEvent(
|
||||||
|
new CustomEvent(EngineCommandManagerEvents.EngineRestartRequest, {})
|
||||||
|
)
|
||||||
|
console.log('online')
|
||||||
|
}
|
||||||
|
|
||||||
async startNewSession() {
|
async startNewSession() {
|
||||||
this.responseMap = {}
|
this.responseMap = {}
|
||||||
}
|
}
|
||||||
|
@ -1018,61 +1018,217 @@ export const yLine: SketchLineHelperKw = {
|
|||||||
|
|
||||||
export const tangentialArc: SketchLineHelperKw = {
|
export const tangentialArc: SketchLineHelperKw = {
|
||||||
add: ({ node, pathToNode, segmentInput, replaceExistingCallback }) => {
|
add: ({ node, pathToNode, segmentInput, replaceExistingCallback }) => {
|
||||||
return tangentialArcHelpers.add({
|
if (segmentInput.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR()
|
||||||
node,
|
const { to } = segmentInput
|
||||||
|
const _node = { ...node }
|
||||||
|
const getNode = getNodeFromPathCurry(_node, pathToNode)
|
||||||
|
const _node1 = getNode<PipeExpression | CallExpressionKw>('PipeExpression')
|
||||||
|
if (err(_node1)) return _node1
|
||||||
|
const { node: pipe } = _node1
|
||||||
|
const _node2 = getNodeFromPath<VariableDeclarator>(
|
||||||
|
_node,
|
||||||
pathToNode,
|
pathToNode,
|
||||||
segmentInput,
|
'VariableDeclarator'
|
||||||
replaceExistingCallback,
|
)
|
||||||
isAbsolute: false,
|
if (err(_node2)) return _node2
|
||||||
})
|
const { node: varDec } = _node2
|
||||||
|
|
||||||
|
const toX = createLiteral(roundOff(to[0], 2))
|
||||||
|
const toY = createLiteral(roundOff(to[1], 2))
|
||||||
|
|
||||||
|
if (replaceExistingCallback && pipe.type !== 'CallExpressionKw') {
|
||||||
|
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
|
||||||
|
const result = replaceExistingCallback([
|
||||||
|
{
|
||||||
|
type: 'labeledArgArrayItem',
|
||||||
|
key: ARG_END_ABSOLUTE,
|
||||||
|
index: 0,
|
||||||
|
argType: 'xAbsolute',
|
||||||
|
expr: toX,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'labeledArgArrayItem',
|
||||||
|
key: ARG_END_ABSOLUTE,
|
||||||
|
index: 1,
|
||||||
|
argType: 'yAbsolute',
|
||||||
|
expr: toY,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
if (err(result)) return result
|
||||||
|
const { callExp, valueUsedInTransform } = result
|
||||||
|
pipe.body[callIndex] = callExp
|
||||||
|
return {
|
||||||
|
modifiedAst: _node,
|
||||||
|
pathToNode,
|
||||||
|
valueUsedInTransform,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const newLine = createCallExpressionStdLibKw(
|
||||||
|
'tangentialArc',
|
||||||
|
null, // Assumes this is being called in a pipeline, so the first arg is optional and if not given, will become pipeline substitution.
|
||||||
|
[createLabeledArg(ARG_END_ABSOLUTE, createArrayExpression([toX, toY]))]
|
||||||
|
)
|
||||||
|
if (pipe.type === 'PipeExpression') {
|
||||||
|
pipe.body = [...pipe.body, newLine]
|
||||||
|
return {
|
||||||
|
modifiedAst: _node,
|
||||||
|
pathToNode: [
|
||||||
|
...pathToNode.slice(
|
||||||
|
0,
|
||||||
|
pathToNode.findIndex(([_, type]) => type === 'PipeExpression') + 1
|
||||||
|
),
|
||||||
|
['body', 'PipeExpression'],
|
||||||
|
[pipe.body.length - 1, 'CallExpressionKw'],
|
||||||
|
],
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
varDec.init = createPipeExpression([varDec.init, newLine])
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
modifiedAst: _node,
|
||||||
|
pathToNode,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updateArgs: ({ node, pathToNode, input }) => {
|
updateArgs: ({ node, pathToNode, input }) => {
|
||||||
return tangentialArcHelpers.update({
|
if (input.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR()
|
||||||
node,
|
const { to } = input
|
||||||
pathToNode,
|
const _node = { ...node }
|
||||||
input,
|
const nodeMeta = getNodeFromPath<CallExpressionKw>(_node, pathToNode)
|
||||||
isAbsolute: false,
|
if (err(nodeMeta)) return nodeMeta
|
||||||
})
|
const { node: callExpression } = nodeMeta
|
||||||
},
|
|
||||||
getTag: getTagKwArg(),
|
if (callExpression.type !== 'CallExpressionKw') {
|
||||||
addTag: addTagKw(),
|
return new Error(
|
||||||
getConstraintInfo: (callExp: CallExpressionKw, code, pathToNode) => {
|
`Expected CallExpressionKw, but found ${callExpression.type}`
|
||||||
return tangentialArcHelpers.getConstraintInfo({
|
)
|
||||||
callExp,
|
|
||||||
code,
|
|
||||||
pathToNode,
|
|
||||||
isAbsolute: false,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tangentialArcTo: SketchLineHelperKw = {
|
for (const arg of callExpression.arguments) {
|
||||||
add: ({ node, pathToNode, segmentInput, replaceExistingCallback }) => {
|
if (arg.label?.name !== ARG_END_ABSOLUTE && arg.label?.name !== ARG_TAG) {
|
||||||
return tangentialArcHelpers.add({
|
console.debug(
|
||||||
node,
|
'Trying to edit unsupported tangentialArc keyword arguments; skipping'
|
||||||
|
)
|
||||||
|
return {
|
||||||
|
modifiedAst: _node,
|
||||||
pathToNode,
|
pathToNode,
|
||||||
segmentInput,
|
}
|
||||||
replaceExistingCallback,
|
}
|
||||||
isAbsolute: true,
|
}
|
||||||
})
|
|
||||||
},
|
const toArrExp = createArrayExpression([
|
||||||
updateArgs: ({ node, pathToNode, input }) => {
|
createLiteral(roundOff(to[0], 2)),
|
||||||
return tangentialArcHelpers.update({
|
createLiteral(roundOff(to[1], 2)),
|
||||||
node,
|
])
|
||||||
|
|
||||||
|
mutateKwArg(ARG_END_ABSOLUTE, callExpression, toArrExp)
|
||||||
|
return {
|
||||||
|
modifiedAst: _node,
|
||||||
pathToNode,
|
pathToNode,
|
||||||
input,
|
}
|
||||||
isAbsolute: true,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
getTag: getTagKwArg(),
|
getTag: getTagKwArg(),
|
||||||
addTag: addTagKw(),
|
addTag: addTagKw(),
|
||||||
getConstraintInfo: (callExp: CallExpressionKw, code, pathToNode) => {
|
getConstraintInfo: (callExp: CallExpressionKw, code, pathToNode) => {
|
||||||
return tangentialArcHelpers.getConstraintInfo({
|
if (callExp.type !== 'CallExpressionKw') return []
|
||||||
callExp,
|
if (callExp.callee.name.name !== 'tangentialArc') return []
|
||||||
code,
|
const callee = callExp.callee
|
||||||
pathToNode,
|
const pathToCallee: PathToNode = [
|
||||||
isAbsolute: true,
|
...pathToNode,
|
||||||
|
['callee', 'CallExpressionKw'],
|
||||||
|
]
|
||||||
|
const endAbsoluteArg = findKwArgWithIndex(ARG_END_ABSOLUTE, callExp)
|
||||||
|
|
||||||
|
const constraints: ConstrainInfo[] = [
|
||||||
|
constrainInfo(
|
||||||
|
'tangentialWithPrevious',
|
||||||
|
true,
|
||||||
|
callee.name.name,
|
||||||
|
'tangentialArc',
|
||||||
|
undefined,
|
||||||
|
topLevelRange(callee.start, callee.end),
|
||||||
|
pathToCallee
|
||||||
|
),
|
||||||
|
]
|
||||||
|
if (endAbsoluteArg) {
|
||||||
|
const { expr, argIndex } = endAbsoluteArg
|
||||||
|
const pathToArgs: PathToNode = [
|
||||||
|
...pathToNode,
|
||||||
|
['arguments', 'CallExpressionKw'],
|
||||||
|
]
|
||||||
|
const pathToArg: PathToNode = [
|
||||||
|
...pathToArgs,
|
||||||
|
[argIndex, ARG_INDEX_FIELD],
|
||||||
|
['arg', LABELED_ARG_FIELD],
|
||||||
|
]
|
||||||
|
if (expr.type !== 'ArrayExpression' || expr.elements.length < 2) {
|
||||||
|
constraints.push({
|
||||||
|
stdLibFnName: 'tangentialArc',
|
||||||
|
type: 'xAbsolute',
|
||||||
|
isConstrained: isNotLiteralArrayOrStatic(expr),
|
||||||
|
sourceRange: topLevelRange(expr.start, expr.end),
|
||||||
|
pathToNode: pathToArg,
|
||||||
|
value: code.slice(expr.start, expr.end),
|
||||||
|
argPosition: {
|
||||||
|
type: 'labeledArgArrayItem',
|
||||||
|
index: 0,
|
||||||
|
key: ARG_END_ABSOLUTE,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
constraints.push({
|
||||||
|
stdLibFnName: 'tangentialArc',
|
||||||
|
type: 'yAbsolute',
|
||||||
|
isConstrained: isNotLiteralArrayOrStatic(expr),
|
||||||
|
sourceRange: topLevelRange(expr.start, expr.end),
|
||||||
|
pathToNode: pathToArg,
|
||||||
|
value: code.slice(expr.start, expr.end),
|
||||||
|
argPosition: {
|
||||||
|
type: 'labeledArgArrayItem',
|
||||||
|
index: 1,
|
||||||
|
key: ARG_END_ABSOLUTE,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return constraints
|
||||||
|
}
|
||||||
|
const pathToX: PathToNode = [
|
||||||
|
...pathToArg,
|
||||||
|
['elements', 'ArrayExpression'],
|
||||||
|
[0, 'index'],
|
||||||
|
]
|
||||||
|
const pathToY: PathToNode = [
|
||||||
|
...pathToArg,
|
||||||
|
['elements', 'ArrayExpression'],
|
||||||
|
[1, 'index'],
|
||||||
|
]
|
||||||
|
const exprX = expr.elements[0]
|
||||||
|
const exprY = expr.elements[1]
|
||||||
|
constraints.push({
|
||||||
|
stdLibFnName: 'tangentialArc',
|
||||||
|
type: 'xAbsolute',
|
||||||
|
isConstrained: isNotLiteralArrayOrStatic(exprX),
|
||||||
|
sourceRange: topLevelRange(exprX.start, exprX.end),
|
||||||
|
pathToNode: pathToX,
|
||||||
|
value: code.slice(exprX.start, exprX.end),
|
||||||
|
argPosition: {
|
||||||
|
type: 'labeledArgArrayItem',
|
||||||
|
index: 0,
|
||||||
|
key: ARG_END_ABSOLUTE,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
constraints.push({
|
||||||
|
stdLibFnName: 'tangentialArc',
|
||||||
|
type: 'yAbsolute',
|
||||||
|
isConstrained: isNotLiteralArrayOrStatic(exprY),
|
||||||
|
sourceRange: topLevelRange(exprY.start, exprY.end),
|
||||||
|
pathToNode: pathToY,
|
||||||
|
value: code.slice(exprY.start, exprY.end),
|
||||||
|
argPosition: {
|
||||||
|
type: 'labeledArgArrayItem',
|
||||||
|
index: 1,
|
||||||
|
key: ARG_END_ABSOLUTE,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return constraints
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3155,7 +3311,6 @@ export const sketchLineHelperMapKw: { [key: string]: SketchLineHelperKw } = {
|
|||||||
angledLineToX,
|
angledLineToX,
|
||||||
angledLineToY,
|
angledLineToY,
|
||||||
tangentialArc,
|
tangentialArc,
|
||||||
tangentialArcTo,
|
|
||||||
startProfile,
|
startProfile,
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
@ -3231,7 +3386,6 @@ export function fnNameToToolTipFromSegment(
|
|||||||
fnName: string
|
fnName: string
|
||||||
): ToolTip | Error {
|
): ToolTip | Error {
|
||||||
switch (fnName) {
|
switch (fnName) {
|
||||||
case 'arcTo':
|
|
||||||
case 'arc': {
|
case 'arc': {
|
||||||
return seg.type === 'ArcThreePoint' ? 'arcTo' : 'arc'
|
return seg.type === 'ArcThreePoint' ? 'arcTo' : 'arc'
|
||||||
}
|
}
|
||||||
@ -3249,7 +3403,6 @@ export function fnNameToToolTipFromSegment(
|
|||||||
case 'circleThreePoint':
|
case 'circleThreePoint':
|
||||||
case 'circle':
|
case 'circle':
|
||||||
case 'tangentialArc':
|
case 'tangentialArc':
|
||||||
case 'tangentialArcTo':
|
|
||||||
case 'angledLine':
|
case 'angledLine':
|
||||||
case 'startProfile':
|
case 'startProfile':
|
||||||
case 'arcTo':
|
case 'arcTo':
|
||||||
@ -3273,7 +3426,8 @@ export function fnNameToTooltip(
|
|||||||
argLabels: string[],
|
argLabels: string[],
|
||||||
fnName: string
|
fnName: string
|
||||||
): ToolTip | Error {
|
): ToolTip | Error {
|
||||||
const isAbsolute = argLabels.some((label) => label === ARG_END_ABSOLUTE)
|
const isAbsolute =
|
||||||
|
argLabels.findIndex((label) => label === ARG_END_ABSOLUTE) >= 0
|
||||||
switch (fnName) {
|
switch (fnName) {
|
||||||
case 'arc': {
|
case 'arc': {
|
||||||
const isArc = argLabels.some((label) =>
|
const isArc = argLabels.some((label) =>
|
||||||
@ -3287,11 +3441,10 @@ export function fnNameToTooltip(
|
|||||||
return isAbsolute ? 'xLineTo' : 'xLine'
|
return isAbsolute ? 'xLineTo' : 'xLine'
|
||||||
case 'yLine':
|
case 'yLine':
|
||||||
return isAbsolute ? 'yLineTo' : 'yLine'
|
return isAbsolute ? 'yLineTo' : 'yLine'
|
||||||
case 'tangentialArc':
|
|
||||||
return isAbsolute ? 'tangentialArcTo' : 'tangentialArc'
|
|
||||||
case 'angledLineThatIntersects':
|
case 'angledLineThatIntersects':
|
||||||
case 'circleThreePoint':
|
case 'circleThreePoint':
|
||||||
case 'circle':
|
case 'circle':
|
||||||
|
case 'tangentialArc':
|
||||||
case 'startProfile':
|
case 'startProfile':
|
||||||
return fnName
|
return fnName
|
||||||
case 'angledLine': {
|
case 'angledLine': {
|
||||||
@ -3332,7 +3485,6 @@ export function tooltipToFnName(tooltip: ToolTip): string | Error {
|
|||||||
case 'xLine':
|
case 'xLine':
|
||||||
case 'yLine':
|
case 'yLine':
|
||||||
case 'line':
|
case 'line':
|
||||||
case 'tangentialArc':
|
|
||||||
return tooltip
|
return tooltip
|
||||||
case 'lineTo':
|
case 'lineTo':
|
||||||
return 'line'
|
return 'line'
|
||||||
@ -3340,8 +3492,6 @@ export function tooltipToFnName(tooltip: ToolTip): string | Error {
|
|||||||
return 'xLine'
|
return 'xLine'
|
||||||
case 'yLineTo':
|
case 'yLineTo':
|
||||||
return 'yLine'
|
return 'yLine'
|
||||||
case 'tangentialArcTo':
|
|
||||||
return 'tangentialArc'
|
|
||||||
case 'angledLine':
|
case 'angledLine':
|
||||||
case 'angledLineToX':
|
case 'angledLineToX':
|
||||||
case 'angledLineToY':
|
case 'angledLineToY':
|
||||||
@ -3949,6 +4099,7 @@ export function isAbsoluteLine(lineCall: CallExpressionKw): boolean | Error {
|
|||||||
const name = lineCall?.callee?.name.name
|
const name = lineCall?.callee?.name.name
|
||||||
switch (name) {
|
switch (name) {
|
||||||
case 'line':
|
case 'line':
|
||||||
|
case 'tangentialArc':
|
||||||
if (findKwArg(ARG_END, lineCall) !== undefined) {
|
if (findKwArg(ARG_END, lineCall) !== undefined) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -3969,8 +4120,6 @@ export function isAbsoluteLine(lineCall: CallExpressionKw): boolean | Error {
|
|||||||
return new Error(
|
return new Error(
|
||||||
`${name} call has neither ${ARG_END} nor ${ARG_END_ABSOLUTE} params`
|
`${name} call has neither ${ARG_END} nor ${ARG_END_ABSOLUTE} params`
|
||||||
)
|
)
|
||||||
case 'tangentialArc':
|
|
||||||
return findKwArg(ARG_END_ABSOLUTE, lineCall) !== undefined
|
|
||||||
case 'angledLineThatIntersects':
|
case 'angledLineThatIntersects':
|
||||||
case 'arc':
|
case 'arc':
|
||||||
case 'circle':
|
case 'circle':
|
||||||
@ -4002,7 +4151,6 @@ export function getArgForEnd(lineCall: CallExpressionKw):
|
|||||||
switch (name) {
|
switch (name) {
|
||||||
case 'circle':
|
case 'circle':
|
||||||
return getCircle(lineCall)
|
return getCircle(lineCall)
|
||||||
case 'tangentialArc':
|
|
||||||
case 'line': {
|
case 'line': {
|
||||||
const arg = findKwArgAny(DETERMINING_ARGS, lineCall)
|
const arg = findKwArgAny(DETERMINING_ARGS, lineCall)
|
||||||
if (arg === undefined) {
|
if (arg === undefined) {
|
||||||
@ -4059,264 +4207,3 @@ export function getArgForEnd(lineCall: CallExpressionKw):
|
|||||||
function removeDeterminingArgs(callExp: CallExpressionKw) {
|
function removeDeterminingArgs(callExp: CallExpressionKw) {
|
||||||
removeKwArgs(DETERMINING_ARGS, callExp)
|
removeKwArgs(DETERMINING_ARGS, callExp)
|
||||||
}
|
}
|
||||||
|
|
||||||
const tangentialArcHelpers = {
|
|
||||||
add: ({
|
|
||||||
node,
|
|
||||||
pathToNode,
|
|
||||||
segmentInput,
|
|
||||||
replaceExistingCallback,
|
|
||||||
isAbsolute = false,
|
|
||||||
}: {
|
|
||||||
node: Node<Program>
|
|
||||||
pathToNode: PathToNode
|
|
||||||
segmentInput: SegmentInputs
|
|
||||||
replaceExistingCallback?: (
|
|
||||||
rawArgs: RawArgs
|
|
||||||
) => CreatedSketchExprResult | Error
|
|
||||||
isAbsolute?: boolean
|
|
||||||
}) => {
|
|
||||||
if (segmentInput.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR()
|
|
||||||
const { to, from } = segmentInput
|
|
||||||
const _node = { ...node }
|
|
||||||
const getNode = getNodeFromPathCurry(_node, pathToNode)
|
|
||||||
const _node1 = getNode<PipeExpression | CallExpressionKw>('PipeExpression')
|
|
||||||
if (err(_node1)) return _node1
|
|
||||||
const { node: pipe } = _node1
|
|
||||||
const _node2 = getNodeFromPath<VariableDeclarator>(
|
|
||||||
_node,
|
|
||||||
pathToNode,
|
|
||||||
'VariableDeclarator'
|
|
||||||
)
|
|
||||||
if (err(_node2)) return _node2
|
|
||||||
const { node: varDec } = _node2
|
|
||||||
|
|
||||||
const toX = createLiteral(roundOff(isAbsolute ? to[0] : to[0] - from[0], 2))
|
|
||||||
const toY = createLiteral(roundOff(isAbsolute ? to[1] : to[1] - from[1], 2))
|
|
||||||
|
|
||||||
const argLabel = isAbsolute ? ARG_END_ABSOLUTE : ARG_END
|
|
||||||
const xArgType = isAbsolute ? 'xAbsolute' : 'xRelative'
|
|
||||||
const yArgType = isAbsolute ? 'yAbsolute' : 'yRelative'
|
|
||||||
|
|
||||||
if (replaceExistingCallback && pipe.type !== 'CallExpressionKw') {
|
|
||||||
const { index: callIndex } = splitPathAtPipeExpression(pathToNode)
|
|
||||||
const result = replaceExistingCallback([
|
|
||||||
{
|
|
||||||
type: 'labeledArgArrayItem',
|
|
||||||
key: argLabel,
|
|
||||||
index: 0,
|
|
||||||
argType: xArgType,
|
|
||||||
expr: toX,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'labeledArgArrayItem',
|
|
||||||
key: argLabel,
|
|
||||||
index: 1,
|
|
||||||
argType: yArgType,
|
|
||||||
expr: toY,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
if (err(result)) return result
|
|
||||||
const { callExp, valueUsedInTransform } = result
|
|
||||||
pipe.body[callIndex] = callExp
|
|
||||||
return {
|
|
||||||
modifiedAst: _node,
|
|
||||||
pathToNode,
|
|
||||||
valueUsedInTransform,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const newLine = createCallExpressionStdLibKw(
|
|
||||||
'tangentialArc',
|
|
||||||
null, // Assumes this is being called in a pipeline, so the first arg is optional and if not given, will become pipeline substitution.
|
|
||||||
[createLabeledArg(argLabel, createArrayExpression([toX, toY]))]
|
|
||||||
)
|
|
||||||
if (pipe.type === 'PipeExpression') {
|
|
||||||
pipe.body = [...pipe.body, newLine]
|
|
||||||
return {
|
|
||||||
modifiedAst: _node,
|
|
||||||
pathToNode: [
|
|
||||||
...pathToNode.slice(
|
|
||||||
0,
|
|
||||||
pathToNode.findIndex(([_, type]) => type === 'PipeExpression') + 1
|
|
||||||
),
|
|
||||||
['body', 'PipeExpression'],
|
|
||||||
[pipe.body.length - 1, 'CallExpressionKw'],
|
|
||||||
] as PathToNode,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
varDec.init = createPipeExpression([varDec.init, newLine])
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
modifiedAst: _node,
|
|
||||||
pathToNode,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
update: ({
|
|
||||||
node,
|
|
||||||
pathToNode,
|
|
||||||
input,
|
|
||||||
isAbsolute = false,
|
|
||||||
}: {
|
|
||||||
node: Node<Program>
|
|
||||||
pathToNode: PathToNode
|
|
||||||
input: SegmentInputs
|
|
||||||
isAbsolute?: boolean
|
|
||||||
}) => {
|
|
||||||
if (input.type !== 'straight-segment') return STRAIGHT_SEGMENT_ERR()
|
|
||||||
const { to, from } = input
|
|
||||||
const _node = { ...node }
|
|
||||||
const nodeMeta = getNodeFromPath<CallExpressionKw>(_node, pathToNode)
|
|
||||||
if (err(nodeMeta)) return nodeMeta
|
|
||||||
const { node: callExpression } = nodeMeta
|
|
||||||
|
|
||||||
if (callExpression.type !== 'CallExpressionKw') {
|
|
||||||
return new Error(
|
|
||||||
`Expected CallExpressionKw, but found ${callExpression.type}`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
const argLabel = isAbsolute ? ARG_END_ABSOLUTE : ARG_END
|
|
||||||
const functionName = isAbsolute ? 'tangentialArcTo' : 'tangentialArc'
|
|
||||||
|
|
||||||
for (const arg of callExpression.arguments) {
|
|
||||||
if (arg.label?.name !== argLabel && arg.label?.name !== ARG_TAG) {
|
|
||||||
console.debug(
|
|
||||||
`Trying to edit unsupported ${functionName} keyword arguments; skipping`
|
|
||||||
)
|
|
||||||
return {
|
|
||||||
modifiedAst: _node,
|
|
||||||
pathToNode,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const toArrExp = createArrayExpression([
|
|
||||||
createLiteral(roundOff(isAbsolute ? to[0] : to[0] - from[0], 2)),
|
|
||||||
createLiteral(roundOff(isAbsolute ? to[1] : to[1] - from[1], 2)),
|
|
||||||
])
|
|
||||||
|
|
||||||
mutateKwArg(argLabel, callExpression, toArrExp)
|
|
||||||
return {
|
|
||||||
modifiedAst: _node,
|
|
||||||
pathToNode,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getConstraintInfo: ({
|
|
||||||
callExp,
|
|
||||||
code,
|
|
||||||
pathToNode,
|
|
||||||
isAbsolute = false,
|
|
||||||
}: {
|
|
||||||
callExp: CallExpressionKw
|
|
||||||
code: string
|
|
||||||
pathToNode: PathToNode
|
|
||||||
isAbsolute?: boolean
|
|
||||||
}): ConstrainInfo[] => {
|
|
||||||
if (callExp.type !== 'CallExpressionKw') return []
|
|
||||||
if (callExp.callee.name.name !== 'tangentialArc') return []
|
|
||||||
|
|
||||||
const callee = callExp.callee
|
|
||||||
const pathToCallee: PathToNode = [
|
|
||||||
...pathToNode,
|
|
||||||
['callee', 'CallExpressionKw'],
|
|
||||||
]
|
|
||||||
|
|
||||||
const argLabel = isAbsolute ? ARG_END_ABSOLUTE : ARG_END
|
|
||||||
const xConstraintType = isAbsolute ? 'xAbsolute' : 'xRelative'
|
|
||||||
const yConstraintType = isAbsolute ? 'yAbsolute' : 'yRelative'
|
|
||||||
|
|
||||||
const endArg = findKwArgWithIndex(argLabel, callExp)
|
|
||||||
|
|
||||||
const constraints: ConstrainInfo[] = [
|
|
||||||
constrainInfo(
|
|
||||||
'tangentialWithPrevious',
|
|
||||||
true,
|
|
||||||
callee.name.name,
|
|
||||||
'tangentialArc',
|
|
||||||
undefined,
|
|
||||||
topLevelRange(callee.start, callee.end),
|
|
||||||
pathToCallee
|
|
||||||
),
|
|
||||||
]
|
|
||||||
if (endArg) {
|
|
||||||
const { expr, argIndex } = endArg
|
|
||||||
const pathToArgs: PathToNode = [
|
|
||||||
...pathToNode,
|
|
||||||
['arguments', 'CallExpressionKw'],
|
|
||||||
]
|
|
||||||
const pathToArg: PathToNode = [
|
|
||||||
...pathToArgs,
|
|
||||||
[argIndex, ARG_INDEX_FIELD],
|
|
||||||
['arg', LABELED_ARG_FIELD],
|
|
||||||
]
|
|
||||||
if (expr.type !== 'ArrayExpression' || expr.elements.length < 2) {
|
|
||||||
constraints.push({
|
|
||||||
stdLibFnName: 'tangentialArc',
|
|
||||||
type: xConstraintType,
|
|
||||||
isConstrained: isNotLiteralArrayOrStatic(expr),
|
|
||||||
sourceRange: topLevelRange(expr.start, expr.end),
|
|
||||||
pathToNode: pathToArg,
|
|
||||||
value: code.slice(expr.start, expr.end),
|
|
||||||
argPosition: {
|
|
||||||
type: 'labeledArgArrayItem',
|
|
||||||
index: 0,
|
|
||||||
key: argLabel,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
constraints.push({
|
|
||||||
stdLibFnName: 'tangentialArc',
|
|
||||||
type: yConstraintType,
|
|
||||||
isConstrained: isNotLiteralArrayOrStatic(expr),
|
|
||||||
sourceRange: topLevelRange(expr.start, expr.end),
|
|
||||||
pathToNode: pathToArg,
|
|
||||||
value: code.slice(expr.start, expr.end),
|
|
||||||
argPosition: {
|
|
||||||
type: 'labeledArgArrayItem',
|
|
||||||
index: 1,
|
|
||||||
key: argLabel,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
return constraints
|
|
||||||
}
|
|
||||||
const pathToX: PathToNode = [
|
|
||||||
...pathToArg,
|
|
||||||
['elements', 'ArrayExpression'],
|
|
||||||
[0, 'index'],
|
|
||||||
]
|
|
||||||
const pathToY: PathToNode = [
|
|
||||||
...pathToArg,
|
|
||||||
['elements', 'ArrayExpression'],
|
|
||||||
[1, 'index'],
|
|
||||||
]
|
|
||||||
const exprX = expr.elements[0]
|
|
||||||
const exprY = expr.elements[1]
|
|
||||||
constraints.push({
|
|
||||||
stdLibFnName: 'tangentialArc',
|
|
||||||
type: xConstraintType,
|
|
||||||
isConstrained: isNotLiteralArrayOrStatic(exprX),
|
|
||||||
sourceRange: topLevelRange(exprX.start, exprX.end),
|
|
||||||
pathToNode: pathToX,
|
|
||||||
value: code.slice(exprX.start, exprX.end),
|
|
||||||
argPosition: {
|
|
||||||
type: 'labeledArgArrayItem',
|
|
||||||
index: 0,
|
|
||||||
key: argLabel,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
constraints.push({
|
|
||||||
stdLibFnName: 'tangentialArc',
|
|
||||||
type: yConstraintType,
|
|
||||||
isConstrained: isNotLiteralArrayOrStatic(exprY),
|
|
||||||
sourceRange: topLevelRange(exprY.start, exprY.end),
|
|
||||||
pathToNode: pathToY,
|
|
||||||
value: code.slice(exprY.start, exprY.end),
|
|
||||||
argPosition: {
|
|
||||||
type: 'labeledArgArrayItem',
|
|
||||||
index: 1,
|
|
||||||
key: argLabel,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return constraints
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
@ -1502,14 +1502,16 @@ export function removeSingleConstraint({
|
|||||||
const literal = rawArg?.overrideExpr ?? rawArg?.expr
|
const literal = rawArg?.overrideExpr ?? rawArg?.expr
|
||||||
return (arg.index === inputToReplace.index && literal) || argExpr
|
return (arg.index === inputToReplace.index && literal) || argExpr
|
||||||
})
|
})
|
||||||
|
|
||||||
// It's a kw call.
|
// It's a kw call.
|
||||||
const isAbsolute = inputs.some((input) => input.argType === 'xAbsolute')
|
const isAbsolute = callExp.node.callee.name.name == 'lineTo'
|
||||||
|
if (isAbsolute) {
|
||||||
const args = [
|
const args = [
|
||||||
createLabeledArg(
|
createLabeledArg(ARG_END_ABSOLUTE, createArrayExpression(values)),
|
||||||
isAbsolute ? ARG_END_ABSOLUTE : ARG_END,
|
]
|
||||||
createArrayExpression(values)
|
return createStdlibCallExpressionKw('line', args, tag)
|
||||||
),
|
} else {
|
||||||
|
const args = [
|
||||||
|
createLabeledArg(ARG_END, createArrayExpression(values)),
|
||||||
]
|
]
|
||||||
return createStdlibCallExpressionKw(
|
return createStdlibCallExpressionKw(
|
||||||
callExp.node.callee.name.name as ToolTip,
|
callExp.node.callee.name.name as ToolTip,
|
||||||
@ -1517,6 +1519,7 @@ export function removeSingleConstraint({
|
|||||||
tag
|
tag
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
inputToReplace.type === 'arrayInObject' ||
|
inputToReplace.type === 'arrayInObject' ||
|
||||||
inputToReplace.type === 'objectProperty'
|
inputToReplace.type === 'objectProperty'
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
import type { Operation } from '@rust/kcl-lib/bindings/Operation'
|
import type { Operation } from '@rust/kcl-lib/bindings/Operation'
|
||||||
import { topLevelRange } from '@src/lang/util'
|
|
||||||
|
|
||||||
import {
|
import { defaultSourceRange } from '@src/lang/wasm'
|
||||||
assertParse,
|
import { filterOperations } from '@src/lib/operations'
|
||||||
defaultSourceRange,
|
|
||||||
type SourceRange,
|
|
||||||
} from '@src/lang/wasm'
|
|
||||||
import { filterOperations, getOperationVariableName } from '@src/lib/operations'
|
|
||||||
|
|
||||||
function stdlib(name: string): Operation {
|
function stdlib(name: string): Operation {
|
||||||
return {
|
return {
|
||||||
@ -167,75 +162,3 @@ describe('operations filtering', () => {
|
|||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
function rangeOfText(fullCode: string, target: string): SourceRange {
|
|
||||||
const start = fullCode.indexOf(target)
|
|
||||||
if (start === -1) {
|
|
||||||
throw new Error(`Could not find \`${target}\` in: ${fullCode}`)
|
|
||||||
}
|
|
||||||
return topLevelRange(start, start + target.length)
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('variable name of operations', () => {
|
|
||||||
it('finds the variable name with simple assignment', async () => {
|
|
||||||
const op = stdlib('stdLibFn')
|
|
||||||
if (op.type !== 'StdLibCall') {
|
|
||||||
throw new Error('Expected operation to be a StdLibCall')
|
|
||||||
}
|
|
||||||
const code = `myVar = stdLibFn()`
|
|
||||||
// Make the source range match the code.
|
|
||||||
op.sourceRange = rangeOfText(code, 'stdLibFn()')
|
|
||||||
|
|
||||||
const program = assertParse(code)
|
|
||||||
const variableName = getOperationVariableName(op, program)
|
|
||||||
expect(variableName).toBe('myVar')
|
|
||||||
})
|
|
||||||
it('finds the variable name inside a function with simple assignment', async () => {
|
|
||||||
const op = stdlib('stdLibFn')
|
|
||||||
if (op.type !== 'StdLibCall') {
|
|
||||||
throw new Error('Expected operation to be a StdLibCall')
|
|
||||||
}
|
|
||||||
const code = `fn myFunc() {
|
|
||||||
myVar = stdLibFn()
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
`
|
|
||||||
// Make the source range match the code.
|
|
||||||
op.sourceRange = rangeOfText(code, 'stdLibFn()')
|
|
||||||
|
|
||||||
const program = assertParse(code)
|
|
||||||
const variableName = getOperationVariableName(op, program)
|
|
||||||
expect(variableName).toBe('myVar')
|
|
||||||
})
|
|
||||||
it("finds the variable name when it's the last in a pipeline", async () => {
|
|
||||||
const op = stdlib('stdLibFn')
|
|
||||||
if (op.type !== 'StdLibCall') {
|
|
||||||
throw new Error('Expected operation to be a StdLibCall')
|
|
||||||
}
|
|
||||||
const code = `myVar = foo()
|
|
||||||
|> stdLibFn()
|
|
||||||
`
|
|
||||||
// Make the source range match the code.
|
|
||||||
op.sourceRange = rangeOfText(code, 'stdLibFn()')
|
|
||||||
|
|
||||||
const program = assertParse(code)
|
|
||||||
const variableName = getOperationVariableName(op, program)
|
|
||||||
expect(variableName).toBe('myVar')
|
|
||||||
})
|
|
||||||
it("finds nothing when it's not the last in a pipeline", async () => {
|
|
||||||
const op = stdlib('stdLibFn')
|
|
||||||
if (op.type !== 'StdLibCall') {
|
|
||||||
throw new Error('Expected operation to be a StdLibCall')
|
|
||||||
}
|
|
||||||
const code = `myVar = foo()
|
|
||||||
|> stdLibFn()
|
|
||||||
|> bar()
|
|
||||||
`
|
|
||||||
// Make the source range match the code.
|
|
||||||
op.sourceRange = rangeOfText(code, 'stdLibFn()')
|
|
||||||
|
|
||||||
const program = assertParse(code)
|
|
||||||
const variableName = getOperationVariableName(op, program)
|
|
||||||
expect(variableName).toBeUndefined()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
@ -15,13 +15,7 @@ import {
|
|||||||
getSweepEdgeCodeRef,
|
getSweepEdgeCodeRef,
|
||||||
getWallCodeRef,
|
getWallCodeRef,
|
||||||
} from '@src/lang/std/artifactGraph'
|
} from '@src/lang/std/artifactGraph'
|
||||||
import {
|
import { type PipeExpression, sourceRangeFromRust } from '@src/lang/wasm'
|
||||||
type CallExpressionKw,
|
|
||||||
type PipeExpression,
|
|
||||||
type Program,
|
|
||||||
sourceRangeFromRust,
|
|
||||||
type VariableDeclaration,
|
|
||||||
} from '@src/lang/wasm'
|
|
||||||
import type {
|
import type {
|
||||||
HelixModes,
|
HelixModes,
|
||||||
ModelingCommandSchema,
|
ModelingCommandSchema,
|
||||||
@ -1080,71 +1074,6 @@ export function getOperationIcon(op: Operation): CustomIconName {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If the result of the operation is assigned to a variable, returns the
|
|
||||||
* variable name.
|
|
||||||
*/
|
|
||||||
export function getOperationVariableName(
|
|
||||||
op: Operation,
|
|
||||||
program: Program
|
|
||||||
): string | undefined {
|
|
||||||
if (
|
|
||||||
op.type !== 'StdLibCall' &&
|
|
||||||
!(op.type === 'GroupBegin' && op.group.type === 'FunctionCall')
|
|
||||||
) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
// Find the AST node.
|
|
||||||
const range = sourceRangeFromRust(op.sourceRange)
|
|
||||||
const pathToNode = getNodePathFromSourceRange(program, range)
|
|
||||||
if (pathToNode.length === 0) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
const call = getNodeFromPath<CallExpressionKw>(
|
|
||||||
program,
|
|
||||||
pathToNode,
|
|
||||||
'CallExpressionKw'
|
|
||||||
)
|
|
||||||
if (err(call) || call.node.type !== 'CallExpressionKw') {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
// Find the var name from the variable declaration.
|
|
||||||
const varDec = getNodeFromPath<VariableDeclaration>(
|
|
||||||
program,
|
|
||||||
pathToNode,
|
|
||||||
'VariableDeclaration'
|
|
||||||
)
|
|
||||||
if (err(varDec)) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
if (varDec.node.type !== 'VariableDeclaration') {
|
|
||||||
// There's no variable declaration for this call.
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
const varName = varDec.node.declaration.id.name
|
|
||||||
// If the operation is a simple assignment, we can use the variable name.
|
|
||||||
if (varDec.node.declaration.init === call.node) {
|
|
||||||
return varName
|
|
||||||
}
|
|
||||||
// If the AST node is in a pipe expression, we can only use the variable
|
|
||||||
// name if it's the last operation in the pipe.
|
|
||||||
const pipe = getNodeFromPath<PipeExpression>(
|
|
||||||
program,
|
|
||||||
pathToNode,
|
|
||||||
'PipeExpression'
|
|
||||||
)
|
|
||||||
if (err(pipe)) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
pipe.node.type === 'PipeExpression' &&
|
|
||||||
pipe.node.body[pipe.node.body.length - 1] === call.node
|
|
||||||
) {
|
|
||||||
return varName
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply all filters to a list of operations.
|
* Apply all filters to a list of operations.
|
||||||
*/
|
*/
|
||||||
|
@ -703,7 +703,8 @@ export async function sendSelectEventToEngine(
|
|||||||
cmd_id: uuidv4(),
|
cmd_id: uuidv4(),
|
||||||
})
|
})
|
||||||
if (!res) {
|
if (!res) {
|
||||||
return Promise.reject('no response')
|
console.warn('No response')
|
||||||
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isArray(res)) {
|
if (isArray(res)) {
|
||||||
|
@ -70,7 +70,6 @@ export async function holdOntoVideoFrameInCanvas(
|
|||||||
video: HTMLVideoElement,
|
video: HTMLVideoElement,
|
||||||
canvas: HTMLCanvasElement
|
canvas: HTMLCanvasElement
|
||||||
) {
|
) {
|
||||||
video.pause()
|
|
||||||
canvas.width = video.videoWidth
|
canvas.width = video.videoWidth
|
||||||
canvas.height = video.videoHeight
|
canvas.height = video.videoHeight
|
||||||
canvas.style.width = video.videoWidth + 'px'
|
canvas.style.width = video.videoWidth + 'px'
|
||||||
@ -220,12 +219,15 @@ export const engineStreamMachine = setup({
|
|||||||
if (context.videoRef.current && context.canvasRef.current) {
|
if (context.videoRef.current && context.canvasRef.current) {
|
||||||
await context.videoRef.current.pause()
|
await context.videoRef.current.pause()
|
||||||
|
|
||||||
|
// It's possible we've already frozen the frame due to a disconnect.
|
||||||
|
if (context.videoRef.current.style.display !== 'none') {
|
||||||
await holdOntoVideoFrameInCanvas(
|
await holdOntoVideoFrameInCanvas(
|
||||||
context.videoRef.current,
|
context.videoRef.current,
|
||||||
context.canvasRef.current
|
context.canvasRef.current
|
||||||
)
|
)
|
||||||
context.videoRef.current.style.display = 'none'
|
context.videoRef.current.style.display = 'none'
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
await rootContext.sceneInfra.camControls.saveRemoteCameraState()
|
await rootContext.sceneInfra.camControls.saveRemoteCameraState()
|
||||||
|
|
||||||
@ -365,9 +367,12 @@ export const engineStreamMachine = setup({
|
|||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
on: {
|
on: {
|
||||||
[EngineStreamTransition.StartOrReconfigureEngine]: {
|
[EngineStreamTransition.Resume]: {
|
||||||
target: EngineStreamState.Resuming,
|
target: EngineStreamState.Resuming,
|
||||||
},
|
},
|
||||||
|
[EngineStreamTransition.Stop]: {
|
||||||
|
target: EngineStreamState.Stopped,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
[EngineStreamState.Stopped]: {
|
[EngineStreamState.Stopped]: {
|
||||||
@ -398,12 +403,23 @@ export const engineStreamMachine = setup({
|
|||||||
rootContext: args.self.system.get('root').getSnapshot().context,
|
rootContext: args.self.system.get('root').getSnapshot().context,
|
||||||
event: args.event,
|
event: args.event,
|
||||||
}),
|
}),
|
||||||
|
// Usually only fails if there was a disconnection mid-way.
|
||||||
|
onError: [
|
||||||
|
{
|
||||||
|
target: EngineStreamState.WaitingForDependencies,
|
||||||
|
reenter: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
on: {
|
on: {
|
||||||
// The stream can be paused as it's resuming.
|
// The stream can be paused as it's resuming.
|
||||||
[EngineStreamTransition.Pause]: {
|
[EngineStreamTransition.Pause]: {
|
||||||
target: EngineStreamState.Paused,
|
target: EngineStreamState.Paused,
|
||||||
},
|
},
|
||||||
|
// The stream can be stopped as it's resuming.
|
||||||
|
[EngineStreamTransition.Stop]: {
|
||||||
|
target: EngineStreamState.Stopped,
|
||||||
|
},
|
||||||
[EngineStreamTransition.SetMediaStream]: {
|
[EngineStreamTransition.SetMediaStream]: {
|
||||||
target: EngineStreamState.Playing,
|
target: EngineStreamState.Playing,
|
||||||
actions: [
|
actions: [
|
||||||
|