fluidcad 0.0.24 → 0.0.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/dist/common/scene-object.d.ts +6 -2
- package/lib/dist/common/scene-object.js +28 -16
- package/lib/dist/common/transformable-primitive.d.ts +16 -0
- package/lib/dist/common/transformable-primitive.js +116 -0
- package/lib/dist/core/2d/tarc.d.ts +2 -2
- package/lib/dist/core/copy.js +5 -4
- package/lib/dist/core/cylinder.d.ts +2 -2
- package/lib/dist/core/index.d.ts +2 -1
- package/lib/dist/core/index.js +1 -0
- package/lib/dist/core/interfaces.d.ts +80 -21
- package/lib/dist/core/local.d.ts +12 -0
- package/lib/dist/core/local.js +18 -0
- package/lib/dist/core/mirror.d.ts +2 -2
- package/lib/dist/core/mirror.js +42 -60
- package/lib/dist/core/plane.d.ts +5 -7
- package/lib/dist/core/sphere.d.ts +3 -3
- package/lib/dist/features/2d/circle.js +2 -1
- package/lib/dist/features/2d/tarc-with-tangent.js +4 -2
- package/lib/dist/features/2d/tarc.js +4 -2
- package/lib/dist/features/axis-from-edge.js +2 -2
- package/lib/dist/features/axis-from-sketch.d.ts +18 -0
- package/lib/dist/features/axis-from-sketch.js +58 -0
- package/lib/dist/features/copy-linear2d.d.ts +4 -2
- package/lib/dist/features/copy-linear2d.js +23 -9
- package/lib/dist/features/cylinder.d.ts +2 -2
- package/lib/dist/features/cylinder.js +2 -2
- package/lib/dist/features/mirror-shape.js +10 -0
- package/lib/dist/features/plane-from-object.d.ts +1 -1
- package/lib/dist/features/plane-from-object.js +11 -6
- package/lib/dist/features/plane-mid.d.ts +1 -1
- package/lib/dist/features/plane.d.ts +1 -1
- package/lib/dist/features/select.js +0 -1
- package/lib/dist/features/sphere.d.ts +2 -2
- package/lib/dist/features/sphere.js +2 -2
- package/lib/dist/math/axis.d.ts +1 -0
- package/lib/dist/math/axis.js +4 -1
- package/lib/dist/math/index.d.ts +2 -2
- package/lib/dist/math/index.js +1 -1
- package/lib/dist/math/plane.d.ts +1 -2
- package/lib/dist/math/plane.js +20 -19
- package/lib/dist/rendering/render.js +8 -0
- package/lib/dist/tests/features/cut-two-distances.test.js +1 -1
- package/lib/dist/tests/features/cut.test.js +1 -1
- package/lib/dist/tests/features/mirror2d.test.js +34 -0
- package/lib/dist/tests/features/primitive-chain.test.d.ts +1 -0
- package/lib/dist/tests/features/primitive-chain.test.js +45 -0
- package/lib/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/server/dist/code-editor.d.ts +3 -2
- package/server/dist/code-editor.js +244 -121
- package/ui/dist/assets/{index-CqP_mgZk.js → index-BeLxRMCv.js} +4 -4
- package/ui/dist/index.html +1 -1
package/package.json
CHANGED
|
@@ -12,8 +12,9 @@ export declare function clearBreakpoints(code: string): Promise<CodeEditResult>;
|
|
|
12
12
|
export declare function insertPoint(code: string, sourceLine: number, point: [number, number]): Promise<CodeEditResult>;
|
|
13
13
|
export declare function addPick(code: string, sourceLine: number): Promise<CodeEditResult>;
|
|
14
14
|
/**
|
|
15
|
-
* Remove an empty `.pick()` call from the
|
|
16
|
-
* untouched so concurrent/stale edits cannot
|
|
15
|
+
* Remove an empty `.pick()` call from the chain on the resolved row.
|
|
16
|
+
* Calls with points are left untouched so concurrent/stale edits cannot
|
|
17
|
+
* discard user data.
|
|
17
18
|
*/
|
|
18
19
|
export declare function removePick(code: string, sourceLine: number): Promise<CodeEditResult>;
|
|
19
20
|
export declare function removePoint(code: string, sourceLine: number, point: [number, number]): Promise<CodeEditResult>;
|
|
@@ -22,7 +22,6 @@ async function getParser() {
|
|
|
22
22
|
parser.setLanguage(lang);
|
|
23
23
|
return parser;
|
|
24
24
|
}
|
|
25
|
-
const POINT_LITERAL = /\[([^\]]+)\]/g;
|
|
26
25
|
function splitLines(code) {
|
|
27
26
|
return code.split('\n');
|
|
28
27
|
}
|
|
@@ -46,6 +45,114 @@ function* walkTree(node) {
|
|
|
46
45
|
yield* walkTree(child);
|
|
47
46
|
}
|
|
48
47
|
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolve a 1-indexed `sourceLine` (captured from a V8 stack trace) to the
|
|
50
|
+
* outermost `call_expression` node whose invocation starts on that row.
|
|
51
|
+
*
|
|
52
|
+
* "Outermost" means: of all call_expression nodes starting on the resolved
|
|
53
|
+
* row, return the one with the largest endIndex. That picks the whole
|
|
54
|
+
* `.pick()` chain for `extrude(sk).pick()` and the only call on the row for
|
|
55
|
+
* the multi-line case
|
|
56
|
+
* trim(
|
|
57
|
+
* edge().circle()
|
|
58
|
+
* )
|
|
59
|
+
* — both match how the old line-based code (which found the last `)` on
|
|
60
|
+
* the line) behaved for the cases it handled.
|
|
61
|
+
*
|
|
62
|
+
* Returns `null` when no call starts on that row, preserving the existing
|
|
63
|
+
* silent-no-op contract of the edit functions.
|
|
64
|
+
*/
|
|
65
|
+
function findEditableCallAt(tree, lines, sourceLine) {
|
|
66
|
+
const row = resolveSourceRow(lines, sourceLine);
|
|
67
|
+
if (row < 0) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
let best = null;
|
|
71
|
+
for (const node of walkTree(tree.rootNode)) {
|
|
72
|
+
if (node.type !== 'call_expression') {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (node.startPosition.row !== row) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (!best || node.endIndex > best.endIndex) {
|
|
79
|
+
best = node;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return best;
|
|
83
|
+
}
|
|
84
|
+
function getArgumentsNode(call) {
|
|
85
|
+
return call.childForFieldName('arguments');
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* If `call` or any call in its `function` chain invokes `.pick(...)`, return
|
|
89
|
+
* the call_expression for that `.pick()` invocation. Centralises the
|
|
90
|
+
* "is this chain already picked?" check for addPick and removePick.
|
|
91
|
+
*/
|
|
92
|
+
function findPickCallInChain(call) {
|
|
93
|
+
let current = call;
|
|
94
|
+
while (current && current.type === 'call_expression') {
|
|
95
|
+
const fn = current.childForFieldName('function');
|
|
96
|
+
if (fn && fn.type === 'member_expression') {
|
|
97
|
+
const prop = fn.childForFieldName('property');
|
|
98
|
+
if (prop && prop.text === 'pick') {
|
|
99
|
+
return current;
|
|
100
|
+
}
|
|
101
|
+
const object = fn.childForFieldName('object');
|
|
102
|
+
current = object;
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Extract `[x, y]` from an `array` node with exactly two numeric children.
|
|
111
|
+
* Handles unary minus (`-5`) because tree-sitter wraps it in a `unary_expression`.
|
|
112
|
+
*/
|
|
113
|
+
function parsePointLiteral(node) {
|
|
114
|
+
if (node.type !== 'array' || node.namedChildren.length !== 2) {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
const parts = [];
|
|
118
|
+
for (const child of node.namedChildren) {
|
|
119
|
+
const value = parseFloat(child.text);
|
|
120
|
+
if (Number.isNaN(value)) {
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
parts.push(value);
|
|
124
|
+
}
|
|
125
|
+
return [parts[0], parts[1]];
|
|
126
|
+
}
|
|
127
|
+
function spliceCode(code, startIndex, endIndex, replacement) {
|
|
128
|
+
return code.slice(0, startIndex) + replacement + code.slice(endIndex);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* For point edits (insertPoint / removePoint / setPickPoints), the target is
|
|
132
|
+
* always the `.pick()` call if one exists in the chain — otherwise the
|
|
133
|
+
* outermost call itself. Without this, a chain like
|
|
134
|
+
* extrude(sk).pick([1, 2]).symmetric([3, 4], [5, 6])
|
|
135
|
+
* would drop new points into `.symmetric(...)` instead of `.pick(...)`,
|
|
136
|
+
* because `findEditableCallAt` picks the outermost (largest endIndex) call.
|
|
137
|
+
* The bezier draw-mode flow has no `.pick()` in its chain, so falling back
|
|
138
|
+
* to the outermost keeps bezier(...) point edits working.
|
|
139
|
+
*/
|
|
140
|
+
function resolvePointEditTarget(call) {
|
|
141
|
+
return findPickCallInChain(call) ?? call;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Shared setup for the five AST-based edit functions: parse the code once,
|
|
145
|
+
* split it into lines for `resolveSourceRow`, run the caller's transform,
|
|
146
|
+
* and wrap the result. Returning `null` from `fn` means "no edit" and
|
|
147
|
+
* yields the original code verbatim.
|
|
148
|
+
*/
|
|
149
|
+
async function withParsedCode(code, fn) {
|
|
150
|
+
const p = await getParser();
|
|
151
|
+
const tree = p.parse(code);
|
|
152
|
+
const lines = splitLines(code);
|
|
153
|
+
const next = fn(tree, lines);
|
|
154
|
+
return { newCode: next ?? code };
|
|
155
|
+
}
|
|
49
156
|
/**
|
|
50
157
|
* Recognise a `breakpoint();` statement: an expression_statement wrapping a
|
|
51
158
|
* call_expression to the bare identifier `breakpoint` with zero arguments.
|
|
@@ -267,8 +374,9 @@ export async function clearBreakpoints(code) {
|
|
|
267
374
|
return { newCode: joinLines(filtered) };
|
|
268
375
|
}
|
|
269
376
|
// ---------------------------------------------------------------------------
|
|
270
|
-
// Point / pick edits —
|
|
271
|
-
//
|
|
377
|
+
// Point / pick edits — AST-driven transformations. `sourceLine` locates the
|
|
378
|
+
// outermost call_expression on that row; edits operate on the node's
|
|
379
|
+
// startIndex/endIndex so multi-line calls are handled the same as single-line.
|
|
272
380
|
// ---------------------------------------------------------------------------
|
|
273
381
|
/**
|
|
274
382
|
* Resolve `sourceLine` (1-indexed) to a 0-indexed row containing code.
|
|
@@ -287,138 +395,153 @@ function resolveSourceRow(lines, sourceLine) {
|
|
|
287
395
|
}
|
|
288
396
|
return row;
|
|
289
397
|
}
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
398
|
+
/**
|
|
399
|
+
* Walk forward from `from` over whitespace; if a `,` follows, consume it
|
|
400
|
+
* and any trailing whitespace. Returns the index up to which to delete
|
|
401
|
+
* when stripping a non-last argument.
|
|
402
|
+
*/
|
|
403
|
+
function consumeTrailingSeparator(code, from) {
|
|
404
|
+
let i = from;
|
|
405
|
+
while (i < code.length && /\s/.test(code[i])) {
|
|
406
|
+
i++;
|
|
407
|
+
}
|
|
408
|
+
if (i < code.length && code[i] === ',') {
|
|
409
|
+
i++;
|
|
410
|
+
while (i < code.length && /\s/.test(code[i])) {
|
|
411
|
+
i++;
|
|
412
|
+
}
|
|
413
|
+
return i;
|
|
304
414
|
}
|
|
305
|
-
|
|
306
|
-
const prefix = between.length > 0 ? ', ' : '';
|
|
307
|
-
const pointText = `[${point[0]}, ${point[1]}]`;
|
|
308
|
-
lines[row] = lineText.slice(0, closeParen) + `${prefix}${pointText}` + lineText.slice(closeParen);
|
|
309
|
-
return { newCode: joinLines(lines) };
|
|
415
|
+
return from;
|
|
310
416
|
}
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
417
|
+
/**
|
|
418
|
+
* Walk backward from `to` over whitespace; if a `,` precedes, consume it
|
|
419
|
+
* and any preceding whitespace. Returns the index from which to start
|
|
420
|
+
* deleting when stripping a non-first argument.
|
|
421
|
+
*/
|
|
422
|
+
function consumeLeadingSeparator(code, to) {
|
|
423
|
+
let i = to;
|
|
424
|
+
while (i > 0 && /\s/.test(code[i - 1])) {
|
|
425
|
+
i--;
|
|
426
|
+
}
|
|
427
|
+
if (i > 0 && code[i - 1] === ',') {
|
|
428
|
+
i--;
|
|
429
|
+
while (i > 0 && /\s/.test(code[i - 1])) {
|
|
430
|
+
i--;
|
|
431
|
+
}
|
|
432
|
+
return i;
|
|
324
433
|
}
|
|
325
|
-
|
|
326
|
-
|
|
434
|
+
return to;
|
|
435
|
+
}
|
|
436
|
+
export function insertPoint(code, sourceLine, point) {
|
|
437
|
+
return withParsedCode(code, (tree, lines) => {
|
|
438
|
+
const call = findEditableCallAt(tree, lines, sourceLine);
|
|
439
|
+
if (!call) {
|
|
440
|
+
return null;
|
|
441
|
+
}
|
|
442
|
+
const target = resolvePointEditTarget(call);
|
|
443
|
+
const args = getArgumentsNode(target);
|
|
444
|
+
if (!args) {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
const pointText = `[${point[0]}, ${point[1]}]`;
|
|
448
|
+
if (args.namedChildren.length === 0) {
|
|
449
|
+
return spliceCode(code, args.startIndex + 1, args.endIndex - 1, pointText);
|
|
450
|
+
}
|
|
451
|
+
return spliceCode(code, args.endIndex - 1, args.endIndex - 1, `, ${pointText}`);
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
export function addPick(code, sourceLine) {
|
|
455
|
+
return withParsedCode(code, (tree, lines) => {
|
|
456
|
+
const call = findEditableCallAt(tree, lines, sourceLine);
|
|
457
|
+
if (!call || findPickCallInChain(call)) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
return spliceCode(code, call.endIndex, call.endIndex, '.pick()');
|
|
461
|
+
});
|
|
327
462
|
}
|
|
328
463
|
/**
|
|
329
|
-
* Remove an empty `.pick()` call from the
|
|
330
|
-
* untouched so concurrent/stale edits cannot
|
|
464
|
+
* Remove an empty `.pick()` call from the chain on the resolved row.
|
|
465
|
+
* Calls with points are left untouched so concurrent/stale edits cannot
|
|
466
|
+
* discard user data.
|
|
331
467
|
*/
|
|
332
|
-
export
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
468
|
+
export function removePick(code, sourceLine) {
|
|
469
|
+
return withParsedCode(code, (tree, lines) => {
|
|
470
|
+
const call = findEditableCallAt(tree, lines, sourceLine);
|
|
471
|
+
if (!call) {
|
|
472
|
+
return null;
|
|
473
|
+
}
|
|
474
|
+
const pickCall = findPickCallInChain(call);
|
|
475
|
+
if (!pickCall) {
|
|
476
|
+
return null;
|
|
477
|
+
}
|
|
478
|
+
const pickArgs = getArgumentsNode(pickCall);
|
|
479
|
+
if (!pickArgs || pickArgs.namedChildren.length !== 0) {
|
|
480
|
+
return null;
|
|
481
|
+
}
|
|
482
|
+
const member = pickCall.childForFieldName('function');
|
|
483
|
+
const object = member ? member.childForFieldName('object') : null;
|
|
484
|
+
if (!object) {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
return spliceCode(code, object.endIndex, pickCall.endIndex, '');
|
|
488
|
+
});
|
|
346
489
|
}
|
|
347
|
-
export
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
let bestIndex = 0;
|
|
368
|
-
let bestDist = Infinity;
|
|
369
|
-
for (let i = 0; i < matches.length; i++) {
|
|
370
|
-
const parts = matches[i][1].split(',').map((s) => parseFloat(s.trim()));
|
|
371
|
-
if (parts.length === 2 && !isNaN(parts[0]) && !isNaN(parts[1])) {
|
|
372
|
-
const dx = parts[0] - point[0];
|
|
373
|
-
const dy = parts[1] - point[1];
|
|
490
|
+
export function removePoint(code, sourceLine, point) {
|
|
491
|
+
return withParsedCode(code, (tree, lines) => {
|
|
492
|
+
const call = findEditableCallAt(tree, lines, sourceLine);
|
|
493
|
+
if (!call) {
|
|
494
|
+
return null;
|
|
495
|
+
}
|
|
496
|
+
const target = resolvePointEditTarget(call);
|
|
497
|
+
const args = getArgumentsNode(target);
|
|
498
|
+
if (!args || args.namedChildren.length === 0) {
|
|
499
|
+
return null;
|
|
500
|
+
}
|
|
501
|
+
let bestIndex = -1;
|
|
502
|
+
let bestDist = Infinity;
|
|
503
|
+
for (let i = 0; i < args.namedChildren.length; i++) {
|
|
504
|
+
const parsed = parsePointLiteral(args.namedChildren[i]);
|
|
505
|
+
if (!parsed) {
|
|
506
|
+
continue;
|
|
507
|
+
}
|
|
508
|
+
const dx = parsed[0] - point[0];
|
|
509
|
+
const dy = parsed[1] - point[1];
|
|
374
510
|
const dist = dx * dx + dy * dy;
|
|
375
511
|
if (dist < bestDist) {
|
|
376
512
|
bestDist = dist;
|
|
377
513
|
bestIndex = i;
|
|
378
514
|
}
|
|
379
515
|
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
const matchStart = openParen + 1 + match.index;
|
|
383
|
-
const matchEnd = matchStart + match[0].length;
|
|
384
|
-
let deleteStart = matchStart;
|
|
385
|
-
let deleteEnd = matchEnd;
|
|
386
|
-
if (matches.length === 1) {
|
|
387
|
-
// Only point — strip just the literal.
|
|
388
|
-
}
|
|
389
|
-
else if (bestIndex === 0) {
|
|
390
|
-
const rest = lineText.substring(deleteEnd);
|
|
391
|
-
const commaMatch = rest.match(/^,\s*/);
|
|
392
|
-
if (commaMatch) {
|
|
393
|
-
deleteEnd += commaMatch[0].length;
|
|
516
|
+
if (bestIndex < 0) {
|
|
517
|
+
return null;
|
|
394
518
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
519
|
+
const pointNode = args.namedChildren[bestIndex];
|
|
520
|
+
let deleteStart = pointNode.startIndex;
|
|
521
|
+
let deleteEnd = pointNode.endIndex;
|
|
522
|
+
if (args.namedChildren.length > 1) {
|
|
523
|
+
if (bestIndex === 0) {
|
|
524
|
+
deleteEnd = consumeTrailingSeparator(code, deleteEnd);
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
deleteStart = consumeLeadingSeparator(code, deleteStart);
|
|
528
|
+
}
|
|
401
529
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
return { newCode: joinLines(lines) };
|
|
530
|
+
return spliceCode(code, deleteStart, deleteEnd, '');
|
|
531
|
+
});
|
|
405
532
|
}
|
|
406
|
-
export
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
}
|
|
421
|
-
const newArgs = points.map((p) => `[${p[0]}, ${p[1]}]`).join(', ');
|
|
422
|
-
lines[row] = lineText.slice(0, openParen + 1) + newArgs + lineText.slice(closeParen);
|
|
423
|
-
return { newCode: joinLines(lines) };
|
|
533
|
+
export function setPickPoints(code, sourceLine, points) {
|
|
534
|
+
return withParsedCode(code, (tree, lines) => {
|
|
535
|
+
const call = findEditableCallAt(tree, lines, sourceLine);
|
|
536
|
+
if (!call) {
|
|
537
|
+
return null;
|
|
538
|
+
}
|
|
539
|
+
const target = resolvePointEditTarget(call);
|
|
540
|
+
const args = getArgumentsNode(target);
|
|
541
|
+
if (!args) {
|
|
542
|
+
return null;
|
|
543
|
+
}
|
|
544
|
+
const newArgs = points.map((p) => `[${p[0]}, ${p[1]}]`).join(', ');
|
|
545
|
+
return spliceCode(code, args.startIndex + 1, args.endIndex - 1, newArgs);
|
|
546
|
+
});
|
|
424
547
|
}
|
|
@@ -4272,7 +4272,7 @@ void main() {
|
|
|
4272
4272
|
|
|
4273
4273
|
}
|
|
4274
4274
|
|
|
4275
|
-
`,extensions:{clipCullDistance:!1,multiDraw:!1}});super(a,o),this.frustumCulled=!1}},Bd={cameraMode:`orthographic`,showGrid:!0,sectionView:!0},Vd=new class{current={...Bd};listeners=new Set;update(e){Object.assign(this.current,e);for(let e of this.listeners)e(this.current)}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}};function Hd(e){Vd.update({showGrid:e.showGrid,cameraMode:e.cameraMode})}var Ud=new B(0,0,1),Wd=new B(50,-50,40),Gd=50;function Kd(e){return new B(e.x,e.y,e.z)}var qd=class{mode=`default`;cameraBackup=null;cameraBackupMode=null;enabled=!0;lastGridNormal=Ud.clone();lastGridPosition;_sectionPlane=null;constructor(e){this.ctx=e,this.setupDefaultAxes(),this.setupGrid(Ud),Vd.subscribe(()=>this.applyGridVisibility()),Pd(()=>this.rebuildGrid())}get currentMode(){return this.mode}get isSketchMode(){return this.mode===`sketch`}get sectionPlane(){return this._sectionPlane}set sketchEnabled(e){this.enabled=e}enterDefaultMode(){this.mode===`sketch`&&(this._sectionPlane=null,this.restoreCamera(),this.cameraBackupMode===`perspective`&&(this.ctx.switchCamera(`perspective`),Vd.update({cameraMode:`perspective`})),this.cameraBackupMode=null),this.mode=`default`,this.ctx.camera.up.copy(Un.DEFAULT_UP),this.ctx.cameraControls.updateCameraUp(),this.showDefaultAxes(),this.setupGrid(Ud)}enterSketchMode(e){if(!this.enabled)return;this.mode=`sketch`,Vd.current.cameraMode===`perspective`&&(this.cameraBackupMode=`perspective`,this.ctx.switchCamera(`orthographic`)),this.positionCameraForSketch(e),this.showSketchAxes(e);let t=Kd(e.normal),n=Kd(e.origin);this.setupGrid(t,n.add(t.clone().multiplyScalar(-.01))),this.createSectionPlane(e)}enforceSketchNormal(e){let t=this.ctx.cameraControls,n=Kd(e.normal),r=Kd(e.yDirection),i=new B;t.getTarget(i);let a=i.clone().add(n.clone().multiplyScalar(Gd));this.ctx.camera.up.copy(r),t.updateCameraUp(),t.normalizeRotations(),t.setLookAt(a.x,a.y,a.z,i.x,i.y,i.z,!1),t.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target,this.createSectionPlane(e)}positionCameraForSketch(e){let t=this.ctx.cameraControls;if(!this.cameraBackup){let e=new B,n=new B;t.getPosition(e),t.getTarget(n),this.cameraBackup={position:e,target:n}}let n=Kd(e.center),r=Kd(e.normal),i=Kd(e.yDirection),a=n.clone().add(r.clone().multiplyScalar(Gd));this.ctx.camera.up.copy(i),t.updateCameraUp(),t.normalizeRotations(),t.setLookAt(a.x,a.y,a.z,n.x,n.y,n.z,!1),t.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target}restoreCamera(){let e=this.ctx.cameraControls,t=this.cameraBackup,n=t?.position??Wd.clone(),r=t?.target??new B(0,0,0);this.ctx.camera.up.copy(Un.DEFAULT_UP),e.updateCameraUp(),e.normalizeRotations(),e.setLookAt(n.x,n.y,n.z,r.x,r.y,r.z,!1),e.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target,this.cameraBackup=null}setupDefaultAxes(){let e=new mo(1e3);e.name=`defaultAxesHelper`,this.ctx.scene.add(e)}showDefaultAxes(){this.removeByName(`sketchAxesHelper`);let e=this.ctx.scene.getObjectByName(`defaultAxesHelper`);e&&(e.visible=!0)}showSketchAxes(e){let t=this.ctx.scene.getObjectByName(`defaultAxesHelper`);t&&(t.visible=!1),this.removeByName(`sketchAxesHelper`);let n=new mo(1e3);n.name=`sketchAxesHelper`;let r=Kd(e.origin),i=Kd(e.xDirection),a=Kd(e.yDirection),o=Kd(e.normal),s=new gn().makeBasis(i,a,o);s.setPosition(r),n.matrix.copy(s),n.matrixAutoUpdate=!1,this.ctx.scene.add(n)}rebuildGrid(){this.setupGrid(this.lastGridNormal,this.lastGridPosition),this.ctx.requestRender()}setupGrid(e,t){this.lastGridNormal=e.clone(),this.lastGridPosition=t?.clone(),this.removeByName(`grid`);let n=new zd(10,100,Nd.gridColor,1e5,e);n.name=`grid`,t&&n.position.copy(t),n.visible=this.mode===`sketch`||Vd.current.showGrid,this.ctx.scene.add(n)}applyGridVisibility(){let e=this.ctx.scene.getObjectByName(`grid`);e&&(e.visible=this.mode===`sketch`||Vd.current.showGrid,this.ctx.requestRender())}createSectionPlane(e){let t=Kd(e.normal).negate(),n=Kd(e.origin).add(Kd(e.normal).multiplyScalar(.1));this._sectionPlane||=new Ai,this._sectionPlane.setFromNormalAndCoplanarPoint(t,n)}removeByName(e){let t=this.ctx.scene.getObjectByName(e);t&&this.ctx.scene.remove(t)}},Jd={color:``,lineWidth:1,opacity:1,depthWrite:!0},Yd=class extends ii{constructor(e,t={}){super();let n={...Jd,...t};for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let r=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new r(t.indices),1));let i=new qi(e,new Fi({color:n.color||Nd.edgeColor,linewidth:n.lineWidth,transparent:n.opacity<1,opacity:n.opacity,polygonOffset:!0,polygonOffsetFactor:2,polygonOffsetUnits:1,side:2,depthWrite:n.depthWrite,depthTest:n.depthWrite}));t.edgeIndex!==void 0&&(i.userData.edgeIndex=t.edgeIndex),this.add(i)}}},Xd={color:``,opacity:1},Zd=class extends ii{constructor(e,t={}){super();let n={...Xd,...t};for(let r of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(r.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(r.normals),3));let i=r.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new i(r.indices),1)),e.computeBoundingBox();let a=t?.color??r.color??`#`+Nd.faceColor.getHexString(),o=t?.color!==void 0||t?.opacity!==void 0,s=new G(e,new la({color:a,transparent:o||n.opacity<1,opacity:n.opacity,depthWrite:!o,polygonOffset:!0,polygonOffsetFactor:o?-1:1,polygonOffsetUnits:1,side:2}));r.faceMapping&&(s.userData.faceMapping=r.faceMapping),this.add(s)}}},Qd=class extends ii{constructor(e,t){super();for(let n of e.meshes)if(n.label===`solid-faces`){let e=new Zd({shapeType:`face`,meshes:[n]},t?.face);e.renderOrder=1,this.add(e)}else if(n.label===`solid-edges`){let e=new Yd({shapeType:`edge`,meshes:[n]},t?.edge);e.renderOrder=2,this.add(e)}}},$d=4,ef=1.5,tf=.6,nf=$d+ef+tf+ef,rf=`
|
|
4275
|
+
`,extensions:{clipCullDistance:!1,multiDraw:!1}});super(a,o),this.frustumCulled=!1}},Bd={cameraMode:`orthographic`,showGrid:!0,sectionView:!0},Vd=new class{current={...Bd};listeners=new Set;update(e){Object.assign(this.current,e);for(let e of this.listeners)e(this.current)}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}};function Hd(e){Vd.update({showGrid:e.showGrid,cameraMode:e.cameraMode})}var Ud=new B(0,0,1),Wd=new B(50,-50,40),Gd=50;function Kd(e){return new B(e.x,e.y,e.z)}var qd=class{mode=`default`;cameraBackup=null;cameraBackupMode=null;enabled=!0;lastGridNormal=Ud.clone();lastGridPosition;_sectionPlane=null;constructor(e){this.ctx=e,this.setupDefaultAxes(),this.setupGrid(Ud),Vd.subscribe(()=>this.applyGridVisibility()),Pd(()=>this.rebuildGrid())}get currentMode(){return this.mode}get isSketchMode(){return this.mode===`sketch`}get sectionPlane(){return this._sectionPlane}set sketchEnabled(e){this.enabled=e}enterDefaultMode(){this.mode===`sketch`&&(this._sectionPlane=null,this.restoreCamera(),this.cameraBackupMode===`perspective`&&(this.ctx.switchCamera(`perspective`),Vd.update({cameraMode:`perspective`})),this.cameraBackupMode=null),this.mode=`default`,this.ctx.camera.up.copy(Un.DEFAULT_UP),this.ctx.cameraControls.updateCameraUp(),this.showDefaultAxes(),this.setupGrid(Ud)}enterSketchMode(e){if(!this.enabled)return;this.mode=`sketch`,Vd.current.cameraMode===`perspective`&&(this.cameraBackupMode=`perspective`,this.ctx.switchCamera(`orthographic`)),this.positionCameraForSketch(e),this.showSketchAxes(e);let t=Kd(e.normal),n=Kd(e.origin);this.setupGrid(t,n.add(t.clone().multiplyScalar(-.01))),this.createSectionPlane(e)}enforceSketchNormal(e){let t=this.ctx.cameraControls,n=Kd(e.normal),r=Kd(e.yDirection),i=new B;t.getTarget(i);let a=i.clone().add(n.clone().multiplyScalar(Gd));this.ctx.camera.up.copy(r),t.updateCameraUp(),t.normalizeRotations(),t.setLookAt(a.x,a.y,a.z,i.x,i.y,i.z,!1),t.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target,this.showSketchAxes(e);let o=Kd(e.origin);this.setupGrid(n,o.add(n.clone().multiplyScalar(-.01))),this.createSectionPlane(e)}positionCameraForSketch(e){let t=this.ctx.cameraControls;if(!this.cameraBackup){let e=new B,n=new B;t.getPosition(e),t.getTarget(n),this.cameraBackup={position:e,target:n}}let n=Kd(e.center),r=Kd(e.normal),i=Kd(e.yDirection),a=n.clone().add(r.clone().multiplyScalar(Gd));this.ctx.camera.up.copy(i),t.updateCameraUp(),t.normalizeRotations(),t.setLookAt(a.x,a.y,a.z,n.x,n.y,n.z,!1),t.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target}restoreCamera(){let e=this.ctx.cameraControls,t=this.cameraBackup,n=t?.position??Wd.clone(),r=t?.target??new B(0,0,0);this.ctx.camera.up.copy(Un.DEFAULT_UP),e.updateCameraUp(),e.normalizeRotations(),e.setLookAt(n.x,n.y,n.z,r.x,r.y,r.z,!1),e.getTarget(this.ctx.controls.target),this.ctx.gizmo.target=this.ctx.controls.target,this.cameraBackup=null}setupDefaultAxes(){let e=new mo(1e3);e.name=`defaultAxesHelper`,this.ctx.scene.add(e)}showDefaultAxes(){this.removeByName(`sketchAxesHelper`);let e=this.ctx.scene.getObjectByName(`defaultAxesHelper`);e&&(e.visible=!0)}showSketchAxes(e){let t=this.ctx.scene.getObjectByName(`defaultAxesHelper`);t&&(t.visible=!1),this.removeByName(`sketchAxesHelper`);let n=new mo(1e3);n.name=`sketchAxesHelper`;let r=Kd(e.origin),i=Kd(e.xDirection),a=Kd(e.yDirection),o=Kd(e.normal),s=new gn().makeBasis(i,a,o);s.setPosition(r),n.matrix.copy(s),n.matrixAutoUpdate=!1,this.ctx.scene.add(n)}rebuildGrid(){this.setupGrid(this.lastGridNormal,this.lastGridPosition),this.ctx.requestRender()}setupGrid(e,t){this.lastGridNormal=e.clone(),this.lastGridPosition=t?.clone(),this.removeByName(`grid`);let n=new zd(10,100,Nd.gridColor,1e5,e);n.name=`grid`,t&&n.position.copy(t),n.visible=this.mode===`sketch`||Vd.current.showGrid,this.ctx.scene.add(n)}applyGridVisibility(){let e=this.ctx.scene.getObjectByName(`grid`);e&&(e.visible=this.mode===`sketch`||Vd.current.showGrid,this.ctx.requestRender())}createSectionPlane(e){let t=Kd(e.normal).negate(),n=Kd(e.origin).add(Kd(e.normal).multiplyScalar(.1));this._sectionPlane||=new Ai,this._sectionPlane.setFromNormalAndCoplanarPoint(t,n)}removeByName(e){let t=this.ctx.scene.getObjectByName(e);t&&this.ctx.scene.remove(t)}},Jd={color:``,lineWidth:1,opacity:1,depthWrite:!0},Yd=class extends ii{constructor(e,t={}){super();let n={...Jd,...t};for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let r=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new r(t.indices),1));let i=new qi(e,new Fi({color:n.color||Nd.edgeColor,linewidth:n.lineWidth,transparent:n.opacity<1,opacity:n.opacity,polygonOffset:!0,polygonOffsetFactor:2,polygonOffsetUnits:1,side:2,depthWrite:n.depthWrite,depthTest:n.depthWrite}));t.edgeIndex!==void 0&&(i.userData.edgeIndex=t.edgeIndex),this.add(i)}}},Xd={color:``,opacity:1},Zd=class extends ii{constructor(e,t={}){super();let n={...Xd,...t};for(let r of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(r.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(r.normals),3));let i=r.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new i(r.indices),1)),e.computeBoundingBox();let a=t?.color??r.color??`#`+Nd.faceColor.getHexString(),o=t?.color!==void 0||t?.opacity!==void 0,s=new G(e,new la({color:a,transparent:o||n.opacity<1,opacity:n.opacity,depthWrite:!o,polygonOffset:!0,polygonOffsetFactor:o?-1:1,polygonOffsetUnits:1,side:2}));r.faceMapping&&(s.userData.faceMapping=r.faceMapping),this.add(s)}}},Qd=class extends ii{constructor(e,t){super();for(let n of e.meshes)if(n.label===`solid-faces`){let e=new Zd({shapeType:`face`,meshes:[n]},t?.face);e.renderOrder=1,this.add(e)}else if(n.label===`solid-edges`){let e=new Yd({shapeType:`edge`,meshes:[n]},t?.edge);e.renderOrder=2,this.add(e)}}},$d=4,ef=1.5,tf=.6,nf=$d+ef+tf+ef,rf=`
|
|
4276
4276
|
attribute float lineDistance;
|
|
4277
4277
|
varying float vLineDistance;
|
|
4278
4278
|
|
|
@@ -4305,7 +4305,7 @@ void main() {
|
|
|
4305
4305
|
|
|
4306
4306
|
gl_FragColor = vec4(color, 1.0);
|
|
4307
4307
|
}
|
|
4308
|
-
`,of=class extends ii{constructor(e){super(),this.userData.isMetaShape=!0;for(let t of e.meshes){let e=t.vertices,n=t.indices,r=[];for(let t=0;t<n.length;t+=2){let i=n[t]*3;r.push(e[i],e[i+1],e[i+2])}if(n.length>=2){let t=n[n.length-1]*3;r.push(e[t],e[t+1],e[t+2])}let i=new Tr;i.setAttribute(`position`,new W(new Float32Array(r),3));let a=new Ui(i,new qr({uniforms:{color:{value:Nd.metaEdgeColor},dashLength:{value:$d},gapLength:{value:ef},dotLength:{value:tf},patternLength:{value:nf}},vertexShader:rf,fragmentShader:af,side:2,transparent:!0,polygonOffset:!0,polygonOffsetFactor:2,polygonOffsetUnits:1}));a.computeLineDistances(),this.add(a)}}},sf=`#2297ff`,cf=2,lf=class extends ii{constructor(e){super(),this.userData.isMetaShape=!0;for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let n=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new n(t.indices),1));let r=new qi(e,new Fi({color:sf,linewidth:cf,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0}));this.add(r)}}},uf=`#2297ff`,df=`#2297ff`,ff=.15,pf=.4,mf=class extends ii{constructor(e,t){super(),this.userData.isMetaShape=!0,this.userData.isPickRegion=!0,this.userData.isPickRegionSelected=t,e.metaData&&(this.userData.metaData=e.metaData);let n=t?df:uf,r=t?pf:ff;for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let i=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new i(t.indices),1)),e.computeBoundingBox();let a=new G(e,new dr({color:n,transparent:!0,opacity:r,side:2,depthWrite:!1,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1}));this.add(a)}}},hf=`#2297ff`,gf=2,_f=2,vf=16,yf=.003,bf=1.5,xf=1e-8;function Sf(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var Cf=class extends ii{constructor(e){super(),this.userData.isMetaShape=!0;let t=new Zi(_f,vf),n=new dr({color:hf,side:2,depthTest:!0}),r=[];for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let n=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new n(t.indices),1));let i=new Fi({color:hf,linewidth:gf,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0});this.add(new qi(e,i));let a=t.vertices,o=t.indices,s=new Map;for(let e of o)s.set(e,(s.get(e)||0)+1);for(let[e,t]of s)if(t===1){let t=new B(a[e*3],a[e*3+1],a[e*3+2]);r.some(e=>e.distanceToSquared(t)<xf)||r.push(t)}}for(let e of r){let r=new G(t,n);r.renderOrder=2;let i=new ii;i.renderOrder=2,i.userData.isVertexDot=!0,i.add(r),i.position.copy(e),r.onBeforeRender=(t,n,r)=>{i.scale.setScalar(Math.min(Sf(r,e,yf),bf)),i.updateMatrixWorld(!0)},this.add(i)}}},wf={color:`#2297ff`,lineWidth:2},Tf={trim:e=>new lf(e),"pick-edge":e=>new Cf(e)};function Ef(e){let t=e.metaType?Tf[e.metaType]:void 0;return t?t(e):new of(e)}var Df={"pick-region":e=>new mf(e,!1),"pick-region-selected":e=>new mf(e,!0)};function Of(e){let t=e.metaType?Df[e.metaType]:void 0;return t?t(e):new Zd(e)}var kf=class extends ii{constructor(e,t,n){if(super(),!e.sceneShapes)return;let r=e.sceneShapes.every(e=>e.isMetaShape||e.shapeType===`wire`||e.shapeType===`edge`),i=[`pick-region`,`pick-region-selected`,`pick-edge`];for(let a of e.sceneShapes){if(!t&&a.isMetaShape&&a.metaType&&i.includes(a.metaType))continue;let e;if(a.isMetaShape)switch(a.shapeType){case`wire`:case`edge`:e=Ef(a);break;case`face`:e=Of(a);break}else switch(a.shapeType){case`wire`:case`edge`:e=new Yd(a,n?.edge??(r?wf:void 0));break;case`face`:e=new Zd(a,n?.face);break;case`solid`:e=new Qd(a,n);break}e&&(a.shapeId&&(e.userData.shapeId=a.shapeId),this.add(e))}}};function Af(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var jf=`#2297ff`,Mf=2,Nf=16,Pf=.003,Ff=1.5,If=15954511,Lf=64,Rf=3,zf=15954511,Bf=.35,Vf=.6,Hf=18,Uf=5,Wf=2.5,Gf=class extends ii{constructor(e,t,n,r){super(),this.buildEdges(e,t),this.buildVertices(e,t,r),n&&e.id===n&&(this.buildCursor(e,r),this.buildTangentArrow(e,r))}buildEdges(e,t){for(let n of t)if(!(n.parentId!==e.id||!n.sceneShapes.length))for(let e of n.sceneShapes){if(e.isMetaShape||e.isGuide){if(e.shapeType===`wire`||e.shapeType===`edge`){let t=Ef(e);e.shapeId&&(t.userData.shapeId=e.shapeId),this.add(t)}continue}let t=new Yd(e,{color:jf,lineWidth:2});e.shapeId&&(t.userData.shapeId=e.shapeId),this.add(t)}}buildVertices(e,t,n){let r=e.object?.plane?.normal,i=[];for(let n of t)if(!(n.parentId!==e.id||!n.sceneShapes.length)){for(let e of n.sceneShapes)if(!(e.isMetaShape||e.isGuide))for(let t of e.meshes){if(!t.indices.length)continue;let e=new Map;for(let n of t.indices)e.set(n,(e.get(n)||0)+1);for(let[n,r]of e)r===1&&i.push(new B(t.vertices[n*3],t.vertices[n*3+1],t.vertices[n*3+2]))}}let a=[];for(let e of i)a.some(t=>t.distanceToSquared(e)<1e-12)||a.push(e);let o=new Zi(Mf,Nf),s=new dr({color:jf,side:2,depthTest:!1});for(let e of a){let t=new G(o,s);t.renderOrder=2;let i=new ii;i.renderOrder=2,i.userData.isVertexDot=!0,i.add(t),i.position.copy(e),r&&i.lookAt(new B(e.x+r.x,e.y+r.y,e.z+r.z)),i.scale.setScalar(Math.min(Af(n,e,Pf),Ff)),t.onBeforeRender=(t,n,r)=>{i.scale.setScalar(Math.min(Af(r,e,Pf),Ff)),i.updateMatrixWorld(!0)},this.add(i)}}buildCursor(e,t){let n=e.object?.currentPosition;if(!n)return;let r=new Zi(Rf,Lf),i=new dr({color:If,side:2,depthTest:!1});i.transparent=!0,i.opacity=.8;let a=new G(r,i);a.renderOrder=1;let o=new ii;o.renderOrder=1,o.add(a),o.position.set(n.x,n.y,n.z);let s=e.object?.plane?.normal;if(s){let e=new B(n.x+s.x,n.y+s.y,n.z+s.z);o.lookAt(e)}o.scale.setScalar(Af(t,o.position,.003)),a.onBeforeRender=(e,t,n)=>{o.scale.setScalar(Af(n,o.position,.003)),o.updateMatrixWorld(!0)},this.add(o)}buildTangentArrow(e,t){let n=e.object?.currentPosition,r=e.object?.currentTangent,i=e.object?.plane?.origin;if(!n||!r||!i)return;let a=new B(r.x-i.x,r.y-i.y,r.z-i.z).normalize(),o=new dr({color:zf,transparent:!0,opacity:Bf,depthTest:!1}),s=new Qi(Vf,Vf,Hf,
|
|
4308
|
+
`,of=class extends ii{constructor(e){super(),this.userData.isMetaShape=!0;for(let t of e.meshes){let e=t.vertices,n=t.indices,r=[];for(let t=0;t<n.length;t+=2){let i=n[t]*3;r.push(e[i],e[i+1],e[i+2])}if(n.length>=2){let t=n[n.length-1]*3;r.push(e[t],e[t+1],e[t+2])}let i=new Tr;i.setAttribute(`position`,new W(new Float32Array(r),3));let a=new Ui(i,new qr({uniforms:{color:{value:Nd.metaEdgeColor},dashLength:{value:$d},gapLength:{value:ef},dotLength:{value:tf},patternLength:{value:nf}},vertexShader:rf,fragmentShader:af,side:2,transparent:!0,polygonOffset:!0,polygonOffsetFactor:2,polygonOffsetUnits:1}));a.computeLineDistances(),this.add(a)}}},sf=`#2297ff`,cf=2,lf=class extends ii{constructor(e){super(),this.userData.isMetaShape=!0;for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let n=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new n(t.indices),1));let r=new qi(e,new Fi({color:sf,linewidth:cf,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0}));this.add(r)}}},uf=`#2297ff`,df=`#2297ff`,ff=.15,pf=.4,mf=class extends ii{constructor(e,t){super(),this.userData.isMetaShape=!0,this.userData.isPickRegion=!0,this.userData.isPickRegionSelected=t,e.metaData&&(this.userData.metaData=e.metaData);let n=t?df:uf,r=t?pf:ff;for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let i=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new i(t.indices),1)),e.computeBoundingBox();let a=new G(e,new dr({color:n,transparent:!0,opacity:r,side:2,depthWrite:!1,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1}));this.add(a)}}},hf=`#2297ff`,gf=2,_f=2,vf=16,yf=.003,bf=1.5,xf=1e-8;function Sf(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var Cf=class extends ii{constructor(e){super(),this.userData.isMetaShape=!0;let t=new Zi(_f,vf),n=new dr({color:hf,side:2,depthTest:!0}),r=[];for(let t of e.meshes){let e=new Tr;e.setAttribute(`position`,new W(new Float32Array(t.vertices),3)),e.setAttribute(`normal`,new W(new Float32Array(t.normals),3));let n=t.vertices.length/3>65535?Uint32Array:Uint16Array;e.setIndex(new W(new n(t.indices),1));let i=new Fi({color:hf,linewidth:gf,polygonOffset:!0,polygonOffsetFactor:-1,polygonOffsetUnits:-1,side:2,depthWrite:!0,depthTest:!0});this.add(new qi(e,i));let a=t.vertices,o=t.indices,s=new Map;for(let e of o)s.set(e,(s.get(e)||0)+1);for(let[e,t]of s)if(t===1){let t=new B(a[e*3],a[e*3+1],a[e*3+2]);r.some(e=>e.distanceToSquared(t)<xf)||r.push(t)}}for(let e of r){let r=new G(t,n);r.renderOrder=2;let i=new ii;i.renderOrder=2,i.userData.isVertexDot=!0,i.add(r),i.position.copy(e),r.onBeforeRender=(t,n,r)=>{i.scale.setScalar(Math.min(Sf(r,e,yf),bf)),i.updateMatrixWorld(!0)},this.add(i)}}},wf={color:`#2297ff`,lineWidth:2},Tf={trim:e=>new lf(e),"pick-edge":e=>new Cf(e)};function Ef(e){let t=e.metaType?Tf[e.metaType]:void 0;return t?t(e):new of(e)}var Df={"pick-region":e=>new mf(e,!1),"pick-region-selected":e=>new mf(e,!0)};function Of(e){let t=e.metaType?Df[e.metaType]:void 0;return t?t(e):new Zd(e)}var kf=class extends ii{constructor(e,t,n){if(super(),!e.sceneShapes)return;let r=e.sceneShapes.every(e=>e.isMetaShape||e.shapeType===`wire`||e.shapeType===`edge`),i=[`pick-region`,`pick-region-selected`,`pick-edge`];for(let a of e.sceneShapes){if(!t&&a.isMetaShape&&a.metaType&&i.includes(a.metaType))continue;let e;if(a.isMetaShape)switch(a.shapeType){case`wire`:case`edge`:e=Ef(a);break;case`face`:e=Of(a);break}else switch(a.shapeType){case`wire`:case`edge`:e=new Yd(a,n?.edge??(r?wf:void 0));break;case`face`:e=new Zd(a,n?.face);break;case`solid`:e=new Qd(a,n);break}e&&(a.shapeId&&(e.userData.shapeId=a.shapeId),this.add(e))}}};function Af(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var jf=`#2297ff`,Mf=2,Nf=16,Pf=.003,Ff=1.5,If=15954511,Lf=64,Rf=3,zf=15954511,Bf=.35,Vf=.6,Hf=18,Uf=5,Wf=2.5,Gf=class extends ii{constructor(e,t,n,r){super(),this.buildEdges(e,t),this.buildVertices(e,t,r),n&&e.id===n&&(this.buildCursor(e,r),this.buildTangentArrow(e,r))}buildEdges(e,t){for(let n of t)if(!(n.parentId!==e.id||!n.sceneShapes.length))for(let e of n.sceneShapes){if(e.isMetaShape||e.isGuide){if(e.shapeType===`wire`||e.shapeType===`edge`){let t=Ef(e);e.shapeId&&(t.userData.shapeId=e.shapeId),this.add(t)}continue}let t=new Yd(e,{color:jf,lineWidth:2});e.shapeId&&(t.userData.shapeId=e.shapeId),this.add(t)}}buildVertices(e,t,n){let r=e.object?.plane?.normal,i=[];for(let n of t)if(!(n.parentId!==e.id||!n.sceneShapes.length)){for(let e of n.sceneShapes)if(!(e.isMetaShape||e.isGuide))for(let t of e.meshes){if(!t.indices.length)continue;let e=new Map;for(let n of t.indices)e.set(n,(e.get(n)||0)+1);for(let[n,r]of e)r===1&&i.push(new B(t.vertices[n*3],t.vertices[n*3+1],t.vertices[n*3+2]))}}let a=[];for(let e of i)a.some(t=>t.distanceToSquared(e)<1e-12)||a.push(e);let o=new Zi(Mf,Nf),s=new dr({color:jf,side:2,depthTest:!1});for(let e of a){let t=new G(o,s);t.renderOrder=2;let i=new ii;i.renderOrder=2,i.userData.isVertexDot=!0,i.add(t),i.position.copy(e),r&&i.lookAt(new B(e.x+r.x,e.y+r.y,e.z+r.z)),i.scale.setScalar(Math.min(Af(n,e,Pf),Ff)),t.onBeforeRender=(t,n,r)=>{i.scale.setScalar(Math.min(Af(r,e,Pf),Ff)),i.updateMatrixWorld(!0)},this.add(i)}}buildCursor(e,t){let n=e.object?.currentPosition;if(!n)return;let r=new Zi(Rf,Lf),i=new dr({color:If,side:2,depthTest:!1});i.transparent=!0,i.opacity=.8;let a=new G(r,i);a.renderOrder=1;let o=new ii;o.renderOrder=1,o.add(a),o.position.set(n.x,n.y,n.z);let s=e.object?.plane?.normal;if(s){let e=new B(n.x+s.x,n.y+s.y,n.z+s.z);o.lookAt(e)}o.scale.setScalar(Af(t,o.position,.003)),a.onBeforeRender=(e,t,n)=>{o.scale.setScalar(Af(n,o.position,.003)),o.updateMatrixWorld(!0)},this.add(o)}buildTangentArrow(e,t){let n=e.object?.currentPosition,r=e.object?.currentTangent,i=e.object?.plane?.origin;if(!n||!r||!i)return;let a=new B(r.x-i.x,r.y-i.y,r.z-i.z).normalize(),o=new dr({color:zf,transparent:!0,opacity:Bf,side:2,depthTest:!1,depthWrite:!1}),s=new Qi(Vf,Vf,Hf,16);s.translate(0,Hf/2,0);let c=new G(s,o),l=new $i(Wf,Uf,16);l.translate(0,Hf+Uf/2,0);let u=new G(l,o),d=new ii;d.renderOrder=1,d.add(c),d.add(u);let f=new B(0,1,0),p=new mt().setFromUnitVectors(f,a);d.quaternion.copy(p),d.position.set(n.x,n.y,n.z),d.scale.setScalar(Af(t,d.position,.003)),c.onBeforeRender=(e,t,n)=>{d.scale.setScalar(Af(n,d.position,.003)),d.updateMatrixWorld(!0)},this.add(d)}};function Kf(e,t,n){if(e instanceof Pa)return(e.top-e.bottom)/e.zoom*n;if(e instanceof Qr){let r=e.position.distanceTo(t),i=e.fov*Math.PI/180;return 2*r*Math.tan(i/2)*n}return 1}var qf=`#ffc26c`,Jf=`#c88f40`,Yf=`#c88f40`,Xf=.1,Zf=20,Qf=3,$f=1.5,ep=.4,tp=class extends ii{constructor(e,t){super();let n=e.sceneShapes[0]?.meshes[0];if(!n)return;this.userData.isMetaShape=!0,this.userData.isConstructionPlane=!0;let r=e.object.normal,i=e.object.center,a=new Tr;a.setAttribute(`position`,new W(new Float32Array(n.vertices),3)),a.setAttribute(`normal`,new W(new Float32Array(n.normals),3)),a.setIndex(new W(new Uint16Array(n.indices),1)),a.computeBoundingBox();let o=new G(a,new dr({color:qf,transparent:!0,opacity:Xf,side:2,polygonOffset:!0,polygonOffsetFactor:1,polygonOffsetUnits:1}));this.add(o);let s=new qi(new ia(a,18),new Fi({color:Jf,linewidth:1}));this.add(s);let c=new B(r.x,r.y,r.z).normalize(),l=new B(i.x,i.y,i.z),u=new dr({color:Yf}),d=Zf-Qf,f=new Qi(ep,ep,d,8);f.translate(0,d/2,0);let p=new G(f,u),m=new $i($f,Qf,8);m.translate(0,d+Qf/2,0);let h=new G(m,u),g=new ii;g.add(p),g.add(h);let _=new B(0,1,0),v=new mt().setFromUnitVectors(_,c);g.quaternion.copy(v),g.position.copy(l),g.scale.setScalar(Kf(t,g.position,.006)),p.onBeforeRender=(e,t,n)=>{g.scale.setScalar(Kf(n,g.position,.006)),g.updateMatrixWorld(!0)},this.add(g),this.position.z=.01}},np=`#c88f40`,rp=class extends ii{constructor(e){super();let t=e.sceneShapes[0]?.meshes[0];if(!t)return;let n=new Tr;n.setAttribute(`position`,new W(new Float32Array(t.vertices),3));let r=new qi(n,new fa({color:np,dashSize:5,gapSize:5}));r.computeLineDistances(),this.add(r)}},ip={edge:{color:`#11a4ed`,lineWidth:3,depthWrite:!1},face:{color:`#5c9fcc`,opacity:1}},ap={edge:{opacity:.3},face:{opacity:.3}};function op(e,t,n,r){if(r)return r;if(e===`select`)return ip;if(t&&n!==`sketch`)return ap}function sp(e,t,n,r,i,a){switch(e.type){case`sketch`:return new Gf(e,t,n,r);case`plane`:return new tp(e,r);case`axis`:return new rp(e)}let o=e.uniqueType===`select`,s=op(e.uniqueType,n,e.type,a),c=t.filter(t=>t.parentId===e.id),l;if(c.length>0){let e=new ii;for(let a of c)e.add(sp(a,t,n,r,i,s));l=e}else l=new kf(e,i,s);return o&&l.traverse(e=>{e.renderOrder=999}),l}function cp(e,t,n,r=!1){let i=new ii;i.name=`compiledMesh`;for(let a of e)a.parentId||!a.visible&&!(t&&a.type===`sketch`)||i.add(sp(a,e,t,n,r));let a=new Map,o=0;for(let t of e)if(t.sceneShapes)for(let e of t.sceneShapes)e.isMetaShape||(e.shapeId&&a.set(e.shapeId,o),o++);return i.traverse(e=>{let t=e.userData.shapeId;t&&a.has(t)&&(e.userData.shapeIndex=a.get(t))}),i}var lp=`/api/preferences`;async function up(){try{let e=await fetch(lp);return e.ok?await e.json():null}catch{return null}}function dp(e,t){fetch(lp,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({[e]:t})}).catch(()=>{})}var fp=`<svg
|
|
4309
4309
|
xmlns="http://www.w3.org/2000/svg"
|
|
4310
4310
|
width="24"
|
|
4311
4311
|
height="24"
|
|
@@ -4871,11 +4871,11 @@ void main() {
|
|
|
4871
4871
|
<div class="h-4 w-px bg-base-content/10"></div>
|
|
4872
4872
|
<label class="flex items-center gap-1.5 cursor-pointer">
|
|
4873
4873
|
<input type="checkbox" class="checkbox checkbox-xs checkbox-primary" data-snap="vertex" checked />
|
|
4874
|
-
<span class="text-xs">
|
|
4874
|
+
<span class="text-xs">Snap to vertices</span>
|
|
4875
4875
|
</label>
|
|
4876
4876
|
<label class="flex items-center gap-1.5 cursor-pointer">
|
|
4877
4877
|
<input type="checkbox" class="checkbox checkbox-xs checkbox-primary" data-snap="grid" checked />
|
|
4878
|
-
<span class="text-xs">
|
|
4878
|
+
<span class="text-xs">Snap to grid</span>
|
|
4879
4879
|
</label>
|
|
4880
4880
|
</div>
|
|
4881
4881
|
`,yh.appendChild(lg),lg.querySelector(`[data-snap="vertex"]`).addEventListener(`change`,e=>{ug&&(ug.snapController.snapToVertices=e.target.checked)}),lg.querySelector(`[data-snap="grid"]`).addEventListener(`change`,e=>{ug&&(ug.snapController.snapToGrid=e.target.checked)});var ug=null,dg=null;function fg(e){let t=null;for(let n=e.length-1;n>=0;n--)if(bh(e[n],e)){t=e[n];break}if(!t||t.type!==`sketch`||!t.id)return!1;for(let n=e.length-1;n>=0;n--)if(e[n].parentId===t.id)return e[n].type===`bezier`;return!1}function pg(e,t){for(let n=e.length-1;n>=0;n--){let r=e[n];if(r.parentId===t&&r.type===`bezier`){let e=r.object?.startPoint,t=r.object?.resolvedPoints;return e?[e,...t||[]]:[]}}return[]}function mg(e){let t=null;for(let n=e.length-1;n>=0;n--)if(bh(e[n],e)){t=e[n];break}let n=t?.type===`sketch`?t:null;if(!n||!n.id||!n.object?.plane){hg();return}let r=null;for(let t=e.length-1;t>=0;t--)if(e[t].parentId===n.id){r=e[t];break}if(!r||r.type!==`bezier`||!r.sourceLocation){hg();return}let i=r.sourceLocation.line,a=n.object.plane,o=pg(e,n.id),s=_h.fromSceneObjects(e,n.id,a);if(ug&&dg===i){ug.updateExistingPoles(o),ug.snapController.updateSnapManager(s);return}hg();let c=r.sourceLocation,l=new vh(s,a),u=lg.querySelector(`[data-snap="vertex"]`),d=lg.querySelector(`[data-snap="grid"]`);u&&(l.snapToVertices=u.checked),d&&(l.snapToGrid=d.checked),ug=new dh($.sceneContext,a,l,o,e=>{fetch(`/api/insert-point`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({point:e,sourceLocation:c})})},e=>{fetch(`/api/set-pick-points`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({points:e,sourceLocation:c})})}),dg=i,ug.activate(),lg.classList.remove(`hidden`)}function hg(){ug&&(ug.deactivate(),ug=null,dg=null),lg.classList.add(`hidden`)}var gg=document.createElement(`div`);gg.className=`absolute bottom-6 left-6 z-[100]`,gg.innerHTML=`
|
package/ui/dist/index.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
6
|
<title>FluidCAD Viewer</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/index-
|
|
7
|
+
<script type="module" crossorigin src="/assets/index-BeLxRMCv.js"></script>
|
|
8
8
|
<link rel="stylesheet" crossorigin href="/assets/index-gPoNOiIs.css">
|
|
9
9
|
</head>
|
|
10
10
|
<body class="m-0 p-0 overflow-hidden w-full h-full bg-base-100 text-base-content">
|