@sequent-org/ifc-viewer 1.2.4-ci.34.0 → 1.2.4-ci.35.0

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@sequent-org/ifc-viewer",
3
3
  "private": false,
4
- "version": "1.2.4-ci.34.0",
4
+ "version": "1.2.4-ci.35.0",
5
5
  "type": "module",
6
6
  "description": "IFC 3D model viewer component for web applications - fully self-contained with local IFCLoader",
7
7
  "main": "src/index.js",
@@ -19,6 +19,7 @@ export class RightMouseModelMoveController {
19
19
  * @param {(e: PointerEvent) => boolean} [deps.shouldIgnoreEvent]
20
20
  * @param {() => boolean} [deps.isDebug]
21
21
  * @param {(pivotWorld: THREE.Vector3) => void} [deps.onRmbStart]
22
+ * @param {(deltaWorld: THREE.Vector3) => void} [deps.onRmbMove]
22
23
  */
23
24
  constructor(deps) {
24
25
  this.domElement = deps.domElement;
@@ -29,6 +30,7 @@ export class RightMouseModelMoveController {
29
30
  this.shouldIgnoreEvent = deps.shouldIgnoreEvent || (() => false);
30
31
  this.isDebug = deps.isDebug || (() => false);
31
32
  this.onRmbStart = typeof deps.onRmbStart === "function" ? deps.onRmbStart : null;
33
+ this.onRmbMove = typeof deps.onRmbMove === "function" ? deps.onRmbMove : null;
32
34
 
33
35
  this._activePointerId = null;
34
36
  this._last = { x: 0, y: 0 };
@@ -171,6 +173,7 @@ export class RightMouseModelMoveController {
171
173
 
172
174
  model.position.add(this._vDelta);
173
175
  model.updateMatrixWorld?.(true);
176
+ try { this.onRmbMove && this.onRmbMove(this._vDelta); } catch (_) {}
174
177
 
175
178
  if (this.isDebug()) {
176
179
  try {
@@ -154,6 +154,10 @@ export class Viewer {
154
154
  clipEnabled: [Infinity, Infinity, Infinity],
155
155
  // Трансформ модели (для сброса ПКМ-сдвигов)
156
156
  modelTransform: null, // { position: Vector3, quaternion: Quaternion, scale: Vector3 }
157
+ // Положение "земли/тени" (чтобы Home возвращал тень вместе с моделью)
158
+ shadowReceiverPos: null, // THREE.Vector3|null
159
+ sunTargetPos: null, // THREE.Vector3|null
160
+ shadowGradCenterXZ: null // THREE.Vector2|null
157
161
  };
158
162
 
159
163
  // Визуализация оси вращения
@@ -541,6 +545,31 @@ export class Viewer {
541
545
  onRmbStart: (pivot) => {
542
546
  try { this._rmbModelMove.pivotAnchor = pivot?.clone?.() || null; } catch (_) { this._rmbModelMove.pivotAnchor = null; }
543
547
  },
548
+ onRmbMove: (delta) => {
549
+ // Двигаем "тень/землю/солнце" вместе с моделью, чтобы тень не отрывалась и не клипалась.
550
+ try {
551
+ if (!delta) return;
552
+ if (this.shadowReceiver?.position?.add) {
553
+ this.shadowReceiver.position.add(delta);
554
+ this.shadowReceiver.updateMatrixWorld?.(true);
555
+ }
556
+ if (this.shadowGradient?.buildingCenterXZ?.add) {
557
+ this.shadowGradient.buildingCenterXZ.add(new THREE.Vector2(delta.x || 0, delta.z || 0));
558
+ this.#applyShadowGradientUniforms();
559
+ }
560
+ if (this.sunLight) {
561
+ try { this.sunLight.position.add(delta); } catch (_) {}
562
+ try {
563
+ if (this.sunLight.target) {
564
+ this.sunLight.target.position.add(delta);
565
+ this.sunLight.target.updateMatrixWorld?.(true);
566
+ }
567
+ } catch (_) {}
568
+ try { this.sunLight.updateMatrixWorld?.(true); } catch (_) {}
569
+ try { this.sunLight.shadow && (this.sunLight.shadow.needsUpdate = true); } catch (_) {}
570
+ }
571
+ } catch (_) {}
572
+ },
544
573
  });
545
574
  } catch (e) {
546
575
  // eslint-disable-next-line no-console
@@ -1230,6 +1259,17 @@ export class Viewer {
1230
1259
  }
1231
1260
  } catch (_) {}
1232
1261
 
1262
+ // Снимем исходное положение тени/земли, чтобы Home возвращал их вместе с моделью
1263
+ try {
1264
+ this._home.shadowReceiverPos = this.shadowReceiver?.position?.clone?.() || null;
1265
+ } catch (_) { this._home.shadowReceiverPos = null; }
1266
+ try {
1267
+ this._home.sunTargetPos = this.sunLight?.target?.position?.clone?.() || null;
1268
+ } catch (_) { this._home.sunTargetPos = null; }
1269
+ try {
1270
+ this._home.shadowGradCenterXZ = this.shadowGradient?.buildingCenterXZ?.clone?.() || null;
1271
+ } catch (_) { this._home.shadowGradCenterXZ = null; }
1272
+
1233
1273
  // После загрузки модели сбрасываем "фиксированную ось" от ПКМ
1234
1274
  try { if (this._rmbModelMove) this._rmbModelMove.pivotAnchor = null; } catch (_) {}
1235
1275
  });
@@ -3082,6 +3122,30 @@ export class Viewer {
3082
3122
  }
3083
3123
  } catch (_) {}
3084
3124
 
3125
+ // Home: вернуть тень/землю/солнце в исходное положение (единое целое с моделью)
3126
+ try {
3127
+ const p = this._home?.shadowReceiverPos;
3128
+ if (this.shadowReceiver && p) {
3129
+ this.shadowReceiver.position.copy(p);
3130
+ this.shadowReceiver.updateMatrixWorld?.(true);
3131
+ }
3132
+ } catch (_) {}
3133
+ try {
3134
+ const p = this._home?.sunTargetPos;
3135
+ if (this.sunLight?.target && p) {
3136
+ this.sunLight.target.position.copy(p);
3137
+ this.sunLight.target.updateMatrixWorld?.(true);
3138
+ }
3139
+ } catch (_) {}
3140
+ try {
3141
+ const c = this._home?.shadowGradCenterXZ;
3142
+ if (this.shadowGradient?.buildingCenterXZ && c) {
3143
+ this.shadowGradient.buildingCenterXZ.copy(c);
3144
+ this.#applyShadowGradientUniforms();
3145
+ }
3146
+ } catch (_) {}
3147
+ try { if (this.sunLight) this.sunLight.shadow && (this.sunLight.shadow.needsUpdate = true); } catch (_) {}
3148
+
3085
3149
  // Home: сбрасываем "фиксированную ось" от ПКМ
3086
3150
  try { if (this._rmbModelMove) this._rmbModelMove.pivotAnchor = null; } catch (_) {}
3087
3151