@2112-lab/central-plant 0.1.0 → 0.1.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.
Files changed (43) hide show
  1. package/dist/bundle/index.js +7782 -6543
  2. package/dist/cjs/_virtual/_rollupPluginBabelHelpers.js +23 -10
  3. package/dist/cjs/node_modules/@2112-lab/pathfinder/dist/index.esm.js +1448 -0
  4. package/dist/cjs/src/animationManager.js +15 -15
  5. package/dist/cjs/src/componentManager.js +8 -8
  6. package/dist/cjs/src/disposalManager.js +12 -12
  7. package/dist/cjs/src/environmentManager.js +392 -99
  8. package/dist/cjs/src/hotReloadManager.js +26 -26
  9. package/dist/cjs/src/index.js +19 -66
  10. package/dist/cjs/src/keyboardControlsManager.js +23 -23
  11. package/dist/cjs/src/nameUtils.js +21 -21
  12. package/dist/cjs/src/pathfindingManager.js +311 -129
  13. package/dist/cjs/src/performanceMonitor.js +52 -52
  14. package/dist/cjs/src/sceneExportManager.js +23 -23
  15. package/dist/cjs/src/sceneInitializationManager.js +18 -18
  16. package/dist/cjs/src/textureConfig.js +469 -40
  17. package/dist/cjs/src/transformControlsManager.js +79 -79
  18. package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +21 -10
  19. package/dist/esm/node_modules/@2112-lab/pathfinder/dist/index.esm.js +1444 -0
  20. package/dist/esm/src/animationManager.js +15 -15
  21. package/dist/esm/src/componentManager.js +8 -8
  22. package/dist/esm/src/disposalManager.js +12 -12
  23. package/dist/esm/src/environmentManager.js +393 -100
  24. package/dist/esm/src/hotReloadManager.js +26 -26
  25. package/dist/esm/src/index.js +19 -66
  26. package/dist/esm/src/keyboardControlsManager.js +23 -23
  27. package/dist/esm/src/nameUtils.js +21 -21
  28. package/dist/esm/src/pathfindingManager.js +313 -129
  29. package/dist/esm/src/performanceMonitor.js +52 -52
  30. package/dist/esm/src/sceneExportManager.js +23 -23
  31. package/dist/esm/src/sceneInitializationManager.js +18 -18
  32. package/dist/esm/src/textureConfig.js +469 -42
  33. package/dist/esm/src/transformControlsManager.js +79 -79
  34. package/dist/index.d.ts +255 -259
  35. package/package.json +52 -53
  36. package/dist/cjs/src/ConnectionManager.js +0 -114
  37. package/dist/cjs/src/Pathfinder.js +0 -88
  38. package/dist/cjs/src/modelPreloader.js +0 -360
  39. package/dist/cjs/src/sceneOperationsManager.js +0 -560
  40. package/dist/esm/src/ConnectionManager.js +0 -110
  41. package/dist/esm/src/Pathfinder.js +0 -84
  42. package/dist/esm/src/modelPreloader.js +0 -337
  43. package/dist/esm/src/sceneOperationsManager.js +0 -536
@@ -1,9 +1,51 @@
1
- import { asyncToGenerator as _asyncToGenerator, regenerator as _regenerator, objectSpread2 as _objectSpread2 } from '../_virtual/_rollupPluginBabelHelpers.js';
1
+ import { asyncToGenerator as _asyncToGenerator, regenerator as _regenerator, slicedToArray as _slicedToArray, objectSpread2 as _objectSpread2 } from '../_virtual/_rollupPluginBabelHelpers.js';
2
2
  import * as THREE from 'three';
3
3
 
4
+ /**
5
+ * Helper function to get asset paths that works in both bundled and modular contexts
6
+ * @param {string} assetPath - Relative path from the assets directory
7
+ * @returns {string} - The full path to the asset
8
+ */
9
+ function getAssetPath(assetPath) {
10
+ // Strip leading slash if present
11
+ if (assetPath.startsWith('/')) {
12
+ assetPath = assetPath.substring(1);
13
+ }
14
+
15
+ // In browser context, check for different module formats
16
+ if (typeof window !== 'undefined') {
17
+ // For bundled version, assets should be in dist/bundle/assets/
18
+ // For ESM/CJS, assets should be in their respective folders
19
+
20
+ // Try to determine if we're using the bundled version or ESM/CJS
21
+ var isBundled = typeof CentralPlantUtils !== 'undefined';
22
+
23
+ // Check if we're running in a Nuxt.js environment (localhost:3000 is a common dev server)
24
+ var isNuxtEnv = window.location.hostname === 'localhost' && (window.location.port === '3000' || window.location.port === '3001');
25
+ if (isNuxtEnv) {
26
+ // In Nuxt.js environment, assets are likely in the /static directory at the root
27
+ return "/".concat(assetPath); // No /assets/ prefix in the URL path
28
+ } else if (isBundled) {
29
+ // Get the base URL for the module
30
+ var baseUrl = import.meta.url;
31
+ // In bundled format, assets are in the assets folder next to the bundle
32
+ return new URL("./assets/".concat(assetPath), baseUrl).href;
33
+ } else {
34
+ // Get the base URL for the module
35
+ var _baseUrl = import.meta.url;
36
+ // In ESM/CJS format, need to go up relative to current module path
37
+ return new URL("../assets/".concat(assetPath), _baseUrl).href;
38
+ }
39
+ }
40
+
41
+ // In Node.js context
42
+ return "assets/".concat(assetPath);
43
+ }
4
44
  var TEXTURE_SETS = {
5
45
  // Light metallic texture using the gravel_embedded_concrete with metallic properties
6
46
  light_metal: {
47
+ // Local path first, with fallback to S3
48
+ localPath: 'textures/gravel_embedded_concrete_1k',
7
49
  path: 'https://central-plant-assets.s3.us-east-1.amazonaws.com/textures/gravel_embedded_concrete_1k',
8
50
  files: {
9
51
  diffuse: 'diffuse.jpg',
@@ -29,6 +71,8 @@ var TEXTURE_SETS = {
29
71
  }
30
72
  },
31
73
  brick: {
74
+ // Local path first, with fallback to S3
75
+ localPath: 'textures/pavement_03_1k',
32
76
  path: 'https://central-plant-assets.s3.us-east-1.amazonaws.com/textures/pavement_03_1k',
33
77
  files: {
34
78
  diffuse: 'diffuse.jpg',
@@ -51,6 +95,8 @@ var TEXTURE_SETS = {
51
95
  }
52
96
  },
53
97
  gravel_embedded_concrete: {
98
+ // Local path first, with fallback to S3
99
+ localPath: 'textures/gravel_embedded_concrete_1k',
54
100
  path: 'https://central-plant-assets.s3.us-east-1.amazonaws.com/textures/gravel_embedded_concrete_1k',
55
101
  files: {
56
102
  diffuse: 'diffuse.jpg',
@@ -71,8 +117,8 @@ var TEXTURE_SETS = {
71
117
  }
72
118
  };
73
119
 
74
- /**
75
- * Create a Three.js texture with appropriate settings
120
+ /**
121
+ * Create a Three.js texture with appropriate settings
76
122
  */
77
123
  function createTexture(textureLoader, url) {
78
124
  var repeat = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {
@@ -83,86 +129,467 @@ function createTexture(textureLoader, url) {
83
129
  textureLoader = new THREE.TextureLoader();
84
130
  }
85
131
  try {
86
- var texture = textureLoader.load(url);
87
- texture.wrapS = THREE.RepeatWrapping;
88
- texture.wrapT = THREE.RepeatWrapping;
89
- texture.repeat.set(repeat.x, repeat.y);
90
- texture.colorSpace = THREE.SRGBColorSpace;
91
- return texture;
132
+ console.log("\uD83D\uDD0D Beginning texture load from: ".concat(url));
133
+
134
+ // Create placeholder texture for immediate use
135
+ // This will prevent the "no image data found" warning
136
+ var placeholderTexture = createPlaceholderTexture(0xcccccc);
137
+
138
+ // Create a promise to track when the real texture is loaded
139
+ var loadPromise = new Promise(function (resolve, reject) {
140
+ textureLoader.load(url, function (loadedTexture) {
141
+ console.log("\u2705 Successfully loaded texture from: ".concat(url));
142
+
143
+ // Check if the loaded texture has valid image data
144
+ if (loadedTexture.image && (loadedTexture.image instanceof HTMLImageElement && loadedTexture.image.complete || !(loadedTexture.image instanceof HTMLImageElement))) {
145
+ console.log("\u2705 Image data verified for ".concat(url));
146
+
147
+ // Explicitly set colorSpace for all textures to ensure proper rendering
148
+ if (loadedTexture.colorSpace !== undefined) {
149
+ loadedTexture.colorSpace = THREE.SRGBColorSpace;
150
+ console.log("\uD83C\uDFA8 Set colorSpace to SRGBColorSpace for ".concat(url));
151
+ } else if (loadedTexture.encoding !== undefined) {
152
+ loadedTexture.encoding = THREE.sRGBEncoding;
153
+ console.log("\uD83C\uDFA8 Set encoding to sRGBEncoding for ".concat(url));
154
+ }
155
+
156
+ // Configure texture properties
157
+ loadedTexture.wrapS = THREE.RepeatWrapping;
158
+ loadedTexture.wrapT = THREE.RepeatWrapping;
159
+ loadedTexture.repeat.set(repeat.x, repeat.y);
160
+ loadedTexture.needsUpdate = true;
161
+ resolve(loadedTexture);
162
+ } else {
163
+ console.warn("\u26A0\uFE0F Loaded texture from ".concat(url, " but image data is not ready"));
164
+ reject(new Error('Texture loaded but image data not ready'));
165
+ }
166
+ }, function (progressEvent) {
167
+ if (progressEvent.lengthComputable) {
168
+ var percentComplete = progressEvent.loaded / progressEvent.total * 100;
169
+ console.log("Loading texture ".concat(url, ": ").concat(Math.round(percentComplete), "% complete"));
170
+ }
171
+ }, function (error) {
172
+ console.error("\u274C Error loading texture from ".concat(url, ":"), error);
173
+ reject(error);
174
+ });
175
+ });
176
+
177
+ // Configure placeholder texture properties
178
+ placeholderTexture.wrapS = THREE.RepeatWrapping;
179
+ placeholderTexture.wrapT = THREE.RepeatWrapping;
180
+ placeholderTexture.repeat.set(repeat.x, repeat.y);
181
+
182
+ // Store the load promise and url for later reference
183
+ placeholderTexture.loadPromise = loadPromise;
184
+ placeholderTexture.url = url;
185
+
186
+ // When the real texture loads, we'll swap it in
187
+ loadPromise.then(function (realTexture) {
188
+ // Copy all properties from the real texture to the placeholder
189
+ Object.keys(realTexture).forEach(function (key) {
190
+ // Skip certain properties that shouldn't be copied
191
+ if (['uuid', 'id', 'version', 'isTexture'].includes(key)) return;
192
+ placeholderTexture[key] = realTexture[key];
193
+ });
194
+ placeholderTexture.image = realTexture.image;
195
+ placeholderTexture.source = realTexture.source;
196
+ placeholderTexture.needsUpdate = true;
197
+ console.log("\uD83D\uDD04 Updated placeholder texture with real image data for ".concat(url));
198
+ }).catch(function () {
199
+ console.warn("\u26A0\uFE0F Using placeholder for texture: ".concat(url));
200
+ });
201
+ return placeholderTexture;
92
202
  } catch (error) {
93
203
  console.error("Failed to load texture: ".concat(url), error);
94
- return null;
204
+ return createPlaceholderTexture(0xdd3333); // Red placeholder for errors
95
205
  }
96
206
  }
97
207
 
98
- /**
99
- * Load a texture set and create a material
208
+ /**
209
+ * Load a texture set and create a material
100
210
  */
101
211
  function loadTextureSetAndCreateMaterial(_x, _x2) {
102
212
  return _loadTextureSetAndCreateMaterial.apply(this, arguments);
103
213
  }
214
+
215
+ /**
216
+ * Check if a texture has valid image data
217
+ * @param {THREE.Texture} texture - The texture to check
218
+ * @returns {boolean} - Whether the texture has valid image data
219
+ */
104
220
  function _loadTextureSetAndCreateMaterial() {
105
- _loadTextureSetAndCreateMaterial = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(component, textureSetName) {
106
- var textureSet, textureLoader, repeat, loadedTextures, loadTexture, material;
107
- return _regenerator().w(function (_context) {
108
- while (1) switch (_context.n) {
221
+ _loadTextureSetAndCreateMaterial = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee4(component, textureSetName) {
222
+ var _textureSet$materialP2;
223
+ var textureSet, textureLoader, repeat, loadedTextures, checkFileExists, loadTexture, texturePromises, hasAnyTextures, _textureSet$materialP, fallbackColor, texturesWithValidData, _i2, _Object$entries, _Object$entries$_i, type, texture, material;
224
+ return _regenerator().w(function (_context4) {
225
+ while (1) switch (_context4.n) {
109
226
  case 0:
110
227
  if (component) {
111
- _context.n = 1;
228
+ _context4.n = 1;
112
229
  break;
113
230
  }
114
231
  console.warn('Component is required for texture loading');
115
- return _context.a(2, new THREE.MeshStandardMaterial({
232
+ return _context4.a(2, new THREE.MeshStandardMaterial({
116
233
  color: 0xaaaaaa
117
234
  }));
118
235
  case 1:
119
236
  textureSet = TEXTURE_SETS[textureSetName];
120
237
  if (textureSet) {
121
- _context.n = 2;
238
+ _context4.n = 2;
122
239
  break;
123
240
  }
124
241
  console.warn("Texture set not found: ".concat(textureSetName));
125
- return _context.a(2, new THREE.MeshStandardMaterial({
242
+ return _context4.a(2, new THREE.MeshStandardMaterial({
126
243
  color: 0xaaaaaa
127
244
  }));
128
245
  case 2:
129
- textureLoader = component.textureLoader || new THREE.TextureLoader();
246
+ console.log("\uD83C\uDF08 Loading texture set: ".concat(textureSetName));
247
+ textureLoader = component.textureLoader || new THREE.TextureLoader(); // Set cross-origin attribute to allow texture loading from different domains
248
+ if (typeof textureLoader.setCrossOrigin === 'function') {
249
+ textureLoader.setCrossOrigin('anonymous');
250
+ console.log('📡 Set cross-origin to anonymous for texture loading');
251
+ }
130
252
  repeat = textureSet.repeat || {
131
253
  x: 1,
132
254
  y: 1
133
255
  };
134
- loadedTextures = {}; // Function to load a specific texture from the set
135
- loadTexture = function loadTexture(type) {
136
- if (!textureSet.files[type]) return null;
137
- var url = "".concat(textureSet.path, "/").concat(textureSet.files[type]);
138
- return createTexture(textureLoader, url, repeat);
139
- }; // Load all textures in the set
140
- Object.keys(textureSet.files).forEach(function (type) {
141
- loadedTextures[type] = loadTexture(type);
256
+ loadedTextures = {}; // Function to check if a file exists
257
+ checkFileExists = /*#__PURE__*/function () {
258
+ var _ref = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee(url) {
259
+ return _regenerator().w(function (_context) {
260
+ while (1) switch (_context.n) {
261
+ case 0:
262
+ if (!(typeof window !== 'undefined')) {
263
+ _context.n = 1;
264
+ break;
265
+ }
266
+ return _context.a(2, new Promise(function (resolve) {
267
+ var img = new Image();
268
+ img.onload = function () {
269
+ return resolve(true);
270
+ };
271
+ img.onerror = function () {
272
+ return resolve(false);
273
+ };
274
+ img.src = url;
275
+ setTimeout(function () {
276
+ return resolve(false);
277
+ }, 2000);
278
+ }));
279
+ case 1:
280
+ return _context.a(2, false);
281
+ }
282
+ }, _callee);
283
+ }));
284
+ return function checkFileExists(_x3) {
285
+ return _ref.apply(this, arguments);
286
+ };
287
+ }(); // Function to load a specific texture from the set
288
+ loadTexture = /*#__PURE__*/function () {
289
+ var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2(type) {
290
+ var paths, _i, _paths, path, exists;
291
+ return _regenerator().w(function (_context2) {
292
+ while (1) switch (_context2.n) {
293
+ case 0:
294
+ if (textureSet.files[type]) {
295
+ _context2.n = 1;
296
+ break;
297
+ }
298
+ return _context2.a(2, null);
299
+ case 1:
300
+ // Try multiple paths to find the texture
301
+ paths = []; // 1. Try local bundled path first
302
+ if (textureSet.localPath) {
303
+ paths.push(getAssetPath("".concat(textureSet.localPath, "/").concat(textureSet.files[type])));
304
+ }
305
+
306
+ // 2. Try direct path to static folder
307
+ paths.push("/textures/".concat(textureSetName, "_1k/").concat(textureSet.files[type]));
308
+
309
+ // 3. Try remote path as fallback
310
+ if (textureSet.path) {
311
+ paths.push("".concat(textureSet.path, "/").concat(textureSet.files[type]));
312
+ }
313
+ console.log("\uD83D\uDD0D Will try loading texture ".concat(type, " from paths:"), paths);
314
+
315
+ // Try each path until one works
316
+ _i = 0, _paths = paths;
317
+ case 2:
318
+ if (!(_i < _paths.length)) {
319
+ _context2.n = 6;
320
+ break;
321
+ }
322
+ path = _paths[_i];
323
+ console.log("\uD83D\uDD04 Checking if texture exists at: ".concat(path));
324
+ _context2.n = 3;
325
+ return checkFileExists(path);
326
+ case 3:
327
+ exists = _context2.v;
328
+ if (!exists) {
329
+ _context2.n = 4;
330
+ break;
331
+ }
332
+ console.log("\u2705 Texture found at: ".concat(path));
333
+ return _context2.a(2, createTexture(textureLoader, path, repeat));
334
+ case 4:
335
+ console.log("\u274C Texture not found at: ".concat(path));
336
+ case 5:
337
+ _i++;
338
+ _context2.n = 2;
339
+ break;
340
+ case 6:
341
+ console.error("\u274C Failed to load ".concat(type, " texture from any path"));
342
+ return _context2.a(2, null);
343
+ }
344
+ }, _callee2);
345
+ }));
346
+ return function loadTexture(_x4) {
347
+ return _ref2.apply(this, arguments);
348
+ };
349
+ }(); // Load all textures in the set
350
+ texturePromises = Object.keys(textureSet.files).map(/*#__PURE__*/function () {
351
+ var _ref3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee3(type) {
352
+ return _regenerator().w(function (_context3) {
353
+ while (1) switch (_context3.n) {
354
+ case 0:
355
+ _context3.n = 1;
356
+ return loadTexture(type);
357
+ case 1:
358
+ loadedTextures[type] = _context3.v;
359
+ return _context3.a(2, {
360
+ type: type,
361
+ texture: loadedTextures[type]
362
+ });
363
+ }
364
+ }, _callee3);
365
+ }));
366
+ return function (_x5) {
367
+ return _ref3.apply(this, arguments);
368
+ };
369
+ }());
370
+ _context4.n = 3;
371
+ return Promise.all(texturePromises);
372
+ case 3:
373
+ // Log successful texture loads
374
+ Object.entries(loadedTextures).forEach(function (_ref4) {
375
+ var _ref5 = _slicedToArray(_ref4, 2),
376
+ type = _ref5[0],
377
+ texture = _ref5[1];
378
+ console.log("".concat(texture ? '✅' : '❌', " ").concat(type, " texture: ").concat(texture ? 'Loaded' : 'Failed'));
379
+ }); // Create material with textures and properties
380
+ console.log('Creating material with loaded textures and properties:', textureSet.materialProps);
381
+
382
+ // Check if we have at least one texture that's not null
383
+ hasAnyTextures = Object.values(loadedTextures).some(function (texture) {
384
+ return texture !== null;
142
385
  });
386
+ if (hasAnyTextures) {
387
+ _context4.n = 4;
388
+ break;
389
+ }
390
+ console.warn('⚠️ No textures loaded successfully for material. Using fallback color material.');
391
+
392
+ // Create a colored material as fallback
393
+ fallbackColor = ((_textureSet$materialP = textureSet.materialProps) === null || _textureSet$materialP === void 0 ? void 0 : _textureSet$materialP.color) || 0xaaaaaa;
394
+ return _context4.a(2, new THREE.MeshStandardMaterial({
395
+ color: fallbackColor,
396
+ roughness: 0.8,
397
+ metalness: 0.2,
398
+ side: THREE.DoubleSide
399
+ }));
400
+ case 4:
401
+ // Verify if the textures have valid image data
402
+ texturesWithValidData = {};
403
+ for (_i2 = 0, _Object$entries = Object.entries(loadedTextures); _i2 < _Object$entries.length; _i2++) {
404
+ _Object$entries$_i = _slicedToArray(_Object$entries[_i2], 2), type = _Object$entries$_i[0], texture = _Object$entries$_i[1];
405
+ if (texture && hasValidImageData(texture)) {
406
+ console.log("\u2705 Texture '".concat(type, "' has valid image data"));
407
+ texturesWithValidData[type] = texture;
408
+ } else if (texture) {
409
+ console.log("\u26A0\uFE0F Texture '".concat(type, "' doesn't have valid image data yet"));
410
+ // Keep the texture even if it doesn't have valid data yet
411
+ // Our createTexture function now handles this with placeholders
412
+ texturesWithValidData[type] = texture;
413
+ }
414
+ }
415
+
416
+ // Create the standard material with loaded textures
417
+ material = new THREE.MeshStandardMaterial(_objectSpread2(_objectSpread2({
418
+ map: texturesWithValidData.diffuse,
419
+ normalMap: texturesWithValidData.normal,
420
+ roughnessMap: texturesWithValidData.roughness,
421
+ metalnessMap: texturesWithValidData.metalness,
422
+ aoMap: texturesWithValidData.ao,
423
+ displacementMap: texturesWithValidData.displacement
424
+ }, textureSet.materialProps), {}, {
425
+ side: THREE.DoubleSide // Always set DoubleSide to avoid rendering issues
426
+ })); // Ensure color is applied even if textures are loading
427
+
428
+ if ((!material.map || !hasValidImageData(material.map)) && (_textureSet$materialP2 = textureSet.materialProps) !== null && _textureSet$materialP2 !== void 0 && _textureSet$materialP2.color) {
429
+ material.color = new THREE.Color(textureSet.materialProps.color);
430
+ console.log("\uD83C\uDFA8 Applied fallback color: #".concat(material.color.getHexString()));
431
+ }
143
432
 
144
- // Create material with textures and properties
145
- material = new THREE.MeshStandardMaterial(_objectSpread2({
146
- map: loadedTextures.diffuse,
147
- normalMap: loadedTextures.normal,
148
- roughnessMap: loadedTextures.roughness,
149
- metalnessMap: loadedTextures.metalness,
150
- aoMap: loadedTextures.ao,
151
- displacementMap: loadedTextures.displacement
152
- }, textureSet.materialProps)); // Add the environment map if available from the component
433
+ // Make sure material updates when textures load
434
+ material.needsUpdate = true;
435
+
436
+ // Add the environment map if available from the component
153
437
  if (component.scene && component.scene.environment) {
154
438
  material.envMap = component.scene.environment;
439
+ console.log('🌐 Added environment map to material');
155
440
  }
156
- return _context.a(2, material);
441
+
442
+ // Set up texture load monitoring for each texture with a load promise
443
+ Object.entries(texturesWithValidData).forEach(function (_ref6) {
444
+ var _ref7 = _slicedToArray(_ref6, 2),
445
+ type = _ref7[0],
446
+ texture = _ref7[1];
447
+ if (texture && texture.loadPromise) {
448
+ texture.loadPromise.then(function () {
449
+ console.log("\u2705 Texture '".concat(type, "' finished loading, updating material"));
450
+ material.needsUpdate = true;
451
+ }).catch(function (error) {
452
+ console.warn("\u26A0\uFE0F Failed to load '".concat(type, "' texture:"), error);
453
+ });
454
+ }
455
+ });
456
+ return _context4.a(2, material);
157
457
  }
158
- }, _callee);
458
+ }, _callee4);
159
459
  }));
160
460
  return _loadTextureSetAndCreateMaterial.apply(this, arguments);
161
461
  }
462
+ function hasValidImageData(texture) {
463
+ if (!texture) return false;
464
+
465
+ // Check if image exists
466
+ if (!texture.image) return false;
467
+
468
+ // For image objects, check width and height
469
+ if (texture.image instanceof HTMLImageElement || texture.image instanceof HTMLCanvasElement) {
470
+ return texture.image.width > 0 && texture.image.height > 0;
471
+ }
472
+
473
+ // For other image types (like ImageBitmap)
474
+ if (texture.image.data && Array.isArray(texture.image.data)) {
475
+ return texture.image.data.length > 0;
476
+ }
477
+ return false;
478
+ }
479
+
480
+ /**
481
+ * Create a placeholder colored texture when image loading fails
482
+ * @param {number} color - The color for the placeholder texture
483
+ * @param {number} size - The size of the texture in pixels
484
+ * @returns {THREE.Texture} - A colored placeholder texture
485
+ */
486
+ function createPlaceholderTexture() {
487
+ var color = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0xcccccc;
488
+ var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 64;
489
+ // Create a canvas element
490
+ var canvas = document.createElement('canvas');
491
+ canvas.width = size;
492
+ canvas.height = size;
493
+
494
+ // Get the 2D context and fill with color
495
+ var context = canvas.getContext('2d');
496
+ if (context) {
497
+ var hexColor = '#' + color.toString(16).padStart(6, '0');
498
+ context.fillStyle = hexColor;
499
+ context.fillRect(0, 0, size, size);
500
+
501
+ // Optional: Add a pattern to make it obvious it's a placeholder
502
+ context.fillStyle = '#' + (color + 0x222222 & 0xffffff).toString(16);
503
+ context.fillRect(0, 0, size / 2, size / 2);
504
+ context.fillRect(size / 2, size / 2, size / 2, size / 2);
505
+ }
506
+
507
+ // Create a texture from the canvas
508
+ var texture = new THREE.CanvasTexture(canvas);
509
+ texture.needsUpdate = true;
510
+
511
+ // Set proper color space
512
+ if (texture.colorSpace !== undefined) {
513
+ texture.colorSpace = THREE.SRGBColorSpace;
514
+ } else if (texture.encoding !== undefined) {
515
+ texture.encoding = THREE.sRGBEncoding;
516
+ }
517
+ return texture;
518
+ }
519
+
520
+ /**
521
+ * Helper function to check Three.js compatibility and configuration
522
+ */
523
+ function checkThreeJSCompatibility() {
524
+ console.group('🔍 Three.js Compatibility Check');
525
+
526
+ // Check Three.js version
527
+ console.log('Three.js version:', THREE.REVISION);
528
+
529
+ // Check color space constants
530
+ console.log('Color space support:', {
531
+ SRGBColorSpace: typeof THREE.SRGBColorSpace !== 'undefined',
532
+ LinearSRGBColorSpace: typeof THREE.LinearSRGBColorSpace !== 'undefined',
533
+ sRGBEncoding: typeof THREE.sRGBEncoding !== 'undefined'
534
+ });
535
+
536
+ // Check texture-related features
537
+ console.log('Texture features:', {
538
+ TextureLoader: typeof THREE.TextureLoader === 'function',
539
+ RepeatWrapping: typeof THREE.RepeatWrapping !== 'undefined',
540
+ MirroredRepeatWrapping: typeof THREE.MirroredRepeatWrapping !== 'undefined'
541
+ });
542
+
543
+ // Check shader and material features
544
+ console.log('Material features:', {
545
+ MeshStandardMaterial: typeof THREE.MeshStandardMaterial === 'function',
546
+ MeshBasicMaterial: typeof THREE.MeshBasicMaterial === 'function',
547
+ ShaderMaterial: typeof THREE.ShaderMaterial === 'function'
548
+ });
549
+ console.groupEnd();
550
+ return {
551
+ version: THREE.REVISION,
552
+ hasNewColorSpace: typeof THREE.SRGBColorSpace !== 'undefined',
553
+ hasOldEncoding: typeof THREE.sRGBEncoding !== 'undefined',
554
+ hasTextureLoader: typeof THREE.TextureLoader === 'function'
555
+ };
556
+ }
557
+ function forceUpdateMaterials(scene) {
558
+ if (!scene) return;
559
+ console.log('🔄 Forcing update on all scene materials...');
560
+ var materialCount = 0;
561
+ scene.traverse(function (node) {
562
+ if (node.isMesh && node.material) {
563
+ var materials = Array.isArray(node.material) ? node.material : [node.material];
564
+ materials.forEach(function (material) {
565
+ if (material) {
566
+ material.needsUpdate = true;
567
+ materialCount++;
568
+
569
+ // Ensure maps are properly set
570
+ if (material.map) {
571
+ material.map.needsUpdate = true;
572
+ }
573
+ if (material.normalMap) {
574
+ material.normalMap.needsUpdate = true;
575
+ }
576
+ if (material.roughnessMap) {
577
+ material.roughnessMap.needsUpdate = true;
578
+ }
579
+ }
580
+ });
581
+ }
582
+ });
583
+ console.log("\u2705 Updated ".concat(materialCount, " materials in the scene"));
584
+ }
162
585
  var textureConfig = {
163
586
  TEXTURE_SETS: TEXTURE_SETS,
164
587
  createTexture: createTexture,
165
- loadTextureSetAndCreateMaterial: loadTextureSetAndCreateMaterial
588
+ loadTextureSetAndCreateMaterial: loadTextureSetAndCreateMaterial,
589
+ checkThreeJSCompatibility: checkThreeJSCompatibility,
590
+ forceUpdateMaterials: forceUpdateMaterials,
591
+ hasValidImageData: hasValidImageData,
592
+ createPlaceholderTexture: createPlaceholderTexture
166
593
  };
167
594
 
168
- export { TEXTURE_SETS, createTexture, textureConfig as default, loadTextureSetAndCreateMaterial };
595
+ export { TEXTURE_SETS, checkThreeJSCompatibility, createTexture, textureConfig as default, forceUpdateMaterials, loadTextureSetAndCreateMaterial };