babylon.quarks 0.18.0 → 0.19.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,17 +1,14 @@
1
- import {Scene} from '@babylonjs/core/scene';
2
- import {TransformNode} from '@babylonjs/core/Meshes/transformNode';
3
- import {Mesh} from '@babylonjs/core/Meshes/mesh';
4
- import {VertexData} from '@babylonjs/core/Meshes/mesh.vertexData';
1
+ import {Constants} from '@babylonjs/core/Engines/constants';
5
2
  import {Texture} from '@babylonjs/core/Materials/Textures/texture';
6
3
  import {StandardMaterial} from '@babylonjs/core/Materials/standardMaterial';
7
- import {Constants} from '@babylonjs/core/Engines/constants';
8
4
  import {Matrix, Quaternion, Vector3} from '@babylonjs/core/Maths/math.vector';
9
- import {
10
- Behavior,
11
- EmitSubParticleSystem,
12
- } from 'quarks.core';
13
- import {ParticleSystem} from './ParticleSystem';
5
+ import {Mesh} from '@babylonjs/core/Meshes/mesh';
6
+ import {VertexData} from '@babylonjs/core/Meshes/mesh.vertexData';
7
+ import {TransformNode} from '@babylonjs/core/Meshes/transformNode';
8
+ import {Scene} from '@babylonjs/core/scene';
9
+ import {Behavior, EmitSubParticleSystem} from 'quarks.core';
14
10
  import {ParticleEmitter} from './ParticleEmitter';
11
+ import {ParticleSystem} from './ParticleSystem';
15
12
  import {QuarksPrefab} from './QuarksPrefab';
16
13
  import {ensureTriangleIndices} from './geometryUtil';
17
14
 
@@ -194,7 +191,8 @@ export class QuarksLoader {
194
191
  if (data.attributes.position?.isInterleavedBufferAttribute) {
195
192
  const attr = data.attributes.position;
196
193
  const buf = buffers[attr.data];
197
- if (buf) positions = this.extractInterleavedAttribute(buf.data, buf.stride, attr.offset, attr.itemSize);
194
+ if (buf)
195
+ positions = this.extractInterleavedAttribute(buf.data, buf.stride, attr.offset, attr.itemSize);
198
196
  }
199
197
  if (data.attributes.uv?.isInterleavedBufferAttribute) {
200
198
  const attr = data.attributes.uv;
@@ -204,7 +202,8 @@ export class QuarksLoader {
204
202
  if (data.attributes.normal?.isInterleavedBufferAttribute) {
205
203
  const attr = data.attributes.normal;
206
204
  const buf = buffers[attr.data];
207
- if (buf) normals = this.extractInterleavedAttribute(buf.data, buf.stride, attr.offset, attr.itemSize);
205
+ if (buf)
206
+ normals = this.extractInterleavedAttribute(buf.data, buf.stride, attr.offset, attr.itemSize);
208
207
  }
209
208
  }
210
209
  } else if (data.attributes) {
@@ -255,8 +254,43 @@ export class QuarksLoader {
255
254
  private parseImages(images: any[], baseUrl: string, _meta: LoadedMeta): void {
256
255
  (this as any)._images = {};
257
256
  for (const img of images) {
258
- (this as any)._images[img.uuid] = img.url ? baseUrl + img.url : null;
257
+ if (img.url) {
258
+ QuarksLoader.warnIfNotAnImageUrl(img.url);
259
+ }
260
+ (this as any)._images[img.uuid] = img.url ? this.resolveImageUrl(baseUrl, img.url) : null;
261
+ }
262
+ }
263
+
264
+ /**
265
+ * Flags an image entry that is plainly not an image, which otherwise only
266
+ * shows up as a texture that silently fails to load.
267
+ *
268
+ * The case worth naming: an exporter that could not embed a texture falls
269
+ * back to writing the source asset's path, and a Unity built-in texture
270
+ * reports a virtual path such as `Resources/unity_builtin_extra` that no
271
+ * file backs.
272
+ */
273
+ private static warnIfNotAnImageUrl(url: string): void {
274
+ if (/^(data|blob):/i.test(url) || /\.(png|jpe?g|webp|gif|bmp|ktx2?|dds|env|basis)(\?|#|$)/i.test(url)) {
275
+ return;
259
276
  }
277
+ console.warn(
278
+ `[QuarksLoader] Image "${url}" does not look like an image; its texture will fail to load. ` +
279
+ 'This usually means the effect was exported without embedding that texture.'
280
+ );
281
+ }
282
+
283
+ /**
284
+ * `img.url` is already absolute for data/blob URIs and full http(s) URLs — common for
285
+ * "portable" exports that embed textures as base64 (see ensurePortableTextureUrl in
286
+ * babylon.quarks-editor). Prepending baseUrl to those turns e.g.
287
+ * "data:image/png;base64,AAAA" into an invalid path like "/some/dir/data:image/png;base64,AAAA".
288
+ */
289
+ private resolveImageUrl(baseUrl: string, url: string): string {
290
+ if (/^(data|blob):/i.test(url) || /^[a-z][a-z0-9+.-]*:\/\//i.test(url) || url.startsWith('/')) {
291
+ return url;
292
+ }
293
+ return baseUrl + url;
260
294
  }
261
295
 
262
296
  private parseTextures(textures: any[], meta: LoadedMeta): void {
@@ -264,7 +298,13 @@ export class QuarksLoader {
264
298
  for (const texDef of textures) {
265
299
  const imageUrl = images[texDef.image];
266
300
  if (imageUrl) {
267
- const texture = new Texture(imageUrl, this.scene);
301
+ const invertY = texDef.invertY !== undefined ? !!texDef.invertY : true;
302
+ const noMipmap = !!texDef.noMipmap;
303
+ const texture = new Texture(imageUrl, this.scene, {
304
+ noMipmap,
305
+ invertY,
306
+ samplingMode: typeof texDef.samplingMode === 'number' ? texDef.samplingMode : undefined,
307
+ });
268
308
  if (Array.isArray(texDef.wrap)) {
269
309
  texture.wrapU = this.mapWrapMode(texDef.wrap[0]);
270
310
  texture.wrapV = this.mapWrapMode(texDef.wrap[1] ?? texDef.wrap[0]);
@@ -319,6 +359,14 @@ export class QuarksLoader {
319
359
  matInfo.texture = meta.textures[textureRef] || null;
320
360
  }
321
361
 
362
+ const reflectionAtlasRef = matDef.reflectionAtlas;
363
+ if (reflectionAtlasRef) {
364
+ matInfo.reflectionAtlas = meta.textures[reflectionAtlasRef] || null;
365
+ }
366
+ if (typeof matDef.reflectionLevel === 'number') {
367
+ matInfo.reflectionLevel = matDef.reflectionLevel;
368
+ }
369
+
322
370
  // QuarksMaterial (what ParticleSystem.ensureMaterialMeta emits) writes `alphaMode`
323
371
  // directly as a Babylon alpha-mode constant; three.js materials (MeshBasicMaterial
324
372
  // etc.) instead use `blending` with three.js's own 1..4 numbering, which does NOT
@@ -451,7 +499,12 @@ export class QuarksLoader {
451
499
  if (data.position) node.position.set(data.position[0], data.position[1], data.position[2]);
452
500
  if (data.scale) node.scaling.set(data.scale[0], data.scale[1], data.scale[2]);
453
501
  if (data.quaternion) {
454
- node.rotationQuaternion = new Quaternion(data.quaternion[0], data.quaternion[1], data.quaternion[2], data.quaternion[3]);
502
+ node.rotationQuaternion = new Quaternion(
503
+ data.quaternion[0],
504
+ data.quaternion[1],
505
+ data.quaternion[2],
506
+ data.quaternion[3]
507
+ );
455
508
  } else if (data.rotation) {
456
509
  node.rotation.set(data.rotation[0], data.rotation[1], data.rotation[2]);
457
510
  }
@@ -1,8 +1,8 @@
1
- import {IAnimationData, IPrefab} from 'quarks.core';
2
1
  import {TransformNode} from '@babylonjs/core/Meshes/transformNode';
3
2
  import {Scene} from '@babylonjs/core/scene';
4
- import {ParticleEmitter} from './ParticleEmitter';
3
+ import {IAnimationData, IPrefab} from 'quarks.core';
5
4
  import {BatchedRenderer} from './BatchedRenderer';
5
+ import {ParticleEmitter} from './ParticleEmitter';
6
6
 
7
7
  export interface QuarksTimelineClip {
8
8
  uuid?: string;
@@ -50,12 +50,7 @@ export class QuarksPrefab extends TransformNode implements IPrefab {
50
50
  this._batchedRenderer = renderer;
51
51
  }
52
52
 
53
- addParticleSystemAnimation(
54
- emitter: ParticleEmitter,
55
- startTime = 0,
56
- duration = 0,
57
- loop = false
58
- ): AnimationData {
53
+ addParticleSystemAnimation(emitter: ParticleEmitter, startTime = 0, duration = 0, loop = false): AnimationData {
59
54
  const animationDuration = duration > 0 ? duration : emitter.system.duration;
60
55
  const data: AnimationData = {
61
56
  startTime,
@@ -78,7 +73,7 @@ export class QuarksPrefab extends TransformNode implements IPrefab {
78
73
  loop = false,
79
74
  clipUUID?: string
80
75
  ): AnimationData {
81
- const animationDuration = duration > 0 ? duration : clip?.duration ?? 0;
76
+ const animationDuration = duration > 0 ? duration : (clip?.duration ?? 0);
82
77
  const data: AnimationData = {
83
78
  startTime,
84
79
  duration: animationDuration,
@@ -260,7 +255,7 @@ export class QuarksPrefab extends TransformNode implements IPrefab {
260
255
  duration: animation.duration,
261
256
  type: animation.type,
262
257
  targetUUID: (animation.target as any)._quarksUUID ?? animation.target.uniqueId.toString(),
263
- clipUUID: animation.type === 'three' ? animation.clipUUID ?? animation.clip?.uuid : undefined,
258
+ clipUUID: animation.type === 'three' ? (animation.clipUUID ?? animation.clip?.uuid) : undefined,
264
259
  loop: animation.loop,
265
260
  })),
266
261
  };
@@ -269,7 +264,9 @@ export class QuarksPrefab extends TransformNode implements IPrefab {
269
264
  static fromJSON(json: any, scene?: Scene): QuarksPrefab {
270
265
  const prefab = new QuarksPrefab(json.name || 'QuarksPrefab', scene);
271
266
  if (Array.isArray(json.animationData)) {
272
- prefab._tempAnimationJSON = json.animationData.filter((item: any) => item?.type === 'ps' || item?.type === 'three');
267
+ prefab._tempAnimationJSON = json.animationData.filter(
268
+ (item: any) => item?.type === 'ps' || item?.type === 'three'
269
+ );
273
270
  }
274
271
  return prefab;
275
272
  }
package/src/QuarksUtil.ts CHANGED
@@ -1,9 +1,7 @@
1
1
  import {Node} from '@babylonjs/core/node';
2
- import {TransformNode} from '@babylonjs/core/Meshes/transformNode';
2
+ import {BatchedRenderer} from './BatchedRenderer';
3
3
  import {ParticleEmitter} from './ParticleEmitter';
4
4
  import {ParticleSystem} from './ParticleSystem';
5
- import {BatchedRenderer} from './BatchedRenderer';
6
- import {IParticleSystem} from 'quarks.core';
7
5
 
8
6
  export class QuarksUtil {
9
7
  static runOnAllParticleEmitters(root: Node, callback: (emitter: ParticleEmitter) => void): void {