minerender 2.1.0-alpha.27 → 2.1.0-alpha.28

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
@@ -45411,6 +45411,7 @@ return ${compiler2.callType("value", tagType)}
45411
45411
  SchematicParser: () => SchematicParser,
45412
45412
  SkinObject: () => SkinObject,
45413
45413
  SkinPart: () => SkinPart,
45414
+ SkinTextures: () => SkinTextures,
45414
45415
  Skins: () => Skins,
45415
45416
  StructureParser: () => StructureParser,
45416
45417
  TextureAtlas: () => TextureAtlas,
@@ -63612,6 +63613,16 @@ return ${compiler2.callType("value", tagType)}
63612
63613
  }
63613
63614
  }
63614
63615
  };
63616
+ var DataTexture = class extends Texture {
63617
+ constructor(data = null, width = 1, height = 1, format2, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace) {
63618
+ super(null, mapping, wrapS, wrapT, magFilter, minFilter, format2, type, anisotropy, colorSpace);
63619
+ this.isDataTexture = true;
63620
+ this.image = { data, width, height };
63621
+ this.generateMipmaps = false;
63622
+ this.flipY = false;
63623
+ this.unpackAlignment = 1;
63624
+ }
63625
+ };
63615
63626
  var InstancedBufferAttribute = class extends BufferAttribute {
63616
63627
  constructor(array, itemSize, normalized, meshPerAttribute = 1) {
63617
63628
  super(array, itemSize, normalized);
@@ -81332,14 +81343,98 @@ return ${compiler2.callType("value", tagType)}
81332
81343
 
81333
81344
  // src/skin/scene/SkinObject.ts
81334
81345
  var import_ts_deepmerge7 = __toESM(require_dist());
81346
+
81347
+ // src/skin/SkinTextures.ts
81348
+ init_dirname();
81349
+ init_buffer2();
81350
+ init_process2();
81351
+ var SkinTextures = class {
81352
+ static async get(src, legacy) {
81353
+ const image = await ImageLoader.getData(src);
81354
+ const scale = image.width / 64;
81355
+ if (!Number.isInteger(scale) || scale < 1 || image.height !== image.width && image.height !== image.width / 2) {
81356
+ throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; expected 64x64 or 64x32, or an integer-scaled equivalent`);
81357
+ }
81358
+ const isLegacy = legacy ?? image.height === image.width / 2;
81359
+ if (!isLegacy && image.height !== image.width) {
81360
+ throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; non-legacy skins must be square`);
81361
+ }
81362
+ const slim = !isLegacy && this.isSlim(image, scale);
81363
+ const key = `skin:${serializeImageKey({ src })}:${isLegacy}`;
81364
+ const material = Caching.materialCache.get(key, () => {
81365
+ const pixels = isLegacy ? this.normalizeLegacy(image, scale) : new Uint8Array(image.data);
81366
+ const texture = Textures.initTextureProps(new DataTexture(pixels, image.width, image.width));
81367
+ texture.colorSpace = SRGBColorSpace;
81368
+ texture.flipY = true;
81369
+ texture.needsUpdate = true;
81370
+ return new MeshBasicMaterial({ map: texture, transparent: true, side: DoubleSide, alphaTest: 0.5 });
81371
+ });
81372
+ return { material, slim, legacy: isLegacy };
81373
+ }
81374
+ static isSlim(image, scale) {
81375
+ for (const [x4, y5] of [[46, 52], [54, 20]]) {
81376
+ for (let row = y5 * scale; row < (y5 + 12) * scale; row++) {
81377
+ for (let column = x4 * scale; column < (x4 + 1) * scale; column++) {
81378
+ if (image.data[(row * image.width + column) * 4 + 3] !== 0) return false;
81379
+ }
81380
+ }
81381
+ }
81382
+ return true;
81383
+ }
81384
+ static normalizeLegacy(image, scale) {
81385
+ const pixels = new Uint8Array(image.width * image.width * 4);
81386
+ pixels.set(image.data.subarray(0, image.width * image.width / 2 * 4));
81387
+ for (const [sx, sy, dx, dy, width, height] of [
81388
+ [4, 16, 20, 48, 4, 4],
81389
+ [8, 16, 24, 48, 4, 4],
81390
+ [0, 20, 24, 52, 4, 12],
81391
+ [4, 20, 20, 52, 4, 12],
81392
+ [8, 20, 16, 52, 4, 12],
81393
+ [12, 20, 28, 52, 4, 12],
81394
+ [44, 16, 36, 48, 4, 4],
81395
+ [48, 16, 40, 48, 4, 4],
81396
+ [40, 20, 40, 52, 4, 12],
81397
+ [44, 20, 36, 52, 4, 12],
81398
+ [48, 20, 32, 52, 4, 12],
81399
+ [52, 20, 44, 52, 4, 12]
81400
+ ]) {
81401
+ for (let y5 = 0; y5 < height * scale; y5++) {
81402
+ for (let x4 = 0; x4 < width * scale; x4++) {
81403
+ const source = ((sy * scale + y5) * image.width + sx * scale + x4) * 4;
81404
+ const target = ((dy * scale + y5) * image.width + (dx + width) * scale - 1 - x4) * 4;
81405
+ pixels.set(image.data.subarray(source, source + 4), target);
81406
+ }
81407
+ }
81408
+ }
81409
+ let clearHat = true;
81410
+ for (let y5 = 0; y5 < 32 * scale; y5++) {
81411
+ for (let x4 = 32 * scale; x4 < image.width; x4++) {
81412
+ if (pixels[(y5 * image.width + x4) * 4 + 3] < 128) clearHat = false;
81413
+ }
81414
+ }
81415
+ for (let y5 = 0; y5 < image.width; y5++) {
81416
+ for (let x4 = 0; x4 < image.width; x4++) {
81417
+ const alpha = (y5 * image.width + x4) * 4 + 3;
81418
+ if (x4 < 32 * scale && y5 < 16 * scale || y5 >= 16 * scale && y5 < 32 * scale || x4 >= 16 * scale && x4 < 48 * scale && y5 >= 48 * scale) {
81419
+ pixels[alpha] = 255;
81420
+ } else if (clearHat && x4 >= 32 * scale && y5 < 32 * scale) {
81421
+ pixels[alpha] = 0;
81422
+ }
81423
+ }
81424
+ }
81425
+ return pixels;
81426
+ }
81427
+ };
81428
+
81429
+ // src/skin/scene/SkinObject.ts
81335
81430
  var SkinObject = class extends SceneObject {
81336
81431
  constructor(options) {
81337
81432
  super();
81338
81433
  this.slim = false;
81339
- this.legacy = false;
81340
- this.skinTextureWidth = 64;
81341
- this.skinTextureHeight = 64;
81434
+ this.detectedSlim = false;
81435
+ this.skinLoad = 0;
81342
81436
  this.options = (0, import_ts_deepmerge7.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
81437
+ this.slim = this.options.slim ?? false;
81343
81438
  }
81344
81439
  async init() {
81345
81440
  this.createMeshes();
@@ -81348,15 +81443,13 @@ return ${compiler2.callType("value", tagType)}
81348
81443
  }
81349
81444
  createMeshes() {
81350
81445
  console.log("#createMeshes");
81351
- const mat = Materials.MISSING_TEXTURE;
81446
+ const mat = this.skinMaterial ?? Materials.MISSING_TEXTURE;
81352
81447
  {
81353
81448
  const headGroup = this.createAndAddGroup("head", 0, 28, 0, "y" /* Y */, -4);
81354
81449
  const headGeo = this.getBoxGeometry("head" /* HEAD */);
81355
81450
  const head = this.createAndAddMesh("head", headGroup, headGeo, mat, "y" /* Y */, 4);
81356
- if (!this.legacy) {
81357
- const hatGeo = this.getBoxGeometry("hat" /* HAT */);
81358
- const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, "y" /* Y */, 4);
81359
- }
81451
+ const hatGeo = this.getBoxGeometry("hat" /* HAT */);
81452
+ const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, "y" /* Y */, 4);
81360
81453
  }
81361
81454
  {
81362
81455
  const bodyGroup = this.createAndAddGroup("body", 0, 18, 0);
@@ -81399,21 +81492,30 @@ return ${compiler2.callType("value", tagType)}
81399
81492
  }
81400
81493
  console.log("#createMeshes done");
81401
81494
  }
81402
- setSkinTexture(src) {
81495
+ async setSkinTexture(src) {
81403
81496
  if (typeof src === "undefined") return;
81404
- const mat = Materials.getImage({
81405
- texture: { src },
81406
- transparent: true
81407
- });
81408
- for (let part of SKIN_PARTS) {
81409
- let mesh = this.getMeshByName(part);
81497
+ this.skinTextureSrc = src;
81498
+ const load = ++this.skinLoad;
81499
+ const texture = await SkinTextures.get(src, this.options.legacy);
81500
+ if (load !== this.skinLoad) return;
81501
+ this.skinMaterial = texture.material;
81502
+ this.detectedSlim = texture.slim;
81503
+ this.updateSlim(this.options.slim ?? this.detectedSlim);
81504
+ for (const part of SKIN_PARTS) {
81505
+ const mesh = this.getMeshByName(part);
81410
81506
  if (mesh) {
81411
- mesh.material = mat;
81507
+ mesh.material = texture.material;
81412
81508
  }
81413
81509
  }
81510
+ this.notifyDirty();
81414
81511
  }
81415
81512
  //TODO: cape
81513
+ /** Select the arm model, or pass undefined to use texture detection. */
81416
81514
  setSlim(slim) {
81515
+ this.options.slim = slim;
81516
+ this.updateSlim(slim ?? this.detectedSlim);
81517
+ }
81518
+ updateSlim(slim) {
81417
81519
  if (slim === this.slim) return;
81418
81520
  this.slim = slim;
81419
81521
  for (const part of ["leftArm" /* LEFT_ARM */, "leftSleeve" /* LEFT_SLEEVE */, "rightArm" /* RIGHT_ARM */, "rightSleeve" /* RIGHT_SLEEVE */]) {
@@ -81427,17 +81529,22 @@ return ${compiler2.callType("value", tagType)}
81427
81529
  if (rightArm) rightArm.position.x -= offset;
81428
81530
  this.notifyDirty();
81429
81531
  }
81430
- setLegacy(legacy) {
81431
- if (legacy !== this.legacy) {
81432
- }
81433
- this.legacy = legacy;
81532
+ /** Select the texture layout, or pass undefined to detect it from image dimensions. */
81533
+ async setLegacy(legacy) {
81534
+ if (legacy === this.options.legacy) return;
81535
+ this.options.legacy = legacy;
81536
+ if (this.skinTextureSrc) await this.setSkinTexture(this.skinTextureSrc);
81537
+ }
81538
+ dispose() {
81539
+ this.skinLoad++;
81540
+ super.dispose();
81434
81541
  }
81435
81542
  //TODO: layer toggles
81436
81543
  getBoxGeometry(part) {
81437
81544
  console.log("slim", this.slim);
81438
81545
  const coordinates = this.slim ? slimSkinTextureCoordinates : classicSkinTextureCoordinates;
81439
81546
  const geometries = this.slim ? slimSkinGeometries : classicSkinGeometries;
81440
- return this._getBoxGeometryFromDimensions(geometries[part], coordinates[part], [64, 64], [this.skinTextureWidth, this.skinTextureHeight]);
81547
+ return this._getBoxGeometryFromDimensions(geometries[part], coordinates[part], [64, 64], [64, 64]);
81441
81548
  }
81442
81549
  };
81443
81550
 
@@ -81547,10 +81654,10 @@ return ${compiler2.callType("value", tagType)}
81547
81654
  this.dirty = true;
81548
81655
  const obj = new SkinObject(options);
81549
81656
  obj.scene = this;
81550
- await obj.init();
81551
81657
  if (skin) {
81552
- obj.setSkinTexture(skin);
81658
+ await obj.setSkinTexture(skin);
81553
81659
  }
81660
+ await obj.init();
81554
81661
  parent.add(obj);
81555
81662
  return obj;
81556
81663
  }