@preference-sl/pref-viewer 2.1.9 → 2.2.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.
@@ -1,240 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <title>PrefViewer Test (Global Babylon)</title>
6
- <style>
7
- html, body {
8
- margin: 0;
9
- padding: 0;
10
- width: 100%;
11
- height: 100%;
12
- overflow: hidden;
13
- }
14
- #viewer-container {
15
- width: 100%;
16
- height: 100%;
17
- display: flex;
18
- align-items: center;
19
- justify-content: center;
20
- background: #f0f0f0;
21
- }
22
- </style>
23
-
24
- <!-- 1) Load Babylon Core (Global) -->
25
- <script src="https://cdn.babylonjs.com/babylon.js"></script>
26
- <!-- 2) Load Babylon glTF loader so SceneLoader.ImportMeshAsync can parse .gltf -->
27
- <script src="https://cdn.babylonjs.com/loaders/babylonjs.loaders.min.js"></script>
28
- </head>
29
- <body>
30
- <div id="viewer-container">
31
- <!-- Omit "model" attribute: PrefViewer will default to "./models/patata.gltf" -->
32
- <pref-viewer style="width: 800px; height: 600px; border: 1px solid #ccc;"></pref-viewer>
33
- </div>
34
-
35
- <!-- 3) Define PrefViewer using the global `BABYLON` object -->
36
- <script>
37
- (function () {
38
- const { Engine, Scene, ArcRotateCamera, Vector3, SceneLoader, Color4, HemisphericLight, DirectionalLight } = BABYLON;
39
-
40
- class PrefViewer extends HTMLElement {
41
- constructor() {
42
- super();
43
- this.attachShadow({ mode: "open" });
44
- this.canvas = document.createElement("canvas");
45
- Object.assign(this.canvas.style, {
46
- width: "100%",
47
- height: "100%",
48
- display: "block",
49
- });
50
-
51
- const wrapper = document.createElement("div");
52
- Object.assign(wrapper.style, {
53
- width: "100%",
54
- height: "100%",
55
- position: "relative",
56
- });
57
- wrapper.appendChild(this.canvas);
58
- this.shadowRoot.append(wrapper);
59
-
60
- this.engine = null;
61
- this.scene = null;
62
- this.camera = null;
63
- this.hemiLight = null;
64
- this.dirLight = null;
65
- this.modelUrl = null;
66
- this._onWindowResize = null;
67
- }
68
-
69
- static get observedAttributes() {
70
- return ["model"];
71
- }
72
-
73
- attributeChangedCallback(name, _oldValue, newValue) {
74
- if (name === "model" && newValue) {
75
- this.modelUrl = newValue;
76
- this._reloadModel();
77
- }
78
- }
79
-
80
- connectedCallback() {
81
- // If no `model` attribute is provided, default to "models/patata.gltf"
82
- if (!this.hasAttribute("model")) {
83
- // Note: NO import.meta.url here—just use a relative path.
84
- this.modelUrl = "models/patata.gltf";
85
- }
86
- this._initializeBabylon();
87
- }
88
-
89
- disconnectedCallback() {
90
- this._disposeEngine();
91
- if (this._onWindowResize) {
92
- window.removeEventListener("resize", this._onWindowResize);
93
- this._onWindowResize = null;
94
- }
95
- }
96
-
97
- // —— Private setup methods ——
98
-
99
- _initializeBabylon() {
100
- // 1) Create engine & scene
101
- this.engine = new Engine(this.canvas, true, { preserveDrawingBuffer: true, stencil: true, disableWebGL2Support: false });
102
- this.scene = new Scene(this.engine);
103
- this.scene.clearColor = new Color4(1, 1, 1, 1);
104
-
105
- // 2) Create camera & lights
106
- this._createCamera();
107
- this._createLights();
108
-
109
- // 3) Hook up events
110
- this._setupEventListeners();
111
-
112
- // 4) Start render loop
113
- this.engine.runRenderLoop(() => {
114
- if (this.scene) {
115
- this.scene.render();
116
- }
117
- });
118
- this._onWindowResize = () => this.engine.resize();
119
- window.addEventListener("resize", this._onWindowResize);
120
-
121
- // 5) Load the initial model
122
- this._reloadModel();
123
- }
124
-
125
- _createCamera() {
126
- // ArcRotateCamera around (0,0,0)
127
- const camera = new ArcRotateCamera(
128
- "camera",
129
- Math.PI / 2,
130
- Math.PI / 3,
131
- 10,
132
- Vector3.Zero(),
133
- this.scene
134
- );
135
- camera.attachControl(this.canvas, true);
136
- this.camera = camera;
137
- }
138
-
139
- _createLights() {
140
- // Hemispheric light (fills in shadows)
141
- const hemiLight = new HemisphericLight("hemiLight", new Vector3(0, 1, 0), this.scene);
142
- hemiLight.intensity = 0.8;
143
-
144
- // Directional key light
145
- const dirLight = new DirectionalLight("dirLight", new Vector3(-0.5, -1, -0.5), this.scene);
146
- dirLight.position = new Vector3(0, 5, 0);
147
- dirLight.intensity = 0.8;
148
-
149
- this.hemiLight = hemiLight;
150
- this.dirLight = dirLight;
151
- }
152
-
153
- _setupEventListeners() {
154
- // Zoom towards the pointer's picked point on wheel scroll:
155
- this.canvas.addEventListener("wheel", (evt) => {
156
- if (!this.scene || !this.camera) return;
157
- const pickResult = this.scene.pick(this.scene.pointerX, this.scene.pointerY);
158
- const pivotPoint = pickResult.hit
159
- ? pickResult.pickedPoint.clone()
160
- : this.camera.target.clone();
161
- this.camera.target = pivotPoint;
162
- this.camera.inertialRadiusOffset += evt.deltaY * this.camera.wheelPrecision * 0.01;
163
- evt.preventDefault();
164
- });
165
- }
166
-
167
- // —— Model loading / management ——
168
-
169
- async _reloadModel() {
170
- if (!this.scene || !this.modelUrl) return;
171
-
172
- // Dispose previous meshes (to avoid stacking them up)
173
- this._disposePreviousMeshes();
174
-
175
- try {
176
- const result = await SceneLoader.ImportMeshAsync(
177
- null,
178
- "",
179
- this.modelUrl,
180
- this.scene,
181
- undefined,
182
- ".gltf"
183
- );
184
-
185
- // Ensure there's at least one camera / light if glTF had none
186
- this.scene.createDefaultCameraOrLight(true, true, true);
187
-
188
- // Turn off back-face culling so you can see both sides
189
- result.meshes.forEach((mesh) => {
190
- if (mesh.material) {
191
- mesh.material.backFaceCulling = false;
192
- }
193
- });
194
-
195
- this.dispatchEvent(
196
- new CustomEvent("model-loaded", {
197
- detail: { meshes: result.meshes, particleSystems: result.particleSystems },
198
- bubbles: true,
199
- composed: true,
200
- })
201
- );
202
- } catch (err) {
203
- console.error("Error loading model:", err);
204
- this.dispatchEvent(
205
- new CustomEvent("model-error", {
206
- detail: { error: err },
207
- bubbles: true,
208
- composed: true,
209
- })
210
- );
211
- }
212
- }
213
-
214
- _disposePreviousMeshes() {
215
- if (!this.scene) return;
216
- this.scene.meshes.slice().forEach((mesh) => {
217
- if (mesh.getClassName && mesh.getClassName() === "Mesh") {
218
- mesh.dispose();
219
- }
220
- });
221
- }
222
-
223
- // —— Cleanup ——
224
-
225
- _disposeEngine() {
226
- if (this.engine) {
227
- this.engine.dispose();
228
- this.engine = null;
229
- this.scene = null;
230
- this.camera = null;
231
- }
232
- }
233
- }
234
-
235
- customElements.define("pref-viewer", PrefViewer);
236
- })();
237
- </script>
238
-
239
- </body>
240
- </html>
package/src/test.html DELETED
@@ -1,62 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <title>PrefViewer Test (Reuse Index.js)</title>
6
- <style>
7
- html, body {
8
- margin: 0;
9
- padding: 0;
10
- width: 100%;
11
- height: 100%;
12
- overflow: hidden;
13
- }
14
- #viewer-container {
15
- width: 100%;
16
- height: 100%;
17
- display: flex;
18
- align-items: center;
19
- justify-content: center;
20
- background: #f0f0f0;
21
- }
22
- </style>
23
-
24
- <!--
25
- IMPORT MAP
26
- ──────────
27
- This tells the browser where to fetch "@babylonjs/core" and "@babylonjs/loaders".
28
- We use jsDelivr's "?module" query so that it automatically serves the ESM build
29
- corresponding to each package's "module" field in package.json.
30
-
31
- Make sure the version (5.0.1 here) matches what you have in package.json.
32
- If you have "@babylonjs/core": "^5.0.2" in your package.json, change both URLs
33
- to "@5.0.2?module", etc.
34
-
35
- This import-map must appear *before* you load index.js as a module.
36
- -->
37
- <script type="importmap">
38
- {
39
- "imports": {
40
- "@babylonjs/core": "https://cdn.jsdelivr.net/npm/@babylonjs/core@5.0.1?module",
41
- "@babylonjs/loaders": "https://cdn.jsdelivr.net/npm/@babylonjs/loaders@5.0.1?module"
42
- }
43
- }
44
- </script>
45
- </head>
46
- <body>
47
- <div id="viewer-container">
48
- <!--
49
- By omitting the `model` attribute, PrefViewer’s connectedCallback()
50
- will fall back to "./models/patata.gltf" (relative to index.js).
51
- -->
52
- <pref-viewer style="width: 800px; height: 600px; border: 1px solid #ccc;"></pref-viewer>
53
- </div>
54
-
55
- <!--
56
- Load your existing ES-module index.js. Because of the import-map above,
57
- any `import { … } from "@babylonjs/core"` inside index.js will resolve to
58
- "https://cdn.jsdelivr.net/npm/@babylonjs/core@5.0.1?module", etc.
59
- -->
60
- <script type="module" src="./index.js"></script>
61
- </body>
62
- </html>