minerender 2.1.0-alpha.51 → 2.1.0-alpha.53

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/dist/bundle.js CHANGED
@@ -79134,51 +79134,6 @@ ${key}` : key;
79134
79134
  }
79135
79135
  });
79136
79136
 
79137
- // src/model/ModelCulling.ts
79138
- var ModelCulling;
79139
- var init_ModelCulling = __esm({
79140
- "src/model/ModelCulling.ts"() {
79141
- init_dirname();
79142
- init_buffer2();
79143
- init_process2();
79144
- init_three_module();
79145
- init_CubeFace();
79146
- ModelCulling = class {
79147
- static toLocalMask(worldMask, rotation) {
79148
- let localMask = 0;
79149
- for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
79150
- const normal = new Vector3(...offset).applyEuler(rotation);
79151
- const worldFace = CUBE_FACE_OFFSETS.findIndex(([x4, y5, z4]) => Math.abs(normal.x - x4) < 1e-6 && Math.abs(normal.y - y5) < 1e-6 && Math.abs(normal.z - z4) < 1e-6);
79152
- if (worldFace < 0) return 0;
79153
- if (worldMask & 1 << worldFace) localMask |= 1 << localFace;
79154
- }
79155
- return localMask;
79156
- }
79157
- static isOpaqueFullCube(atlas) {
79158
- if (!atlas || atlas.hasTransparency !== false || atlas.model.elements?.length !== 1) return false;
79159
- const element = atlas.model.elements[0];
79160
- if (element.from.length !== 3 || !element.from.every((value) => value === 0) || element.to.length !== 3 || !element.to.every((value) => value === 16) || element.rotation && element.rotation.angle !== 0 || element.mappedUv?.length !== 48 || !element.mappedUv.every(Number.isFinite)) return false;
79161
- if (!(atlas.image.width > 0 && atlas.image.height > 0)) return false;
79162
- return CUBE_FACES.every((face, faceIndex) => {
79163
- const texture = element.faces[face]?.texture;
79164
- if (!texture?.startsWith("#")) return false;
79165
- const key = texture.slice(1);
79166
- const position = atlas.positions[key];
79167
- const size = atlas.sizes[key];
79168
- if (position?.length !== 2 || !position.every(Number.isFinite) || size?.length !== 2 || !size.every((value) => value > 0 && Number.isFinite(value))) return false;
79169
- for (let vertex2 = 0; vertex2 < 4; vertex2++) {
79170
- const uvIndex = (faceIndex * 4 + vertex2) * 2;
79171
- const x4 = element.mappedUv[uvIndex] * atlas.image.width;
79172
- const y5 = (1 - element.mappedUv[uvIndex + 1]) * atlas.image.height;
79173
- if (x4 < position[0] - 1e-6 || x4 > position[0] + size[0] + 1e-6 || y5 < position[1] - 1e-6 || y5 > position[1] + size[1] + 1e-6) return false;
79174
- }
79175
- return true;
79176
- });
79177
- }
79178
- };
79179
- }
79180
- });
79181
-
79182
79137
  // src/three/BufferGeometryUtils.js
79183
79138
  function computeTangents(geometry) {
79184
79139
  geometry.computeTangents();
@@ -79718,11 +79673,56 @@ ${key}` : key;
79718
79673
  }
79719
79674
  });
79720
79675
 
79676
+ // src/model/ModelCulling.ts
79677
+ var ModelCulling;
79678
+ var init_ModelCulling = __esm({
79679
+ "src/model/ModelCulling.ts"() {
79680
+ init_dirname();
79681
+ init_buffer2();
79682
+ init_process2();
79683
+ init_three_module();
79684
+ init_CubeFace();
79685
+ ModelCulling = class {
79686
+ static toLocalMask(worldMask, rotation) {
79687
+ let localMask = 0;
79688
+ for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
79689
+ const normal = new Vector3(...offset).applyEuler(rotation);
79690
+ const worldFace = CUBE_FACE_OFFSETS.findIndex(([x4, y5, z4]) => Math.abs(normal.x - x4) < 1e-6 && Math.abs(normal.y - y5) < 1e-6 && Math.abs(normal.z - z4) < 1e-6);
79691
+ if (worldFace < 0) return 0;
79692
+ if (worldMask & 1 << worldFace) localMask |= 1 << localFace;
79693
+ }
79694
+ return localMask;
79695
+ }
79696
+ static isOpaqueFullCube(atlas) {
79697
+ if (!atlas || atlas.hasTransparency !== false || atlas.model.elements?.length !== 1) return false;
79698
+ const element = atlas.model.elements[0];
79699
+ if (element.from.length !== 3 || !element.from.every((value) => value === 0) || element.to.length !== 3 || !element.to.every((value) => value === 16) || element.rotation && element.rotation.angle !== 0 || element.mappedUv?.length !== 48 || !element.mappedUv.every(Number.isFinite)) return false;
79700
+ if (!(atlas.image.width > 0 && atlas.image.height > 0)) return false;
79701
+ return CUBE_FACES.every((face, faceIndex) => {
79702
+ const texture = element.faces[face]?.texture;
79703
+ if (!texture?.startsWith("#")) return false;
79704
+ const key = texture.slice(1);
79705
+ const position = atlas.positions[key];
79706
+ const size = atlas.sizes[key];
79707
+ if (position?.length !== 2 || !position.every(Number.isFinite) || size?.length !== 2 || !size.every((value) => value > 0 && Number.isFinite(value))) return false;
79708
+ for (let vertex2 = 0; vertex2 < 4; vertex2++) {
79709
+ const uvIndex = (faceIndex * 4 + vertex2) * 2;
79710
+ const x4 = element.mappedUv[uvIndex] * atlas.image.width;
79711
+ const y5 = (1 - element.mappedUv[uvIndex + 1]) * atlas.image.height;
79712
+ if (x4 < position[0] - 1e-6 || x4 > position[0] + size[0] + 1e-6 || y5 < position[1] - 1e-6 || y5 > position[1] + size[1] + 1e-6) return false;
79713
+ }
79714
+ return true;
79715
+ });
79716
+ }
79717
+ };
79718
+ }
79719
+ });
79720
+
79721
79721
  // src/model/scene/ModelObject.ts
79722
79722
  function isModelObject(obj) {
79723
79723
  return obj.isModelObject;
79724
79724
  }
79725
- var import_ts_deepmerge5, p12, _ModelObject, ModelObject;
79725
+ var import_ts_deepmerge5, p10, _ModelObject, ModelObject;
79726
79726
  var init_ModelObject = __esm({
79727
79727
  "src/model/scene/ModelObject.ts"() {
79728
79728
  init_dirname();
@@ -79739,7 +79739,7 @@ ${key}` : key;
79739
79739
  init_CubeFace();
79740
79740
  init_DisplayTransforms();
79741
79741
  init_ModelCulling();
79742
- p12 = prefix("ModelObject");
79742
+ p10 = prefix("ModelObject");
79743
79743
  _ModelObject = class _ModelObject extends SceneObject {
79744
79744
  constructor(originalModel, options) {
79745
79745
  super(options);
@@ -79818,10 +79818,10 @@ ${key}` : key;
79818
79818
  }
79819
79819
  });
79820
79820
  } else {
79821
- console.debug(p12, this.atlas.model, "has no elements");
79821
+ console.debug(p10, this.atlas.model, "has no elements");
79822
79822
  }
79823
79823
  } else {
79824
- console.debug(p12, "Missing atlas for", this);
79824
+ console.debug(p10, "Missing atlas for", this);
79825
79825
  }
79826
79826
  if (this.options.mergeMeshes) {
79827
79827
  let combinedGeo;
@@ -86352,9 +86352,24 @@ property list uchar int vertex_index
86352
86352
  init_three_module();
86353
86353
  init_AssetKey();
86354
86354
  init_ModelTextures();
86355
+ init_Models();
86355
86356
  init_Caching();
86356
86357
  init_SceneObject();
86357
86358
  init_Materials();
86359
+ init_ModelObject();
86360
+ init_DisplayPosition();
86361
+
86362
+ // src/model/GuiLight.ts
86363
+ init_dirname();
86364
+ init_buffer2();
86365
+ init_process2();
86366
+ var GuiLight = /* @__PURE__ */ ((GuiLight2) => {
86367
+ GuiLight2["FRONT"] = "front";
86368
+ GuiLight2["SIDE"] = "side";
86369
+ return GuiLight2;
86370
+ })(GuiLight || {});
86371
+
86372
+ // src/gui/scene/GuiObject.ts
86358
86373
  var GuiObject = class extends SceneObject {
86359
86374
  constructor(textureLayers, options) {
86360
86375
  super({ ...options, instanceMeshes: false, mergeMeshes: false });
@@ -86369,13 +86384,34 @@ property list uchar int vertex_index
86369
86384
  async init() {
86370
86385
  if (this.initialized) return;
86371
86386
  try {
86387
+ let depth = 0;
86372
86388
  for (const [index, layer] of this.textureLayers.entries()) {
86389
+ const [x4, y5] = layer.position ?? [0, 0];
86390
+ if ("item" in layer) {
86391
+ const [width2, height2] = layer.size ?? [16, 16];
86392
+ const item = await this.createItem(layer, index);
86393
+ item.position.set(x4 + width2 / 2, -y5 - height2 / 2, 0);
86394
+ item.scale.set(width2 / 16, height2 / 16, width2 / 16);
86395
+ item.updateMatrix();
86396
+ const bounds = new Box3();
86397
+ item.iterateAllMeshes((mesh2) => {
86398
+ mesh2.geometry.computeBoundingBox();
86399
+ bounds.union(mesh2.geometry.boundingBox);
86400
+ });
86401
+ bounds.applyMatrix4(item.matrix);
86402
+ item.position.z = depth - bounds.min.z;
86403
+ depth += bounds.max.z - bounds.min.z + 0.01;
86404
+ this.bounds.expandByPoint(new Vector2(x4, y5));
86405
+ this.bounds.expandByPoint(new Vector2(x4 + width2, y5 + height2));
86406
+ this.bounds.expandByPoint(new Vector2(bounds.min.x, -bounds.max.y));
86407
+ this.bounds.expandByPoint(new Vector2(bounds.max.x, -bounds.min.y));
86408
+ continue;
86409
+ }
86373
86410
  const key = typeof layer.texture === "string" ? AssetKey.parse("textures", layer.texture) : layer.texture;
86374
86411
  const material = await this.loadMaterial(key);
86375
86412
  const image = material.map.image;
86376
86413
  const [cropX, cropY, cropWidth, cropHeight] = layer.crop ?? [0, 0, image.width, image.height];
86377
86414
  const [width, height] = layer.size ?? [cropWidth, cropHeight];
86378
- const [x4, y5] = layer.position ?? [0, 0];
86379
86415
  const geometry = new PlaneGeometry(width, height);
86380
86416
  this.geometries.add(geometry);
86381
86417
  const uv = geometry.getAttribute("uv");
@@ -86388,12 +86424,14 @@ property list uchar int vertex_index
86388
86424
  }
86389
86425
  const mesh = new Mesh(geometry, material);
86390
86426
  mesh.name = `mesh:${layer.name ?? index}`;
86391
- mesh.position.set(x4 + width / 2, -y5 - height / 2, 0);
86427
+ mesh.position.set(x4 + width / 2, -y5 - height / 2, depth);
86392
86428
  mesh.renderOrder = index;
86393
86429
  this.add(mesh);
86394
86430
  this.bounds.expandByPoint(new Vector2(x4, y5));
86395
86431
  this.bounds.expandByPoint(new Vector2(x4 + width, y5 + height));
86432
+ depth += 0.01;
86396
86433
  }
86434
+ for (const child of this.children) child.position.z -= depth - 0.01;
86397
86435
  this.initialized = true;
86398
86436
  this.notifyDirty();
86399
86437
  } catch (error) {
@@ -86401,6 +86439,32 @@ property list uchar int vertex_index
86401
86439
  throw error;
86402
86440
  }
86403
86441
  }
86442
+ async createItem(layer, index) {
86443
+ const key = typeof layer.item === "string" ? AssetKey.parse("models", layer.item) : layer.item;
86444
+ const model = await Models.getMerged(key);
86445
+ if (!model) throw new Error(`Could not load GUI item ${key.toNamespacedString()}`);
86446
+ const item = new ModelObject(model, {
86447
+ displayPosition: "gui" /* GUI */,
86448
+ tints: layer.tints,
86449
+ instanceMeshes: false,
86450
+ mergeMeshes: true
86451
+ });
86452
+ item.name = `group:${layer.name ?? index}`;
86453
+ this.add(item);
86454
+ await item.init();
86455
+ item.iterateAllMeshes((mesh) => {
86456
+ this.geometries.add(mesh.geometry);
86457
+ mesh.name = `mesh:${layer.name ?? index}`;
86458
+ mesh.renderOrder = index;
86459
+ for (const material of Array.isArray(mesh.material) ? mesh.material : [mesh.material]) {
86460
+ material.transparent = true;
86461
+ if (model.gui_light === "front" /* FRONT */ && material.uniforms?.SHADE) {
86462
+ material.uniforms.SHADE.value = false;
86463
+ }
86464
+ }
86465
+ });
86466
+ return item;
86467
+ }
86404
86468
  async loadMaterial(key) {
86405
86469
  const assetKey = key.serialize();
86406
86470
  const materialKey = `gui:${assetKey}`;
@@ -86452,7 +86516,7 @@ property list uchar int vertex_index
86452
86516
  init_util();
86453
86517
  init_log();
86454
86518
  init_three();
86455
- var p10 = prefix("SceneInspector");
86519
+ var p11 = prefix("SceneInspector");
86456
86520
  var help = "<span>Ctrl/Cmd+Click to Select<br/></span><br/>";
86457
86521
  var SceneInspector = class {
86458
86522
  constructor(renderer) {
@@ -86546,7 +86610,7 @@ property list uchar int vertex_index
86546
86610
  }
86547
86611
  selectObject(targetObject, targetIntersection, instance = this.getIntersectionInstance(targetIntersection)) {
86548
86612
  this.selectedObject = targetObject;
86549
- console.log(p10, "selected", targetObject);
86613
+ console.log(p11, "selected", targetObject);
86550
86614
  this.redraw(targetObject, targetIntersection, instance);
86551
86615
  }
86552
86616
  redraw(targetObject, targetIntersection, instance) {
@@ -86781,7 +86845,7 @@ property list uchar int vertex_index
86781
86845
  }
86782
86846
  init() {
86783
86847
  this.statsContainer.classList.add("minerender-stats");
86784
- setInterval(() => {
86848
+ this.interval = setInterval(() => {
86785
86849
  for (let line of this.lines) {
86786
86850
  line.update();
86787
86851
  }
@@ -86790,6 +86854,13 @@ property list uchar int vertex_index
86790
86854
  appendTo(el) {
86791
86855
  el.append(this.statsContainer);
86792
86856
  }
86857
+ dispose() {
86858
+ clearInterval(this.interval);
86859
+ this.interval = void 0;
86860
+ this.lines.length = 0;
86861
+ this.statsContainer.replaceChildren();
86862
+ this.statsContainer.remove();
86863
+ }
86793
86864
  add(line) {
86794
86865
  if (typeof line !== "undefined") {
86795
86866
  this.lines.push(line);
@@ -86809,7 +86880,7 @@ property list uchar int vertex_index
86809
86880
  init_buffer2();
86810
86881
  init_process2();
86811
86882
  init_log();
86812
- var p11 = prefix("InstanceManager");
86883
+ var p12 = prefix("InstanceManager");
86813
86884
  var InstanceManager = class {
86814
86885
  constructor() {
86815
86886
  this.isInstanceManager = true;
@@ -86817,7 +86888,7 @@ property list uchar int vertex_index
86817
86888
  }
86818
86889
  async get(key) {
86819
86890
  if (key in this.instanceCache) {
86820
- console.debug(p11, "key in cache", key);
86891
+ console.debug(p12, "key in cache", key);
86821
86892
  return (await this.instanceCache[key]).nextInstance();
86822
86893
  }
86823
86894
  return void 0;
@@ -86826,7 +86897,7 @@ property list uchar int vertex_index
86826
86897
  if (key in this.instanceCache) {
86827
86898
  return await this.get(key);
86828
86899
  }
86829
- console.debug(p11, "key not in cache", key);
86900
+ console.debug(p12, "key not in cache", key);
86830
86901
  const pending = Promise.resolve().then(supplier).then((obj) => obj.nextInstance());
86831
86902
  this.instanceCache[key] = pending;
86832
86903
  try {
@@ -86871,16 +86942,6 @@ property list uchar int vertex_index
86871
86942
  init_buffer2();
86872
86943
  init_process2();
86873
86944
 
86874
- // src/model/GuiLight.ts
86875
- init_dirname();
86876
- init_buffer2();
86877
- init_process2();
86878
- var GuiLight = /* @__PURE__ */ ((GuiLight2) => {
86879
- GuiLight2["FRONT"] = "front";
86880
- GuiLight2["SIDE"] = "side";
86881
- return GuiLight2;
86882
- })(GuiLight || {});
86883
-
86884
86945
  // src/model/Model.ts
86885
86946
  init_dirname();
86886
86947
  init_buffer2();
@@ -92921,7 +92982,10 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
92921
92982
  constructor(options) {
92922
92983
  this._dirty = true;
92923
92984
  this._resizeListener = void 0;
92985
+ this._running = false;
92986
+ this._inAnimationLoop = false;
92924
92987
  this._disposed = false;
92988
+ this._frameCallbacks = /* @__PURE__ */ new Map();
92925
92989
  this._debugHelpers = [];
92926
92990
  this._eventDispatchers = /* @__PURE__ */ new Map();
92927
92991
  this._changeListener = () => {
@@ -92932,7 +92996,14 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
92932
92996
  if (!Number.isFinite(pixelRatio) || pixelRatio <= 0) {
92933
92997
  throw new RangeError("render.pixelRatio must be a finite positive number");
92934
92998
  }
92935
- this._animationLoop = this.animate.bind(this);
92999
+ this._animationLoop = (time) => {
93000
+ this._inAnimationLoop = true;
93001
+ try {
93002
+ this.animate(time);
93003
+ } finally {
93004
+ this._inAnimationLoop = false;
93005
+ }
93006
+ };
92936
93007
  this._frameInterval = this.options.render.fpsLimit > 0 ? 1e3 / this.options.render.fpsLimit : void 0;
92937
93008
  this._scene = this.createScene();
92938
93009
  this._camera = this.createCamera();
@@ -93107,15 +93178,39 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
93107
93178
  this._dirty = dirty;
93108
93179
  this.scene.dirty = dirty;
93109
93180
  }
93181
+ /**
93182
+ * Calls a synchronous animation update before each FPS-limited draw while started.
93183
+ * Subscriptions keep the scene drawing without manual dirty flags. Returns an unsubscribe function.
93184
+ * Registering the same callback twice has no effect. Image exports do not invoke callbacks.
93185
+ */
93186
+ onFrame(callback) {
93187
+ if (this._disposed) return () => {
93188
+ };
93189
+ const subscription = this._frameCallbacks.get(callback) ?? {};
93190
+ this._frameCallbacks.set(callback, subscription);
93191
+ return () => {
93192
+ if (this._frameCallbacks.get(callback) === subscription) this._frameCallbacks.delete(callback);
93193
+ };
93194
+ }
93110
93195
  start() {
93111
93196
  if (this._disposed) return;
93112
93197
  this.stop();
93113
- this.renderer.setAnimationLoop(this._animationLoop);
93198
+ this._running = true;
93199
+ if (!this._inAnimationLoop) this.renderer.setAnimationLoop(this._animationLoop);
93114
93200
  }
93115
93201
  stop() {
93116
93202
  if (this._disposed) return;
93117
- this.renderer.setAnimationLoop(null);
93203
+ this._running = false;
93204
+ if (this._inAnimationLoop) {
93205
+ queueMicrotask(() => {
93206
+ this.renderer.setAnimationLoop(null);
93207
+ if (this._running) this.renderer.setAnimationLoop(this._animationLoop);
93208
+ });
93209
+ } else {
93210
+ this.renderer.setAnimationLoop(null);
93211
+ }
93118
93212
  this._nextFrameTime = void 0;
93213
+ for (const subscription of this._frameCallbacks.values()) subscription.previous = void 0;
93119
93214
  }
93120
93215
  /**
93121
93216
  * Stops rendering and releases owned resources. Repeated calls have no effect, and a disposed
@@ -93126,6 +93221,7 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
93126
93221
  if (this._disposed) return;
93127
93222
  this.stop();
93128
93223
  this._disposed = true;
93224
+ this._frameCallbacks.clear();
93129
93225
  if (this._resizeListener) {
93130
93226
  window.removeEventListener("resize", this._resizeListener);
93131
93227
  this._resizeListener = void 0;
@@ -93160,18 +93256,25 @@ uniform float opacity;varying vec2 vUv;void main(){vec4 texel=texture2D(inputBuf
93160
93256
  this.renderer.forceContextLoss();
93161
93257
  }
93162
93258
  animate(t5 = performance.now()) {
93163
- if (this._disposed) return;
93259
+ if (!this._running) return;
93164
93260
  if (this._controls?.enabled) {
93165
93261
  this._controls.update();
93166
93262
  }
93167
- if (this._disposed) return;
93168
- if (!this.dirty && !this.options.render.renderAlways) return;
93263
+ if (!this._running) return;
93264
+ if (!this.dirty && !this.options.render.renderAlways && !this._frameCallbacks.size) return;
93169
93265
  const interval = this._frameInterval;
93170
93266
  if (interval) {
93171
93267
  const next = this._nextFrameTime;
93172
93268
  if (next !== void 0 && t5 + 0.1 < next) return;
93173
93269
  this._nextFrameTime = next !== void 0 && t5 - next < interval ? next + interval : t5 + interval;
93174
93270
  }
93271
+ for (const [callback, subscription] of [...this._frameCallbacks]) {
93272
+ if (this._frameCallbacks.get(callback) !== subscription) continue;
93273
+ const previous = subscription.previous;
93274
+ subscription.previous = t5;
93275
+ callback({ time: t5 / 1e3, delta: previous === void 0 ? 0 : (t5 - previous) / 1e3 });
93276
+ if (!this._running) return;
93277
+ }
93175
93278
  this.drawFrame();
93176
93279
  }
93177
93280
  drawFrame() {