copper3d 3.6.6 → 3.6.8

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.
@@ -22,6 +22,7 @@ export interface Annotation {
22
22
  label: string;
23
23
  color: string;
24
24
  closed: boolean;
25
+ visible: boolean;
25
26
  vertices: AnnotationVertex[];
26
27
  object3D: THREE.Object3D | null;
27
28
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/Utils/surfaceAnnotation/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAuC/B,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;AAEjC,sGAAsG;AACtG,MAAM,UAAU,qBAAqB,CACnC,CAAa,EACb,IAAgB;IAEhB,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,CAAC;IACrC,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;IACjE,OAAO;QACL,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,EAAE,EAAE,EAAE,CAAC,CAAC;QACR,EAAE,EAAE,EAAE,CAAC,CAAC;QACR,EAAE,EAAE,EAAE,CAAC,CAAC;QACR,SAAS,EAAE,CAAC,CAAC,SAAS;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;AAEhC,oEAAoE;AACpE,MAAM,UAAU,kBAAkB,CAChC,CAAmB,EACnB,IAAgB;IAEhB,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1E,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC;IAC5E,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/Utils/surfaceAnnotation/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAwC/B,MAAM,IAAI,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;AAEjC,sGAAsG;AACtG,MAAM,UAAU,qBAAqB,CACnC,CAAa,EACb,IAAgB;IAEhB,MAAM,EAAE,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,EAAE,CAAC;IACrC,MAAM,EAAE,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;IACjE,OAAO;QACL,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,CAAC,EAAE,EAAE,CAAC,CAAC;QACP,EAAE,EAAE,EAAE,CAAC,CAAC;QACR,EAAE,EAAE,EAAE,CAAC,CAAC;QACR,EAAE,EAAE,EAAE,CAAC,CAAC;QACR,SAAS,EAAE,CAAC,CAAC,SAAS;KACvB,CAAC;AACJ,CAAC;AAED,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;AAEhC,oEAAoE;AACpE,MAAM,UAAU,kBAAkB,CAChC,CAAmB,EACnB,IAAgB;IAEhB,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1E,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,CAAC;IAC5E,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAClB,CAAC"}
@@ -49752,8 +49752,11 @@ class baseScene extends commonScene {
49752
49752
  this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
49753
49753
  };
49754
49754
  this.renderer = renderer;
49755
- this.ambientLight = new AmbientLight(0x606060, 0.8);
49756
- this.directionalLight = new DirectionalLight(0xffffff, 1.0);
49755
+ // three r165+ removed `useLegacyLights`; lighting is always physically
49756
+ // correct now, which makes the same intensity ~1/PI as dim as the old
49757
+ // (three <=0.150) legacy default. Scale by PI to keep the prior brightness.
49758
+ this.ambientLight = new AmbientLight(0x606060, 0.8 * Math.PI);
49759
+ this.directionalLight = new DirectionalLight(0xffffff, 1.0 * Math.PI);
49757
49760
  if (!(opt === null || opt === void 0 ? void 0 : opt.alpha)) {
49758
49761
  this.vignette = createBackground({
49759
49762
  aspect: this.container.clientWidth / this.container.clientHeight,
@@ -49838,7 +49841,7 @@ class baseScene extends commonScene {
49838
49841
  }
49839
49842
  addLights() {
49840
49843
  // Hemisphere light: sky/ground for broad ambient fill
49841
- const hemiLight = new HemisphereLight(0xddeeff, 0x0f0e0d, 0.6);
49844
+ const hemiLight = new HemisphereLight(0xddeeff, 0x0f0e0d, 0.6 * Math.PI);
49842
49845
  hemiLight.name = "hemi_light";
49843
49846
  this.scene.add(hemiLight);
49844
49847
  // Main key light — front-right, slightly above
@@ -49848,12 +49851,12 @@ class baseScene extends commonScene {
49848
49851
  this.camera.add(this.ambientLight);
49849
49852
  this.camera.add(this.directionalLight);
49850
49853
  // Fill light — opposite side to soften shadows
49851
- const fillLight = new DirectionalLight(0xffffff, 0.4);
49854
+ const fillLight = new DirectionalLight(0xffffff, 0.4 * Math.PI);
49852
49855
  fillLight.name = "fill_light";
49853
49856
  fillLight.position.set(-0.5, -0.2, -0.866);
49854
49857
  this.camera.add(fillLight);
49855
49858
  // Top light — illuminates the top surface that key/fill lights miss
49856
- const topLight = new DirectionalLight(0xffffff, 0.5);
49859
+ const topLight = new DirectionalLight(0xffffff, 0.5 * Math.PI);
49857
49860
  topLight.name = "top_light";
49858
49861
  topLight.position.set(0, 1, 0.2);
49859
49862
  this.camera.add(topLight);
@@ -61165,6 +61168,15 @@ class MeshGraph {
61165
61168
  const nm = new Matrix3().getNormalMatrix(mesh.matrixWorld);
61166
61169
  return n.applyMatrix3(nm).normalize();
61167
61170
  }
61171
+ /** Vertex local normal at index i (reads from the welded graphGeo normal attribute). */
61172
+ vertexNormalLocal(i) {
61173
+ return new Vector3(this.normals ? this.normals[i * 3] : 0, this.normals ? this.normals[i * 3 + 1] : 0, this.normals ? this.normals[i * 3 + 2] : 1);
61174
+ }
61175
+ /** Normal at the vertex nearest to localPoint (for recovering normals from imported point coordinates). */
61176
+ nearestNormalLocal(p) {
61177
+ const i = this.nearestVertex(p);
61178
+ return this.vertexNormalLocal(i);
61179
+ }
61168
61180
  /** Vertex local coordinates + local normal (the graph geometry is already local space). */
61169
61181
  vertexLocal(i) {
61170
61182
  return {
@@ -61390,6 +61402,13 @@ class AnnotationStore {
61390
61402
  this.notify();
61391
61403
  }
61392
61404
  }
61405
+ setVisible(id, visible) {
61406
+ const a = this.get(id);
61407
+ if (a) {
61408
+ a.visible = visible;
61409
+ this.notify();
61410
+ }
61411
+ }
61393
61412
  toJSON(modelName, mesh, opts = {}) {
61394
61413
  var _a;
61395
61414
  const space = (_a = opts.space) !== null && _a !== void 0 ? _a : "local";
@@ -61414,6 +61433,7 @@ class AnnotationStore {
61414
61433
  label: a.label,
61415
61434
  color: a.color,
61416
61435
  closed: a.closed,
61436
+ visible: a.visible,
61417
61437
  points: a.vertices.map(toPt),
61418
61438
  })),
61419
61439
  };
@@ -61433,6 +61453,10 @@ class SurfaceAnnotator {
61433
61453
  var _a, _b, _c;
61434
61454
  this.mode = "navigate";
61435
61455
  this.spaceHeld = false;
61456
+ this.drawLock = false;
61457
+ this.armed = "freehand";
61458
+ this.spaceDownAt = 0;
61459
+ this.spaceDragged = false;
61436
61460
  this.pointerDown = false;
61437
61461
  this.store = new AnnotationStore();
61438
61462
  this.managed = new Set();
@@ -61459,14 +61483,18 @@ class SurfaceAnnotator {
61459
61483
  (this.activeGeoLine.material.resolution.set(w, h));
61460
61484
  };
61461
61485
  this.onPointerDown = (e) => {
61462
- if (this.spaceHeld)
61463
- return;
61464
61486
  if (e.button !== 0)
61465
61487
  return; // left button only
61466
61488
  if (!this.insideContainer(e))
61467
61489
  return;
61468
61490
  this.pointerDown = true;
61469
- if (this.mode === "point") {
61491
+ // Only act with the armed tool when in drawing mode (drawLock or spaceHeld).
61492
+ // When not drawing, navigation is the default — pointer events go to camera controls.
61493
+ if (!this.drawing)
61494
+ return;
61495
+ // Use armed tool (not this.mode which may be "navigate")
61496
+ const activeTool = this.armed;
61497
+ if (activeTool === "point") {
61470
61498
  const h = this.hit(e);
61471
61499
  if (!h)
61472
61500
  return;
@@ -61480,13 +61508,14 @@ class SurfaceAnnotator {
61480
61508
  label: `Point ${this.seq}`,
61481
61509
  color: this.pointColorVal,
61482
61510
  closed: false,
61511
+ visible: true,
61483
61512
  vertices: [v],
61484
61513
  object3D: marker,
61485
61514
  };
61486
61515
  this.store.add(ann);
61487
61516
  return;
61488
61517
  }
61489
- if (this.mode === "freehand") {
61518
+ if (activeTool === "freehand") {
61490
61519
  this.activeStroke = new StrokeContour(this.minGap, this.maxJump, this.o.mesh);
61491
61520
  this.activeStroke.begin();
61492
61521
  const h = this.hit(e);
@@ -61496,7 +61525,7 @@ class SurfaceAnnotator {
61496
61525
  this.o.scene.add(this.activeLine);
61497
61526
  return;
61498
61527
  }
61499
- if (this.mode === "geodesic") {
61528
+ if (activeTool === "geodesic") {
61500
61529
  // First check whether an existing anchor was clicked → cancel that point (any point can be canceled).
61501
61530
  const pick = this.pickGeoMarker(e);
61502
61531
  if (pick >= 0 && this.activeGeo) {
@@ -61523,15 +61552,26 @@ class SurfaceAnnotator {
61523
61552
  }
61524
61553
  };
61525
61554
  this.onPointerMove = (e) => {
61526
- if (this.spaceHeld) {
61527
- this.setGeoHover(-1);
61555
+ // Track if user dragged while space was held (so a hold-drag is not treated as a tap).
61556
+ if (this.spaceHeld && this.pointerDown) {
61557
+ this.spaceDragged = true;
61558
+ }
61559
+ // When not drawing, navigation is default — don't interfere with camera controls.
61560
+ if (!this.drawing) {
61561
+ // In geodesic mode we can still show the hover hint when not drawing.
61562
+ if (this.armed === "geodesic" && !this.pointerDown) {
61563
+ this.setGeoHover(this.insideContainer(e) ? this.pickGeoMarker(e) : -1);
61564
+ }
61565
+ else {
61566
+ this.setGeoHover(-1);
61567
+ }
61528
61568
  return;
61529
61569
  }
61530
- // In geodesic mode, show the "✕" hint when hovering an anchor sphere (that point can be clicked to cancel).
61531
- if (this.mode === "geodesic" && !this.pointerDown) {
61570
+ // Drawing mode: geodesic hover hint
61571
+ if (this.armed === "geodesic" && !this.pointerDown) {
61532
61572
  this.setGeoHover(this.insideContainer(e) ? this.pickGeoMarker(e) : -1);
61533
61573
  }
61534
- if (this.mode === "freehand" &&
61574
+ if (this.armed === "freehand" &&
61535
61575
  this.pointerDown &&
61536
61576
  this.activeStroke &&
61537
61577
  this.activeLine) {
@@ -61556,6 +61596,7 @@ class SurfaceAnnotator {
61556
61596
  label: `Contour ${this.seq}`,
61557
61597
  color: this.freehandColor,
61558
61598
  closed: false,
61599
+ visible: true,
61559
61600
  vertices: verts,
61560
61601
  object3D: this.activeLine,
61561
61602
  };
@@ -61573,11 +61614,17 @@ class SurfaceAnnotator {
61573
61614
  if (this.isTypingTarget(e))
61574
61615
  return;
61575
61616
  if (e.code === "Space") {
61617
+ if (!this.spaceHeld) {
61618
+ this.spaceDownAt = performance.now();
61619
+ this.spaceDragged = false;
61620
+ }
61576
61621
  this.spaceHeld = true;
61577
61622
  this.applyCameraGating();
61623
+ e.preventDefault();
61578
61624
  return;
61579
61625
  }
61580
61626
  if (e.key === "Escape") {
61627
+ this.drawLock = false;
61581
61628
  this.setMode("navigate");
61582
61629
  return;
61583
61630
  }
@@ -61610,7 +61657,11 @@ class SurfaceAnnotator {
61610
61657
  };
61611
61658
  this.onKeyUp = (e) => {
61612
61659
  if (e.code === "Space") {
61660
+ const held = performance.now() - this.spaceDownAt;
61613
61661
  this.spaceHeld = false;
61662
+ if (held <= SurfaceAnnotator.TAP_MS && !this.spaceDragged) {
61663
+ this.drawLock = !this.drawLock; // tap toggles lock
61664
+ }
61614
61665
  this.applyCameraGating();
61615
61666
  }
61616
61667
  };
@@ -61666,6 +61717,10 @@ class SurfaceAnnotator {
61666
61717
  if (m !== "geodesic" && this.activeGeo)
61667
61718
  this.clearActiveGeo();
61668
61719
  this.mode = m;
61720
+ // Record armed tool when choosing a drawing mode (not navigate).
61721
+ // Camera gating is NOT changed here — the user must use Space to enter drawing.
61722
+ if (m !== "navigate")
61723
+ this.armed = m;
61669
61724
  this.applyCameraGating();
61670
61725
  (_b = (_a = this.o).onModeChange) === null || _b === void 0 ? void 0 : _b.call(_a, m);
61671
61726
  }
@@ -61728,10 +61783,92 @@ class SurfaceAnnotator {
61728
61783
  exportJSON(modelName, opts) {
61729
61784
  return this.store.toJSON(modelName, this.o.mesh, opts);
61730
61785
  }
61786
+ setVisible(id, visible) {
61787
+ this.store.setVisible(id, visible);
61788
+ }
61789
+ /**
61790
+ * Rebuild annotations from an exported payload (local-space points). Normals are taken from the
61791
+ * point when present ([x,y,z,nx,ny,nz]); otherwise recovered from the welded graph's nearest
61792
+ * vertex. Each imported item becomes first-class (select/recolor/hide/delete/export).
61793
+ */
61794
+ importAnnotations(payload) {
61795
+ var _a, _b, _c, _d;
61796
+ let count = 0;
61797
+ let maxImported = this.seq;
61798
+ for (const a of (_a = payload.annotations) !== null && _a !== void 0 ? _a : []) {
61799
+ const verts = a.points.map((p) => {
61800
+ const [x, y, z] = p;
61801
+ let nx = p[3], ny = p[4], nz = p[5];
61802
+ if (nx === undefined || ny === undefined || nz === undefined) {
61803
+ const nrm = this.graph.nearestNormalLocal(new Vector3(x, y, z));
61804
+ nx = nrm.x;
61805
+ ny = nrm.y;
61806
+ nz = nrm.z;
61807
+ }
61808
+ return { x, y, z, nx, ny, nz, faceIndex: 0 };
61809
+ });
61810
+ if (a.type === "points") {
61811
+ for (const v of verts) {
61812
+ // Only reuse the provided id for a single-point entry (the round-trip case);
61813
+ // a multi-point points entry must get a fresh id per marker to avoid duplicate keys.
61814
+ const id = a.id && verts.length === 1 ? a.id : this.nextId();
61815
+ const marker = makePointMarker(v, this.o.mesh, a.color, this.markerRadius);
61816
+ this.o.scene.add(marker);
61817
+ this.store.add({
61818
+ id,
61819
+ type: "points",
61820
+ mode: null,
61821
+ label: a.label,
61822
+ color: a.color,
61823
+ closed: false,
61824
+ visible: (_b = a.visible) !== null && _b !== void 0 ? _b : true,
61825
+ vertices: [v],
61826
+ object3D: marker,
61827
+ });
61828
+ // track max numeric id
61829
+ const m = id.match(/^a(\d+)$/);
61830
+ if (m)
61831
+ maxImported = Math.max(maxImported, parseInt(m[1], 10));
61832
+ count++;
61833
+ }
61834
+ }
61835
+ else {
61836
+ if (verts.length < 2)
61837
+ continue;
61838
+ const id = (_c = a.id) !== null && _c !== void 0 ? _c : this.nextId();
61839
+ const line = makeContourLine(verts, a.color, a.closed, this.o.container, this.epsilon, this.o.mesh);
61840
+ this.o.scene.add(line);
61841
+ this.store.add({
61842
+ id,
61843
+ type: "contour",
61844
+ mode: a.mode,
61845
+ label: a.label,
61846
+ color: a.color,
61847
+ closed: a.closed,
61848
+ visible: (_d = a.visible) !== null && _d !== void 0 ? _d : true,
61849
+ vertices: verts,
61850
+ object3D: line,
61851
+ });
61852
+ const m = id.match(/^a(\d+)$/);
61853
+ if (m)
61854
+ maxImported = Math.max(maxImported, parseInt(m[1], 10));
61855
+ count++;
61856
+ }
61857
+ }
61858
+ // keep seq ahead of any imported numeric ids to avoid collisions
61859
+ if (maxImported > this.seq)
61860
+ this.seq = maxImported;
61861
+ return count;
61862
+ }
61731
61863
  // ---- Internal ----
61864
+ get drawing() {
61865
+ return this.drawLock || this.spaceHeld;
61866
+ }
61732
61867
  applyCameraGating() {
61733
- // Holding Space for temporary rotation takes priority; otherwise enable the camera only in navigate mode.
61734
- this.o.controls.enabled = this.spaceHeld || this.mode === "navigate";
61868
+ var _a, _b;
61869
+ // Default is navigate (camera enabled). Drawing only when drawLock or spaceHeld.
61870
+ this.o.controls.enabled = !this.drawing;
61871
+ (_b = (_a = this.o).onInteractionChange) === null || _b === void 0 ? void 0 : _b.call(_a, { drawing: this.drawing, armed: this.armed, locked: this.drawLock });
61735
61872
  }
61736
61873
  /** Reconcile the scene against store.list(): add missing objects, remove deleted ones (no dispose, kept for undo restore). */
61737
61874
  reconcile() {
@@ -61749,6 +61886,11 @@ class SurfaceAnnotator {
61749
61886
  this.o.scene.add(o);
61750
61887
  }
61751
61888
  this.managed = present;
61889
+ // Apply per-annotation visibility
61890
+ for (const a of this.store.list()) {
61891
+ if (a.object3D)
61892
+ a.object3D.visible = a.visible;
61893
+ }
61752
61894
  this.applySelection();
61753
61895
  (_b = (_a = this.o).onChange) === null || _b === void 0 ? void 0 : _b.call(_a, this.store.list());
61754
61896
  }
@@ -61756,6 +61898,8 @@ class SurfaceAnnotator {
61756
61898
  for (const a of this.store.list()) {
61757
61899
  if (!a.object3D)
61758
61900
  continue;
61901
+ if (!a.visible)
61902
+ continue;
61759
61903
  const sel = a.id === this.selectedId;
61760
61904
  if (a.type === "contour") {
61761
61905
  const mat = a.object3D.material;
@@ -61988,6 +62132,7 @@ class SurfaceAnnotator {
61988
62132
  label: `Contour ${this.seq}`,
61989
62133
  color: this.geodesicColor,
61990
62134
  closed,
62135
+ visible: true,
61991
62136
  vertices: verts,
61992
62137
  object3D: this.activeGeoLine,
61993
62138
  };
@@ -62021,7 +62166,8 @@ class SurfaceAnnotator {
62021
62166
  window.removeEventListener("keyup", this.onKeyUp);
62022
62167
  window.removeEventListener("resize", this.onResize);
62023
62168
  }
62024
- }
62169
+ }
62170
+ SurfaceAnnotator.TAP_MS = 250;
62025
62171
 
62026
62172
  class copperScene extends baseScene {
62027
62173
  // rayster pick
@@ -83444,15 +83590,15 @@ function evaluateElement(element, weights) {
83444
83590
  }
83445
83591
 
83446
83592
  // import * as kiwrious from "copper3d_plugin_heart_k";
83447
- // "v3.6.6" is injected at build time by rollup @rollup/plugin-replace, sourced from package.json version.
83593
+ // "v3.6.8" is injected at build time by rollup @rollup/plugin-replace, sourced from package.json version.
83448
83594
  // When copper3d is consumed from local source (no rollup replace step), the identifier is undefined and
83449
83595
  // referencing it throws a ReferenceError — guard it so local loading still works.
83450
83596
  let _revision = "unknown";
83451
83597
  try {
83452
- _revision = "v3.6.6";
83598
+ _revision = "v3.6.8";
83453
83599
  }
83454
83600
  catch (_a) {
83455
- /* "v3.6.6" not injected (local source build) */
83601
+ /* "v3.6.8" not injected (local source build) */
83456
83602
  }
83457
83603
  const REVISION = _revision;
83458
83604
  // Expose on global so the version can be read in a production browser console via window.__COPPER3D_VERSION__