u-space 0.0.1 → 0.0.2

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/dist/index.js CHANGED
@@ -1,18 +1,18 @@
1
- import { Raycaster as ue, Vector2 as P, RenderPipeline as Be, Sphere as me, Box3 as ge, Spherical as C, Matrix4 as Re, Quaternion as _e, Vector4 as Ae, Vector3 as we, MathUtils as Ne, PMREMGenerator as Ue, OrthographicCamera as F, TimestampQuery as De, Cache as je, EventDispatcher as ke, Timer as Ge, PerspectiveCamera as W, WebGPURenderer as Fe, PCFShadowMap as He, AgXToneMapping as ze, Scene as $e, Color as J, MeshStandardNodeMaterial as I, Loader as We, LoaderUtils as L, FileLoader as fe, TextureLoader as ye, Group as z, SRGBColorSpace as ve, RepeatWrapping as se, BufferGeometry as Qe, BufferAttribute as ne, Mesh as j, FrontSide as Ke, BackSide as Xe, DoubleSide as qe, REVISION as ie, CubeTextureLoader as Ye, EquirectangularReflectionMapping as Je, Sprite as Ze, SphereGeometry as Ve, TubeGeometry as et, LineCurve3 as tt, CatmullRomCurve3 as st, SpriteNodeMaterial as nt, CanvasTexture as it, ShapeGeometry as rt, Shape as be, ExtrudeGeometry as at, PlaneGeometry as ot, CircleGeometry as ct } from "three/webgpu";
2
- import { pass as q, blendColor as ht, color as A, uv as re, time as Q, pow as K, sin as ae, mix as X, mx_noise_float as oe, Fn as Te, userData as D, materialColor as ce, select as Y, materialOpacity as lt, vec3 as dt } from "three/tsl";
1
+ import { Raycaster as me, Vector2 as P, RenderPipeline as Be, Sphere as ge, Box3 as we, Spherical as C, Matrix4 as Re, Quaternion as _e, Vector4 as Ne, Vector3 as J, MathUtils as Ae, PMREMGenerator as Ue, OrthographicCamera as F, TimestampQuery as De, Cache as je, EventDispatcher as ke, Timer as Ge, PerspectiveCamera as W, WebGPURenderer as Fe, PCFShadowMap as He, AgXToneMapping as ze, Scene as $e, Color as Z, MeshStandardNodeMaterial as I, Loader as We, LoaderUtils as L, FileLoader as fe, TextureLoader as ye, Group as z, SRGBColorSpace as ve, RepeatWrapping as ne, BufferGeometry as Qe, BufferAttribute as ie, Mesh as j, FrontSide as Ke, BackSide as Xe, DoubleSide as qe, REVISION as re, CubeTextureLoader as Ye, EquirectangularReflectionMapping as Je, Sprite as Ze, SphereGeometry as Ve, TubeGeometry as et, LineCurve3 as tt, CatmullRomCurve3 as st, SpriteNodeMaterial as nt, CanvasTexture as it, ShapeGeometry as rt, Shape as be, ExtrudeGeometry as at, PlaneGeometry as ot, CircleGeometry as ct } from "three/webgpu";
2
+ import { pass as q, blendColor as ht, color as N, uv as ae, time as Q, pow as K, sin as oe, mix as X, mx_noise_float as ce, Fn as Te, userData as D, materialColor as he, select as Y, materialOpacity as lt, vec3 as dt } from "three/tsl";
3
3
  import Ce from "camera-controls";
4
4
  import { RoomEnvironment as pt } from "three/addons/environments/RoomEnvironment.js";
5
5
  import { ViewHelper as ut } from "three/addons/helpers/ViewHelper.js";
6
- import { GLTFLoader as Me } from "three/addons/loaders/GLTFLoader.js";
6
+ import { GLTFLoader as xe } from "three/addons/loaders/GLTFLoader.js";
7
7
  import { FBXLoader as mt } from "three/addons/loaders/FBXLoader.js";
8
8
  import { OBJLoader as gt } from "three/addons/loaders/OBJLoader.js";
9
9
  import { STLLoader as wt } from "three/addons/loaders/STLLoader.js";
10
10
  import { DRACOLoader as ft } from "three/addons/loaders/DRACOLoader.js";
11
11
  import { KTX2Loader as yt } from "three/addons/loaders/KTX2Loader.js";
12
- import { MeshoptDecoder as he } from "three/addons/libs/meshopt_decoder.module.js";
12
+ import { MeshoptDecoder as le } from "three/addons/libs/meshopt_decoder.module.js";
13
13
  import { HDRLoader as vt } from "three/addons/loaders/HDRLoader.js";
14
14
  import { clone as bt } from "three/addons/utils/SkeletonUtils.js";
15
- import { Color as N } from "three";
15
+ import { Color as A } from "three";
16
16
  import { Easing as d, Tween as Tt } from "three/addons/libs/tween.module.js";
17
17
  class Ct {
18
18
  /** The type of event (e.g., 'click', 'pointerdown'). */
@@ -42,11 +42,11 @@ class Ct {
42
42
  return this._propagationStopped;
43
43
  }
44
44
  }
45
- class Mt {
45
+ class xt {
46
46
  domElement;
47
47
  scene;
48
48
  camera;
49
- raycaster = new ue();
49
+ raycaster = new me();
50
50
  pointer = new P();
51
51
  hoveredObject = null;
52
52
  pointerDownTime = 0;
@@ -55,17 +55,16 @@ class Mt {
55
55
  longPressThreshold = 500;
56
56
  moveThreshold = 0.01;
57
57
  /**
58
- * The objects to check for intersections.
59
- * If not set, it defaults to the children of the scene.
58
+ * The objects to check for intersections. default to all children of the scene (including nested).
60
59
  */
61
- targetObjects = null;
60
+ targetObjects;
62
61
  /**
63
62
  * Whether to enable pointer move events (pointermove, pointerenter, pointerleave).
64
63
  * Disabled by default for performance optimization.
65
64
  */
66
65
  pointerMoveEventsEnabled = !1;
67
66
  constructor(e, t, s) {
68
- this.domElement = e, this.scene = t, this.camera = s, this.raycaster.params.Points.threshold = 0.1, this.raycaster.params.Line.threshold = 0.1, this._bindEvents();
67
+ this.domElement = e, this.scene = t, this.camera = s, this.raycaster.params.Points.threshold = 0.1, this.raycaster.params.Line.threshold = 0.1, this.targetObjects = this.scene.children, this._bindEvents();
69
68
  }
70
69
  /**
71
70
  * Updates the camera reference (useful when switching cameras).
@@ -81,9 +80,7 @@ class Mt {
81
80
  this.pointer.x = (e.clientX - t.left) / t.width * 2 - 1, this.pointer.y = -((e.clientY - t.top) / t.height) * 2 + 1;
82
81
  }
83
82
  _getIntersects() {
84
- this.raycaster.setFromCamera(this.pointer, this.camera);
85
- const e = this.targetObjects || this.scene.children;
86
- return this.raycaster.intersectObjects(e, !0);
83
+ return this.raycaster.setFromCamera(this.pointer, this.camera), this.raycaster.intersectObjects(this.targetObjects, !0);
87
84
  }
88
85
  /**
89
86
  * Dispatches an event to the target object and bubbles up the parent chain.
@@ -125,12 +122,18 @@ class Mt {
125
122
  this.clickTimer && (clearTimeout(this.clickTimer), this.clickTimer = null), this._handleEvent("dblclick", e);
126
123
  };
127
124
  _onContextMenu = (e) => {
128
- e.preventDefault(), this._handleEvent("contextmenu", e);
125
+ e.preventDefault();
129
126
  };
130
127
  _onPointerDown = (e) => {
131
128
  this.pointerDownTime = Date.now(), this._updatePointer(e), this.pointerDownPos.copy(this.pointer), this._handleEvent("pointerdown", e);
132
129
  };
133
- _onPointerUp = (e) => this._handleEvent("pointerup", e);
130
+ _onPointerUp = (e) => {
131
+ if (this._updatePointer(e), e.button === 2) {
132
+ const t = Date.now() - this.pointerDownTime, s = this.pointer.distanceTo(this.pointerDownPos);
133
+ t <= this.longPressThreshold && s <= this.moveThreshold && this._handleEvent("rightclick", e);
134
+ }
135
+ this._handleEvent("pointerup", e);
136
+ };
134
137
  _onPointerMove = (e) => {
135
138
  if (!this.pointerMoveEventsEnabled) return;
136
139
  this._updatePointer(e);
@@ -144,7 +147,7 @@ class Mt {
144
147
  this.domElement.removeEventListener("click", this._onClick), this.domElement.removeEventListener("dblclick", this._onDblClick), this.domElement.removeEventListener("contextmenu", this._onContextMenu), this.domElement.removeEventListener("pointerdown", this._onPointerDown), this.domElement.removeEventListener("pointerup", this._onPointerUp), this.domElement.removeEventListener("pointermove", this._onPointerMove), this.hoveredObject = null;
145
148
  }
146
149
  }
147
- class xt {
150
+ class Mt {
148
151
  idMap = /* @__PURE__ */ new Map();
149
152
  nameMap = /* @__PURE__ */ new Map();
150
153
  typeMap = /* @__PURE__ */ new Map();
@@ -284,14 +287,14 @@ class Et extends Be {
284
287
  }
285
288
  const Ot = {
286
289
  Vector2: P,
287
- Vector3: we,
288
- Vector4: Ae,
290
+ Vector3: J,
291
+ Vector4: Ne,
289
292
  Quaternion: _e,
290
293
  Matrix4: Re,
291
294
  Spherical: C,
292
- Box3: ge,
293
- Sphere: me,
294
- Raycaster: ue
295
+ Box3: we,
296
+ Sphere: ge,
297
+ Raycaster: me
295
298
  };
296
299
  Ce.install({ THREE: Ot });
297
300
  class Pt extends Ce {
@@ -310,7 +313,7 @@ class Pt extends Ce {
310
313
  this.absoluteRotations();
311
314
  const { viewpoint: s = "frontTop", enableTransition: n = !0, padding: i = 0.1, cover: a = !1 } = t, c = [];
312
315
  if (s !== "current") {
313
- const r = le[s.toUpperCase()] ?? le.FRONTTOP, h = r.theta, l = r.phi;
316
+ const r = de[s.toUpperCase()] ?? de.FRONTTOP, h = r.theta, l = r.phi;
314
317
  c.push(
315
318
  this.fitToBox(e, n, {
316
319
  paddingLeft: i,
@@ -321,17 +324,17 @@ class Pt extends Ce {
321
324
  })
322
325
  ), c.push(this.rotateTo(h, l, n));
323
326
  } else {
324
- const r = new me();
327
+ const r = new ge();
325
328
  e.getBoundingSphere(r), r.radius += i, c.push(this.fitToSphere(r, n));
326
329
  }
327
330
  return await Promise.all(c), !0;
328
331
  }
329
332
  async flyToObject(e, t = {}) {
330
- const s = new ge().setFromObject(e);
333
+ const s = new we().setFromObject(e);
331
334
  return this.flyToBox(s, t);
332
335
  }
333
336
  }
334
- const le = {
337
+ const de = {
335
338
  LEFT: new C(0, Math.PI / 2, -Math.PI / 2),
336
339
  RIGHT: new C(0, Math.PI / 2, Math.PI / 2),
337
340
  FRONT: new C(0, Math.PI / 2, 0),
@@ -349,7 +352,7 @@ const le = {
349
352
  };
350
353
  function St(o, e) {
351
354
  const t = o - e;
352
- return Ne.euclideanModulo(t + Math.PI, Math.PI * 2) - Math.PI;
355
+ return Ae.euclideanModulo(t + Math.PI, Math.PI * 2) - Math.PI;
353
356
  }
354
357
  class Lt {
355
358
  environment = new pt();
@@ -447,7 +450,7 @@ class ys extends ke {
447
450
  frameCount = 1;
448
451
  frameloop = "demand";
449
452
  constructor({ el: e, rendererOptions: t }) {
450
- super(), this.el = e, this.renderer = this._initRenderer(t), this.scene = this.createScene(), this.camera = this.createPerspectiveCamera(), this.info = new Bt(this.el, this.renderer), this.controls = new Pt(this.camera, this.renderer.domElement), this.renderPipeline = new Et(this.renderer, this.scene, this.camera), this.timer = new Ge(), this.roomEnvironment = new Lt(this.renderer), this.interactionManager = new Mt(this.renderer.domElement, this.scene, this.camera), this.objectManager = new xt(), this.viewerHelper = new It(this), window.addEventListener("resize", this.onWindowResize);
453
+ super(), this.el = e, this.renderer = this._initRenderer(t), this.scene = this.createScene(), this.camera = this.createPerspectiveCamera(), this.info = new Bt(this.el, this.renderer), this.controls = new Pt(this.camera, this.renderer.domElement), this.renderPipeline = new Et(this.renderer, this.scene, this.camera), this.timer = new Ge(), this.roomEnvironment = new Lt(this.renderer), this.interactionManager = new xt(this.renderer.domElement, this.scene, this.camera), this.objectManager = new Mt(), this.viewerHelper = new It(this), window.addEventListener("resize", this.onWindowResize);
451
454
  }
452
455
  onWindowResize = () => {
453
456
  const e = this.el.clientWidth, t = this.el.clientHeight;
@@ -487,7 +490,7 @@ class ys extends ke {
487
490
  }
488
491
  createScene() {
489
492
  const e = new $e();
490
- return e.background = new J(0), e;
493
+ return e.background = new Z(0), e;
491
494
  }
492
495
  createPerspectiveCamera() {
493
496
  const e = new W(50, this.el.clientWidth / this.el.clientHeight, 0.1, 1e5);
@@ -508,13 +511,13 @@ class ys extends ke {
508
511
  this.el.removeChild(this.renderer.domElement), window.removeEventListener("resize", this.onWindowResize), this.info.dispose(), this.interactionManager.dispose(), this.roomEnvironment.dispose(), this.renderPipeline.dispose(), this.renderer.dispose();
509
512
  }
510
513
  }
511
- class Rt extends Me {
514
+ class Rt extends xe {
512
515
  constructor(e) {
513
516
  super(e);
514
517
  }
515
518
  parse(e, t, s, n) {
516
519
  if (_t(e.slice(0, 8)) === "SBMG----") {
517
- const a = At(e.slice(8));
520
+ const a = Nt(e.slice(8));
518
521
  return super.parse(a, t, s, n);
519
522
  } else
520
523
  return super.parse(e, t, s, n);
@@ -523,7 +526,7 @@ class Rt extends Me {
523
526
  function _t(o) {
524
527
  return new TextDecoder().decode(new Uint8Array(o));
525
528
  }
526
- function At(o) {
529
+ function Nt(o) {
527
530
  const e = new DataView(o);
528
531
  for (let t = 0; t < e.byteLength; t++) {
529
532
  const s = e.getUint8(t), n = (s >> 4 & 15) + (s << 4 & 240);
@@ -531,18 +534,18 @@ function At(o) {
531
534
  }
532
535
  return e.buffer;
533
536
  }
534
- const Nt = 8, Ut = 130, de = 66, Dt = "SBK-----", jt = "SBM-----", xe = new TextDecoder(), kt = new TextEncoder();
537
+ const At = 8, Ut = 130, pe = 66, Dt = "SBK-----", jt = "SBM-----", Me = new TextDecoder(), kt = new TextEncoder();
535
538
  function Gt(o) {
536
- let e = Nt;
539
+ let e = At;
537
540
  const t = new Uint8Array(o, 0, e);
538
- if (xe.decode(t) !== Dt)
541
+ if (Me.decode(t) !== Dt)
539
542
  return o;
540
543
  e += Ut;
541
544
  const n = new Uint8Array(o, 0, e);
542
545
  if (n[40] === 1) {
543
546
  const a = kt.encode(jt), c = new Uint8Array([n[41]]), r = Ft(n), h = Ht(r);
544
- let l = de % h.length;
545
- const u = e + de, f = new Uint8Array(o, u), p = new Uint8Array(f.length);
547
+ let l = pe % h.length;
548
+ const u = e + pe, f = new Uint8Array(o, u), p = new Uint8Array(f.length);
546
549
  for (let w = 0; w < f.length; w++)
547
550
  p[w] = f[w] ^ h[l], l = (l + 1) % h.length;
548
551
  const g = new Uint8Array(a.length + c.length + p.length);
@@ -559,13 +562,13 @@ function Ht(o) {
559
562
  }
560
563
  const zt = (o, e, t) => {
561
564
  const s = o.buffer.slice(t, t + e);
562
- let n = xe.decode(s);
565
+ let n = Me.decode(s);
563
566
  return n = n.replace("\\", "/"), n.startsWith("Maps/") || (n = `Maps/${n}`), n;
564
567
  }, $t = (o, e, t) => {
565
568
  const [s, n, i, a, c] = e, r = t || a < 1;
566
569
  return new I({
567
570
  name: o,
568
- color: new J(s, n, i),
571
+ color: new Z(s, n, i),
569
572
  opacity: a,
570
573
  transparent: r,
571
574
  alphaTest: 0.01,
@@ -614,7 +617,7 @@ class Qt {
614
617
  if (t += g, !this.materials.has(r)) {
615
618
  const v = $t(r, [h, l, u, f, p], Wt(w));
616
619
  this.materials.set(r, v), w && this.options.path && this.textureLoader.load(L.resolveURL(w, this.options.path), (b) => {
617
- b.colorSpace = ve, b.wrapS = se, b.wrapT = se, b.flipY = !1, b.anisotropy = 16, v.map = b;
620
+ b.colorSpace = ve, b.wrapS = ne, b.wrapT = ne, b.flipY = !1, b.anisotropy = 16, v.map = b;
618
621
  });
619
622
  }
620
623
  }
@@ -626,7 +629,7 @@ class Qt {
626
629
  const l = [], u = [], f = [], p = [], g = e.getUint16(t, this.littleEndian);
627
630
  if (t += 2, g > 0)
628
631
  for (let m = 0; m < g; m++) {
629
- const y = new we();
632
+ const y = new J();
630
633
  y.setX(e.getFloat32(t, this.littleEndian)), t += 4, y.setY(e.getFloat32(t, this.littleEndian)), t += 4, y.setZ(e.getFloat32(t, this.littleEndian)), t += 4, l.push(y);
631
634
  }
632
635
  const w = e.getUint16(t, this.littleEndian);
@@ -651,16 +654,16 @@ class Qt {
651
654
  const O = [y, B, _];
652
655
  f.push(O), u.length > 0 && p.push([u[O[0]], u[O[1]], u[O[2]]]);
653
656
  }
654
- const b = [], M = [];
657
+ const b = [], x = [];
655
658
  for (let m = 0; m < f.length; m++) {
656
659
  const y = f[m], B = l[y[0]], _ = l[y[1]], O = l[y[2]];
657
660
  b.push(...B.toArray(), ..._.toArray(), ...O.toArray());
658
- let V = new P(), ee = new P(), te = new P();
661
+ let ee = new P(), te = new P(), se = new P();
659
662
  const k = p[m];
660
- k !== void 0 && (V = k[0], ee = k[1], te = k[2]), M.push(...V.toArray(), ...ee.toArray(), ...te.toArray());
663
+ k !== void 0 && (ee = k[0], te = k[1], se = k[2]), x.push(...ee.toArray(), ...te.toArray(), ...se.toArray());
661
664
  }
662
- const x = new Float32Array(b), E = new Float32Array(M), S = new Qe();
663
- if (x.length > 0 && S.setAttribute("position", new ne(x, 3)), E.length > 0 && S.setAttribute("uv", new ne(E, 2)), S.computeVertexNormals(), this.materials.has(h)) {
665
+ const M = new Float32Array(b), E = new Float32Array(x), S = new Qe();
666
+ if (M.length > 0 && S.setAttribute("position", new ie(M, 3)), E.length > 0 && S.setAttribute("uv", new ie(E, 2)), S.computeVertexNormals(), this.materials.has(h)) {
664
667
  const m = new j(S, this.materials.get(h));
665
668
  m.name = r, m.castShadow = !0, m.receiveShadow = !0, n.add(m);
666
669
  }
@@ -738,13 +741,13 @@ class R {
738
741
  static CACHE_NAME = "u-space-model-loader-cache";
739
742
  static fileLoader = new fe().setResponseType("arraybuffer");
740
743
  static dracoLoader = new ft().setDecoderPath(
741
- `https://cdn.jsdelivr.net/npm/three@0.${ie}.0/examples/jsm/libs/draco/`
744
+ `https://cdn.jsdelivr.net/npm/three@0.${re}.0/examples/jsm/libs/draco/`
742
745
  );
743
746
  static ktx2Loader = new yt().setTranscoderPath(
744
- `https://cdn.jsdelivr.net/npm/three@0.${ie}.0/examples/jsm/libs/basis/`
747
+ `https://cdn.jsdelivr.net/npm/three@0.${re}.0/examples/jsm/libs/basis/`
745
748
  );
746
- static gltfLoader = new Me().setDRACOLoader(R.dracoLoader).setKTX2Loader(R.ktx2Loader).setMeshoptDecoder(he);
747
- static sbmxLoader = new Rt().setDRACOLoader(R.dracoLoader).setKTX2Loader(R.ktx2Loader).setMeshoptDecoder(he);
749
+ static gltfLoader = new xe().setDRACOLoader(R.dracoLoader).setKTX2Loader(R.ktx2Loader).setMeshoptDecoder(le);
750
+ static sbmxLoader = new Rt().setDRACOLoader(R.dracoLoader).setKTX2Loader(R.ktx2Loader).setMeshoptDecoder(le);
748
751
  static sbmLoader = new Kt();
749
752
  static fbxLoader = new mt();
750
753
  static objLoader = new gt();
@@ -896,7 +899,7 @@ class qt extends U {
896
899
  ), this.material = new I(t);
897
900
  }
898
901
  }
899
- class pe extends U {
902
+ class ue extends U {
900
903
  isTubeMesh = !0;
901
904
  type = "TubeMesh";
902
905
  constructor({ geometryParameters: e, materialParameters: t } = {}) {
@@ -1035,7 +1038,7 @@ class bs extends Ee {
1035
1038
  t.add(c);
1036
1039
  const r = this.nodes.get(n), h = this.nodes.get(a);
1037
1040
  if (r && h) {
1038
- const l = new tt(r, h), u = new pe({
1041
+ const l = new tt(r, h), u = new ue({
1039
1042
  geometryParameters: {
1040
1043
  path: l,
1041
1044
  tubularSegments: 1,
@@ -1062,7 +1065,7 @@ class bs extends Ee {
1062
1065
  */
1063
1066
  renderPath(e, t = this.parameters.pathColor) {
1064
1067
  if (e.length < 2) return;
1065
- const s = new st(e, !1, "catmullrom", 0), n = new pe({
1068
+ const s = new st(e, !1, "catmullrom", 0), n = new ue({
1066
1069
  geometryParameters: {
1067
1070
  path: s,
1068
1071
  tubularSegments: e.length * 10,
@@ -1080,6 +1083,31 @@ class bs extends Ee {
1080
1083
  this.remove(e), e.geometry.dispose(), e.material.dispose();
1081
1084
  }), this.pathMeshes = [];
1082
1085
  }
1086
+ /** Export nodes and edges as a JSON-serializable object. */
1087
+ exportData() {
1088
+ const e = {};
1089
+ this.nodes.forEach((n, i) => {
1090
+ e[i] = { x: n.x, y: n.y, z: n.z };
1091
+ });
1092
+ const t = [], s = /* @__PURE__ */ new Set();
1093
+ return this.adjacencyMap.forEach((n, i) => {
1094
+ n.forEach((a, c) => {
1095
+ const r = [i, c].sort().join("-");
1096
+ s.has(r) || (s.add(r), t.push({ from: i, to: c, weight: a }));
1097
+ });
1098
+ }), { nodes: e, edges: t };
1099
+ }
1100
+ /**
1101
+ * Load topology from a previously exported data object.
1102
+ * Replaces all current nodes, edges, and path meshes, then re-renders the graph.
1103
+ */
1104
+ importData(e) {
1105
+ this.clearGraph(), this.clearPaths(), this.nodes.clear(), this.adjacencyMap.clear(), Object.entries(e.nodes).forEach(([t, s]) => {
1106
+ this.addNode(t, new J(s.x, s.y, s.z));
1107
+ }), e.edges.forEach(({ from: t, to: s, weight: n }) => {
1108
+ this.addEdge(t, s, n);
1109
+ }), this.renderGraph();
1110
+ }
1083
1111
  dispose() {
1084
1112
  this.clearGraph(), this.clearPaths();
1085
1113
  }
@@ -1117,26 +1145,26 @@ class Ts extends Xt {
1117
1145
  let n = null;
1118
1146
  this.parameters.img && (n = await this._loadImage(this.parameters.img));
1119
1147
  const { text: i, fontSize: a, color: c, iconSize: r, padding: h, backgroundColor: l, borderRadius: u, textPosition: f } = this.parameters, p = s.measureText(i), g = i ? p.width : 0, w = i ? a : 0;
1120
- let T = 0, v = 0, b = 0, M = 0, x = 0, E = 0;
1148
+ let T = 0, v = 0, b = 0, x = 0, M = 0, E = 0;
1121
1149
  const S = !!n, m = !!i;
1122
1150
  if (S && m)
1123
1151
  switch (f) {
1124
1152
  case "top":
1125
- T = Math.max(r, g), v = r + h + w, x = (T - g) / 2, E = w / 2, b = (T - r) / 2, M = w + h;
1153
+ T = Math.max(r, g), v = r + h + w, M = (T - g) / 2, E = w / 2, b = (T - r) / 2, x = w + h;
1126
1154
  break;
1127
1155
  case "bottom":
1128
- T = Math.max(r, g), v = r + h + w, b = (T - r) / 2, M = 0, x = (T - g) / 2, E = r + h + w / 2;
1156
+ T = Math.max(r, g), v = r + h + w, b = (T - r) / 2, x = 0, M = (T - g) / 2, E = r + h + w / 2;
1129
1157
  break;
1130
1158
  case "left":
1131
- T = r + h + g, v = Math.max(r, w), x = 0, E = v / 2, b = g + h, M = (v - r) / 2;
1159
+ T = r + h + g, v = Math.max(r, w), M = 0, E = v / 2, b = g + h, x = (v - r) / 2;
1132
1160
  break;
1133
1161
  default:
1134
- T = r + h + g, v = Math.max(r, w), b = 0, M = (v - r) / 2, x = r + h, E = v / 2;
1162
+ T = r + h + g, v = Math.max(r, w), b = 0, x = (v - r) / 2, M = r + h, E = v / 2;
1135
1163
  break;
1136
1164
  }
1137
- else S ? (T = r, v = r, b = 0, M = 0) : m && (T = g, v = w, x = 0, E = w / 2);
1165
+ else S ? (T = r, v = r, b = 0, x = 0) : m && (T = g, v = w, M = 0, E = w / 2);
1138
1166
  const y = T + h * 2, B = v + h * 2;
1139
- t.width = y, t.height = B, s.font = `${a}px ${this.parameters.fontFamily}`, s.textBaseline = "middle", l && (s.fillStyle = l, this._drawRoundedRect(s, 0, 0, y, B, u), s.fill()), S && s.drawImage(n, b + h, M + h, r, r), m && (s.fillStyle = c, s.fillText(i, x + h, E + h)), this.material.map?.dispose();
1167
+ t.width = y, t.height = B, s.font = `${a}px ${this.parameters.fontFamily}`, s.textBaseline = "middle", l && (s.fillStyle = l, this._drawRoundedRect(s, 0, 0, y, B, u), s.fill()), S && s.drawImage(n, b + h, x + h, r, r), m && (s.fillStyle = c, s.fillText(i, M + h, E + h)), this.material.map?.dispose();
1140
1168
  const _ = new it(t);
1141
1169
  _.colorSpace = ve, this.material.map = _;
1142
1170
  const O = 0.01;
@@ -1202,7 +1230,7 @@ class Cs extends U {
1202
1230
  ), this.material = new I(t);
1203
1231
  }
1204
1232
  }
1205
- class Ms extends U {
1233
+ class xs extends U {
1206
1234
  isCircleMesh = !0;
1207
1235
  type = "CircleMesh";
1208
1236
  constructor({ geometryParameters: e, materialParameters: t } = {}) {
@@ -1224,13 +1252,13 @@ class Yt {
1224
1252
  });
1225
1253
  }
1226
1254
  }
1227
- class xs {
1255
+ class Ms {
1228
1256
  static flow(e = {}) {
1229
- const { baseColor: t = 16777215, flowColor: s = 65280, speed: n = 1, scale: i = 3, intensity: a = 4 } = e, c = A(new N(t)), r = A(new N(s)), h = re().x.mul(i).sub(Q.mul(n)), l = K(ae(h).add(1).mul(0.5), a);
1257
+ const { baseColor: t = 16777215, flowColor: s = 65280, speed: n = 1, scale: i = 3, intensity: a = 4 } = e, c = N(new A(t)), r = N(new A(s)), h = ae().x.mul(i).sub(Q.mul(n)), l = K(oe(h).add(1).mul(0.5), a);
1230
1258
  return X(c, r, l);
1231
1259
  }
1232
1260
  static breathe(e = {}) {
1233
- const { baseColor: t = 16777215, breathColor: s = 65280, speed: n = 1, intensity: i = 2 } = e, a = A(new N(t)), c = A(new N(s)), r = ae(Q.mul(n)).add(1).mul(0.5), h = K(r, i);
1261
+ const { baseColor: t = 16777215, breathColor: s = 65280, speed: n = 1, intensity: i = 2 } = e, a = N(new A(t)), c = N(new A(s)), r = oe(Q.mul(n)).add(1).mul(0.5), h = K(r, i);
1234
1262
  return X(a, c, h);
1235
1263
  }
1236
1264
  static fluid(e = {}) {
@@ -1241,17 +1269,17 @@ class xs {
1241
1269
  scale: i = 1,
1242
1270
  intensity: a = 1,
1243
1271
  distortion: c = 0.5
1244
- } = e, r = A(new N(t)), h = A(new N(s)), l = re().mul(i), u = Q.mul(n), f = oe(l.add(u), 1, 0), p = l.add(f.mul(c)), g = oe(p, 1, 0).add(1).mul(0.5), w = K(g, a);
1272
+ } = e, r = N(new A(t)), h = N(new A(s)), l = ae().mul(i), u = Q.mul(n), f = ce(l.add(u), 1, 0), p = l.add(f.mul(c)), g = ce(p, 1, 0).add(1).mul(0.5), w = K(g, a);
1245
1273
  return X(r, h, w);
1246
1274
  }
1247
1275
  }
1248
1276
  function Es(o) {
1249
1277
  }
1250
- const $ = "uSpaceHighlight", Z = `${$}/enabled`, Se = `${$}/opacity`, Le = `${$}/color`, Ie = `${$}/overwrite`, Jt = Te(() => {
1251
- const o = D(Z, "uint"), e = D(Le, "uint"), t = D(Ie, "uint"), s = Vt(e), n = ce.mul(s), i = Y(t.greaterThan(0), s, n);
1252
- return Y(o.greaterThan(0), i, ce);
1278
+ const $ = "uSpaceHighlight", V = `${$}/enabled`, Se = `${$}/opacity`, Le = `${$}/color`, Ie = `${$}/overwrite`, Jt = Te(() => {
1279
+ const o = D(V, "uint"), e = D(Le, "uint"), t = D(Ie, "uint"), s = Vt(e), n = he.mul(s), i = Y(t.greaterThan(0), s, n);
1280
+ return Y(o.greaterThan(0), i, he);
1253
1281
  })(), Zt = Te(() => {
1254
- const o = D(Z, "uint"), e = D(Se, "float");
1282
+ const o = D(V, "uint"), e = D(Se, "float");
1255
1283
  return Y(o.greaterThan(0), e, lt);
1256
1284
  })();
1257
1285
  class Os {
@@ -1265,8 +1293,8 @@ class Os {
1265
1293
  },
1266
1294
  t
1267
1295
  );
1268
- s.color = new J(s.color).getHex(), Yt.traverseMeshes(e, (n) => {
1269
- n.userData[Z] = s.enabled ? 1 : 0, n.userData[Se] = s.opacity, n.userData[Le] = s.color, n.userData[Ie] = s.overwrite ? 1 : 0;
1296
+ s.color = new Z(s.color).getHex(), Yt.traverseMeshes(e, (n) => {
1297
+ n.userData[V] = s.enabled ? 1 : 0, n.userData[Se] = s.opacity, n.userData[Le] = s.color, n.userData[Ie] = s.overwrite ? 1 : 0;
1270
1298
  const i = n.material;
1271
1299
  i && !Array.isArray(i) && (i.transparent = !0, i.colorNode = Jt, i.opacityNode = Zt, i.needsUpdate = !0);
1272
1300
  });
@@ -1347,14 +1375,14 @@ export {
1347
1375
  U as BaseMesh,
1348
1376
  Xt as BaseSprite,
1349
1377
  Pt as CameraControls,
1350
- Ms as CircleMesh,
1378
+ xs as CircleMesh,
1351
1379
  Pe as ExtrudeMesh,
1352
1380
  Ct as InteractionEvent,
1353
- Mt as InteractionManager,
1381
+ xt as InteractionManager,
1354
1382
  Os as MaterialEffects,
1355
1383
  H as Model,
1356
1384
  R as ModelLoaderManager,
1357
- xt as ObjectManager,
1385
+ Mt as ObjectManager,
1358
1386
  Yt as ObjectUtils,
1359
1387
  Cs as PlaneMesh,
1360
1388
  Ts as Poi,
@@ -1363,10 +1391,10 @@ export {
1363
1391
  Rt as SBMXLoader,
1364
1392
  Oe as ShapeMesh,
1365
1393
  qt as SphereMesh,
1366
- xs as TSLEffects,
1394
+ Ms as TSLEffects,
1367
1395
  vs as TextureLoaderManager,
1368
1396
  bs as Topology,
1369
- pe as TubeMesh,
1397
+ ue as TubeMesh,
1370
1398
  es as Tween,
1371
1399
  ys as Viewer,
1372
1400
  Es as reinterpretType,
@@ -0,0 +1,69 @@
1
+ import { TransformControls } from 'three/addons/controls/TransformControls.js';
2
+ import type { Viewer } from 'u-space';
3
+ export interface ObjectControlsOptions {
4
+ /** Transform mode. Default: 'translate' */
5
+ mode?: 'translate' | 'rotate' | 'scale';
6
+ /** Transform space. Default: 'world' */
7
+ space?: 'world' | 'local';
8
+ /** Gizmo size. Default: 1 */
9
+ size?: number;
10
+ /** Show X axis handle. Default: true */
11
+ showX?: boolean;
12
+ /** Show Y axis handle. Default: true */
13
+ showY?: boolean;
14
+ /** Show Z axis handle. Default: true */
15
+ showZ?: boolean;
16
+ }
17
+ /**
18
+ * Interactive plugin for translating, rotating, and scaling 3D objects.
19
+ *
20
+ * Extends Three.js `TransformControls` with the u-space `Viewer` lifecycle:
21
+ * - `enable()` adds the gizmo to the scene and switches frameloop to 'always'.
22
+ * - `disable()` removes the gizmo and restores previous state.
23
+ * - While dragging, `viewer.controls` (CameraControls) is automatically
24
+ * suspended to prevent conflicts.
25
+ *
26
+ * Since this class extends `TransformControls` (→ `Controls` → `EventDispatcher`),
27
+ * all native TransformControls events are available:
28
+ * - `'change'` : Any transform property changed (fires every frame while dragging).
29
+ * - `'objectChange'` : The attached object's matrix was updated.
30
+ * - `'mouseDown'` : Drag started.
31
+ * - `'mouseUp'` : Drag ended.
32
+ * - `'dragging-changed'` : `{ value: boolean }` — true when drag begins, false when it ends.
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * const controls = new ObjectControls(viewer, { mode: 'translate' });
37
+ * controls.enable();
38
+ * controls.attach(myMesh);
39
+ *
40
+ * controls.addEventListener('objectChange', () => {
41
+ * console.log(myMesh.position);
42
+ * });
43
+ * ```
44
+ */
45
+ declare class ObjectControls extends TransformControls {
46
+ viewer: Viewer;
47
+ private _active;
48
+ private _prevFrameloop;
49
+ constructor(viewer: Viewer, options?: ObjectControlsOptions);
50
+ private _onDraggingChanged;
51
+ private _onCameraChange;
52
+ /** Whether the controls are currently active (added to the scene). */
53
+ get isActive(): boolean;
54
+ /**
55
+ * Enable the controls.
56
+ * Adds the gizmo helper to the scene and switches frameloop to 'always'
57
+ * so drags render continuously.
58
+ */
59
+ enable(): this;
60
+ /**
61
+ * Disable the controls.
62
+ * Removes the gizmo from the scene and restores the previous frameloop.
63
+ * Re-enables CameraControls in case they were suspended mid-drag.
64
+ */
65
+ disable(): this;
66
+ /** Fully dispose all resources and remove the gizmo from the scene. */
67
+ dispose(): void;
68
+ }
69
+ export { ObjectControls };
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("three/addons/controls/TransformControls.js");class s extends r.TransformControls{viewer;_active=!1;_prevFrameloop="demand";constructor(i,e){super(i.camera,i.renderer.domElement),this.viewer=i,e?.mode!==void 0&&(this.mode=e.mode),e?.space!==void 0&&(this.space=e.space),e?.size!==void 0&&(this.size=e.size),e?.showX!==void 0&&(this.showX=e.showX),e?.showY!==void 0&&(this.showY=e.showY),e?.showZ!==void 0&&(this.showZ=e.showZ),this.addEventListener("dragging-changed",this._onDraggingChanged),this.viewer.addEventListener("cameraChange",this._onCameraChange)}_onDraggingChanged=i=>{this.viewer.controls.enabled=!i.value};_onCameraChange=({camera:i})=>{this.camera=i};get isActive(){return this._active}enable(){return this._active?this:(this._active=!0,this._prevFrameloop=this.viewer.frameloop,this.viewer.frameloop="always",this.viewer.scene.add(this.getHelper()),this.viewer.render(),this)}disable(){return this._active?(this._active=!1,this.viewer.frameloop=this._prevFrameloop,this.viewer.scene.remove(this.getHelper()),this.viewer.controls.enabled=!0,this.viewer.render(),this):this}dispose(){this.disable(),this.removeEventListener("dragging-changed",this._onDraggingChanged),this.viewer.removeEventListener("cameraChange",this._onCameraChange),super.dispose()}}exports.ObjectControls=s;
@@ -0,0 +1 @@
1
+ export * from './ObjectControls';
@@ -0,0 +1,44 @@
1
+ import { TransformControls as r } from "three/addons/controls/TransformControls.js";
2
+ class a extends r {
3
+ viewer;
4
+ _active = !1;
5
+ _prevFrameloop = "demand";
6
+ constructor(i, e) {
7
+ super(i.camera, i.renderer.domElement), this.viewer = i, e?.mode !== void 0 && (this.mode = e.mode), e?.space !== void 0 && (this.space = e.space), e?.size !== void 0 && (this.size = e.size), e?.showX !== void 0 && (this.showX = e.showX), e?.showY !== void 0 && (this.showY = e.showY), e?.showZ !== void 0 && (this.showZ = e.showZ), this.addEventListener("dragging-changed", this._onDraggingChanged), this.viewer.addEventListener("cameraChange", this._onCameraChange);
8
+ }
9
+ // ─── Private handlers ─────────────────────────────────────────────────────
10
+ _onDraggingChanged = (i) => {
11
+ this.viewer.controls.enabled = !i.value;
12
+ };
13
+ _onCameraChange = ({ camera: i }) => {
14
+ this.camera = i;
15
+ };
16
+ // ─── Public API ───────────────────────────────────────────────────────────
17
+ /** Whether the controls are currently active (added to the scene). */
18
+ get isActive() {
19
+ return this._active;
20
+ }
21
+ /**
22
+ * Enable the controls.
23
+ * Adds the gizmo helper to the scene and switches frameloop to 'always'
24
+ * so drags render continuously.
25
+ */
26
+ enable() {
27
+ return this._active ? this : (this._active = !0, this._prevFrameloop = this.viewer.frameloop, this.viewer.frameloop = "always", this.viewer.scene.add(this.getHelper()), this.viewer.render(), this);
28
+ }
29
+ /**
30
+ * Disable the controls.
31
+ * Removes the gizmo from the scene and restores the previous frameloop.
32
+ * Re-enables CameraControls in case they were suspended mid-drag.
33
+ */
34
+ disable() {
35
+ return this._active ? (this._active = !1, this.viewer.frameloop = this._prevFrameloop, this.viewer.scene.remove(this.getHelper()), this.viewer.controls.enabled = !0, this.viewer.render(), this) : this;
36
+ }
37
+ /** Fully dispose all resources and remove the gizmo from the scene. */
38
+ dispose() {
39
+ this.disable(), this.removeEventListener("dragging-changed", this._onDraggingChanged), this.viewer.removeEventListener("cameraChange", this._onCameraChange), super.dispose();
40
+ }
41
+ }
42
+ export {
43
+ a as ObjectControls
44
+ };