minerender 2.1.0-alpha.26 → 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);
@@ -81254,7 +81265,41 @@ return ${compiler2.callType("value", tagType)}
81254
81265
  var classicSkinTextureCoordinates = {
81255
81266
  ...baseSkinCoordinates
81256
81267
  };
81257
- var slimSkinTextureCoordinates = { ...baseSkinCoordinates };
81268
+ var slimSkinTextureCoordinates = {
81269
+ ...baseSkinCoordinates,
81270
+ leftArm: {
81271
+ ...baseSkinCoordinates.leftArm,
81272
+ west: { uv: [39, 52, 43, 64] },
81273
+ north: { uv: [36, 52, 39, 64] },
81274
+ south: { uv: [43, 52, 46, 64] },
81275
+ up: { uv: [39, 52, 36, 48] },
81276
+ down: { uv: [42, 48, 39, 52] }
81277
+ },
81278
+ rightArm: {
81279
+ ...baseSkinCoordinates.rightArm,
81280
+ west: { uv: [47, 20, 51, 32] },
81281
+ north: { uv: [44, 20, 47, 32] },
81282
+ south: { uv: [51, 20, 54, 32] },
81283
+ up: { uv: [47, 20, 44, 16] },
81284
+ down: { uv: [50, 16, 47, 20] }
81285
+ },
81286
+ leftSleeve: {
81287
+ ...baseSkinCoordinates.leftSleeve,
81288
+ west: { uv: [55, 52, 59, 64] },
81289
+ north: { uv: [52, 52, 55, 64] },
81290
+ south: { uv: [59, 52, 62, 64] },
81291
+ up: { uv: [55, 52, 52, 48] },
81292
+ down: { uv: [58, 48, 55, 52], rotation: 180 }
81293
+ },
81294
+ rightSleeve: {
81295
+ ...baseSkinCoordinates.rightSleeve,
81296
+ west: { uv: [47, 36, 51, 48] },
81297
+ north: { uv: [44, 36, 47, 48] },
81298
+ south: { uv: [51, 36, 54, 48] },
81299
+ up: { uv: [47, 36, 44, 32] },
81300
+ down: { uv: [50, 32, 47, 36], rotation: 180 }
81301
+ }
81302
+ };
81258
81303
 
81259
81304
  // src/skin/SkinGeometries.ts
81260
81305
  init_dirname();
@@ -81298,14 +81343,98 @@ return ${compiler2.callType("value", tagType)}
81298
81343
 
81299
81344
  // src/skin/scene/SkinObject.ts
81300
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
81301
81430
  var SkinObject = class extends SceneObject {
81302
81431
  constructor(options) {
81303
81432
  super();
81304
81433
  this.slim = false;
81305
- this.legacy = false;
81306
- this.skinTextureWidth = 64;
81307
- this.skinTextureHeight = 64;
81434
+ this.detectedSlim = false;
81435
+ this.skinLoad = 0;
81308
81436
  this.options = (0, import_ts_deepmerge7.default)({}, SceneObject.DEFAULT_OPTIONS, options ?? {});
81437
+ this.slim = this.options.slim ?? false;
81309
81438
  }
81310
81439
  async init() {
81311
81440
  this.createMeshes();
@@ -81314,15 +81443,13 @@ return ${compiler2.callType("value", tagType)}
81314
81443
  }
81315
81444
  createMeshes() {
81316
81445
  console.log("#createMeshes");
81317
- const mat = Materials.MISSING_TEXTURE;
81446
+ const mat = this.skinMaterial ?? Materials.MISSING_TEXTURE;
81318
81447
  {
81319
81448
  const headGroup = this.createAndAddGroup("head", 0, 28, 0, "y" /* Y */, -4);
81320
81449
  const headGeo = this.getBoxGeometry("head" /* HEAD */);
81321
81450
  const head = this.createAndAddMesh("head", headGroup, headGeo, mat, "y" /* Y */, 4);
81322
- if (!this.legacy) {
81323
- const hatGeo = this.getBoxGeometry("hat" /* HAT */);
81324
- const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, "y" /* Y */, 4);
81325
- }
81451
+ const hatGeo = this.getBoxGeometry("hat" /* HAT */);
81452
+ const hat = this.createAndAddMesh("hat", headGroup, hatGeo, mat, "y" /* Y */, 4);
81326
81453
  }
81327
81454
  {
81328
81455
  const bodyGroup = this.createAndAddGroup("body", 0, 18, 0);
@@ -81365,46 +81492,59 @@ return ${compiler2.callType("value", tagType)}
81365
81492
  }
81366
81493
  console.log("#createMeshes done");
81367
81494
  }
81368
- setSkinTexture(src) {
81495
+ async setSkinTexture(src) {
81369
81496
  if (typeof src === "undefined") return;
81370
81497
  this.skinTextureSrc = src;
81371
- const mat = Materials.getImage({
81372
- texture: { src },
81373
- transparent: true
81374
- });
81375
- for (let part of SKIN_PARTS) {
81376
- let mesh = this.getMeshByName(part);
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);
81377
81506
  if (mesh) {
81378
- mesh.material = mat;
81507
+ mesh.material = texture.material;
81379
81508
  }
81380
81509
  }
81510
+ this.notifyDirty();
81381
81511
  }
81382
81512
  //TODO: cape
81513
+ /** Select the arm model, or pass undefined to use texture detection. */
81383
81514
  setSlim(slim) {
81384
- console.log("#setSlim");
81385
- const changed = slim !== this.slim;
81515
+ this.options.slim = slim;
81516
+ this.updateSlim(slim ?? this.detectedSlim);
81517
+ }
81518
+ updateSlim(slim) {
81519
+ if (slim === this.slim) return;
81386
81520
  this.slim = slim;
81387
- if (changed) {
81388
- this.createMeshes();
81389
- }
81390
- if (changed) {
81391
- if (this.skinTextureSrc) {
81392
- this.setSkinTexture(this.skinTextureSrc);
81393
- }
81394
- }
81395
- console.log("#setSlim done");
81521
+ for (const part of ["leftArm" /* LEFT_ARM */, "leftSleeve" /* LEFT_SLEEVE */, "rightArm" /* RIGHT_ARM */, "rightSleeve" /* RIGHT_SLEEVE */]) {
81522
+ const mesh = this.getMeshByName(part);
81523
+ if (mesh) mesh.geometry = this.getBoxGeometry(part);
81524
+ }
81525
+ const offset = slim ? 0.5 : -0.5;
81526
+ const leftArm = this.getGroupByName("leftArm" /* LEFT_ARM */);
81527
+ const rightArm = this.getGroupByName("rightArm" /* RIGHT_ARM */);
81528
+ if (leftArm) leftArm.position.x += offset;
81529
+ if (rightArm) rightArm.position.x -= offset;
81530
+ this.notifyDirty();
81396
81531
  }
81397
- setLegacy(legacy) {
81398
- if (legacy !== this.legacy) {
81399
- }
81400
- 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();
81401
81541
  }
81402
81542
  //TODO: layer toggles
81403
81543
  getBoxGeometry(part) {
81404
81544
  console.log("slim", this.slim);
81405
81545
  const coordinates = this.slim ? slimSkinTextureCoordinates : classicSkinTextureCoordinates;
81406
81546
  const geometries = this.slim ? slimSkinGeometries : classicSkinGeometries;
81407
- 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]);
81408
81548
  }
81409
81549
  };
81410
81550
 
@@ -81514,10 +81654,10 @@ return ${compiler2.callType("value", tagType)}
81514
81654
  this.dirty = true;
81515
81655
  const obj = new SkinObject(options);
81516
81656
  obj.scene = this;
81517
- await obj.init();
81518
81657
  if (skin) {
81519
- obj.setSkinTexture(skin);
81658
+ await obj.setSkinTexture(skin);
81520
81659
  }
81660
+ await obj.init();
81521
81661
  parent.add(obj);
81522
81662
  return obj;
81523
81663
  }