Implement dual camera sync direction (#1597)
* implement dual camer sync direction The existance of the client side scene requires two cameras to stay in sync, really these need to be a master-slave relationship, intitial this was implemented with the client side scene taking the lead and sending updates to the server using the endpoint (as it didn't require an new endpoints), but even though we added a sequence property to this endpoint and sent it over udp, it was still an abuse of this endpoint as the engine didn't have this endpoint setup with a fload of messages and low-latency in mind. Now we have migrated back to sending mouse events to the engine instead, but with the engine replying with camera details on drag_end etc so that we can keep the client camera in sync. The client side camera still does take the master role in sketch mode as it makes sense to keep the low latency benfits of the local camera for the locallay rendered assets in sketch mode, moving the camera in this mode already did hide the engine camera while the camera is moving so as to avoid ghoasting so this works well. The camera controls now work by syncing in either direction depending on what's appropiate * fmt * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * update default plane extrude numbers * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * trigger-ci --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
@ -16,9 +16,9 @@ document.addEventListener('mousemove', (e) =>
|
||||
*/
|
||||
|
||||
const commonPoints = {
|
||||
startAt: '[0.93, -1.26]',
|
||||
num1: 0.95,
|
||||
num2: 1.88,
|
||||
startAt: '[9.06, -12.22]',
|
||||
num1: 9.14,
|
||||
num2: 18.2,
|
||||
}
|
||||
|
||||
test.beforeEach(async ({ context, page }) => {
|
||||
@ -102,13 +102,13 @@ test('Basic sketch', async ({ page }) => {
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt(${commonPoints.startAt}, %)
|
||||
|> line([${commonPoints.num1}, 0], %)
|
||||
|> line([0, ${commonPoints.num1 - 0.01}], %)`)
|
||||
|> line([0, ${commonPoints.num1}], %)`)
|
||||
await page.mouse.click(startXPx, 500 - PUR * 20)
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt(${commonPoints.startAt}, %)
|
||||
|> line([${commonPoints.num1}, 0], %)
|
||||
|> line([0, ${commonPoints.num1 - 0.01}], %)
|
||||
|> line([0, ${commonPoints.num1}], %)
|
||||
|> line([-${commonPoints.num2}, 0], %)`)
|
||||
|
||||
// deselect line tool
|
||||
@ -133,7 +133,7 @@ test('Basic sketch', async ({ page }) => {
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt(${commonPoints.startAt}, %)
|
||||
|> line({ to: [${commonPoints.num1}, 0], tag: 'seg01' }, %)
|
||||
|> line([0, ${commonPoints.num1 - 0.01}], %)
|
||||
|> line([0, ${commonPoints.num1}], %)
|
||||
|> angledLine([180, segLen('seg01', %)], %)`)
|
||||
})
|
||||
|
||||
@ -492,13 +492,13 @@ test('Selections work on fresh and edited sketch', async ({ page }) => {
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt(${commonPoints.startAt}, %)
|
||||
|> line([${commonPoints.num1}, 0], %)
|
||||
|> line([0, ${commonPoints.num1 - 0.01}], %)`)
|
||||
|> line([0, ${commonPoints.num1}], %)`)
|
||||
await page.mouse.click(startXPx, 500 - PUR * 20)
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt(${commonPoints.startAt}, %)
|
||||
|> line([${commonPoints.num1}, 0], %)
|
||||
|> line([0, ${commonPoints.num1 - 0.01}], %)
|
||||
|> line([0, ${commonPoints.num1}], %)
|
||||
|> line([-${commonPoints.num2}, 0], %)`)
|
||||
|
||||
// deselect line tool
|
||||
@ -771,12 +771,12 @@ test('Can add multiple sketches', async ({ page }) => {
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt(${commonPoints.startAt}, %)
|
||||
|> line([${commonPoints.num1}, 0], %)
|
||||
|> line([0, ${commonPoints.num1 - 0.01}], %)`)
|
||||
|> line([0, ${commonPoints.num1}], %)`)
|
||||
await page.mouse.click(startXPx, 500 - PUR * 20)
|
||||
const finalCodeFirstSketch = `const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt(${commonPoints.startAt}, %)
|
||||
|> line([${commonPoints.num1}, 0], %)
|
||||
|> line([0, ${commonPoints.num1 - 0.01}], %)
|
||||
|> line([0, ${commonPoints.num1}], %)
|
||||
|> line([-${commonPoints.num2}, 0], %)`
|
||||
await expect(page.locator('.cm-content')).toHaveText(finalCodeFirstSketch)
|
||||
|
||||
|
||||
@ -384,13 +384,13 @@ test('extrude on each default plane should be stable', async ({
|
||||
}) => {
|
||||
const u = getUtils(page)
|
||||
const makeCode = (plane = 'XY') => `const part001 = startSketchOn('${plane}')
|
||||
|> startProfileAt([0.70, 0.44], %)
|
||||
|> line([0.66, -0.02], %)
|
||||
|> line([0.28, 0.50], %)
|
||||
|> line([-0.56, 0.44], %)
|
||||
|> line([-0.54, -0.38], %)
|
||||
|> startProfileAt([7.00, 4.40], %)
|
||||
|> line([6.60, -0.20], %)
|
||||
|> line([2.80, 5.00], %)
|
||||
|> line([-5.60, 4.40], %)
|
||||
|> line([-5.40, -3.80], %)
|
||||
|> close(%)
|
||||
|> extrude(1.00, %)
|
||||
|> extrude(10.00, %)
|
||||
`
|
||||
await context.addInitScript(async (code) => {
|
||||
localStorage.setItem('persistCode', code)
|
||||
@ -484,7 +484,7 @@ test('Draft segments should look right', async ({ page, context }) => {
|
||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([0.93, -1.26], %)`)
|
||||
|> startProfileAt([9.06, -12.22], %)`)
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
await u.closeDebugPanel()
|
||||
@ -498,8 +498,8 @@ test('Draft segments should look right', async ({ page, context }) => {
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([0.93, -1.26], %)
|
||||
|> line([0.95, 0], %)`)
|
||||
|> startProfileAt([9.06, -12.22], %)
|
||||
|> line([9.14, 0], %)`)
|
||||
|
||||
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
||||
|
||||
@ -562,7 +562,7 @@ test('Client side scene scale should match engine scale inch', async ({
|
||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([0.93, -1.26], %)`)
|
||||
|> startProfileAt([9.06, -12.22], %)`)
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
await u.closeDebugPanel()
|
||||
@ -572,8 +572,8 @@ test('Client side scene scale should match engine scale inch', async ({
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([0.93, -1.26], %)
|
||||
|> line([0.95, 0], %)`)
|
||||
|> startProfileAt([9.06, -12.22], %)
|
||||
|> line([9.14, 0], %)`)
|
||||
|
||||
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
||||
await page.waitForTimeout(100)
|
||||
@ -582,9 +582,13 @@ test('Client side scene scale should match engine scale inch', async ({
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([0.93, -1.26], %)
|
||||
|> line([0.95, 0], %)
|
||||
|> tangentialArcTo([2.82, -0.32], %)`)
|
||||
|> startProfileAt([9.06, -12.22], %)
|
||||
|> line([9.14, 0], %)
|
||||
|> tangentialArcTo([27.34, -3.08], %)`)
|
||||
|
||||
// click tangential arc tool again to unequip it
|
||||
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
// screen shot should show the sketch
|
||||
await expect(page).toHaveScreenshot({
|
||||
@ -658,7 +662,7 @@ test('Client side scene scale should match engine scale mm', async ({
|
||||
await page.mouse.click(startXPx + PUR * 10, 500 - PUR * 10)
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([0.93, -1.26], %)`)
|
||||
|> startProfileAt([230.03, -310.33], %)`)
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
await u.closeDebugPanel()
|
||||
@ -668,8 +672,8 @@ test('Client side scene scale should match engine scale mm', async ({
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([0.93, -1.26], %)
|
||||
|> line([0.95, 0], %)`)
|
||||
|> startProfileAt([230.03, -310.33], %)
|
||||
|> line([232.2, 0], %)`)
|
||||
|
||||
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
||||
await page.waitForTimeout(100)
|
||||
@ -678,9 +682,12 @@ test('Client side scene scale should match engine scale mm', async ({
|
||||
|
||||
await expect(page.locator('.cm-content'))
|
||||
.toHaveText(`const part001 = startSketchOn('-XZ')
|
||||
|> startProfileAt([0.93, -1.26], %)
|
||||
|> line([0.95, 0], %)
|
||||
|> tangentialArcTo([2.82, -0.32], %)`)
|
||||
|> startProfileAt([230.03, -310.33], %)
|
||||
|> line([232.2, 0], %)
|
||||
|> tangentialArcTo([694.43, -78.12], %)`)
|
||||
|
||||
await page.getByRole('button', { name: 'Tangential Arc' }).click()
|
||||
await page.waitForTimeout(100)
|
||||
|
||||
// screen shot should show the sketch
|
||||
await expect(page).toHaveScreenshot({
|
||||
|
||||
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 45 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 118 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 51 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 53 KiB |