@preference-sl/pref-viewer 2.11.0-beta.5 → 2.11.0-beta.6

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,6 +1,6 @@
1
1
  {
2
2
  "name": "@preference-sl/pref-viewer",
3
- "version": "2.11.0-beta.5",
3
+ "version": "2.11.0-beta.6",
4
4
  "description": "Web Component to preview GLTF models with Babylon.js",
5
5
  "author": "Alex Moreno Palacio <amoreno@preference.es>",
6
6
  "scripts": {
@@ -12,6 +12,9 @@ import { OpeningAnimation } from "./babylonjs-animation-opening.js";
12
12
  * - Displays and disposes the animation control menu (GUI) for animated nodes.
13
13
  * - Provides API for interaction and animation control.
14
14
  *
15
+ * Public Methods:
16
+ * - dispose(): Disposes all resources managed by the animation controller.
17
+ *
15
18
  * @class
16
19
  */
17
20
  export default class BabylonJSAnimationController {
@@ -50,6 +53,7 @@ export default class BabylonJSAnimationController {
50
53
  */
51
54
  #getAnimatedNodes() {
52
55
  this.#scene.animationGroups.forEach((animationGroup) => {
56
+ animationGroup.stop();
53
57
  if (!animationGroup._targetedAnimations.length) {
54
58
  return;
55
59
  }
@@ -150,21 +154,34 @@ export default class BabylonJSAnimationController {
150
154
  * @private
151
155
  */
152
156
  #setupPointerObservers() {
153
- this.#scene.onPointerObservable.add((pointerInfo) => {
154
- if (pointerInfo.type === PointerEventTypes.POINTERMOVE) {
155
- const pickingInfo = this.#scene.pick(pointerInfo.event.clientX, pointerInfo.event.clientY);
156
- this.#hightlightMeshesForAnimation(pickingInfo);
157
- }
158
- if (pointerInfo.type === PointerEventTypes.POINTERUP) {
159
- // Remove any previously created Babylon GUI
160
- if (this.#advancedDynamicTexture) {
161
- this.#advancedDynamicTexture.dispose();
162
- this.#advancedDynamicTexture = null;
163
- }
164
- const pickingInfo = this.#scene.pick(pointerInfo.event.clientX, pointerInfo.event.clientY);
165
- this.#showMenu(pickingInfo);
157
+ if (this.#openingAnimations.length === 0) {
158
+ return;
159
+ }
160
+ this.#scene.onPointerObservable.add(this.#onAnimationPointerObservable.bind(this));
161
+ }
162
+
163
+ /**
164
+ * Handles pointer events in the Babylon.js scene for animation interaction.
165
+ * On pointer move, highlights meshes belonging to animated nodes under the cursor.
166
+ * On pointer up (click), disposes any existing GUI and displays the animation control menu for the selected node.
167
+ *
168
+ * @private
169
+ * @param {PointerInfo} pointerInfo - The pointer event information from Babylon.js.
170
+ */
171
+ #onAnimationPointerObservable(pointerInfo) {
172
+ if (pointerInfo.type === PointerEventTypes.POINTERMOVE) {
173
+ const pickingInfo = this.#scene.pick(pointerInfo.event.clientX, pointerInfo.event.clientY);
174
+ this.#hightlightMeshesForAnimation(pickingInfo);
175
+ }
176
+ if (pointerInfo.type === PointerEventTypes.POINTERUP) {
177
+ // Remove any previously created Babylon GUI
178
+ if (this.#advancedDynamicTexture) {
179
+ this.#advancedDynamicTexture.dispose();
180
+ this.#advancedDynamicTexture = null;
166
181
  }
167
- });
182
+ const pickingInfo = this.#scene.pick(pointerInfo.event.clientX, pointerInfo.event.clientY);
183
+ this.#showMenu(pickingInfo);
184
+ }
168
185
  }
169
186
 
170
187
  /**
@@ -192,4 +209,27 @@ export default class BabylonJSAnimationController {
192
209
  }
193
210
  openingAnimation.showControls(this.#advancedDynamicTexture);
194
211
  }
212
+
213
+ /**
214
+ * Disposes all resources managed by the animation controller.
215
+ * Cleans up the highlight layer, GUI texture, and internal animation/node lists.
216
+ * Should be called when the controller is no longer needed to prevent memory leaks.
217
+ * @public
218
+ */
219
+ dispose() {
220
+ if (this.#highlightLayer) {
221
+ this.#highlightLayer.dispose();
222
+ this.#highlightLayer = null;
223
+ }
224
+ if (this.#advancedDynamicTexture) {
225
+ this.#advancedDynamicTexture.dispose();
226
+ this.#advancedDynamicTexture = null;
227
+ }
228
+ this.#animatedNodes = [];
229
+ this.#openingAnimations = [];
230
+ const observer = this.#scene.onPointerObservable._observers.find((observer) => observer.callback.name.includes("#onAnimationPointerObservable"));
231
+ if (observer) {
232
+ this.#scene.onPointerObservable.remove(observer);
233
+ }
234
+ }
195
235
  }
@@ -768,6 +768,10 @@ export default class BabylonJSController {
768
768
 
769
769
  await Promise.allSettled(promiseArray)
770
770
  .then((values) => {
771
+ if (this.#babylonJSAnimationController) {
772
+ this.#babylonJSAnimationController.dispose();
773
+ this.#babylonJSAnimationController = null;
774
+ };
771
775
  values.forEach((result) => {
772
776
  const container = result.value ? result.value[0] : null;
773
777
  const assetContainer = result.value ? result.value[1] : null;
@@ -775,10 +779,7 @@ export default class BabylonJSController {
775
779
  if (container.state.name === "model") {
776
780
  assetContainer.lights = [];
777
781
  }
778
- const replaced = this.#replaceContainer(container, assetContainer);
779
- if (replaced && container.state.name === "model") {
780
- this.#babylonJSAnimationController = new BabylonJSAnimationController(this.#scene);
781
- }
782
+ this.#replaceContainer(container, assetContainer);
782
783
  container.state.setSuccess(true);
783
784
  } else {
784
785
  if (container.assetContainer && container.state.mustBeShown !== container.state.isVisible && container.state.name === "materials") {
@@ -787,7 +788,7 @@ export default class BabylonJSController {
787
788
  container.state.setSuccess(false);
788
789
  }
789
790
  });
790
-
791
+
791
792
  this.#setOptions_Materials();
792
793
  this.#setOptions_Camera();
793
794
  this.#setVisibilityOfWallAndFloorInModel();
@@ -802,9 +803,9 @@ export default class BabylonJSController {
802
803
  .finally(async () => {
803
804
  this.#setMaxSimultaneousLights();
804
805
  this.#initializeShadows();
806
+ this.#babylonJSAnimationController = new BabylonJSAnimationController(this.#scene);
805
807
  this.#startRender();
806
808
  });
807
-
808
809
  return detail;
809
810
  }
810
811