@xmcl/model
Version:
Create Three.js model for player and block
919 lines (914 loc) • 28.4 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
return value;
};
// block.ts
import { LinearFilter, NearestFilter } from "three/src/constants";
import { Object3D } from "three/src/core/Object3D";
import { TextureLoader } from "three/src/loaders/TextureLoader";
import { MeshBasicMaterial } from "three/src/materials/MeshBasicMaterial";
import { MeshLambertMaterial } from "three/src/materials/MeshLambertMaterial";
import { Mesh } from "three/src/objects/Mesh";
import { Group } from "three/src/objects/Group";
import { BoxGeometry } from "three/src/geometries/BoxGeometry";
import { Vector3 } from "three/src/math/Vector3";
import { Vector2 } from "three/src/math/Vector2";
import { BufferAttribute } from "three/src/core/BufferAttribute";
var BasicTextureManager = class {
constructor(textures = {}, loader = new TextureLoader()) {
this.textures = textures;
this.loader = loader;
}
hasTexture(path) {
return !!this.textures[path];
}
loadTexture(path) {
const texture = this.loader.load(this.textures[path].url);
texture.magFilter = NearestFilter;
texture.minFilter = LinearFilter;
return texture;
}
};
var DEFAULT_TRANSFORM = {
rotation: [0, 0, 0],
translation: [0, 0, 0],
scale: [1, 1, 1]
};
var DEFAULT_DISPLAY = {
ground: DEFAULT_TRANSFORM,
gui: DEFAULT_TRANSFORM,
thirdperson_lefthand: DEFAULT_TRANSFORM,
thirdperson_righthand: DEFAULT_TRANSFORM,
firstperson_lefthand: DEFAULT_TRANSFORM,
firstperson_righthand: DEFAULT_TRANSFORM,
fixed: DEFAULT_TRANSFORM,
head: DEFAULT_TRANSFORM
};
var BUILTIN_GENERATED = {
display: DEFAULT_DISPLAY,
ambientocclusion: false,
textures: {},
elements: [
{
from: [0, 0, 0],
to: [16, 16, 16],
faces: {
down: { uv: [0, 0, 16, 16], texture: "" }
}
}
],
overrides: []
};
function findRealTexturePath(model, variantKey) {
let texturePath = model.textures[variantKey];
while (texturePath.startsWith("#")) {
const next = model.textures[texturePath.substring(1, texturePath.length)];
if (!next) {
return void 0;
}
texturePath = next;
}
return texturePath;
}
var BlockModelObject = class extends Object3D {
animationLoop = false;
displayOption = DEFAULT_DISPLAY;
applyDisplay(option) {
const group = this.children[0];
if (option === "block") {
group.rotation.set(0, 0, 0);
group.position.set(0, 0, 0);
group.scale.set(1, 1, 1);
} else {
if (!(option in this.displayOption)) {
throw new Error("Display option is invalid.");
}
const options = this.displayOption[option];
const rot = options.rotation;
const pos = options.translation;
const scale = options.scale;
group.rotation.set(rot[0] * Math.PI / 180, rot[1] * Math.PI / 180, rot[2] * Math.PI / 180);
group.position.set(pos[0], pos[1], pos[2]);
group.scale.set(scale[0] === 0 ? 1e-5 : scale[0], scale[1] === 0 ? 1e-5 : scale[1], scale[2] === 0 ? 1e-5 : scale[2]);
}
}
getCenter() {
const group = this.children[0];
const box = {
minx: 0,
miny: 0,
minz: 0,
maxx: 0,
maxy: 0,
maxz: 0
};
for (let i = 0; i < group.children.length; i++) {
const pivot = group.children[i];
const mesh = pivot.children[0];
const geo = mesh.geometry;
}
return new Vector3(
(box.minx + box.maxx) / 2,
(box.miny + box.maxy) / 2,
(box.minz + box.maxz) / 2
);
}
};
var _BlockModelFactory = class {
constructor(textureManager, option = {}) {
this.textureManager = textureManager;
this.option = option;
}
cachedMaterial = {};
/**
* Get threejs `Object3D` for that block model.
*/
getObject(model, options = {}, fix = 1e-3) {
const xRotation = options.x || 0;
const yRotation = options.y || 0;
const uvlock = options.uvlock || false;
const option = this.option;
const textureManager = this.textureManager;
const clipUVs = option.clipUVs || false;
const modelOnly = option.modelOnly || false;
const obj = new BlockModelObject();
const group = new Group();
group.name = "wrapper";
const materials = [_BlockModelFactory.TRANSPARENT_MATERIAL];
const materialIndexes = {};
const materialPathIndexes = {};
for (const variant of Object.keys(model.textures)) {
const texPath = findRealTexturePath(model, variant);
let materialIndex = 0;
if (!texPath) {
console.error(`Cannot find texture {texPath}`);
} else {
let materialPathIndex = materialPathIndexes[texPath];
if (materialPathIndex) {
} else if (texPath in this.cachedMaterial) {
materialPathIndex = materials.length;
materials.push(this.cachedMaterial[texPath]);
} else if (textureManager.hasTexture(texPath)) {
const texture = textureManager.loadTexture(texPath);
const mat = new MeshLambertMaterial({ map: texture, transparent: true, alphaTest: 0.5 });
materialPathIndex = materials.length;
this.cachedMaterial[texPath] = mat;
mat.name = texPath;
materials.push(mat);
}
materialPathIndexes[texPath] = materialPathIndex;
materialIndex = materialPathIndex;
}
materialIndexes[variant] = materialIndex;
}
for (const element of model.elements) {
const width = element.to[0] - element.from[0];
const height = element.to[1] - element.from[1];
const length = element.to[2] - element.from[2];
const origin = {
x: (element.to[0] + element.from[0]) / 2 - 8,
y: (element.to[1] + element.from[1]) / 2 - 8,
z: (element.to[2] + element.from[2]) / 2 - 8
};
const blockGeometry = new BoxGeometry(width + fix, height + fix, length + fix);
const blockMesh = new Mesh(blockGeometry, materials);
blockMesh.name = "block-element";
blockGeometry.clearGroups();
blockMesh.position.x = origin.x;
blockMesh.position.y = origin.y;
blockMesh.position.z = origin.z;
const uvAttr = [];
const faces = ["east", "west", "up", "down", "south", "north"];
const getDefaultUv = (i) => [
[
// east
element.from[2],
element.from[1],
element.to[2],
element.to[1]
],
[
// west
element.from[2],
element.from[1],
element.to[2],
element.to[1]
],
[
// up
element.from[0],
element.from[2],
element.to[0],
element.to[2]
],
[
// down
element.from[0],
element.from[2],
element.to[0],
element.to[2]
],
[
// south
element.from[0],
element.from[1],
element.to[0],
element.to[1]
],
[
// north
element.from[0],
element.from[1],
element.to[0],
element.to[1]
]
][i];
for (let i = 0; i < 6; i++) {
const faceName = faces[i];
const face = element.faces[faceName];
let materialIndex = 0;
let uv;
if (face) {
materialIndex = materialIndexes[face.texture.substring(1, face.texture.length)];
uv = face.uv || getDefaultUv(i);
if (clipUVs) {
uv = uv.map((e) => {
if (e + 1e-5 < 0) {
return 0;
} else if (e - 1e-5 > 16) {
return 16;
} else {
return e;
}
});
}
uv = uv.map((e) => e / 16);
} else {
uv = [0, 0, 1, 1];
}
const [x1, y1, x2, y2] = uv;
let map = [
new Vector2(x1, y2),
new Vector2(x2, y2),
new Vector2(x1, y1),
new Vector2(x2, y1)
];
if (face && face.rotation) {
let amount = Number(face.rotation);
if (!([0, 90, 180, 270].indexOf(amount) >= 0)) {
console.error('The "rotation" property for "' + face + '" face is invalid (got "' + amount + '").');
}
amount = (360 - amount) % 360;
for (let j = 0; j < amount / 90; j++) {
map = [map[1], map[3], map[0], map[2]];
}
}
if (uvlock) {
let rotation = 0;
if (xRotation >= 180) {
if (faceName === "up") {
rotation = yRotation;
} else if (faceName === "down") {
rotation = (360 - yRotation) % 360;
} else {
rotation = xRotation;
}
} else {
if (faceName === "down") {
rotation = yRotation;
} else if (faceName === "up") {
rotation = (360 - yRotation) % 360;
} else {
rotation = xRotation;
}
}
for (let j = 0; j < rotation / 90; j++) {
for (let m = 0; m < map.length; m++) {
const vector = map[m];
const x = vector.x;
const y = vector.y;
vector.x = 1 - y;
vector.y = x;
}
}
}
uvAttr.push(
map[0].x,
map[0].y,
map[1].x,
map[1].y,
map[2].x,
map[2].y,
map[3].x,
map[3].y
);
blockGeometry.addGroup(i * 6, 6, materialIndex);
}
blockGeometry.setAttribute("uv", new BufferAttribute(
new Float32Array(uvAttr),
2
));
if (element.rotation) {
const rotationOrigin = {
x: element.rotation.origin[0] - 8,
y: element.rotation.origin[1] - 8,
z: element.rotation.origin[2] - 8
};
const axis = element.rotation.axis;
const angle = element.rotation.angle;
const pivot = new Group();
pivot.name = "pivot";
pivot.position.x = rotationOrigin.x;
pivot.position.y = rotationOrigin.y;
pivot.position.z = rotationOrigin.z;
pivot.add(blockMesh);
blockMesh.position.x -= rotationOrigin.x;
blockMesh.position.y -= rotationOrigin.y;
blockMesh.position.z -= rotationOrigin.z;
if (axis === "x") {
pivot.rotateX(angle * Math.PI / 180);
} else if (axis === "y") {
pivot.rotateY(angle * Math.PI / 180);
} else if (axis === "z") {
pivot.rotateZ(angle * Math.PI / 180);
}
const rescale = element.rotation.rescale || false;
if (rescale) {
if (angle % 90 === 45) {
if (axis === "x") {
pivot.scale.y *= Math.sqrt(2);
pivot.scale.z *= Math.sqrt(2);
}
if (axis === "y") {
pivot.scale.x *= Math.sqrt(2);
pivot.scale.z *= Math.sqrt(2);
}
if (axis === "z") {
pivot.scale.x *= Math.sqrt(2);
pivot.scale.y *= Math.sqrt(2);
}
}
}
group.add(pivot);
} else {
const pivot = new Group();
pivot.name = "pivot";
pivot.add(blockMesh);
group.add(pivot);
}
}
obj.rotateY(-yRotation * Math.PI / 180);
obj.rotateX(-xRotation * Math.PI / 180);
obj.add(group);
return obj;
}
};
var BlockModelFactory = _BlockModelFactory;
__publicField(BlockModelFactory, "TRANSPARENT_MATERIAL", new MeshBasicMaterial({ transparent: true, opacity: 0, alphaTest: 0.5 }));
// player.ts
import { BufferAttribute as BufferAttribute2, Vector2 as Vector22 } from "three";
import { DoubleSide, NearestFilter as NearestFilter2 } from "three/src/constants";
import { Object3D as Object3D2 } from "three/src/core/Object3D";
import { BoxGeometry as BoxGeometry2 } from "three/src/geometries/BoxGeometry";
import { BoxHelper } from "three/src/helpers/BoxHelper";
import { MeshBasicMaterial as MeshBasicMaterial2 } from "three/src/materials/MeshBasicMaterial";
import { Color } from "three/src/math/Color";
import { Mesh as Mesh2 } from "three/src/objects/Mesh";
import { CanvasTexture } from "three/src/textures/CanvasTexture";
// player-model.ts
function createGroup(slim) {
return {
head: {
h: 0,
w: 0,
d: 0,
x: 0,
y: 0,
z: 0,
layer: {
w: 9,
h: 9,
d: 9,
top: [40, 0, 48, 8],
bottom: [48, 0, 56, 8],
right: [32, 8, 40, 16],
front: [40, 8, 48, 16],
left: [48, 8, 56, 16],
back: [56, 8, 64, 16]
},
top: [8, 0, 16, 8],
bottom: [24, 8, 16, 0],
right: [0, 8, 8, 16],
front: [8, 8, 16, 16],
left: [16, 8, 24, 16],
back: [24, 8, 32, 16]
},
rightLeg: {
h: 0,
w: 0,
d: 0,
x: 0,
y: 0,
z: 0,
layer: {
w: 4.5,
d: 4.5,
h: 13.5,
top: [4, 48, 8, 36],
bottom: [8, 48, 12, 36],
right: [0, 36, 4, 48],
front: [4, 36, 8, 48],
left: [8, 36, 12, 48],
back: [12, 36, 16, 48]
},
top: [4, 16, 8, 20],
bottom: [8, 16, 12, 20],
right: [0, 20, 4, 32],
front: [4, 20, 8, 32],
left: [8, 20, 12, 32],
back: [12, 20, 16, 32]
},
torso: {
h: 0,
w: 0,
d: 0,
x: 0,
y: 0,
z: 0,
layer: {
w: 9,
h: 13.5,
d: 4.5,
top: [20, 48, 28, 36],
bottom: [28, 48, 36, 36],
right: [16, 36, 20, 48],
front: [20, 36, 28, 48],
left: [28, 36, 32, 48],
back: [32, 36, 40, 48]
},
top: [20, 16, 28, 20],
bottom: [28, 16, 36, 20],
right: [16, 20, 20, 32],
front: [20, 20, 28, 32],
left: [28, 20, 32, 32],
back: [32, 20, 40, 32]
},
leftArm: {
h: 0,
w: 0,
d: 0,
x: 0,
y: 0,
z: 0,
layer: {
w: 4.5,
h: 13.5,
d: 4.5,
top: [52, 48, 56, 52],
bottom: [56, 48, 60, 52],
right: [48, 52, 52, 64],
front: [52, 52, 56, 64],
left: [56, 52, 60, 64],
back: [60, 52, 64, 64]
},
top: [36, 48, slim ? 39 : 40, 52],
bottom: [slim ? 39 : 40, 48, slim ? 42 : 44, 52],
left: [32, 52, 36, 64],
front: [36, 52, slim ? 39 : 40, 64],
right: [slim ? 39 : 40, 52, slim ? 43 : 44, 64],
back: [slim ? 43 : 44, 52, slim ? 46 : 48, 64]
},
rightArm: {
h: 0,
w: 0,
d: 0,
x: 0,
y: 0,
z: 0,
layer: {
w: 4.5,
h: 13.5,
d: 4.5,
top: [44, 48, 48, 36],
bottom: [48, 48, 52, 36],
left: [48, 36, 52, 48],
front: [44, 36, 48, 48],
right: [40, 36, 44, 48],
back: [52, 36, 64, 48]
},
top: [44, 16, slim ? 47 : 48, 20],
bottom: [slim ? 47 : 48, 16, slim ? 50 : 52, 20],
left: [40, 20, 44, 32],
front: [44, 20, slim ? 47 : 48, 32],
right: [slim ? 47 : 48, 20, slim ? 51 : 52, 32],
back: [slim ? 51 : 52, 20, slim ? 54 : 56, 32]
},
leftLeg: {
h: 0,
w: 0,
d: 0,
x: 0,
y: 0,
z: 0,
layer: {
w: 4.5,
d: 4.5,
h: 13.5,
top: [4, 48, 8, 52],
bottom: [8, 48, 12, 52],
right: [0, 52, 4, 64],
front: [4, 52, 8, 64],
left: [8, 52, 12, 64],
back: [12, 52, 16, 64]
},
top: [20, 48, 24, 52],
bottom: [24, 48, 28, 52],
right: [16, 52, 20, 64],
front: [20, 52, 24, 64],
left: [24, 52, 28, 64],
back: [28, 52, 32, 64]
},
cape: {
x: 0,
y: 0,
z: 0,
h: 0,
w: 0,
d: 0,
top: [1, 0, 11, 1],
bottom: [11, 0, 21, 1],
left: [11, 1, 12, 17],
front: [12, 1, 22, 17],
right: [0, 1, 1, 17],
back: [1, 1, 11, 17]
}
};
}
var PIXRATIO = 1 / 32;
function create(slim) {
function decorateDimension(group) {
function calculate(model) {
return {
h: Math.abs(model.front[1] - model.front[3]) * PIXRATIO,
w: Math.abs(model.front[0] - model.front[2]) * PIXRATIO,
d: Math.abs(model.right[0] - model.right[2]) * PIXRATIO
};
}
for (const part of Object.values(group)) {
Object.assign(part, calculate(part));
if ("layer" in part) {
part.layer.w *= PIXRATIO;
part.layer.h *= PIXRATIO;
part.layer.d *= PIXRATIO;
}
}
return group;
}
function decoratePos(group) {
const charH = 1;
group.head.y = charH - group.head.h / 2;
group.torso.y = group.rightLeg.h + group.torso.h / 2;
group.rightLeg.x = -group.rightLeg.w / 2;
group.rightLeg.y = group.rightLeg.h / 2;
group.leftLeg.x = group.leftLeg.w / 2;
group.leftLeg.y = group.leftLeg.h / 2;
group.rightArm.x = -group.torso.w / 2 - group.rightArm.w / 2;
group.rightArm.y = group.rightLeg.h + group.torso.h - group.rightArm.h / 2;
group.leftArm.x = group.torso.w / 2 + group.leftArm.w / 2;
group.leftArm.y = group.leftLeg.h + group.torso.h - group.leftArm.h / 2;
group.cape.y = group.rightLeg.h + group.torso.h / 5 * 2;
group.cape.z = -group.torso.d * 3 / 2;
return group;
}
return decoratePos(decorateDimension(createGroup(slim)));
}
var player_model_default = {
steve: create(false),
alex: create(true)
};
// player.ts
function convertLegacySkin(context, width) {
const scale = width / 64;
function copySkin(ctx, sX, sY, w, h, dX, dY, flipHorizontal) {
sX *= scale;
sY *= scale;
w *= scale;
h *= scale;
dX *= scale;
dY *= scale;
const imgData = ctx.getImageData(sX, sY, w, h);
if (flipHorizontal) {
for (let y = 0; y < h; y++) {
for (let x = 0; x < w / 2; x++) {
const index = (x + y * w) * 4;
const index2 = (w - x - 1 + y * w) * 4;
const pA1 = imgData.data[index];
const pA2 = imgData.data[index + 1];
const pA3 = imgData.data[index + 2];
const pA4 = imgData.data[index + 3];
const pB1 = imgData.data[index2];
const pB2 = imgData.data[index2 + 1];
const pB3 = imgData.data[index2 + 2];
const pB4 = imgData.data[index2 + 3];
imgData.data[index] = pB1;
imgData.data[index + 1] = pB2;
imgData.data[index + 2] = pB3;
imgData.data[index + 3] = pB4;
imgData.data[index2] = pA1;
imgData.data[index2 + 1] = pA2;
imgData.data[index2 + 2] = pA3;
imgData.data[index2 + 3] = pA4;
}
}
}
ctx.putImageData(imgData, dX, dY);
}
copySkin(context, 4, 16, 4, 4, 20, 48, true);
copySkin(context, 8, 16, 4, 4, 24, 48, true);
copySkin(context, 0, 20, 4, 12, 24, 52, true);
copySkin(context, 4, 20, 4, 12, 20, 52, true);
copySkin(context, 8, 20, 4, 12, 16, 52, true);
copySkin(context, 12, 20, 4, 12, 28, 52, true);
copySkin(context, 44, 16, 4, 4, 36, 48, true);
copySkin(context, 48, 16, 4, 4, 40, 48, true);
copySkin(context, 40, 20, 4, 12, 40, 52, true);
copySkin(context, 44, 20, 4, 12, 36, 52, true);
copySkin(context, 48, 20, 4, 12, 32, 52, true);
copySkin(context, 52, 20, 4, 12, 44, 52, true);
}
function mapCubeUV(mesh, src) {
const material = mesh.material;
const texture = material.map;
const tileUvW = 1 / texture.image.width;
const tileUvH = 1 / texture.image.height;
const uvs = [];
function mapUV(x1, y1, x2, y2) {
x1 *= tileUvW;
x2 *= tileUvW;
y1 = 1 - y1 * tileUvH;
y2 = 1 - y2 * tileUvH;
uvs.push(
new Vector22(x1, y1),
new Vector22(x2, y1),
new Vector22(x1, y2),
new Vector22(x2, y2)
);
}
const faces = ["left", "right", "top", "bottom", "front", "back"];
for (let i = 0; i < faces.length; i++) {
const uvs2 = src[faces[i]];
mapUV(uvs2[0], uvs2[1], uvs2[2], uvs2[3]);
}
const fArr = new Float32Array(uvs.length * 2);
for (let i = 0; i < uvs.length; i++) {
fArr[i * 2] = uvs[i].x;
fArr[i * 2 + 1] = uvs[i].y;
}
const attr = new BufferAttribute2(fArr, 2);
mesh.geometry.setAttribute("uv", attr);
}
var PlayerObject3D = class extends Object3D2 {
_slim = false;
constructor(skin, cape, transparent, slim) {
super();
this._slim = slim;
buildPlayerModel(this, skin, cape, transparent, slim);
}
get slim() {
return this._slim;
}
set slim(slim) {
if (slim !== this._slim) {
const template = slim ? player_model_default.alex : player_model_default.steve;
const leftArm = this.getObjectByName("leftArm");
const rightArm = this.getObjectByName("rightArm");
leftArm.geometry = new BoxGeometry2(template.leftArm.w, template.leftArm.h, template.leftArm.d);
mapCubeUV(leftArm, template.leftArm);
rightArm.geometry = new BoxGeometry2(template.rightArm.w, template.rightArm.h, template.rightArm.d);
mapCubeUV(rightArm, template.rightArm);
const leftArmLayer = this.getObjectByName("leftArmLayer");
const rightArmLayer = this.getObjectByName("rightArmLayer");
if (leftArmLayer) {
leftArmLayer.geometry = new BoxGeometry2(template.leftArm.layer.w, template.leftArm.layer.h, template.leftArm.layer.d);
mapCubeUV(leftArmLayer, template.leftArm.layer);
}
if (rightArmLayer) {
rightArmLayer.geometry = new BoxGeometry2(template.rightArm.layer.w, template.rightArm.layer.h, template.rightArm.layer.d);
mapCubeUV(rightArmLayer, template.rightArm.layer);
}
}
this._slim = slim;
}
};
function buildPlayerModel(root, skin, cape, transparent, slim) {
const template = slim ? player_model_default.alex : player_model_default.steve;
const partsNames = Object.keys(template);
for (const partName of partsNames) {
const model = template[partName];
const mesh = new Mesh2(
new BoxGeometry2(model.w, model.h, model.d),
partName === "cape" ? cape : skin
);
mesh.name = partName;
if (model.y) {
mesh.position.y = model.y;
}
if (model.x) {
mesh.position.x = model.x;
}
if (model.z) {
mesh.position.z = model.z;
}
if (partName === "cape") {
mesh.rotation.x = 25 * (Math.PI / 180);
}
mapCubeUV(mesh, model);
const box = new BoxHelper(mesh, new Color(16777215));
box.name = `${partName}Box`;
box.visible = false;
mesh.add(box);
if ("layer" in model) {
const layer = model.layer;
const layerMesh = new Mesh2(new BoxGeometry2(layer.w, layer.h, layer.d), transparent);
layerMesh.name = `${partName}Layer`;
if (layer.y) {
layerMesh.position.y = layer.y;
}
if (layer.x) {
layerMesh.position.x = layer.x;
}
if (layer.z) {
layerMesh.position.z = layer.z;
}
mapCubeUV(layerMesh, layer);
mesh.add(layerMesh);
}
root.add(mesh);
}
return root;
}
function ensureImage(textureSource) {
if (textureSource instanceof Image) {
return textureSource;
}
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = "anonymous";
img.onload = () => {
resolve(img);
};
img.onerror = (e, source, lineno, colno, error) => {
reject(error);
};
if (textureSource instanceof URL) {
img.src = textureSource.toString();
} else {
img.src = textureSource;
}
});
}
var PlayerModel = class {
static create() {
return new PlayerModel();
}
playerObject3d;
materialPlayer;
materialTransparent;
materialCape;
textureCape;
texturePlayer;
constructor() {
const canvas = document.createElement("canvas");
canvas.width = 64;
canvas.height = 64;
const texture = new CanvasTexture(canvas);
texture.magFilter = NearestFilter2;
texture.minFilter = NearestFilter2;
this.texturePlayer = texture;
texture.name = "skinTexture";
this.materialPlayer = new MeshBasicMaterial2({ map: texture });
this.materialTransparent = new MeshBasicMaterial2({
map: texture,
transparent: true,
depthWrite: false,
side: DoubleSide
});
const textureCape = new CanvasTexture(document.createElement("canvas"));
textureCape.magFilter = NearestFilter2;
textureCape.minFilter = NearestFilter2;
textureCape.name = "capeTexture";
this.textureCape = textureCape;
const materialCape = new MeshBasicMaterial2({
map: this.textureCape
});
materialCape.name = "capeMaterial";
materialCape.visible = false;
this.materialCape = materialCape;
this.playerObject3d = new PlayerObject3D(this.materialPlayer, this.materialCape, this.materialTransparent, false);
}
/**
* @param skin The skin texture source. Should be url string, URL object, or a Image HTML element
* @param isSlim Is this skin slim
*/
async setSkin(skin, isSlim = false) {
this.playerObject3d.slim = isSlim;
const texture = this.texturePlayer;
const i = await ensureImage(skin);
const legacy = i.width !== i.height;
const canvas = texture.image;
const context = canvas.getContext("2d");
canvas.width = i.width;
canvas.height = i.width;
context.clearRect(0, 0, i.width, i.width);
if (legacy) {
context.drawImage(i, 0, 0, i.width, i.width / 2);
convertLegacySkin(context, i.width);
} else {
context.drawImage(i, 0, 0, i.width, i.width);
}
texture.needsUpdate = true;
}
async setCape(cape) {
if (cape === void 0) {
this.materialCape.visible = false;
return;
}
this.materialCape.visible = true;
const img = await ensureImage(cape);
const texture = this.textureCape;
texture.image = img;
texture.needsUpdate = true;
}
// name(name) {
// if (name === undefined || name === "" || name === null) {
// if (this.nameTagObject === null) { return this; }
// this.root.remove(this.nameTagObject);
// this.nameTagObject = null;
// }
// if (this.nameTagObject) { this.clear(); }
// // build the texture
// const canvas = buildNameTag(name);
// const texture = new Texture(canvas);
// texture.needsUpdate = true;
// // build the sprite itself
// const material = new SpriteMaterial({
// map: texture,
// // useScreenCoordinates: false
// });
// const sprite = new Sprite(material);
// this.nameTagObject = sprite;
// sprite.position.y = 1.15;
// // add sprite to the character
// this.root.add(this.nameTagObject);
// return this;
// }
// load(option) {
// if (!option) { return this; }
// if (option.skin) { this.loadSkin(option.skin); }
// if (option.cape) { this.loadCape(option.skin); }
// return this;
// }
// say(text, expire = 4) {
// expire *= 1000;
// if (this.speakExpire) {
// clearTimeout(this.speakExpire);
// this.root.remove(this.speakBox);
// this.speakBox = null;
// this.speakExpire = null;
// }
// this.speakExpire = setTimeout(() => {
// this.root.remove(this.speakBox);
// this.speakBox = null;
// this.speakExpire = null;
// }, expire);
// // build the texture
// const canvas = buildChatBox(text);
// const texture = new Texture(canvas);
// texture.needsUpdate = true;
// // build the sprite itself
// const material = new SpriteMaterial({
// map: texture,
// // useScreenCoordinates: false
// });
// const sprite = new Sprite(material);
// this.speakBox = sprite;
// sprite.scale.multiplyScalar(4);
// sprite.position.y = 1.5;
// // add sprite to the character
// this.root.add(this.speakBox);
// return this;
// }
};
export {
BUILTIN_GENERATED,
BasicTextureManager,
BlockModelFactory,
BlockModelObject,
DEFAULT_DISPLAY,
DEFAULT_TRANSFORM,
PlayerModel,
PlayerObject3D
};
//# sourceMappingURL=index.mjs.map