@preference-sl/pref-viewer 2.11.0-beta.8 → 2.11.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,53 +1,64 @@
1
1
  {
2
- "name": "@preference-sl/pref-viewer",
3
- "version": "2.11.0-beta.8",
4
- "description": "Web Component to preview GLTF models with Babylon.js",
5
- "author": "Alex Moreno Palacio <amoreno@preference.es>",
6
- "scripts": {
7
- "release": "standard-version --releaseCommitMessageFormat \"chore(release): {{currentTag}} [skip ci]\"",
8
- "release:beta": "standard-version --prerelease beta --releaseCommitMessageFormat \"chore(release): {{currentTag}} [skip ci]\"",
9
- "build": "esbuild src/index.js --bundle --platform=node --outfile=dist/bundle.js --sourcemap",
10
- "start": "npm run build && http-server -c-1 . -p 8080",
11
- "test": "vitest"
12
- },
13
- "repository": {
14
- "type": "git",
15
- "url": "git+https://bitbucket.org/preferencesl/pref-viewer.git"
16
- },
17
- "publishConfig": {
18
- "access": "public"
19
- },
20
- "license": "MIT",
21
- "type": "module",
22
- "main": "src/index.js",
23
- "types": "index.d.ts",
24
- "exports": {
25
- ".": {
26
- "import": "./src/index.js",
27
- "require": "./src/index.js"
2
+ "name": "@preference-sl/pref-viewer",
3
+ "version": "2.11.0",
4
+ "description": "Web Component to preview GLTF models with Babylon.js",
5
+ "author": "Alex Moreno Palacio <amoreno@preference.es>",
6
+ "scripts": {
7
+ "build:prefweb": "webpack --config webpack.config.cjs --mode production",
8
+ "build:prefweb:dev": "webpack --config webpack.config.cjs --mode development",
9
+ "release": "standard-version --releaseCommitMessageFormat \"chore(release): {{currentTag}} [skip ci]\"",
10
+ "release:beta": "standard-version --prerelease beta --releaseCommitMessageFormat \"chore(release): {{currentTag}} [skip ci]\"",
11
+ "build": "esbuild src/index.js --bundle --platform=node --format=esm --outfile=dist/bundle.js --sourcemap",
12
+ "start": "npm run build && http-server -c-1 . -p 8080",
13
+ "test": "vitest"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://bitbucket.org/preferencesl/pref-viewer.git"
18
+ },
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "license": "MIT",
23
+ "type": "module",
24
+ "main": "src/index.js",
25
+ "types": "index.d.ts",
26
+ "exports": {
27
+ ".": {
28
+ "import": "./src/index.js",
29
+ "require": "./src/index.js"
30
+ }
31
+ },
32
+ "sideEffects": false,
33
+ "files": [
34
+ "src",
35
+ "index.d.ts"
36
+ ],
37
+ "dependencies": {
38
+ "@babylonjs/core": "^8.39.2",
39
+ "@babylonjs/loaders": "^8.39.2",
40
+ "@babylonjs/serializers": "^8.39.2",
41
+ "@panzoom/panzoom": "^4.6.0",
42
+ "babylonjs-gltf2interface": "^8.39.2",
43
+ "buffer": "^6.0.3",
44
+ "idb": "^8.0.3",
45
+ "is-svg": "^6.1.0",
46
+ "jszip": "^3.10.1",
47
+ "stream": "^0.0.3",
48
+ "string_decoder": "^1.3.0"
49
+ },
50
+ "devDependencies": {
51
+ "@babel/core": "^7.22.0",
52
+ "@babel/preset-env": "^7.22.0",
53
+ "babel-loader": "^9.2.1",
54
+ "clean-webpack-plugin": "^4.0.0",
55
+ "esbuild": "^0.25.10",
56
+ "http-server": "^14.1.1",
57
+ "jsdom": "^26.1.0",
58
+ "standard-version": "^9.5.0",
59
+ "terser-webpack-plugin": "^5.3.6",
60
+ "vitest": "^3.2.3",
61
+ "webpack": "^5.88.2",
62
+ "webpack-cli": "^5.1.4"
28
63
  }
29
- },
30
- "sideEffects": false,
31
- "files": [
32
- "src",
33
- "index.d.ts"
34
- ],
35
- "dependencies": {
36
- "@babylonjs/core": "^8.36.1",
37
- "@babylonjs/gui": "^8.36.1",
38
- "@babylonjs/loaders": "^8.36.1",
39
- "@babylonjs/serializers": "^8.36.1",
40
- "@panzoom/panzoom": "^4.6.0",
41
- "babylonjs-gltf2interface": "^8.36.1",
42
- "idb": "^8.0.3",
43
- "is-svg": "^6.1.0",
44
- "jszip": "^3.10.1"
45
- },
46
- "devDependencies": {
47
- "esbuild": "^0.25.10",
48
- "http-server": "^14.1.1",
49
- "jsdom": "^26.1.0",
50
- "standard-version": "^9.5.0",
51
- "vitest": "^3.2.3"
52
- }
53
64
  }
@@ -1,28 +1,35 @@
1
- import { Color3, HighlightLayer, Mesh, PickingInfo, PointerEventTypes, Scene } from "@babylonjs/core";
2
- import { AdvancedDynamicTexture } from "@babylonjs/gui";
3
- import { OpeningAnimation } from "./babylonjs-animation-opening.js";
1
+ import { Color3, HighlightLayer, Mesh, PickingInfo, Scene } from "@babylonjs/core";
2
+ import { PrefViewerColors } from "./styles.js";
3
+ import OpeningAnimation from "./babylonjs-animation-opening.js";
4
4
 
5
5
  /**
6
- * BabylonJSAnimationController - Manages animation playback and interactive highlighting for model containers in Babylon.js scenes.
6
+ * BabylonJSAnimationController - Manages animation playback, highlighting, and interactive controls for animated nodes in Babylon.js scenes.
7
7
  *
8
- * Responsibilities:
8
+ * Summary:
9
+ * This class detects, groups, and manages opening/closing animations for scene nodes, provides interactive highlighting of animated nodes and their meshes, and displays a menu for animation control. It is designed for integration with product configurators and interactive 3D applications using Babylon.js.
10
+ *
11
+ * Key features:
9
12
  * - Detects and groups opening/closing animations in the scene.
10
13
  * - Tracks animated transformation nodes and their relationships to meshes.
11
- * - Highlights animated nodes and their child meshes when hovered.
12
- * - Displays and disposes the animation control menu (GUI) for animated nodes.
13
- * - Provides API for interaction and animation control.
14
+ * - Highlights animated nodes and their child meshes on pointer hover.
15
+ * - Displays and disposes the animation control menu for animated nodes.
16
+ * - Provides public API for highlighting, showing the animation menu, and disposing resources.
17
+ * - Cleans up all resources and observers to prevent memory leaks.
14
18
  *
15
19
  * Public Methods:
16
20
  * - dispose(): Disposes all resources managed by the animation controller.
21
+ * - hightlightMeshes(pickingInfo): Highlights meshes that are children of an animated node when hovered.
22
+ * - hideMenu(): Hides and disposes the animation control menu if it exists.
23
+ * - showMenu(pickingInfo): Displays the animation control menu for the animated node under the pointer.
17
24
  *
18
25
  * @class
19
26
  */
20
27
  export default class BabylonJSAnimationController {
21
28
  #scene = null;
29
+ #canvas = null;
22
30
  #animatedNodes = [];
23
31
  #highlightLayer = null;
24
- #highlightColor = new Color3(0, 1, 0); // Color para resaltar los elementos animados (Verde)
25
- #advancedDynamicTexture = null;
32
+ #highlightColor = Color3.FromHexString(PrefViewerColors.primary);
26
33
  #openingAnimations = [];
27
34
 
28
35
  /**
@@ -31,8 +38,8 @@ export default class BabylonJSAnimationController {
31
38
  */
32
39
  constructor(scene) {
33
40
  this.#scene = scene;
41
+ this.#canvas = this.#scene._engine._renderingCanvas;
34
42
  this.#initializeAnimations();
35
- this.#setupPointerObservers();
36
43
  }
37
44
 
38
45
  /**
@@ -40,11 +47,12 @@ export default class BabylonJSAnimationController {
40
47
  * @private
41
48
  */
42
49
  #initializeAnimations() {
50
+ this.hideMenu(); // Clean up any existing menus
43
51
  if (!this.#scene.animationGroups.length) {
44
52
  return;
45
53
  }
46
54
  this.#getAnimatedNodes();
47
- this.#getOpeneingAnimations();
55
+ this.#getOpeningAnimations();
48
56
  }
49
57
 
50
58
  /**
@@ -71,7 +79,7 @@ export default class BabylonJSAnimationController {
71
79
  * @description
72
80
  * Uses animation group names with the pattern "animation_open_<name>" and "animation_close_<name>".
73
81
  */
74
- #getOpeneingAnimations() {
82
+ #getOpeningAnimations() {
75
83
  const openings = {};
76
84
  this.#scene.animationGroups.forEach((animationGroup) => {
77
85
  const match = animationGroup.name.match(/^animation_(open|close)_(.+)$/);
@@ -122,12 +130,36 @@ export default class BabylonJSAnimationController {
122
130
  return nodeId;
123
131
  };
124
132
 
133
+ /**
134
+ * ---------------------------
135
+ * Public methods
136
+ * ---------------------------
137
+ */
138
+
139
+ /**
140
+ * Disposes all resources managed by the animation controller.
141
+ * Cleans up the highlight layer, animation menu, and internal animation/node lists.
142
+ * Should be called when the controller is no longer needed to prevent memory leaks.
143
+ * @public
144
+ */
145
+ dispose() {
146
+ if (this.#highlightLayer) {
147
+ this.#highlightLayer.removeAllMeshes();
148
+ this.#highlightLayer.dispose();
149
+ this.#highlightLayer = null;
150
+ }
151
+ this.hideMenu();
152
+ this.#animatedNodes = [];
153
+ this.#openingAnimations.forEach((openingAnimation) => openingAnimation.dispose());
154
+ this.#openingAnimations = [];
155
+ }
156
+
125
157
  /**
126
158
  * Highlights meshes that are children of an animated node when hovered.
127
- * @private
159
+ * @public
128
160
  * @param {PickingInfo} pickingInfo - Raycast info from pointer position.
129
161
  */
130
- #hightlightMeshesForAnimation(pickingInfo) {
162
+ hightlightMeshes(pickingInfo) {
131
163
  if (!this.#highlightLayer) {
132
164
  this.#highlightLayer = new HighlightLayer("hl_animations", this.#scene);
133
165
  }
@@ -150,52 +182,27 @@ export default class BabylonJSAnimationController {
150
182
  }
151
183
 
152
184
  /**
153
- * Sets up pointer observers to highlight animated nodes on hover and show the animation menu on click.
154
- * @private
155
- */
156
- #setupPointerObservers() {
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.
185
+ * Hides and disposes the animation control menu if it exists.
186
+ * @public
187
+ * @returns {void}
170
188
  */
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;
181
- }
182
- const pickingInfo = this.#scene.pick(pointerInfo.event.clientX, pointerInfo.event.clientY);
183
- this.#showMenu(pickingInfo);
184
- }
189
+ hideMenu() {
190
+ this.#openingAnimations.forEach((openingAnimation) => openingAnimation.hideControls());
191
+ this.#canvas.parentElement.querySelectorAll("div.pref-viewer-3d.animation-menu").forEach((menu) => menu.remove());
185
192
  }
186
193
 
187
194
  /**
188
195
  * Displays the animation control menu for the animated node under the pointer.
189
- * @private
196
+ * @public
190
197
  * @param {PickingInfo} pickingInfo - Raycast info from pointer position.
191
- * @description
192
- * Creates the GUI if needed and invokes OpeningAnimation.showControls.
193
198
  */
194
- #showMenu(pickingInfo) {
199
+ showMenu(pickingInfo) {
195
200
  if (!pickingInfo?.hit && !pickingInfo?.pickedMesh) {
196
201
  return;
197
202
  }
198
203
 
204
+ this.hideMenu();
205
+
199
206
  const nodeId = this.#getNodeAnimatedByMesh(pickingInfo.pickedMesh);
200
207
  if (!nodeId) {
201
208
  return;
@@ -204,32 +211,7 @@ export default class BabylonJSAnimationController {
204
211
  if (!openingAnimation) {
205
212
  return;
206
213
  }
207
- if (!this.#advancedDynamicTexture) {
208
- this.#advancedDynamicTexture = AdvancedDynamicTexture.CreateFullscreenUI("UI_Animation");
209
- }
210
- openingAnimation.showControls(this.#advancedDynamicTexture);
211
- }
212
214
 
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
- }
215
+ openingAnimation.showControls(this.#canvas);
234
216
  }
235
217
  }