minerender 2.1.0-alpha.52 → 2.1.0-alpha.54

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.
@@ -799,7 +799,7 @@ var init_Textures = __esm({
799
799
  });
800
800
 
801
801
  // src/Materials.ts
802
- import { Color, DoubleSide, FrontSide, MeshBasicMaterial, MeshStandardMaterial, ShaderChunk, ShaderMaterial } from "three";
802
+ import { Color, CustomBlending, DoubleSide, OneFactor, RepeatWrapping, FrontSide, MeshBasicMaterial, MeshStandardMaterial, ShaderChunk, ShaderMaterial, ZeroFactor } from "three";
803
803
  var _Materials, Materials;
804
804
  var init_Materials = __esm({
805
805
  "src/Materials.ts"() {
@@ -838,6 +838,71 @@ var init_Materials = __esm({
838
838
  alphaTest: 0.5
839
839
  });
840
840
  }
841
+ /** Whether vanilla's render type for the mode culls back faces. */
842
+ static entityModeCulls(mode = "cutout") {
843
+ return mode === "cutout_cull" || mode === "solid" || mode === "eyes" || mode === "water_mask";
844
+ }
845
+ /** UV offset per tick of entity age for the scrolling modes, as vanilla's texture matrix applies it. */
846
+ static entityModeScroll(mode = "cutout") {
847
+ if (mode === "energy_swirl") return [0.01, 0.01];
848
+ if (mode === "breeze_wind") return [0.02, 0];
849
+ return void 0;
850
+ }
851
+ /**
852
+ * Entity material for one of vanilla's render types. Entities are unlit here, so the lit and full-bright modes
853
+ * differ only in blending and depth state. Culling is not a material property: {@link entityModeCulls} decides
854
+ * whether the geometry gets inward faces.
855
+ */
856
+ static createEntityCanvasMaterial(canvas, mode = "cutout", tint) {
857
+ const material = _Materials.createBasicCanvasMaterial(canvas);
858
+ switch (mode) {
859
+ case "cutout":
860
+ case "cutout_cull":
861
+ break;
862
+ case "cutout_z_offset":
863
+ material.polygonOffset = true;
864
+ material.polygonOffsetFactor = -1;
865
+ material.polygonOffsetUnits = -10;
866
+ break;
867
+ case "solid":
868
+ material.alphaTest = 0;
869
+ break;
870
+ case "translucent":
871
+ case "breeze_wind":
872
+ material.transparent = true;
873
+ material.alphaTest = 0.1;
874
+ break;
875
+ case "translucent_emissive":
876
+ material.transparent = true;
877
+ material.alphaTest = 0.1;
878
+ material.depthWrite = false;
879
+ break;
880
+ case "eyes":
881
+ material.transparent = true;
882
+ material.alphaTest = 0;
883
+ material.depthWrite = false;
884
+ break;
885
+ case "energy_swirl":
886
+ material.transparent = true;
887
+ material.alphaTest = 0.1;
888
+ material.blending = CustomBlending;
889
+ material.blendSrc = OneFactor;
890
+ material.blendDst = OneFactor;
891
+ material.blendSrcAlpha = ZeroFactor;
892
+ material.blendDstAlpha = OneFactor;
893
+ material.color.set(8421504);
894
+ break;
895
+ case "water_mask":
896
+ material.alphaTest = 0;
897
+ material.colorWrite = false;
898
+ break;
899
+ }
900
+ if (_Materials.entityModeScroll(mode)) {
901
+ material.map.wrapS = material.map.wrapT = RepeatWrapping;
902
+ }
903
+ if (tint !== void 0) material.color.multiply(new Color(tint));
904
+ return material;
905
+ }
841
906
  static createGuiCanvasMaterial(canvas) {
842
907
  const material = new MeshBasicMaterial({
843
908
  map: Textures.createCanvasTexture(canvas),
@@ -3450,48 +3515,6 @@ var init_SceneObject = __esm({
3450
3515
  }
3451
3516
  });
3452
3517
 
3453
- // src/model/ModelCulling.ts
3454
- import { Vector3 as Vector39 } from "three";
3455
- var ModelCulling;
3456
- var init_ModelCulling = __esm({
3457
- "src/model/ModelCulling.ts"() {
3458
- init_CubeFace();
3459
- ModelCulling = class {
3460
- static toLocalMask(worldMask, rotation) {
3461
- let localMask = 0;
3462
- for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
3463
- const normal = new Vector39(...offset).applyEuler(rotation);
3464
- const worldFace = CUBE_FACE_OFFSETS.findIndex(([x, y, z]) => Math.abs(normal.x - x) < 1e-6 && Math.abs(normal.y - y) < 1e-6 && Math.abs(normal.z - z) < 1e-6);
3465
- if (worldFace < 0) return 0;
3466
- if (worldMask & 1 << worldFace) localMask |= 1 << localFace;
3467
- }
3468
- return localMask;
3469
- }
3470
- static isOpaqueFullCube(atlas) {
3471
- if (!atlas || atlas.hasTransparency !== false || atlas.model.elements?.length !== 1) return false;
3472
- const element = atlas.model.elements[0];
3473
- 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;
3474
- if (!(atlas.image.width > 0 && atlas.image.height > 0)) return false;
3475
- return CUBE_FACES.every((face, faceIndex) => {
3476
- const texture = element.faces[face]?.texture;
3477
- if (!texture?.startsWith("#")) return false;
3478
- const key = texture.slice(1);
3479
- const position = atlas.positions[key];
3480
- const size = atlas.sizes[key];
3481
- if (position?.length !== 2 || !position.every(Number.isFinite) || size?.length !== 2 || !size.every((value) => value > 0 && Number.isFinite(value))) return false;
3482
- for (let vertex = 0; vertex < 4; vertex++) {
3483
- const uvIndex = (faceIndex * 4 + vertex) * 2;
3484
- const x = element.mappedUv[uvIndex] * atlas.image.width;
3485
- const y = (1 - element.mappedUv[uvIndex + 1]) * atlas.image.height;
3486
- if (x < position[0] - 1e-6 || x > position[0] + size[0] + 1e-6 || y < position[1] - 1e-6 || y > position[1] + size[1] + 1e-6) return false;
3487
- }
3488
- return true;
3489
- });
3490
- }
3491
- };
3492
- }
3493
- });
3494
-
3495
3518
  // src/three/BufferGeometryUtils.js
3496
3519
  import {
3497
3520
  BufferAttribute as BufferAttribute4,
@@ -3502,7 +3525,7 @@ import {
3502
3525
  TriangleFanDrawMode,
3503
3526
  TriangleStripDrawMode,
3504
3527
  TrianglesDrawMode,
3505
- Vector3 as Vector310
3528
+ Vector3 as Vector39
3506
3529
  } from "three";
3507
3530
  function computeTangents(geometry) {
3508
3531
  geometry.computeTangents();
@@ -3821,15 +3844,15 @@ function computeMorphedAttributes(object) {
3821
3844
  console.error("THREE.BufferGeometryUtils: Geometry is not of type BufferGeometry.");
3822
3845
  return null;
3823
3846
  }
3824
- const _vA = new Vector310();
3825
- const _vB = new Vector310();
3826
- const _vC = new Vector310();
3827
- const _tempA = new Vector310();
3828
- const _tempB = new Vector310();
3829
- const _tempC = new Vector310();
3830
- const _morphA = new Vector310();
3831
- const _morphB = new Vector310();
3832
- const _morphC = new Vector310();
3847
+ const _vA = new Vector39();
3848
+ const _vB = new Vector39();
3849
+ const _vC = new Vector39();
3850
+ const _tempA = new Vector39();
3851
+ const _tempB = new Vector39();
3852
+ const _tempC = new Vector39();
3853
+ const _morphA = new Vector39();
3854
+ const _morphB = new Vector39();
3855
+ const _morphC = new Vector39();
3833
3856
  function _calculateMorphedAttributeData(object2, material2, attribute, morphAttribute, morphTargetsRelative2, a2, b2, c2, modifiedAttributeArray) {
3834
3857
  _vA.fromBufferAttribute(attribute, a2);
3835
3858
  _vB.fromBufferAttribute(attribute, b2);
@@ -4038,12 +4061,54 @@ var init_BufferGeometryUtils = __esm({
4038
4061
  }
4039
4062
  });
4040
4063
 
4064
+ // src/model/ModelCulling.ts
4065
+ import { Vector3 as Vector310 } from "three";
4066
+ var ModelCulling;
4067
+ var init_ModelCulling = __esm({
4068
+ "src/model/ModelCulling.ts"() {
4069
+ init_CubeFace();
4070
+ ModelCulling = class {
4071
+ static toLocalMask(worldMask, rotation) {
4072
+ let localMask = 0;
4073
+ for (const [localFace, offset] of CUBE_FACE_OFFSETS.entries()) {
4074
+ const normal = new Vector310(...offset).applyEuler(rotation);
4075
+ const worldFace = CUBE_FACE_OFFSETS.findIndex(([x, y, z]) => Math.abs(normal.x - x) < 1e-6 && Math.abs(normal.y - y) < 1e-6 && Math.abs(normal.z - z) < 1e-6);
4076
+ if (worldFace < 0) return 0;
4077
+ if (worldMask & 1 << worldFace) localMask |= 1 << localFace;
4078
+ }
4079
+ return localMask;
4080
+ }
4081
+ static isOpaqueFullCube(atlas) {
4082
+ if (!atlas || atlas.hasTransparency !== false || atlas.model.elements?.length !== 1) return false;
4083
+ const element = atlas.model.elements[0];
4084
+ 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;
4085
+ if (!(atlas.image.width > 0 && atlas.image.height > 0)) return false;
4086
+ return CUBE_FACES.every((face, faceIndex) => {
4087
+ const texture = element.faces[face]?.texture;
4088
+ if (!texture?.startsWith("#")) return false;
4089
+ const key = texture.slice(1);
4090
+ const position = atlas.positions[key];
4091
+ const size = atlas.sizes[key];
4092
+ if (position?.length !== 2 || !position.every(Number.isFinite) || size?.length !== 2 || !size.every((value) => value > 0 && Number.isFinite(value))) return false;
4093
+ for (let vertex = 0; vertex < 4; vertex++) {
4094
+ const uvIndex = (faceIndex * 4 + vertex) * 2;
4095
+ const x = element.mappedUv[uvIndex] * atlas.image.width;
4096
+ const y = (1 - element.mappedUv[uvIndex + 1]) * atlas.image.height;
4097
+ if (x < position[0] - 1e-6 || x > position[0] + size[0] + 1e-6 || y < position[1] - 1e-6 || y > position[1] + size[1] + 1e-6) return false;
4098
+ }
4099
+ return true;
4100
+ });
4101
+ }
4102
+ };
4103
+ }
4104
+ });
4105
+
4041
4106
  // src/model/scene/ModelObject.ts
4042
- import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color7, Euler as Euler6, Matrix4 as Matrix46 } from "three";
4107
+ import { BoxGeometry as BoxGeometry5, BufferAttribute as BufferAttribute5, Color as Color8, Euler as Euler6, Matrix4 as Matrix47 } from "three";
4043
4108
  function isModelObject(obj) {
4044
4109
  return obj.isModelObject;
4045
4110
  }
4046
- var import_ts_deepmerge5, p9, _ModelObject, ModelObject;
4111
+ var import_ts_deepmerge5, p7, _ModelObject, ModelObject;
4047
4112
  var init_ModelObject = __esm({
4048
4113
  "src/model/scene/ModelObject.ts"() {
4049
4114
  init_SceneObject();
@@ -4056,7 +4121,7 @@ var init_ModelObject = __esm({
4056
4121
  init_CubeFace();
4057
4122
  init_DisplayTransforms();
4058
4123
  init_ModelCulling();
4059
- p9 = prefix("ModelObject");
4124
+ p7 = prefix("ModelObject");
4060
4125
  _ModelObject = class _ModelObject extends SceneObject {
4061
4126
  constructor(originalModel, options) {
4062
4127
  super(options);
@@ -4111,19 +4176,19 @@ var init_ModelObject = __esm({
4111
4176
  if (tintIndex === void 0 || tintIndex < 0) continue;
4112
4177
  const tint = this.options.tints[tintIndex];
4113
4178
  if (tint === void 0) continue;
4114
- const color = new Color7(tint);
4179
+ const color = new Color8(tint);
4115
4180
  for (let vertex = 0; vertex < 4; vertex++) {
4116
4181
  color.toArray(colors, (faceIndex * 4 + vertex) * 3);
4117
4182
  }
4118
4183
  }
4119
4184
  elGeo.setAttribute("color", new BufferAttribute5(colors, 3));
4120
4185
  }
4121
- elGeo.applyMatrix4(new Matrix46().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4122
- elGeo.applyMatrix4(new Matrix46().makeTranslation(el.from[0], el.from[1], el.from[2]));
4186
+ elGeo.applyMatrix4(new Matrix47().makeTranslation((el.to[0] - el.from[0]) / 2, (el.to[1] - el.from[1]) / 2, (el.to[2] - el.from[2]) / 2));
4187
+ elGeo.applyMatrix4(new Matrix47().makeTranslation(el.from[0], el.from[1], el.from[2]));
4123
4188
  if (el.rotation) {
4124
4189
  applyElementRotation(el.rotation, elGeo);
4125
4190
  }
4126
- elGeo.applyMatrix4(new Matrix46().makeTranslation(-8, -8, -8));
4191
+ elGeo.applyMatrix4(new Matrix47().makeTranslation(-8, -8, -8));
4127
4192
  if (displayTransform) DisplayTransforms.apply(elGeo, displayTransform);
4128
4193
  if (this.options.mergeMeshes) {
4129
4194
  allGeos.push(elGeo);
@@ -4135,10 +4200,10 @@ var init_ModelObject = __esm({
4135
4200
  }
4136
4201
  });
4137
4202
  } else {
4138
- console.debug(p9, this.atlas.model, "has no elements");
4203
+ console.debug(p7, this.atlas.model, "has no elements");
4139
4204
  }
4140
4205
  } else {
4141
- console.debug(p9, "Missing atlas for", this);
4206
+ console.debug(p7, "Missing atlas for", this);
4142
4207
  }
4143
4208
  if (this.options.mergeMeshes) {
4144
4209
  let combinedGeo;
@@ -4238,7 +4303,7 @@ var init_fluidBlocks = __esm({
4238
4303
  });
4239
4304
 
4240
4305
  // src/model/fluid/FluidGeometry.ts
4241
- import { BufferGeometry as BufferGeometry3, Float32BufferAttribute as Float32BufferAttribute5 } from "three";
4306
+ import { BufferGeometry as BufferGeometry4, Float32BufferAttribute as Float32BufferAttribute5 } from "three";
4242
4307
  function getBlockFluidState(key, state) {
4243
4308
  const rule = key && fluidRules[key.toNamespacedString()];
4244
4309
  if (rule) return {
@@ -4256,7 +4321,7 @@ function ownHeight(sample) {
4256
4321
  return (level === 0 || level >= 8 ? 8 : 8 - level) / 9;
4257
4322
  }
4258
4323
  function createFluidGeometry(kind, sample) {
4259
- const geometry = new BufferGeometry3();
4324
+ const geometry = new BufferGeometry4();
4260
4325
  const positions = [], normals = [], uvs = [], indices = [];
4261
4326
  const self = sample(0, 0, 0);
4262
4327
  const height = (x, z) => {
@@ -4377,7 +4442,7 @@ __export(FluidModelObject_exports, {
4377
4442
  FluidModelObject: () => FluidModelObject,
4378
4443
  sampleFluid: () => sampleFluid
4379
4444
  });
4380
- import { BufferAttribute as BufferAttribute6, Color as Color8, DoubleSide as DoubleSide3 } from "three";
4445
+ import { BufferAttribute as BufferAttribute6, Color as Color9, DoubleSide as DoubleSide3 } from "three";
4381
4446
  function sampleFluid(kind, sample) {
4382
4447
  const cells = [];
4383
4448
  const key = [];
@@ -4428,7 +4493,7 @@ var init_FluidModelObject = __esm({
4428
4493
  }
4429
4494
  }
4430
4495
  geometry.clearGroups();
4431
- const color = new Color8(this.options.tints?.[0] ?? (this.kind === "water" ? 4159204 : 16777215));
4496
+ const color = new Color9(this.options.tints?.[0] ?? (this.kind === "water" ? 4159204 : 16777215));
4432
4497
  const colors = new Float32Array(geometry.getAttribute("position").count * 3);
4433
4498
  for (let i = 0; i < colors.length; i += 3) color.toArray(colors, i);
4434
4499
  geometry.setAttribute("color", new BufferAttribute6(colors, 3));
@@ -4763,32 +4828,44 @@ var Entities = class {
4763
4828
  static async getLayerList(modelKey) {
4764
4829
  return Object.keys((await this.getModelFile(modelKey))?.layers ?? {});
4765
4830
  }
4831
+ /** The dataset's extra draws on top of `main`; their `when` labels are the states `EntityModelOptions.when` can enable. */
4832
+ static async getPassList(modelKey) {
4833
+ return (await this.getModelFile(modelKey))?.passes ?? [];
4834
+ }
4766
4835
  static async getEntity(modelKey, textureKey, options) {
4767
4836
  const model = await this.getModelFile(modelKey);
4768
4837
  if (!model) return void 0;
4769
- const names = [...new Set(options?.layers ?? [options?.layer ?? "main"])];
4770
- if (names.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
4771
- const selected = names.map((name) => {
4772
- const layer = model.layers[name];
4838
+ const passes = options?.layers || options?.layer !== void 0 ? [] : (model.passes ?? []).filter((pass) => pass.when === void 0 || options?.when?.includes(pass.when));
4839
+ const draws = [...new Set(options?.layers ?? [options?.layer ?? "main"])].map((layer) => ({ layer }));
4840
+ if (draws.length === 0) throw new MineRenderError(`Entity ${model.id} requires at least one layer`);
4841
+ draws.push(...passes);
4842
+ const names = [];
4843
+ const selected = draws.map((pass) => {
4844
+ const layer = model.layers[pass.layer];
4773
4845
  if (!layer) {
4774
- throw new MineRenderError(`Entity ${model.id} has no layer "${name}". Available layers: ${Object.keys(model.layers).join(", ")}`);
4846
+ throw new MineRenderError(`Entity ${model.id} has no layer "${pass.layer}". Available layers: ${Object.keys(model.layers).join(", ")}`);
4775
4847
  }
4776
- return { name, layer };
4848
+ let name = pass.layer;
4849
+ for (let n = 2; names.includes(name); n++) name = `${pass.layer}#${n}`;
4850
+ names.push(name);
4851
+ return { name, layer, pass };
4777
4852
  });
4778
- const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer }, index) => {
4853
+ const layers = Object.fromEntries(await Promise.all(selected.map(async ({ name, layer, pass }, index) => {
4779
4854
  const override = options?.textures?.[name] ?? (index === 0 ? textureKey : void 0);
4855
+ const textureLocation = pass.textureLocation ?? layer.textureLocation;
4780
4856
  let texture;
4781
4857
  if (override) {
4782
4858
  const path = isAssetKey(override) ? override.getFullPath() : override.path;
4783
4859
  texture = isAssetKey(override) && override.assetType === "textures" && path.startsWith("entity/") ? override : new AssetKey(override.namespace, path, "textures", "entity", "assets", ".png", isAssetKey(override) ? override.root : void 0);
4784
- } else if (layer.textureLocation !== void 0) {
4785
- texture = AssetKey.parse("textures", layer.textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
4860
+ } else if (textureLocation !== void 0) {
4861
+ texture = AssetKey.parse("textures", textureLocation.replace(/^([^:]+:)?textures\//, "$1"));
4786
4862
  } else {
4787
4863
  texture = await this.resolveTexture(modelKey);
4788
4864
  }
4789
- return [name, { key: override ?? modelKey, texture, layer }];
4865
+ const render = pass.render ?? layer.render;
4866
+ return [name, { key: override ?? modelKey, texture, layer, ...render && { render }, ...pass.tint && { tint: pass.tint } }];
4790
4867
  })));
4791
- return { ...layers[names[0]], id: model.id, layers };
4868
+ return { ...layers[names[0]], id: model.id, layers, ...model.transform && { transform: model.transform } };
4792
4869
  }
4793
4870
  static async resolveTexture(modelKey) {
4794
4871
  const path = isAssetKey(modelKey) ? modelKey.getFullPath() : modelKey.path;
@@ -4870,11 +4947,12 @@ function trimCanvas(source) {
4870
4947
  init_SceneObject();
4871
4948
  init_Caching();
4872
4949
  var import_ts_deepmerge4 = __toESM(require_dist());
4950
+ init_Ticker();
4873
4951
  init_model();
4874
4952
  init_ModelTextures();
4875
4953
  init_AssetKey();
4876
4954
  init_Materials();
4877
- import { Object3D as Object3D3 } from "three";
4955
+ import { Color as Color3, Euler as Euler4, Matrix4 as Matrix44, Object3D as Object3D3 } from "three";
4878
4956
  init_three();
4879
4957
  var _EntityObject = class _EntityObject extends SceneObject {
4880
4958
  constructor(entity, options) {
@@ -4882,6 +4960,10 @@ var _EntityObject = class _EntityObject extends SceneObject {
4882
4960
  this.entity = entity;
4883
4961
  this.isEntityObject = true;
4884
4962
  this.meshesCreated = false;
4963
+ /** Scrolling materials are owned: their texture offset follows this entity's age. */
4964
+ this.scrollMaterials = [];
4965
+ /** Entity age in ticks, as vanilla's `ageInTicks`; drives the scrolling render modes. */
4966
+ this.age = 0;
4885
4967
  this.options = (0, import_ts_deepmerge4.default)({}, _EntityObject.DEFAULT_OPTIONS, options ?? {});
4886
4968
  }
4887
4969
  async init() {
@@ -4891,6 +4973,25 @@ var _EntityObject = class _EntityObject extends SceneObject {
4891
4973
  dispose() {
4892
4974
  super.dispose();
4893
4975
  }
4976
+ disposeAndRemoveAllChildren() {
4977
+ this.clearScrollMaterials();
4978
+ super.disposeAndRemoveAllChildren();
4979
+ }
4980
+ clearScrollMaterials() {
4981
+ Ticker.remove(this.scrollTicker);
4982
+ this.scrollTicker = void 0;
4983
+ for (const { material } of this.scrollMaterials.splice(0)) {
4984
+ material.map?.dispose();
4985
+ material.dispose();
4986
+ }
4987
+ }
4988
+ /** Applies the entity age to the scrolling materials; the ticker calls this 20 times per second. */
4989
+ updateScroll() {
4990
+ for (const { offset, speed } of this.scrollMaterials) {
4991
+ offset.set(this.age * speed[0] % 1, 0 - this.age * speed[1] % 1);
4992
+ }
4993
+ this.notifyDirty();
4994
+ }
4894
4995
  getLayerGroup(name) {
4895
4996
  return super.getGroupByName(`layer:${name}`);
4896
4997
  }
@@ -4921,16 +5022,29 @@ var _EntityObject = class _EntityObject extends SceneObject {
4921
5022
  createMeshes(force = false) {
4922
5023
  if (this.meshesCreated && !force) return;
4923
5024
  const modelRoot = new Object3D3();
4924
- if (this.options.flip) modelRoot.scale.set(-1, -1, 1);
5025
+ const transform = this.options.flip === void 0 ? this.entity.transform : void 0;
5026
+ if (transform) {
5027
+ for (const op of transform) {
5028
+ const matrix = new Matrix44();
5029
+ if ("scale" in op) matrix.makeScale(...op.scale);
5030
+ else if ("translate" in op) matrix.makeTranslation(...op.translate);
5031
+ else matrix.makeRotationFromEuler(new Euler4(...op.rotate, "ZYX"));
5032
+ modelRoot.matrix.multiply(matrix);
5033
+ }
5034
+ modelRoot.matrixAutoUpdate = false;
5035
+ } else if (this.options.flip ?? true) {
5036
+ modelRoot.scale.set(-1, -1, 1);
5037
+ }
4925
5038
  this.add(modelRoot);
4926
5039
  Object.entries(this.entityLayers).forEach(([name, layer], index) => {
4927
5040
  const group = this.createGroup(`layer:${name}`);
4928
5041
  modelRoot.add(group);
4929
- this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index);
5042
+ const inward = !Materials.entityModeCulls(layer.render ?? layer.layer.render);
5043
+ this.createPart("root", layer.layer.root, group, layer.layer.texture, Materials.MISSING_TEXTURE, index, inward);
4930
5044
  });
4931
5045
  this.meshesCreated = true;
4932
5046
  }
4933
- createPart(name, part, parent, textureSize, material, renderOrder) {
5047
+ createPart(name, part, parent, textureSize, material, renderOrder, inward = true) {
4934
5048
  const anchor = this.createGroup(name);
4935
5049
  anchor.position.fromArray(part.pose.offset);
4936
5050
  anchor.rotation.set(...part.pose.rotation, "ZYX");
@@ -4949,7 +5063,7 @@ var _EntityObject = class _EntityObject extends SceneObject {
4949
5063
  uv
4950
5064
  ).clone();
4951
5065
  geometry.translate(cube.origin[0] + width / 2, cube.origin[1] + height / 2, cube.origin[2] + depth / 2);
4952
- if (Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
5066
+ if (inward && Math.min(width + growX * 2, height + growY * 2, depth + growZ * 2) > 0) {
4953
5067
  const index = Array.from(geometry.getIndex().array);
4954
5068
  geometry.setIndex(index.concat(index.slice().reverse()));
4955
5069
  }
@@ -4959,30 +5073,46 @@ var _EntityObject = class _EntityObject extends SceneObject {
4959
5073
  if (this.options.wireframe) addWireframeToMesh(geometry, mesh);
4960
5074
  }
4961
5075
  for (const [childName, child] of Object.entries(part.children)) {
4962
- this.createPart(childName, child, anchor, size, material, renderOrder);
5076
+ this.createPart(childName, child, anchor, size, material, renderOrder, inward);
4963
5077
  }
4964
5078
  }
4965
5079
  async applyTextures() {
5080
+ this.clearScrollMaterials();
4966
5081
  await Promise.all(Object.entries(this.entityLayers).map(async ([name, layer]) => {
5082
+ const mode = layer.render ?? layer.layer.render ?? "cutout";
5083
+ const tint = layer.tint === void 0 ? void 0 : this.options.tints?.[layer.tint];
5084
+ const scroll = Materials.entityModeScroll(mode);
4967
5085
  const assetKeyStr = this.getTextureKey(layer).serialize();
4968
- const keyStr = `entity:${assetKeyStr}`;
4969
- let mat = Caching.materialCache.getIfPresent(keyStr);
5086
+ const keyStr = `entity:${mode}:${tint === void 0 ? "" : new Color3(tint).getHexString()}:${assetKeyStr}`;
5087
+ let mat = scroll ? void 0 : Caching.materialCache.getIfPresent(keyStr);
4970
5088
  if (!mat) {
4971
5089
  const cachedAsset = Caching.textureAssetCache.getIfPresent(assetKeyStr);
4972
5090
  const imageData = await this.loadTextures(layer);
4973
5091
  if (!imageData) return;
4974
5092
  const canvas = imageData.data.canvas;
4975
- const createMaterial = () => Materials.createBasicCanvasMaterial(canvas);
4976
- mat = cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
5093
+ const createMaterial = () => Materials.createEntityCanvasMaterial(canvas, mode, tint);
5094
+ mat = !scroll && cachedAsset && Caching.textureAssetCache.getIfPresent(assetKeyStr) === cachedAsset ? Caching.materialCache.get(keyStr, createMaterial) : createMaterial();
5095
+ if (scroll) {
5096
+ this.scrollMaterials.push({ material: mat, offset: mat.map.offset, speed: scroll });
5097
+ }
4977
5098
  }
4978
5099
  this.getLayerGroup(name)?.traverse((object) => {
4979
5100
  if (isMesh(object)) object.material = mat;
4980
5101
  });
4981
5102
  }));
5103
+ if (!this.children.length) {
5104
+ this.clearScrollMaterials();
5105
+ } else if (this.scrollMaterials.length) {
5106
+ this.updateScroll();
5107
+ this.scrollTicker = Ticker.add(() => {
5108
+ this.age++;
5109
+ this.updateScroll();
5110
+ });
5111
+ }
4982
5112
  this.notifyDirty();
4983
5113
  }
4984
5114
  };
4985
- _EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS, { flip: true });
5115
+ _EntityObject.DEFAULT_OPTIONS = (0, import_ts_deepmerge4.default)({}, SceneObject.DEFAULT_OPTIONS);
4986
5116
  var EntityObject = _EntityObject;
4987
5117
  function isEntityObject(obj) {
4988
5118
  return obj.isEntityObject;
@@ -4992,11 +5122,11 @@ function isEntityObject(obj) {
4992
5122
  init_MineRenderError();
4993
5123
 
4994
5124
  // src/export/SceneExporter.ts
4995
- import { ClampToEdgeWrapping as ClampToEdgeWrapping2, Color as Color6, Float32BufferAttribute as Float32BufferAttribute3, Matrix4 as Matrix45, Mesh as Mesh5, MeshBasicMaterial as MeshBasicMaterial2, NearestFilter as NearestFilter3, RGBAFormat as RGBAFormat3, Scene as Scene4, Source as Source2, Texture as Texture4, UnsignedByteType } from "three";
5125
+ import { ClampToEdgeWrapping as ClampToEdgeWrapping2, Color as Color7, Float32BufferAttribute as Float32BufferAttribute3, Matrix4 as Matrix46, Mesh as Mesh5, MeshBasicMaterial as MeshBasicMaterial2, NearestFilter as NearestFilter3, RGBAFormat as RGBAFormat3, Scene as Scene4, Source as Source2, Texture as Texture4, UnsignedByteType } from "three";
4996
5126
 
4997
5127
  // ../../node_modules/three/examples/jsm/exporters/OBJExporter.js
4998
5128
  import {
4999
- Color as Color3,
5129
+ Color as Color4,
5000
5130
  Matrix3,
5001
5131
  Vector2 as Vector22,
5002
5132
  Vector3 as Vector36
@@ -5008,7 +5138,7 @@ var OBJExporter = class {
5008
5138
  let indexVertexUvs = 0;
5009
5139
  let indexNormals = 0;
5010
5140
  const vertex = new Vector36();
5011
- const color = new Color3();
5141
+ const color = new Color4();
5012
5142
  const normal = new Vector36();
5013
5143
  const uv = new Vector22();
5014
5144
  const face = [];
@@ -5139,7 +5269,7 @@ var OBJExporter = class {
5139
5269
  import {
5140
5270
  Matrix3 as Matrix32,
5141
5271
  Vector3 as Vector37,
5142
- Color as Color4
5272
+ Color as Color5
5143
5273
  } from "three";
5144
5274
  var PLYExporter = class {
5145
5275
  parse(object, onDone, options = {}) {
@@ -5197,7 +5327,7 @@ var PLYExporter = class {
5197
5327
  includeIndices = false;
5198
5328
  }
5199
5329
  });
5200
- const tempColor = new Color4();
5330
+ const tempColor = new Color5();
5201
5331
  includeIndices = includeIndices && excludeAttributes.indexOf("index") === -1;
5202
5332
  includeNormals = includeNormals && excludeAttributes.indexOf("normal") === -1;
5203
5333
  includeColors = includeColors && excludeAttributes.indexOf("color") === -1;
@@ -5409,7 +5539,7 @@ property list uchar int vertex_index
5409
5539
  import {
5410
5540
  BufferAttribute as BufferAttribute3,
5411
5541
  ClampToEdgeWrapping,
5412
- Color as Color5,
5542
+ Color as Color6,
5413
5543
  DoubleSide as DoubleSide2,
5414
5544
  InterpolateDiscrete,
5415
5545
  InterpolateLinear,
@@ -5418,14 +5548,14 @@ import {
5418
5548
  LinearMipmapLinearFilter,
5419
5549
  LinearMipmapNearestFilter,
5420
5550
  MathUtils as MathUtils2,
5421
- Matrix4 as Matrix44,
5551
+ Matrix4 as Matrix45,
5422
5552
  MirroredRepeatWrapping,
5423
5553
  NearestFilter as NearestFilter2,
5424
5554
  NearestMipmapLinearFilter,
5425
5555
  NearestMipmapNearestFilter,
5426
5556
  PropertyBinding,
5427
5557
  RGBAFormat as RGBAFormat2,
5428
- RepeatWrapping,
5558
+ RepeatWrapping as RepeatWrapping2,
5429
5559
  Scene as Scene3,
5430
5560
  Source,
5431
5561
  SRGBColorSpace as SRGBColorSpace4,
@@ -5643,7 +5773,7 @@ THREE_TO_WEBGL[LinearFilter] = WEBGL_CONSTANTS.LINEAR;
5643
5773
  THREE_TO_WEBGL[LinearMipmapNearestFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_NEAREST;
5644
5774
  THREE_TO_WEBGL[LinearMipmapLinearFilter] = WEBGL_CONSTANTS.LINEAR_MIPMAP_LINEAR;
5645
5775
  THREE_TO_WEBGL[ClampToEdgeWrapping] = WEBGL_CONSTANTS.CLAMP_TO_EDGE;
5646
- THREE_TO_WEBGL[RepeatWrapping] = WEBGL_CONSTANTS.REPEAT;
5776
+ THREE_TO_WEBGL[RepeatWrapping2] = WEBGL_CONSTANTS.REPEAT;
5647
5777
  THREE_TO_WEBGL[MirroredRepeatWrapping] = WEBGL_CONSTANTS.MIRRORED_REPEAT;
5648
5778
  var PATH_PROPERTIES = {
5649
5779
  scale: "scale",
@@ -5651,7 +5781,7 @@ var PATH_PROPERTIES = {
5651
5781
  quaternion: "rotation",
5652
5782
  morphTargetInfluences: "weights"
5653
5783
  };
5654
- var DEFAULT_SPECULAR_COLOR = new Color5();
5784
+ var DEFAULT_SPECULAR_COLOR = new Color6();
5655
5785
  var GLB_HEADER_BYTES = 12;
5656
5786
  var GLB_HEADER_MAGIC = 1179937895;
5657
5787
  var GLB_VERSION = 2;
@@ -6708,7 +6838,7 @@ var GLTFWriter = class {
6708
6838
  if (rootJoint === void 0) return null;
6709
6839
  const joints = [];
6710
6840
  const inverseBindMatrices = new Float32Array(skeleton.bones.length * 16);
6711
- const temporaryBoneInverse = new Matrix44();
6841
+ const temporaryBoneInverse = new Matrix45();
6712
6842
  for (let i = 0; i < skeleton.bones.length; ++i) {
6713
6843
  joints.push(nodeMap.get(skeleton.bones[i]));
6714
6844
  temporaryBoneInverse.copy(skeleton.boneInverses[i]);
@@ -7174,7 +7304,7 @@ var GLTFMeshGpuInstancing = class {
7174
7304
  const translationAttr = new Float32Array(mesh.count * 3);
7175
7305
  const rotationAttr = new Float32Array(mesh.count * 4);
7176
7306
  const scaleAttr = new Float32Array(mesh.count * 3);
7177
- const matrix = new Matrix44();
7307
+ const matrix = new Matrix45();
7178
7308
  const position = new Vector38();
7179
7309
  const quaternion = new Quaternion4();
7180
7310
  const scale = new Vector38();
@@ -7348,7 +7478,7 @@ var SceneExporter = class {
7348
7478
  }
7349
7479
  };
7350
7480
  function localMatrix(object) {
7351
- return object.matrixAutoUpdate ? new Matrix45().compose(object.position, object.quaternion, object.scale) : object.matrix.clone();
7481
+ return object.matrixAutoUpdate ? new Matrix46().compose(object.position, object.quaternion, object.scale) : object.matrix.clone();
7352
7482
  }
7353
7483
  function createSnapshot(root, gltf, bakeColors = false) {
7354
7484
  const scene = new Scene4();
@@ -7433,7 +7563,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7433
7563
  const material = copyMaterial(sourceMaterial, geometry);
7434
7564
  if (!sourceMaterial.vertexColors) geometry.deleteAttribute("color");
7435
7565
  if (bakeColors || instanceColor) {
7436
- const tint = (material.color ?? new Color6()).clone();
7566
+ const tint = (material.color ?? new Color7()).clone();
7437
7567
  if (instanceColor) tint.multiply(instanceColor);
7438
7568
  if (bakeColors) {
7439
7569
  const original = geometry.getAttribute("color");
@@ -7460,9 +7590,9 @@ function createSnapshot(root, gltf, bakeColors = false) {
7460
7590
  const instanced = mesh;
7461
7591
  if (instanced.isInstancedMesh) {
7462
7592
  for (let i = 0; i < instanced.count; i++) {
7463
- const matrix = new Matrix45();
7593
+ const matrix = new Matrix46();
7464
7594
  instanced.getMatrixAt(i, matrix);
7465
- const color = instanced.instanceColor ? new Color6().fromBufferAttribute(instanced.instanceColor, i) : void 0;
7595
+ const color = instanced.instanceColor ? new Color7().fromBufferAttribute(instanced.instanceColor, i) : void 0;
7466
7596
  addMesh(mesh, world.clone().multiply(matrix), color);
7467
7597
  }
7468
7598
  } else {
@@ -7474,7 +7604,7 @@ function createSnapshot(root, gltf, bakeColors = false) {
7474
7604
  try {
7475
7605
  const ancestors = [];
7476
7606
  for (let parent = root.parent; parent; parent = parent.parent) ancestors.unshift(parent);
7477
- const world = new Matrix45();
7607
+ const world = new Matrix46();
7478
7608
  for (const ancestor of ancestors) {
7479
7609
  if (!ancestor.visible) return { scene, dispose };
7480
7610
  world.multiply(localMatrix(ancestor));
@@ -7541,20 +7671,90 @@ function copyDataTexture(source) {
7541
7671
  }
7542
7672
 
7543
7673
  // src/gui/GuiHelper.ts
7674
+ init_AssetKey();
7544
7675
  var GuiHelper = class {
7545
7676
  static inventorySlot(slot, origin = [0, 0], offset = [18, 18], rowSize = 9) {
7546
7677
  const [column, row] = typeof slot === "number" ? [slot % rowSize, Math.floor(slot / rowSize)] : slot;
7547
7678
  return [origin[0] + column * offset[0], origin[1] + row * offset[1]];
7548
7679
  }
7680
+ /** Creates crafting-table layers for ingredients and the result; stack counts are not drawn. */
7681
+ static recipe(recipe, options = {}) {
7682
+ const layers = [
7683
+ { name: "background", texture: "minecraft:gui/container/crafting_table", crop: [0, 0, 176, 166] }
7684
+ ];
7685
+ const itemKey = (ingredient) => {
7686
+ const item = typeof ingredient === "string" && !ingredient.startsWith("#") ? ingredient : typeof ingredient === "object" && "item" in ingredient ? ingredient.item : options.resolveIngredient?.(ingredient);
7687
+ if (isAssetKey(item)) return item;
7688
+ if (!item || item.startsWith("#")) {
7689
+ throw new Error(`Select a concrete item for recipe ingredient ${JSON.stringify(ingredient)}`);
7690
+ }
7691
+ const key = AssetKey.parse("models", item);
7692
+ return new AssetKey(key.namespace, key.getFullPath(), "models", "item");
7693
+ };
7694
+ const addIngredient = (ingredient, slot) => {
7695
+ layers.push({
7696
+ name: `ingredient-${slot}`,
7697
+ item: itemKey(ingredient),
7698
+ position: this.inventorySlot(slot, [30, 17], [18, 18], 3)
7699
+ });
7700
+ };
7701
+ switch (recipe.type) {
7702
+ case "minecraft:crafting_shaped":
7703
+ case "crafting_shaped": {
7704
+ const pattern = recipe.pattern;
7705
+ if (!pattern.length || pattern.length > 3 || !pattern[0].length || pattern[0].length > 3 || pattern.some((row) => row.length !== pattern[0].length)) {
7706
+ throw new Error("Crafting patterns must be rectangular, with 1\u20133 rows and columns");
7707
+ }
7708
+ const cells = pattern.flatMap((row, y) => row.split("").map((symbol, x) => ({ symbol, x, y }))).filter((cell) => cell.symbol !== " ");
7709
+ if (!cells.length) throw new Error("Crafting patterns must contain an ingredient");
7710
+ const minX = Math.min(...cells.map((cell) => cell.x)), maxX = Math.max(...cells.map((cell) => cell.x));
7711
+ const minY = Math.min(...cells.map((cell) => cell.y)), maxY = Math.max(...cells.map((cell) => cell.y));
7712
+ const offsetX = minX === maxX ? 1 : 0, offsetY = minY === maxY ? 1 : 0;
7713
+ for (const { symbol, x, y } of cells) {
7714
+ const ingredient = recipe.key[symbol];
7715
+ if (!ingredient) throw new Error(`Missing recipe ingredient for symbol ${JSON.stringify(symbol)}`);
7716
+ addIngredient(ingredient, (y - minY + offsetY) * 3 + x - minX + offsetX);
7717
+ }
7718
+ break;
7719
+ }
7720
+ case "minecraft:crafting_shapeless":
7721
+ case "crafting_shapeless":
7722
+ if (!recipe.ingredients.length || recipe.ingredients.length > 9) {
7723
+ throw new Error("Shapeless crafting recipes require 1\u20139 ingredients");
7724
+ }
7725
+ recipe.ingredients.forEach(addIngredient);
7726
+ break;
7727
+ default:
7728
+ throw new Error(`Unsupported crafting recipe type: ${recipe.type}`);
7729
+ }
7730
+ layers.push({
7731
+ name: "result",
7732
+ item: itemKey("id" in recipe.result ? recipe.result.id : recipe.result.item),
7733
+ position: [124, 35]
7734
+ });
7735
+ return layers;
7736
+ }
7549
7737
  };
7550
7738
 
7551
7739
  // src/gui/scene/GuiObject.ts
7552
7740
  init_AssetKey();
7553
7741
  init_ModelTextures();
7742
+ init_Models();
7554
7743
  init_Caching();
7555
7744
  init_SceneObject();
7556
7745
  init_Materials();
7557
- import { Box2, Mesh as Mesh6, PlaneGeometry as PlaneGeometry2, Vector2 as Vector23 } from "three";
7746
+ init_ModelObject();
7747
+ init_DisplayPosition();
7748
+ import { Box2, Box3 as Box32, Mesh as Mesh7, PlaneGeometry as PlaneGeometry2, Vector2 as Vector23 } from "three";
7749
+
7750
+ // src/model/GuiLight.ts
7751
+ var GuiLight = /* @__PURE__ */ ((GuiLight2) => {
7752
+ GuiLight2["FRONT"] = "front";
7753
+ GuiLight2["SIDE"] = "side";
7754
+ return GuiLight2;
7755
+ })(GuiLight || {});
7756
+
7757
+ // src/gui/scene/GuiObject.ts
7558
7758
  var GuiObject = class extends SceneObject {
7559
7759
  constructor(textureLayers, options) {
7560
7760
  super({ ...options, instanceMeshes: false, mergeMeshes: false });
@@ -7569,13 +7769,34 @@ var GuiObject = class extends SceneObject {
7569
7769
  async init() {
7570
7770
  if (this.initialized) return;
7571
7771
  try {
7772
+ let depth = 0;
7572
7773
  for (const [index, layer] of this.textureLayers.entries()) {
7774
+ const [x, y] = layer.position ?? [0, 0];
7775
+ if ("item" in layer) {
7776
+ const [width2, height2] = layer.size ?? [16, 16];
7777
+ const item = await this.createItem(layer, index);
7778
+ item.position.set(x + width2 / 2, -y - height2 / 2, 0);
7779
+ item.scale.set(width2 / 16, height2 / 16, width2 / 16);
7780
+ item.updateMatrix();
7781
+ const bounds = new Box32();
7782
+ item.iterateAllMeshes((mesh2) => {
7783
+ mesh2.geometry.computeBoundingBox();
7784
+ bounds.union(mesh2.geometry.boundingBox);
7785
+ });
7786
+ bounds.applyMatrix4(item.matrix);
7787
+ item.position.z = depth - bounds.min.z;
7788
+ depth += bounds.max.z - bounds.min.z + 0.01;
7789
+ this.bounds.expandByPoint(new Vector23(x, y));
7790
+ this.bounds.expandByPoint(new Vector23(x + width2, y + height2));
7791
+ this.bounds.expandByPoint(new Vector23(bounds.min.x, -bounds.max.y));
7792
+ this.bounds.expandByPoint(new Vector23(bounds.max.x, -bounds.min.y));
7793
+ continue;
7794
+ }
7573
7795
  const key = typeof layer.texture === "string" ? AssetKey.parse("textures", layer.texture) : layer.texture;
7574
7796
  const material = await this.loadMaterial(key);
7575
7797
  const image = material.map.image;
7576
7798
  const [cropX, cropY, cropWidth, cropHeight] = layer.crop ?? [0, 0, image.width, image.height];
7577
7799
  const [width, height] = layer.size ?? [cropWidth, cropHeight];
7578
- const [x, y] = layer.position ?? [0, 0];
7579
7800
  const geometry = new PlaneGeometry2(width, height);
7580
7801
  this.geometries.add(geometry);
7581
7802
  const uv = geometry.getAttribute("uv");
@@ -7586,14 +7807,16 @@ var GuiObject = class extends SceneObject {
7586
7807
  1 - (cropY + (1 - uv.getY(i)) * cropHeight) / image.height
7587
7808
  );
7588
7809
  }
7589
- const mesh = new Mesh6(geometry, material);
7810
+ const mesh = new Mesh7(geometry, material);
7590
7811
  mesh.name = `mesh:${layer.name ?? index}`;
7591
- mesh.position.set(x + width / 2, -y - height / 2, 0);
7812
+ mesh.position.set(x + width / 2, -y - height / 2, depth);
7592
7813
  mesh.renderOrder = index;
7593
7814
  this.add(mesh);
7594
7815
  this.bounds.expandByPoint(new Vector23(x, y));
7595
7816
  this.bounds.expandByPoint(new Vector23(x + width, y + height));
7817
+ depth += 0.01;
7596
7818
  }
7819
+ for (const child of this.children) child.position.z -= depth - 0.01;
7597
7820
  this.initialized = true;
7598
7821
  this.notifyDirty();
7599
7822
  } catch (error) {
@@ -7601,6 +7824,32 @@ var GuiObject = class extends SceneObject {
7601
7824
  throw error;
7602
7825
  }
7603
7826
  }
7827
+ async createItem(layer, index) {
7828
+ const key = typeof layer.item === "string" ? AssetKey.parse("models", layer.item) : layer.item;
7829
+ const model = await Models.getMerged(key);
7830
+ if (!model) throw new Error(`Could not load GUI item ${key.toNamespacedString()}`);
7831
+ const item = new ModelObject(model, {
7832
+ displayPosition: "gui" /* GUI */,
7833
+ tints: layer.tints,
7834
+ instanceMeshes: false,
7835
+ mergeMeshes: true
7836
+ });
7837
+ item.name = `group:${layer.name ?? index}`;
7838
+ this.add(item);
7839
+ await item.init();
7840
+ item.iterateAllMeshes((mesh) => {
7841
+ this.geometries.add(mesh.geometry);
7842
+ mesh.name = `mesh:${layer.name ?? index}`;
7843
+ mesh.renderOrder = index;
7844
+ for (const material of Array.isArray(mesh.material) ? mesh.material : [mesh.material]) {
7845
+ material.transparent = true;
7846
+ if (model.gui_light === "front" /* FRONT */ && material.uniforms?.SHADE) {
7847
+ material.uniforms.SHADE.value = false;
7848
+ }
7849
+ }
7850
+ });
7851
+ return item;
7852
+ }
7604
7853
  async loadMaterial(key) {
7605
7854
  const assetKey = key.serialize();
7606
7855
  const materialKey = `gui:${assetKey}`;
@@ -7644,7 +7893,7 @@ init_util();
7644
7893
  import { Raycaster, Vector2 as Vector24 } from "three";
7645
7894
  init_log();
7646
7895
  init_three();
7647
- var p7 = prefix("SceneInspector");
7896
+ var p8 = prefix("SceneInspector");
7648
7897
  var help = "<span>Ctrl/Cmd+Click to Select<br/></span><br/>";
7649
7898
  var SceneInspector = class {
7650
7899
  constructor(renderer) {
@@ -7738,7 +7987,7 @@ var SceneInspector = class {
7738
7987
  }
7739
7988
  selectObject(targetObject, targetIntersection, instance = this.getIntersectionInstance(targetIntersection)) {
7740
7989
  this.selectedObject = targetObject;
7741
- console.log(p7, "selected", targetObject);
7990
+ console.log(p8, "selected", targetObject);
7742
7991
  this.redraw(targetObject, targetIntersection, instance);
7743
7992
  }
7744
7993
  redraw(targetObject, targetIntersection, instance) {
@@ -7997,7 +8246,7 @@ var SceneStatsDisplay = class {
7997
8246
 
7998
8247
  // src/instance/InstanceManager.ts
7999
8248
  init_log();
8000
- var p8 = prefix("InstanceManager");
8249
+ var p9 = prefix("InstanceManager");
8001
8250
  var InstanceManager = class {
8002
8251
  constructor() {
8003
8252
  this.isInstanceManager = true;
@@ -8005,7 +8254,7 @@ var InstanceManager = class {
8005
8254
  }
8006
8255
  async get(key) {
8007
8256
  if (key in this.instanceCache) {
8008
- console.debug(p8, "key in cache", key);
8257
+ console.debug(p9, "key in cache", key);
8009
8258
  return (await this.instanceCache[key]).nextInstance();
8010
8259
  }
8011
8260
  return void 0;
@@ -8014,7 +8263,7 @@ var InstanceManager = class {
8014
8263
  if (key in this.instanceCache) {
8015
8264
  return await this.get(key);
8016
8265
  }
8017
- console.debug(p8, "key not in cache", key);
8266
+ console.debug(p9, "key not in cache", key);
8018
8267
  const pending = Promise.resolve().then(supplier).then((obj) => obj.nextInstance());
8019
8268
  this.instanceCache[key] = pending;
8020
8269
  try {
@@ -8048,13 +8297,6 @@ function isInstanceable(obj) {
8048
8297
  init_DisplayPosition();
8049
8298
  init_DisplayTransforms();
8050
8299
 
8051
- // src/model/GuiLight.ts
8052
- var GuiLight = /* @__PURE__ */ ((GuiLight2) => {
8053
- GuiLight2["FRONT"] = "front";
8054
- GuiLight2["SIDE"] = "side";
8055
- return GuiLight2;
8056
- })(GuiLight || {});
8057
-
8058
8300
  // src/model/Model.ts
8059
8301
  var ITEM_GENERATED = "item/generated";
8060
8302
  var BUILTIN_GENERATED = "builtin/generated";
@@ -8079,7 +8321,7 @@ init_ModelMerger();
8079
8321
  init_BlockStates();
8080
8322
  init_MineRenderError();
8081
8323
  init_util();
8082
- import { Euler as Euler5 } from "three";
8324
+ import { Euler as Euler7 } from "three";
8083
8325
  function matchesCondition(condition, state) {
8084
8326
  return Object.entries(condition).every(([key, value]) => {
8085
8327
  if (Array.isArray(value)) {
@@ -8154,7 +8396,7 @@ var BlockStateResolver = class {
8154
8396
  return variants[variants.length - 1];
8155
8397
  }
8156
8398
  static rotation(variant) {
8157
- const rotation = new Euler5();
8399
+ const rotation = new Euler7();
8158
8400
  if (typeof variant.x !== "undefined") {
8159
8401
  rotation.x = toRadians(clampRotationDegrees(variant.x));
8160
8402
  }
@@ -8264,7 +8506,7 @@ var import_ts_deepmerge6 = __toESM(require_dist());
8264
8506
  init_MineRenderError();
8265
8507
  init_InstanceReference();
8266
8508
  init_AssetKey();
8267
- import { Euler as Euler7, Matrix4 as Matrix47, Quaternion as Quaternion5, Vector3 as Vector311 } from "three";
8509
+ import { Euler as Euler8, Matrix4 as Matrix48, Quaternion as Quaternion5, Vector3 as Vector311 } from "three";
8268
8510
  init_ModelCulling();
8269
8511
  init_FluidGeometry();
8270
8512
  var _BlockObject = class _BlockObject extends SceneObject {
@@ -8330,7 +8572,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
8330
8572
  const scale = new Vector311();
8331
8573
  this.getModelMatrix(model).decompose(position, rotation, scale);
8332
8574
  if (position.distanceToSquared(this.position) > 1e-10 || scale.distanceToSquared(new Vector311(1, 1, 1)) > 1e-10) return 0;
8333
- return ModelCulling.toLocalMask(worldMask, new Euler7().setFromQuaternion(rotation));
8575
+ return ModelCulling.toLocalMask(worldMask, new Euler8().setFromQuaternion(rotation));
8334
8576
  }
8335
8577
  async setCullMask(worldMask) {
8336
8578
  worldMask &= 63;
@@ -8392,7 +8634,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
8392
8634
  () => new FluidModelObject2(kind, surface.sample, this.blockState.key, this.options)
8393
8635
  );
8394
8636
  const previous = this._fluidModel;
8395
- const matrix = previous ? this.getModelMatrix(previous) : new Matrix47().makeTranslation(...this.position.toArray());
8637
+ const matrix = previous ? this.getModelMatrix(previous) : new Matrix48().makeTranslation(...this.position.toArray());
8396
8638
  if (isInstanceReference(replacement)) replacement.setMatrix(matrix);
8397
8639
  else matrix.decompose(replacement.position, replacement.quaternion, replacement.scale);
8398
8640
  this._models = this._models.filter((model) => model !== previous);
@@ -8523,7 +8765,7 @@ var _BlockObject = class _BlockObject extends SceneObject {
8523
8765
  setPositionRotationScaleAt(index, position, rotation, scale) {
8524
8766
  super.setPositionRotationScaleAt(index, position, rotation, scale);
8525
8767
  }
8526
- getMatrixAt(index, matrix = new Matrix47()) {
8768
+ getMatrixAt(index, matrix = new Matrix48()) {
8527
8769
  if (!this.isInstanced) throw new MineRenderError("Object is not instanced");
8528
8770
  const child = this._models[0];
8529
8771
  if (child && isModelObject(child)) {
@@ -13087,7 +13329,7 @@ init_CubeFace();
13087
13329
  init_AssetKey();
13088
13330
  init_Models();
13089
13331
  init_CubeFace();
13090
- import { Matrix4 as Matrix48, Vector3 as Vector314 } from "three";
13332
+ import { Matrix4 as Matrix49, Vector3 as Vector314 } from "three";
13091
13333
  init_ModelCulling();
13092
13334
  init_ModelObject();
13093
13335
  init_UVMapper();
@@ -13150,7 +13392,7 @@ var SectionModels = class {
13150
13392
  });
13151
13393
  await object.init();
13152
13394
  const geometry = object.children[0].geometry;
13153
- geometry.applyMatrix4(new Matrix48().makeRotationFromEuler(rotation));
13395
+ geometry.applyMatrix4(new Matrix49().makeRotationFromEuler(rotation));
13154
13396
  object.clear();
13155
13397
  const cullFaces = CUBE_FACES.map((face) => {
13156
13398
  const local = CUBE_FACES.findIndex((name) => name === atlas.model.elements[0].faces[face]?.cullface);
@@ -13400,7 +13642,7 @@ var MineRenderWorld = class {
13400
13642
  // src/world/SectionMesh.ts
13401
13643
  init_CanvasCompat();
13402
13644
  init_Materials();
13403
- import { BufferGeometry as BufferGeometry5, Float32BufferAttribute as Float32BufferAttribute6, Group, Mesh as Mesh10 } from "three";
13645
+ import { BufferGeometry as BufferGeometry6, Float32BufferAttribute as Float32BufferAttribute6, Group, Mesh as Mesh10 } from "three";
13404
13646
  var SectionMesh = class _SectionMesh extends Group {
13405
13647
  constructor() {
13406
13648
  super(...arguments);
@@ -13474,7 +13716,7 @@ var SectionMesh = class _SectionMesh extends Group {
13474
13716
  for (let corner = 0; corner < 6; corner++) indices.push(start + sourceIndices.getX(face * 6 + corner) - face * 4);
13475
13717
  }
13476
13718
  }
13477
- const geometry = new BufferGeometry5();
13719
+ const geometry = new BufferGeometry6();
13478
13720
  geometry.setAttribute("position", new Float32BufferAttribute6(positions, 3));
13479
13721
  geometry.setAttribute("normal", new Float32BufferAttribute6(normals, 3));
13480
13722
  geometry.setAttribute("uv", new Float32BufferAttribute6(uvs, 2));