minerender 2.1.0-alpha.30 → 2.1.0-alpha.31

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.
@@ -5431,17 +5431,17 @@ var baseSkinCoordinates = {
5431
5431
  },
5432
5432
  up: {
5433
5433
  uv: [
5434
- 4,
5435
- 36,
5436
5434
  8,
5435
+ 36,
5436
+ 4,
5437
5437
  32
5438
5438
  ]
5439
5439
  },
5440
5440
  down: {
5441
5441
  uv: [
5442
- 8,
5443
- 32,
5444
5442
  12,
5443
+ 32,
5444
+ 8,
5445
5445
  36
5446
5446
  ],
5447
5447
  rotation: 180
@@ -5497,13 +5497,13 @@ var slimSkinTextureCoordinates = {
5497
5497
 
5498
5498
  // src/skin/SkinGeometries.ts
5499
5499
  var box8inner = [8, 8, 8];
5500
- var box8outer = [8.504, 8.504, 8.504];
5500
+ var box8outer = [9, 9, 9];
5501
5501
  var box8_12_4inner = [8, 12, 4];
5502
- var box8_12_4outer = [8.504, 12.504, 4.504];
5502
+ var box8_12_4outer = [8.5, 12.5, 4.5];
5503
5503
  var box4_12_4inner = [4, 12, 4];
5504
- var box4_12_4outer = [4.504, 12.504, 4.504];
5504
+ var box4_12_4outer = [4.5, 12.5, 4.5];
5505
5505
  var box3_12_4inner = [3, 12, 4];
5506
- var box3_12_4outer = [3.504, 12.504, 4.504];
5506
+ var box3_12_4outer = [3.5, 12.5, 4.5];
5507
5507
  var box10_16_1 = [10, 16, 1];
5508
5508
  var baseSkinGeometries = {
5509
5509
  head: box8inner,
@@ -5537,9 +5537,54 @@ var import_ts_deepmerge7 = __toESM(require_dist());
5537
5537
 
5538
5538
  // src/skin/SkinTextures.ts
5539
5539
  import { DataTexture, DoubleSide as DoubleSide2, FrontSide as FrontSide2, MeshBasicMaterial as MeshBasicMaterial3, SRGBColorSpace as SRGBColorSpace3 } from "three";
5540
+
5541
+ // src/skin/SkinImage.ts
5542
+ var SkinImage = class {
5543
+ static async getData(src) {
5544
+ const key = serializeImageKey({ src });
5545
+ return await Caching.imageDataCache.get(`skin:${key}`, async () => {
5546
+ const info = await ImageLoader.getInfo(src);
5547
+ if (info.type !== "png") return ImageLoader.getData(src);
5548
+ try {
5549
+ return await this.decodePng(info.data);
5550
+ } catch (error) {
5551
+ Caching.rawImageCache.invalidate(key);
5552
+ throw error;
5553
+ }
5554
+ });
5555
+ }
5556
+ static async decodePng(bytes) {
5557
+ const { decode, convertIndexedToRgb } = await import("fast-png");
5558
+ const png = decode(bytes);
5559
+ let { data, channels, depth } = png;
5560
+ if (channels === 1 && (png.palette || depth < 8)) {
5561
+ const max = (1 << depth) - 1;
5562
+ const palette = png.palette ?? Array.from({ length: max + 1 }, (_, value) => {
5563
+ const gray = value * 255 / max;
5564
+ return [gray, gray, gray, png.transparency?.[0] === value ? 0 : 255];
5565
+ });
5566
+ data = convertIndexedToRgb({ ...png, palette });
5567
+ channels = palette[0].length;
5568
+ depth = 8;
5569
+ }
5570
+ const pixels = new Uint8ClampedArray(png.width * png.height * 4);
5571
+ for (let pixel = 0; pixel < png.width * png.height; pixel++) {
5572
+ const source = pixel * channels;
5573
+ const target = pixel * 4;
5574
+ const sample = (channel) => depth === 16 ? data[source + channel] >>> 8 : data[source + channel];
5575
+ pixels[target] = sample(0);
5576
+ pixels[target + 1] = sample(channels < 3 ? 0 : 1);
5577
+ pixels[target + 2] = sample(channels < 3 ? 0 : 2);
5578
+ pixels[target + 3] = channels % 2 === 0 ? sample(channels - 1) : png.transparency?.every((value, channel) => data[source + channel] === value) ? 0 : 255;
5579
+ }
5580
+ return { width: png.width, height: png.height, data: pixels, colorSpace: "srgb" };
5581
+ }
5582
+ };
5583
+
5584
+ // src/skin/SkinTextures.ts
5540
5585
  var SkinTextures = class {
5541
5586
  static async get(src, legacy) {
5542
- const image = await ImageLoader.getData(src);
5587
+ const image = await SkinImage.getData(src);
5543
5588
  const scale = image.width / 64;
5544
5589
  if (!Number.isInteger(scale) || scale < 1 || image.height !== image.width && image.height !== image.width / 2) {
5545
5590
  throw new MineRenderError(`Invalid skin dimensions ${image.width}x${image.height}; expected 64x64 or 64x32, or an integer-scaled equivalent`);
@@ -5552,12 +5597,13 @@ var SkinTextures = class {
5552
5597
  const key = `skin:${serializeImageKey({ src })}:${isLegacy}`;
5553
5598
  const material = Caching.materialCache.get(key, () => {
5554
5599
  const pixels = isLegacy ? this.normalizeLegacy(image, scale) : new Uint8Array(image.data);
5600
+ this.makeBaseOpaque(pixels, image.width, scale);
5555
5601
  return this.createMaterial(pixels, image.width, image.width);
5556
5602
  });
5557
5603
  return { material, slim, legacy: isLegacy };
5558
5604
  }
5559
5605
  static async getCape(src, layout = "minecraft") {
5560
- const image = await ImageLoader.getData(src);
5606
+ const image = await SkinImage.getData(src);
5561
5607
  const scale = image.width / 64;
5562
5608
  if (layout === "minecraft" && (!Number.isInteger(scale) || scale < 1 || image.height !== image.width / 2)) {
5563
5609
  throw new MineRenderError(`Invalid cape dimensions ${image.width}x${image.height}; expected 64x32 or an integer-scaled equivalent`);
@@ -5571,7 +5617,7 @@ var SkinTextures = class {
5571
5617
  texture.colorSpace = SRGBColorSpace3;
5572
5618
  texture.flipY = true;
5573
5619
  texture.needsUpdate = true;
5574
- return new MeshBasicMaterial3({ map: texture, transparent, side: transparent ? DoubleSide2 : FrontSide2, alphaTest: transparent ? 0.5 : 0 });
5620
+ return new MeshBasicMaterial3({ map: texture, transparent, side: transparent ? DoubleSide2 : FrontSide2, alphaTest: transparent ? 0.1 : 0 });
5575
5621
  }
5576
5622
  static isSlim(image, scale) {
5577
5623
  for (const [x, y] of [[46, 52], [54, 20]]) {
@@ -5614,18 +5660,22 @@ var SkinTextures = class {
5614
5660
  if (pixels[(y * image.width + x) * 4 + 3] < 128) clearHat = false;
5615
5661
  }
5616
5662
  }
5617
- for (let y = 0; y < image.width; y++) {
5618
- for (let x = 0; x < image.width; x++) {
5619
- const alpha = (y * image.width + x) * 4 + 3;
5620
- if (x < 32 * scale && y < 16 * scale || y >= 16 * scale && y < 32 * scale || x >= 16 * scale && x < 48 * scale && y >= 48 * scale) {
5621
- pixels[alpha] = 255;
5622
- } else if (clearHat && x >= 32 * scale && y < 32 * scale) {
5623
- pixels[alpha] = 0;
5663
+ if (clearHat) {
5664
+ for (let y = 0; y < 32 * scale; y++) {
5665
+ for (let x = 32 * scale; x < image.width; x++) {
5666
+ pixels[(y * image.width + x) * 4 + 3] = 0;
5624
5667
  }
5625
5668
  }
5626
5669
  }
5627
5670
  return pixels;
5628
5671
  }
5672
+ static makeBaseOpaque(pixels, width, scale) {
5673
+ for (const [x0, y0, x1, y1] of [[0, 0, 32, 16], [0, 16, 64, 32], [16, 48, 48, 64]]) {
5674
+ for (let y = y0 * scale; y < y1 * scale; y++) {
5675
+ for (let x = x0 * scale; x < x1 * scale; x++) pixels[(y * width + x) * 4 + 3] = 255;
5676
+ }
5677
+ }
5678
+ }
5629
5679
  };
5630
5680
 
5631
5681
  // src/skin/CapeLayout.ts
@@ -5647,12 +5697,13 @@ var SkinObject = class extends SceneObject {
5647
5697
  this.slim = this.options.slim ?? false;
5648
5698
  }
5649
5699
  async init() {
5700
+ const cape = this.getGroupByName("cape" /* CAPE */);
5650
5701
  this.createMeshes();
5702
+ if (cape) this.getGroupByName("body" /* BODY */).attach(cape);
5651
5703
  }
5652
5704
  removeMeshes() {
5653
5705
  }
5654
5706
  createMeshes() {
5655
- console.log("#createMeshes");
5656
5707
  const mat = this.skinMaterial ?? Materials.MISSING_TEXTURE;
5657
5708
  {
5658
5709
  const headGroup = this.createAndAddGroup("head", 0, 28, 0, "y" /* Y */, -4);
@@ -5662,45 +5713,48 @@ var SkinObject = class extends SceneObject {
5662
5713
  const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, "y" /* Y */, 4);
5663
5714
  }
5664
5715
  {
5665
- const bodyGroup = this.createAndAddGroup("body", 0, 18, 0);
5716
+ const bodyGroup = this.createAndAddGroup("body", 0, 24, 0);
5666
5717
  const bodyGeo = this.getBoxGeometry("body" /* BODY */);
5667
- const body = this.createAndAddMesh("body", bodyGroup, bodyGeo, mat);
5718
+ const body = this.createAndAddMesh("body", bodyGroup, bodyGeo, mat, "y" /* Y */, -6);
5668
5719
  const jacketGeo = this.getBoxGeometry("jacket" /* JACKET */);
5669
- const jacket = this.createAndAddMesh("jacket", bodyGroup, jacketGeo, mat);
5720
+ const jacket = this.createAndAddMesh("jacket", bodyGroup, jacketGeo, mat, "y" /* Y */, -6);
5670
5721
  }
5671
5722
  {
5672
5723
  {
5673
- const leftArmGroup = this.createAndAddGroup("leftArm", this.slim ? -5.5 : -6, 18, 0, "y" /* Y */, 4);
5724
+ const leftArmGroup = this.createAndAddGroup("leftArm", -5, 22, 0);
5674
5725
  const leftArmGeo = this.getBoxGeometry("leftArm" /* LEFT_ARM */);
5675
5726
  const leftArm = this.createAndAddMesh("leftArm", leftArmGroup, leftArmGeo, mat, "y" /* Y */, -4);
5727
+ leftArm.position.x = this.slim ? -0.5 : -1;
5676
5728
  const leftSleeveGeo = this.getBoxGeometry("leftSleeve" /* LEFT_SLEEVE */);
5677
5729
  const leftSleeve = this.createAndAddMesh("leftSleeve", leftArmGroup, leftSleeveGeo, mat, "y" /* Y */, -4);
5730
+ leftSleeve.position.x = this.slim ? -0.5 : -1;
5678
5731
  }
5679
5732
  {
5680
- const rightArmGroup = this.createAndAddGroup("rightArm", this.slim ? 5.5 : 6, 18, 0, "y" /* Y */, 4);
5733
+ const rightArmGroup = this.createAndAddGroup("rightArm", 5, 22, 0);
5681
5734
  const rightArmGeo = this.getBoxGeometry("rightArm" /* RIGHT_ARM */);
5682
5735
  const rightArm = this.createAndAddMesh("rightArm", rightArmGroup, rightArmGeo, mat, "y" /* Y */, -4);
5736
+ rightArm.position.x = this.slim ? 0.5 : 1;
5683
5737
  const rightSleeveGeo = this.getBoxGeometry("rightSleeve" /* RIGHT_SLEEVE */);
5684
5738
  const rightSleeve = this.createAndAddMesh("rightSleeve", rightArmGroup, rightSleeveGeo, mat, "y" /* Y */, -4);
5739
+ rightSleeve.position.x = this.slim ? 0.5 : 1;
5685
5740
  }
5686
5741
  }
5687
5742
  {
5688
5743
  {
5689
- const leftLegGroup = this.createAndAddGroup("leftLeg", -2, 6, 0, "y" /* Y */, 4);
5744
+ const leftLegGroup = this.createAndAddGroup("leftLeg", -1.9, 12, 0);
5690
5745
  const leftLegGeo = this.getBoxGeometry("leftLeg" /* LEFT_LEG */);
5691
- const leftLeg = this.createAndAddMesh("leftLeg", leftLegGroup, leftLegGeo, mat, "y" /* Y */, -4);
5746
+ const leftLeg = this.createAndAddMesh("leftLeg", leftLegGroup, leftLegGeo, mat, "y" /* Y */, -6);
5692
5747
  const leftTrousersGeo = this.getBoxGeometry("leftTrousers" /* LEFT_TROUSERS */);
5693
- const leftTrousers = this.createAndAddMesh("leftTrousers", leftLegGroup, leftTrousersGeo, mat, "y" /* Y */, -4);
5748
+ const leftTrousers = this.createAndAddMesh("leftTrousers", leftLegGroup, leftTrousersGeo, mat, "y" /* Y */, -6);
5694
5749
  }
5695
5750
  {
5696
- const rightLegGroup = this.createAndAddGroup("rightLeg", 2, 6, 0, "y" /* Y */, 4);
5751
+ const rightLegGroup = this.createAndAddGroup("rightLeg", 1.9, 12, 0);
5697
5752
  const rightLegGeo = this.getBoxGeometry("rightLeg" /* RIGHT_LEG */);
5698
- const rightLeg = this.createAndAddMesh("rightLeg", rightLegGroup, rightLegGeo, mat, "y" /* Y */, -4);
5753
+ const rightLeg = this.createAndAddMesh("rightLeg", rightLegGroup, rightLegGeo, mat, "y" /* Y */, -6);
5699
5754
  const rightTrousersGeo = this.getBoxGeometry("rightTrousers" /* RIGHT_TROUSERS */);
5700
- const rightTrousers = this.createAndAddMesh("rightTrousers", rightLegGroup, rightTrousersGeo, mat, "y" /* Y */, -4);
5755
+ const rightTrousers = this.createAndAddMesh("rightTrousers", rightLegGroup, rightTrousersGeo, mat, "y" /* Y */, -6);
5701
5756
  }
5702
5757
  }
5703
- console.log("#createMeshes done");
5704
5758
  }
5705
5759
  async setSkinTexture(src) {
5706
5760
  if (typeof src === "undefined") return;
@@ -5725,7 +5779,7 @@ var SkinObject = class extends SceneObject {
5725
5779
  const load = ++this.capeLoad;
5726
5780
  if (src === void 0) {
5727
5781
  const group = this.getGroupByName("cape" /* CAPE */);
5728
- if (group) this.remove(group);
5782
+ group?.removeFromParent();
5729
5783
  this.notifyDirty();
5730
5784
  return;
5731
5785
  }
@@ -5743,7 +5797,9 @@ var SkinObject = class extends SceneObject {
5743
5797
  mesh.material = material;
5744
5798
  mesh.geometry = geometry;
5745
5799
  } else {
5746
- const group = this.createAndAddGroup("cape" /* CAPE */, 0, 24, 2);
5800
+ const body = this.getGroupByName("body" /* BODY */);
5801
+ const group = this.createGroup("cape" /* CAPE */, 0, body ? 0 : 24, 2);
5802
+ (body ?? this).add(group);
5747
5803
  group.rotation.set(toRadians(-6), Math.PI, 0);
5748
5804
  const cape = this.createAndAddMesh("cape" /* CAPE */, group, geometry, material);
5749
5805
  cape.position.set(0, -8, -0.5);
@@ -5758,15 +5814,14 @@ var SkinObject = class extends SceneObject {
5758
5814
  updateSlim(slim) {
5759
5815
  if (slim === this.slim) return;
5760
5816
  this.slim = slim;
5817
+ const offset = slim ? 0.5 : -0.5;
5761
5818
  for (const part of ["leftArm" /* LEFT_ARM */, "leftSleeve" /* LEFT_SLEEVE */, "rightArm" /* RIGHT_ARM */, "rightSleeve" /* RIGHT_SLEEVE */]) {
5762
5819
  const mesh = this.getMeshByName(part);
5763
- if (mesh) mesh.geometry = this.getBoxGeometry(part);
5820
+ if (mesh) {
5821
+ mesh.geometry = this.getBoxGeometry(part);
5822
+ mesh.position.x += part === "leftArm" /* LEFT_ARM */ || part === "leftSleeve" /* LEFT_SLEEVE */ ? offset : -offset;
5823
+ }
5764
5824
  }
5765
- const offset = slim ? 0.5 : -0.5;
5766
- const leftArm = this.getGroupByName("leftArm" /* LEFT_ARM */);
5767
- const rightArm = this.getGroupByName("rightArm" /* RIGHT_ARM */);
5768
- if (leftArm) leftArm.position.x += offset;
5769
- if (rightArm) rightArm.position.x -= offset;
5770
5825
  this.notifyDirty();
5771
5826
  }
5772
5827
  /** Select the texture layout, or pass undefined to detect it from image dimensions. */
@@ -5782,7 +5837,6 @@ var SkinObject = class extends SceneObject {
5782
5837
  }
5783
5838
  //TODO: layer toggles
5784
5839
  getBoxGeometry(part) {
5785
- console.log("slim", this.slim);
5786
5840
  const coordinates = this.slim ? slimSkinTextureCoordinates : classicSkinTextureCoordinates;
5787
5841
  const geometries = this.slim ? slimSkinGeometries : classicSkinGeometries;
5788
5842
  return this._getBoxGeometryFromDimensions(geometries[part], coordinates[part], [64, 64], [64, 64]);
@@ -7365,6 +7419,7 @@ export {
7365
7419
  SceneStats,
7366
7420
  SceneStatsDisplay,
7367
7421
  SchematicParser,
7422
+ SkinImage,
7368
7423
  SkinObject,
7369
7424
  SkinPart,
7370
7425
  SkinTextures,