diff --git a/.gitignore b/.gitignore index dc084eb..c6e90b0 100644 --- a/.gitignore +++ b/.gitignore @@ -62,4 +62,5 @@ _ignore/ package.json.lock -!js/build/ +!js/dist/ +.rpt2_cache diff --git a/dist/animation.d.ts b/dist/animation.d.ts new file mode 100644 index 0000000..f4cf943 --- /dev/null +++ b/dist/animation.d.ts @@ -0,0 +1,22 @@ +import { PlayerObject } from "./model"; +export interface IAnimation { + play(player: PlayerObject, time: number): void; +} +export declare type AnimationFn = (player: PlayerObject, time: number) => void; +export declare type Animation = AnimationFn | IAnimation; +export declare function invokeAnimation(animation: Animation, player: PlayerObject, time: number): void; +export interface AnimationHandle { + paused: boolean; + speed: number; + readonly animation: Animation; + reset(): void; + remove(): void; +} +export declare class CompositeAnimation implements IAnimation { + readonly handles: Set; + add(animation: Animation): AnimationHandle; + play(player: PlayerObject, time: number): void; +} +export declare const WalkingAnimation: Animation; +export declare const RunningAnimation: Animation; +export declare const RotatingAnimation: Animation; diff --git a/dist/model.d.ts b/dist/model.d.ts new file mode 100644 index 0000000..33d22c0 --- /dev/null +++ b/dist/model.d.ts @@ -0,0 +1,33 @@ +import * as THREE from "three"; +/** + * Notice that innerLayer and outerLayer may NOT be the direct children of the Group. + */ +export declare class BodyPart extends THREE.Group { + readonly innerLayer: THREE.Object3D; + readonly outerLayer: THREE.Object3D; + constructor(innerLayer: THREE.Object3D, outerLayer: THREE.Object3D); +} +export declare class SkinObject extends THREE.Group { + readonly head: BodyPart; + readonly body: BodyPart; + readonly rightArm: BodyPart; + readonly leftArm: BodyPart; + readonly rightLeg: BodyPart; + readonly leftLeg: BodyPart; + private modelListeners; + private _slim; + constructor(layer1Material: THREE.MeshBasicMaterial, layer2Material: THREE.MeshBasicMaterial); + slim: boolean; + private getBodyParts; + setInnerLayerVisible(value: boolean): void; + setOuterLayerVisible(value: boolean): void; +} +export declare class CapeObject extends THREE.Group { + readonly cape: THREE.Mesh; + constructor(capeMaterial: THREE.MeshBasicMaterial); +} +export declare class PlayerObject extends THREE.Group { + readonly skin: SkinObject; + readonly cape: CapeObject; + constructor(layer1Material: THREE.MeshBasicMaterial, layer2Material: THREE.MeshBasicMaterial, capeMaterial: THREE.MeshBasicMaterial); +} diff --git a/dist/orbit_controls.d.ts b/dist/orbit_controls.d.ts new file mode 100644 index 0000000..0c83f07 --- /dev/null +++ b/dist/orbit_controls.d.ts @@ -0,0 +1,123 @@ +import * as THREE from "three"; +import { SkinViewer } from "./viewer"; +export declare class OrbitControls extends THREE.EventDispatcher { + /** + * @preserve + * The code was originally from https://github.com/mrdoob/three.js/blob/d45a042cf962e9b1aa9441810ba118647b48aacb/examples/js/controls/OrbitControls.js + */ + /** + * @license + * Copyright (C) 2010-2017 three.js authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * @author qiao / https://github.com/qiao + * @author mrdoob / http://mrdoob.com + * @author alteredq / http://alteredqualia.com/ + * @author WestLangley / http://github.com/WestLangley + * @author erich666 / http://erichaines.com + */ + object: THREE.Camera; + domElement: HTMLElement | HTMLDocument; + window: Window; + enabled: boolean; + target: THREE.Vector3; + enableZoom: boolean; + zoomSpeed: number; + minDistance: number; + maxDistance: number; + enableRotate: boolean; + rotateSpeed: number; + enablePan: boolean; + keyPanSpeed: number; + autoRotate: boolean; + autoRotateSpeed: number; + minZoom: number; + maxZoom: number; + minPolarAngle: number; + maxPolarAngle: number; + minAzimuthAngle: number; + maxAzimuthAngle: number; + enableKeys: boolean; + keys: { + LEFT: number; + UP: number; + RIGHT: number; + BOTTOM: number; + }; + mouseButtons: { + ORBIT: THREE.MOUSE; + ZOOM: THREE.MOUSE; + PAN: THREE.MOUSE; + }; + enableDamping: boolean; + dampingFactor: number; + private spherical; + private sphericalDelta; + private scale; + private target0; + private position0; + private zoom0; + private state; + private panOffset; + private zoomChanged; + private rotateStart; + private rotateEnd; + private rotateDelta; + private panStart; + private panEnd; + private panDelta; + private dollyStart; + private dollyEnd; + private dollyDelta; + private updateLastPosition; + private updateOffset; + private updateQuat; + private updateLastQuaternion; + private updateQuatInverse; + private panLeftV; + private panUpV; + private panInternalOffset; + private onContextMenu; + private onMouseUp; + private onMouseDown; + private onMouseMove; + private onMouseWheel; + private onTouchStart; + private onTouchEnd; + private onTouchMove; + private onKeyDown; + constructor(object: THREE.Camera, domElement?: HTMLElement, domWindow?: Window); + update(): boolean; + panLeft(distance: number, objectMatrix: any): void; + panUp(distance: number, objectMatrix: any): void; + pan(deltaX: number, deltaY: number): void; + dollyIn(dollyScale: any): void; + dollyOut(dollyScale: any): void; + getAutoRotationAngle(): number; + getZoomScale(): number; + rotateLeft(angle: number): void; + rotateUp(angle: number): void; + getPolarAngle(): number; + getAzimuthalAngle(): number; + dispose(): void; + reset(): void; +} +export declare function createOrbitControls(skinViewer: SkinViewer): OrbitControls; diff --git a/dist/skinview3d.d.ts b/dist/skinview3d.d.ts new file mode 100644 index 0000000..bcad6e7 --- /dev/null +++ b/dist/skinview3d.d.ts @@ -0,0 +1,5 @@ +export { SkinObject, BodyPart, CapeObject, PlayerObject } from "./model"; +export { SkinViewer, SkinViewerOptions } from "./viewer"; +export { OrbitControls, createOrbitControls } from "./orbit_controls"; +export { IAnimation, AnimationFn, Animation, invokeAnimation, AnimationHandle, CompositeAnimation, WalkingAnimation, RunningAnimation, RotatingAnimation } from "./animation"; +export { isSlimSkin } from "./utils"; diff --git a/dist/skinview3d.js b/dist/skinview3d.js new file mode 100644 index 0000000..a114eef --- /dev/null +++ b/dist/skinview3d.js @@ -0,0 +1,1234 @@ +/** + * skinview3d (https://github.com/bs-community/skinview3d) + * + * MIT License + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('three')) : + typeof define === 'function' && define.amd ? define(['exports', 'three'], factory) : + (factory((global.skinview3d = {}),global.THREE)); +}(this, (function (exports,THREE) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + function toFaceVertices(x1, y1, x2, y2, w, h) { + return [ + new THREE.Vector2(x1 / w, 1.0 - y2 / h), + new THREE.Vector2(x2 / w, 1.0 - y2 / h), + new THREE.Vector2(x2 / w, 1.0 - y1 / h), + new THREE.Vector2(x1 / w, 1.0 - y1 / h) + ]; + } + function toSkinVertices(x1, y1, x2, y2) { + return toFaceVertices(x1, y1, x2, y2, 64.0, 64.0); + } + function toCapeVertices(x1, y1, x2, y2) { + return toFaceVertices(x1, y1, x2, y2, 64.0, 32.0); + } + function setVertices(box, top, bottom, left, front, right, back) { + box.faceVertexUvs[0] = []; + box.faceVertexUvs[0][0] = [right[3], right[0], right[2]]; + box.faceVertexUvs[0][1] = [right[0], right[1], right[2]]; + box.faceVertexUvs[0][2] = [left[3], left[0], left[2]]; + box.faceVertexUvs[0][3] = [left[0], left[1], left[2]]; + box.faceVertexUvs[0][4] = [top[3], top[0], top[2]]; + box.faceVertexUvs[0][5] = [top[0], top[1], top[2]]; + box.faceVertexUvs[0][6] = [bottom[0], bottom[3], bottom[1]]; + box.faceVertexUvs[0][7] = [bottom[3], bottom[2], bottom[1]]; + box.faceVertexUvs[0][8] = [front[3], front[0], front[2]]; + box.faceVertexUvs[0][9] = [front[0], front[1], front[2]]; + box.faceVertexUvs[0][10] = [back[3], back[0], back[2]]; + box.faceVertexUvs[0][11] = [back[0], back[1], back[2]]; + } + var esp = 0.002; + /** + * Notice that innerLayer and outerLayer may NOT be the direct children of the Group. + */ + var BodyPart = /** @class */ (function (_super) { + __extends(BodyPart, _super); + function BodyPart(innerLayer, outerLayer) { + var _this = _super.call(this) || this; + _this.innerLayer = innerLayer; + _this.outerLayer = outerLayer; + return _this; + } + return BodyPart; + }(THREE.Group)); + var SkinObject = /** @class */ (function (_super) { + __extends(SkinObject, _super); + function SkinObject(layer1Material, layer2Material) { + var _this = _super.call(this) || this; + _this.modelListeners = []; // called when model(slim property) is changed + _this._slim = false; + // Head + var headBox = new THREE.BoxGeometry(8, 8, 8, 0, 0, 0); + setVertices(headBox, toSkinVertices(8, 0, 16, 8), toSkinVertices(16, 0, 24, 8), toSkinVertices(0, 8, 8, 16), toSkinVertices(8, 8, 16, 16), toSkinVertices(16, 8, 24, 16), toSkinVertices(24, 8, 32, 16)); + var headMesh = new THREE.Mesh(headBox, layer1Material); + var head2Box = new THREE.BoxGeometry(9, 9, 9, 0, 0, 0); + setVertices(head2Box, toSkinVertices(40, 0, 48, 8), toSkinVertices(48, 0, 56, 8), toSkinVertices(32, 8, 40, 16), toSkinVertices(40, 8, 48, 16), toSkinVertices(48, 8, 56, 16), toSkinVertices(56, 8, 64, 16)); + var head2Mesh = new THREE.Mesh(head2Box, layer2Material); + head2Mesh.renderOrder = -1; + _this.head = new BodyPart(headMesh, head2Mesh); + _this.head.add(headMesh, head2Mesh); + _this.add(_this.head); + // Body + var bodyBox = new THREE.BoxGeometry(8, 12, 4, 0, 0, 0); + setVertices(bodyBox, toSkinVertices(20, 16, 28, 20), toSkinVertices(28, 16, 36, 20), toSkinVertices(16, 20, 20, 32), toSkinVertices(20, 20, 28, 32), toSkinVertices(28, 20, 32, 32), toSkinVertices(32, 20, 40, 32)); + var bodyMesh = new THREE.Mesh(bodyBox, layer1Material); + var body2Box = new THREE.BoxGeometry(9, 13.5, 4.5, 0, 0, 0); + setVertices(body2Box, toSkinVertices(20, 32, 28, 36), toSkinVertices(28, 32, 36, 36), toSkinVertices(16, 36, 20, 48), toSkinVertices(20, 36, 28, 48), toSkinVertices(28, 36, 32, 48), toSkinVertices(32, 36, 40, 48)); + var body2Mesh = new THREE.Mesh(body2Box, layer2Material); + _this.body = new BodyPart(bodyMesh, body2Mesh); + _this.body.add(bodyMesh, body2Mesh); + _this.body.position.y = -10; + _this.add(_this.body); + // Right Arm + var rightArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related + var rightArmMesh = new THREE.Mesh(rightArmBox, layer1Material); + _this.modelListeners.push(function () { + rightArmMesh.scale.x = (_this.slim ? 3 : 4) - esp; + rightArmMesh.scale.y = 12 - esp; + rightArmMesh.scale.z = 4 - esp; + if (_this.slim) { + setVertices(rightArmBox, toSkinVertices(44, 16, 47, 20), toSkinVertices(47, 16, 50, 20), toSkinVertices(40, 20, 44, 32), toSkinVertices(44, 20, 47, 32), toSkinVertices(47, 20, 51, 32), toSkinVertices(51, 20, 54, 32)); + } + else { + setVertices(rightArmBox, toSkinVertices(44, 16, 48, 20), toSkinVertices(48, 16, 52, 20), toSkinVertices(40, 20, 44, 32), toSkinVertices(44, 20, 48, 32), toSkinVertices(48, 20, 52, 32), toSkinVertices(52, 20, 56, 32)); + } + rightArmBox.uvsNeedUpdate = true; + rightArmBox.elementsNeedUpdate = true; + }); + var rightArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related + var rightArm2Mesh = new THREE.Mesh(rightArm2Box, layer2Material); + rightArm2Mesh.renderOrder = 1; + _this.modelListeners.push(function () { + rightArm2Mesh.scale.x = (_this.slim ? 3.375 : 4.5) - esp; + rightArm2Mesh.scale.y = 13.5 - esp; + rightArm2Mesh.scale.z = 4.5 - esp; + if (_this.slim) { + setVertices(rightArm2Box, toSkinVertices(44, 32, 47, 36), toSkinVertices(47, 32, 50, 36), toSkinVertices(40, 36, 44, 48), toSkinVertices(44, 36, 47, 48), toSkinVertices(47, 36, 51, 48), toSkinVertices(51, 36, 54, 48)); + } + else { + setVertices(rightArm2Box, toSkinVertices(44, 32, 48, 36), toSkinVertices(48, 32, 52, 36), toSkinVertices(40, 36, 44, 48), toSkinVertices(44, 36, 48, 48), toSkinVertices(48, 36, 52, 48), toSkinVertices(52, 36, 56, 48)); + } + rightArm2Box.uvsNeedUpdate = true; + rightArm2Box.elementsNeedUpdate = true; + }); + var rightArmPivot = new THREE.Group(); + rightArmPivot.add(rightArmMesh, rightArm2Mesh); + rightArmPivot.position.y = -6; + _this.rightArm = new BodyPart(rightArmMesh, rightArm2Mesh); + _this.rightArm.add(rightArmPivot); + _this.rightArm.position.y = -4; + _this.modelListeners.push(function () { + _this.rightArm.position.x = _this.slim ? -5.5 : -6; + }); + _this.add(_this.rightArm); + // Left Arm + var leftArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related + var leftArmMesh = new THREE.Mesh(leftArmBox, layer1Material); + _this.modelListeners.push(function () { + leftArmMesh.scale.x = (_this.slim ? 3 : 4) - esp; + leftArmMesh.scale.y = 12 - esp; + leftArmMesh.scale.z = 4 - esp; + if (_this.slim) { + setVertices(leftArmBox, toSkinVertices(36, 48, 39, 52), toSkinVertices(39, 48, 42, 52), toSkinVertices(32, 52, 36, 64), toSkinVertices(36, 52, 39, 64), toSkinVertices(39, 52, 43, 64), toSkinVertices(43, 52, 46, 64)); + } + else { + setVertices(leftArmBox, toSkinVertices(36, 48, 40, 52), toSkinVertices(40, 48, 44, 52), toSkinVertices(32, 52, 36, 64), toSkinVertices(36, 52, 40, 64), toSkinVertices(40, 52, 44, 64), toSkinVertices(44, 52, 48, 64)); + } + leftArmBox.uvsNeedUpdate = true; + leftArmBox.elementsNeedUpdate = true; + }); + var leftArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related + var leftArm2Mesh = new THREE.Mesh(leftArm2Box, layer2Material); + leftArm2Mesh.renderOrder = 1; + _this.modelListeners.push(function () { + leftArm2Mesh.scale.x = (_this.slim ? 3.375 : 4.5) - esp; + leftArm2Mesh.scale.y = 13.5 - esp; + leftArm2Mesh.scale.z = 4.5 - esp; + if (_this.slim) { + setVertices(leftArm2Box, toSkinVertices(52, 48, 55, 52), toSkinVertices(55, 48, 58, 52), toSkinVertices(48, 52, 52, 64), toSkinVertices(52, 52, 55, 64), toSkinVertices(55, 52, 59, 64), toSkinVertices(59, 52, 62, 64)); + } + else { + setVertices(leftArm2Box, toSkinVertices(52, 48, 56, 52), toSkinVertices(56, 48, 60, 52), toSkinVertices(48, 52, 52, 64), toSkinVertices(52, 52, 56, 64), toSkinVertices(56, 52, 60, 64), toSkinVertices(60, 52, 64, 64)); + } + leftArm2Box.uvsNeedUpdate = true; + leftArm2Box.elementsNeedUpdate = true; + }); + var leftArmPivot = new THREE.Group(); + leftArmPivot.add(leftArmMesh, leftArm2Mesh); + leftArmPivot.position.y = -6; + _this.leftArm = new BodyPart(leftArmMesh, leftArm2Mesh); + _this.leftArm.add(leftArmPivot); + _this.leftArm.position.y = -4; + _this.modelListeners.push(function () { + _this.leftArm.position.x = _this.slim ? 5.5 : 6; + }); + _this.add(_this.leftArm); + // Right Leg + var rightLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0); + setVertices(rightLegBox, toSkinVertices(4, 16, 8, 20), toSkinVertices(8, 16, 12, 20), toSkinVertices(0, 20, 4, 32), toSkinVertices(4, 20, 8, 32), toSkinVertices(8, 20, 12, 32), toSkinVertices(12, 20, 16, 32)); + var rightLegMesh = new THREE.Mesh(rightLegBox, layer1Material); + var rightLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0); + setVertices(rightLeg2Box, toSkinVertices(4, 32, 8, 36), toSkinVertices(8, 32, 12, 36), toSkinVertices(0, 36, 4, 48), toSkinVertices(4, 36, 8, 48), toSkinVertices(8, 36, 12, 48), toSkinVertices(12, 36, 16, 48)); + var rightLeg2Mesh = new THREE.Mesh(rightLeg2Box, layer2Material); + rightLeg2Mesh.renderOrder = 1; + var rightLegPivot = new THREE.Group(); + rightLegPivot.add(rightLegMesh, rightLeg2Mesh); + rightLegPivot.position.y = -6; + _this.rightLeg = new BodyPart(rightLegMesh, rightLeg2Mesh); + _this.rightLeg.add(rightLegPivot); + _this.rightLeg.position.y = -16; + _this.rightLeg.position.x = -2; + _this.add(_this.rightLeg); + // Left Leg + var leftLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0); + setVertices(leftLegBox, toSkinVertices(20, 48, 24, 52), toSkinVertices(24, 48, 28, 52), toSkinVertices(16, 52, 20, 64), toSkinVertices(20, 52, 24, 64), toSkinVertices(24, 52, 28, 64), toSkinVertices(28, 52, 32, 64)); + var leftLegMesh = new THREE.Mesh(leftLegBox, layer1Material); + var leftLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0); + setVertices(leftLeg2Box, toSkinVertices(4, 48, 8, 52), toSkinVertices(8, 48, 12, 52), toSkinVertices(0, 52, 4, 64), toSkinVertices(4, 52, 8, 64), toSkinVertices(8, 52, 12, 64), toSkinVertices(12, 52, 16, 64)); + var leftLeg2Mesh = new THREE.Mesh(leftLeg2Box, layer2Material); + leftLeg2Mesh.renderOrder = 1; + var leftLegPivot = new THREE.Group(); + leftLegPivot.add(leftLegMesh, leftLeg2Mesh); + leftLegPivot.position.y = -6; + _this.leftLeg = new BodyPart(leftLegMesh, leftLeg2Mesh); + _this.leftLeg.add(leftLegPivot); + _this.leftLeg.position.y = -16; + _this.leftLeg.position.x = 2; + _this.add(_this.leftLeg); + _this.slim = false; + return _this; + } + Object.defineProperty(SkinObject.prototype, "slim", { + get: function () { + return this._slim; + }, + set: function (value) { + this._slim = value; + this.modelListeners.forEach(function (listener) { return listener(); }); + }, + enumerable: true, + configurable: true + }); + SkinObject.prototype.getBodyParts = function () { + return this.children.filter(function (it) { return it instanceof BodyPart; }); + }; + SkinObject.prototype.setInnerLayerVisible = function (value) { + this.getBodyParts().forEach(function (part) { return part.innerLayer.visible = value; }); + }; + SkinObject.prototype.setOuterLayerVisible = function (value) { + this.getBodyParts().forEach(function (part) { return part.outerLayer.visible = value; }); + }; + return SkinObject; + }(THREE.Group)); + var CapeObject = /** @class */ (function (_super) { + __extends(CapeObject, _super); + function CapeObject(capeMaterial) { + var _this = _super.call(this) || this; + // back = outside + // front = inside + var capeBox = new THREE.BoxGeometry(10, 16, 1, 0, 0, 0); + setVertices(capeBox, toCapeVertices(1, 0, 11, 1), toCapeVertices(11, 0, 21, 1), toCapeVertices(11, 1, 12, 17), toCapeVertices(12, 1, 22, 17), toCapeVertices(0, 1, 1, 17), toCapeVertices(1, 1, 11, 17)); + _this.cape = new THREE.Mesh(capeBox, capeMaterial); + _this.cape.position.y = -8; + _this.cape.position.z = -0.5; + _this.add(_this.cape); + return _this; + } + return CapeObject; + }(THREE.Group)); + var PlayerObject = /** @class */ (function (_super) { + __extends(PlayerObject, _super); + function PlayerObject(layer1Material, layer2Material, capeMaterial) { + var _this = _super.call(this) || this; + _this.skin = new SkinObject(layer1Material, layer2Material); + _this.skin.visible = false; + _this.add(_this.skin); + _this.cape = new CapeObject(capeMaterial); + _this.cape.position.z = -2; + _this.cape.position.y = -4; + _this.cape.rotation.x = 25 * Math.PI / 180; + _this.cape.visible = false; + _this.add(_this.cape); + return _this; + } + return PlayerObject; + }(THREE.Group)); + + function invokeAnimation(animation, player, time) { + if (animation instanceof Function) { + animation(player, time); + } + else { + // must be IAnimation here + animation.play(player, time); + } + } + var AnimationWrapper = /** @class */ (function () { + function AnimationWrapper(animation) { + this.paused = false; + this.speed = 1.0; + this._paused = false; + this._lastChange = null; + this._speed = 1.0; + this._lastChangeX = null; + this.animation = animation; + } + AnimationWrapper.prototype.play = function (player, time) { + if (this._lastChange === null) { + this._lastChange = time; + this._lastChangeX = 0; + } + else if (this.paused !== this._paused || this.speed !== this._speed) { + var dt = time - this._lastChange; + if (this._paused === false) { + this._lastChangeX += dt * this._speed; + } + this._paused = this.paused; + this._speed = this.speed; + this._lastChange = time; + } + if (this.paused === false) { + var dt = time - this._lastChange; + var x = this._lastChangeX + this.speed * dt; + invokeAnimation(this.animation, player, x); + } + }; + AnimationWrapper.prototype.reset = function () { + this._lastChange = null; + }; + AnimationWrapper.prototype.remove = function () { + // stub get's overriden + }; + return AnimationWrapper; + }()); + var CompositeAnimation = /** @class */ (function () { + function CompositeAnimation() { + this.handles = new Set(); + } + CompositeAnimation.prototype.add = function (animation) { + var _this = this; + var handle = new AnimationWrapper(animation); + handle.remove = function () { return _this.handles.delete(handle); }; + this.handles.add(handle); + return handle; + }; + CompositeAnimation.prototype.play = function (player, time) { + this.handles.forEach(function (handle) { return handle.play(player, time); }); + }; + return CompositeAnimation; + }()); + var WalkingAnimation = function (player, time) { + var skin = player.skin; + // Multiply by animation's natural speed + time *= 8; + // Leg swing + skin.leftLeg.rotation.x = Math.sin(time) * 0.5; + skin.rightLeg.rotation.x = Math.sin(time + Math.PI) * 0.5; + // Arm swing + skin.leftArm.rotation.x = Math.sin(time + Math.PI) * 0.5; + skin.rightArm.rotation.x = Math.sin(time) * 0.5; + var basicArmRotationZ = Math.PI * 0.02; + skin.leftArm.rotation.z = Math.cos(time) * 0.03 + basicArmRotationZ; + skin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.03 - basicArmRotationZ; + // Head shaking with different frequency & amplitude + skin.head.rotation.y = Math.sin(time / 4) * 0.2; + skin.head.rotation.x = Math.sin(time / 5) * 0.1; + // Always add an angle for cape around the x axis + var basicCapeRotationX = Math.PI * 0.06; + player.cape.rotation.x = Math.sin(time / 1.5) * 0.06 + basicCapeRotationX; + }; + var RunningAnimation = function (player, time) { + var skin = player.skin; + time *= 15; + // Leg swing with larger amplitude + skin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3; + skin.rightLeg.rotation.x = Math.cos(time) * 1.3; + // Arm swing + skin.leftArm.rotation.x = Math.cos(time) * 1.5; + skin.rightArm.rotation.x = Math.cos(time + Math.PI) * 1.5; + var basicArmRotationZ = Math.PI * 0.1; + skin.leftArm.rotation.z = Math.cos(time) * 0.1 + basicArmRotationZ; + skin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.1 - basicArmRotationZ; + // Jumping + player.position.y = Math.cos(time * 2); + // Dodging when running + player.position.x = Math.cos(time) * 0.15; + // Slightly tilting when running + player.rotation.z = Math.cos(time + Math.PI) * 0.01; + // Apply higher swing frequency, lower amplitude, + // and greater basic rotation around x axis, + // to cape when running. + var basicCapeRotationX = Math.PI * 0.3; + player.cape.rotation.x = Math.sin(time * 2) * 0.1 + basicCapeRotationX; + // What about head shaking? + // You shouldn't glance right and left when running dude :P + }; + var RotatingAnimation = function (player, time) { + player.rotation.y = time; + }; + + function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) { + var imgData = context.getImageData(sX, sY, w, h); + if (flipHorizontal) { + for (var y = 0; y < h; y++) { + for (var x = 0; x < (w / 2); x++) { + var index = (x + y * w) * 4; + var index2 = ((w - x - 1) + y * w) * 4; + var pA1 = imgData.data[index]; + var pA2 = imgData.data[index + 1]; + var pA3 = imgData.data[index + 2]; + var pA4 = imgData.data[index + 3]; + var pB1 = imgData.data[index2]; + var pB2 = imgData.data[index2 + 1]; + var pB3 = imgData.data[index2 + 2]; + var 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; + } + } + } + context.putImageData(imgData, dX, dY); + } + function hasTransparency(context, x0, y0, w, h) { + var imgData = context.getImageData(x0, y0, w, h); + for (var x = 0; x < w; x++) { + for (var y = 0; y < h; y++) { + var offset = (x + y * w) * 4; + if (imgData.data[offset + 3] !== 0xff) { + return true; + } + } + } + return false; + } + function computeSkinScale(width) { + return width / 64.0; + } + function fixOpaqueSkin(context, width) { + // Some ancient skins don't have transparent pixels (nor have helm). + // We have to make the helm area transparent, otherwise it will be rendered as black. + if (!hasTransparency(context, 0, 0, width, width / 2)) { + var scale_1 = computeSkinScale(width); + var clearArea = function (x, y, w, h) { return context.clearRect(x * scale_1, y * scale_1, w * scale_1, h * scale_1); }; + clearArea(40, 0, 8, 8); // Helm Top + clearArea(48, 0, 8, 8); // Helm Bottom + clearArea(32, 8, 8, 8); // Helm Right + clearArea(40, 8, 8, 8); // Helm Front + clearArea(48, 8, 8, 8); // Helm Left + clearArea(56, 8, 8, 8); // Helm Back + } + } + function convertSkinTo1_8(context, width) { + var scale = computeSkinScale(width); + var copySkin = function (sX, sY, w, h, dX, dY, flipHorizontal) { return copyImage(context, sX * scale, sY * scale, w * scale, h * scale, dX * scale, dY * scale, flipHorizontal); }; + fixOpaqueSkin(context, width); + copySkin(4, 16, 4, 4, 20, 48, true); // Top Leg + copySkin(8, 16, 4, 4, 24, 48, true); // Bottom Leg + copySkin(0, 20, 4, 12, 24, 52, true); // Outer Leg + copySkin(4, 20, 4, 12, 20, 52, true); // Front Leg + copySkin(8, 20, 4, 12, 16, 52, true); // Inner Leg + copySkin(12, 20, 4, 12, 28, 52, true); // Back Leg + copySkin(44, 16, 4, 4, 36, 48, true); // Top Arm + copySkin(48, 16, 4, 4, 40, 48, true); // Bottom Arm + copySkin(40, 20, 4, 12, 40, 52, true); // Outer Arm + copySkin(44, 20, 4, 12, 36, 52, true); // Front Arm + copySkin(48, 20, 4, 12, 32, 52, true); // Inner Arm + copySkin(52, 20, 4, 12, 44, 52, true); // Back Arm + } + function loadSkinToCanvas(canvas, image) { + var isOldFormat = false; + if (image.width !== image.height) { + if (image.width === 2 * image.height) { + isOldFormat = true; + } + else { + throw new Error("Bad skin size: " + image.width + "x" + image.height); + } + } + var context = canvas.getContext("2d"); + if (isOldFormat) { + var sideLength = image.width; + canvas.width = sideLength; + canvas.height = sideLength; + context.clearRect(0, 0, sideLength, sideLength); + context.drawImage(image, 0, 0, sideLength, sideLength / 2.0); + convertSkinTo1_8(context, sideLength); + } + else { + canvas.width = image.width; + canvas.height = image.height; + context.clearRect(0, 0, image.width, image.height); + context.drawImage(image, 0, 0, canvas.width, canvas.height); + } + } + function loadCapeToCanvas(canvas, image) { + var isOldFormat = false; + if (image.width !== 2 * image.height) { + if (image.width * 17 === image.height * 22) { + // width/height = 22/17 + isOldFormat = true; + } + else { + throw new Error("Bad cape size: " + image.width + "x" + image.height); + } + } + var context = canvas.getContext("2d"); + if (isOldFormat) { + var width = image.width * 64 / 22; + canvas.width = width; + canvas.height = width / 2; + } + else { + canvas.width = image.width; + canvas.height = image.height; + } + context.clearRect(0, 0, canvas.width, canvas.height); + context.drawImage(image, 0, 0, image.width, image.height); + } + function isSlimSkin(canvasOrImage) { + // Detects whether the skin is default or slim. + // + // The right arm area of *default* skins: + // (44,16)->*-------*-------* + // (40,20) |top |bottom | + // \|/ |4x4 |4x4 | + // *-------*-------*-------*-------* + // |right |front |left |back | + // |4x12 |4x12 |4x12 |4x12 | + // *-------*-------*-------*-------* + // The right arm area of *slim* skins: + // (44,16)->*------*------*-* + // (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4] + // \|/ |3x4 |3x4 | | + // *-------*------*------***-----*-* + // |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12] + // |4x12 |3x12 |4x12 |3x12 | | + // *-------*------*-------*------*-* + // Compared with default right arms, slim right arms have 2 unused areas. + // + // The same is true for left arm: + // The left arm area of *default* skins: + // (36,48)->*-------*-------* + // (32,52) |top |bottom | + // \|/ |4x4 |4x4 | + // *-------*-------*-------*-------* + // |right |front |left |back | + // |4x12 |4x12 |4x12 |4x12 | + // *-------*-------*-------*-------* + // The left arm area of *slim* skins: + // (36,48)->*------*------*-* + // (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4] + // \|/ |3x4 |3x4 | | + // *-------*------*------***-----*-* + // |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12] + // |4x12 |3x12 |4x12 |3x12 | | + // *-------*------*-------*------*-* + // + // If there is a transparent pixel in any of the 4 unused areas, the skin must be slim, + // as transparent pixels are not allowed in the first layer. + if (canvasOrImage instanceof HTMLCanvasElement) { + var canvas = canvasOrImage; + var scale_2 = computeSkinScale(canvas.width); + var context_1 = canvas.getContext("2d"); + var checkArea = function (x, y, w, h) { return hasTransparency(context_1, x * scale_2, y * scale_2, w * scale_2, h * scale_2); }; + return checkArea(50, 16, 2, 4) || + checkArea(54, 20, 2, 12) || + checkArea(42, 48, 2, 4) || + checkArea(46, 52, 2, 12); + } + else { + var image = canvasOrImage; + var canvas = document.createElement("canvas"); + loadSkinToCanvas(canvas, image); + return isSlimSkin(canvas); + } + } + + var SkinViewer = /** @class */ (function () { + function SkinViewer(options) { + var _this = this; + this.detectModel = true; + this.animationPaused = false; + this.animationTime = 0; + this.disposed = false; + this.domElement = options.domElement; + this.animation = options.animation || null; + if (options.detectModel === false) { + this.detectModel = false; + } + // texture + this.skinImg = new Image(); + this.skinCanvas = document.createElement("canvas"); + this.skinTexture = new THREE.Texture(this.skinCanvas); + this.skinTexture.magFilter = THREE.NearestFilter; + this.skinTexture.minFilter = THREE.NearestFilter; + this.capeImg = new Image(); + this.capeCanvas = document.createElement("canvas"); + this.capeTexture = new THREE.Texture(this.capeCanvas); + this.capeTexture.magFilter = THREE.NearestFilter; + this.capeTexture.minFilter = THREE.NearestFilter; + this.layer1Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, side: THREE.FrontSide }); + this.layer2Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 }); + this.capeMaterial = new THREE.MeshBasicMaterial({ map: this.capeTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 }); + // scene + this.scene = new THREE.Scene(); + // Use smaller fov to avoid distortion + this.camera = new THREE.PerspectiveCamera(40); + this.camera.position.y = -12; + this.camera.position.z = 60; + this.renderer = new THREE.WebGLRenderer({ alpha: true, antialias: false }); + this.renderer.setSize(300, 300); // default size + this.renderer.context.getShaderInfoLog = function () { return ""; }; // shut firefox up + this.domElement.appendChild(this.renderer.domElement); + this.playerObject = new PlayerObject(this.layer1Material, this.layer2Material, this.capeMaterial); + this.scene.add(this.playerObject); + // texture loading + this.skinImg.crossOrigin = "anonymous"; + this.skinImg.onerror = function () { return console.error("Failed loading " + _this.skinImg.src); }; + this.skinImg.onload = function () { + loadSkinToCanvas(_this.skinCanvas, _this.skinImg); + if (_this.detectModel) { + _this.playerObject.skin.slim = isSlimSkin(_this.skinCanvas); + } + _this.skinTexture.needsUpdate = true; + _this.layer1Material.needsUpdate = true; + _this.layer2Material.needsUpdate = true; + _this.playerObject.skin.visible = true; + }; + this.capeImg.crossOrigin = "anonymous"; + this.capeImg.onerror = function () { return console.error("Failed loading " + _this.capeImg.src); }; + this.capeImg.onload = function () { + loadCapeToCanvas(_this.capeCanvas, _this.capeImg); + _this.capeTexture.needsUpdate = true; + _this.capeMaterial.needsUpdate = true; + _this.playerObject.cape.visible = true; + }; + if (options.skinUrl) + this.skinUrl = options.skinUrl; + if (options.capeUrl) + this.capeUrl = options.capeUrl; + if (options.width) + this.width = options.width; + if (options.height) + this.height = options.height; + var draw = function () { + if (_this.disposed) + return; + window.requestAnimationFrame(draw); + if (!_this.animationPaused) { + _this.animationTime++; + if (_this.animation) { + invokeAnimation(_this.animation, _this.playerObject, _this.animationTime / 100.0); + } + } + _this.renderer.render(_this.scene, _this.camera); + }; + draw(); + } + SkinViewer.prototype.setSize = function (width, height) { + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + }; + SkinViewer.prototype.dispose = function () { + this.disposed = true; + this.domElement.removeChild(this.renderer.domElement); + this.renderer.dispose(); + this.skinTexture.dispose(); + this.capeTexture.dispose(); + }; + Object.defineProperty(SkinViewer.prototype, "skinUrl", { + get: function () { + return this.skinImg.src; + }, + set: function (url) { + this.skinImg.src = url; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "capeUrl", { + get: function () { + return this.capeImg.src; + }, + set: function (url) { + this.capeImg.src = url; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "width", { + get: function () { + return this.renderer.getSize().width; + }, + set: function (newWidth) { + this.setSize(newWidth, this.height); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "height", { + get: function () { + return this.renderer.getSize().height; + }, + set: function (newHeight) { + this.setSize(this.width, newHeight); + }, + enumerable: true, + configurable: true + }); + return SkinViewer; + }()); + + var STATE = { + NONE: -1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_DOLLY: 4, + TOUCH_PAN: 5 + }; + var CHANGE_EVENT = { type: "change" }; + var START_EVENT = { type: "start" }; + var END_EVENT = { type: "end" }; + var EPS = 0.000001; + var OrbitControls = /** @class */ (function (_super) { + __extends(OrbitControls, _super); + function OrbitControls(object, domElement, domWindow) { + var _this = _super.call(this) || this; + _this.object = object; + _this.domElement = (domElement !== undefined) ? domElement : document; + _this.window = (domWindow !== undefined) ? domWindow : window; + // Set to false to disable this control + _this.enabled = true; + // "target" sets the location of focus, where the object orbits around + _this.target = new THREE.Vector3(); + // How far you can dolly in and out ( PerspectiveCamera only ) + _this.minDistance = 0; + _this.maxDistance = Infinity; + // How far you can zoom in and out ( OrthographicCamera only ) + _this.minZoom = 0; + _this.maxZoom = Infinity; + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + _this.minPolarAngle = 0; // radians + _this.maxPolarAngle = Math.PI; // radians + // How far you can orbit horizontally, upper and lower limits. + // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. + _this.minAzimuthAngle = -Infinity; // radians + _this.maxAzimuthAngle = Infinity; // radians + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + _this.enableDamping = false; + _this.dampingFactor = 0.25; + // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. + // Set to false to disable zooming + _this.enableZoom = true; + _this.zoomSpeed = 1.0; + // Set to false to disable rotating + _this.enableRotate = true; + _this.rotateSpeed = 1.0; + // Set to false to disable panning + _this.enablePan = true; + _this.keyPanSpeed = 7.0; // pixels moved per arrow key push + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + _this.autoRotate = false; + _this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + // Set to false to disable use of the keys + _this.enableKeys = true; + // The four arrow keys + _this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; + // Mouse buttons + _this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT }; + // for reset + _this.target0 = _this.target.clone(); + _this.position0 = _this.object.position.clone(); + _this.zoom0 = _this.object.zoom; + // for update speedup + _this.updateOffset = new THREE.Vector3(); + // so camera.up is the orbit axis + _this.updateQuat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0)); + _this.updateQuatInverse = _this.updateQuat.clone().inverse(); + _this.updateLastPosition = new THREE.Vector3(); + _this.updateLastQuaternion = new THREE.Quaternion(); + _this.state = STATE.NONE; + _this.scale = 1; + // current position in spherical coordinates + _this.spherical = new THREE.Spherical(); + _this.sphericalDelta = new THREE.Spherical(); + _this.panOffset = new THREE.Vector3(); + _this.zoomChanged = false; + _this.rotateStart = new THREE.Vector2(); + _this.rotateEnd = new THREE.Vector2(); + _this.rotateDelta = new THREE.Vector2(); + _this.panStart = new THREE.Vector2(); + _this.panEnd = new THREE.Vector2(); + _this.panDelta = new THREE.Vector2(); + _this.dollyStart = new THREE.Vector2(); + _this.dollyEnd = new THREE.Vector2(); + _this.dollyDelta = new THREE.Vector2(); + _this.panLeftV = new THREE.Vector3(); + _this.panUpV = new THREE.Vector3(); + _this.panInternalOffset = new THREE.Vector3(); + // event handlers - FSM: listen for events and reset state + _this.onMouseDown = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + if (event.button === _this.mouseButtons.ORBIT) { + if (_this.enableRotate === false) + return; + _this.rotateStart.set(event.clientX, event.clientY); + _this.state = STATE.ROTATE; + } + else if (event.button === _this.mouseButtons.ZOOM) { + if (_this.enableZoom === false) + return; + _this.dollyStart.set(event.clientX, event.clientY); + _this.state = STATE.DOLLY; + } + else if (event.button === _this.mouseButtons.PAN) { + if (_this.enablePan === false) + return; + _this.panStart.set(event.clientX, event.clientY); + _this.state = STATE.PAN; + } + if (_this.state !== STATE.NONE) { + document.addEventListener("mousemove", _this.onMouseMove, false); + document.addEventListener("mouseup", _this.onMouseUp, false); + _this.dispatchEvent(START_EVENT); + } + }; + _this.onMouseMove = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + if (_this.state === STATE.ROTATE) { + if (_this.enableRotate === false) + return; + _this.rotateEnd.set(event.clientX, event.clientY); + _this.rotateDelta.subVectors(_this.rotateEnd, _this.rotateStart); + var element = _this.domElement === document ? _this.domElement.body : _this.domElement; + // rotating across whole screen goes 360 degrees around + _this.rotateLeft(2 * Math.PI * _this.rotateDelta.x / element.clientWidth * _this.rotateSpeed); + // rotating up and down along whole screen attempts to go 360, but limited to 180 + _this.rotateUp(2 * Math.PI * _this.rotateDelta.y / element.clientHeight * _this.rotateSpeed); + _this.rotateStart.copy(_this.rotateEnd); + _this.update(); + } + else if (_this.state === STATE.DOLLY) { + if (_this.enableZoom === false) + return; + _this.dollyEnd.set(event.clientX, event.clientY); + _this.dollyDelta.subVectors(_this.dollyEnd, _this.dollyStart); + if (_this.dollyDelta.y > 0) { + _this.dollyIn(_this.getZoomScale()); + } + else if (_this.dollyDelta.y < 0) { + _this.dollyOut(_this.getZoomScale()); + } + _this.dollyStart.copy(_this.dollyEnd); + _this.update(); + } + else if (_this.state === STATE.PAN) { + if (_this.enablePan === false) + return; + _this.panEnd.set(event.clientX, event.clientY); + _this.panDelta.subVectors(_this.panEnd, _this.panStart); + _this.pan(_this.panDelta.x, _this.panDelta.y); + _this.panStart.copy(_this.panEnd); + _this.update(); + } + }; + _this.onMouseUp = function (event) { + if (_this.enabled === false) + return; + document.removeEventListener("mousemove", _this.onMouseMove, false); + document.removeEventListener("mouseup", _this.onMouseUp, false); + _this.dispatchEvent(END_EVENT); + _this.state = STATE.NONE; + }; + _this.onMouseWheel = function (event) { + if (_this.enabled === false || _this.enableZoom === false || (_this.state !== STATE.NONE && _this.state !== STATE.ROTATE)) + return; + event.preventDefault(); + event.stopPropagation(); + if (event.deltaY < 0) { + _this.dollyOut(_this.getZoomScale()); + } + else if (event.deltaY > 0) { + _this.dollyIn(_this.getZoomScale()); + } + _this.update(); + _this.dispatchEvent(START_EVENT); // not sure why these are here... + _this.dispatchEvent(END_EVENT); + }; + _this.onKeyDown = function (event) { + if (_this.enabled === false || _this.enableKeys === false || _this.enablePan === false) + return; + switch (event.keyCode) { + case _this.keys.UP: { + _this.pan(0, _this.keyPanSpeed); + _this.update(); + break; + } + case _this.keys.BOTTOM: { + _this.pan(0, -_this.keyPanSpeed); + _this.update(); + break; + } + case _this.keys.LEFT: { + _this.pan(_this.keyPanSpeed, 0); + _this.update(); + break; + } + case _this.keys.RIGHT: { + _this.pan(-_this.keyPanSpeed, 0); + _this.update(); + break; + } + } + }; + _this.onTouchStart = function (event) { + if (_this.enabled === false) + return; + switch (event.touches.length) { + // one-fingered touch: rotate + case 1: { + if (_this.enableRotate === false) + return; + _this.rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); + _this.state = STATE.TOUCH_ROTATE; + break; + } + // two-fingered touch: dolly + case 2: { + if (_this.enableZoom === false) + return; + var dx = event.touches[0].pageX - event.touches[1].pageX; + var dy = event.touches[0].pageY - event.touches[1].pageY; + var distance = Math.sqrt(dx * dx + dy * dy); + _this.dollyStart.set(0, distance); + _this.state = STATE.TOUCH_DOLLY; + break; + } + // three-fingered touch: pan + case 3: { + if (_this.enablePan === false) + return; + _this.panStart.set(event.touches[0].pageX, event.touches[0].pageY); + _this.state = STATE.TOUCH_PAN; + break; + } + default: { + _this.state = STATE.NONE; + } + } + if (_this.state !== STATE.NONE) { + _this.dispatchEvent(START_EVENT); + } + }; + _this.onTouchMove = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + event.stopPropagation(); + switch (event.touches.length) { + // one-fingered touch: rotate + case 1: { + if (_this.enableRotate === false) + return; + if (_this.state !== STATE.TOUCH_ROTATE) + return; // is this needed?... + _this.rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); + _this.rotateDelta.subVectors(_this.rotateEnd, _this.rotateStart); + var element = _this.domElement === document ? _this.domElement.body : _this.domElement; + // rotating across whole screen goes 360 degrees around + _this.rotateLeft(2 * Math.PI * _this.rotateDelta.x / element.clientWidth * _this.rotateSpeed); + // rotating up and down along whole screen attempts to go 360, but limited to 180 + _this.rotateUp(2 * Math.PI * _this.rotateDelta.y / element.clientHeight * _this.rotateSpeed); + _this.rotateStart.copy(_this.rotateEnd); + _this.update(); + break; + } + // two-fingered touch: dolly + case 2: { + if (_this.enableZoom === false) + return; + if (_this.state !== STATE.TOUCH_DOLLY) + return; // is this needed?... + // console.log( "handleTouchMoveDolly" ); + var dx = event.touches[0].pageX - event.touches[1].pageX; + var dy = event.touches[0].pageY - event.touches[1].pageY; + var distance = Math.sqrt(dx * dx + dy * dy); + _this.dollyEnd.set(0, distance); + _this.dollyDelta.subVectors(_this.dollyEnd, _this.dollyStart); + if (_this.dollyDelta.y > 0) { + _this.dollyOut(_this.getZoomScale()); + } + else if (_this.dollyDelta.y < 0) { + _this.dollyIn(_this.getZoomScale()); + } + _this.dollyStart.copy(_this.dollyEnd); + _this.update(); + break; + } + // three-fingered touch: pan + case 3: { + if (_this.enablePan === false) + return; + if (_this.state !== STATE.TOUCH_PAN) + return; // is this needed?... + _this.panEnd.set(event.touches[0].pageX, event.touches[0].pageY); + _this.panDelta.subVectors(_this.panEnd, _this.panStart); + _this.pan(_this.panDelta.x, _this.panDelta.y); + _this.panStart.copy(_this.panEnd); + _this.update(); + break; + } + default: { + _this.state = STATE.NONE; + } + } + }; + _this.onTouchEnd = function (event) { + if (_this.enabled === false) + return; + _this.dispatchEvent(END_EVENT); + _this.state = STATE.NONE; + }; + _this.onContextMenu = function (event) { + event.preventDefault(); + }; + _this.domElement.addEventListener("contextmenu", _this.onContextMenu, false); + _this.domElement.addEventListener("mousedown", _this.onMouseDown, false); + _this.domElement.addEventListener("wheel", _this.onMouseWheel, false); + _this.domElement.addEventListener("touchstart", _this.onTouchStart, false); + _this.domElement.addEventListener("touchend", _this.onTouchEnd, false); + _this.domElement.addEventListener("touchmove", _this.onTouchMove, false); + _this.window.addEventListener("keydown", _this.onKeyDown, false); + // force an update at start + _this.update(); + return _this; + } + OrbitControls.prototype.update = function () { + var position = this.object.position; + this.updateOffset.copy(position).sub(this.target); + // rotate offset to "y-axis-is-up" space + this.updateOffset.applyQuaternion(this.updateQuat); + // angle from z-axis around y-axis + this.spherical.setFromVector3(this.updateOffset); + if (this.autoRotate && this.state === STATE.NONE) { + this.rotateLeft(this.getAutoRotationAngle()); + } + this.spherical.theta += this.sphericalDelta.theta; + this.spherical.phi += this.sphericalDelta.phi; + // restrict theta to be between desired limits + this.spherical.theta = Math.max(this.minAzimuthAngle, Math.min(this.maxAzimuthAngle, this.spherical.theta)); + // restrict phi to be between desired limits + this.spherical.phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.spherical.phi)); + this.spherical.makeSafe(); + this.spherical.radius *= this.scale; + // restrict radius to be between desired limits + this.spherical.radius = Math.max(this.minDistance, Math.min(this.maxDistance, this.spherical.radius)); + // move target to panned location + this.target.add(this.panOffset); + this.updateOffset.setFromSpherical(this.spherical); + // rotate offset back to "camera-up-vector-is-up" space + this.updateOffset.applyQuaternion(this.updateQuatInverse); + position.copy(this.target).add(this.updateOffset); + this.object.lookAt(this.target); + if (this.enableDamping === true) { + this.sphericalDelta.theta *= (1 - this.dampingFactor); + this.sphericalDelta.phi *= (1 - this.dampingFactor); + } + else { + this.sphericalDelta.set(0, 0, 0); + } + this.scale = 1; + this.panOffset.set(0, 0, 0); + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + if (this.zoomChanged || + this.updateLastPosition.distanceToSquared(this.object.position) > EPS || + 8 * (1 - this.updateLastQuaternion.dot(this.object.quaternion)) > EPS) { + this.dispatchEvent(CHANGE_EVENT); + this.updateLastPosition.copy(this.object.position); + this.updateLastQuaternion.copy(this.object.quaternion); + this.zoomChanged = false; + return true; + } + return false; + }; + OrbitControls.prototype.panLeft = function (distance, objectMatrix) { + this.panLeftV.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix + this.panLeftV.multiplyScalar(-distance); + this.panOffset.add(this.panLeftV); + }; + OrbitControls.prototype.panUp = function (distance, objectMatrix) { + this.panUpV.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix + this.panUpV.multiplyScalar(distance); + this.panOffset.add(this.panUpV); + }; + // deltaX and deltaY are in pixels; right and down are positive + OrbitControls.prototype.pan = function (deltaX, deltaY) { + var element = this.domElement === document ? this.domElement.body : this.domElement; + if (this.object instanceof THREE.PerspectiveCamera) { + // perspective + var position = this.object.position; + this.panInternalOffset.copy(position).sub(this.target); + var targetDistance = this.panInternalOffset.length(); + // half of the fov is center to top of screen + targetDistance *= Math.tan((this.object.fov / 2) * Math.PI / 180.0); + // we actually don"t use screenWidth, since perspective camera is fixed to screen height + this.panLeft(2 * deltaX * targetDistance / element.clientHeight, this.object.matrix); + this.panUp(2 * deltaY * targetDistance / element.clientHeight, this.object.matrix); + } + else if (this.object instanceof THREE.OrthographicCamera) { + // orthographic + this.panLeft(deltaX * (this.object.right - this.object.left) / this.object.zoom / element.clientWidth, this.object.matrix); + this.panUp(deltaY * (this.object.top - this.object.bottom) / this.object.zoom / element.clientHeight, this.object.matrix); + } + else { + // camera neither orthographic nor perspective + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."); + this.enablePan = false; + } + }; + OrbitControls.prototype.dollyIn = function (dollyScale) { + if (this.object instanceof THREE.PerspectiveCamera) { + this.scale /= dollyScale; + } + else if (this.object instanceof THREE.OrthographicCamera) { + this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom * dollyScale)); + this.object.updateProjectionMatrix(); + this.zoomChanged = true; + } + else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); + this.enableZoom = false; + } + }; + OrbitControls.prototype.dollyOut = function (dollyScale) { + if (this.object instanceof THREE.PerspectiveCamera) { + this.scale *= dollyScale; + } + else if (this.object instanceof THREE.OrthographicCamera) { + this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / dollyScale)); + this.object.updateProjectionMatrix(); + this.zoomChanged = true; + } + else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); + this.enableZoom = false; + } + }; + OrbitControls.prototype.getAutoRotationAngle = function () { + return 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }; + OrbitControls.prototype.getZoomScale = function () { + return Math.pow(0.95, this.zoomSpeed); + }; + OrbitControls.prototype.rotateLeft = function (angle) { + this.sphericalDelta.theta -= angle; + }; + OrbitControls.prototype.rotateUp = function (angle) { + this.sphericalDelta.phi -= angle; + }; + OrbitControls.prototype.getPolarAngle = function () { + return this.spherical.phi; + }; + OrbitControls.prototype.getAzimuthalAngle = function () { + return this.spherical.theta; + }; + OrbitControls.prototype.dispose = function () { + this.domElement.removeEventListener("contextmenu", this.onContextMenu, false); + this.domElement.removeEventListener("mousedown", this.onMouseDown, false); + this.domElement.removeEventListener("wheel", this.onMouseWheel, false); + this.domElement.removeEventListener("touchstart", this.onTouchStart, false); + this.domElement.removeEventListener("touchend", this.onTouchEnd, false); + this.domElement.removeEventListener("touchmove", this.onTouchMove, false); + document.removeEventListener("mousemove", this.onMouseMove, false); + document.removeEventListener("mouseup", this.onMouseUp, false); + this.window.removeEventListener("keydown", this.onKeyDown, false); + // this.dispatchEvent( { type: "dispose" } ); // should this be added here? + }; + OrbitControls.prototype.reset = function () { + this.target.copy(this.target0); + this.object.position.copy(this.position0); + this.object.zoom = this.zoom0; + this.object.updateProjectionMatrix(); + this.dispatchEvent(CHANGE_EVENT); + this.update(); + this.state = STATE.NONE; + }; + return OrbitControls; + }(THREE.EventDispatcher)); + function createOrbitControls(skinViewer) { + var control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement); + // default configuration + control.enablePan = false; + control.target = new THREE.Vector3(0, -12, 0); + control.minDistance = 10; + control.maxDistance = 256; + control.update(); + return control; + } + + exports.SkinObject = SkinObject; + exports.BodyPart = BodyPart; + exports.CapeObject = CapeObject; + exports.PlayerObject = PlayerObject; + exports.SkinViewer = SkinViewer; + exports.OrbitControls = OrbitControls; + exports.createOrbitControls = createOrbitControls; + exports.invokeAnimation = invokeAnimation; + exports.CompositeAnimation = CompositeAnimation; + exports.WalkingAnimation = WalkingAnimation; + exports.RunningAnimation = RunningAnimation; + exports.RotatingAnimation = RotatingAnimation; + exports.isSlimSkin = isSlimSkin; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/dist/skinview3d.min.js b/dist/skinview3d.min.js new file mode 100644 index 0000000..452294a --- /dev/null +++ b/dist/skinview3d.min.js @@ -0,0 +1,7 @@ +/** + * skinview3d (https://github.com/bs-community/skinview3d) + * + * MIT License + */ + +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("three")):"function"==typeof define&&define.amd?define(["exports","three"],t):t(e.skinview3d={},e.THREE)}(this,function(e,U){"use strict";var a=function(e,t){return(a=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function t(e,t){function n(){this.constructor=e}a(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}function i(e,t,n,a,i,o){return[new U.Vector2(e/i,1-a/o),new U.Vector2(n/i,1-a/o),new U.Vector2(n/i,1-t/o),new U.Vector2(e/i,1-t/o)]}function V(e,t,n,a){return i(e,t,n,a,64,64)}function o(e,t,n,a){return i(e,t,n,a,64,32)}function A(e,t,n,a,i,o,s){e.faceVertexUvs[0]=[],e.faceVertexUvs[0][0]=[o[3],o[0],o[2]],e.faceVertexUvs[0][1]=[o[0],o[1],o[2]],e.faceVertexUvs[0][2]=[a[3],a[0],a[2]],e.faceVertexUvs[0][3]=[a[0],a[1],a[2]],e.faceVertexUvs[0][4]=[t[3],t[0],t[2]],e.faceVertexUvs[0][5]=[t[0],t[1],t[2]],e.faceVertexUvs[0][6]=[n[0],n[3],n[1]],e.faceVertexUvs[0][7]=[n[3],n[2],n[1]],e.faceVertexUvs[0][8]=[i[3],i[0],i[2]],e.faceVertexUvs[0][9]=[i[0],i[1],i[2]],e.faceVertexUvs[0][10]=[s[3],s[0],s[2]],e.faceVertexUvs[0][11]=[s[0],s[1],s[2]]}var C=.002,z=function(a){function e(e,t){var n=a.call(this)||this;return n.innerLayer=e,n.outerLayer=t,n}return t(e,a),e}(U.Group),s=function(D){function e(e,t){var n=D.call(this)||this;n.modelListeners=[],n._slim=!1;var a=new U.BoxGeometry(8,8,8,0,0,0);A(a,V(8,0,16,8),V(16,0,24,8),V(0,8,8,16),V(8,8,16,16),V(16,8,24,16),V(24,8,32,16));var i=new U.Mesh(a,e),o=new U.BoxGeometry(9,9,9,0,0,0);A(o,V(40,0,48,8),V(48,0,56,8),V(32,8,40,16),V(40,8,48,16),V(48,8,56,16),V(56,8,64,16));var s=new U.Mesh(o,t);s.renderOrder=-1,n.head=new z(i,s),n.head.add(i,s),n.add(n.head);var r=new U.BoxGeometry(8,12,4,0,0,0);A(r,V(20,16,28,20),V(28,16,36,20),V(16,20,20,32),V(20,20,28,32),V(28,20,32,32),V(32,20,40,32));var h=new U.Mesh(r,e),c=new U.BoxGeometry(9,13.5,4.5,0,0,0);A(c,V(20,32,28,36),V(28,32,36,36),V(16,36,20,48),V(20,36,28,48),V(28,36,32,48),V(32,36,40,48));var d=new U.Mesh(c,t);n.body=new z(h,d),n.body.add(h,d),n.body.position.y=-10,n.add(n.body);var l=new U.BoxGeometry(1,1,1,0,0,0),p=new U.Mesh(l,e);n.modelListeners.push(function(){p.scale.x=(n.slim?3:4)-C,p.scale.y=12-C,p.scale.z=4-C,n.slim?A(l,V(44,16,47,20),V(47,16,50,20),V(40,20,44,32),V(44,20,47,32),V(47,20,51,32),V(51,20,54,32)):A(l,V(44,16,48,20),V(48,16,52,20),V(40,20,44,32),V(44,20,48,32),V(48,20,52,32),V(52,20,56,32)),l.uvsNeedUpdate=!0,l.elementsNeedUpdate=!0});var u=new U.BoxGeometry(1,1,1,0,0,0),m=new U.Mesh(u,t);m.renderOrder=1,n.modelListeners.push(function(){m.scale.x=(n.slim?3.375:4.5)-C,m.scale.y=13.498,m.scale.z=4.498,n.slim?A(u,V(44,32,47,36),V(47,32,50,36),V(40,36,44,48),V(44,36,47,48),V(47,36,51,48),V(51,36,54,48)):A(u,V(44,32,48,36),V(48,32,52,36),V(40,36,44,48),V(44,36,48,48),V(48,36,52,48),V(52,36,56,48)),u.uvsNeedUpdate=!0,u.elementsNeedUpdate=!0});var f=new U.Group;f.add(p,m),f.position.y=-6,n.rightArm=new z(p,m),n.rightArm.add(f),n.rightArm.position.y=-4,n.modelListeners.push(function(){n.rightArm.position.x=n.slim?-5.5:-6}),n.add(n.rightArm);var y=new U.BoxGeometry(1,1,1,0,0,0),g=new U.Mesh(y,e);n.modelListeners.push(function(){g.scale.x=(n.slim?3:4)-C,g.scale.y=12-C,g.scale.z=4-C,n.slim?A(y,V(36,48,39,52),V(39,48,42,52),V(32,52,36,64),V(36,52,39,64),V(39,52,43,64),V(43,52,46,64)):A(y,V(36,48,40,52),V(40,48,44,52),V(32,52,36,64),V(36,52,40,64),V(40,52,44,64),V(44,52,48,64)),y.uvsNeedUpdate=!0,y.elementsNeedUpdate=!0});var v=new U.BoxGeometry(1,1,1,0,0,0),w=new U.Mesh(v,t);w.renderOrder=1,n.modelListeners.push(function(){w.scale.x=(n.slim?3.375:4.5)-C,w.scale.y=13.498,w.scale.z=4.498,n.slim?A(v,V(52,48,55,52),V(55,48,58,52),V(48,52,52,64),V(52,52,55,64),V(55,52,59,64),V(59,52,62,64)):A(v,V(52,48,56,52),V(56,48,60,52),V(48,52,52,64),V(52,52,56,64),V(56,52,60,64),V(60,52,64,64)),v.uvsNeedUpdate=!0,v.elementsNeedUpdate=!0});var b=new U.Group;b.add(g,w),b.position.y=-6,n.leftArm=new z(g,w),n.leftArm.add(b),n.leftArm.position.y=-4,n.modelListeners.push(function(){n.leftArm.position.x=n.slim?5.5:6}),n.add(n.leftArm);var M=new U.BoxGeometry(4-C,12-C,4-C,0,0,0);A(M,V(4,16,8,20),V(8,16,12,20),V(0,20,4,32),V(4,20,8,32),V(8,20,12,32),V(12,20,16,32));var x=new U.Mesh(M,e),E=new U.BoxGeometry(4.498,13.498,4.498,0,0,0);A(E,V(4,32,8,36),V(8,32,12,36),V(0,36,4,48),V(4,36,8,48),V(8,36,12,48),V(12,36,16,48));var L=new U.Mesh(E,t);L.renderOrder=1;var S=new U.Group;S.add(x,L),S.position.y=-6,n.rightLeg=new z(x,L),n.rightLeg.add(S),n.rightLeg.position.y=-16,n.rightLeg.position.x=-2,n.add(n.rightLeg);var P=new U.BoxGeometry(4-C,12-C,4-C,0,0,0);A(P,V(20,48,24,52),V(24,48,28,52),V(16,52,20,64),V(20,52,24,64),V(24,52,28,64),V(28,52,32,64));var O=new U.Mesh(P,e),k=new U.BoxGeometry(4.498,13.498,4.498,0,0,0);A(k,V(4,48,8,52),V(8,48,12,52),V(0,52,4,64),V(4,52,8,64),V(8,52,12,64),V(12,52,16,64));var I=new U.Mesh(k,t);I.renderOrder=1;var j=new U.Group;return j.add(O,I),j.position.y=-6,n.leftLeg=new z(O,I),n.leftLeg.add(j),n.leftLeg.position.y=-16,n.leftLeg.position.x=2,n.add(n.leftLeg),n.slim=!1,n}return t(e,D),Object.defineProperty(e.prototype,"slim",{get:function(){return this._slim},set:function(e){this._slim=e,this.modelListeners.forEach(function(e){return e()})},enumerable:!0,configurable:!0}),e.prototype.getBodyParts=function(){return this.children.filter(function(e){return e instanceof z})},e.prototype.setInnerLayerVisible=function(t){this.getBodyParts().forEach(function(e){return e.innerLayer.visible=t})},e.prototype.setOuterLayerVisible=function(t){this.getBodyParts().forEach(function(e){return e.outerLayer.visible=t})},e}(U.Group),r=function(a){function e(e){var t=a.call(this)||this,n=new U.BoxGeometry(10,16,1,0,0,0);return A(n,o(1,0,11,1),o(11,0,21,1),o(11,1,12,17),o(12,1,22,17),o(0,1,1,17),o(1,1,11,17)),t.cape=new U.Mesh(n,e),t.cape.position.y=-8,t.cape.position.z=-.5,t.add(t.cape),t}return t(e,a),e}(U.Group),h=function(i){function e(e,t,n){var a=i.call(this)||this;return a.skin=new s(e,t),a.skin.visible=!1,a.add(a.skin),a.cape=new r(n),a.cape.position.z=-2,a.cape.position.y=-4,a.cape.rotation.x=25*Math.PI/180,a.cape.visible=!1,a.add(a.cape),a}return t(e,i),e}(U.Group);function c(e,t,n){e instanceof Function?e(t,n):e.play(t,n)}var d=function(){function e(e){this.paused=!1,this.speed=1,this._paused=!1,this._lastChange=null,this._speed=1,this._lastChangeX=null,this.animation=e}return e.prototype.play=function(e,t){if(null===this._lastChange)this._lastChange=t,this._lastChangeX=0;else if(this.paused!==this._paused||this.speed!==this._speed){var n=t-this._lastChange;!1===this._paused&&(this._lastChangeX+=n*this._speed),this._paused=this.paused,this._speed=this.speed,this._lastChange=t}if(!1===this.paused){n=t-this._lastChange;var a=this._lastChangeX+this.speed*n;c(this.animation,e,a)}},e.prototype.reset=function(){this._lastChange=null},e.prototype.remove=function(){},e}(),n=function(){function e(){this.handles=new Set}return e.prototype.add=function(e){var t=this,n=new d(e);return n.remove=function(){return t.handles.delete(n)},this.handles.add(n),n},e.prototype.play=function(t,n){this.handles.forEach(function(e){return e.play(t,n)})},e}();function l(e,t,n,a,i){for(var o=e.getImageData(t,n,a,i),s=0;s*-------*-------* + // (40,20) |top |bottom | + // \|/ |4x4 |4x4 | + // *-------*-------*-------*-------* + // |right |front |left |back | + // |4x12 |4x12 |4x12 |4x12 | + // *-------*-------*-------*-------* + // The right arm area of *slim* skins: + // (44,16)->*------*------*-* + // (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4] + // \|/ |3x4 |3x4 | | + // *-------*------*------***-----*-* + // |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12] + // |4x12 |3x12 |4x12 |3x12 | | + // *-------*------*-------*------*-* + // Compared with default right arms, slim right arms have 2 unused areas. + // + // The same is true for left arm: + // The left arm area of *default* skins: + // (36,48)->*-------*-------* + // (32,52) |top |bottom | + // \|/ |4x4 |4x4 | + // *-------*-------*-------*-------* + // |right |front |left |back | + // |4x12 |4x12 |4x12 |4x12 | + // *-------*-------*-------*-------* + // The left arm area of *slim* skins: + // (36,48)->*------*------*-* + // (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4] + // \|/ |3x4 |3x4 | | + // *-------*------*------***-----*-* + // |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12] + // |4x12 |3x12 |4x12 |3x12 | | + // *-------*------*-------*------*-* + // + // If there is a transparent pixel in any of the 4 unused areas, the skin must be slim, + // as transparent pixels are not allowed in the first layer. + if (canvasOrImage instanceof HTMLCanvasElement) { + var canvas = canvasOrImage; + var scale_2 = computeSkinScale(canvas.width); + var context_1 = canvas.getContext("2d"); + var checkArea = function (x, y, w, h) { return hasTransparency(context_1, x * scale_2, y * scale_2, w * scale_2, h * scale_2); }; + return checkArea(50, 16, 2, 4) || + checkArea(54, 20, 2, 12) || + checkArea(42, 48, 2, 4) || + checkArea(46, 52, 2, 12); + } + else { + var image = canvasOrImage; + var canvas = document.createElement("canvas"); + loadSkinToCanvas(canvas, image); + return isSlimSkin(canvas); + } +} + +var SkinViewer = /** @class */ (function () { + function SkinViewer(options) { + var _this = this; + this.detectModel = true; + this.animationPaused = false; + this.animationTime = 0; + this.disposed = false; + this.domElement = options.domElement; + this.animation = options.animation || null; + if (options.detectModel === false) { + this.detectModel = false; + } + // texture + this.skinImg = new Image(); + this.skinCanvas = document.createElement("canvas"); + this.skinTexture = new Texture(this.skinCanvas); + this.skinTexture.magFilter = NearestFilter; + this.skinTexture.minFilter = NearestFilter; + this.capeImg = new Image(); + this.capeCanvas = document.createElement("canvas"); + this.capeTexture = new Texture(this.capeCanvas); + this.capeTexture.magFilter = NearestFilter; + this.capeTexture.minFilter = NearestFilter; + this.layer1Material = new MeshBasicMaterial({ map: this.skinTexture, side: FrontSide }); + this.layer2Material = new MeshBasicMaterial({ map: this.skinTexture, transparent: true, opacity: 1, side: DoubleSide, alphaTest: 0.5 }); + this.capeMaterial = new MeshBasicMaterial({ map: this.capeTexture, transparent: true, opacity: 1, side: DoubleSide, alphaTest: 0.5 }); + // scene + this.scene = new Scene(); + // Use smaller fov to avoid distortion + this.camera = new PerspectiveCamera(40); + this.camera.position.y = -12; + this.camera.position.z = 60; + this.renderer = new WebGLRenderer({ alpha: true, antialias: false }); + this.renderer.setSize(300, 300); // default size + this.renderer.context.getShaderInfoLog = function () { return ""; }; // shut firefox up + this.domElement.appendChild(this.renderer.domElement); + this.playerObject = new PlayerObject(this.layer1Material, this.layer2Material, this.capeMaterial); + this.scene.add(this.playerObject); + // texture loading + this.skinImg.crossOrigin = "anonymous"; + this.skinImg.onerror = function () { return console.error("Failed loading " + _this.skinImg.src); }; + this.skinImg.onload = function () { + loadSkinToCanvas(_this.skinCanvas, _this.skinImg); + if (_this.detectModel) { + _this.playerObject.skin.slim = isSlimSkin(_this.skinCanvas); + } + _this.skinTexture.needsUpdate = true; + _this.layer1Material.needsUpdate = true; + _this.layer2Material.needsUpdate = true; + _this.playerObject.skin.visible = true; + }; + this.capeImg.crossOrigin = "anonymous"; + this.capeImg.onerror = function () { return console.error("Failed loading " + _this.capeImg.src); }; + this.capeImg.onload = function () { + loadCapeToCanvas(_this.capeCanvas, _this.capeImg); + _this.capeTexture.needsUpdate = true; + _this.capeMaterial.needsUpdate = true; + _this.playerObject.cape.visible = true; + }; + if (options.skinUrl) + this.skinUrl = options.skinUrl; + if (options.capeUrl) + this.capeUrl = options.capeUrl; + if (options.width) + this.width = options.width; + if (options.height) + this.height = options.height; + var draw = function () { + if (_this.disposed) + return; + window.requestAnimationFrame(draw); + if (!_this.animationPaused) { + _this.animationTime++; + if (_this.animation) { + invokeAnimation(_this.animation, _this.playerObject, _this.animationTime / 100.0); + } + } + _this.renderer.render(_this.scene, _this.camera); + }; + draw(); + } + SkinViewer.prototype.setSize = function (width, height) { + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + }; + SkinViewer.prototype.dispose = function () { + this.disposed = true; + this.domElement.removeChild(this.renderer.domElement); + this.renderer.dispose(); + this.skinTexture.dispose(); + this.capeTexture.dispose(); + }; + Object.defineProperty(SkinViewer.prototype, "skinUrl", { + get: function () { + return this.skinImg.src; + }, + set: function (url) { + this.skinImg.src = url; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "capeUrl", { + get: function () { + return this.capeImg.src; + }, + set: function (url) { + this.capeImg.src = url; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "width", { + get: function () { + return this.renderer.getSize().width; + }, + set: function (newWidth) { + this.setSize(newWidth, this.height); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "height", { + get: function () { + return this.renderer.getSize().height; + }, + set: function (newHeight) { + this.setSize(this.width, newHeight); + }, + enumerable: true, + configurable: true + }); + return SkinViewer; +}()); + +var STATE = { + NONE: -1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_DOLLY: 4, + TOUCH_PAN: 5 +}; +var CHANGE_EVENT = { type: "change" }; +var START_EVENT = { type: "start" }; +var END_EVENT = { type: "end" }; +var EPS = 0.000001; +var OrbitControls = /** @class */ (function (_super) { + __extends(OrbitControls, _super); + function OrbitControls(object, domElement, domWindow) { + var _this = _super.call(this) || this; + _this.object = object; + _this.domElement = (domElement !== undefined) ? domElement : document; + _this.window = (domWindow !== undefined) ? domWindow : window; + // Set to false to disable this control + _this.enabled = true; + // "target" sets the location of focus, where the object orbits around + _this.target = new Vector3(); + // How far you can dolly in and out ( PerspectiveCamera only ) + _this.minDistance = 0; + _this.maxDistance = Infinity; + // How far you can zoom in and out ( OrthographicCamera only ) + _this.minZoom = 0; + _this.maxZoom = Infinity; + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + _this.minPolarAngle = 0; // radians + _this.maxPolarAngle = Math.PI; // radians + // How far you can orbit horizontally, upper and lower limits. + // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. + _this.minAzimuthAngle = -Infinity; // radians + _this.maxAzimuthAngle = Infinity; // radians + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + _this.enableDamping = false; + _this.dampingFactor = 0.25; + // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. + // Set to false to disable zooming + _this.enableZoom = true; + _this.zoomSpeed = 1.0; + // Set to false to disable rotating + _this.enableRotate = true; + _this.rotateSpeed = 1.0; + // Set to false to disable panning + _this.enablePan = true; + _this.keyPanSpeed = 7.0; // pixels moved per arrow key push + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + _this.autoRotate = false; + _this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + // Set to false to disable use of the keys + _this.enableKeys = true; + // The four arrow keys + _this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; + // Mouse buttons + _this.mouseButtons = { ORBIT: MOUSE.LEFT, ZOOM: MOUSE.MIDDLE, PAN: MOUSE.RIGHT }; + // for reset + _this.target0 = _this.target.clone(); + _this.position0 = _this.object.position.clone(); + _this.zoom0 = _this.object.zoom; + // for update speedup + _this.updateOffset = new Vector3(); + // so camera.up is the orbit axis + _this.updateQuat = new Quaternion().setFromUnitVectors(object.up, new Vector3(0, 1, 0)); + _this.updateQuatInverse = _this.updateQuat.clone().inverse(); + _this.updateLastPosition = new Vector3(); + _this.updateLastQuaternion = new Quaternion(); + _this.state = STATE.NONE; + _this.scale = 1; + // current position in spherical coordinates + _this.spherical = new Spherical(); + _this.sphericalDelta = new Spherical(); + _this.panOffset = new Vector3(); + _this.zoomChanged = false; + _this.rotateStart = new Vector2(); + _this.rotateEnd = new Vector2(); + _this.rotateDelta = new Vector2(); + _this.panStart = new Vector2(); + _this.panEnd = new Vector2(); + _this.panDelta = new Vector2(); + _this.dollyStart = new Vector2(); + _this.dollyEnd = new Vector2(); + _this.dollyDelta = new Vector2(); + _this.panLeftV = new Vector3(); + _this.panUpV = new Vector3(); + _this.panInternalOffset = new Vector3(); + // event handlers - FSM: listen for events and reset state + _this.onMouseDown = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + if (event.button === _this.mouseButtons.ORBIT) { + if (_this.enableRotate === false) + return; + _this.rotateStart.set(event.clientX, event.clientY); + _this.state = STATE.ROTATE; + } + else if (event.button === _this.mouseButtons.ZOOM) { + if (_this.enableZoom === false) + return; + _this.dollyStart.set(event.clientX, event.clientY); + _this.state = STATE.DOLLY; + } + else if (event.button === _this.mouseButtons.PAN) { + if (_this.enablePan === false) + return; + _this.panStart.set(event.clientX, event.clientY); + _this.state = STATE.PAN; + } + if (_this.state !== STATE.NONE) { + document.addEventListener("mousemove", _this.onMouseMove, false); + document.addEventListener("mouseup", _this.onMouseUp, false); + _this.dispatchEvent(START_EVENT); + } + }; + _this.onMouseMove = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + if (_this.state === STATE.ROTATE) { + if (_this.enableRotate === false) + return; + _this.rotateEnd.set(event.clientX, event.clientY); + _this.rotateDelta.subVectors(_this.rotateEnd, _this.rotateStart); + var element = _this.domElement === document ? _this.domElement.body : _this.domElement; + // rotating across whole screen goes 360 degrees around + _this.rotateLeft(2 * Math.PI * _this.rotateDelta.x / element.clientWidth * _this.rotateSpeed); + // rotating up and down along whole screen attempts to go 360, but limited to 180 + _this.rotateUp(2 * Math.PI * _this.rotateDelta.y / element.clientHeight * _this.rotateSpeed); + _this.rotateStart.copy(_this.rotateEnd); + _this.update(); + } + else if (_this.state === STATE.DOLLY) { + if (_this.enableZoom === false) + return; + _this.dollyEnd.set(event.clientX, event.clientY); + _this.dollyDelta.subVectors(_this.dollyEnd, _this.dollyStart); + if (_this.dollyDelta.y > 0) { + _this.dollyIn(_this.getZoomScale()); + } + else if (_this.dollyDelta.y < 0) { + _this.dollyOut(_this.getZoomScale()); + } + _this.dollyStart.copy(_this.dollyEnd); + _this.update(); + } + else if (_this.state === STATE.PAN) { + if (_this.enablePan === false) + return; + _this.panEnd.set(event.clientX, event.clientY); + _this.panDelta.subVectors(_this.panEnd, _this.panStart); + _this.pan(_this.panDelta.x, _this.panDelta.y); + _this.panStart.copy(_this.panEnd); + _this.update(); + } + }; + _this.onMouseUp = function (event) { + if (_this.enabled === false) + return; + document.removeEventListener("mousemove", _this.onMouseMove, false); + document.removeEventListener("mouseup", _this.onMouseUp, false); + _this.dispatchEvent(END_EVENT); + _this.state = STATE.NONE; + }; + _this.onMouseWheel = function (event) { + if (_this.enabled === false || _this.enableZoom === false || (_this.state !== STATE.NONE && _this.state !== STATE.ROTATE)) + return; + event.preventDefault(); + event.stopPropagation(); + if (event.deltaY < 0) { + _this.dollyOut(_this.getZoomScale()); + } + else if (event.deltaY > 0) { + _this.dollyIn(_this.getZoomScale()); + } + _this.update(); + _this.dispatchEvent(START_EVENT); // not sure why these are here... + _this.dispatchEvent(END_EVENT); + }; + _this.onKeyDown = function (event) { + if (_this.enabled === false || _this.enableKeys === false || _this.enablePan === false) + return; + switch (event.keyCode) { + case _this.keys.UP: { + _this.pan(0, _this.keyPanSpeed); + _this.update(); + break; + } + case _this.keys.BOTTOM: { + _this.pan(0, -_this.keyPanSpeed); + _this.update(); + break; + } + case _this.keys.LEFT: { + _this.pan(_this.keyPanSpeed, 0); + _this.update(); + break; + } + case _this.keys.RIGHT: { + _this.pan(-_this.keyPanSpeed, 0); + _this.update(); + break; + } + } + }; + _this.onTouchStart = function (event) { + if (_this.enabled === false) + return; + switch (event.touches.length) { + // one-fingered touch: rotate + case 1: { + if (_this.enableRotate === false) + return; + _this.rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); + _this.state = STATE.TOUCH_ROTATE; + break; + } + // two-fingered touch: dolly + case 2: { + if (_this.enableZoom === false) + return; + var dx = event.touches[0].pageX - event.touches[1].pageX; + var dy = event.touches[0].pageY - event.touches[1].pageY; + var distance = Math.sqrt(dx * dx + dy * dy); + _this.dollyStart.set(0, distance); + _this.state = STATE.TOUCH_DOLLY; + break; + } + // three-fingered touch: pan + case 3: { + if (_this.enablePan === false) + return; + _this.panStart.set(event.touches[0].pageX, event.touches[0].pageY); + _this.state = STATE.TOUCH_PAN; + break; + } + default: { + _this.state = STATE.NONE; + } + } + if (_this.state !== STATE.NONE) { + _this.dispatchEvent(START_EVENT); + } + }; + _this.onTouchMove = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + event.stopPropagation(); + switch (event.touches.length) { + // one-fingered touch: rotate + case 1: { + if (_this.enableRotate === false) + return; + if (_this.state !== STATE.TOUCH_ROTATE) + return; // is this needed?... + _this.rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); + _this.rotateDelta.subVectors(_this.rotateEnd, _this.rotateStart); + var element = _this.domElement === document ? _this.domElement.body : _this.domElement; + // rotating across whole screen goes 360 degrees around + _this.rotateLeft(2 * Math.PI * _this.rotateDelta.x / element.clientWidth * _this.rotateSpeed); + // rotating up and down along whole screen attempts to go 360, but limited to 180 + _this.rotateUp(2 * Math.PI * _this.rotateDelta.y / element.clientHeight * _this.rotateSpeed); + _this.rotateStart.copy(_this.rotateEnd); + _this.update(); + break; + } + // two-fingered touch: dolly + case 2: { + if (_this.enableZoom === false) + return; + if (_this.state !== STATE.TOUCH_DOLLY) + return; // is this needed?... + // console.log( "handleTouchMoveDolly" ); + var dx = event.touches[0].pageX - event.touches[1].pageX; + var dy = event.touches[0].pageY - event.touches[1].pageY; + var distance = Math.sqrt(dx * dx + dy * dy); + _this.dollyEnd.set(0, distance); + _this.dollyDelta.subVectors(_this.dollyEnd, _this.dollyStart); + if (_this.dollyDelta.y > 0) { + _this.dollyOut(_this.getZoomScale()); + } + else if (_this.dollyDelta.y < 0) { + _this.dollyIn(_this.getZoomScale()); + } + _this.dollyStart.copy(_this.dollyEnd); + _this.update(); + break; + } + // three-fingered touch: pan + case 3: { + if (_this.enablePan === false) + return; + if (_this.state !== STATE.TOUCH_PAN) + return; // is this needed?... + _this.panEnd.set(event.touches[0].pageX, event.touches[0].pageY); + _this.panDelta.subVectors(_this.panEnd, _this.panStart); + _this.pan(_this.panDelta.x, _this.panDelta.y); + _this.panStart.copy(_this.panEnd); + _this.update(); + break; + } + default: { + _this.state = STATE.NONE; + } + } + }; + _this.onTouchEnd = function (event) { + if (_this.enabled === false) + return; + _this.dispatchEvent(END_EVENT); + _this.state = STATE.NONE; + }; + _this.onContextMenu = function (event) { + event.preventDefault(); + }; + _this.domElement.addEventListener("contextmenu", _this.onContextMenu, false); + _this.domElement.addEventListener("mousedown", _this.onMouseDown, false); + _this.domElement.addEventListener("wheel", _this.onMouseWheel, false); + _this.domElement.addEventListener("touchstart", _this.onTouchStart, false); + _this.domElement.addEventListener("touchend", _this.onTouchEnd, false); + _this.domElement.addEventListener("touchmove", _this.onTouchMove, false); + _this.window.addEventListener("keydown", _this.onKeyDown, false); + // force an update at start + _this.update(); + return _this; + } + OrbitControls.prototype.update = function () { + var position = this.object.position; + this.updateOffset.copy(position).sub(this.target); + // rotate offset to "y-axis-is-up" space + this.updateOffset.applyQuaternion(this.updateQuat); + // angle from z-axis around y-axis + this.spherical.setFromVector3(this.updateOffset); + if (this.autoRotate && this.state === STATE.NONE) { + this.rotateLeft(this.getAutoRotationAngle()); + } + this.spherical.theta += this.sphericalDelta.theta; + this.spherical.phi += this.sphericalDelta.phi; + // restrict theta to be between desired limits + this.spherical.theta = Math.max(this.minAzimuthAngle, Math.min(this.maxAzimuthAngle, this.spherical.theta)); + // restrict phi to be between desired limits + this.spherical.phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.spherical.phi)); + this.spherical.makeSafe(); + this.spherical.radius *= this.scale; + // restrict radius to be between desired limits + this.spherical.radius = Math.max(this.minDistance, Math.min(this.maxDistance, this.spherical.radius)); + // move target to panned location + this.target.add(this.panOffset); + this.updateOffset.setFromSpherical(this.spherical); + // rotate offset back to "camera-up-vector-is-up" space + this.updateOffset.applyQuaternion(this.updateQuatInverse); + position.copy(this.target).add(this.updateOffset); + this.object.lookAt(this.target); + if (this.enableDamping === true) { + this.sphericalDelta.theta *= (1 - this.dampingFactor); + this.sphericalDelta.phi *= (1 - this.dampingFactor); + } + else { + this.sphericalDelta.set(0, 0, 0); + } + this.scale = 1; + this.panOffset.set(0, 0, 0); + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + if (this.zoomChanged || + this.updateLastPosition.distanceToSquared(this.object.position) > EPS || + 8 * (1 - this.updateLastQuaternion.dot(this.object.quaternion)) > EPS) { + this.dispatchEvent(CHANGE_EVENT); + this.updateLastPosition.copy(this.object.position); + this.updateLastQuaternion.copy(this.object.quaternion); + this.zoomChanged = false; + return true; + } + return false; + }; + OrbitControls.prototype.panLeft = function (distance, objectMatrix) { + this.panLeftV.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix + this.panLeftV.multiplyScalar(-distance); + this.panOffset.add(this.panLeftV); + }; + OrbitControls.prototype.panUp = function (distance, objectMatrix) { + this.panUpV.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix + this.panUpV.multiplyScalar(distance); + this.panOffset.add(this.panUpV); + }; + // deltaX and deltaY are in pixels; right and down are positive + OrbitControls.prototype.pan = function (deltaX, deltaY) { + var element = this.domElement === document ? this.domElement.body : this.domElement; + if (this.object instanceof PerspectiveCamera) { + // perspective + var position = this.object.position; + this.panInternalOffset.copy(position).sub(this.target); + var targetDistance = this.panInternalOffset.length(); + // half of the fov is center to top of screen + targetDistance *= Math.tan((this.object.fov / 2) * Math.PI / 180.0); + // we actually don"t use screenWidth, since perspective camera is fixed to screen height + this.panLeft(2 * deltaX * targetDistance / element.clientHeight, this.object.matrix); + this.panUp(2 * deltaY * targetDistance / element.clientHeight, this.object.matrix); + } + else if (this.object instanceof OrthographicCamera) { + // orthographic + this.panLeft(deltaX * (this.object.right - this.object.left) / this.object.zoom / element.clientWidth, this.object.matrix); + this.panUp(deltaY * (this.object.top - this.object.bottom) / this.object.zoom / element.clientHeight, this.object.matrix); + } + else { + // camera neither orthographic nor perspective + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."); + this.enablePan = false; + } + }; + OrbitControls.prototype.dollyIn = function (dollyScale) { + if (this.object instanceof PerspectiveCamera) { + this.scale /= dollyScale; + } + else if (this.object instanceof OrthographicCamera) { + this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom * dollyScale)); + this.object.updateProjectionMatrix(); + this.zoomChanged = true; + } + else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); + this.enableZoom = false; + } + }; + OrbitControls.prototype.dollyOut = function (dollyScale) { + if (this.object instanceof PerspectiveCamera) { + this.scale *= dollyScale; + } + else if (this.object instanceof OrthographicCamera) { + this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / dollyScale)); + this.object.updateProjectionMatrix(); + this.zoomChanged = true; + } + else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); + this.enableZoom = false; + } + }; + OrbitControls.prototype.getAutoRotationAngle = function () { + return 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }; + OrbitControls.prototype.getZoomScale = function () { + return Math.pow(0.95, this.zoomSpeed); + }; + OrbitControls.prototype.rotateLeft = function (angle) { + this.sphericalDelta.theta -= angle; + }; + OrbitControls.prototype.rotateUp = function (angle) { + this.sphericalDelta.phi -= angle; + }; + OrbitControls.prototype.getPolarAngle = function () { + return this.spherical.phi; + }; + OrbitControls.prototype.getAzimuthalAngle = function () { + return this.spherical.theta; + }; + OrbitControls.prototype.dispose = function () { + this.domElement.removeEventListener("contextmenu", this.onContextMenu, false); + this.domElement.removeEventListener("mousedown", this.onMouseDown, false); + this.domElement.removeEventListener("wheel", this.onMouseWheel, false); + this.domElement.removeEventListener("touchstart", this.onTouchStart, false); + this.domElement.removeEventListener("touchend", this.onTouchEnd, false); + this.domElement.removeEventListener("touchmove", this.onTouchMove, false); + document.removeEventListener("mousemove", this.onMouseMove, false); + document.removeEventListener("mouseup", this.onMouseUp, false); + this.window.removeEventListener("keydown", this.onKeyDown, false); + // this.dispatchEvent( { type: "dispose" } ); // should this be added here? + }; + OrbitControls.prototype.reset = function () { + this.target.copy(this.target0); + this.object.position.copy(this.position0); + this.object.zoom = this.zoom0; + this.object.updateProjectionMatrix(); + this.dispatchEvent(CHANGE_EVENT); + this.update(); + this.state = STATE.NONE; + }; + return OrbitControls; +}(EventDispatcher)); +function createOrbitControls(skinViewer) { + var control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement); + // default configuration + control.enablePan = false; + control.target = new Vector3(0, -12, 0); + control.minDistance = 10; + control.maxDistance = 256; + control.update(); + return control; +} + +export { SkinObject, BodyPart, CapeObject, PlayerObject, SkinViewer, OrbitControls, createOrbitControls, invokeAnimation, CompositeAnimation, WalkingAnimation, RunningAnimation, RotatingAnimation, isSlimSkin }; diff --git a/dist/utils.d.ts b/dist/utils.d.ts new file mode 100644 index 0000000..fddaf88 --- /dev/null +++ b/dist/utils.d.ts @@ -0,0 +1,3 @@ +export declare function loadSkinToCanvas(canvas: HTMLCanvasElement, image: HTMLImageElement): void; +export declare function loadCapeToCanvas(canvas: HTMLCanvasElement, image: HTMLImageElement): void; +export declare function isSlimSkin(canvasOrImage: HTMLCanvasElement | HTMLImageElement): boolean; diff --git a/dist/viewer.d.ts b/dist/viewer.d.ts new file mode 100644 index 0000000..6a89653 --- /dev/null +++ b/dist/viewer.d.ts @@ -0,0 +1,39 @@ +import * as THREE from "three"; +import { PlayerObject } from "./model"; +export interface SkinViewerOptions { + domElement: Node; + animation?: Animation; + skinUrl?: string; + capeUrl?: string; + width?: number; + height?: number; + detectModel?: boolean; +} +export declare class SkinViewer { + readonly domElement: Node; + animation: Animation | null; + detectModel: boolean; + animationPaused: boolean; + animationTime: number; + disposed: boolean; + readonly skinImg: HTMLImageElement; + readonly skinCanvas: HTMLCanvasElement; + readonly skinTexture: THREE.Texture; + readonly capeImg: HTMLImageElement; + readonly capeCanvas: HTMLCanvasElement; + readonly capeTexture: THREE.Texture; + readonly layer1Material: THREE.MeshBasicMaterial; + readonly layer2Material: THREE.MeshBasicMaterial; + readonly capeMaterial: THREE.MeshBasicMaterial; + readonly scene: THREE.Scene; + readonly camera: THREE.PerspectiveCamera; + readonly renderer: THREE.WebGLRenderer; + readonly playerObject: PlayerObject; + constructor(options: SkinViewerOptions); + setSize(width: any, height: any): void; + dispose(): void; + skinUrl: string; + capeUrl: string; + width: number; + height: number; +} diff --git a/img/hd_cape.png b/img/hd_cape.png new file mode 100644 index 0000000..81b20d3 Binary files /dev/null and b/img/hd_cape.png differ diff --git a/index.html b/index.html index c20441a..b772508 100644 --- a/index.html +++ b/index.html @@ -1,66 +1,139 @@ + skinview3d examples + -
+
-

Animate: - - - - - -
- Global Animation Speed: x +

+ +
+

Animate

+ + + + + +
+
+ + Global Animation Speed: x -

-

Animation Mouse Control: - - - -

+
+

Animation Mouse Control

+ + + +
-

Width: - Height: - -

+
+

Canvas Size

+ Width: + Height: + +
-

Skin Url: - -
- Cape Url: - - -

+
+

Layers

-

All textures available to load: -

    -
  • img/1_8_texturemap_redux.png
  • -
  • img/cape.png
  • -
  • img/Hacksore.png
  • -
  • img/haka.png
  • -
  • img/hatsune_miku.png
  • -
  • img/ironman_hd.png
  • -
  • img/mojang_cape.png
  • -
  • img/sethbling.png
  • -
-

+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + +
+ +
+

Skin

+ +
+
+

Cape

+ +
+
- + - + + \ No newline at end of file diff --git a/js/build/revision b/js/build/revision deleted file mode 100644 index 519fc5d..0000000 --- a/js/build/revision +++ /dev/null @@ -1 +0,0 @@ -41b8ab9dab3b7d4d873ee8944cb783dee5b5a9ce diff --git a/js/build/skinview3d.js b/js/build/skinview3d.js deleted file mode 100644 index 6ec1718..0000000 --- a/js/build/skinview3d.js +++ /dev/null @@ -1,1440 +0,0 @@ -/** - * skinview3d (https://github.com/to2mbn/skinview3d) - * - * MIT License - * - * Copyright (c) 2014-2018 Kent Rasmussen - * Copyright (c) 2017-2018 Haowei Wen, Sean Boult and contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -(function (global, factory) { - typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('three')) : - typeof define === 'function' && define.amd ? define(['exports', 'three'], factory) : - (factory((global.skinview3d = {}),global.THREE)); -}(this, (function (exports,THREE) { 'use strict'; - - var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } - }; - - var createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; - }(); - - var inherits = function (subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true - } - }); - if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; - }; - - var possibleConstructorReturn = function (self, call) { - if (!self) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return call && (typeof call === "object" || typeof call === "function") ? call : self; - }; - - function toFaceVertices(x1, y1, x2, y2, w, h) { - return [new THREE.Vector2(x1 / w, 1.0 - y2 / h), new THREE.Vector2(x2 / w, 1.0 - y2 / h), new THREE.Vector2(x2 / w, 1.0 - y1 / h), new THREE.Vector2(x1 / w, 1.0 - y1 / h)]; - } - - function toSkinVertices(x1, y1, x2, y2) { - return toFaceVertices(x1, y1, x2, y2, 64.0, 64.0); - } - - function toCapeVertices(x1, y1, x2, y2) { - return toFaceVertices(x1, y1, x2, y2, 64.0, 32.0); - } - - function setVertices(box, top, bottom, left, front, right, back) { - box.faceVertexUvs[0] = []; - box.faceVertexUvs[0][0] = [right[3], right[0], right[2]]; - box.faceVertexUvs[0][1] = [right[0], right[1], right[2]]; - box.faceVertexUvs[0][2] = [left[3], left[0], left[2]]; - box.faceVertexUvs[0][3] = [left[0], left[1], left[2]]; - box.faceVertexUvs[0][4] = [top[3], top[0], top[2]]; - box.faceVertexUvs[0][5] = [top[0], top[1], top[2]]; - box.faceVertexUvs[0][6] = [bottom[0], bottom[3], bottom[1]]; - box.faceVertexUvs[0][7] = [bottom[3], bottom[2], bottom[1]]; - box.faceVertexUvs[0][8] = [front[3], front[0], front[2]]; - box.faceVertexUvs[0][9] = [front[0], front[1], front[2]]; - box.faceVertexUvs[0][10] = [back[3], back[0], back[2]]; - box.faceVertexUvs[0][11] = [back[0], back[1], back[2]]; - } - - var esp = 0.002; - - var SkinObject = function (_THREE$Group) { - inherits(SkinObject, _THREE$Group); - - function SkinObject(layer1Material, layer2Material) { - classCallCheck(this, SkinObject); - - var _this = possibleConstructorReturn(this, (SkinObject.__proto__ || Object.getPrototypeOf(SkinObject)).call(this)); - - _this.modelListeners = []; // called when model(slim property) is changed - - // Head - _this.head = new THREE.Group(); - - var headBox = new THREE.BoxGeometry(8, 8, 8, 0, 0, 0); - setVertices(headBox, toSkinVertices(8, 0, 16, 8), toSkinVertices(16, 0, 24, 8), toSkinVertices(0, 8, 8, 16), toSkinVertices(8, 8, 16, 16), toSkinVertices(16, 8, 24, 16), toSkinVertices(24, 8, 32, 16)); - var headMesh = new THREE.Mesh(headBox, layer1Material); - _this.head.add(headMesh); - - var head2Box = new THREE.BoxGeometry(9, 9, 9, 0, 0, 0); - setVertices(head2Box, toSkinVertices(40, 0, 48, 8), toSkinVertices(48, 0, 56, 8), toSkinVertices(32, 8, 40, 16), toSkinVertices(40, 8, 48, 16), toSkinVertices(48, 8, 56, 16), toSkinVertices(56, 8, 64, 16)); - var head2Mesh = new THREE.Mesh(head2Box, layer2Material); - head2Mesh.renderOrder = -1; - _this.head.add(head2Mesh); - - _this.add(_this.head); - - // Body - _this.body = new THREE.Group(); - - var bodyBox = new THREE.BoxGeometry(8, 12, 4, 0, 0, 0); - setVertices(bodyBox, toSkinVertices(20, 16, 28, 20), toSkinVertices(28, 16, 36, 20), toSkinVertices(16, 20, 20, 32), toSkinVertices(20, 20, 28, 32), toSkinVertices(28, 20, 32, 32), toSkinVertices(32, 20, 40, 32)); - var bodyMesh = new THREE.Mesh(bodyBox, layer1Material); - _this.body.add(bodyMesh); - - var body2Box = new THREE.BoxGeometry(9, 13.5, 4.5, 0, 0, 0); - setVertices(body2Box, toSkinVertices(20, 32, 28, 36), toSkinVertices(28, 32, 36, 36), toSkinVertices(16, 36, 20, 48), toSkinVertices(20, 36, 28, 48), toSkinVertices(28, 36, 32, 48), toSkinVertices(32, 36, 40, 48)); - var body2Mesh = new THREE.Mesh(body2Box, layer2Material); - _this.body.add(body2Mesh); - - _this.body.position.y = -10; - _this.add(_this.body); - - // Right Arm - _this.rightArm = new THREE.Group(); - var rightArmPivot = new THREE.Group(); - - var rightArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related - var rightArmMesh = new THREE.Mesh(rightArmBox, layer1Material); - rightArmPivot.add(rightArmMesh); - _this.modelListeners.push(function () { - rightArmMesh.scale.x = (_this.slim ? 3 : 4) - esp; - rightArmMesh.scale.y = 12 - esp; - rightArmMesh.scale.z = 4 - esp; - if (_this.slim) { - setVertices(rightArmBox, toSkinVertices(44, 16, 47, 20), toSkinVertices(47, 16, 50, 20), toSkinVertices(40, 20, 44, 32), toSkinVertices(44, 20, 47, 32), toSkinVertices(47, 20, 51, 32), toSkinVertices(51, 20, 54, 32)); - } else { - setVertices(rightArmBox, toSkinVertices(44, 16, 48, 20), toSkinVertices(48, 16, 52, 20), toSkinVertices(40, 20, 44, 32), toSkinVertices(44, 20, 48, 32), toSkinVertices(48, 20, 52, 32), toSkinVertices(52, 20, 56, 32)); - } - rightArmBox.uvsNeedUpdate = true; - rightArmBox.elementsNeedUpdate = true; - }); - - var rightArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related - var rightArm2Mesh = new THREE.Mesh(rightArm2Box, layer2Material); - rightArm2Mesh.renderOrder = 1; - rightArmPivot.add(rightArm2Mesh); - _this.modelListeners.push(function () { - rightArm2Mesh.scale.x = (_this.slim ? 3.375 : 4.5) - esp; - rightArm2Mesh.scale.y = 13.5 - esp; - rightArm2Mesh.scale.z = 4.5 - esp; - if (_this.slim) { - setVertices(rightArm2Box, toSkinVertices(44, 32, 47, 36), toSkinVertices(47, 32, 50, 36), toSkinVertices(40, 36, 44, 48), toSkinVertices(44, 36, 47, 48), toSkinVertices(47, 36, 51, 48), toSkinVertices(51, 36, 54, 48)); - } else { - setVertices(rightArm2Box, toSkinVertices(44, 32, 48, 36), toSkinVertices(48, 32, 52, 36), toSkinVertices(40, 36, 44, 48), toSkinVertices(44, 36, 48, 48), toSkinVertices(48, 36, 52, 48), toSkinVertices(52, 36, 56, 48)); - } - rightArm2Box.uvsNeedUpdate = true; - rightArm2Box.elementsNeedUpdate = true; - }); - - rightArmPivot.position.y = -6; - _this.rightArm.add(rightArmPivot); - _this.rightArm.position.y = -4; - _this.modelListeners.push(function () { - _this.rightArm.position.x = _this.slim ? -5.5 : -6; - }); - _this.add(_this.rightArm); - - // Left Arm - _this.leftArm = new THREE.Group(); - var leftArmPivot = new THREE.Group(); - - var leftArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related - var leftArmMesh = new THREE.Mesh(leftArmBox, layer1Material); - leftArmPivot.add(leftArmMesh); - _this.modelListeners.push(function () { - leftArmMesh.scale.x = (_this.slim ? 3 : 4) - esp; - leftArmMesh.scale.y = 12 - esp; - leftArmMesh.scale.z = 4 - esp; - if (_this.slim) { - setVertices(leftArmBox, toSkinVertices(36, 48, 39, 52), toSkinVertices(39, 48, 42, 52), toSkinVertices(32, 52, 36, 64), toSkinVertices(36, 52, 39, 64), toSkinVertices(39, 52, 43, 64), toSkinVertices(43, 52, 46, 64)); - } else { - setVertices(leftArmBox, toSkinVertices(36, 48, 40, 52), toSkinVertices(40, 48, 44, 52), toSkinVertices(32, 52, 36, 64), toSkinVertices(36, 52, 40, 64), toSkinVertices(40, 52, 44, 64), toSkinVertices(44, 52, 48, 64)); - } - leftArmBox.uvsNeedUpdate = true; - leftArmBox.elementsNeedUpdate = true; - }); - - var leftArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related - var leftArm2Mesh = new THREE.Mesh(leftArm2Box, layer2Material); - leftArm2Mesh.renderOrder = 1; - leftArmPivot.add(leftArm2Mesh); - _this.modelListeners.push(function () { - leftArm2Mesh.scale.x = (_this.slim ? 3.375 : 4.5) - esp; - leftArm2Mesh.scale.y = 13.5 - esp; - leftArm2Mesh.scale.z = 4.5 - esp; - if (_this.slim) { - setVertices(leftArm2Box, toSkinVertices(52, 48, 55, 52), toSkinVertices(55, 48, 58, 52), toSkinVertices(48, 52, 52, 64), toSkinVertices(52, 52, 55, 64), toSkinVertices(55, 52, 59, 64), toSkinVertices(59, 52, 62, 64)); - } else { - setVertices(leftArm2Box, toSkinVertices(52, 48, 56, 52), toSkinVertices(56, 48, 60, 52), toSkinVertices(48, 52, 52, 64), toSkinVertices(52, 52, 56, 64), toSkinVertices(56, 52, 60, 64), toSkinVertices(60, 52, 64, 64)); - } - leftArm2Box.uvsNeedUpdate = true; - leftArm2Box.elementsNeedUpdate = true; - }); - - leftArmPivot.position.y = -6; - _this.leftArm.add(leftArmPivot); - _this.leftArm.position.y = -4; - _this.modelListeners.push(function () { - _this.leftArm.position.x = _this.slim ? 5.5 : 6; - }); - _this.add(_this.leftArm); - - // Right Leg - _this.rightLeg = new THREE.Group(); - var rightLegPivot = new THREE.Group(); - - var rightLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0); - setVertices(rightLegBox, toSkinVertices(4, 16, 8, 20), toSkinVertices(8, 16, 12, 20), toSkinVertices(0, 20, 4, 32), toSkinVertices(4, 20, 8, 32), toSkinVertices(8, 20, 12, 32), toSkinVertices(12, 20, 16, 32)); - var rightLegMesh = new THREE.Mesh(rightLegBox, layer1Material); - rightLegPivot.add(rightLegMesh); - - var rightLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0); - setVertices(rightLeg2Box, toSkinVertices(4, 32, 8, 36), toSkinVertices(8, 32, 12, 36), toSkinVertices(0, 36, 4, 48), toSkinVertices(4, 36, 8, 48), toSkinVertices(8, 36, 12, 48), toSkinVertices(12, 36, 16, 48)); - var rightLeg2Mesh = new THREE.Mesh(rightLeg2Box, layer2Material); - rightLeg2Mesh.renderOrder = 1; - rightLegPivot.add(rightLeg2Mesh); - - rightLegPivot.position.y = -6; - _this.rightLeg.add(rightLegPivot); - _this.rightLeg.position.y = -16; - _this.rightLeg.position.x = -2; - _this.add(_this.rightLeg); - - // Left Leg - _this.leftLeg = new THREE.Group(); - var leftLegPivot = new THREE.Group(); - - var leftLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0); - setVertices(leftLegBox, toSkinVertices(20, 48, 24, 52), toSkinVertices(24, 48, 28, 52), toSkinVertices(16, 52, 20, 64), toSkinVertices(20, 52, 24, 64), toSkinVertices(24, 52, 28, 64), toSkinVertices(28, 52, 32, 64)); - var leftLegMesh = new THREE.Mesh(leftLegBox, layer1Material); - leftLegPivot.add(leftLegMesh); - - var leftLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0); - setVertices(leftLeg2Box, toSkinVertices(4, 48, 8, 52), toSkinVertices(8, 48, 12, 52), toSkinVertices(0, 52, 4, 64), toSkinVertices(4, 52, 8, 64), toSkinVertices(8, 52, 12, 64), toSkinVertices(12, 52, 16, 64)); - var leftLeg2Mesh = new THREE.Mesh(leftLeg2Box, layer2Material); - leftLeg2Mesh.renderOrder = 1; - leftLegPivot.add(leftLeg2Mesh); - - leftLegPivot.position.y = -6; - _this.leftLeg.add(leftLegPivot); - _this.leftLeg.position.y = -16; - _this.leftLeg.position.x = 2; - _this.add(_this.leftLeg); - - _this.slim = false; - return _this; - } - - createClass(SkinObject, [{ - key: "slim", - get: function get$$1() { - return this._slim; - }, - set: function set$$1(value) { - if (this._slim !== value) { - this._slim = value; - this.modelListeners.forEach(function (listener) { - return listener(); - }); - } - } - }]); - return SkinObject; - }(THREE.Group); - - var CapeObject = function (_THREE$Group2) { - inherits(CapeObject, _THREE$Group2); - - function CapeObject(capeMaterial) { - classCallCheck(this, CapeObject); - - // back = outside - // front = inside - var _this2 = possibleConstructorReturn(this, (CapeObject.__proto__ || Object.getPrototypeOf(CapeObject)).call(this)); - - var capeBox = new THREE.BoxGeometry(10, 16, 1, 0, 0, 0); - setVertices(capeBox, toCapeVertices(1, 0, 11, 1), toCapeVertices(11, 0, 21, 1), toCapeVertices(11, 1, 12, 17), toCapeVertices(12, 1, 22, 17), toCapeVertices(0, 1, 1, 17), toCapeVertices(1, 1, 11, 17)); - _this2.cape = new THREE.Mesh(capeBox, capeMaterial); - _this2.cape.position.y = -8; - _this2.cape.position.z = -0.5; - _this2.add(_this2.cape); - return _this2; - } - - return CapeObject; - }(THREE.Group); - - var PlayerObject = function (_THREE$Group3) { - inherits(PlayerObject, _THREE$Group3); - - function PlayerObject(layer1Material, layer2Material, capeMaterial) { - classCallCheck(this, PlayerObject); - - var _this3 = possibleConstructorReturn(this, (PlayerObject.__proto__ || Object.getPrototypeOf(PlayerObject)).call(this)); - - _this3.skin = new SkinObject(layer1Material, layer2Material); - _this3.skin.visible = false; - _this3.add(_this3.skin); - - _this3.cape = new CapeObject(capeMaterial); - _this3.cape.position.z = -2; - _this3.cape.position.y = -4; - _this3.cape.rotation.x = 25 * Math.PI / 180; - _this3.cape.visible = false; - _this3.add(_this3.cape); - return _this3; - } - - return PlayerObject; - }(THREE.Group); - - function invokeAnimation(animation, player, time) { - if (animation instanceof CompositeAnimation) { - animation.play(player, time); - } else if (animation instanceof Function) { - animation(player, time); - } else { - throw "Not an animation: " + animation; - } - } - - var AnimationHandle = function () { - function AnimationHandle(animation) { - classCallCheck(this, AnimationHandle); - - this.animation = animation; - this.paused = this._paused = false; - this.speed = this._speed = 1.0; - this._lastChange = null; - this._lastChangeX = null; - } - - createClass(AnimationHandle, [{ - key: "play", - value: function play(player, time) { - if (this._lastChange === null) { - this._lastChange = time; - this._lastChangeX = 0; - } else if (this.paused !== this._paused || this.speed !== this._speed) { - var dt = time - this._lastChange; - if (this._paused === false) { - this._lastChangeX += dt * this._speed; - } - this._paused = this.paused; - this._speed = this.speed; - this._lastChange = time; - } - if (this.paused === false) { - var _dt = time - this._lastChange; - var x = this._lastChangeX + this.speed * _dt; - invokeAnimation(this.animation, player, x); - } - } - }, { - key: "reset", - value: function reset() { - this._lastChange = null; - } - }]); - return AnimationHandle; - }(); - - var CompositeAnimation = function () { - function CompositeAnimation() { - classCallCheck(this, CompositeAnimation); - - this.handles = new Set(); - } - - createClass(CompositeAnimation, [{ - key: "add", - value: function add(animation) { - var _this = this; - - var handle = new AnimationHandle(animation); - handle.remove = function () { - return _this.handles.delete(handle); - }; - this.handles.add(handle); - return handle; - } - }, { - key: "play", - value: function play(player, time) { - this.handles.forEach(function (handle) { - return handle.play(player, time); - }); - } - }]); - return CompositeAnimation; - }(); - - var WalkingAnimation = function WalkingAnimation(player, time) { - var skin = player.skin; - - // Multiply by animation's natural speed - time *= 8; - - // Leg swing - skin.leftLeg.rotation.x = Math.sin(time) * 0.5; - skin.rightLeg.rotation.x = Math.sin(time + Math.PI) * 0.5; - - // Arm swing - skin.leftArm.rotation.x = Math.sin(time + Math.PI) * 0.5; - skin.rightArm.rotation.x = Math.sin(time) * 0.5; - var basicArmRotationZ = Math.PI * 0.02; - skin.leftArm.rotation.z = Math.cos(time) * 0.03 + basicArmRotationZ; - skin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.03 - basicArmRotationZ; - - // Head shaking with different frequency & amplitude - skin.head.rotation.y = Math.sin(time / 4) * 0.2; - skin.head.rotation.x = Math.sin(time / 5) * 0.1; - - // Always add an angle for cape around the x axis - var basicCapeRotationX = Math.PI * 0.06; - player.cape.rotation.x = Math.sin(time / 1.5) * 0.06 + basicCapeRotationX; - }; - - var RunningAnimation = function RunningAnimation(player, time) { - var skin = player.skin; - - time *= 15; - - // Leg swing with larger amplitude - skin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3; - skin.rightLeg.rotation.x = Math.cos(time) * 1.3; - - // Arm swing - skin.leftArm.rotation.x = Math.cos(time) * 1.5; - skin.rightArm.rotation.x = Math.cos(time + Math.PI) * 1.5; - var basicArmRotationZ = Math.PI * 0.1; - skin.leftArm.rotation.z = Math.cos(time) * 0.1 + basicArmRotationZ; - skin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.1 - basicArmRotationZ; - - // Jumping - player.position.y = Math.cos(time * 2); - // Dodging when running - player.position.x = Math.cos(time) * 0.15; - // Slightly tilting when running - player.rotation.z = Math.cos(time + Math.PI) * 0.01; - - // Apply higher swing frequency, lower amplitude, - // and greater basic rotation around x axis, - // to cape when running. - var basicCapeRotationX = Math.PI * 0.3; - player.cape.rotation.x = Math.sin(time * 2) * 0.1 + basicCapeRotationX; - - // What about head shaking? - // You shouldn't glance right and left when running dude :P - }; - - var RotatingAnimation = function RotatingAnimation(player, time) { - player.rotation.y = time; - }; - - function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) { - var imgData = context.getImageData(sX, sY, w, h); - if (flipHorizontal) { - for (var y = 0; y < h; y++) { - for (var x = 0; x < w / 2; x++) { - var index = (x + y * w) * 4; - var index2 = (w - x - 1 + y * w) * 4; - var pA1 = imgData.data[index]; - var pA2 = imgData.data[index + 1]; - var pA3 = imgData.data[index + 2]; - var pA4 = imgData.data[index + 3]; - - var pB1 = imgData.data[index2]; - var pB2 = imgData.data[index2 + 1]; - var pB3 = imgData.data[index2 + 2]; - var 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; - } - } - } - context.putImageData(imgData, dX, dY); - } - - function hasTransparency(context, x0, y0, w, h) { - var imgData = context.getImageData(x0, y0, w, h); - for (var x = 0; x < w; x++) { - for (var y = 0; y < h; y++) { - var offset = (x + y * w) * 4; - if (imgData.data[offset + 3] !== 0xff) { - return true; - } - } - } - return false; - } - - function computeSkinScale(width) { - return width / 64.0; - } - - function fixOpaqueSkin(context, width) { - // Some ancient skins don't have transparent pixels (nor have helm). - // We have to make the helm area transparent, otherwise it will be rendered as black. - if (!hasTransparency(context, 0, 0, width, width / 2)) { - var scale = computeSkinScale(width); - var clearArea = function clearArea(x, y, w, h) { - return context.clearRect(x * scale, y * scale, w * scale, h * scale); - }; - clearArea(40, 0, 8, 8); // Helm Top - clearArea(48, 0, 8, 8); // Helm Bottom - clearArea(32, 8, 8, 8); // Helm Right - clearArea(40, 8, 8, 8); // Helm Front - clearArea(48, 8, 8, 8); // Helm Left - clearArea(56, 8, 8, 8); // Helm Back - } - } - - function convertSkinTo1_8(context, width) { - var scale = computeSkinScale(width); - var copySkin = function copySkin(sX, sY, w, h, dX, dY, flipHorizontal) { - return copyImage(context, sX * scale, sY * scale, w * scale, h * scale, dX * scale, dY * scale, flipHorizontal); - }; - - fixOpaqueSkin(context, width); - - copySkin(4, 16, 4, 4, 20, 48, true); // Top Leg - copySkin(8, 16, 4, 4, 24, 48, true); // Bottom Leg - copySkin(0, 20, 4, 12, 24, 52, true); // Outer Leg - copySkin(4, 20, 4, 12, 20, 52, true); // Front Leg - copySkin(8, 20, 4, 12, 16, 52, true); // Inner Leg - copySkin(12, 20, 4, 12, 28, 52, true); // Back Leg - copySkin(44, 16, 4, 4, 36, 48, true); // Top Arm - copySkin(48, 16, 4, 4, 40, 48, true); // Bottom Arm - copySkin(40, 20, 4, 12, 40, 52, true); // Outer Arm - copySkin(44, 20, 4, 12, 36, 52, true); // Front Arm - copySkin(48, 20, 4, 12, 32, 52, true); // Inner Arm - copySkin(52, 20, 4, 12, 44, 52, true); // Back Arm - } - - function loadSkinToCanvas(canvas, image) { - var isOldFormat = false; - if (image.width !== image.height) { - if (image.width === 2 * image.height) { - isOldFormat = true; - } else { - throw "Bad skin size: " + image.width + "x" + image.height; - } - } - - var context = canvas.getContext("2d"); - if (isOldFormat) { - var sideLength = image.width; - canvas.width = sideLength; - canvas.height = sideLength; - context.clearRect(0, 0, sideLength, sideLength); - context.drawImage(image, 0, 0, sideLength, sideLength / 2.0); - convertSkinTo1_8(context, sideLength); - } else { - canvas.width = image.width; - canvas.height = image.height; - context.clearRect(0, 0, image.width, image.height); - context.drawImage(image, 0, 0, canvas.width, canvas.height); - } - } - - function loadCapeToCanvas(canvas, image) { - var isOldFormat = false; - if (image.width !== 2 * image.height) { - if (image.width * 17 == image.height * 22) { - // width/height = 22/17 - isOldFormat = true; - } else { - throw "Bad cape size: " + image.width + "x" + image.height; - } - } - - var context = canvas.getContext("2d"); - if (isOldFormat) { - var width = image.width * 64 / 22; - canvas.width = width; - canvas.height = width / 2; - } else { - canvas.width = image.width; - canvas.height = image.height; - } - context.clearRect(0, 0, canvas.width, canvas.height); - context.drawImage(image, 0, 0, image.width, image.height); - } - - function isSlimSkin(canvasOrImage) { - // Detects whether the skin is default or slim. - // - // The right arm area of *default* skins: - // (44,16)->*-------*-------* - // (40,20) |top |bottom | - // \|/ |4x4 |4x4 | - // *-------*-------*-------*-------* - // |right |front |left |back | - // |4x12 |4x12 |4x12 |4x12 | - // *-------*-------*-------*-------* - // The right arm area of *slim* skins: - // (44,16)->*------*------*-* - // (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4] - // \|/ |3x4 |3x4 | | - // *-------*------*------***-----*-* - // |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12] - // |4x12 |3x12 |4x12 |3x12 | | - // *-------*------*-------*------*-* - // Compared with default right arms, slim right arms have 2 unused areas. - // - // The same is true for left arm: - // The left arm area of *default* skins: - // (36,48)->*-------*-------* - // (32,52) |top |bottom | - // \|/ |4x4 |4x4 | - // *-------*-------*-------*-------* - // |right |front |left |back | - // |4x12 |4x12 |4x12 |4x12 | - // *-------*-------*-------*-------* - // The left arm area of *slim* skins: - // (36,48)->*------*------*-* - // (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4] - // \|/ |3x4 |3x4 | | - // *-------*------*------***-----*-* - // |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12] - // |4x12 |3x12 |4x12 |3x12 | | - // *-------*------*-------*------*-* - // - // If there is a transparent pixel in any of the 4 unused areas, the skin must be slim, - // as transparent pixels are not allowed in the first layer. - - if (canvasOrImage instanceof HTMLCanvasElement) { - var canvas = canvasOrImage; - var scale = computeSkinScale(canvas.width); - var context = canvas.getContext("2d"); - var checkArea = function checkArea(x, y, w, h) { - return hasTransparency(context, x * scale, y * scale, w * scale, h * scale); - }; - return checkArea(50, 16, 2, 4) || checkArea(54, 20, 2, 12) || checkArea(42, 48, 2, 4) || checkArea(46, 52, 2, 12); - } else if (canvasOrImage instanceof HTMLImageElement) { - var image = canvasOrImage; - var _canvas = document.createElement("canvas"); - loadSkinToCanvas(_canvas, image); - return isSlimSkin(_canvas); - } else { - throw "Illegal argument: " + canvasOrImage; - } - } - - var SkinViewer = function () { - function SkinViewer(options) { - var _this = this; - - classCallCheck(this, SkinViewer); - - this.domElement = options.domElement; - this.animation = options.animation || null; - this.detectModel = options.detectModel !== false; // true by default - this.animationPaused = false; - this.animationTime = 0; - this.disposed = false; - - // texture - this.skinImg = new Image(); - this.skinCanvas = document.createElement("canvas"); - this.skinTexture = new THREE.Texture(this.skinCanvas); - this.skinTexture.magFilter = THREE.NearestFilter; - this.skinTexture.minFilter = THREE.NearestFilter; - - this.capeImg = new Image(); - this.capeCanvas = document.createElement("canvas"); - this.capeTexture = new THREE.Texture(this.capeCanvas); - this.capeTexture.magFilter = THREE.NearestFilter; - this.capeTexture.minFilter = THREE.NearestFilter; - - this.layer1Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, side: THREE.FrontSide }); - this.layer2Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 }); - this.capeMaterial = new THREE.MeshBasicMaterial({ map: this.capeTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 }); - - // scene - this.scene = new THREE.Scene(); - - // Use smaller fov to avoid distortion - this.camera = new THREE.PerspectiveCamera(40); - this.camera.position.y = -12; - this.camera.position.z = 60; - - this.renderer = new THREE.WebGLRenderer({ angleRot: true, alpha: true, antialias: false }); - this.renderer.setSize(300, 300); // default size - this.renderer.context.getShaderInfoLog = function () { - return ""; - }; // shut firefox up - this.domElement.appendChild(this.renderer.domElement); - - this.playerObject = new PlayerObject(this.layer1Material, this.layer2Material, this.capeMaterial); - this.scene.add(this.playerObject); - - // texture loading - this.skinImg.crossOrigin = "anonymous"; - this.skinImg.onerror = function () { - return console.error("Failed loading " + _this.skinImg.src); - }; - this.skinImg.onload = function () { - loadSkinToCanvas(_this.skinCanvas, _this.skinImg); - - if (_this.detectModel) { - _this.playerObject.skin.slim = isSlimSkin(_this.skinCanvas); - } - - _this.skinTexture.needsUpdate = true; - _this.layer1Material.needsUpdate = true; - _this.layer2Material.needsUpdate = true; - - _this.playerObject.skin.visible = true; - }; - - this.capeImg.crossOrigin = "anonymous"; - this.capeImg.onerror = function () { - return console.error("Failed loading " + _this.capeImg.src); - }; - this.capeImg.onload = function () { - loadCapeToCanvas(_this.capeCanvas, _this.capeImg); - - _this.capeTexture.needsUpdate = true; - _this.capeMaterial.needsUpdate = true; - - _this.playerObject.cape.visible = true; - }; - - if (options.skinUrl) this.skinUrl = options.skinUrl; - if (options.capeUrl) this.capeUrl = options.capeUrl; - if (options.width) this.width = options.width; - if (options.height) this.height = options.height; - - var draw = function draw() { - if (_this.disposed) return; - window.requestAnimationFrame(draw); - if (!_this.animationPaused) { - _this.animationTime++; - if (_this.animation) { - invokeAnimation(_this.animation, _this.playerObject, _this.animationTime / 100.0); - } - } - _this.renderer.render(_this.scene, _this.camera); - }; - draw(); - } - - createClass(SkinViewer, [{ - key: "setSize", - value: function setSize(width, height) { - this.camera.aspect = width / height; - this.camera.updateProjectionMatrix(); - this.renderer.setSize(width, height); - } - }, { - key: "dispose", - value: function dispose() { - this.disposed = true; - this.domElement.removeChild(this.renderer.domElement); - this.renderer.dispose(); - this.skinTexture.dispose(); - this.capeTexture.dispose(); - } - }, { - key: "skinUrl", - get: function get$$1() { - return this.skinImg.src; - }, - set: function set$$1(url) { - this.skinImg.src = url; - } - }, { - key: "capeUrl", - get: function get$$1() { - return this.capeImg.src; - }, - set: function set$$1(url) { - this.capeImg.src = url; - } - }, { - key: "width", - get: function get$$1() { - return this.renderer.getSize().width; - }, - set: function set$$1(newWidth) { - this.setSize(newWidth, this.height); - } - }, { - key: "height", - get: function get$$1() { - return this.renderer.getSize().height; - }, - set: function set$$1(newHeight) { - this.setSize(this.width, newHeight); - } - }]); - return SkinViewer; - }(); - - var OrbitControls = function (_THREE$EventDispatche) { - inherits(OrbitControls, _THREE$EventDispatche); - - /** - * @preserve - * The code was originally from https://github.com/mrdoob/three.js/blob/d45a042cf962e9b1aa9441810ba118647b48aacb/examples/js/controls/OrbitControls.js - */ - /** - * @license - * Copyright (C) 2010-2017 three.js authors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * - * @author qiao / https://github.com/qiao - * @author mrdoob / http://mrdoob.com - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author erich666 / http://erichaines.com - */ - - // This set of controls performs orbiting, dollying (zooming), and panning. - // Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). - // - // Orbit - left mouse / touch: one finger move - // Zoom - middle mouse, or mousewheel / touch: two finger spread or squish - // Pan - right mouse, or arrow keys / touch: three finger swipe - - function OrbitControls(object, domElement) { - classCallCheck(this, OrbitControls); - - var _this = possibleConstructorReturn(this, (OrbitControls.__proto__ || Object.getPrototypeOf(OrbitControls)).call(this)); - - _this.object = object; - _this.domElement = domElement !== undefined ? domElement : document; - - // Set to false to disable this control - _this.enabled = true; - - // "target" sets the location of focus, where the object orbits around - _this.target = new THREE.Vector3(); - - // How far you can dolly in and out (PerspectiveCamera only) - _this.minDistance = 0; - _this.maxDistance = Infinity; - - // How far you can zoom in and out (OrthographicCamera only) - _this.minZoom = 0; - _this.maxZoom = Infinity; - - // How far you can orbit vertically, upper and lower limits. - // Range is 0 to Math.PI radians. - _this.minPolarAngle = 0; // radians - _this.maxPolarAngle = Math.PI; // radians - - // How far you can orbit horizontally, upper and lower limits. - // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. - _this.minAzimuthAngle = -Infinity; // radians - _this.maxAzimuthAngle = Infinity; // radians - - // Set to true to enable damping (inertia) - // If damping is enabled, you must call controls.update() in your animation loop - _this.enableDamping = false; - _this.dampingFactor = 0.25; - - // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. - // Set to false to disable zooming - _this.enableZoom = true; - _this.zoomSpeed = 1.0; - - // Set to false to disable rotating - _this.enableRotate = true; - _this.rotateSpeed = 1.0; - - // Set to false to disable panning - _this.enablePan = true; - _this.keyPanSpeed = 7.0; // pixels moved per arrow key push - - // Set to true to automatically rotate around the target - // If auto-rotate is enabled, you must call controls.update() in your animation loop - _this.autoRotate = false; - _this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 - - // Set to false to disable use of the keys - _this.enableKeys = true; - - // The four arrow keys - _this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; - - // Mouse buttons - _this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT }; - - // for reset - _this.target0 = _this.target.clone(); - _this.position0 = _this.object.position.clone(); - _this.zoom0 = _this.object.zoom; - - // - // public methods - // - _this.getPolarAngle = function () { - return spherical.phi; - }; - _this.getAzimuthalAngle = function () { - return spherical.theta; - }; - _this.saveState = function () { - scope.target0.copy(scope.target); - scope.position0.copy(scope.object.position); - scope.zoom0 = scope.object.zoom; - }; - _this.reset = function () { - scope.target.copy(scope.target0); - scope.object.position.copy(scope.position0); - scope.object.zoom = scope.zoom0; - scope.object.updateProjectionMatrix(); - scope.dispatchEvent(changeEvent); - scope.update(); - state = STATE.NONE; - }; - - // this method is exposed, but perhaps it would be better if we can make it private... - _this.update = function () { - var offset = new THREE.Vector3(); - // so camera.up is the orbit axis - var quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0)); - var quatInverse = quat.clone().inverse(); - var lastPosition = new THREE.Vector3(); - var lastQuaternion = new THREE.Quaternion(); - return function update() { - var position = scope.object.position; - offset.copy(position).sub(scope.target); - // rotate offset to "y-axis-is-up" space - offset.applyQuaternion(quat); - // angle from z-axis around y-axis - spherical.setFromVector3(offset); - if (scope.autoRotate && state === STATE.NONE) { - rotateLeft(getAutoRotationAngle()); - } - spherical.theta += sphericalDelta.theta; - spherical.phi += sphericalDelta.phi; - // restrict theta to be between desired limits - spherical.theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta)); - // restrict phi to be between desired limits - spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi)); - spherical.makeSafe(); - spherical.radius *= scale; - // restrict radius to be between desired limits - spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius)); - // move target to panned location - scope.target.add(panOffset); - offset.setFromSpherical(spherical); - // rotate offset back to "camera-up-vector-is-up" space - offset.applyQuaternion(quatInverse); - position.copy(scope.target).add(offset); - scope.object.lookAt(scope.target); - if (scope.enableDamping === true) { - sphericalDelta.theta *= 1 - scope.dampingFactor; - sphericalDelta.phi *= 1 - scope.dampingFactor; - } else { - sphericalDelta.set(0, 0, 0); - } - scale = 1; - panOffset.set(0, 0, 0); - // update condition is: - // min(camera displacement, camera rotation in radians)^2 > EPS - // using small-angle approximation cos(x/2) = 1 - x^2 / 8 - if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) { - scope.dispatchEvent(changeEvent); - lastPosition.copy(scope.object.position); - lastQuaternion.copy(scope.object.quaternion); - zoomChanged = false; - return true; - } - return false; - }; - }(); - _this.dispose = function () { - scope.domElement.removeEventListener("contextmenu", onContextMenu, false); - scope.domElement.removeEventListener("mousedown", onMouseDown, false); - scope.domElement.removeEventListener("wheel", onMouseWheel, false); - scope.domElement.removeEventListener("touchstart", onTouchStart, false); - scope.domElement.removeEventListener("touchend", onTouchEnd, false); - scope.domElement.removeEventListener("touchmove", onTouchMove, false); - document.removeEventListener("mousemove", onMouseMove, false); - document.removeEventListener("mouseup", onMouseUp, false); - window.removeEventListener("keydown", onKeyDown, false); - //scope.dispatchEvent({ type: "dispose" }); // should this be added here? - }; - // - // internals - // - var scope = _this; - var changeEvent = { type: "change" }; - var startEvent = { type: "start" }; - var endEvent = { type: "end" }; - var STATE = { NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 }; - var state = STATE.NONE; - var EPS = 0.000001; - // current position in spherical coordinates - var spherical = new THREE.Spherical(); - var sphericalDelta = new THREE.Spherical(); - var scale = 1; - var panOffset = new THREE.Vector3(); - var zoomChanged = false; - var rotateStart = new THREE.Vector2(); - var rotateEnd = new THREE.Vector2(); - var rotateDelta = new THREE.Vector2(); - var panStart = new THREE.Vector2(); - var panEnd = new THREE.Vector2(); - var panDelta = new THREE.Vector2(); - var dollyStart = new THREE.Vector2(); - var dollyEnd = new THREE.Vector2(); - var dollyDelta = new THREE.Vector2(); - function getAutoRotationAngle() { - return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; - } - function getZoomScale() { - return Math.pow(0.95, scope.zoomSpeed); - } - function rotateLeft(angle) { - sphericalDelta.theta -= angle; - } - function rotateUp(angle) { - sphericalDelta.phi -= angle; - } - var panLeft = function () { - var v = new THREE.Vector3(); - return function panLeft(distance, objectMatrix) { - v.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix - v.multiplyScalar(-distance); - panOffset.add(v); - }; - }(); - var panUp = function () { - var v = new THREE.Vector3(); - return function panUp(distance, objectMatrix) { - v.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix - v.multiplyScalar(distance); - panOffset.add(v); - }; - }(); - // deltaX and deltaY are in pixels; right and down are positive - var pan = function () { - var offset = new THREE.Vector3(); - return function pan(deltaX, deltaY) { - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - if (scope.object instanceof THREE.PerspectiveCamera) { - // perspective - var position = scope.object.position; - offset.copy(position).sub(scope.target); - var targetDistance = offset.length(); - // half of the fov is center to top of screen - targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180.0); - // we actually don't use screenWidth, since perspective camera is fixed to screen height - panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix); - panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix); - } else if (scope.object instanceof THREE.OrthographicCamera) { - // orthographic - panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix); - panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix); - } else { - // camera neither orthographic nor perspective - console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."); - scope.enablePan = false; - } - }; - }(); - function dollyIn(dollyScale) { - if (scope.object instanceof THREE.PerspectiveCamera) { - scale /= dollyScale; - } else if (scope.object instanceof THREE.OrthographicCamera) { - scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale)); - scope.object.updateProjectionMatrix(); - zoomChanged = true; - } else { - console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); - scope.enableZoom = false; - } - } - function dollyOut(dollyScale) { - if (scope.object instanceof THREE.PerspectiveCamera) { - scale *= dollyScale; - } else if (scope.object instanceof THREE.OrthographicCamera) { - scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale)); - scope.object.updateProjectionMatrix(); - zoomChanged = true; - } else { - console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); - scope.enableZoom = false; - } - } - // - // event callbacks - update the object state - // - function handleMouseDownRotate(event) { - rotateStart.set(event.clientX, event.clientY); - } - function handleMouseDownDolly(event) { - dollyStart.set(event.clientX, event.clientY); - } - function handleMouseDownPan(event) { - panStart.set(event.clientX, event.clientY); - } - function handleMouseMoveRotate(event) { - rotateEnd.set(event.clientX, event.clientY); - rotateDelta.subVectors(rotateEnd, rotateStart); - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - // rotating across whole screen goes 360 degrees around - rotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed); - // rotating up and down along whole screen attempts to go 360, but limited to 180 - rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed); - rotateStart.copy(rotateEnd); - scope.update(); - } - function handleMouseMoveDolly(event) { - dollyEnd.set(event.clientX, event.clientY); - dollyDelta.subVectors(dollyEnd, dollyStart); - if (dollyDelta.y > 0) { - dollyIn(getZoomScale()); - } else if (dollyDelta.y < 0) { - dollyOut(getZoomScale()); - } - dollyStart.copy(dollyEnd); - scope.update(); - } - function handleMouseMovePan(event) { - panEnd.set(event.clientX, event.clientY); - panDelta.subVectors(panEnd, panStart); - pan(panDelta.x, panDelta.y); - panStart.copy(panEnd); - scope.update(); - } - function handleMouseWheel(event) { - if (event.deltaY < 0) { - dollyOut(getZoomScale()); - } else if (event.deltaY > 0) { - dollyIn(getZoomScale()); - } - scope.update(); - } - function handleKeyDown(event) { - switch (event.keyCode) { - case scope.keys.UP: - pan(0, scope.keyPanSpeed); - scope.update(); - break; - case scope.keys.BOTTOM: - pan(0, -scope.keyPanSpeed); - scope.update(); - break; - case scope.keys.LEFT: - pan(scope.keyPanSpeed, 0); - scope.update(); - break; - case scope.keys.RIGHT: - pan(-scope.keyPanSpeed, 0); - scope.update(); - break; - } - } - function handleTouchStartRotate(event) { - rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); - } - function handleTouchStartDolly(event) { - var dx = event.touches[0].pageX - event.touches[1].pageX; - var dy = event.touches[0].pageY - event.touches[1].pageY; - var distance = Math.sqrt(dx * dx + dy * dy); - dollyStart.set(0, distance); - } - function handleTouchStartPan(event) { - panStart.set(event.touches[0].pageX, event.touches[0].pageY); - } - function handleTouchMoveRotate(event) { - rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); - rotateDelta.subVectors(rotateEnd, rotateStart); - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - rotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed); - rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed); - rotateStart.copy(rotateEnd); - scope.update(); - } - function handleTouchMoveDolly(event) { - var dx = event.touches[0].pageX - event.touches[1].pageX; - var dy = event.touches[0].pageY - event.touches[1].pageY; - var distance = Math.sqrt(dx * dx + dy * dy); - dollyEnd.set(0, distance); - dollyDelta.subVectors(dollyEnd, dollyStart); - if (dollyDelta.y > 0) { - dollyOut(getZoomScale()); - } else if (dollyDelta.y < 0) { - dollyIn(getZoomScale()); - } - dollyStart.copy(dollyEnd); - scope.update(); - } - function handleTouchMovePan(event) { - panEnd.set(event.touches[0].pageX, event.touches[0].pageY); - panDelta.subVectors(panEnd, panStart); - pan(panDelta.x, panDelta.y); - panStart.copy(panEnd); - scope.update(); - } - // - // event handlers - FSM: listen for events and reset state - // - function onMouseDown(event) { - if (scope.enabled === false) return; - switch (event.button) { - case scope.mouseButtons.ORBIT: - if (scope.enableRotate === false) return; - handleMouseDownRotate(event); - state = STATE.ROTATE; - break; - case scope.mouseButtons.ZOOM: - if (scope.enableZoom === false) return; - handleMouseDownDolly(event); - state = STATE.DOLLY; - break; - case scope.mouseButtons.PAN: - if (scope.enablePan === false) return; - handleMouseDownPan(event); - state = STATE.PAN; - break; - } - event.preventDefault(); - if (state !== STATE.NONE) { - document.addEventListener("mousemove", onMouseMove, false); - document.addEventListener("mouseup", onMouseUp, false); - scope.dispatchEvent(startEvent); - } - } - function onMouseMove(event) { - if (scope.enabled === false) return; - switch (state) { - case STATE.ROTATE: - if (scope.enableRotate === false) return; - handleMouseMoveRotate(event); - break; - case STATE.DOLLY: - if (scope.enableZoom === false) return; - handleMouseMoveDolly(event); - break; - case STATE.PAN: - if (scope.enablePan === false) return; - handleMouseMovePan(event); - break; - } - event.preventDefault(); - } - function onMouseUp(event) { - if (scope.enabled === false) return; - document.removeEventListener("mousemove", onMouseMove, false); - document.removeEventListener("mouseup", onMouseUp, false); - scope.dispatchEvent(endEvent); - state = STATE.NONE; - } - function onMouseWheel(event) { - if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE && state !== STATE.ROTATE) return; - event.preventDefault(); - event.stopPropagation(); - handleMouseWheel(event); - scope.dispatchEvent(startEvent); // not sure why these are here... - scope.dispatchEvent(endEvent); - } - function onKeyDown(event) { - if (scope.enabled === false || scope.enableKeys === false || scope.enablePan === false) return; - handleKeyDown(event); - } - function onTouchStart(event) { - if (scope.enabled === false) return; - switch (event.touches.length) { - case 1: - // one-fingered touch: rotate - if (scope.enableRotate === false) return; - handleTouchStartRotate(event); - state = STATE.TOUCH_ROTATE; - break; - case 2: - // two-fingered touch: dolly - if (scope.enableZoom === false) return; - handleTouchStartDolly(event); - state = STATE.TOUCH_DOLLY; - break; - case 3: - // three-fingered touch: pan - if (scope.enablePan === false) return; - handleTouchStartPan(event); - state = STATE.TOUCH_PAN; - break; - default: - state = STATE.NONE; - } - if (state !== STATE.NONE) { - scope.dispatchEvent(startEvent); - } - } - function onTouchMove(event) { - if (scope.enabled === false) return; - switch (event.touches.length) { - case 1: - // one-fingered touch: rotate - if (scope.enableRotate === false) return; - if (state !== STATE.TOUCH_ROTATE) return; // is this needed?... - handleTouchMoveRotate(event); - break; - case 2: - // two-fingered touch: dolly - if (scope.enableZoom === false) return; - if (state !== STATE.TOUCH_DOLLY) return; // is this needed?... - handleTouchMoveDolly(event); - break; - case 3: - // three-fingered touch: pan - if (scope.enablePan === false) return; - if (state !== STATE.TOUCH_PAN) return; // is this needed?... - handleTouchMovePan(event); - break; - default: - state = STATE.NONE; - } - event.preventDefault(); - event.stopPropagation(); - } - function onTouchEnd(event) { - if (scope.enabled === false) return; - scope.dispatchEvent(endEvent); - state = STATE.NONE; - } - function onContextMenu(event) { - if (scope.enabled === false || scope.enablePan === false) return; - event.preventDefault(); - } - // - scope.domElement.addEventListener("contextmenu", onContextMenu, false); - scope.domElement.addEventListener("mousedown", onMouseDown, false); - scope.domElement.addEventListener("wheel", onMouseWheel, false); - scope.domElement.addEventListener("touchstart", onTouchStart, false); - scope.domElement.addEventListener("touchend", onTouchEnd, false); - scope.domElement.addEventListener("touchmove", onTouchMove, false); - window.addEventListener("keydown", onKeyDown, false); - // force an update at start - _this.update(); - return _this; - } - - return OrbitControls; - }(THREE.EventDispatcher); - - function createOrbitControls(skinViewer) { - var control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement); - - // default configuration - control.enablePan = false; - control.target = new THREE.Vector3(0, -12, 0); - control.minDistance = 10; - control.maxDistance = 256; - control.update(); - - return control; - } - - exports.SkinObject = SkinObject; - exports.CapeObject = CapeObject; - exports.PlayerObject = PlayerObject; - exports.SkinViewer = SkinViewer; - exports.OrbitControls = OrbitControls; - exports.createOrbitControls = createOrbitControls; - exports.invokeAnimation = invokeAnimation; - exports.CompositeAnimation = CompositeAnimation; - exports.WalkingAnimation = WalkingAnimation; - exports.RunningAnimation = RunningAnimation; - exports.RotatingAnimation = RotatingAnimation; - exports.isSlimSkin = isSlimSkin; - - Object.defineProperty(exports, '__esModule', { value: true }); - -}))); -//# sourceMappingURL=skinview3d.js.map diff --git a/js/build/skinview3d.js.map b/js/build/skinview3d.js.map deleted file mode 100644 index e4874bc..0000000 --- a/js/build/skinview3d.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"skinview3d.js","sources":["../src/model.js","../src/animation.js","../src/utils.js","../src/viewer.js","../src/orbit_controls.js"],"sourcesContent":["import * as THREE from \"three\";\n\nfunction toFaceVertices(x1, y1, x2, y2, w, h) {\n\treturn [\n\t\tnew THREE.Vector2(x1 / w, 1.0 - y2 / h),\n\t\tnew THREE.Vector2(x2 / w, 1.0 - y2 / h),\n\t\tnew THREE.Vector2(x2 / w, 1.0 - y1 / h),\n\t\tnew THREE.Vector2(x1 / w, 1.0 - y1 / h)\n\t];\n}\n\nfunction toSkinVertices(x1, y1, x2, y2) {\n\treturn toFaceVertices(x1, y1, x2, y2, 64.0, 64.0);\n}\n\nfunction toCapeVertices(x1, y1, x2, y2) {\n\treturn toFaceVertices(x1, y1, x2, y2, 64.0, 32.0);\n}\n\nfunction setVertices(box, top, bottom, left, front, right, back) {\n\tbox.faceVertexUvs[0] = [];\n\tbox.faceVertexUvs[0][0] = [right[3], right[0], right[2]];\n\tbox.faceVertexUvs[0][1] = [right[0], right[1], right[2]];\n\tbox.faceVertexUvs[0][2] = [left[3], left[0], left[2]];\n\tbox.faceVertexUvs[0][3] = [left[0], left[1], left[2]];\n\tbox.faceVertexUvs[0][4] = [top[3], top[0], top[2]];\n\tbox.faceVertexUvs[0][5] = [top[0], top[1], top[2]];\n\tbox.faceVertexUvs[0][6] = [bottom[0], bottom[3], bottom[1]];\n\tbox.faceVertexUvs[0][7] = [bottom[3], bottom[2], bottom[1]];\n\tbox.faceVertexUvs[0][8] = [front[3], front[0], front[2]];\n\tbox.faceVertexUvs[0][9] = [front[0], front[1], front[2]];\n\tbox.faceVertexUvs[0][10] = [back[3], back[0], back[2]];\n\tbox.faceVertexUvs[0][11] = [back[0], back[1], back[2]];\n}\n\nconst esp = 0.002;\n\nclass SkinObject extends THREE.Group {\n\tconstructor(layer1Material, layer2Material) {\n\t\tsuper();\n\n\t\tthis.modelListeners = []; // called when model(slim property) is changed\n\n\t\t// Head\n\t\tthis.head = new THREE.Group();\n\n\t\tlet headBox = new THREE.BoxGeometry(8, 8, 8, 0, 0, 0);\n\t\tsetVertices(headBox,\n\t\t\ttoSkinVertices(8, 0, 16, 8),\n\t\t\ttoSkinVertices(16, 0, 24, 8),\n\t\t\ttoSkinVertices(0, 8, 8, 16),\n\t\t\ttoSkinVertices(8, 8, 16, 16),\n\t\t\ttoSkinVertices(16, 8, 24, 16),\n\t\t\ttoSkinVertices(24, 8, 32, 16)\n\t\t);\n\t\tlet headMesh = new THREE.Mesh(headBox, layer1Material);\n\t\tthis.head.add(headMesh);\n\n\t\tlet head2Box = new THREE.BoxGeometry(9, 9, 9, 0, 0, 0);\n\t\tsetVertices(head2Box,\n\t\t\ttoSkinVertices(40, 0, 48, 8),\n\t\t\ttoSkinVertices(48, 0, 56, 8),\n\t\t\ttoSkinVertices(32, 8, 40, 16),\n\t\t\ttoSkinVertices(40, 8, 48, 16),\n\t\t\ttoSkinVertices(48, 8, 56, 16),\n\t\t\ttoSkinVertices(56, 8, 64, 16)\n\t\t);\n\t\tlet head2Mesh = new THREE.Mesh(head2Box, layer2Material);\n\t\thead2Mesh.renderOrder = -1;\n\t\tthis.head.add(head2Mesh);\n\n\t\tthis.add(this.head);\n\n\n\t\t// Body\n\t\tthis.body = new THREE.Group();\n\n\t\tlet bodyBox = new THREE.BoxGeometry(8, 12, 4, 0, 0, 0);\n\t\tsetVertices(bodyBox,\n\t\t\ttoSkinVertices(20, 16, 28, 20),\n\t\t\ttoSkinVertices(28, 16, 36, 20),\n\t\t\ttoSkinVertices(16, 20, 20, 32),\n\t\t\ttoSkinVertices(20, 20, 28, 32),\n\t\t\ttoSkinVertices(28, 20, 32, 32),\n\t\t\ttoSkinVertices(32, 20, 40, 32)\n\t\t);\n\t\tlet bodyMesh = new THREE.Mesh(bodyBox, layer1Material);\n\t\tthis.body.add(bodyMesh);\n\n\t\tlet body2Box = new THREE.BoxGeometry(9, 13.5, 4.5, 0, 0, 0);\n\t\tsetVertices(body2Box,\n\t\t\ttoSkinVertices(20, 32, 28, 36),\n\t\t\ttoSkinVertices(28, 32, 36, 36),\n\t\t\ttoSkinVertices(16, 36, 20, 48),\n\t\t\ttoSkinVertices(20, 36, 28, 48),\n\t\t\ttoSkinVertices(28, 36, 32, 48),\n\t\t\ttoSkinVertices(32, 36, 40, 48)\n\t\t);\n\t\tlet body2Mesh = new THREE.Mesh(body2Box, layer2Material);\n\t\tthis.body.add(body2Mesh);\n\n\t\tthis.body.position.y = -10;\n\t\tthis.add(this.body);\n\n\n\t\t// Right Arm\n\t\tthis.rightArm = new THREE.Group();\n\t\tlet rightArmPivot = new THREE.Group();\n\n\t\tlet rightArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet rightArmMesh = new THREE.Mesh(rightArmBox, layer1Material);\n\t\trightArmPivot.add(rightArmMesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\trightArmMesh.scale.x = (this.slim ? 3 : 4) - esp;\n\t\t\trightArmMesh.scale.y = 12 - esp;\n\t\t\trightArmMesh.scale.z = 4 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(rightArmBox,\n\t\t\t\t\ttoSkinVertices(44, 16, 47, 20),\n\t\t\t\t\ttoSkinVertices(47, 16, 50, 20),\n\t\t\t\t\ttoSkinVertices(40, 20, 44, 32),\n\t\t\t\t\ttoSkinVertices(44, 20, 47, 32),\n\t\t\t\t\ttoSkinVertices(47, 20, 51, 32),\n\t\t\t\t\ttoSkinVertices(51, 20, 54, 32)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(rightArmBox,\n\t\t\t\t\ttoSkinVertices(44, 16, 48, 20),\n\t\t\t\t\ttoSkinVertices(48, 16, 52, 20),\n\t\t\t\t\ttoSkinVertices(40, 20, 44, 32),\n\t\t\t\t\ttoSkinVertices(44, 20, 48, 32),\n\t\t\t\t\ttoSkinVertices(48, 20, 52, 32),\n\t\t\t\t\ttoSkinVertices(52, 20, 56, 32)\n\t\t\t\t);\n\t\t\t}\n\t\t\trightArmBox.uvsNeedUpdate = true;\n\t\t\trightArmBox.elementsNeedUpdate = true;\n\t\t});\n\n\t\tlet rightArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet rightArm2Mesh = new THREE.Mesh(rightArm2Box, layer2Material);\n\t\trightArm2Mesh.renderOrder = 1;\n\t\trightArmPivot.add(rightArm2Mesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\trightArm2Mesh.scale.x = (this.slim ? 3.375 : 4.5) - esp;\n\t\t\trightArm2Mesh.scale.y = 13.5 - esp;\n\t\t\trightArm2Mesh.scale.z = 4.5 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(rightArm2Box,\n\t\t\t\t\ttoSkinVertices(44, 32, 47, 36),\n\t\t\t\t\ttoSkinVertices(47, 32, 50, 36),\n\t\t\t\t\ttoSkinVertices(40, 36, 44, 48),\n\t\t\t\t\ttoSkinVertices(44, 36, 47, 48),\n\t\t\t\t\ttoSkinVertices(47, 36, 51, 48),\n\t\t\t\t\ttoSkinVertices(51, 36, 54, 48)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(rightArm2Box,\n\t\t\t\t\ttoSkinVertices(44, 32, 48, 36),\n\t\t\t\t\ttoSkinVertices(48, 32, 52, 36),\n\t\t\t\t\ttoSkinVertices(40, 36, 44, 48),\n\t\t\t\t\ttoSkinVertices(44, 36, 48, 48),\n\t\t\t\t\ttoSkinVertices(48, 36, 52, 48),\n\t\t\t\t\ttoSkinVertices(52, 36, 56, 48)\n\t\t\t\t);\n\t\t\t}\n\t\t\trightArm2Box.uvsNeedUpdate = true;\n\t\t\trightArm2Box.elementsNeedUpdate = true;\n\t\t});\n\n\t\trightArmPivot.position.y = -6;\n\t\tthis.rightArm.add(rightArmPivot);\n\t\tthis.rightArm.position.y = -4;\n\t\tthis.modelListeners.push(() => {\n\t\t\tthis.rightArm.position.x = this.slim ? -5.5 : -6;\n\t\t});\n\t\tthis.add(this.rightArm);\n\n\n\t\t// Left Arm\n\t\tthis.leftArm = new THREE.Group();\n\t\tlet leftArmPivot = new THREE.Group();\n\n\t\tlet leftArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet leftArmMesh = new THREE.Mesh(leftArmBox, layer1Material);\n\t\tleftArmPivot.add(leftArmMesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\tleftArmMesh.scale.x = (this.slim ? 3 : 4) - esp;\n\t\t\tleftArmMesh.scale.y = 12 - esp;\n\t\t\tleftArmMesh.scale.z = 4 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(leftArmBox,\n\t\t\t\t\ttoSkinVertices(36, 48, 39, 52),\n\t\t\t\t\ttoSkinVertices(39, 48, 42, 52),\n\t\t\t\t\ttoSkinVertices(32, 52, 36, 64),\n\t\t\t\t\ttoSkinVertices(36, 52, 39, 64),\n\t\t\t\t\ttoSkinVertices(39, 52, 43, 64),\n\t\t\t\t\ttoSkinVertices(43, 52, 46, 64)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(leftArmBox,\n\t\t\t\t\ttoSkinVertices(36, 48, 40, 52),\n\t\t\t\t\ttoSkinVertices(40, 48, 44, 52),\n\t\t\t\t\ttoSkinVertices(32, 52, 36, 64),\n\t\t\t\t\ttoSkinVertices(36, 52, 40, 64),\n\t\t\t\t\ttoSkinVertices(40, 52, 44, 64),\n\t\t\t\t\ttoSkinVertices(44, 52, 48, 64)\n\t\t\t\t);\n\t\t\t}\n\t\t\tleftArmBox.uvsNeedUpdate = true;\n\t\t\tleftArmBox.elementsNeedUpdate=true;\n\t\t});\n\n\t\tlet leftArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet leftArm2Mesh = new THREE.Mesh(leftArm2Box, layer2Material);\n\t\tleftArm2Mesh.renderOrder = 1;\n\t\tleftArmPivot.add(leftArm2Mesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\tleftArm2Mesh.scale.x = (this.slim ? 3.375 : 4.5) - esp;\n\t\t\tleftArm2Mesh.scale.y = 13.5 - esp;\n\t\t\tleftArm2Mesh.scale.z = 4.5 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(leftArm2Box,\n\t\t\t\t\ttoSkinVertices(52, 48, 55, 52),\n\t\t\t\t\ttoSkinVertices(55, 48, 58, 52),\n\t\t\t\t\ttoSkinVertices(48, 52, 52, 64),\n\t\t\t\t\ttoSkinVertices(52, 52, 55, 64),\n\t\t\t\t\ttoSkinVertices(55, 52, 59, 64),\n\t\t\t\t\ttoSkinVertices(59, 52, 62, 64)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(leftArm2Box,\n\t\t\t\t\ttoSkinVertices(52, 48, 56, 52),\n\t\t\t\t\ttoSkinVertices(56, 48, 60, 52),\n\t\t\t\t\ttoSkinVertices(48, 52, 52, 64),\n\t\t\t\t\ttoSkinVertices(52, 52, 56, 64),\n\t\t\t\t\ttoSkinVertices(56, 52, 60, 64),\n\t\t\t\t\ttoSkinVertices(60, 52, 64, 64)\n\t\t\t\t);\n\t\t\t}\n\t\t\tleftArm2Box.uvsNeedUpdate = true;\n\t\t\tleftArm2Box.elementsNeedUpdate = true;\n\t\t});\n\n\t\tleftArmPivot.position.y = -6;\n\t\tthis.leftArm.add(leftArmPivot);\n\t\tthis.leftArm.position.y = -4;\n\t\tthis.modelListeners.push(() => {\n\t\t\tthis.leftArm.position.x = this.slim ? 5.5 : 6;\n\t\t});\n\t\tthis.add(this.leftArm);\n\n\n\t\t// Right Leg\n\t\tthis.rightLeg = new THREE.Group();\n\t\tlet rightLegPivot = new THREE.Group();\n\n\t\tlet rightLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0);\n\t\tsetVertices(rightLegBox,\n\t\t\ttoSkinVertices(4, 16, 8, 20),\n\t\t\ttoSkinVertices(8, 16, 12, 20),\n\t\t\ttoSkinVertices(0, 20, 4, 32),\n\t\t\ttoSkinVertices(4, 20, 8, 32),\n\t\t\ttoSkinVertices(8, 20, 12, 32),\n\t\t\ttoSkinVertices(12, 20, 16, 32)\n\t\t);\n\t\tlet rightLegMesh = new THREE.Mesh(rightLegBox, layer1Material);\n\t\trightLegPivot.add(rightLegMesh);\n\n\t\tlet rightLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0);\n\t\tsetVertices(rightLeg2Box,\n\t\t\ttoSkinVertices(4, 32, 8, 36),\n\t\t\ttoSkinVertices(8, 32, 12, 36),\n\t\t\ttoSkinVertices(0, 36, 4, 48),\n\t\t\ttoSkinVertices(4, 36, 8, 48),\n\t\t\ttoSkinVertices(8, 36, 12, 48),\n\t\t\ttoSkinVertices(12, 36, 16, 48)\n\t\t);\n\t\tlet rightLeg2Mesh = new THREE.Mesh(rightLeg2Box, layer2Material);\n\t\trightLeg2Mesh.renderOrder = 1;\n\t\trightLegPivot.add(rightLeg2Mesh);\n\n\t\trightLegPivot.position.y = -6;\n\t\tthis.rightLeg.add(rightLegPivot);\n\t\tthis.rightLeg.position.y = -16;\n\t\tthis.rightLeg.position.x = -2;\n\t\tthis.add(this.rightLeg);\n\n\t\t// Left Leg\n\t\tthis.leftLeg = new THREE.Group();\n\t\tlet leftLegPivot = new THREE.Group();\n\n\t\tlet leftLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0);\n\t\tsetVertices(leftLegBox,\n\t\t\ttoSkinVertices(20, 48, 24, 52),\n\t\t\ttoSkinVertices(24, 48, 28, 52),\n\t\t\ttoSkinVertices(16, 52, 20, 64),\n\t\t\ttoSkinVertices(20, 52, 24, 64),\n\t\t\ttoSkinVertices(24, 52, 28, 64),\n\t\t\ttoSkinVertices(28, 52, 32, 64)\n\t\t);\n\t\tlet leftLegMesh = new THREE.Mesh(leftLegBox, layer1Material);\n\t\tleftLegPivot.add(leftLegMesh);\n\n\t\tlet leftLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0);\n\t\tsetVertices(leftLeg2Box,\n\t\t\ttoSkinVertices(4, 48, 8, 52),\n\t\t\ttoSkinVertices(8, 48, 12, 52),\n\t\t\ttoSkinVertices(0, 52, 4, 64),\n\t\t\ttoSkinVertices(4, 52, 8, 64),\n\t\t\ttoSkinVertices(8, 52, 12, 64),\n\t\t\ttoSkinVertices(12, 52, 16, 64)\n\t\t);\n\t\tlet leftLeg2Mesh = new THREE.Mesh(leftLeg2Box, layer2Material);\n\t\tleftLeg2Mesh.renderOrder = 1;\n\t\tleftLegPivot.add(leftLeg2Mesh);\n\n\t\tleftLegPivot.position.y = -6;\n\t\tthis.leftLeg.add(leftLegPivot);\n\t\tthis.leftLeg.position.y = -16;\n\t\tthis.leftLeg.position.x = 2;\n\t\tthis.add(this.leftLeg);\n\n\t\tthis.slim = false;\n\t}\n\n\tget slim() {\n\t\treturn this._slim;\n\t}\n\n\tset slim(value) {\n\t\tif (this._slim !== value) {\n\t\t\tthis._slim = value;\n\t\t\tthis.modelListeners.forEach(listener => listener());\n\t\t}\n\t}\n}\n\nclass CapeObject extends THREE.Group {\n\tconstructor(capeMaterial) {\n\t\tsuper();\n\n\t\t// back = outside\n\t\t// front = inside\n\t\tlet capeBox = new THREE.BoxGeometry(10, 16, 1, 0, 0, 0);\n\t\tsetVertices(capeBox,\n\t\t\ttoCapeVertices(1, 0, 11, 1),\n\t\t\ttoCapeVertices(11, 0, 21, 1),\n\t\t\ttoCapeVertices(11, 1, 12, 17),\n\t\t\ttoCapeVertices(12, 1, 22, 17),\n\t\t\ttoCapeVertices(0, 1, 1, 17),\n\t\t\ttoCapeVertices(1, 1, 11, 17)\n\t\t);\n\t\tthis.cape = new THREE.Mesh(capeBox, capeMaterial);\n\t\tthis.cape.position.y = -8;\n\t\tthis.cape.position.z = -0.5;\n\t\tthis.add(this.cape);\n\t}\n}\n\nclass PlayerObject extends THREE.Group {\n\tconstructor(layer1Material, layer2Material, capeMaterial) {\n\t\tsuper();\n\n\t\tthis.skin = new SkinObject(layer1Material, layer2Material);\n\t\tthis.skin.visible = false;\n\t\tthis.add(this.skin);\n\n\t\tthis.cape = new CapeObject(capeMaterial);\n\t\tthis.cape.position.z = -2;\n\t\tthis.cape.position.y = -4;\n\t\tthis.cape.rotation.x = 25 * Math.PI / 180;\n\t\tthis.cape.visible = false;\n\t\tthis.add(this.cape);\n\t}\n}\n\nexport { SkinObject, CapeObject, PlayerObject };\n","function invokeAnimation(animation, player, time) {\n\tif (animation instanceof CompositeAnimation) {\n\t\tanimation.play(player, time);\n\t} else if (animation instanceof Function) {\n\t\tanimation(player, time);\n\t} else {\n\t\tthrow `Not an animation: ${animation}`;\n\t}\n}\n\nclass AnimationHandle {\n\tconstructor(animation) {\n\t\tthis.animation = animation;\n\t\tthis.paused = this._paused = false;\n\t\tthis.speed = this._speed = 1.0;\n\t\tthis._lastChange = null;\n\t\tthis._lastChangeX = null;\n\t}\n\tplay(player, time) {\n\t\tif (this._lastChange === null) {\n\t\t\tthis._lastChange = time;\n\t\t\tthis._lastChangeX = 0;\n\t\t} else if (this.paused !== this._paused || this.speed !== this._speed) {\n\t\t\tlet dt = time - this._lastChange;\n\t\t\tif (this._paused === false) {\n\t\t\t\tthis._lastChangeX += dt * this._speed;\n\t\t\t}\n\t\t\tthis._paused = this.paused;\n\t\t\tthis._speed = this.speed;\n\t\t\tthis._lastChange = time;\n\t\t}\n\t\tif (this.paused === false) {\n\t\t\tlet dt = time - this._lastChange;\n\t\t\tlet x = this._lastChangeX + this.speed * dt;\n\t\t\tinvokeAnimation(this.animation, player, x);\n\t\t}\n\t}\n\treset(){\n\t\tthis._lastChange = null;\n\t}\n}\n\nclass CompositeAnimation {\n\tconstructor() {\n\t\tthis.handles = new Set();\n\t}\n\tadd(animation) {\n\t\tlet handle = new AnimationHandle(animation);\n\t\thandle.remove = () => this.handles.delete(handle);\n\t\tthis.handles.add(handle);\n\t\treturn handle;\n\t}\n\tplay(player, time) {\n\t\tthis.handles.forEach(handle => handle.play(player, time));\n\t}\n}\n\nlet WalkingAnimation = (player, time) => {\n\tlet skin = player.skin;\n\n\t// Multiply by animation's natural speed\n\ttime *= 8;\n\n\t// Leg swing\n\tskin.leftLeg.rotation.x = Math.sin(time) * 0.5;\n\tskin.rightLeg.rotation.x = Math.sin(time + Math.PI) * 0.5;\n\n\t// Arm swing\n\tskin.leftArm.rotation.x = Math.sin(time + Math.PI) * 0.5;\n\tskin.rightArm.rotation.x = Math.sin(time) * 0.5;\n\tlet basicArmRotationZ = Math.PI * 0.02;\n\tskin.leftArm.rotation.z = Math.cos(time) * 0.03 + basicArmRotationZ;\n\tskin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.03 - basicArmRotationZ;\n\n\t// Head shaking with different frequency & amplitude\n\tskin.head.rotation.y = Math.sin(time / 4) * 0.2;\n\tskin.head.rotation.x = Math.sin(time / 5) * 0.1;\n\n\t// Always add an angle for cape around the x axis\n\tlet basicCapeRotationX = Math.PI * 0.06;\n\tplayer.cape.rotation.x = Math.sin(time / 1.5) * 0.06 + basicCapeRotationX;\n};\n\nlet RunningAnimation = (player, time) => {\n\tlet skin = player.skin;\n\n\ttime *= 15;\n\n\t// Leg swing with larger amplitude\n\tskin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3;\n\tskin.rightLeg.rotation.x = Math.cos(time) * 1.3;\n\n\t// Arm swing\n\tskin.leftArm.rotation.x = Math.cos(time) * 1.5;\n\tskin.rightArm.rotation.x = Math.cos(time + Math.PI) * 1.5;\n\tlet basicArmRotationZ = Math.PI * 0.1;\n\tskin.leftArm.rotation.z = Math.cos(time) * 0.1 + basicArmRotationZ;\n\tskin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.1 - basicArmRotationZ;\n\n\t// Jumping\n\tplayer.position.y = Math.cos(time * 2);\n\t// Dodging when running\n\tplayer.position.x = Math.cos(time) * 0.15;\n\t// Slightly tilting when running\n\tplayer.rotation.z = Math.cos(time + Math.PI) * 0.01;\n\n\t// Apply higher swing frequency, lower amplitude,\n\t// and greater basic rotation around x axis,\n\t// to cape when running.\n\tlet basicCapeRotationX = Math.PI * 0.3;\n\tplayer.cape.rotation.x = Math.sin(time * 2) * 0.1 + basicCapeRotationX;\n\n\t// What about head shaking?\n\t// You shouldn't glance right and left when running dude :P\n};\n\nlet RotatingAnimation = (player, time) => {\n\tplayer.rotation.y = time;\n};\n\nexport {\n\tCompositeAnimation,\n\tinvokeAnimation,\n\tWalkingAnimation,\n\tRunningAnimation,\n\tRotatingAnimation\n};\n","function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) {\n\tlet imgData = context.getImageData(sX, sY, w, h);\n\tif (flipHorizontal) {\n\t\tfor (let y = 0; y < h; y++) {\n\t\t\tfor (let x = 0; x < (w / 2); x++) {\n\t\t\t\tlet index = (x + y * w) * 4;\n\t\t\t\tlet index2 = ((w - x - 1) + y * w) * 4;\n\t\t\t\tlet pA1 = imgData.data[index];\n\t\t\t\tlet pA2 = imgData.data[index + 1];\n\t\t\t\tlet pA3 = imgData.data[index + 2];\n\t\t\t\tlet pA4 = imgData.data[index + 3];\n\n\t\t\t\tlet pB1 = imgData.data[index2];\n\t\t\t\tlet pB2 = imgData.data[index2 + 1];\n\t\t\t\tlet pB3 = imgData.data[index2 + 2];\n\t\t\t\tlet pB4 = imgData.data[index2 + 3];\n\n\t\t\t\timgData.data[index] = pB1;\n\t\t\t\timgData.data[index + 1] = pB2;\n\t\t\t\timgData.data[index + 2] = pB3;\n\t\t\t\timgData.data[index + 3] = pB4;\n\n\t\t\t\timgData.data[index2] = pA1;\n\t\t\t\timgData.data[index2 + 1] = pA2;\n\t\t\t\timgData.data[index2 + 2] = pA3;\n\t\t\t\timgData.data[index2 + 3] = pA4;\n\t\t\t}\n\t\t}\n\t}\n\tcontext.putImageData(imgData, dX, dY);\n}\n\nfunction hasTransparency(context, x0, y0, w, h) {\n\tlet imgData = context.getImageData(x0, y0, w, h);\n\tfor (let x = 0; x < w; x++) {\n\t\tfor (let y = 0; y < h; y++) {\n\t\t\tlet offset = (x + y * w) * 4;\n\t\t\tif (imgData.data[offset + 3] !== 0xff) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction computeSkinScale(width) {\n\treturn width / 64.0;\n}\n\nfunction fixOpaqueSkin(context, width) {\n\t// Some ancient skins don't have transparent pixels (nor have helm).\n\t// We have to make the helm area transparent, otherwise it will be rendered as black.\n\tif (!hasTransparency(context, 0, 0, width, width / 2)) {\n\t\tlet scale = computeSkinScale(width);\n\t\tlet clearArea = (x, y, w, h) => context.clearRect(x * scale, y * scale, w * scale, h * scale);\n\t\tclearArea(40, 0, 8, 8); // Helm Top\n\t\tclearArea(48, 0, 8, 8); // Helm Bottom\n\t\tclearArea(32, 8, 8, 8); // Helm Right\n\t\tclearArea(40, 8, 8, 8); // Helm Front\n\t\tclearArea(48, 8, 8, 8); // Helm Left\n\t\tclearArea(56, 8, 8, 8); // Helm Back\n\t}\n}\n\nfunction convertSkinTo1_8(context, width) {\n\tlet scale = computeSkinScale(width);\n\tlet copySkin = (sX, sY, w, h, dX, dY, flipHorizontal) => copyImage(context, sX * scale, sY * scale, w * scale, h * scale, dX * scale, dY * scale, flipHorizontal);\n\n\tfixOpaqueSkin(context, width);\n\n\tcopySkin(4, 16, 4, 4, 20, 48, true); // Top Leg\n\tcopySkin(8, 16, 4, 4, 24, 48, true); // Bottom Leg\n\tcopySkin(0, 20, 4, 12, 24, 52, true); // Outer Leg\n\tcopySkin(4, 20, 4, 12, 20, 52, true); // Front Leg\n\tcopySkin(8, 20, 4, 12, 16, 52, true); // Inner Leg\n\tcopySkin(12, 20, 4, 12, 28, 52, true); // Back Leg\n\tcopySkin(44, 16, 4, 4, 36, 48, true); // Top Arm\n\tcopySkin(48, 16, 4, 4, 40, 48, true); // Bottom Arm\n\tcopySkin(40, 20, 4, 12, 40, 52, true); // Outer Arm\n\tcopySkin(44, 20, 4, 12, 36, 52, true); // Front Arm\n\tcopySkin(48, 20, 4, 12, 32, 52, true); // Inner Arm\n\tcopySkin(52, 20, 4, 12, 44, 52, true); // Back Arm\n}\n\nfunction loadSkinToCanvas(canvas, image) {\n\tlet isOldFormat = false;\n\tif (image.width !== image.height) {\n\t\tif (image.width === 2 * image.height) {\n\t\t\tisOldFormat = true;\n\t\t} else {\n\t\t\tthrow `Bad skin size: ${image.width}x${image.height}`;\n\t\t}\n\t}\n\n\tlet context = canvas.getContext(\"2d\");\n\tif (isOldFormat) {\n\t\tlet sideLength = image.width;\n\t\tcanvas.width = sideLength;\n\t\tcanvas.height = sideLength;\n\t\tcontext.clearRect(0, 0, sideLength, sideLength);\n\t\tcontext.drawImage(image, 0, 0, sideLength, sideLength / 2.0);\n\t\tconvertSkinTo1_8(context, sideLength);\n\t} else {\n\t\tcanvas.width = image.width;\n\t\tcanvas.height = image.height;\n\t\tcontext.clearRect(0, 0, image.width, image.height);\n\t\tcontext.drawImage(image, 0, 0, canvas.width, canvas.height);\n\t}\n}\n\nfunction loadCapeToCanvas(canvas, image) {\n\tlet isOldFormat = false;\n\tif (image.width !== 2 * image.height) {\n\t\tif (image.width * 17 == image.height * 22) {\n\t\t\t// width/height = 22/17\n\t\t\tisOldFormat = true;\n\t\t} else {\n\t\t\tthrow `Bad cape size: ${image.width}x${image.height}`;\n\t\t}\n\t}\n\n\tlet context = canvas.getContext(\"2d\");\n\tif (isOldFormat) {\n\t\tlet width = image.width * 64 / 22;\n\t\tcanvas.width = width;\n\t\tcanvas.height = width / 2;\n\t} else {\n\t\tcanvas.width = image.width;\n\t\tcanvas.height = image.height;\n\t}\n\tcontext.clearRect(0, 0, canvas.width, canvas.height);\n\tcontext.drawImage(image, 0, 0, image.width, image.height);\n}\n\nfunction isSlimSkin(canvasOrImage) {\n\t// Detects whether the skin is default or slim.\n\t//\n\t// The right arm area of *default* skins:\n\t// (44,16)->*-------*-------*\n\t// (40,20) |top |bottom |\n\t// \\|/ |4x4 |4x4 |\n\t// *-------*-------*-------*-------*\n\t// |right |front |left |back |\n\t// |4x12 |4x12 |4x12 |4x12 |\n\t// *-------*-------*-------*-------*\n\t// The right arm area of *slim* skins:\n\t// (44,16)->*------*------*-*\n\t// (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4]\n\t// \\|/ |3x4 |3x4 | |\n\t// *-------*------*------***-----*-*\n\t// |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12]\n\t// |4x12 |3x12 |4x12 |3x12 | |\n\t// *-------*------*-------*------*-*\n\t// Compared with default right arms, slim right arms have 2 unused areas.\n\t//\n\t// The same is true for left arm:\n\t// The left arm area of *default* skins:\n\t// (36,48)->*-------*-------*\n\t// (32,52) |top |bottom |\n\t// \\|/ |4x4 |4x4 |\n\t// *-------*-------*-------*-------*\n\t// |right |front |left |back |\n\t// |4x12 |4x12 |4x12 |4x12 |\n\t// *-------*-------*-------*-------*\n\t// The left arm area of *slim* skins:\n\t// (36,48)->*------*------*-*\n\t// (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4]\n\t// \\|/ |3x4 |3x4 | |\n\t// *-------*------*------***-----*-*\n\t// |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12]\n\t// |4x12 |3x12 |4x12 |3x12 | |\n\t// *-------*------*-------*------*-*\n\t//\n\t// If there is a transparent pixel in any of the 4 unused areas, the skin must be slim,\n\t// as transparent pixels are not allowed in the first layer.\n\n\tif (canvasOrImage instanceof HTMLCanvasElement) {\n\t\tlet canvas = canvasOrImage;\n\t\tlet scale = computeSkinScale(canvas.width);\n\t\tlet context = canvas.getContext(\"2d\");\n\t\tlet checkArea = (x, y, w, h) => hasTransparency(context, x * scale, y * scale, w * scale, h * scale);\n\t\treturn checkArea(50, 16, 2, 4) ||\n\t\t\tcheckArea(54, 20, 2, 12) ||\n\t\t\tcheckArea(42, 48, 2, 4) ||\n\t\t\tcheckArea(46, 52, 2, 12);\n\t} else if (canvasOrImage instanceof HTMLImageElement) {\n\t\tlet image = canvasOrImage;\n\t\tlet canvas = document.createElement(\"canvas\");\n\t\tloadSkinToCanvas(canvas, image);\n\t\treturn isSlimSkin(canvas);\n\t} else {\n\t\tthrow `Illegal argument: ${canvasOrImage}`;\n\t}\n}\n\nexport { isSlimSkin, loadSkinToCanvas, loadCapeToCanvas };\n","import * as THREE from \"three\";\nimport { PlayerObject } from \"./model\";\nimport { invokeAnimation } from \"./animation\";\nimport { loadSkinToCanvas,loadCapeToCanvas, isSlimSkin } from \"./utils\";\n\nclass SkinViewer {\n\tconstructor(options) {\n\t\tthis.domElement = options.domElement;\n\t\tthis.animation = options.animation || null;\n\t\tthis.detectModel = options.detectModel !== false; // true by default\n\t\tthis.animationPaused = false;\n\t\tthis.animationTime = 0;\n\t\tthis.disposed = false;\n\n\t\t// texture\n\t\tthis.skinImg = new Image();\n\t\tthis.skinCanvas = document.createElement(\"canvas\");\n\t\tthis.skinTexture = new THREE.Texture(this.skinCanvas);\n\t\tthis.skinTexture.magFilter = THREE.NearestFilter;\n\t\tthis.skinTexture.minFilter = THREE.NearestFilter;\n\n\t\tthis.capeImg = new Image();\n\t\tthis.capeCanvas = document.createElement(\"canvas\");\n\t\tthis.capeTexture = new THREE.Texture(this.capeCanvas);\n\t\tthis.capeTexture.magFilter = THREE.NearestFilter;\n\t\tthis.capeTexture.minFilter = THREE.NearestFilter;\n\n\t\tthis.layer1Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, side: THREE.FrontSide });\n\t\tthis.layer2Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 });\n\t\tthis.capeMaterial = new THREE.MeshBasicMaterial({ map: this.capeTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 });\n\n\t\t// scene\n\t\tthis.scene = new THREE.Scene();\n\n\t\t// Use smaller fov to avoid distortion\n\t\tthis.camera = new THREE.PerspectiveCamera(40);\n\t\tthis.camera.position.y = -12;\n\t\tthis.camera.position.z = 60;\n\n\t\tthis.renderer = new THREE.WebGLRenderer({ angleRot: true, alpha: true, antialias: false });\n\t\tthis.renderer.setSize(300, 300); // default size\n\t\tthis.renderer.context.getShaderInfoLog = () => \"\"; // shut firefox up\n\t\tthis.domElement.appendChild(this.renderer.domElement);\n\n\t\tthis.playerObject = new PlayerObject(this.layer1Material, this.layer2Material, this.capeMaterial);\n\t\tthis.scene.add(this.playerObject);\n\n\t\t// texture loading\n\t\tthis.skinImg.crossOrigin = \"anonymous\";\n\t\tthis.skinImg.onerror = () => console.error(\"Failed loading \" + this.skinImg.src);\n\t\tthis.skinImg.onload = () => {\n\t\t\tloadSkinToCanvas(this.skinCanvas, this.skinImg);\n\n\t\t\tif (this.detectModel) {\n\t\t\t\tthis.playerObject.skin.slim = isSlimSkin(this.skinCanvas);\n\t\t\t}\n\n\t\t\tthis.skinTexture.needsUpdate = true;\n\t\t\tthis.layer1Material.needsUpdate = true;\n\t\t\tthis.layer2Material.needsUpdate = true;\n\n\t\t\tthis.playerObject.skin.visible = true;\n\t\t};\n\n\t\tthis.capeImg.crossOrigin = \"anonymous\";\n\t\tthis.capeImg.onerror = () => console.error(\"Failed loading \" + this.capeImg.src);\n\t\tthis.capeImg.onload = () => {\n\t\t\tloadCapeToCanvas(this.capeCanvas, this.capeImg);\n\n\t\t\tthis.capeTexture.needsUpdate = true;\n\t\t\tthis.capeMaterial.needsUpdate = true;\n\n\t\t\tthis.playerObject.cape.visible = true;\n\t\t};\n\n\t\tif (options.skinUrl) this.skinUrl = options.skinUrl;\n\t\tif (options.capeUrl) this.capeUrl = options.capeUrl;\n\t\tif (options.width) this.width = options.width;\n\t\tif (options.height) this.height = options.height;\n\n\t\tlet draw = () => {\n\t\t\tif (this.disposed) return;\n\t\t\twindow.requestAnimationFrame(draw);\n\t\t\tif (!this.animationPaused) {\n\t\t\t\tthis.animationTime++;\n\t\t\t\tif (this.animation) {\n\t\t\t\t\tinvokeAnimation(this.animation, this.playerObject, this.animationTime / 100.0);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.renderer.render(this.scene, this.camera);\n\t\t};\n\t\tdraw();\n\t}\n\n\tsetSize(width, height) {\n\t\tthis.camera.aspect = width / height;\n\t\tthis.camera.updateProjectionMatrix();\n\t\tthis.renderer.setSize(width, height);\n\t}\n\n\tdispose() {\n\t\tthis.disposed = true;\n\t\tthis.domElement.removeChild(this.renderer.domElement);\n\t\tthis.renderer.dispose();\n\t\tthis.skinTexture.dispose();\n\t\tthis.capeTexture.dispose();\n\t}\n\n\tget skinUrl() {\n\t\treturn this.skinImg.src;\n\t}\n\n\tset skinUrl(url) {\n\t\tthis.skinImg.src = url;\n\t}\n\n\tget capeUrl() {\n\t\treturn this.capeImg.src;\n\t}\n\n\tset capeUrl(url) {\n\t\tthis.capeImg.src = url;\n\t}\n\n\tget width() {\n\t\treturn this.renderer.getSize().width;\n\t}\n\n\tset width(newWidth) {\n\t\tthis.setSize(newWidth, this.height);\n\t}\n\n\tget height() {\n\t\treturn this.renderer.getSize().height;\n\t}\n\n\tset height(newHeight) {\n\t\tthis.setSize(this.width, newHeight);\n\t}\n}\n\nexport { SkinViewer };\n","import * as THREE from \"three\";\n\nclass OrbitControls extends THREE.EventDispatcher {\n\t/**\n\t * @preserve\n\t * The code was originally from https://github.com/mrdoob/three.js/blob/d45a042cf962e9b1aa9441810ba118647b48aacb/examples/js/controls/OrbitControls.js\n\t */\n\t/**\n\t * @license\n\t * Copyright (C) 2010-2017 three.js authors\n\t *\n\t * Permission is hereby granted, free of charge, to any person obtaining a copy\n\t * of this software and associated documentation files (the \"Software\"), to deal\n\t * in the Software without restriction, including without limitation the rights\n\t * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\t * copies of the Software, and to permit persons to whom the Software is\n\t * furnished to do so, subject to the following conditions:\n\t *\n\t * The above copyright notice and this permission notice shall be included in\n\t * all copies or substantial portions of the Software.\n\t *\n\t * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\t * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\t * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\t * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\t * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\t * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n\t * THE SOFTWARE.\n\t *\n\t *\n\t * @author qiao / https://github.com/qiao\n\t * @author mrdoob / http://mrdoob.com\n\t * @author alteredq / http://alteredqualia.com/\n\t * @author WestLangley / http://github.com/WestLangley\n\t * @author erich666 / http://erichaines.com\n\t */\n\n\t// This set of controls performs orbiting, dollying (zooming), and panning.\n\t// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n\t//\n\t// Orbit - left mouse / touch: one finger move\n\t// Zoom - middle mouse, or mousewheel / touch: two finger spread or squish\n\t// Pan - right mouse, or arrow keys / touch: three finger swipe\n\n\tconstructor(object, domElement) {\n\t\tsuper();\n\t\tthis.object = object;\n\t\tthis.domElement = (domElement !== undefined) ? domElement : document;\n\n\t\t// Set to false to disable this control\n\t\tthis.enabled = true;\n\n\t\t// \"target\" sets the location of focus, where the object orbits around\n\t\tthis.target = new THREE.Vector3();\n\n\t\t// How far you can dolly in and out (PerspectiveCamera only)\n\t\tthis.minDistance = 0;\n\t\tthis.maxDistance = Infinity;\n\n\t\t// How far you can zoom in and out (OrthographicCamera only)\n\t\tthis.minZoom = 0;\n\t\tthis.maxZoom = Infinity;\n\n\t\t// How far you can orbit vertically, upper and lower limits.\n\t\t// Range is 0 to Math.PI radians.\n\t\tthis.minPolarAngle = 0; // radians\n\t\tthis.maxPolarAngle = Math.PI; // radians\n\n\t\t// How far you can orbit horizontally, upper and lower limits.\n\t\t// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].\n\t\tthis.minAzimuthAngle = -Infinity; // radians\n\t\tthis.maxAzimuthAngle = Infinity; // radians\n\n\t\t// Set to true to enable damping (inertia)\n\t\t// If damping is enabled, you must call controls.update() in your animation loop\n\t\tthis.enableDamping = false;\n\t\tthis.dampingFactor = 0.25;\n\n\t\t// This option actually enables dollying in and out; left as \"zoom\" for backwards compatibility.\n\t\t// Set to false to disable zooming\n\t\tthis.enableZoom = true;\n\t\tthis.zoomSpeed = 1.0;\n\n\t\t// Set to false to disable rotating\n\t\tthis.enableRotate = true;\n\t\tthis.rotateSpeed = 1.0;\n\n\t\t// Set to false to disable panning\n\t\tthis.enablePan = true;\n\t\tthis.keyPanSpeed = 7.0; // pixels moved per arrow key push\n\n\t\t// Set to true to automatically rotate around the target\n\t\t// If auto-rotate is enabled, you must call controls.update() in your animation loop\n\t\tthis.autoRotate = false;\n\t\tthis.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\n\n\t\t// Set to false to disable use of the keys\n\t\tthis.enableKeys = true;\n\n\t\t// The four arrow keys\n\t\tthis.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\n\n\t\t// Mouse buttons\n\t\tthis.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };\n\n\t\t// for reset\n\t\tthis.target0 = this.target.clone();\n\t\tthis.position0 = this.object.position.clone();\n\t\tthis.zoom0 = this.object.zoom;\n\n\t\t//\n\t\t// public methods\n\t\t//\n\t\tthis.getPolarAngle = function () {\n\t\t\treturn spherical.phi;\n\t\t};\n\t\tthis.getAzimuthalAngle = function () {\n\t\t\treturn spherical.theta;\n\t\t};\n\t\tthis.saveState = function () {\n\t\t\tscope.target0.copy(scope.target);\n\t\t\tscope.position0.copy(scope.object.position);\n\t\t\tscope.zoom0 = scope.object.zoom;\n\t\t};\n\t\tthis.reset = function () {\n\t\t\tscope.target.copy(scope.target0);\n\t\t\tscope.object.position.copy(scope.position0);\n\t\t\tscope.object.zoom = scope.zoom0;\n\t\t\tscope.object.updateProjectionMatrix();\n\t\t\tscope.dispatchEvent(changeEvent);\n\t\t\tscope.update();\n\t\t\tstate = STATE.NONE;\n\t\t};\n\n\t\t// this method is exposed, but perhaps it would be better if we can make it private...\n\t\tthis.update = function () {\n\t\t\tlet offset = new THREE.Vector3();\n\t\t\t// so camera.up is the orbit axis\n\t\t\tlet quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));\n\t\t\tlet quatInverse = quat.clone().inverse();\n\t\t\tlet lastPosition = new THREE.Vector3();\n\t\t\tlet lastQuaternion = new THREE.Quaternion();\n\t\t\treturn function update() {\n\t\t\t\tlet position = scope.object.position;\n\t\t\t\toffset.copy(position).sub(scope.target);\n\t\t\t\t// rotate offset to \"y-axis-is-up\" space\n\t\t\t\toffset.applyQuaternion(quat);\n\t\t\t\t// angle from z-axis around y-axis\n\t\t\t\tspherical.setFromVector3(offset);\n\t\t\t\tif (scope.autoRotate && state === STATE.NONE) {\n\t\t\t\t\trotateLeft(getAutoRotationAngle());\n\t\t\t\t}\n\t\t\t\tspherical.theta += sphericalDelta.theta;\n\t\t\t\tspherical.phi += sphericalDelta.phi;\n\t\t\t\t// restrict theta to be between desired limits\n\t\t\t\tspherical.theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta));\n\t\t\t\t// restrict phi to be between desired limits\n\t\t\t\tspherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));\n\t\t\t\tspherical.makeSafe();\n\t\t\t\tspherical.radius *= scale;\n\t\t\t\t// restrict radius to be between desired limits\n\t\t\t\tspherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));\n\t\t\t\t// move target to panned location\n\t\t\t\tscope.target.add(panOffset);\n\t\t\t\toffset.setFromSpherical(spherical);\n\t\t\t\t// rotate offset back to \"camera-up-vector-is-up\" space\n\t\t\t\toffset.applyQuaternion(quatInverse);\n\t\t\t\tposition.copy(scope.target).add(offset);\n\t\t\t\tscope.object.lookAt(scope.target);\n\t\t\t\tif (scope.enableDamping === true) {\n\t\t\t\t\tsphericalDelta.theta *= (1 - scope.dampingFactor);\n\t\t\t\t\tsphericalDelta.phi *= (1 - scope.dampingFactor);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsphericalDelta.set(0, 0, 0);\n\t\t\t\t}\n\t\t\t\tscale = 1;\n\t\t\t\tpanOffset.set(0, 0, 0);\n\t\t\t\t// update condition is:\n\t\t\t\t// min(camera displacement, camera rotation in radians)^2 > EPS\n\t\t\t\t// using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\t\t\t\tif (zoomChanged ||\n\t\t\t\t\tlastPosition.distanceToSquared(scope.object.position) > EPS ||\n\t\t\t\t\t8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {\n\t\t\t\t\tscope.dispatchEvent(changeEvent);\n\t\t\t\t\tlastPosition.copy(scope.object.position);\n\t\t\t\t\tlastQuaternion.copy(scope.object.quaternion);\n\t\t\t\t\tzoomChanged = false;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}();\n\t\tthis.dispose = function () {\n\t\t\tscope.domElement.removeEventListener(\"contextmenu\", onContextMenu, false);\n\t\t\tscope.domElement.removeEventListener(\"mousedown\", onMouseDown, false);\n\t\t\tscope.domElement.removeEventListener(\"wheel\", onMouseWheel, false);\n\t\t\tscope.domElement.removeEventListener(\"touchstart\", onTouchStart, false);\n\t\t\tscope.domElement.removeEventListener(\"touchend\", onTouchEnd, false);\n\t\t\tscope.domElement.removeEventListener(\"touchmove\", onTouchMove, false);\n\t\t\tdocument.removeEventListener(\"mousemove\", onMouseMove, false);\n\t\t\tdocument.removeEventListener(\"mouseup\", onMouseUp, false);\n\t\t\twindow.removeEventListener(\"keydown\", onKeyDown, false);\n\t\t\t//scope.dispatchEvent({ type: \"dispose\" }); // should this be added here?\n\t\t};\n\t\t//\n\t\t// internals\n\t\t//\n\t\tlet scope = this;\n\t\tlet changeEvent = { type: \"change\" };\n\t\tlet startEvent = { type: \"start\" };\n\t\tlet endEvent = { type: \"end\" };\n\t\tlet STATE = { NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 };\n\t\tlet state = STATE.NONE;\n\t\tlet EPS = 0.000001;\n\t\t// current position in spherical coordinates\n\t\tlet spherical = new THREE.Spherical();\n\t\tlet sphericalDelta = new THREE.Spherical();\n\t\tlet scale = 1;\n\t\tlet panOffset = new THREE.Vector3();\n\t\tlet zoomChanged = false;\n\t\tlet rotateStart = new THREE.Vector2();\n\t\tlet rotateEnd = new THREE.Vector2();\n\t\tlet rotateDelta = new THREE.Vector2();\n\t\tlet panStart = new THREE.Vector2();\n\t\tlet panEnd = new THREE.Vector2();\n\t\tlet panDelta = new THREE.Vector2();\n\t\tlet dollyStart = new THREE.Vector2();\n\t\tlet dollyEnd = new THREE.Vector2();\n\t\tlet dollyDelta = new THREE.Vector2();\n\t\tfunction getAutoRotationAngle() {\n\t\t\treturn 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n\t\t}\n\t\tfunction getZoomScale() {\n\t\t\treturn Math.pow(0.95, scope.zoomSpeed);\n\t\t}\n\t\tfunction rotateLeft(angle) {\n\t\t\tsphericalDelta.theta -= angle;\n\t\t}\n\t\tfunction rotateUp(angle) {\n\t\t\tsphericalDelta.phi -= angle;\n\t\t}\n\t\tlet panLeft = function () {\n\t\t\tlet v = new THREE.Vector3();\n\t\t\treturn function panLeft(distance, objectMatrix) {\n\t\t\t\tv.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix\n\t\t\t\tv.multiplyScalar(-distance);\n\t\t\t\tpanOffset.add(v);\n\t\t\t};\n\t\t}();\n\t\tlet panUp = function () {\n\t\t\tlet v = new THREE.Vector3();\n\t\t\treturn function panUp(distance, objectMatrix) {\n\t\t\t\tv.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix\n\t\t\t\tv.multiplyScalar(distance);\n\t\t\t\tpanOffset.add(v);\n\t\t\t};\n\t\t}();\n\t\t// deltaX and deltaY are in pixels; right and down are positive\n\t\tlet pan = function () {\n\t\t\tlet offset = new THREE.Vector3();\n\t\t\treturn function pan(deltaX, deltaY) {\n\t\t\t\tlet element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\t\t\t\t// perspective\n\t\t\t\t\tlet position = scope.object.position;\n\t\t\t\t\toffset.copy(position).sub(scope.target);\n\t\t\t\t\tlet targetDistance = offset.length();\n\t\t\t\t\t// half of the fov is center to top of screen\n\t\t\t\t\ttargetDistance *= Math.tan((scope.object.fov / 2) * Math.PI / 180.0);\n\t\t\t\t\t// we actually don't use screenWidth, since perspective camera is fixed to screen height\n\t\t\t\t\tpanLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);\n\t\t\t\t\tpanUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);\n\t\t\t\t}\n\t\t\t\telse if (scope.object instanceof THREE.OrthographicCamera) {\n\t\t\t\t\t// orthographic\n\t\t\t\t\tpanLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);\n\t\t\t\t\tpanUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// camera neither orthographic nor perspective\n\t\t\t\t\tconsole.warn(\"WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.\");\n\t\t\t\t\tscope.enablePan = false;\n\t\t\t\t}\n\t\t\t};\n\t\t}();\n\t\tfunction dollyIn(dollyScale) {\n\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\t\t\tscale /= dollyScale;\n\t\t\t}\n\t\t\telse if (scope.object instanceof THREE.OrthographicCamera) {\n\t\t\t\tscope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));\n\t\t\t\tscope.object.updateProjectionMatrix();\n\t\t\t\tzoomChanged = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconsole.warn(\"WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.\");\n\t\t\t\tscope.enableZoom = false;\n\t\t\t}\n\t\t}\n\t\tfunction dollyOut(dollyScale) {\n\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\t\t\tscale *= dollyScale;\n\t\t\t}\n\t\t\telse if (scope.object instanceof THREE.OrthographicCamera) {\n\t\t\t\tscope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));\n\t\t\t\tscope.object.updateProjectionMatrix();\n\t\t\t\tzoomChanged = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconsole.warn(\"WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.\");\n\t\t\t\tscope.enableZoom = false;\n\t\t\t}\n\t\t}\n\t\t//\n\t\t// event callbacks - update the object state\n\t\t//\n\t\tfunction handleMouseDownRotate(event) {\n\t\t\trotateStart.set(event.clientX, event.clientY);\n\t\t}\n\t\tfunction handleMouseDownDolly(event) {\n\t\t\tdollyStart.set(event.clientX, event.clientY);\n\t\t}\n\t\tfunction handleMouseDownPan(event) {\n\t\t\tpanStart.set(event.clientX, event.clientY);\n\t\t}\n\t\tfunction handleMouseMoveRotate(event) {\n\t\t\trotateEnd.set(event.clientX, event.clientY);\n\t\t\trotateDelta.subVectors(rotateEnd, rotateStart);\n\t\t\tlet element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\t\t// rotating across whole screen goes 360 degrees around\n\t\t\trotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);\n\t\t\t// rotating up and down along whole screen attempts to go 360, but limited to 180\n\t\t\trotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);\n\t\t\trotateStart.copy(rotateEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleMouseMoveDolly(event) {\n\t\t\tdollyEnd.set(event.clientX, event.clientY);\n\t\t\tdollyDelta.subVectors(dollyEnd, dollyStart);\n\t\t\tif (dollyDelta.y > 0) {\n\t\t\t\tdollyIn(getZoomScale());\n\t\t\t}\n\t\t\telse if (dollyDelta.y < 0) {\n\t\t\t\tdollyOut(getZoomScale());\n\t\t\t}\n\t\t\tdollyStart.copy(dollyEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleMouseMovePan(event) {\n\t\t\tpanEnd.set(event.clientX, event.clientY);\n\t\t\tpanDelta.subVectors(panEnd, panStart);\n\t\t\tpan(panDelta.x, panDelta.y);\n\t\t\tpanStart.copy(panEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleMouseUp(event) {\n\t\t}\n\t\tfunction handleMouseWheel(event) {\n\t\t\tif (event.deltaY < 0) {\n\t\t\t\tdollyOut(getZoomScale());\n\t\t\t}\n\t\t\telse if (event.deltaY > 0) {\n\t\t\t\tdollyIn(getZoomScale());\n\t\t\t}\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleKeyDown(event) {\n\t\t\tswitch (event.keyCode) {\n\t\t\t\tcase scope.keys.UP:\n\t\t\t\t\tpan(0, scope.keyPanSpeed);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.keys.BOTTOM:\n\t\t\t\t\tpan(0, -scope.keyPanSpeed);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.keys.LEFT:\n\t\t\t\t\tpan(scope.keyPanSpeed, 0);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.keys.RIGHT:\n\t\t\t\t\tpan(-scope.keyPanSpeed, 0);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfunction handleTouchStartRotate(event) {\n\t\t\trotateStart.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t}\n\t\tfunction handleTouchStartDolly(event) {\n\t\t\tlet dx = event.touches[0].pageX - event.touches[1].pageX;\n\t\t\tlet dy = event.touches[0].pageY - event.touches[1].pageY;\n\t\t\tlet distance = Math.sqrt(dx * dx + dy * dy);\n\t\t\tdollyStart.set(0, distance);\n\t\t}\n\t\tfunction handleTouchStartPan(event) {\n\t\t\tpanStart.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t}\n\t\tfunction handleTouchMoveRotate(event) {\n\t\t\trotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t\trotateDelta.subVectors(rotateEnd, rotateStart);\n\t\t\tlet element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\t\trotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);\n\t\t\trotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);\n\t\t\trotateStart.copy(rotateEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleTouchMoveDolly(event) {\n\t\t\tlet dx = event.touches[0].pageX - event.touches[1].pageX;\n\t\t\tlet dy = event.touches[0].pageY - event.touches[1].pageY;\n\t\t\tlet distance = Math.sqrt(dx * dx + dy * dy);\n\t\t\tdollyEnd.set(0, distance);\n\t\t\tdollyDelta.subVectors(dollyEnd, dollyStart);\n\t\t\tif (dollyDelta.y > 0) {\n\t\t\t\tdollyOut(getZoomScale());\n\t\t\t}\n\t\t\telse if (dollyDelta.y < 0) {\n\t\t\t\tdollyIn(getZoomScale());\n\t\t\t}\n\t\t\tdollyStart.copy(dollyEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleTouchMovePan(event) {\n\t\t\tpanEnd.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t\tpanDelta.subVectors(panEnd, panStart);\n\t\t\tpan(panDelta.x, panDelta.y);\n\t\t\tpanStart.copy(panEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleTouchEnd(event) {\n\t\t}\n\t\t//\n\t\t// event handlers - FSM: listen for events and reset state\n\t\t//\n\t\tfunction onMouseDown(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (event.button) {\n\t\t\t\tcase scope.mouseButtons.ORBIT:\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseDownRotate(event);\n\t\t\t\t\tstate = STATE.ROTATE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.mouseButtons.ZOOM:\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseDownDolly(event);\n\t\t\t\t\tstate = STATE.DOLLY;\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.mouseButtons.PAN:\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseDownPan(event);\n\t\t\t\t\tstate = STATE.PAN;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t\tif (state !== STATE.NONE) {\n\t\t\t\tdocument.addEventListener(\"mousemove\", onMouseMove, false);\n\t\t\t\tdocument.addEventListener(\"mouseup\", onMouseUp, false);\n\t\t\t\tscope.dispatchEvent(startEvent);\n\t\t\t}\n\t\t}\n\t\tfunction onMouseMove(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (state) {\n\t\t\t\tcase STATE.ROTATE:\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseMoveRotate(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase STATE.DOLLY:\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseMoveDolly(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase STATE.PAN:\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseMovePan(event);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t}\n\t\tfunction onMouseUp(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\thandleMouseUp(event);\n\t\t\tdocument.removeEventListener(\"mousemove\", onMouseMove, false);\n\t\t\tdocument.removeEventListener(\"mouseup\", onMouseUp, false);\n\t\t\tscope.dispatchEvent(endEvent);\n\t\t\tstate = STATE.NONE;\n\t\t}\n\t\tfunction onMouseWheel(event) {\n\t\t\tif (scope.enabled === false || scope.enableZoom === false || (state !== STATE.NONE && state !== STATE.ROTATE))\n\t\t\t\treturn;\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\thandleMouseWheel(event);\n\t\t\tscope.dispatchEvent(startEvent); // not sure why these are here...\n\t\t\tscope.dispatchEvent(endEvent);\n\t\t}\n\t\tfunction onKeyDown(event) {\n\t\t\tif (scope.enabled === false || scope.enableKeys === false || scope.enablePan === false)\n\t\t\t\treturn;\n\t\t\thandleKeyDown(event);\n\t\t}\n\t\tfunction onTouchStart(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (event.touches.length) {\n\t\t\t\tcase 1:// one-fingered touch: rotate\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleTouchStartRotate(event);\n\t\t\t\t\tstate = STATE.TOUCH_ROTATE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:// two-fingered touch: dolly\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleTouchStartDolly(event);\n\t\t\t\t\tstate = STATE.TOUCH_DOLLY;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:// three-fingered touch: pan\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleTouchStartPan(event);\n\t\t\t\t\tstate = STATE.TOUCH_PAN;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tstate = STATE.NONE;\n\t\t\t}\n\t\t\tif (state !== STATE.NONE) {\n\t\t\t\tscope.dispatchEvent(startEvent);\n\t\t\t}\n\t\t}\n\t\tfunction onTouchMove(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (event.touches.length) {\n\t\t\t\tcase 1:// one-fingered touch: rotate\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (state !== STATE.TOUCH_ROTATE)\n\t\t\t\t\t\treturn; // is this needed?...\n\t\t\t\t\thandleTouchMoveRotate(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:// two-fingered touch: dolly\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (state !== STATE.TOUCH_DOLLY)\n\t\t\t\t\t\treturn; // is this needed?...\n\t\t\t\t\thandleTouchMoveDolly(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:// three-fingered touch: pan\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (state !== STATE.TOUCH_PAN)\n\t\t\t\t\t\treturn; // is this needed?...\n\t\t\t\t\thandleTouchMovePan(event);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tstate = STATE.NONE;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t\tfunction onTouchEnd(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\thandleTouchEnd(event);\n\t\t\tscope.dispatchEvent(endEvent);\n\t\t\tstate = STATE.NONE;\n\t\t}\n\t\tfunction onContextMenu(event) {\n\t\t\tif (scope.enabled === false || scope.enablePan === false)\n\t\t\t\treturn;\n\t\t\tevent.preventDefault();\n\t\t}\n\t\t//\n\t\tscope.domElement.addEventListener(\"contextmenu\", onContextMenu, false);\n\t\tscope.domElement.addEventListener(\"mousedown\", onMouseDown, false);\n\t\tscope.domElement.addEventListener(\"wheel\", onMouseWheel, false);\n\t\tscope.domElement.addEventListener(\"touchstart\", onTouchStart, false);\n\t\tscope.domElement.addEventListener(\"touchend\", onTouchEnd, false);\n\t\tscope.domElement.addEventListener(\"touchmove\", onTouchMove, false);\n\t\twindow.addEventListener(\"keydown\", onKeyDown, false);\n\t\t// force an update at start\n\t\tthis.update();\n\t}\n}\n\nfunction createOrbitControls(skinViewer) {\n\tlet control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement);\n\n\t// default configuration\n\tcontrol.enablePan = false;\n\tcontrol.target = new THREE.Vector3(0, -12, 0);\n\tcontrol.minDistance = 10;\n\tcontrol.maxDistance = 256;\n\tcontrol.update();\n\n\treturn control;\n}\n\nexport { OrbitControls, createOrbitControls };\n"],"names":["toFaceVertices","x1","y1","x2","y2","w","h","THREE","toSkinVertices","toCapeVertices","setVertices","box","top","bottom","left","front","right","back","faceVertexUvs","esp","SkinObject","layer1Material","layer2Material","modelListeners","head","headBox","headMesh","add","head2Box","head2Mesh","renderOrder","body","bodyBox","bodyMesh","body2Box","body2Mesh","position","y","rightArm","rightArmPivot","rightArmBox","rightArmMesh","push","scale","x","slim","z","uvsNeedUpdate","elementsNeedUpdate","rightArm2Box","rightArm2Mesh","leftArm","leftArmPivot","leftArmBox","leftArmMesh","leftArm2Box","leftArm2Mesh","rightLeg","rightLegPivot","rightLegBox","rightLegMesh","rightLeg2Box","rightLeg2Mesh","leftLeg","leftLegPivot","leftLegBox","leftLegMesh","leftLeg2Box","leftLeg2Mesh","_slim","value","forEach","listener","CapeObject","capeMaterial","capeBox","cape","PlayerObject","skin","visible","rotation","Math","PI","invokeAnimation","animation","player","time","CompositeAnimation","play","Function","AnimationHandle","paused","_paused","speed","_speed","_lastChange","_lastChangeX","dt","handles","Set","handle","remove","delete","WalkingAnimation","sin","basicArmRotationZ","cos","basicCapeRotationX","RunningAnimation","RotatingAnimation","copyImage","context","sX","sY","dX","dY","flipHorizontal","imgData","getImageData","index","index2","pA1","data","pA2","pA3","pA4","pB1","pB2","pB3","pB4","putImageData","hasTransparency","x0","y0","offset","computeSkinScale","width","fixOpaqueSkin","clearArea","clearRect","convertSkinTo1_8","copySkin","loadSkinToCanvas","canvas","image","isOldFormat","height","getContext","sideLength","drawImage","loadCapeToCanvas","isSlimSkin","canvasOrImage","HTMLCanvasElement","checkArea","HTMLImageElement","document","createElement","SkinViewer","options","domElement","detectModel","animationPaused","animationTime","disposed","skinImg","Image","skinCanvas","skinTexture","magFilter","minFilter","capeImg","capeCanvas","capeTexture","map","side","transparent","opacity","alphaTest","scene","camera","renderer","angleRot","alpha","antialias","setSize","getShaderInfoLog","appendChild","playerObject","crossOrigin","onerror","console","error","src","onload","needsUpdate","skinUrl","capeUrl","draw","window","requestAnimationFrame","render","aspect","updateProjectionMatrix","removeChild","dispose","url","getSize","newWidth","newHeight","OrbitControls","object","undefined","enabled","target","minDistance","maxDistance","Infinity","minZoom","maxZoom","minPolarAngle","maxPolarAngle","minAzimuthAngle","maxAzimuthAngle","enableDamping","dampingFactor","enableZoom","zoomSpeed","enableRotate","rotateSpeed","enablePan","keyPanSpeed","autoRotate","autoRotateSpeed","enableKeys","keys","LEFT","UP","RIGHT","BOTTOM","mouseButtons","ORBIT","ZOOM","MIDDLE","PAN","target0","clone","position0","zoom0","zoom","getPolarAngle","spherical","phi","getAzimuthalAngle","theta","saveState","scope","copy","reset","dispatchEvent","changeEvent","update","state","STATE","NONE","quat","setFromUnitVectors","up","quatInverse","inverse","lastPosition","lastQuaternion","sub","applyQuaternion","setFromVector3","rotateLeft","getAutoRotationAngle","sphericalDelta","max","min","makeSafe","radius","panOffset","setFromSpherical","lookAt","set","zoomChanged","distanceToSquared","EPS","dot","quaternion","removeEventListener","onContextMenu","onMouseDown","onMouseWheel","onTouchStart","onTouchEnd","onTouchMove","onMouseMove","onMouseUp","onKeyDown","type","startEvent","endEvent","ROTATE","DOLLY","TOUCH_ROTATE","TOUCH_DOLLY","TOUCH_PAN","rotateStart","rotateEnd","rotateDelta","panStart","panEnd","panDelta","dollyStart","dollyEnd","dollyDelta","getZoomScale","pow","angle","rotateUp","panLeft","v","distance","objectMatrix","setFromMatrixColumn","multiplyScalar","panUp","pan","deltaX","deltaY","element","targetDistance","length","tan","fov","clientHeight","matrix","clientWidth","warn","dollyIn","dollyScale","dollyOut","handleMouseDownRotate","event","clientX","clientY","handleMouseDownDolly","handleMouseDownPan","handleMouseMoveRotate","subVectors","handleMouseMoveDolly","handleMouseMovePan","handleMouseWheel","handleKeyDown","keyCode","handleTouchStartRotate","touches","pageX","pageY","handleTouchStartDolly","dx","dy","sqrt","handleTouchStartPan","handleTouchMoveRotate","handleTouchMoveDolly","handleTouchMovePan","button","preventDefault","addEventListener","handleMouseUp","stopPropagation","handleTouchEnd","createOrbitControls","skinViewer","control"],"mappings":"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"} \ No newline at end of file diff --git a/js/build/skinview3d.min.js b/js/build/skinview3d.min.js deleted file mode 100644 index 8e534ae..0000000 --- a/js/build/skinview3d.min.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * skinview3d (https://github.com/to2mbn/skinview3d) - * - * MIT License - * - * Copyright (c) 2014-2018 Kent Rasmussen - * Copyright (c) 2017-2018 Haowei Wen, Sean Boult and contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("three")):"function"==typeof define&&define.amd?define(["exports","three"],t):t(e.skinview3d={},e.THREE)}(this,function(e,Q){"use strict";var K=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},a=function(){function a(e,t){for(var n=0;np||8*(1-r.dot(c.object.quaternion))>p)||(c.dispatchEvent(h),o.copy(c.object.position),r.copy(c.object.quaternion),w=!1))}),s.dispose=function(){c.domElement.removeEventListener("contextmenu",W,!1),c.domElement.removeEventListener("mousedown",G,!1),c.domElement.removeEventListener("wheel",F,!1),c.domElement.removeEventListener("touchstart",H,!1),c.domElement.removeEventListener("touchend",Z,!1),c.domElement.removeEventListener("touchmove",X,!1),document.removeEventListener("mousemove",D,!1),document.removeEventListener("mouseup",B,!1),window.removeEventListener("keydown",Y,!1)};var c=s,h={type:"change"},d={type:"start"},u={type:"end"},l={NONE:-1,ROTATE:0,DOLLY:1,PAN:2,TOUCH_ROTATE:3,TOUCH_DOLLY:4,TOUCH_PAN:5},m=l.NONE,p=1e-6,f=new Q.Spherical,g=new Q.Spherical,v=1,b=new Q.Vector3,w=!1,y=new Q.Vector2,x=new Q.Vector2,M=new Q.Vector2,E=new Q.Vector2,O=new Q.Vector2,k=new Q.Vector2,P=new Q.Vector2,j=new Q.Vector2,L=new Q.Vector2;function T(){return Math.pow(.95,c.zoomSpeed)}function A(e){g.theta-=e}function I(e){g.phi-=e}var _,C,N,U=(_=new Q.Vector3,function(e,t){_.setFromMatrixColumn(t,0),_.multiplyScalar(-e),b.add(_)}),V=(C=new Q.Vector3,function(e,t){C.setFromMatrixColumn(t,1),C.multiplyScalar(e),b.add(C)}),S=(N=new Q.Vector3,function(e,t){var n=c.domElement===document?c.domElement.body:c.domElement;if(c.object instanceof Q.PerspectiveCamera){var a=c.object.position;N.copy(a).sub(c.target);var i=N.length();i*=Math.tan(c.object.fov/2*Math.PI/180),U(2*e*i/n.clientHeight,c.object.matrix),V(2*t*i/n.clientHeight,c.object.matrix)}else c.object instanceof Q.OrthographicCamera?(U(e*(c.object.right-c.object.left)/c.object.zoom/n.clientWidth,c.object.matrix),V(t*(c.object.top-c.object.bottom)/c.object.zoom/n.clientHeight,c.object.matrix)):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."),c.enablePan=!1)});function z(e){c.object instanceof Q.PerspectiveCamera?v/=e:c.object instanceof Q.OrthographicCamera?(c.object.zoom=Math.max(c.minZoom,Math.min(c.maxZoom,c.object.zoom*e)),c.object.updateProjectionMatrix(),w=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),c.enableZoom=!1)}function R(e){c.object instanceof Q.PerspectiveCamera?v*=e:c.object instanceof Q.OrthographicCamera?(c.object.zoom=Math.max(c.minZoom,Math.min(c.maxZoom,c.object.zoom/e)),c.object.updateProjectionMatrix(),w=!0):(console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."),c.enableZoom=!1)}function G(e){if(!1!==c.enabled){switch(e.button){case c.mouseButtons.ORBIT:if(!1===c.enableRotate)return;a=e,y.set(a.clientX,a.clientY),m=l.ROTATE;break;case c.mouseButtons.ZOOM:if(!1===c.enableZoom)return;n=e,P.set(n.clientX,n.clientY),m=l.DOLLY;break;case c.mouseButtons.PAN:if(!1===c.enablePan)return;t=e,E.set(t.clientX,t.clientY),m=l.PAN}var t,n,a;e.preventDefault(),m!==l.NONE&&(document.addEventListener("mousemove",D,!1),document.addEventListener("mouseup",B,!1),c.dispatchEvent(d))}}function D(e){if(!1!==c.enabled){switch(m){case l.ROTATE:if(!1===c.enableRotate)return;!function(e){x.set(e.clientX,e.clientY),M.subVectors(x,y);var t=c.domElement===document?c.domElement.body:c.domElement;A(2*Math.PI*M.x/t.clientWidth*c.rotateSpeed),I(2*Math.PI*M.y/t.clientHeight*c.rotateSpeed),y.copy(x),c.update()}(e);break;case l.DOLLY:if(!1===c.enableZoom)return;n=e,j.set(n.clientX,n.clientY),L.subVectors(j,P),0 {\n\t\t\trightArmMesh.scale.x = (this.slim ? 3 : 4) - esp;\n\t\t\trightArmMesh.scale.y = 12 - esp;\n\t\t\trightArmMesh.scale.z = 4 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(rightArmBox,\n\t\t\t\t\ttoSkinVertices(44, 16, 47, 20),\n\t\t\t\t\ttoSkinVertices(47, 16, 50, 20),\n\t\t\t\t\ttoSkinVertices(40, 20, 44, 32),\n\t\t\t\t\ttoSkinVertices(44, 20, 47, 32),\n\t\t\t\t\ttoSkinVertices(47, 20, 51, 32),\n\t\t\t\t\ttoSkinVertices(51, 20, 54, 32)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(rightArmBox,\n\t\t\t\t\ttoSkinVertices(44, 16, 48, 20),\n\t\t\t\t\ttoSkinVertices(48, 16, 52, 20),\n\t\t\t\t\ttoSkinVertices(40, 20, 44, 32),\n\t\t\t\t\ttoSkinVertices(44, 20, 48, 32),\n\t\t\t\t\ttoSkinVertices(48, 20, 52, 32),\n\t\t\t\t\ttoSkinVertices(52, 20, 56, 32)\n\t\t\t\t);\n\t\t\t}\n\t\t\trightArmBox.uvsNeedUpdate = true;\n\t\t\trightArmBox.elementsNeedUpdate = true;\n\t\t});\n\n\t\tlet rightArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet rightArm2Mesh = new THREE.Mesh(rightArm2Box, layer2Material);\n\t\trightArm2Mesh.renderOrder = 1;\n\t\trightArmPivot.add(rightArm2Mesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\trightArm2Mesh.scale.x = (this.slim ? 3.375 : 4.5) - esp;\n\t\t\trightArm2Mesh.scale.y = 13.5 - esp;\n\t\t\trightArm2Mesh.scale.z = 4.5 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(rightArm2Box,\n\t\t\t\t\ttoSkinVertices(44, 32, 47, 36),\n\t\t\t\t\ttoSkinVertices(47, 32, 50, 36),\n\t\t\t\t\ttoSkinVertices(40, 36, 44, 48),\n\t\t\t\t\ttoSkinVertices(44, 36, 47, 48),\n\t\t\t\t\ttoSkinVertices(47, 36, 51, 48),\n\t\t\t\t\ttoSkinVertices(51, 36, 54, 48)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(rightArm2Box,\n\t\t\t\t\ttoSkinVertices(44, 32, 48, 36),\n\t\t\t\t\ttoSkinVertices(48, 32, 52, 36),\n\t\t\t\t\ttoSkinVertices(40, 36, 44, 48),\n\t\t\t\t\ttoSkinVertices(44, 36, 48, 48),\n\t\t\t\t\ttoSkinVertices(48, 36, 52, 48),\n\t\t\t\t\ttoSkinVertices(52, 36, 56, 48)\n\t\t\t\t);\n\t\t\t}\n\t\t\trightArm2Box.uvsNeedUpdate = true;\n\t\t\trightArm2Box.elementsNeedUpdate = true;\n\t\t});\n\n\t\trightArmPivot.position.y = -6;\n\t\tthis.rightArm.add(rightArmPivot);\n\t\tthis.rightArm.position.y = -4;\n\t\tthis.modelListeners.push(() => {\n\t\t\tthis.rightArm.position.x = this.slim ? -5.5 : -6;\n\t\t});\n\t\tthis.add(this.rightArm);\n\n\n\t\t// Left Arm\n\t\tthis.leftArm = new THREE.Group();\n\t\tlet leftArmPivot = new THREE.Group();\n\n\t\tlet leftArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet leftArmMesh = new THREE.Mesh(leftArmBox, layer1Material);\n\t\tleftArmPivot.add(leftArmMesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\tleftArmMesh.scale.x = (this.slim ? 3 : 4) - esp;\n\t\t\tleftArmMesh.scale.y = 12 - esp;\n\t\t\tleftArmMesh.scale.z = 4 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(leftArmBox,\n\t\t\t\t\ttoSkinVertices(36, 48, 39, 52),\n\t\t\t\t\ttoSkinVertices(39, 48, 42, 52),\n\t\t\t\t\ttoSkinVertices(32, 52, 36, 64),\n\t\t\t\t\ttoSkinVertices(36, 52, 39, 64),\n\t\t\t\t\ttoSkinVertices(39, 52, 43, 64),\n\t\t\t\t\ttoSkinVertices(43, 52, 46, 64)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(leftArmBox,\n\t\t\t\t\ttoSkinVertices(36, 48, 40, 52),\n\t\t\t\t\ttoSkinVertices(40, 48, 44, 52),\n\t\t\t\t\ttoSkinVertices(32, 52, 36, 64),\n\t\t\t\t\ttoSkinVertices(36, 52, 40, 64),\n\t\t\t\t\ttoSkinVertices(40, 52, 44, 64),\n\t\t\t\t\ttoSkinVertices(44, 52, 48, 64)\n\t\t\t\t);\n\t\t\t}\n\t\t\tleftArmBox.uvsNeedUpdate = true;\n\t\t\tleftArmBox.elementsNeedUpdate=true;\n\t\t});\n\n\t\tlet leftArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet leftArm2Mesh = new THREE.Mesh(leftArm2Box, layer2Material);\n\t\tleftArm2Mesh.renderOrder = 1;\n\t\tleftArmPivot.add(leftArm2Mesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\tleftArm2Mesh.scale.x = (this.slim ? 3.375 : 4.5) - esp;\n\t\t\tleftArm2Mesh.scale.y = 13.5 - esp;\n\t\t\tleftArm2Mesh.scale.z = 4.5 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(leftArm2Box,\n\t\t\t\t\ttoSkinVertices(52, 48, 55, 52),\n\t\t\t\t\ttoSkinVertices(55, 48, 58, 52),\n\t\t\t\t\ttoSkinVertices(48, 52, 52, 64),\n\t\t\t\t\ttoSkinVertices(52, 52, 55, 64),\n\t\t\t\t\ttoSkinVertices(55, 52, 59, 64),\n\t\t\t\t\ttoSkinVertices(59, 52, 62, 64)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(leftArm2Box,\n\t\t\t\t\ttoSkinVertices(52, 48, 56, 52),\n\t\t\t\t\ttoSkinVertices(56, 48, 60, 52),\n\t\t\t\t\ttoSkinVertices(48, 52, 52, 64),\n\t\t\t\t\ttoSkinVertices(52, 52, 56, 64),\n\t\t\t\t\ttoSkinVertices(56, 52, 60, 64),\n\t\t\t\t\ttoSkinVertices(60, 52, 64, 64)\n\t\t\t\t);\n\t\t\t}\n\t\t\tleftArm2Box.uvsNeedUpdate = true;\n\t\t\tleftArm2Box.elementsNeedUpdate = true;\n\t\t});\n\n\t\tleftArmPivot.position.y = -6;\n\t\tthis.leftArm.add(leftArmPivot);\n\t\tthis.leftArm.position.y = -4;\n\t\tthis.modelListeners.push(() => {\n\t\t\tthis.leftArm.position.x = this.slim ? 5.5 : 6;\n\t\t});\n\t\tthis.add(this.leftArm);\n\n\n\t\t// Right Leg\n\t\tthis.rightLeg = new THREE.Group();\n\t\tlet rightLegPivot = new THREE.Group();\n\n\t\tlet rightLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0);\n\t\tsetVertices(rightLegBox,\n\t\t\ttoSkinVertices(4, 16, 8, 20),\n\t\t\ttoSkinVertices(8, 16, 12, 20),\n\t\t\ttoSkinVertices(0, 20, 4, 32),\n\t\t\ttoSkinVertices(4, 20, 8, 32),\n\t\t\ttoSkinVertices(8, 20, 12, 32),\n\t\t\ttoSkinVertices(12, 20, 16, 32)\n\t\t);\n\t\tlet rightLegMesh = new THREE.Mesh(rightLegBox, layer1Material);\n\t\trightLegPivot.add(rightLegMesh);\n\n\t\tlet rightLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0);\n\t\tsetVertices(rightLeg2Box,\n\t\t\ttoSkinVertices(4, 32, 8, 36),\n\t\t\ttoSkinVertices(8, 32, 12, 36),\n\t\t\ttoSkinVertices(0, 36, 4, 48),\n\t\t\ttoSkinVertices(4, 36, 8, 48),\n\t\t\ttoSkinVertices(8, 36, 12, 48),\n\t\t\ttoSkinVertices(12, 36, 16, 48)\n\t\t);\n\t\tlet rightLeg2Mesh = new THREE.Mesh(rightLeg2Box, layer2Material);\n\t\trightLeg2Mesh.renderOrder = 1;\n\t\trightLegPivot.add(rightLeg2Mesh);\n\n\t\trightLegPivot.position.y = -6;\n\t\tthis.rightLeg.add(rightLegPivot);\n\t\tthis.rightLeg.position.y = -16;\n\t\tthis.rightLeg.position.x = -2;\n\t\tthis.add(this.rightLeg);\n\n\t\t// Left Leg\n\t\tthis.leftLeg = new THREE.Group();\n\t\tlet leftLegPivot = new THREE.Group();\n\n\t\tlet leftLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0);\n\t\tsetVertices(leftLegBox,\n\t\t\ttoSkinVertices(20, 48, 24, 52),\n\t\t\ttoSkinVertices(24, 48, 28, 52),\n\t\t\ttoSkinVertices(16, 52, 20, 64),\n\t\t\ttoSkinVertices(20, 52, 24, 64),\n\t\t\ttoSkinVertices(24, 52, 28, 64),\n\t\t\ttoSkinVertices(28, 52, 32, 64)\n\t\t);\n\t\tlet leftLegMesh = new THREE.Mesh(leftLegBox, layer1Material);\n\t\tleftLegPivot.add(leftLegMesh);\n\n\t\tlet leftLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0);\n\t\tsetVertices(leftLeg2Box,\n\t\t\ttoSkinVertices(4, 48, 8, 52),\n\t\t\ttoSkinVertices(8, 48, 12, 52),\n\t\t\ttoSkinVertices(0, 52, 4, 64),\n\t\t\ttoSkinVertices(4, 52, 8, 64),\n\t\t\ttoSkinVertices(8, 52, 12, 64),\n\t\t\ttoSkinVertices(12, 52, 16, 64)\n\t\t);\n\t\tlet leftLeg2Mesh = new THREE.Mesh(leftLeg2Box, layer2Material);\n\t\tleftLeg2Mesh.renderOrder = 1;\n\t\tleftLegPivot.add(leftLeg2Mesh);\n\n\t\tleftLegPivot.position.y = -6;\n\t\tthis.leftLeg.add(leftLegPivot);\n\t\tthis.leftLeg.position.y = -16;\n\t\tthis.leftLeg.position.x = 2;\n\t\tthis.add(this.leftLeg);\n\n\t\tthis.slim = false;\n\t}\n\n\tget slim() {\n\t\treturn this._slim;\n\t}\n\n\tset slim(value) {\n\t\tif (this._slim !== value) {\n\t\t\tthis._slim = value;\n\t\t\tthis.modelListeners.forEach(listener => listener());\n\t\t}\n\t}\n}\n\nclass CapeObject extends THREE.Group {\n\tconstructor(capeMaterial) {\n\t\tsuper();\n\n\t\t// back = outside\n\t\t// front = inside\n\t\tlet capeBox = new THREE.BoxGeometry(10, 16, 1, 0, 0, 0);\n\t\tsetVertices(capeBox,\n\t\t\ttoCapeVertices(1, 0, 11, 1),\n\t\t\ttoCapeVertices(11, 0, 21, 1),\n\t\t\ttoCapeVertices(11, 1, 12, 17),\n\t\t\ttoCapeVertices(12, 1, 22, 17),\n\t\t\ttoCapeVertices(0, 1, 1, 17),\n\t\t\ttoCapeVertices(1, 1, 11, 17)\n\t\t);\n\t\tthis.cape = new THREE.Mesh(capeBox, capeMaterial);\n\t\tthis.cape.position.y = -8;\n\t\tthis.cape.position.z = -0.5;\n\t\tthis.add(this.cape);\n\t}\n}\n\nclass PlayerObject extends THREE.Group {\n\tconstructor(layer1Material, layer2Material, capeMaterial) {\n\t\tsuper();\n\n\t\tthis.skin = new SkinObject(layer1Material, layer2Material);\n\t\tthis.skin.visible = false;\n\t\tthis.add(this.skin);\n\n\t\tthis.cape = new CapeObject(capeMaterial);\n\t\tthis.cape.position.z = -2;\n\t\tthis.cape.position.y = -4;\n\t\tthis.cape.rotation.x = 25 * Math.PI / 180;\n\t\tthis.cape.visible = false;\n\t\tthis.add(this.cape);\n\t}\n}\n\nexport { SkinObject, CapeObject, PlayerObject };\n","function invokeAnimation(animation, player, time) {\n\tif (animation instanceof CompositeAnimation) {\n\t\tanimation.play(player, time);\n\t} else if (animation instanceof Function) {\n\t\tanimation(player, time);\n\t} else {\n\t\tthrow `Not an animation: ${animation}`;\n\t}\n}\n\nclass AnimationHandle {\n\tconstructor(animation) {\n\t\tthis.animation = animation;\n\t\tthis.paused = this._paused = false;\n\t\tthis.speed = this._speed = 1.0;\n\t\tthis._lastChange = null;\n\t\tthis._lastChangeX = null;\n\t}\n\tplay(player, time) {\n\t\tif (this._lastChange === null) {\n\t\t\tthis._lastChange = time;\n\t\t\tthis._lastChangeX = 0;\n\t\t} else if (this.paused !== this._paused || this.speed !== this._speed) {\n\t\t\tlet dt = time - this._lastChange;\n\t\t\tif (this._paused === false) {\n\t\t\t\tthis._lastChangeX += dt * this._speed;\n\t\t\t}\n\t\t\tthis._paused = this.paused;\n\t\t\tthis._speed = this.speed;\n\t\t\tthis._lastChange = time;\n\t\t}\n\t\tif (this.paused === false) {\n\t\t\tlet dt = time - this._lastChange;\n\t\t\tlet x = this._lastChangeX + this.speed * dt;\n\t\t\tinvokeAnimation(this.animation, player, x);\n\t\t}\n\t}\n\treset(){\n\t\tthis._lastChange = null;\n\t}\n}\n\nclass CompositeAnimation {\n\tconstructor() {\n\t\tthis.handles = new Set();\n\t}\n\tadd(animation) {\n\t\tlet handle = new AnimationHandle(animation);\n\t\thandle.remove = () => this.handles.delete(handle);\n\t\tthis.handles.add(handle);\n\t\treturn handle;\n\t}\n\tplay(player, time) {\n\t\tthis.handles.forEach(handle => handle.play(player, time));\n\t}\n}\n\nlet WalkingAnimation = (player, time) => {\n\tlet skin = player.skin;\n\n\t// Multiply by animation's natural speed\n\ttime *= 8;\n\n\t// Leg swing\n\tskin.leftLeg.rotation.x = Math.sin(time) * 0.5;\n\tskin.rightLeg.rotation.x = Math.sin(time + Math.PI) * 0.5;\n\n\t// Arm swing\n\tskin.leftArm.rotation.x = Math.sin(time + Math.PI) * 0.5;\n\tskin.rightArm.rotation.x = Math.sin(time) * 0.5;\n\tlet basicArmRotationZ = Math.PI * 0.02;\n\tskin.leftArm.rotation.z = Math.cos(time) * 0.03 + basicArmRotationZ;\n\tskin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.03 - basicArmRotationZ;\n\n\t// Head shaking with different frequency & amplitude\n\tskin.head.rotation.y = Math.sin(time / 4) * 0.2;\n\tskin.head.rotation.x = Math.sin(time / 5) * 0.1;\n\n\t// Always add an angle for cape around the x axis\n\tlet basicCapeRotationX = Math.PI * 0.06;\n\tplayer.cape.rotation.x = Math.sin(time / 1.5) * 0.06 + basicCapeRotationX;\n};\n\nlet RunningAnimation = (player, time) => {\n\tlet skin = player.skin;\n\n\ttime *= 15;\n\n\t// Leg swing with larger amplitude\n\tskin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3;\n\tskin.rightLeg.rotation.x = Math.cos(time) * 1.3;\n\n\t// Arm swing\n\tskin.leftArm.rotation.x = Math.cos(time) * 1.5;\n\tskin.rightArm.rotation.x = Math.cos(time + Math.PI) * 1.5;\n\tlet basicArmRotationZ = Math.PI * 0.1;\n\tskin.leftArm.rotation.z = Math.cos(time) * 0.1 + basicArmRotationZ;\n\tskin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.1 - basicArmRotationZ;\n\n\t// Jumping\n\tplayer.position.y = Math.cos(time * 2);\n\t// Dodging when running\n\tplayer.position.x = Math.cos(time) * 0.15;\n\t// Slightly tilting when running\n\tplayer.rotation.z = Math.cos(time + Math.PI) * 0.01;\n\n\t// Apply higher swing frequency, lower amplitude,\n\t// and greater basic rotation around x axis,\n\t// to cape when running.\n\tlet basicCapeRotationX = Math.PI * 0.3;\n\tplayer.cape.rotation.x = Math.sin(time * 2) * 0.1 + basicCapeRotationX;\n\n\t// What about head shaking?\n\t// You shouldn't glance right and left when running dude :P\n};\n\nlet RotatingAnimation = (player, time) => {\n\tplayer.rotation.y = time;\n};\n\nexport {\n\tCompositeAnimation,\n\tinvokeAnimation,\n\tWalkingAnimation,\n\tRunningAnimation,\n\tRotatingAnimation\n};\n","function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) {\n\tlet imgData = context.getImageData(sX, sY, w, h);\n\tif (flipHorizontal) {\n\t\tfor (let y = 0; y < h; y++) {\n\t\t\tfor (let x = 0; x < (w / 2); x++) {\n\t\t\t\tlet index = (x + y * w) * 4;\n\t\t\t\tlet index2 = ((w - x - 1) + y * w) * 4;\n\t\t\t\tlet pA1 = imgData.data[index];\n\t\t\t\tlet pA2 = imgData.data[index + 1];\n\t\t\t\tlet pA3 = imgData.data[index + 2];\n\t\t\t\tlet pA4 = imgData.data[index + 3];\n\n\t\t\t\tlet pB1 = imgData.data[index2];\n\t\t\t\tlet pB2 = imgData.data[index2 + 1];\n\t\t\t\tlet pB3 = imgData.data[index2 + 2];\n\t\t\t\tlet pB4 = imgData.data[index2 + 3];\n\n\t\t\t\timgData.data[index] = pB1;\n\t\t\t\timgData.data[index + 1] = pB2;\n\t\t\t\timgData.data[index + 2] = pB3;\n\t\t\t\timgData.data[index + 3] = pB4;\n\n\t\t\t\timgData.data[index2] = pA1;\n\t\t\t\timgData.data[index2 + 1] = pA2;\n\t\t\t\timgData.data[index2 + 2] = pA3;\n\t\t\t\timgData.data[index2 + 3] = pA4;\n\t\t\t}\n\t\t}\n\t}\n\tcontext.putImageData(imgData, dX, dY);\n}\n\nfunction hasTransparency(context, x0, y0, w, h) {\n\tlet imgData = context.getImageData(x0, y0, w, h);\n\tfor (let x = 0; x < w; x++) {\n\t\tfor (let y = 0; y < h; y++) {\n\t\t\tlet offset = (x + y * w) * 4;\n\t\t\tif (imgData.data[offset + 3] !== 0xff) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction computeSkinScale(width) {\n\treturn width / 64.0;\n}\n\nfunction fixOpaqueSkin(context, width) {\n\t// Some ancient skins don't have transparent pixels (nor have helm).\n\t// We have to make the helm area transparent, otherwise it will be rendered as black.\n\tif (!hasTransparency(context, 0, 0, width, width / 2)) {\n\t\tlet scale = computeSkinScale(width);\n\t\tlet clearArea = (x, y, w, h) => context.clearRect(x * scale, y * scale, w * scale, h * scale);\n\t\tclearArea(40, 0, 8, 8); // Helm Top\n\t\tclearArea(48, 0, 8, 8); // Helm Bottom\n\t\tclearArea(32, 8, 8, 8); // Helm Right\n\t\tclearArea(40, 8, 8, 8); // Helm Front\n\t\tclearArea(48, 8, 8, 8); // Helm Left\n\t\tclearArea(56, 8, 8, 8); // Helm Back\n\t}\n}\n\nfunction convertSkinTo1_8(context, width) {\n\tlet scale = computeSkinScale(width);\n\tlet copySkin = (sX, sY, w, h, dX, dY, flipHorizontal) => copyImage(context, sX * scale, sY * scale, w * scale, h * scale, dX * scale, dY * scale, flipHorizontal);\n\n\tfixOpaqueSkin(context, width);\n\n\tcopySkin(4, 16, 4, 4, 20, 48, true); // Top Leg\n\tcopySkin(8, 16, 4, 4, 24, 48, true); // Bottom Leg\n\tcopySkin(0, 20, 4, 12, 24, 52, true); // Outer Leg\n\tcopySkin(4, 20, 4, 12, 20, 52, true); // Front Leg\n\tcopySkin(8, 20, 4, 12, 16, 52, true); // Inner Leg\n\tcopySkin(12, 20, 4, 12, 28, 52, true); // Back Leg\n\tcopySkin(44, 16, 4, 4, 36, 48, true); // Top Arm\n\tcopySkin(48, 16, 4, 4, 40, 48, true); // Bottom Arm\n\tcopySkin(40, 20, 4, 12, 40, 52, true); // Outer Arm\n\tcopySkin(44, 20, 4, 12, 36, 52, true); // Front Arm\n\tcopySkin(48, 20, 4, 12, 32, 52, true); // Inner Arm\n\tcopySkin(52, 20, 4, 12, 44, 52, true); // Back Arm\n}\n\nfunction loadSkinToCanvas(canvas, image) {\n\tlet isOldFormat = false;\n\tif (image.width !== image.height) {\n\t\tif (image.width === 2 * image.height) {\n\t\t\tisOldFormat = true;\n\t\t} else {\n\t\t\tthrow `Bad skin size: ${image.width}x${image.height}`;\n\t\t}\n\t}\n\n\tlet context = canvas.getContext(\"2d\");\n\tif (isOldFormat) {\n\t\tlet sideLength = image.width;\n\t\tcanvas.width = sideLength;\n\t\tcanvas.height = sideLength;\n\t\tcontext.clearRect(0, 0, sideLength, sideLength);\n\t\tcontext.drawImage(image, 0, 0, sideLength, sideLength / 2.0);\n\t\tconvertSkinTo1_8(context, sideLength);\n\t} else {\n\t\tcanvas.width = image.width;\n\t\tcanvas.height = image.height;\n\t\tcontext.clearRect(0, 0, image.width, image.height);\n\t\tcontext.drawImage(image, 0, 0, canvas.width, canvas.height);\n\t}\n}\n\nfunction loadCapeToCanvas(canvas, image) {\n\tlet isOldFormat = false;\n\tif (image.width !== 2 * image.height) {\n\t\tif (image.width * 17 == image.height * 22) {\n\t\t\t// width/height = 22/17\n\t\t\tisOldFormat = true;\n\t\t} else {\n\t\t\tthrow `Bad cape size: ${image.width}x${image.height}`;\n\t\t}\n\t}\n\n\tlet context = canvas.getContext(\"2d\");\n\tif (isOldFormat) {\n\t\tlet width = image.width * 64 / 22;\n\t\tcanvas.width = width;\n\t\tcanvas.height = width / 2;\n\t} else {\n\t\tcanvas.width = image.width;\n\t\tcanvas.height = image.height;\n\t}\n\tcontext.clearRect(0, 0, canvas.width, canvas.height);\n\tcontext.drawImage(image, 0, 0, image.width, image.height);\n}\n\nfunction isSlimSkin(canvasOrImage) {\n\t// Detects whether the skin is default or slim.\n\t//\n\t// The right arm area of *default* skins:\n\t// (44,16)->*-------*-------*\n\t// (40,20) |top |bottom |\n\t// \\|/ |4x4 |4x4 |\n\t// *-------*-------*-------*-------*\n\t// |right |front |left |back |\n\t// |4x12 |4x12 |4x12 |4x12 |\n\t// *-------*-------*-------*-------*\n\t// The right arm area of *slim* skins:\n\t// (44,16)->*------*------*-*\n\t// (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4]\n\t// \\|/ |3x4 |3x4 | |\n\t// *-------*------*------***-----*-*\n\t// |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12]\n\t// |4x12 |3x12 |4x12 |3x12 | |\n\t// *-------*------*-------*------*-*\n\t// Compared with default right arms, slim right arms have 2 unused areas.\n\t//\n\t// The same is true for left arm:\n\t// The left arm area of *default* skins:\n\t// (36,48)->*-------*-------*\n\t// (32,52) |top |bottom |\n\t// \\|/ |4x4 |4x4 |\n\t// *-------*-------*-------*-------*\n\t// |right |front |left |back |\n\t// |4x12 |4x12 |4x12 |4x12 |\n\t// *-------*-------*-------*-------*\n\t// The left arm area of *slim* skins:\n\t// (36,48)->*------*------*-*\n\t// (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4]\n\t// \\|/ |3x4 |3x4 | |\n\t// *-------*------*------***-----*-*\n\t// |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12]\n\t// |4x12 |3x12 |4x12 |3x12 | |\n\t// *-------*------*-------*------*-*\n\t//\n\t// If there is a transparent pixel in any of the 4 unused areas, the skin must be slim,\n\t// as transparent pixels are not allowed in the first layer.\n\n\tif (canvasOrImage instanceof HTMLCanvasElement) {\n\t\tlet canvas = canvasOrImage;\n\t\tlet scale = computeSkinScale(canvas.width);\n\t\tlet context = canvas.getContext(\"2d\");\n\t\tlet checkArea = (x, y, w, h) => hasTransparency(context, x * scale, y * scale, w * scale, h * scale);\n\t\treturn checkArea(50, 16, 2, 4) ||\n\t\t\tcheckArea(54, 20, 2, 12) ||\n\t\t\tcheckArea(42, 48, 2, 4) ||\n\t\t\tcheckArea(46, 52, 2, 12);\n\t} else if (canvasOrImage instanceof HTMLImageElement) {\n\t\tlet image = canvasOrImage;\n\t\tlet canvas = document.createElement(\"canvas\");\n\t\tloadSkinToCanvas(canvas, image);\n\t\treturn isSlimSkin(canvas);\n\t} else {\n\t\tthrow `Illegal argument: ${canvasOrImage}`;\n\t}\n}\n\nexport { isSlimSkin, loadSkinToCanvas, loadCapeToCanvas };\n","import * as THREE from \"three\";\nimport { PlayerObject } from \"./model\";\nimport { invokeAnimation } from \"./animation\";\nimport { loadSkinToCanvas,loadCapeToCanvas, isSlimSkin } from \"./utils\";\n\nclass SkinViewer {\n\tconstructor(options) {\n\t\tthis.domElement = options.domElement;\n\t\tthis.animation = options.animation || null;\n\t\tthis.detectModel = options.detectModel !== false; // true by default\n\t\tthis.animationPaused = false;\n\t\tthis.animationTime = 0;\n\t\tthis.disposed = false;\n\n\t\t// texture\n\t\tthis.skinImg = new Image();\n\t\tthis.skinCanvas = document.createElement(\"canvas\");\n\t\tthis.skinTexture = new THREE.Texture(this.skinCanvas);\n\t\tthis.skinTexture.magFilter = THREE.NearestFilter;\n\t\tthis.skinTexture.minFilter = THREE.NearestFilter;\n\n\t\tthis.capeImg = new Image();\n\t\tthis.capeCanvas = document.createElement(\"canvas\");\n\t\tthis.capeTexture = new THREE.Texture(this.capeCanvas);\n\t\tthis.capeTexture.magFilter = THREE.NearestFilter;\n\t\tthis.capeTexture.minFilter = THREE.NearestFilter;\n\n\t\tthis.layer1Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, side: THREE.FrontSide });\n\t\tthis.layer2Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 });\n\t\tthis.capeMaterial = new THREE.MeshBasicMaterial({ map: this.capeTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 });\n\n\t\t// scene\n\t\tthis.scene = new THREE.Scene();\n\n\t\t// Use smaller fov to avoid distortion\n\t\tthis.camera = new THREE.PerspectiveCamera(40);\n\t\tthis.camera.position.y = -12;\n\t\tthis.camera.position.z = 60;\n\n\t\tthis.renderer = new THREE.WebGLRenderer({ angleRot: true, alpha: true, antialias: false });\n\t\tthis.renderer.setSize(300, 300); // default size\n\t\tthis.renderer.context.getShaderInfoLog = () => \"\"; // shut firefox up\n\t\tthis.domElement.appendChild(this.renderer.domElement);\n\n\t\tthis.playerObject = new PlayerObject(this.layer1Material, this.layer2Material, this.capeMaterial);\n\t\tthis.scene.add(this.playerObject);\n\n\t\t// texture loading\n\t\tthis.skinImg.crossOrigin = \"anonymous\";\n\t\tthis.skinImg.onerror = () => console.error(\"Failed loading \" + this.skinImg.src);\n\t\tthis.skinImg.onload = () => {\n\t\t\tloadSkinToCanvas(this.skinCanvas, this.skinImg);\n\n\t\t\tif (this.detectModel) {\n\t\t\t\tthis.playerObject.skin.slim = isSlimSkin(this.skinCanvas);\n\t\t\t}\n\n\t\t\tthis.skinTexture.needsUpdate = true;\n\t\t\tthis.layer1Material.needsUpdate = true;\n\t\t\tthis.layer2Material.needsUpdate = true;\n\n\t\t\tthis.playerObject.skin.visible = true;\n\t\t};\n\n\t\tthis.capeImg.crossOrigin = \"anonymous\";\n\t\tthis.capeImg.onerror = () => console.error(\"Failed loading \" + this.capeImg.src);\n\t\tthis.capeImg.onload = () => {\n\t\t\tloadCapeToCanvas(this.capeCanvas, this.capeImg);\n\n\t\t\tthis.capeTexture.needsUpdate = true;\n\t\t\tthis.capeMaterial.needsUpdate = true;\n\n\t\t\tthis.playerObject.cape.visible = true;\n\t\t};\n\n\t\tif (options.skinUrl) this.skinUrl = options.skinUrl;\n\t\tif (options.capeUrl) this.capeUrl = options.capeUrl;\n\t\tif (options.width) this.width = options.width;\n\t\tif (options.height) this.height = options.height;\n\n\t\tlet draw = () => {\n\t\t\tif (this.disposed) return;\n\t\t\twindow.requestAnimationFrame(draw);\n\t\t\tif (!this.animationPaused) {\n\t\t\t\tthis.animationTime++;\n\t\t\t\tif (this.animation) {\n\t\t\t\t\tinvokeAnimation(this.animation, this.playerObject, this.animationTime / 100.0);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.renderer.render(this.scene, this.camera);\n\t\t};\n\t\tdraw();\n\t}\n\n\tsetSize(width, height) {\n\t\tthis.camera.aspect = width / height;\n\t\tthis.camera.updateProjectionMatrix();\n\t\tthis.renderer.setSize(width, height);\n\t}\n\n\tdispose() {\n\t\tthis.disposed = true;\n\t\tthis.domElement.removeChild(this.renderer.domElement);\n\t\tthis.renderer.dispose();\n\t\tthis.skinTexture.dispose();\n\t\tthis.capeTexture.dispose();\n\t}\n\n\tget skinUrl() {\n\t\treturn this.skinImg.src;\n\t}\n\n\tset skinUrl(url) {\n\t\tthis.skinImg.src = url;\n\t}\n\n\tget capeUrl() {\n\t\treturn this.capeImg.src;\n\t}\n\n\tset capeUrl(url) {\n\t\tthis.capeImg.src = url;\n\t}\n\n\tget width() {\n\t\treturn this.renderer.getSize().width;\n\t}\n\n\tset width(newWidth) {\n\t\tthis.setSize(newWidth, this.height);\n\t}\n\n\tget height() {\n\t\treturn this.renderer.getSize().height;\n\t}\n\n\tset height(newHeight) {\n\t\tthis.setSize(this.width, newHeight);\n\t}\n}\n\nexport { SkinViewer };\n","import * as THREE from \"three\";\n\nclass OrbitControls extends THREE.EventDispatcher {\n\t/**\n\t * @preserve\n\t * The code was originally from https://github.com/mrdoob/three.js/blob/d45a042cf962e9b1aa9441810ba118647b48aacb/examples/js/controls/OrbitControls.js\n\t */\n\t/**\n\t * @license\n\t * Copyright (C) 2010-2017 three.js authors\n\t *\n\t * Permission is hereby granted, free of charge, to any person obtaining a copy\n\t * of this software and associated documentation files (the \"Software\"), to deal\n\t * in the Software without restriction, including without limitation the rights\n\t * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\t * copies of the Software, and to permit persons to whom the Software is\n\t * furnished to do so, subject to the following conditions:\n\t *\n\t * The above copyright notice and this permission notice shall be included in\n\t * all copies or substantial portions of the Software.\n\t *\n\t * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\t * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\t * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\t * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\t * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\t * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n\t * THE SOFTWARE.\n\t *\n\t *\n\t * @author qiao / https://github.com/qiao\n\t * @author mrdoob / http://mrdoob.com\n\t * @author alteredq / http://alteredqualia.com/\n\t * @author WestLangley / http://github.com/WestLangley\n\t * @author erich666 / http://erichaines.com\n\t */\n\n\t// This set of controls performs orbiting, dollying (zooming), and panning.\n\t// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n\t//\n\t// Orbit - left mouse / touch: one finger move\n\t// Zoom - middle mouse, or mousewheel / touch: two finger spread or squish\n\t// Pan - right mouse, or arrow keys / touch: three finger swipe\n\n\tconstructor(object, domElement) {\n\t\tsuper();\n\t\tthis.object = object;\n\t\tthis.domElement = (domElement !== undefined) ? domElement : document;\n\n\t\t// Set to false to disable this control\n\t\tthis.enabled = true;\n\n\t\t// \"target\" sets the location of focus, where the object orbits around\n\t\tthis.target = new THREE.Vector3();\n\n\t\t// How far you can dolly in and out (PerspectiveCamera only)\n\t\tthis.minDistance = 0;\n\t\tthis.maxDistance = Infinity;\n\n\t\t// How far you can zoom in and out (OrthographicCamera only)\n\t\tthis.minZoom = 0;\n\t\tthis.maxZoom = Infinity;\n\n\t\t// How far you can orbit vertically, upper and lower limits.\n\t\t// Range is 0 to Math.PI radians.\n\t\tthis.minPolarAngle = 0; // radians\n\t\tthis.maxPolarAngle = Math.PI; // radians\n\n\t\t// How far you can orbit horizontally, upper and lower limits.\n\t\t// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].\n\t\tthis.minAzimuthAngle = -Infinity; // radians\n\t\tthis.maxAzimuthAngle = Infinity; // radians\n\n\t\t// Set to true to enable damping (inertia)\n\t\t// If damping is enabled, you must call controls.update() in your animation loop\n\t\tthis.enableDamping = false;\n\t\tthis.dampingFactor = 0.25;\n\n\t\t// This option actually enables dollying in and out; left as \"zoom\" for backwards compatibility.\n\t\t// Set to false to disable zooming\n\t\tthis.enableZoom = true;\n\t\tthis.zoomSpeed = 1.0;\n\n\t\t// Set to false to disable rotating\n\t\tthis.enableRotate = true;\n\t\tthis.rotateSpeed = 1.0;\n\n\t\t// Set to false to disable panning\n\t\tthis.enablePan = true;\n\t\tthis.keyPanSpeed = 7.0; // pixels moved per arrow key push\n\n\t\t// Set to true to automatically rotate around the target\n\t\t// If auto-rotate is enabled, you must call controls.update() in your animation loop\n\t\tthis.autoRotate = false;\n\t\tthis.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\n\n\t\t// Set to false to disable use of the keys\n\t\tthis.enableKeys = true;\n\n\t\t// The four arrow keys\n\t\tthis.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\n\n\t\t// Mouse buttons\n\t\tthis.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };\n\n\t\t// for reset\n\t\tthis.target0 = this.target.clone();\n\t\tthis.position0 = this.object.position.clone();\n\t\tthis.zoom0 = this.object.zoom;\n\n\t\t//\n\t\t// public methods\n\t\t//\n\t\tthis.getPolarAngle = function () {\n\t\t\treturn spherical.phi;\n\t\t};\n\t\tthis.getAzimuthalAngle = function () {\n\t\t\treturn spherical.theta;\n\t\t};\n\t\tthis.saveState = function () {\n\t\t\tscope.target0.copy(scope.target);\n\t\t\tscope.position0.copy(scope.object.position);\n\t\t\tscope.zoom0 = scope.object.zoom;\n\t\t};\n\t\tthis.reset = function () {\n\t\t\tscope.target.copy(scope.target0);\n\t\t\tscope.object.position.copy(scope.position0);\n\t\t\tscope.object.zoom = scope.zoom0;\n\t\t\tscope.object.updateProjectionMatrix();\n\t\t\tscope.dispatchEvent(changeEvent);\n\t\t\tscope.update();\n\t\t\tstate = STATE.NONE;\n\t\t};\n\n\t\t// this method is exposed, but perhaps it would be better if we can make it private...\n\t\tthis.update = function () {\n\t\t\tlet offset = new THREE.Vector3();\n\t\t\t// so camera.up is the orbit axis\n\t\t\tlet quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));\n\t\t\tlet quatInverse = quat.clone().inverse();\n\t\t\tlet lastPosition = new THREE.Vector3();\n\t\t\tlet lastQuaternion = new THREE.Quaternion();\n\t\t\treturn function update() {\n\t\t\t\tlet position = scope.object.position;\n\t\t\t\toffset.copy(position).sub(scope.target);\n\t\t\t\t// rotate offset to \"y-axis-is-up\" space\n\t\t\t\toffset.applyQuaternion(quat);\n\t\t\t\t// angle from z-axis around y-axis\n\t\t\t\tspherical.setFromVector3(offset);\n\t\t\t\tif (scope.autoRotate && state === STATE.NONE) {\n\t\t\t\t\trotateLeft(getAutoRotationAngle());\n\t\t\t\t}\n\t\t\t\tspherical.theta += sphericalDelta.theta;\n\t\t\t\tspherical.phi += sphericalDelta.phi;\n\t\t\t\t// restrict theta to be between desired limits\n\t\t\t\tspherical.theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta));\n\t\t\t\t// restrict phi to be between desired limits\n\t\t\t\tspherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));\n\t\t\t\tspherical.makeSafe();\n\t\t\t\tspherical.radius *= scale;\n\t\t\t\t// restrict radius to be between desired limits\n\t\t\t\tspherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));\n\t\t\t\t// move target to panned location\n\t\t\t\tscope.target.add(panOffset);\n\t\t\t\toffset.setFromSpherical(spherical);\n\t\t\t\t// rotate offset back to \"camera-up-vector-is-up\" space\n\t\t\t\toffset.applyQuaternion(quatInverse);\n\t\t\t\tposition.copy(scope.target).add(offset);\n\t\t\t\tscope.object.lookAt(scope.target);\n\t\t\t\tif (scope.enableDamping === true) {\n\t\t\t\t\tsphericalDelta.theta *= (1 - scope.dampingFactor);\n\t\t\t\t\tsphericalDelta.phi *= (1 - scope.dampingFactor);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsphericalDelta.set(0, 0, 0);\n\t\t\t\t}\n\t\t\t\tscale = 1;\n\t\t\t\tpanOffset.set(0, 0, 0);\n\t\t\t\t// update condition is:\n\t\t\t\t// min(camera displacement, camera rotation in radians)^2 > EPS\n\t\t\t\t// using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\t\t\t\tif (zoomChanged ||\n\t\t\t\t\tlastPosition.distanceToSquared(scope.object.position) > EPS ||\n\t\t\t\t\t8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {\n\t\t\t\t\tscope.dispatchEvent(changeEvent);\n\t\t\t\t\tlastPosition.copy(scope.object.position);\n\t\t\t\t\tlastQuaternion.copy(scope.object.quaternion);\n\t\t\t\t\tzoomChanged = false;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}();\n\t\tthis.dispose = function () {\n\t\t\tscope.domElement.removeEventListener(\"contextmenu\", onContextMenu, false);\n\t\t\tscope.domElement.removeEventListener(\"mousedown\", onMouseDown, false);\n\t\t\tscope.domElement.removeEventListener(\"wheel\", onMouseWheel, false);\n\t\t\tscope.domElement.removeEventListener(\"touchstart\", onTouchStart, false);\n\t\t\tscope.domElement.removeEventListener(\"touchend\", onTouchEnd, false);\n\t\t\tscope.domElement.removeEventListener(\"touchmove\", onTouchMove, false);\n\t\t\tdocument.removeEventListener(\"mousemove\", onMouseMove, false);\n\t\t\tdocument.removeEventListener(\"mouseup\", onMouseUp, false);\n\t\t\twindow.removeEventListener(\"keydown\", onKeyDown, false);\n\t\t\t//scope.dispatchEvent({ type: \"dispose\" }); // should this be added here?\n\t\t};\n\t\t//\n\t\t// internals\n\t\t//\n\t\tlet scope = this;\n\t\tlet changeEvent = { type: \"change\" };\n\t\tlet startEvent = { type: \"start\" };\n\t\tlet endEvent = { type: \"end\" };\n\t\tlet STATE = { NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 };\n\t\tlet state = STATE.NONE;\n\t\tlet EPS = 0.000001;\n\t\t// current position in spherical coordinates\n\t\tlet spherical = new THREE.Spherical();\n\t\tlet sphericalDelta = new THREE.Spherical();\n\t\tlet scale = 1;\n\t\tlet panOffset = new THREE.Vector3();\n\t\tlet zoomChanged = false;\n\t\tlet rotateStart = new THREE.Vector2();\n\t\tlet rotateEnd = new THREE.Vector2();\n\t\tlet rotateDelta = new THREE.Vector2();\n\t\tlet panStart = new THREE.Vector2();\n\t\tlet panEnd = new THREE.Vector2();\n\t\tlet panDelta = new THREE.Vector2();\n\t\tlet dollyStart = new THREE.Vector2();\n\t\tlet dollyEnd = new THREE.Vector2();\n\t\tlet dollyDelta = new THREE.Vector2();\n\t\tfunction getAutoRotationAngle() {\n\t\t\treturn 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n\t\t}\n\t\tfunction getZoomScale() {\n\t\t\treturn Math.pow(0.95, scope.zoomSpeed);\n\t\t}\n\t\tfunction rotateLeft(angle) {\n\t\t\tsphericalDelta.theta -= angle;\n\t\t}\n\t\tfunction rotateUp(angle) {\n\t\t\tsphericalDelta.phi -= angle;\n\t\t}\n\t\tlet panLeft = function () {\n\t\t\tlet v = new THREE.Vector3();\n\t\t\treturn function panLeft(distance, objectMatrix) {\n\t\t\t\tv.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix\n\t\t\t\tv.multiplyScalar(-distance);\n\t\t\t\tpanOffset.add(v);\n\t\t\t};\n\t\t}();\n\t\tlet panUp = function () {\n\t\t\tlet v = new THREE.Vector3();\n\t\t\treturn function panUp(distance, objectMatrix) {\n\t\t\t\tv.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix\n\t\t\t\tv.multiplyScalar(distance);\n\t\t\t\tpanOffset.add(v);\n\t\t\t};\n\t\t}();\n\t\t// deltaX and deltaY are in pixels; right and down are positive\n\t\tlet pan = function () {\n\t\t\tlet offset = new THREE.Vector3();\n\t\t\treturn function pan(deltaX, deltaY) {\n\t\t\t\tlet element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\t\t\t\t// perspective\n\t\t\t\t\tlet position = scope.object.position;\n\t\t\t\t\toffset.copy(position).sub(scope.target);\n\t\t\t\t\tlet targetDistance = offset.length();\n\t\t\t\t\t// half of the fov is center to top of screen\n\t\t\t\t\ttargetDistance *= Math.tan((scope.object.fov / 2) * Math.PI / 180.0);\n\t\t\t\t\t// we actually don't use screenWidth, since perspective camera is fixed to screen height\n\t\t\t\t\tpanLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);\n\t\t\t\t\tpanUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);\n\t\t\t\t}\n\t\t\t\telse if (scope.object instanceof THREE.OrthographicCamera) {\n\t\t\t\t\t// orthographic\n\t\t\t\t\tpanLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);\n\t\t\t\t\tpanUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// camera neither orthographic nor perspective\n\t\t\t\t\tconsole.warn(\"WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.\");\n\t\t\t\t\tscope.enablePan = false;\n\t\t\t\t}\n\t\t\t};\n\t\t}();\n\t\tfunction dollyIn(dollyScale) {\n\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\t\t\tscale /= dollyScale;\n\t\t\t}\n\t\t\telse if (scope.object instanceof THREE.OrthographicCamera) {\n\t\t\t\tscope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));\n\t\t\t\tscope.object.updateProjectionMatrix();\n\t\t\t\tzoomChanged = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconsole.warn(\"WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.\");\n\t\t\t\tscope.enableZoom = false;\n\t\t\t}\n\t\t}\n\t\tfunction dollyOut(dollyScale) {\n\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\t\t\tscale *= dollyScale;\n\t\t\t}\n\t\t\telse if (scope.object instanceof THREE.OrthographicCamera) {\n\t\t\t\tscope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));\n\t\t\t\tscope.object.updateProjectionMatrix();\n\t\t\t\tzoomChanged = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconsole.warn(\"WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.\");\n\t\t\t\tscope.enableZoom = false;\n\t\t\t}\n\t\t}\n\t\t//\n\t\t// event callbacks - update the object state\n\t\t//\n\t\tfunction handleMouseDownRotate(event) {\n\t\t\trotateStart.set(event.clientX, event.clientY);\n\t\t}\n\t\tfunction handleMouseDownDolly(event) {\n\t\t\tdollyStart.set(event.clientX, event.clientY);\n\t\t}\n\t\tfunction handleMouseDownPan(event) {\n\t\t\tpanStart.set(event.clientX, event.clientY);\n\t\t}\n\t\tfunction handleMouseMoveRotate(event) {\n\t\t\trotateEnd.set(event.clientX, event.clientY);\n\t\t\trotateDelta.subVectors(rotateEnd, rotateStart);\n\t\t\tlet element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\t\t// rotating across whole screen goes 360 degrees around\n\t\t\trotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);\n\t\t\t// rotating up and down along whole screen attempts to go 360, but limited to 180\n\t\t\trotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);\n\t\t\trotateStart.copy(rotateEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleMouseMoveDolly(event) {\n\t\t\tdollyEnd.set(event.clientX, event.clientY);\n\t\t\tdollyDelta.subVectors(dollyEnd, dollyStart);\n\t\t\tif (dollyDelta.y > 0) {\n\t\t\t\tdollyIn(getZoomScale());\n\t\t\t}\n\t\t\telse if (dollyDelta.y < 0) {\n\t\t\t\tdollyOut(getZoomScale());\n\t\t\t}\n\t\t\tdollyStart.copy(dollyEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleMouseMovePan(event) {\n\t\t\tpanEnd.set(event.clientX, event.clientY);\n\t\t\tpanDelta.subVectors(panEnd, panStart);\n\t\t\tpan(panDelta.x, panDelta.y);\n\t\t\tpanStart.copy(panEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleMouseUp(event) {\n\t\t}\n\t\tfunction handleMouseWheel(event) {\n\t\t\tif (event.deltaY < 0) {\n\t\t\t\tdollyOut(getZoomScale());\n\t\t\t}\n\t\t\telse if (event.deltaY > 0) {\n\t\t\t\tdollyIn(getZoomScale());\n\t\t\t}\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleKeyDown(event) {\n\t\t\tswitch (event.keyCode) {\n\t\t\t\tcase scope.keys.UP:\n\t\t\t\t\tpan(0, scope.keyPanSpeed);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.keys.BOTTOM:\n\t\t\t\t\tpan(0, -scope.keyPanSpeed);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.keys.LEFT:\n\t\t\t\t\tpan(scope.keyPanSpeed, 0);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.keys.RIGHT:\n\t\t\t\t\tpan(-scope.keyPanSpeed, 0);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfunction handleTouchStartRotate(event) {\n\t\t\trotateStart.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t}\n\t\tfunction handleTouchStartDolly(event) {\n\t\t\tlet dx = event.touches[0].pageX - event.touches[1].pageX;\n\t\t\tlet dy = event.touches[0].pageY - event.touches[1].pageY;\n\t\t\tlet distance = Math.sqrt(dx * dx + dy * dy);\n\t\t\tdollyStart.set(0, distance);\n\t\t}\n\t\tfunction handleTouchStartPan(event) {\n\t\t\tpanStart.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t}\n\t\tfunction handleTouchMoveRotate(event) {\n\t\t\trotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t\trotateDelta.subVectors(rotateEnd, rotateStart);\n\t\t\tlet element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\t\trotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);\n\t\t\trotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);\n\t\t\trotateStart.copy(rotateEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleTouchMoveDolly(event) {\n\t\t\tlet dx = event.touches[0].pageX - event.touches[1].pageX;\n\t\t\tlet dy = event.touches[0].pageY - event.touches[1].pageY;\n\t\t\tlet distance = Math.sqrt(dx * dx + dy * dy);\n\t\t\tdollyEnd.set(0, distance);\n\t\t\tdollyDelta.subVectors(dollyEnd, dollyStart);\n\t\t\tif (dollyDelta.y > 0) {\n\t\t\t\tdollyOut(getZoomScale());\n\t\t\t}\n\t\t\telse if (dollyDelta.y < 0) {\n\t\t\t\tdollyIn(getZoomScale());\n\t\t\t}\n\t\t\tdollyStart.copy(dollyEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleTouchMovePan(event) {\n\t\t\tpanEnd.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t\tpanDelta.subVectors(panEnd, panStart);\n\t\t\tpan(panDelta.x, panDelta.y);\n\t\t\tpanStart.copy(panEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleTouchEnd(event) {\n\t\t}\n\t\t//\n\t\t// event handlers - FSM: listen for events and reset state\n\t\t//\n\t\tfunction onMouseDown(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (event.button) {\n\t\t\t\tcase scope.mouseButtons.ORBIT:\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseDownRotate(event);\n\t\t\t\t\tstate = STATE.ROTATE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.mouseButtons.ZOOM:\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseDownDolly(event);\n\t\t\t\t\tstate = STATE.DOLLY;\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.mouseButtons.PAN:\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseDownPan(event);\n\t\t\t\t\tstate = STATE.PAN;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t\tif (state !== STATE.NONE) {\n\t\t\t\tdocument.addEventListener(\"mousemove\", onMouseMove, false);\n\t\t\t\tdocument.addEventListener(\"mouseup\", onMouseUp, false);\n\t\t\t\tscope.dispatchEvent(startEvent);\n\t\t\t}\n\t\t}\n\t\tfunction onMouseMove(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (state) {\n\t\t\t\tcase STATE.ROTATE:\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseMoveRotate(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase STATE.DOLLY:\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseMoveDolly(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase STATE.PAN:\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseMovePan(event);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t}\n\t\tfunction onMouseUp(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\thandleMouseUp(event);\n\t\t\tdocument.removeEventListener(\"mousemove\", onMouseMove, false);\n\t\t\tdocument.removeEventListener(\"mouseup\", onMouseUp, false);\n\t\t\tscope.dispatchEvent(endEvent);\n\t\t\tstate = STATE.NONE;\n\t\t}\n\t\tfunction onMouseWheel(event) {\n\t\t\tif (scope.enabled === false || scope.enableZoom === false || (state !== STATE.NONE && state !== STATE.ROTATE))\n\t\t\t\treturn;\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\thandleMouseWheel(event);\n\t\t\tscope.dispatchEvent(startEvent); // not sure why these are here...\n\t\t\tscope.dispatchEvent(endEvent);\n\t\t}\n\t\tfunction onKeyDown(event) {\n\t\t\tif (scope.enabled === false || scope.enableKeys === false || scope.enablePan === false)\n\t\t\t\treturn;\n\t\t\thandleKeyDown(event);\n\t\t}\n\t\tfunction onTouchStart(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (event.touches.length) {\n\t\t\t\tcase 1:// one-fingered touch: rotate\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleTouchStartRotate(event);\n\t\t\t\t\tstate = STATE.TOUCH_ROTATE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:// two-fingered touch: dolly\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleTouchStartDolly(event);\n\t\t\t\t\tstate = STATE.TOUCH_DOLLY;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:// three-fingered touch: pan\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleTouchStartPan(event);\n\t\t\t\t\tstate = STATE.TOUCH_PAN;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tstate = STATE.NONE;\n\t\t\t}\n\t\t\tif (state !== STATE.NONE) {\n\t\t\t\tscope.dispatchEvent(startEvent);\n\t\t\t}\n\t\t}\n\t\tfunction onTouchMove(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (event.touches.length) {\n\t\t\t\tcase 1:// one-fingered touch: rotate\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (state !== STATE.TOUCH_ROTATE)\n\t\t\t\t\t\treturn; // is this needed?...\n\t\t\t\t\thandleTouchMoveRotate(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:// two-fingered touch: dolly\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (state !== STATE.TOUCH_DOLLY)\n\t\t\t\t\t\treturn; // is this needed?...\n\t\t\t\t\thandleTouchMoveDolly(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:// three-fingered touch: pan\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (state !== STATE.TOUCH_PAN)\n\t\t\t\t\t\treturn; // is this needed?...\n\t\t\t\t\thandleTouchMovePan(event);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tstate = STATE.NONE;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t\tfunction onTouchEnd(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\thandleTouchEnd(event);\n\t\t\tscope.dispatchEvent(endEvent);\n\t\t\tstate = STATE.NONE;\n\t\t}\n\t\tfunction onContextMenu(event) {\n\t\t\tif (scope.enabled === false || scope.enablePan === false)\n\t\t\t\treturn;\n\t\t\tevent.preventDefault();\n\t\t}\n\t\t//\n\t\tscope.domElement.addEventListener(\"contextmenu\", onContextMenu, false);\n\t\tscope.domElement.addEventListener(\"mousedown\", onMouseDown, false);\n\t\tscope.domElement.addEventListener(\"wheel\", onMouseWheel, false);\n\t\tscope.domElement.addEventListener(\"touchstart\", onTouchStart, false);\n\t\tscope.domElement.addEventListener(\"touchend\", onTouchEnd, false);\n\t\tscope.domElement.addEventListener(\"touchmove\", onTouchMove, false);\n\t\twindow.addEventListener(\"keydown\", onKeyDown, false);\n\t\t// force an update at start\n\t\tthis.update();\n\t}\n}\n\nfunction createOrbitControls(skinViewer) {\n\tlet control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement);\n\n\t// default configuration\n\tcontrol.enablePan = false;\n\tcontrol.target = new THREE.Vector3(0, -12, 0);\n\tcontrol.minDistance = 10;\n\tcontrol.maxDistance = 256;\n\tcontrol.update();\n\n\treturn control;\n}\n\nexport { OrbitControls, createOrbitControls };\n"],"names":["toFaceVertices","x1","y1","x2","y2","w","h","THREE","toSkinVertices","toCapeVertices","setVertices","box","top","bottom","left","front","right","back","faceVertexUvs","esp","SkinObject","layer1Material","layer2Material","modelListeners","head","headBox","headMesh","add","head2Box","head2Mesh","renderOrder","_this","body","bodyBox","bodyMesh","body2Box","body2Mesh","position","y","rightArm","rightArmPivot","rightArmBox","rightArmMesh","push","scale","x","slim","z","uvsNeedUpdate","elementsNeedUpdate","rightArm2Box","rightArm2Mesh","leftArm","leftArmPivot","leftArmBox","leftArmMesh","leftArm2Box","leftArm2Mesh","rightLeg","rightLegPivot","rightLegBox","rightLegMesh","rightLeg2Box","rightLeg2Mesh","leftLeg","leftLegPivot","leftLegBox","leftLegMesh","leftLeg2Box","leftLeg2Mesh","this","_slim","value","forEach","listener","CapeObject","capeMaterial","capeBox","cape","_this2","PlayerObject","skin","visible","_this3","rotation","Math","PI","invokeAnimation","animation","player","time","CompositeAnimation","play","Function","AnimationHandle","paused","_paused","speed","_speed","_lastChange","_lastChangeX","dt","handles","Set","handle","remove","delete","hasTransparency","context","x0","y0","imgData","getImageData","offset","data","computeSkinScale","width","convertSkinTo1_8","copySkin","sX","sY","dX","dY","flipHorizontal","index","index2","pA1","pA2","pA3","pA4","pB1","pB2","pB3","pB4","putImageData","copyImage","clearArea","clearRect","loadSkinToCanvas","canvas","image","isOldFormat","height","getContext","sideLength","drawImage","isSlimSkin","canvasOrImage","HTMLCanvasElement","checkArea","HTMLImageElement","document","createElement","SkinViewer","options","domElement","detectModel","animationPaused","animationTime","disposed","skinImg","Image","skinCanvas","skinTexture","magFilter","minFilter","capeImg","capeCanvas","capeTexture","map","side","transparent","opacity","alphaTest","scene","camera","renderer","angleRot","alpha","antialias","setSize","getShaderInfoLog","appendChild","playerObject","crossOrigin","onerror","console","error","src","onload","needsUpdate","skinUrl","capeUrl","draw","requestAnimationFrame","render","aspect","updateProjectionMatrix","removeChild","dispose","url","getSize","newWidth","newHeight","OrbitControls","object","quat","quatInverse","lastPosition","lastQuaternion","undefined","enabled","target","minDistance","maxDistance","Infinity","minZoom","maxZoom","minPolarAngle","maxPolarAngle","minAzimuthAngle","maxAzimuthAngle","enableDamping","dampingFactor","enableZoom","zoomSpeed","enableRotate","rotateSpeed","enablePan","keyPanSpeed","autoRotate","autoRotateSpeed","enableKeys","keys","LEFT","UP","RIGHT","BOTTOM","mouseButtons","ORBIT","ZOOM","MIDDLE","PAN","target0","clone","position0","zoom0","zoom","getPolarAngle","spherical","phi","getAzimuthalAngle","theta","saveState","copy","scope","reset","dispatchEvent","changeEvent","update","STATE","NONE","setFromUnitVectors","up","inverse","sub","applyQuaternion","setFromVector3","state","sphericalDelta","max","min","makeSafe","radius","panOffset","setFromSpherical","lookAt","set","zoomChanged","distanceToSquared","EPS","dot","quaternion","removeEventListener","onContextMenu","onMouseDown","onMouseWheel","onTouchStart","onTouchEnd","onTouchMove","onMouseMove","onMouseUp","onKeyDown","type","startEvent","endEvent","ROTATE","DOLLY","TOUCH_ROTATE","TOUCH_DOLLY","TOUCH_PAN","rotateStart","rotateEnd","rotateDelta","panStart","panEnd","panDelta","dollyStart","dollyEnd","dollyDelta","getZoomScale","pow","rotateLeft","angle","rotateUp","v","panLeft","distance","objectMatrix","setFromMatrixColumn","multiplyScalar","panUp","pan","deltaX","deltaY","element","targetDistance","length","tan","fov","clientHeight","matrix","clientWidth","warn","dollyIn","dollyScale","dollyOut","event","button","clientX","clientY","preventDefault","addEventListener","subVectors","stopPropagation","keyCode","touches","pageX","pageY","dx","dy","sqrt","skinViewer","control","sin","basicArmRotationZ","cos","basicCapeRotationX"],"mappings":"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"} \ No newline at end of file diff --git a/js/build/skinview3d.module.js b/js/build/skinview3d.module.js deleted file mode 100644 index 8b6a241..0000000 --- a/js/build/skinview3d.module.js +++ /dev/null @@ -1,1421 +0,0 @@ -/** - * skinview3d (https://github.com/to2mbn/skinview3d) - * - * MIT License - * - * Copyright (c) 2014-2018 Kent Rasmussen - * Copyright (c) 2017-2018 Haowei Wen, Sean Boult and contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -import { Vector2, Group, BoxGeometry, Mesh, Texture, NearestFilter, MeshBasicMaterial, FrontSide, DoubleSide, Scene, PerspectiveCamera, WebGLRenderer, Vector3, MOUSE, Quaternion, Spherical, OrthographicCamera, EventDispatcher } from 'three'; - -var classCallCheck = function (instance, Constructor) { - if (!(instance instanceof Constructor)) { - throw new TypeError("Cannot call a class as a function"); - } -}; - -var createClass = function () { - function defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } - } - - return function (Constructor, protoProps, staticProps) { - if (protoProps) defineProperties(Constructor.prototype, protoProps); - if (staticProps) defineProperties(Constructor, staticProps); - return Constructor; - }; -}(); - -var inherits = function (subClass, superClass) { - if (typeof superClass !== "function" && superClass !== null) { - throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); - } - - subClass.prototype = Object.create(superClass && superClass.prototype, { - constructor: { - value: subClass, - enumerable: false, - writable: true, - configurable: true - } - }); - if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; -}; - -var possibleConstructorReturn = function (self, call) { - if (!self) { - throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); - } - - return call && (typeof call === "object" || typeof call === "function") ? call : self; -}; - -function toFaceVertices(x1, y1, x2, y2, w, h) { - return [new Vector2(x1 / w, 1.0 - y2 / h), new Vector2(x2 / w, 1.0 - y2 / h), new Vector2(x2 / w, 1.0 - y1 / h), new Vector2(x1 / w, 1.0 - y1 / h)]; -} - -function toSkinVertices(x1, y1, x2, y2) { - return toFaceVertices(x1, y1, x2, y2, 64.0, 64.0); -} - -function toCapeVertices(x1, y1, x2, y2) { - return toFaceVertices(x1, y1, x2, y2, 64.0, 32.0); -} - -function setVertices(box, top, bottom, left, front, right, back) { - box.faceVertexUvs[0] = []; - box.faceVertexUvs[0][0] = [right[3], right[0], right[2]]; - box.faceVertexUvs[0][1] = [right[0], right[1], right[2]]; - box.faceVertexUvs[0][2] = [left[3], left[0], left[2]]; - box.faceVertexUvs[0][3] = [left[0], left[1], left[2]]; - box.faceVertexUvs[0][4] = [top[3], top[0], top[2]]; - box.faceVertexUvs[0][5] = [top[0], top[1], top[2]]; - box.faceVertexUvs[0][6] = [bottom[0], bottom[3], bottom[1]]; - box.faceVertexUvs[0][7] = [bottom[3], bottom[2], bottom[1]]; - box.faceVertexUvs[0][8] = [front[3], front[0], front[2]]; - box.faceVertexUvs[0][9] = [front[0], front[1], front[2]]; - box.faceVertexUvs[0][10] = [back[3], back[0], back[2]]; - box.faceVertexUvs[0][11] = [back[0], back[1], back[2]]; -} - -var esp = 0.002; - -var SkinObject = function (_THREE$Group) { - inherits(SkinObject, _THREE$Group); - - function SkinObject(layer1Material, layer2Material) { - classCallCheck(this, SkinObject); - - var _this = possibleConstructorReturn(this, (SkinObject.__proto__ || Object.getPrototypeOf(SkinObject)).call(this)); - - _this.modelListeners = []; // called when model(slim property) is changed - - // Head - _this.head = new Group(); - - var headBox = new BoxGeometry(8, 8, 8, 0, 0, 0); - setVertices(headBox, toSkinVertices(8, 0, 16, 8), toSkinVertices(16, 0, 24, 8), toSkinVertices(0, 8, 8, 16), toSkinVertices(8, 8, 16, 16), toSkinVertices(16, 8, 24, 16), toSkinVertices(24, 8, 32, 16)); - var headMesh = new Mesh(headBox, layer1Material); - _this.head.add(headMesh); - - var head2Box = new BoxGeometry(9, 9, 9, 0, 0, 0); - setVertices(head2Box, toSkinVertices(40, 0, 48, 8), toSkinVertices(48, 0, 56, 8), toSkinVertices(32, 8, 40, 16), toSkinVertices(40, 8, 48, 16), toSkinVertices(48, 8, 56, 16), toSkinVertices(56, 8, 64, 16)); - var head2Mesh = new Mesh(head2Box, layer2Material); - head2Mesh.renderOrder = -1; - _this.head.add(head2Mesh); - - _this.add(_this.head); - - // Body - _this.body = new Group(); - - var bodyBox = new BoxGeometry(8, 12, 4, 0, 0, 0); - setVertices(bodyBox, toSkinVertices(20, 16, 28, 20), toSkinVertices(28, 16, 36, 20), toSkinVertices(16, 20, 20, 32), toSkinVertices(20, 20, 28, 32), toSkinVertices(28, 20, 32, 32), toSkinVertices(32, 20, 40, 32)); - var bodyMesh = new Mesh(bodyBox, layer1Material); - _this.body.add(bodyMesh); - - var body2Box = new BoxGeometry(9, 13.5, 4.5, 0, 0, 0); - setVertices(body2Box, toSkinVertices(20, 32, 28, 36), toSkinVertices(28, 32, 36, 36), toSkinVertices(16, 36, 20, 48), toSkinVertices(20, 36, 28, 48), toSkinVertices(28, 36, 32, 48), toSkinVertices(32, 36, 40, 48)); - var body2Mesh = new Mesh(body2Box, layer2Material); - _this.body.add(body2Mesh); - - _this.body.position.y = -10; - _this.add(_this.body); - - // Right Arm - _this.rightArm = new Group(); - var rightArmPivot = new Group(); - - var rightArmBox = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related - var rightArmMesh = new Mesh(rightArmBox, layer1Material); - rightArmPivot.add(rightArmMesh); - _this.modelListeners.push(function () { - rightArmMesh.scale.x = (_this.slim ? 3 : 4) - esp; - rightArmMesh.scale.y = 12 - esp; - rightArmMesh.scale.z = 4 - esp; - if (_this.slim) { - setVertices(rightArmBox, toSkinVertices(44, 16, 47, 20), toSkinVertices(47, 16, 50, 20), toSkinVertices(40, 20, 44, 32), toSkinVertices(44, 20, 47, 32), toSkinVertices(47, 20, 51, 32), toSkinVertices(51, 20, 54, 32)); - } else { - setVertices(rightArmBox, toSkinVertices(44, 16, 48, 20), toSkinVertices(48, 16, 52, 20), toSkinVertices(40, 20, 44, 32), toSkinVertices(44, 20, 48, 32), toSkinVertices(48, 20, 52, 32), toSkinVertices(52, 20, 56, 32)); - } - rightArmBox.uvsNeedUpdate = true; - rightArmBox.elementsNeedUpdate = true; - }); - - var rightArm2Box = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related - var rightArm2Mesh = new Mesh(rightArm2Box, layer2Material); - rightArm2Mesh.renderOrder = 1; - rightArmPivot.add(rightArm2Mesh); - _this.modelListeners.push(function () { - rightArm2Mesh.scale.x = (_this.slim ? 3.375 : 4.5) - esp; - rightArm2Mesh.scale.y = 13.5 - esp; - rightArm2Mesh.scale.z = 4.5 - esp; - if (_this.slim) { - setVertices(rightArm2Box, toSkinVertices(44, 32, 47, 36), toSkinVertices(47, 32, 50, 36), toSkinVertices(40, 36, 44, 48), toSkinVertices(44, 36, 47, 48), toSkinVertices(47, 36, 51, 48), toSkinVertices(51, 36, 54, 48)); - } else { - setVertices(rightArm2Box, toSkinVertices(44, 32, 48, 36), toSkinVertices(48, 32, 52, 36), toSkinVertices(40, 36, 44, 48), toSkinVertices(44, 36, 48, 48), toSkinVertices(48, 36, 52, 48), toSkinVertices(52, 36, 56, 48)); - } - rightArm2Box.uvsNeedUpdate = true; - rightArm2Box.elementsNeedUpdate = true; - }); - - rightArmPivot.position.y = -6; - _this.rightArm.add(rightArmPivot); - _this.rightArm.position.y = -4; - _this.modelListeners.push(function () { - _this.rightArm.position.x = _this.slim ? -5.5 : -6; - }); - _this.add(_this.rightArm); - - // Left Arm - _this.leftArm = new Group(); - var leftArmPivot = new Group(); - - var leftArmBox = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related - var leftArmMesh = new Mesh(leftArmBox, layer1Material); - leftArmPivot.add(leftArmMesh); - _this.modelListeners.push(function () { - leftArmMesh.scale.x = (_this.slim ? 3 : 4) - esp; - leftArmMesh.scale.y = 12 - esp; - leftArmMesh.scale.z = 4 - esp; - if (_this.slim) { - setVertices(leftArmBox, toSkinVertices(36, 48, 39, 52), toSkinVertices(39, 48, 42, 52), toSkinVertices(32, 52, 36, 64), toSkinVertices(36, 52, 39, 64), toSkinVertices(39, 52, 43, 64), toSkinVertices(43, 52, 46, 64)); - } else { - setVertices(leftArmBox, toSkinVertices(36, 48, 40, 52), toSkinVertices(40, 48, 44, 52), toSkinVertices(32, 52, 36, 64), toSkinVertices(36, 52, 40, 64), toSkinVertices(40, 52, 44, 64), toSkinVertices(44, 52, 48, 64)); - } - leftArmBox.uvsNeedUpdate = true; - leftArmBox.elementsNeedUpdate = true; - }); - - var leftArm2Box = new BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related - var leftArm2Mesh = new Mesh(leftArm2Box, layer2Material); - leftArm2Mesh.renderOrder = 1; - leftArmPivot.add(leftArm2Mesh); - _this.modelListeners.push(function () { - leftArm2Mesh.scale.x = (_this.slim ? 3.375 : 4.5) - esp; - leftArm2Mesh.scale.y = 13.5 - esp; - leftArm2Mesh.scale.z = 4.5 - esp; - if (_this.slim) { - setVertices(leftArm2Box, toSkinVertices(52, 48, 55, 52), toSkinVertices(55, 48, 58, 52), toSkinVertices(48, 52, 52, 64), toSkinVertices(52, 52, 55, 64), toSkinVertices(55, 52, 59, 64), toSkinVertices(59, 52, 62, 64)); - } else { - setVertices(leftArm2Box, toSkinVertices(52, 48, 56, 52), toSkinVertices(56, 48, 60, 52), toSkinVertices(48, 52, 52, 64), toSkinVertices(52, 52, 56, 64), toSkinVertices(56, 52, 60, 64), toSkinVertices(60, 52, 64, 64)); - } - leftArm2Box.uvsNeedUpdate = true; - leftArm2Box.elementsNeedUpdate = true; - }); - - leftArmPivot.position.y = -6; - _this.leftArm.add(leftArmPivot); - _this.leftArm.position.y = -4; - _this.modelListeners.push(function () { - _this.leftArm.position.x = _this.slim ? 5.5 : 6; - }); - _this.add(_this.leftArm); - - // Right Leg - _this.rightLeg = new Group(); - var rightLegPivot = new Group(); - - var rightLegBox = new BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0); - setVertices(rightLegBox, toSkinVertices(4, 16, 8, 20), toSkinVertices(8, 16, 12, 20), toSkinVertices(0, 20, 4, 32), toSkinVertices(4, 20, 8, 32), toSkinVertices(8, 20, 12, 32), toSkinVertices(12, 20, 16, 32)); - var rightLegMesh = new Mesh(rightLegBox, layer1Material); - rightLegPivot.add(rightLegMesh); - - var rightLeg2Box = new BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0); - setVertices(rightLeg2Box, toSkinVertices(4, 32, 8, 36), toSkinVertices(8, 32, 12, 36), toSkinVertices(0, 36, 4, 48), toSkinVertices(4, 36, 8, 48), toSkinVertices(8, 36, 12, 48), toSkinVertices(12, 36, 16, 48)); - var rightLeg2Mesh = new Mesh(rightLeg2Box, layer2Material); - rightLeg2Mesh.renderOrder = 1; - rightLegPivot.add(rightLeg2Mesh); - - rightLegPivot.position.y = -6; - _this.rightLeg.add(rightLegPivot); - _this.rightLeg.position.y = -16; - _this.rightLeg.position.x = -2; - _this.add(_this.rightLeg); - - // Left Leg - _this.leftLeg = new Group(); - var leftLegPivot = new Group(); - - var leftLegBox = new BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0); - setVertices(leftLegBox, toSkinVertices(20, 48, 24, 52), toSkinVertices(24, 48, 28, 52), toSkinVertices(16, 52, 20, 64), toSkinVertices(20, 52, 24, 64), toSkinVertices(24, 52, 28, 64), toSkinVertices(28, 52, 32, 64)); - var leftLegMesh = new Mesh(leftLegBox, layer1Material); - leftLegPivot.add(leftLegMesh); - - var leftLeg2Box = new BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0); - setVertices(leftLeg2Box, toSkinVertices(4, 48, 8, 52), toSkinVertices(8, 48, 12, 52), toSkinVertices(0, 52, 4, 64), toSkinVertices(4, 52, 8, 64), toSkinVertices(8, 52, 12, 64), toSkinVertices(12, 52, 16, 64)); - var leftLeg2Mesh = new Mesh(leftLeg2Box, layer2Material); - leftLeg2Mesh.renderOrder = 1; - leftLegPivot.add(leftLeg2Mesh); - - leftLegPivot.position.y = -6; - _this.leftLeg.add(leftLegPivot); - _this.leftLeg.position.y = -16; - _this.leftLeg.position.x = 2; - _this.add(_this.leftLeg); - - _this.slim = false; - return _this; - } - - createClass(SkinObject, [{ - key: "slim", - get: function get$$1() { - return this._slim; - }, - set: function set$$1(value) { - if (this._slim !== value) { - this._slim = value; - this.modelListeners.forEach(function (listener) { - return listener(); - }); - } - } - }]); - return SkinObject; -}(Group); - -var CapeObject = function (_THREE$Group2) { - inherits(CapeObject, _THREE$Group2); - - function CapeObject(capeMaterial) { - classCallCheck(this, CapeObject); - - // back = outside - // front = inside - var _this2 = possibleConstructorReturn(this, (CapeObject.__proto__ || Object.getPrototypeOf(CapeObject)).call(this)); - - var capeBox = new BoxGeometry(10, 16, 1, 0, 0, 0); - setVertices(capeBox, toCapeVertices(1, 0, 11, 1), toCapeVertices(11, 0, 21, 1), toCapeVertices(11, 1, 12, 17), toCapeVertices(12, 1, 22, 17), toCapeVertices(0, 1, 1, 17), toCapeVertices(1, 1, 11, 17)); - _this2.cape = new Mesh(capeBox, capeMaterial); - _this2.cape.position.y = -8; - _this2.cape.position.z = -0.5; - _this2.add(_this2.cape); - return _this2; - } - - return CapeObject; -}(Group); - -var PlayerObject = function (_THREE$Group3) { - inherits(PlayerObject, _THREE$Group3); - - function PlayerObject(layer1Material, layer2Material, capeMaterial) { - classCallCheck(this, PlayerObject); - - var _this3 = possibleConstructorReturn(this, (PlayerObject.__proto__ || Object.getPrototypeOf(PlayerObject)).call(this)); - - _this3.skin = new SkinObject(layer1Material, layer2Material); - _this3.skin.visible = false; - _this3.add(_this3.skin); - - _this3.cape = new CapeObject(capeMaterial); - _this3.cape.position.z = -2; - _this3.cape.position.y = -4; - _this3.cape.rotation.x = 25 * Math.PI / 180; - _this3.cape.visible = false; - _this3.add(_this3.cape); - return _this3; - } - - return PlayerObject; -}(Group); - -function invokeAnimation(animation, player, time) { - if (animation instanceof CompositeAnimation) { - animation.play(player, time); - } else if (animation instanceof Function) { - animation(player, time); - } else { - throw "Not an animation: " + animation; - } -} - -var AnimationHandle = function () { - function AnimationHandle(animation) { - classCallCheck(this, AnimationHandle); - - this.animation = animation; - this.paused = this._paused = false; - this.speed = this._speed = 1.0; - this._lastChange = null; - this._lastChangeX = null; - } - - createClass(AnimationHandle, [{ - key: "play", - value: function play(player, time) { - if (this._lastChange === null) { - this._lastChange = time; - this._lastChangeX = 0; - } else if (this.paused !== this._paused || this.speed !== this._speed) { - var dt = time - this._lastChange; - if (this._paused === false) { - this._lastChangeX += dt * this._speed; - } - this._paused = this.paused; - this._speed = this.speed; - this._lastChange = time; - } - if (this.paused === false) { - var _dt = time - this._lastChange; - var x = this._lastChangeX + this.speed * _dt; - invokeAnimation(this.animation, player, x); - } - } - }, { - key: "reset", - value: function reset() { - this._lastChange = null; - } - }]); - return AnimationHandle; -}(); - -var CompositeAnimation = function () { - function CompositeAnimation() { - classCallCheck(this, CompositeAnimation); - - this.handles = new Set(); - } - - createClass(CompositeAnimation, [{ - key: "add", - value: function add(animation) { - var _this = this; - - var handle = new AnimationHandle(animation); - handle.remove = function () { - return _this.handles.delete(handle); - }; - this.handles.add(handle); - return handle; - } - }, { - key: "play", - value: function play(player, time) { - this.handles.forEach(function (handle) { - return handle.play(player, time); - }); - } - }]); - return CompositeAnimation; -}(); - -var WalkingAnimation = function WalkingAnimation(player, time) { - var skin = player.skin; - - // Multiply by animation's natural speed - time *= 8; - - // Leg swing - skin.leftLeg.rotation.x = Math.sin(time) * 0.5; - skin.rightLeg.rotation.x = Math.sin(time + Math.PI) * 0.5; - - // Arm swing - skin.leftArm.rotation.x = Math.sin(time + Math.PI) * 0.5; - skin.rightArm.rotation.x = Math.sin(time) * 0.5; - var basicArmRotationZ = Math.PI * 0.02; - skin.leftArm.rotation.z = Math.cos(time) * 0.03 + basicArmRotationZ; - skin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.03 - basicArmRotationZ; - - // Head shaking with different frequency & amplitude - skin.head.rotation.y = Math.sin(time / 4) * 0.2; - skin.head.rotation.x = Math.sin(time / 5) * 0.1; - - // Always add an angle for cape around the x axis - var basicCapeRotationX = Math.PI * 0.06; - player.cape.rotation.x = Math.sin(time / 1.5) * 0.06 + basicCapeRotationX; -}; - -var RunningAnimation = function RunningAnimation(player, time) { - var skin = player.skin; - - time *= 15; - - // Leg swing with larger amplitude - skin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3; - skin.rightLeg.rotation.x = Math.cos(time) * 1.3; - - // Arm swing - skin.leftArm.rotation.x = Math.cos(time) * 1.5; - skin.rightArm.rotation.x = Math.cos(time + Math.PI) * 1.5; - var basicArmRotationZ = Math.PI * 0.1; - skin.leftArm.rotation.z = Math.cos(time) * 0.1 + basicArmRotationZ; - skin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.1 - basicArmRotationZ; - - // Jumping - player.position.y = Math.cos(time * 2); - // Dodging when running - player.position.x = Math.cos(time) * 0.15; - // Slightly tilting when running - player.rotation.z = Math.cos(time + Math.PI) * 0.01; - - // Apply higher swing frequency, lower amplitude, - // and greater basic rotation around x axis, - // to cape when running. - var basicCapeRotationX = Math.PI * 0.3; - player.cape.rotation.x = Math.sin(time * 2) * 0.1 + basicCapeRotationX; - - // What about head shaking? - // You shouldn't glance right and left when running dude :P -}; - -var RotatingAnimation = function RotatingAnimation(player, time) { - player.rotation.y = time; -}; - -function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) { - var imgData = context.getImageData(sX, sY, w, h); - if (flipHorizontal) { - for (var y = 0; y < h; y++) { - for (var x = 0; x < w / 2; x++) { - var index = (x + y * w) * 4; - var index2 = (w - x - 1 + y * w) * 4; - var pA1 = imgData.data[index]; - var pA2 = imgData.data[index + 1]; - var pA3 = imgData.data[index + 2]; - var pA4 = imgData.data[index + 3]; - - var pB1 = imgData.data[index2]; - var pB2 = imgData.data[index2 + 1]; - var pB3 = imgData.data[index2 + 2]; - var 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; - } - } - } - context.putImageData(imgData, dX, dY); -} - -function hasTransparency(context, x0, y0, w, h) { - var imgData = context.getImageData(x0, y0, w, h); - for (var x = 0; x < w; x++) { - for (var y = 0; y < h; y++) { - var offset = (x + y * w) * 4; - if (imgData.data[offset + 3] !== 0xff) { - return true; - } - } - } - return false; -} - -function computeSkinScale(width) { - return width / 64.0; -} - -function fixOpaqueSkin(context, width) { - // Some ancient skins don't have transparent pixels (nor have helm). - // We have to make the helm area transparent, otherwise it will be rendered as black. - if (!hasTransparency(context, 0, 0, width, width / 2)) { - var scale = computeSkinScale(width); - var clearArea = function clearArea(x, y, w, h) { - return context.clearRect(x * scale, y * scale, w * scale, h * scale); - }; - clearArea(40, 0, 8, 8); // Helm Top - clearArea(48, 0, 8, 8); // Helm Bottom - clearArea(32, 8, 8, 8); // Helm Right - clearArea(40, 8, 8, 8); // Helm Front - clearArea(48, 8, 8, 8); // Helm Left - clearArea(56, 8, 8, 8); // Helm Back - } -} - -function convertSkinTo1_8(context, width) { - var scale = computeSkinScale(width); - var copySkin = function copySkin(sX, sY, w, h, dX, dY, flipHorizontal) { - return copyImage(context, sX * scale, sY * scale, w * scale, h * scale, dX * scale, dY * scale, flipHorizontal); - }; - - fixOpaqueSkin(context, width); - - copySkin(4, 16, 4, 4, 20, 48, true); // Top Leg - copySkin(8, 16, 4, 4, 24, 48, true); // Bottom Leg - copySkin(0, 20, 4, 12, 24, 52, true); // Outer Leg - copySkin(4, 20, 4, 12, 20, 52, true); // Front Leg - copySkin(8, 20, 4, 12, 16, 52, true); // Inner Leg - copySkin(12, 20, 4, 12, 28, 52, true); // Back Leg - copySkin(44, 16, 4, 4, 36, 48, true); // Top Arm - copySkin(48, 16, 4, 4, 40, 48, true); // Bottom Arm - copySkin(40, 20, 4, 12, 40, 52, true); // Outer Arm - copySkin(44, 20, 4, 12, 36, 52, true); // Front Arm - copySkin(48, 20, 4, 12, 32, 52, true); // Inner Arm - copySkin(52, 20, 4, 12, 44, 52, true); // Back Arm -} - -function loadSkinToCanvas(canvas, image) { - var isOldFormat = false; - if (image.width !== image.height) { - if (image.width === 2 * image.height) { - isOldFormat = true; - } else { - throw "Bad skin size: " + image.width + "x" + image.height; - } - } - - var context = canvas.getContext("2d"); - if (isOldFormat) { - var sideLength = image.width; - canvas.width = sideLength; - canvas.height = sideLength; - context.clearRect(0, 0, sideLength, sideLength); - context.drawImage(image, 0, 0, sideLength, sideLength / 2.0); - convertSkinTo1_8(context, sideLength); - } else { - canvas.width = image.width; - canvas.height = image.height; - context.clearRect(0, 0, image.width, image.height); - context.drawImage(image, 0, 0, canvas.width, canvas.height); - } -} - -function loadCapeToCanvas(canvas, image) { - var isOldFormat = false; - if (image.width !== 2 * image.height) { - if (image.width * 17 == image.height * 22) { - // width/height = 22/17 - isOldFormat = true; - } else { - throw "Bad cape size: " + image.width + "x" + image.height; - } - } - - var context = canvas.getContext("2d"); - if (isOldFormat) { - var width = image.width * 64 / 22; - canvas.width = width; - canvas.height = width / 2; - } else { - canvas.width = image.width; - canvas.height = image.height; - } - context.clearRect(0, 0, canvas.width, canvas.height); - context.drawImage(image, 0, 0, image.width, image.height); -} - -function isSlimSkin(canvasOrImage) { - // Detects whether the skin is default or slim. - // - // The right arm area of *default* skins: - // (44,16)->*-------*-------* - // (40,20) |top |bottom | - // \|/ |4x4 |4x4 | - // *-------*-------*-------*-------* - // |right |front |left |back | - // |4x12 |4x12 |4x12 |4x12 | - // *-------*-------*-------*-------* - // The right arm area of *slim* skins: - // (44,16)->*------*------*-* - // (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4] - // \|/ |3x4 |3x4 | | - // *-------*------*------***-----*-* - // |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12] - // |4x12 |3x12 |4x12 |3x12 | | - // *-------*------*-------*------*-* - // Compared with default right arms, slim right arms have 2 unused areas. - // - // The same is true for left arm: - // The left arm area of *default* skins: - // (36,48)->*-------*-------* - // (32,52) |top |bottom | - // \|/ |4x4 |4x4 | - // *-------*-------*-------*-------* - // |right |front |left |back | - // |4x12 |4x12 |4x12 |4x12 | - // *-------*-------*-------*-------* - // The left arm area of *slim* skins: - // (36,48)->*------*------*-* - // (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4] - // \|/ |3x4 |3x4 | | - // *-------*------*------***-----*-* - // |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12] - // |4x12 |3x12 |4x12 |3x12 | | - // *-------*------*-------*------*-* - // - // If there is a transparent pixel in any of the 4 unused areas, the skin must be slim, - // as transparent pixels are not allowed in the first layer. - - if (canvasOrImage instanceof HTMLCanvasElement) { - var canvas = canvasOrImage; - var scale = computeSkinScale(canvas.width); - var context = canvas.getContext("2d"); - var checkArea = function checkArea(x, y, w, h) { - return hasTransparency(context, x * scale, y * scale, w * scale, h * scale); - }; - return checkArea(50, 16, 2, 4) || checkArea(54, 20, 2, 12) || checkArea(42, 48, 2, 4) || checkArea(46, 52, 2, 12); - } else if (canvasOrImage instanceof HTMLImageElement) { - var image = canvasOrImage; - var _canvas = document.createElement("canvas"); - loadSkinToCanvas(_canvas, image); - return isSlimSkin(_canvas); - } else { - throw "Illegal argument: " + canvasOrImage; - } -} - -var SkinViewer = function () { - function SkinViewer(options) { - var _this = this; - - classCallCheck(this, SkinViewer); - - this.domElement = options.domElement; - this.animation = options.animation || null; - this.detectModel = options.detectModel !== false; // true by default - this.animationPaused = false; - this.animationTime = 0; - this.disposed = false; - - // texture - this.skinImg = new Image(); - this.skinCanvas = document.createElement("canvas"); - this.skinTexture = new Texture(this.skinCanvas); - this.skinTexture.magFilter = NearestFilter; - this.skinTexture.minFilter = NearestFilter; - - this.capeImg = new Image(); - this.capeCanvas = document.createElement("canvas"); - this.capeTexture = new Texture(this.capeCanvas); - this.capeTexture.magFilter = NearestFilter; - this.capeTexture.minFilter = NearestFilter; - - this.layer1Material = new MeshBasicMaterial({ map: this.skinTexture, side: FrontSide }); - this.layer2Material = new MeshBasicMaterial({ map: this.skinTexture, transparent: true, opacity: 1, side: DoubleSide, alphaTest: 0.5 }); - this.capeMaterial = new MeshBasicMaterial({ map: this.capeTexture, transparent: true, opacity: 1, side: DoubleSide, alphaTest: 0.5 }); - - // scene - this.scene = new Scene(); - - // Use smaller fov to avoid distortion - this.camera = new PerspectiveCamera(40); - this.camera.position.y = -12; - this.camera.position.z = 60; - - this.renderer = new WebGLRenderer({ angleRot: true, alpha: true, antialias: false }); - this.renderer.setSize(300, 300); // default size - this.renderer.context.getShaderInfoLog = function () { - return ""; - }; // shut firefox up - this.domElement.appendChild(this.renderer.domElement); - - this.playerObject = new PlayerObject(this.layer1Material, this.layer2Material, this.capeMaterial); - this.scene.add(this.playerObject); - - // texture loading - this.skinImg.crossOrigin = "anonymous"; - this.skinImg.onerror = function () { - return console.error("Failed loading " + _this.skinImg.src); - }; - this.skinImg.onload = function () { - loadSkinToCanvas(_this.skinCanvas, _this.skinImg); - - if (_this.detectModel) { - _this.playerObject.skin.slim = isSlimSkin(_this.skinCanvas); - } - - _this.skinTexture.needsUpdate = true; - _this.layer1Material.needsUpdate = true; - _this.layer2Material.needsUpdate = true; - - _this.playerObject.skin.visible = true; - }; - - this.capeImg.crossOrigin = "anonymous"; - this.capeImg.onerror = function () { - return console.error("Failed loading " + _this.capeImg.src); - }; - this.capeImg.onload = function () { - loadCapeToCanvas(_this.capeCanvas, _this.capeImg); - - _this.capeTexture.needsUpdate = true; - _this.capeMaterial.needsUpdate = true; - - _this.playerObject.cape.visible = true; - }; - - if (options.skinUrl) this.skinUrl = options.skinUrl; - if (options.capeUrl) this.capeUrl = options.capeUrl; - if (options.width) this.width = options.width; - if (options.height) this.height = options.height; - - var draw = function draw() { - if (_this.disposed) return; - window.requestAnimationFrame(draw); - if (!_this.animationPaused) { - _this.animationTime++; - if (_this.animation) { - invokeAnimation(_this.animation, _this.playerObject, _this.animationTime / 100.0); - } - } - _this.renderer.render(_this.scene, _this.camera); - }; - draw(); - } - - createClass(SkinViewer, [{ - key: "setSize", - value: function setSize(width, height) { - this.camera.aspect = width / height; - this.camera.updateProjectionMatrix(); - this.renderer.setSize(width, height); - } - }, { - key: "dispose", - value: function dispose() { - this.disposed = true; - this.domElement.removeChild(this.renderer.domElement); - this.renderer.dispose(); - this.skinTexture.dispose(); - this.capeTexture.dispose(); - } - }, { - key: "skinUrl", - get: function get$$1() { - return this.skinImg.src; - }, - set: function set$$1(url) { - this.skinImg.src = url; - } - }, { - key: "capeUrl", - get: function get$$1() { - return this.capeImg.src; - }, - set: function set$$1(url) { - this.capeImg.src = url; - } - }, { - key: "width", - get: function get$$1() { - return this.renderer.getSize().width; - }, - set: function set$$1(newWidth) { - this.setSize(newWidth, this.height); - } - }, { - key: "height", - get: function get$$1() { - return this.renderer.getSize().height; - }, - set: function set$$1(newHeight) { - this.setSize(this.width, newHeight); - } - }]); - return SkinViewer; -}(); - -var OrbitControls = function (_THREE$EventDispatche) { - inherits(OrbitControls, _THREE$EventDispatche); - - /** - * @preserve - * The code was originally from https://github.com/mrdoob/three.js/blob/d45a042cf962e9b1aa9441810ba118647b48aacb/examples/js/controls/OrbitControls.js - */ - /** - * @license - * Copyright (C) 2010-2017 three.js authors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * - * @author qiao / https://github.com/qiao - * @author mrdoob / http://mrdoob.com - * @author alteredq / http://alteredqualia.com/ - * @author WestLangley / http://github.com/WestLangley - * @author erich666 / http://erichaines.com - */ - - // This set of controls performs orbiting, dollying (zooming), and panning. - // Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default). - // - // Orbit - left mouse / touch: one finger move - // Zoom - middle mouse, or mousewheel / touch: two finger spread or squish - // Pan - right mouse, or arrow keys / touch: three finger swipe - - function OrbitControls(object, domElement) { - classCallCheck(this, OrbitControls); - - var _this = possibleConstructorReturn(this, (OrbitControls.__proto__ || Object.getPrototypeOf(OrbitControls)).call(this)); - - _this.object = object; - _this.domElement = domElement !== undefined ? domElement : document; - - // Set to false to disable this control - _this.enabled = true; - - // "target" sets the location of focus, where the object orbits around - _this.target = new Vector3(); - - // How far you can dolly in and out (PerspectiveCamera only) - _this.minDistance = 0; - _this.maxDistance = Infinity; - - // How far you can zoom in and out (OrthographicCamera only) - _this.minZoom = 0; - _this.maxZoom = Infinity; - - // How far you can orbit vertically, upper and lower limits. - // Range is 0 to Math.PI radians. - _this.minPolarAngle = 0; // radians - _this.maxPolarAngle = Math.PI; // radians - - // How far you can orbit horizontally, upper and lower limits. - // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. - _this.minAzimuthAngle = -Infinity; // radians - _this.maxAzimuthAngle = Infinity; // radians - - // Set to true to enable damping (inertia) - // If damping is enabled, you must call controls.update() in your animation loop - _this.enableDamping = false; - _this.dampingFactor = 0.25; - - // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. - // Set to false to disable zooming - _this.enableZoom = true; - _this.zoomSpeed = 1.0; - - // Set to false to disable rotating - _this.enableRotate = true; - _this.rotateSpeed = 1.0; - - // Set to false to disable panning - _this.enablePan = true; - _this.keyPanSpeed = 7.0; // pixels moved per arrow key push - - // Set to true to automatically rotate around the target - // If auto-rotate is enabled, you must call controls.update() in your animation loop - _this.autoRotate = false; - _this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 - - // Set to false to disable use of the keys - _this.enableKeys = true; - - // The four arrow keys - _this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; - - // Mouse buttons - _this.mouseButtons = { ORBIT: MOUSE.LEFT, ZOOM: MOUSE.MIDDLE, PAN: MOUSE.RIGHT }; - - // for reset - _this.target0 = _this.target.clone(); - _this.position0 = _this.object.position.clone(); - _this.zoom0 = _this.object.zoom; - - // - // public methods - // - _this.getPolarAngle = function () { - return spherical.phi; - }; - _this.getAzimuthalAngle = function () { - return spherical.theta; - }; - _this.saveState = function () { - scope.target0.copy(scope.target); - scope.position0.copy(scope.object.position); - scope.zoom0 = scope.object.zoom; - }; - _this.reset = function () { - scope.target.copy(scope.target0); - scope.object.position.copy(scope.position0); - scope.object.zoom = scope.zoom0; - scope.object.updateProjectionMatrix(); - scope.dispatchEvent(changeEvent); - scope.update(); - state = STATE.NONE; - }; - - // this method is exposed, but perhaps it would be better if we can make it private... - _this.update = function () { - var offset = new Vector3(); - // so camera.up is the orbit axis - var quat = new Quaternion().setFromUnitVectors(object.up, new Vector3(0, 1, 0)); - var quatInverse = quat.clone().inverse(); - var lastPosition = new Vector3(); - var lastQuaternion = new Quaternion(); - return function update() { - var position = scope.object.position; - offset.copy(position).sub(scope.target); - // rotate offset to "y-axis-is-up" space - offset.applyQuaternion(quat); - // angle from z-axis around y-axis - spherical.setFromVector3(offset); - if (scope.autoRotate && state === STATE.NONE) { - rotateLeft(getAutoRotationAngle()); - } - spherical.theta += sphericalDelta.theta; - spherical.phi += sphericalDelta.phi; - // restrict theta to be between desired limits - spherical.theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta)); - // restrict phi to be between desired limits - spherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi)); - spherical.makeSafe(); - spherical.radius *= scale; - // restrict radius to be between desired limits - spherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius)); - // move target to panned location - scope.target.add(panOffset); - offset.setFromSpherical(spherical); - // rotate offset back to "camera-up-vector-is-up" space - offset.applyQuaternion(quatInverse); - position.copy(scope.target).add(offset); - scope.object.lookAt(scope.target); - if (scope.enableDamping === true) { - sphericalDelta.theta *= 1 - scope.dampingFactor; - sphericalDelta.phi *= 1 - scope.dampingFactor; - } else { - sphericalDelta.set(0, 0, 0); - } - scale = 1; - panOffset.set(0, 0, 0); - // update condition is: - // min(camera displacement, camera rotation in radians)^2 > EPS - // using small-angle approximation cos(x/2) = 1 - x^2 / 8 - if (zoomChanged || lastPosition.distanceToSquared(scope.object.position) > EPS || 8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) { - scope.dispatchEvent(changeEvent); - lastPosition.copy(scope.object.position); - lastQuaternion.copy(scope.object.quaternion); - zoomChanged = false; - return true; - } - return false; - }; - }(); - _this.dispose = function () { - scope.domElement.removeEventListener("contextmenu", onContextMenu, false); - scope.domElement.removeEventListener("mousedown", onMouseDown, false); - scope.domElement.removeEventListener("wheel", onMouseWheel, false); - scope.domElement.removeEventListener("touchstart", onTouchStart, false); - scope.domElement.removeEventListener("touchend", onTouchEnd, false); - scope.domElement.removeEventListener("touchmove", onTouchMove, false); - document.removeEventListener("mousemove", onMouseMove, false); - document.removeEventListener("mouseup", onMouseUp, false); - window.removeEventListener("keydown", onKeyDown, false); - //scope.dispatchEvent({ type: "dispose" }); // should this be added here? - }; - // - // internals - // - var scope = _this; - var changeEvent = { type: "change" }; - var startEvent = { type: "start" }; - var endEvent = { type: "end" }; - var STATE = { NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 }; - var state = STATE.NONE; - var EPS = 0.000001; - // current position in spherical coordinates - var spherical = new Spherical(); - var sphericalDelta = new Spherical(); - var scale = 1; - var panOffset = new Vector3(); - var zoomChanged = false; - var rotateStart = new Vector2(); - var rotateEnd = new Vector2(); - var rotateDelta = new Vector2(); - var panStart = new Vector2(); - var panEnd = new Vector2(); - var panDelta = new Vector2(); - var dollyStart = new Vector2(); - var dollyEnd = new Vector2(); - var dollyDelta = new Vector2(); - function getAutoRotationAngle() { - return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; - } - function getZoomScale() { - return Math.pow(0.95, scope.zoomSpeed); - } - function rotateLeft(angle) { - sphericalDelta.theta -= angle; - } - function rotateUp(angle) { - sphericalDelta.phi -= angle; - } - var panLeft = function () { - var v = new Vector3(); - return function panLeft(distance, objectMatrix) { - v.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix - v.multiplyScalar(-distance); - panOffset.add(v); - }; - }(); - var panUp = function () { - var v = new Vector3(); - return function panUp(distance, objectMatrix) { - v.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix - v.multiplyScalar(distance); - panOffset.add(v); - }; - }(); - // deltaX and deltaY are in pixels; right and down are positive - var pan = function () { - var offset = new Vector3(); - return function pan(deltaX, deltaY) { - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - if (scope.object instanceof PerspectiveCamera) { - // perspective - var position = scope.object.position; - offset.copy(position).sub(scope.target); - var targetDistance = offset.length(); - // half of the fov is center to top of screen - targetDistance *= Math.tan(scope.object.fov / 2 * Math.PI / 180.0); - // we actually don't use screenWidth, since perspective camera is fixed to screen height - panLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix); - panUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix); - } else if (scope.object instanceof OrthographicCamera) { - // orthographic - panLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix); - panUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix); - } else { - // camera neither orthographic nor perspective - console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."); - scope.enablePan = false; - } - }; - }(); - function dollyIn(dollyScale) { - if (scope.object instanceof PerspectiveCamera) { - scale /= dollyScale; - } else if (scope.object instanceof OrthographicCamera) { - scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale)); - scope.object.updateProjectionMatrix(); - zoomChanged = true; - } else { - console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); - scope.enableZoom = false; - } - } - function dollyOut(dollyScale) { - if (scope.object instanceof PerspectiveCamera) { - scale *= dollyScale; - } else if (scope.object instanceof OrthographicCamera) { - scope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale)); - scope.object.updateProjectionMatrix(); - zoomChanged = true; - } else { - console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); - scope.enableZoom = false; - } - } - // - // event callbacks - update the object state - // - function handleMouseDownRotate(event) { - rotateStart.set(event.clientX, event.clientY); - } - function handleMouseDownDolly(event) { - dollyStart.set(event.clientX, event.clientY); - } - function handleMouseDownPan(event) { - panStart.set(event.clientX, event.clientY); - } - function handleMouseMoveRotate(event) { - rotateEnd.set(event.clientX, event.clientY); - rotateDelta.subVectors(rotateEnd, rotateStart); - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - // rotating across whole screen goes 360 degrees around - rotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed); - // rotating up and down along whole screen attempts to go 360, but limited to 180 - rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed); - rotateStart.copy(rotateEnd); - scope.update(); - } - function handleMouseMoveDolly(event) { - dollyEnd.set(event.clientX, event.clientY); - dollyDelta.subVectors(dollyEnd, dollyStart); - if (dollyDelta.y > 0) { - dollyIn(getZoomScale()); - } else if (dollyDelta.y < 0) { - dollyOut(getZoomScale()); - } - dollyStart.copy(dollyEnd); - scope.update(); - } - function handleMouseMovePan(event) { - panEnd.set(event.clientX, event.clientY); - panDelta.subVectors(panEnd, panStart); - pan(panDelta.x, panDelta.y); - panStart.copy(panEnd); - scope.update(); - } - function handleMouseWheel(event) { - if (event.deltaY < 0) { - dollyOut(getZoomScale()); - } else if (event.deltaY > 0) { - dollyIn(getZoomScale()); - } - scope.update(); - } - function handleKeyDown(event) { - switch (event.keyCode) { - case scope.keys.UP: - pan(0, scope.keyPanSpeed); - scope.update(); - break; - case scope.keys.BOTTOM: - pan(0, -scope.keyPanSpeed); - scope.update(); - break; - case scope.keys.LEFT: - pan(scope.keyPanSpeed, 0); - scope.update(); - break; - case scope.keys.RIGHT: - pan(-scope.keyPanSpeed, 0); - scope.update(); - break; - } - } - function handleTouchStartRotate(event) { - rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); - } - function handleTouchStartDolly(event) { - var dx = event.touches[0].pageX - event.touches[1].pageX; - var dy = event.touches[0].pageY - event.touches[1].pageY; - var distance = Math.sqrt(dx * dx + dy * dy); - dollyStart.set(0, distance); - } - function handleTouchStartPan(event) { - panStart.set(event.touches[0].pageX, event.touches[0].pageY); - } - function handleTouchMoveRotate(event) { - rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); - rotateDelta.subVectors(rotateEnd, rotateStart); - var element = scope.domElement === document ? scope.domElement.body : scope.domElement; - rotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed); - rotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed); - rotateStart.copy(rotateEnd); - scope.update(); - } - function handleTouchMoveDolly(event) { - var dx = event.touches[0].pageX - event.touches[1].pageX; - var dy = event.touches[0].pageY - event.touches[1].pageY; - var distance = Math.sqrt(dx * dx + dy * dy); - dollyEnd.set(0, distance); - dollyDelta.subVectors(dollyEnd, dollyStart); - if (dollyDelta.y > 0) { - dollyOut(getZoomScale()); - } else if (dollyDelta.y < 0) { - dollyIn(getZoomScale()); - } - dollyStart.copy(dollyEnd); - scope.update(); - } - function handleTouchMovePan(event) { - panEnd.set(event.touches[0].pageX, event.touches[0].pageY); - panDelta.subVectors(panEnd, panStart); - pan(panDelta.x, panDelta.y); - panStart.copy(panEnd); - scope.update(); - } - // - // event handlers - FSM: listen for events and reset state - // - function onMouseDown(event) { - if (scope.enabled === false) return; - switch (event.button) { - case scope.mouseButtons.ORBIT: - if (scope.enableRotate === false) return; - handleMouseDownRotate(event); - state = STATE.ROTATE; - break; - case scope.mouseButtons.ZOOM: - if (scope.enableZoom === false) return; - handleMouseDownDolly(event); - state = STATE.DOLLY; - break; - case scope.mouseButtons.PAN: - if (scope.enablePan === false) return; - handleMouseDownPan(event); - state = STATE.PAN; - break; - } - event.preventDefault(); - if (state !== STATE.NONE) { - document.addEventListener("mousemove", onMouseMove, false); - document.addEventListener("mouseup", onMouseUp, false); - scope.dispatchEvent(startEvent); - } - } - function onMouseMove(event) { - if (scope.enabled === false) return; - switch (state) { - case STATE.ROTATE: - if (scope.enableRotate === false) return; - handleMouseMoveRotate(event); - break; - case STATE.DOLLY: - if (scope.enableZoom === false) return; - handleMouseMoveDolly(event); - break; - case STATE.PAN: - if (scope.enablePan === false) return; - handleMouseMovePan(event); - break; - } - event.preventDefault(); - } - function onMouseUp(event) { - if (scope.enabled === false) return; - document.removeEventListener("mousemove", onMouseMove, false); - document.removeEventListener("mouseup", onMouseUp, false); - scope.dispatchEvent(endEvent); - state = STATE.NONE; - } - function onMouseWheel(event) { - if (scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE && state !== STATE.ROTATE) return; - event.preventDefault(); - event.stopPropagation(); - handleMouseWheel(event); - scope.dispatchEvent(startEvent); // not sure why these are here... - scope.dispatchEvent(endEvent); - } - function onKeyDown(event) { - if (scope.enabled === false || scope.enableKeys === false || scope.enablePan === false) return; - handleKeyDown(event); - } - function onTouchStart(event) { - if (scope.enabled === false) return; - switch (event.touches.length) { - case 1: - // one-fingered touch: rotate - if (scope.enableRotate === false) return; - handleTouchStartRotate(event); - state = STATE.TOUCH_ROTATE; - break; - case 2: - // two-fingered touch: dolly - if (scope.enableZoom === false) return; - handleTouchStartDolly(event); - state = STATE.TOUCH_DOLLY; - break; - case 3: - // three-fingered touch: pan - if (scope.enablePan === false) return; - handleTouchStartPan(event); - state = STATE.TOUCH_PAN; - break; - default: - state = STATE.NONE; - } - if (state !== STATE.NONE) { - scope.dispatchEvent(startEvent); - } - } - function onTouchMove(event) { - if (scope.enabled === false) return; - switch (event.touches.length) { - case 1: - // one-fingered touch: rotate - if (scope.enableRotate === false) return; - if (state !== STATE.TOUCH_ROTATE) return; // is this needed?... - handleTouchMoveRotate(event); - break; - case 2: - // two-fingered touch: dolly - if (scope.enableZoom === false) return; - if (state !== STATE.TOUCH_DOLLY) return; // is this needed?... - handleTouchMoveDolly(event); - break; - case 3: - // three-fingered touch: pan - if (scope.enablePan === false) return; - if (state !== STATE.TOUCH_PAN) return; // is this needed?... - handleTouchMovePan(event); - break; - default: - state = STATE.NONE; - } - event.preventDefault(); - event.stopPropagation(); - } - function onTouchEnd(event) { - if (scope.enabled === false) return; - scope.dispatchEvent(endEvent); - state = STATE.NONE; - } - function onContextMenu(event) { - if (scope.enabled === false || scope.enablePan === false) return; - event.preventDefault(); - } - // - scope.domElement.addEventListener("contextmenu", onContextMenu, false); - scope.domElement.addEventListener("mousedown", onMouseDown, false); - scope.domElement.addEventListener("wheel", onMouseWheel, false); - scope.domElement.addEventListener("touchstart", onTouchStart, false); - scope.domElement.addEventListener("touchend", onTouchEnd, false); - scope.domElement.addEventListener("touchmove", onTouchMove, false); - window.addEventListener("keydown", onKeyDown, false); - // force an update at start - _this.update(); - return _this; - } - - return OrbitControls; -}(EventDispatcher); - -function createOrbitControls(skinViewer) { - var control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement); - - // default configuration - control.enablePan = false; - control.target = new Vector3(0, -12, 0); - control.minDistance = 10; - control.maxDistance = 256; - control.update(); - - return control; -} - -export { SkinObject, CapeObject, PlayerObject, SkinViewer, OrbitControls, createOrbitControls, invokeAnimation, CompositeAnimation, WalkingAnimation, RunningAnimation, RotatingAnimation, isSlimSkin }; -//# sourceMappingURL=skinview3d.module.js.map diff --git a/js/build/skinview3d.module.js.map b/js/build/skinview3d.module.js.map deleted file mode 100644 index 109b19b..0000000 --- a/js/build/skinview3d.module.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"file":"skinview3d.module.js","sources":["../src/model.js","../src/animation.js","../src/utils.js","../src/viewer.js","../src/orbit_controls.js"],"sourcesContent":["import * as THREE from \"three\";\n\nfunction toFaceVertices(x1, y1, x2, y2, w, h) {\n\treturn [\n\t\tnew THREE.Vector2(x1 / w, 1.0 - y2 / h),\n\t\tnew THREE.Vector2(x2 / w, 1.0 - y2 / h),\n\t\tnew THREE.Vector2(x2 / w, 1.0 - y1 / h),\n\t\tnew THREE.Vector2(x1 / w, 1.0 - y1 / h)\n\t];\n}\n\nfunction toSkinVertices(x1, y1, x2, y2) {\n\treturn toFaceVertices(x1, y1, x2, y2, 64.0, 64.0);\n}\n\nfunction toCapeVertices(x1, y1, x2, y2) {\n\treturn toFaceVertices(x1, y1, x2, y2, 64.0, 32.0);\n}\n\nfunction setVertices(box, top, bottom, left, front, right, back) {\n\tbox.faceVertexUvs[0] = [];\n\tbox.faceVertexUvs[0][0] = [right[3], right[0], right[2]];\n\tbox.faceVertexUvs[0][1] = [right[0], right[1], right[2]];\n\tbox.faceVertexUvs[0][2] = [left[3], left[0], left[2]];\n\tbox.faceVertexUvs[0][3] = [left[0], left[1], left[2]];\n\tbox.faceVertexUvs[0][4] = [top[3], top[0], top[2]];\n\tbox.faceVertexUvs[0][5] = [top[0], top[1], top[2]];\n\tbox.faceVertexUvs[0][6] = [bottom[0], bottom[3], bottom[1]];\n\tbox.faceVertexUvs[0][7] = [bottom[3], bottom[2], bottom[1]];\n\tbox.faceVertexUvs[0][8] = [front[3], front[0], front[2]];\n\tbox.faceVertexUvs[0][9] = [front[0], front[1], front[2]];\n\tbox.faceVertexUvs[0][10] = [back[3], back[0], back[2]];\n\tbox.faceVertexUvs[0][11] = [back[0], back[1], back[2]];\n}\n\nconst esp = 0.002;\n\nclass SkinObject extends THREE.Group {\n\tconstructor(layer1Material, layer2Material) {\n\t\tsuper();\n\n\t\tthis.modelListeners = []; // called when model(slim property) is changed\n\n\t\t// Head\n\t\tthis.head = new THREE.Group();\n\n\t\tlet headBox = new THREE.BoxGeometry(8, 8, 8, 0, 0, 0);\n\t\tsetVertices(headBox,\n\t\t\ttoSkinVertices(8, 0, 16, 8),\n\t\t\ttoSkinVertices(16, 0, 24, 8),\n\t\t\ttoSkinVertices(0, 8, 8, 16),\n\t\t\ttoSkinVertices(8, 8, 16, 16),\n\t\t\ttoSkinVertices(16, 8, 24, 16),\n\t\t\ttoSkinVertices(24, 8, 32, 16)\n\t\t);\n\t\tlet headMesh = new THREE.Mesh(headBox, layer1Material);\n\t\tthis.head.add(headMesh);\n\n\t\tlet head2Box = new THREE.BoxGeometry(9, 9, 9, 0, 0, 0);\n\t\tsetVertices(head2Box,\n\t\t\ttoSkinVertices(40, 0, 48, 8),\n\t\t\ttoSkinVertices(48, 0, 56, 8),\n\t\t\ttoSkinVertices(32, 8, 40, 16),\n\t\t\ttoSkinVertices(40, 8, 48, 16),\n\t\t\ttoSkinVertices(48, 8, 56, 16),\n\t\t\ttoSkinVertices(56, 8, 64, 16)\n\t\t);\n\t\tlet head2Mesh = new THREE.Mesh(head2Box, layer2Material);\n\t\thead2Mesh.renderOrder = -1;\n\t\tthis.head.add(head2Mesh);\n\n\t\tthis.add(this.head);\n\n\n\t\t// Body\n\t\tthis.body = new THREE.Group();\n\n\t\tlet bodyBox = new THREE.BoxGeometry(8, 12, 4, 0, 0, 0);\n\t\tsetVertices(bodyBox,\n\t\t\ttoSkinVertices(20, 16, 28, 20),\n\t\t\ttoSkinVertices(28, 16, 36, 20),\n\t\t\ttoSkinVertices(16, 20, 20, 32),\n\t\t\ttoSkinVertices(20, 20, 28, 32),\n\t\t\ttoSkinVertices(28, 20, 32, 32),\n\t\t\ttoSkinVertices(32, 20, 40, 32)\n\t\t);\n\t\tlet bodyMesh = new THREE.Mesh(bodyBox, layer1Material);\n\t\tthis.body.add(bodyMesh);\n\n\t\tlet body2Box = new THREE.BoxGeometry(9, 13.5, 4.5, 0, 0, 0);\n\t\tsetVertices(body2Box,\n\t\t\ttoSkinVertices(20, 32, 28, 36),\n\t\t\ttoSkinVertices(28, 32, 36, 36),\n\t\t\ttoSkinVertices(16, 36, 20, 48),\n\t\t\ttoSkinVertices(20, 36, 28, 48),\n\t\t\ttoSkinVertices(28, 36, 32, 48),\n\t\t\ttoSkinVertices(32, 36, 40, 48)\n\t\t);\n\t\tlet body2Mesh = new THREE.Mesh(body2Box, layer2Material);\n\t\tthis.body.add(body2Mesh);\n\n\t\tthis.body.position.y = -10;\n\t\tthis.add(this.body);\n\n\n\t\t// Right Arm\n\t\tthis.rightArm = new THREE.Group();\n\t\tlet rightArmPivot = new THREE.Group();\n\n\t\tlet rightArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet rightArmMesh = new THREE.Mesh(rightArmBox, layer1Material);\n\t\trightArmPivot.add(rightArmMesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\trightArmMesh.scale.x = (this.slim ? 3 : 4) - esp;\n\t\t\trightArmMesh.scale.y = 12 - esp;\n\t\t\trightArmMesh.scale.z = 4 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(rightArmBox,\n\t\t\t\t\ttoSkinVertices(44, 16, 47, 20),\n\t\t\t\t\ttoSkinVertices(47, 16, 50, 20),\n\t\t\t\t\ttoSkinVertices(40, 20, 44, 32),\n\t\t\t\t\ttoSkinVertices(44, 20, 47, 32),\n\t\t\t\t\ttoSkinVertices(47, 20, 51, 32),\n\t\t\t\t\ttoSkinVertices(51, 20, 54, 32)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(rightArmBox,\n\t\t\t\t\ttoSkinVertices(44, 16, 48, 20),\n\t\t\t\t\ttoSkinVertices(48, 16, 52, 20),\n\t\t\t\t\ttoSkinVertices(40, 20, 44, 32),\n\t\t\t\t\ttoSkinVertices(44, 20, 48, 32),\n\t\t\t\t\ttoSkinVertices(48, 20, 52, 32),\n\t\t\t\t\ttoSkinVertices(52, 20, 56, 32)\n\t\t\t\t);\n\t\t\t}\n\t\t\trightArmBox.uvsNeedUpdate = true;\n\t\t\trightArmBox.elementsNeedUpdate = true;\n\t\t});\n\n\t\tlet rightArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet rightArm2Mesh = new THREE.Mesh(rightArm2Box, layer2Material);\n\t\trightArm2Mesh.renderOrder = 1;\n\t\trightArmPivot.add(rightArm2Mesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\trightArm2Mesh.scale.x = (this.slim ? 3.375 : 4.5) - esp;\n\t\t\trightArm2Mesh.scale.y = 13.5 - esp;\n\t\t\trightArm2Mesh.scale.z = 4.5 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(rightArm2Box,\n\t\t\t\t\ttoSkinVertices(44, 32, 47, 36),\n\t\t\t\t\ttoSkinVertices(47, 32, 50, 36),\n\t\t\t\t\ttoSkinVertices(40, 36, 44, 48),\n\t\t\t\t\ttoSkinVertices(44, 36, 47, 48),\n\t\t\t\t\ttoSkinVertices(47, 36, 51, 48),\n\t\t\t\t\ttoSkinVertices(51, 36, 54, 48)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(rightArm2Box,\n\t\t\t\t\ttoSkinVertices(44, 32, 48, 36),\n\t\t\t\t\ttoSkinVertices(48, 32, 52, 36),\n\t\t\t\t\ttoSkinVertices(40, 36, 44, 48),\n\t\t\t\t\ttoSkinVertices(44, 36, 48, 48),\n\t\t\t\t\ttoSkinVertices(48, 36, 52, 48),\n\t\t\t\t\ttoSkinVertices(52, 36, 56, 48)\n\t\t\t\t);\n\t\t\t}\n\t\t\trightArm2Box.uvsNeedUpdate = true;\n\t\t\trightArm2Box.elementsNeedUpdate = true;\n\t\t});\n\n\t\trightArmPivot.position.y = -6;\n\t\tthis.rightArm.add(rightArmPivot);\n\t\tthis.rightArm.position.y = -4;\n\t\tthis.modelListeners.push(() => {\n\t\t\tthis.rightArm.position.x = this.slim ? -5.5 : -6;\n\t\t});\n\t\tthis.add(this.rightArm);\n\n\n\t\t// Left Arm\n\t\tthis.leftArm = new THREE.Group();\n\t\tlet leftArmPivot = new THREE.Group();\n\n\t\tlet leftArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet leftArmMesh = new THREE.Mesh(leftArmBox, layer1Material);\n\t\tleftArmPivot.add(leftArmMesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\tleftArmMesh.scale.x = (this.slim ? 3 : 4) - esp;\n\t\t\tleftArmMesh.scale.y = 12 - esp;\n\t\t\tleftArmMesh.scale.z = 4 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(leftArmBox,\n\t\t\t\t\ttoSkinVertices(36, 48, 39, 52),\n\t\t\t\t\ttoSkinVertices(39, 48, 42, 52),\n\t\t\t\t\ttoSkinVertices(32, 52, 36, 64),\n\t\t\t\t\ttoSkinVertices(36, 52, 39, 64),\n\t\t\t\t\ttoSkinVertices(39, 52, 43, 64),\n\t\t\t\t\ttoSkinVertices(43, 52, 46, 64)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(leftArmBox,\n\t\t\t\t\ttoSkinVertices(36, 48, 40, 52),\n\t\t\t\t\ttoSkinVertices(40, 48, 44, 52),\n\t\t\t\t\ttoSkinVertices(32, 52, 36, 64),\n\t\t\t\t\ttoSkinVertices(36, 52, 40, 64),\n\t\t\t\t\ttoSkinVertices(40, 52, 44, 64),\n\t\t\t\t\ttoSkinVertices(44, 52, 48, 64)\n\t\t\t\t);\n\t\t\t}\n\t\t\tleftArmBox.uvsNeedUpdate = true;\n\t\t\tleftArmBox.elementsNeedUpdate=true;\n\t\t});\n\n\t\tlet leftArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related\n\t\tlet leftArm2Mesh = new THREE.Mesh(leftArm2Box, layer2Material);\n\t\tleftArm2Mesh.renderOrder = 1;\n\t\tleftArmPivot.add(leftArm2Mesh);\n\t\tthis.modelListeners.push(() => {\n\t\t\tleftArm2Mesh.scale.x = (this.slim ? 3.375 : 4.5) - esp;\n\t\t\tleftArm2Mesh.scale.y = 13.5 - esp;\n\t\t\tleftArm2Mesh.scale.z = 4.5 - esp;\n\t\t\tif (this.slim) {\n\t\t\t\tsetVertices(leftArm2Box,\n\t\t\t\t\ttoSkinVertices(52, 48, 55, 52),\n\t\t\t\t\ttoSkinVertices(55, 48, 58, 52),\n\t\t\t\t\ttoSkinVertices(48, 52, 52, 64),\n\t\t\t\t\ttoSkinVertices(52, 52, 55, 64),\n\t\t\t\t\ttoSkinVertices(55, 52, 59, 64),\n\t\t\t\t\ttoSkinVertices(59, 52, 62, 64)\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tsetVertices(leftArm2Box,\n\t\t\t\t\ttoSkinVertices(52, 48, 56, 52),\n\t\t\t\t\ttoSkinVertices(56, 48, 60, 52),\n\t\t\t\t\ttoSkinVertices(48, 52, 52, 64),\n\t\t\t\t\ttoSkinVertices(52, 52, 56, 64),\n\t\t\t\t\ttoSkinVertices(56, 52, 60, 64),\n\t\t\t\t\ttoSkinVertices(60, 52, 64, 64)\n\t\t\t\t);\n\t\t\t}\n\t\t\tleftArm2Box.uvsNeedUpdate = true;\n\t\t\tleftArm2Box.elementsNeedUpdate = true;\n\t\t});\n\n\t\tleftArmPivot.position.y = -6;\n\t\tthis.leftArm.add(leftArmPivot);\n\t\tthis.leftArm.position.y = -4;\n\t\tthis.modelListeners.push(() => {\n\t\t\tthis.leftArm.position.x = this.slim ? 5.5 : 6;\n\t\t});\n\t\tthis.add(this.leftArm);\n\n\n\t\t// Right Leg\n\t\tthis.rightLeg = new THREE.Group();\n\t\tlet rightLegPivot = new THREE.Group();\n\n\t\tlet rightLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0);\n\t\tsetVertices(rightLegBox,\n\t\t\ttoSkinVertices(4, 16, 8, 20),\n\t\t\ttoSkinVertices(8, 16, 12, 20),\n\t\t\ttoSkinVertices(0, 20, 4, 32),\n\t\t\ttoSkinVertices(4, 20, 8, 32),\n\t\t\ttoSkinVertices(8, 20, 12, 32),\n\t\t\ttoSkinVertices(12, 20, 16, 32)\n\t\t);\n\t\tlet rightLegMesh = new THREE.Mesh(rightLegBox, layer1Material);\n\t\trightLegPivot.add(rightLegMesh);\n\n\t\tlet rightLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0);\n\t\tsetVertices(rightLeg2Box,\n\t\t\ttoSkinVertices(4, 32, 8, 36),\n\t\t\ttoSkinVertices(8, 32, 12, 36),\n\t\t\ttoSkinVertices(0, 36, 4, 48),\n\t\t\ttoSkinVertices(4, 36, 8, 48),\n\t\t\ttoSkinVertices(8, 36, 12, 48),\n\t\t\ttoSkinVertices(12, 36, 16, 48)\n\t\t);\n\t\tlet rightLeg2Mesh = new THREE.Mesh(rightLeg2Box, layer2Material);\n\t\trightLeg2Mesh.renderOrder = 1;\n\t\trightLegPivot.add(rightLeg2Mesh);\n\n\t\trightLegPivot.position.y = -6;\n\t\tthis.rightLeg.add(rightLegPivot);\n\t\tthis.rightLeg.position.y = -16;\n\t\tthis.rightLeg.position.x = -2;\n\t\tthis.add(this.rightLeg);\n\n\t\t// Left Leg\n\t\tthis.leftLeg = new THREE.Group();\n\t\tlet leftLegPivot = new THREE.Group();\n\n\t\tlet leftLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0);\n\t\tsetVertices(leftLegBox,\n\t\t\ttoSkinVertices(20, 48, 24, 52),\n\t\t\ttoSkinVertices(24, 48, 28, 52),\n\t\t\ttoSkinVertices(16, 52, 20, 64),\n\t\t\ttoSkinVertices(20, 52, 24, 64),\n\t\t\ttoSkinVertices(24, 52, 28, 64),\n\t\t\ttoSkinVertices(28, 52, 32, 64)\n\t\t);\n\t\tlet leftLegMesh = new THREE.Mesh(leftLegBox, layer1Material);\n\t\tleftLegPivot.add(leftLegMesh);\n\n\t\tlet leftLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0);\n\t\tsetVertices(leftLeg2Box,\n\t\t\ttoSkinVertices(4, 48, 8, 52),\n\t\t\ttoSkinVertices(8, 48, 12, 52),\n\t\t\ttoSkinVertices(0, 52, 4, 64),\n\t\t\ttoSkinVertices(4, 52, 8, 64),\n\t\t\ttoSkinVertices(8, 52, 12, 64),\n\t\t\ttoSkinVertices(12, 52, 16, 64)\n\t\t);\n\t\tlet leftLeg2Mesh = new THREE.Mesh(leftLeg2Box, layer2Material);\n\t\tleftLeg2Mesh.renderOrder = 1;\n\t\tleftLegPivot.add(leftLeg2Mesh);\n\n\t\tleftLegPivot.position.y = -6;\n\t\tthis.leftLeg.add(leftLegPivot);\n\t\tthis.leftLeg.position.y = -16;\n\t\tthis.leftLeg.position.x = 2;\n\t\tthis.add(this.leftLeg);\n\n\t\tthis.slim = false;\n\t}\n\n\tget slim() {\n\t\treturn this._slim;\n\t}\n\n\tset slim(value) {\n\t\tif (this._slim !== value) {\n\t\t\tthis._slim = value;\n\t\t\tthis.modelListeners.forEach(listener => listener());\n\t\t}\n\t}\n}\n\nclass CapeObject extends THREE.Group {\n\tconstructor(capeMaterial) {\n\t\tsuper();\n\n\t\t// back = outside\n\t\t// front = inside\n\t\tlet capeBox = new THREE.BoxGeometry(10, 16, 1, 0, 0, 0);\n\t\tsetVertices(capeBox,\n\t\t\ttoCapeVertices(1, 0, 11, 1),\n\t\t\ttoCapeVertices(11, 0, 21, 1),\n\t\t\ttoCapeVertices(11, 1, 12, 17),\n\t\t\ttoCapeVertices(12, 1, 22, 17),\n\t\t\ttoCapeVertices(0, 1, 1, 17),\n\t\t\ttoCapeVertices(1, 1, 11, 17)\n\t\t);\n\t\tthis.cape = new THREE.Mesh(capeBox, capeMaterial);\n\t\tthis.cape.position.y = -8;\n\t\tthis.cape.position.z = -0.5;\n\t\tthis.add(this.cape);\n\t}\n}\n\nclass PlayerObject extends THREE.Group {\n\tconstructor(layer1Material, layer2Material, capeMaterial) {\n\t\tsuper();\n\n\t\tthis.skin = new SkinObject(layer1Material, layer2Material);\n\t\tthis.skin.visible = false;\n\t\tthis.add(this.skin);\n\n\t\tthis.cape = new CapeObject(capeMaterial);\n\t\tthis.cape.position.z = -2;\n\t\tthis.cape.position.y = -4;\n\t\tthis.cape.rotation.x = 25 * Math.PI / 180;\n\t\tthis.cape.visible = false;\n\t\tthis.add(this.cape);\n\t}\n}\n\nexport { SkinObject, CapeObject, PlayerObject };\n","function invokeAnimation(animation, player, time) {\n\tif (animation instanceof CompositeAnimation) {\n\t\tanimation.play(player, time);\n\t} else if (animation instanceof Function) {\n\t\tanimation(player, time);\n\t} else {\n\t\tthrow `Not an animation: ${animation}`;\n\t}\n}\n\nclass AnimationHandle {\n\tconstructor(animation) {\n\t\tthis.animation = animation;\n\t\tthis.paused = this._paused = false;\n\t\tthis.speed = this._speed = 1.0;\n\t\tthis._lastChange = null;\n\t\tthis._lastChangeX = null;\n\t}\n\tplay(player, time) {\n\t\tif (this._lastChange === null) {\n\t\t\tthis._lastChange = time;\n\t\t\tthis._lastChangeX = 0;\n\t\t} else if (this.paused !== this._paused || this.speed !== this._speed) {\n\t\t\tlet dt = time - this._lastChange;\n\t\t\tif (this._paused === false) {\n\t\t\t\tthis._lastChangeX += dt * this._speed;\n\t\t\t}\n\t\t\tthis._paused = this.paused;\n\t\t\tthis._speed = this.speed;\n\t\t\tthis._lastChange = time;\n\t\t}\n\t\tif (this.paused === false) {\n\t\t\tlet dt = time - this._lastChange;\n\t\t\tlet x = this._lastChangeX + this.speed * dt;\n\t\t\tinvokeAnimation(this.animation, player, x);\n\t\t}\n\t}\n\treset(){\n\t\tthis._lastChange = null;\n\t}\n}\n\nclass CompositeAnimation {\n\tconstructor() {\n\t\tthis.handles = new Set();\n\t}\n\tadd(animation) {\n\t\tlet handle = new AnimationHandle(animation);\n\t\thandle.remove = () => this.handles.delete(handle);\n\t\tthis.handles.add(handle);\n\t\treturn handle;\n\t}\n\tplay(player, time) {\n\t\tthis.handles.forEach(handle => handle.play(player, time));\n\t}\n}\n\nlet WalkingAnimation = (player, time) => {\n\tlet skin = player.skin;\n\n\t// Multiply by animation's natural speed\n\ttime *= 8;\n\n\t// Leg swing\n\tskin.leftLeg.rotation.x = Math.sin(time) * 0.5;\n\tskin.rightLeg.rotation.x = Math.sin(time + Math.PI) * 0.5;\n\n\t// Arm swing\n\tskin.leftArm.rotation.x = Math.sin(time + Math.PI) * 0.5;\n\tskin.rightArm.rotation.x = Math.sin(time) * 0.5;\n\tlet basicArmRotationZ = Math.PI * 0.02;\n\tskin.leftArm.rotation.z = Math.cos(time) * 0.03 + basicArmRotationZ;\n\tskin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.03 - basicArmRotationZ;\n\n\t// Head shaking with different frequency & amplitude\n\tskin.head.rotation.y = Math.sin(time / 4) * 0.2;\n\tskin.head.rotation.x = Math.sin(time / 5) * 0.1;\n\n\t// Always add an angle for cape around the x axis\n\tlet basicCapeRotationX = Math.PI * 0.06;\n\tplayer.cape.rotation.x = Math.sin(time / 1.5) * 0.06 + basicCapeRotationX;\n};\n\nlet RunningAnimation = (player, time) => {\n\tlet skin = player.skin;\n\n\ttime *= 15;\n\n\t// Leg swing with larger amplitude\n\tskin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3;\n\tskin.rightLeg.rotation.x = Math.cos(time) * 1.3;\n\n\t// Arm swing\n\tskin.leftArm.rotation.x = Math.cos(time) * 1.5;\n\tskin.rightArm.rotation.x = Math.cos(time + Math.PI) * 1.5;\n\tlet basicArmRotationZ = Math.PI * 0.1;\n\tskin.leftArm.rotation.z = Math.cos(time) * 0.1 + basicArmRotationZ;\n\tskin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.1 - basicArmRotationZ;\n\n\t// Jumping\n\tplayer.position.y = Math.cos(time * 2);\n\t// Dodging when running\n\tplayer.position.x = Math.cos(time) * 0.15;\n\t// Slightly tilting when running\n\tplayer.rotation.z = Math.cos(time + Math.PI) * 0.01;\n\n\t// Apply higher swing frequency, lower amplitude,\n\t// and greater basic rotation around x axis,\n\t// to cape when running.\n\tlet basicCapeRotationX = Math.PI * 0.3;\n\tplayer.cape.rotation.x = Math.sin(time * 2) * 0.1 + basicCapeRotationX;\n\n\t// What about head shaking?\n\t// You shouldn't glance right and left when running dude :P\n};\n\nlet RotatingAnimation = (player, time) => {\n\tplayer.rotation.y = time;\n};\n\nexport {\n\tCompositeAnimation,\n\tinvokeAnimation,\n\tWalkingAnimation,\n\tRunningAnimation,\n\tRotatingAnimation\n};\n","function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) {\n\tlet imgData = context.getImageData(sX, sY, w, h);\n\tif (flipHorizontal) {\n\t\tfor (let y = 0; y < h; y++) {\n\t\t\tfor (let x = 0; x < (w / 2); x++) {\n\t\t\t\tlet index = (x + y * w) * 4;\n\t\t\t\tlet index2 = ((w - x - 1) + y * w) * 4;\n\t\t\t\tlet pA1 = imgData.data[index];\n\t\t\t\tlet pA2 = imgData.data[index + 1];\n\t\t\t\tlet pA3 = imgData.data[index + 2];\n\t\t\t\tlet pA4 = imgData.data[index + 3];\n\n\t\t\t\tlet pB1 = imgData.data[index2];\n\t\t\t\tlet pB2 = imgData.data[index2 + 1];\n\t\t\t\tlet pB3 = imgData.data[index2 + 2];\n\t\t\t\tlet pB4 = imgData.data[index2 + 3];\n\n\t\t\t\timgData.data[index] = pB1;\n\t\t\t\timgData.data[index + 1] = pB2;\n\t\t\t\timgData.data[index + 2] = pB3;\n\t\t\t\timgData.data[index + 3] = pB4;\n\n\t\t\t\timgData.data[index2] = pA1;\n\t\t\t\timgData.data[index2 + 1] = pA2;\n\t\t\t\timgData.data[index2 + 2] = pA3;\n\t\t\t\timgData.data[index2 + 3] = pA4;\n\t\t\t}\n\t\t}\n\t}\n\tcontext.putImageData(imgData, dX, dY);\n}\n\nfunction hasTransparency(context, x0, y0, w, h) {\n\tlet imgData = context.getImageData(x0, y0, w, h);\n\tfor (let x = 0; x < w; x++) {\n\t\tfor (let y = 0; y < h; y++) {\n\t\t\tlet offset = (x + y * w) * 4;\n\t\t\tif (imgData.data[offset + 3] !== 0xff) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction computeSkinScale(width) {\n\treturn width / 64.0;\n}\n\nfunction fixOpaqueSkin(context, width) {\n\t// Some ancient skins don't have transparent pixels (nor have helm).\n\t// We have to make the helm area transparent, otherwise it will be rendered as black.\n\tif (!hasTransparency(context, 0, 0, width, width / 2)) {\n\t\tlet scale = computeSkinScale(width);\n\t\tlet clearArea = (x, y, w, h) => context.clearRect(x * scale, y * scale, w * scale, h * scale);\n\t\tclearArea(40, 0, 8, 8); // Helm Top\n\t\tclearArea(48, 0, 8, 8); // Helm Bottom\n\t\tclearArea(32, 8, 8, 8); // Helm Right\n\t\tclearArea(40, 8, 8, 8); // Helm Front\n\t\tclearArea(48, 8, 8, 8); // Helm Left\n\t\tclearArea(56, 8, 8, 8); // Helm Back\n\t}\n}\n\nfunction convertSkinTo1_8(context, width) {\n\tlet scale = computeSkinScale(width);\n\tlet copySkin = (sX, sY, w, h, dX, dY, flipHorizontal) => copyImage(context, sX * scale, sY * scale, w * scale, h * scale, dX * scale, dY * scale, flipHorizontal);\n\n\tfixOpaqueSkin(context, width);\n\n\tcopySkin(4, 16, 4, 4, 20, 48, true); // Top Leg\n\tcopySkin(8, 16, 4, 4, 24, 48, true); // Bottom Leg\n\tcopySkin(0, 20, 4, 12, 24, 52, true); // Outer Leg\n\tcopySkin(4, 20, 4, 12, 20, 52, true); // Front Leg\n\tcopySkin(8, 20, 4, 12, 16, 52, true); // Inner Leg\n\tcopySkin(12, 20, 4, 12, 28, 52, true); // Back Leg\n\tcopySkin(44, 16, 4, 4, 36, 48, true); // Top Arm\n\tcopySkin(48, 16, 4, 4, 40, 48, true); // Bottom Arm\n\tcopySkin(40, 20, 4, 12, 40, 52, true); // Outer Arm\n\tcopySkin(44, 20, 4, 12, 36, 52, true); // Front Arm\n\tcopySkin(48, 20, 4, 12, 32, 52, true); // Inner Arm\n\tcopySkin(52, 20, 4, 12, 44, 52, true); // Back Arm\n}\n\nfunction loadSkinToCanvas(canvas, image) {\n\tlet isOldFormat = false;\n\tif (image.width !== image.height) {\n\t\tif (image.width === 2 * image.height) {\n\t\t\tisOldFormat = true;\n\t\t} else {\n\t\t\tthrow `Bad skin size: ${image.width}x${image.height}`;\n\t\t}\n\t}\n\n\tlet context = canvas.getContext(\"2d\");\n\tif (isOldFormat) {\n\t\tlet sideLength = image.width;\n\t\tcanvas.width = sideLength;\n\t\tcanvas.height = sideLength;\n\t\tcontext.clearRect(0, 0, sideLength, sideLength);\n\t\tcontext.drawImage(image, 0, 0, sideLength, sideLength / 2.0);\n\t\tconvertSkinTo1_8(context, sideLength);\n\t} else {\n\t\tcanvas.width = image.width;\n\t\tcanvas.height = image.height;\n\t\tcontext.clearRect(0, 0, image.width, image.height);\n\t\tcontext.drawImage(image, 0, 0, canvas.width, canvas.height);\n\t}\n}\n\nfunction loadCapeToCanvas(canvas, image) {\n\tlet isOldFormat = false;\n\tif (image.width !== 2 * image.height) {\n\t\tif (image.width * 17 == image.height * 22) {\n\t\t\t// width/height = 22/17\n\t\t\tisOldFormat = true;\n\t\t} else {\n\t\t\tthrow `Bad cape size: ${image.width}x${image.height}`;\n\t\t}\n\t}\n\n\tlet context = canvas.getContext(\"2d\");\n\tif (isOldFormat) {\n\t\tlet width = image.width * 64 / 22;\n\t\tcanvas.width = width;\n\t\tcanvas.height = width / 2;\n\t} else {\n\t\tcanvas.width = image.width;\n\t\tcanvas.height = image.height;\n\t}\n\tcontext.clearRect(0, 0, canvas.width, canvas.height);\n\tcontext.drawImage(image, 0, 0, image.width, image.height);\n}\n\nfunction isSlimSkin(canvasOrImage) {\n\t// Detects whether the skin is default or slim.\n\t//\n\t// The right arm area of *default* skins:\n\t// (44,16)->*-------*-------*\n\t// (40,20) |top |bottom |\n\t// \\|/ |4x4 |4x4 |\n\t// *-------*-------*-------*-------*\n\t// |right |front |left |back |\n\t// |4x12 |4x12 |4x12 |4x12 |\n\t// *-------*-------*-------*-------*\n\t// The right arm area of *slim* skins:\n\t// (44,16)->*------*------*-*\n\t// (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4]\n\t// \\|/ |3x4 |3x4 | |\n\t// *-------*------*------***-----*-*\n\t// |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12]\n\t// |4x12 |3x12 |4x12 |3x12 | |\n\t// *-------*------*-------*------*-*\n\t// Compared with default right arms, slim right arms have 2 unused areas.\n\t//\n\t// The same is true for left arm:\n\t// The left arm area of *default* skins:\n\t// (36,48)->*-------*-------*\n\t// (32,52) |top |bottom |\n\t// \\|/ |4x4 |4x4 |\n\t// *-------*-------*-------*-------*\n\t// |right |front |left |back |\n\t// |4x12 |4x12 |4x12 |4x12 |\n\t// *-------*-------*-------*-------*\n\t// The left arm area of *slim* skins:\n\t// (36,48)->*------*------*-*\n\t// (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4]\n\t// \\|/ |3x4 |3x4 | |\n\t// *-------*------*------***-----*-*\n\t// |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12]\n\t// |4x12 |3x12 |4x12 |3x12 | |\n\t// *-------*------*-------*------*-*\n\t//\n\t// If there is a transparent pixel in any of the 4 unused areas, the skin must be slim,\n\t// as transparent pixels are not allowed in the first layer.\n\n\tif (canvasOrImage instanceof HTMLCanvasElement) {\n\t\tlet canvas = canvasOrImage;\n\t\tlet scale = computeSkinScale(canvas.width);\n\t\tlet context = canvas.getContext(\"2d\");\n\t\tlet checkArea = (x, y, w, h) => hasTransparency(context, x * scale, y * scale, w * scale, h * scale);\n\t\treturn checkArea(50, 16, 2, 4) ||\n\t\t\tcheckArea(54, 20, 2, 12) ||\n\t\t\tcheckArea(42, 48, 2, 4) ||\n\t\t\tcheckArea(46, 52, 2, 12);\n\t} else if (canvasOrImage instanceof HTMLImageElement) {\n\t\tlet image = canvasOrImage;\n\t\tlet canvas = document.createElement(\"canvas\");\n\t\tloadSkinToCanvas(canvas, image);\n\t\treturn isSlimSkin(canvas);\n\t} else {\n\t\tthrow `Illegal argument: ${canvasOrImage}`;\n\t}\n}\n\nexport { isSlimSkin, loadSkinToCanvas, loadCapeToCanvas };\n","import * as THREE from \"three\";\nimport { PlayerObject } from \"./model\";\nimport { invokeAnimation } from \"./animation\";\nimport { loadSkinToCanvas,loadCapeToCanvas, isSlimSkin } from \"./utils\";\n\nclass SkinViewer {\n\tconstructor(options) {\n\t\tthis.domElement = options.domElement;\n\t\tthis.animation = options.animation || null;\n\t\tthis.detectModel = options.detectModel !== false; // true by default\n\t\tthis.animationPaused = false;\n\t\tthis.animationTime = 0;\n\t\tthis.disposed = false;\n\n\t\t// texture\n\t\tthis.skinImg = new Image();\n\t\tthis.skinCanvas = document.createElement(\"canvas\");\n\t\tthis.skinTexture = new THREE.Texture(this.skinCanvas);\n\t\tthis.skinTexture.magFilter = THREE.NearestFilter;\n\t\tthis.skinTexture.minFilter = THREE.NearestFilter;\n\n\t\tthis.capeImg = new Image();\n\t\tthis.capeCanvas = document.createElement(\"canvas\");\n\t\tthis.capeTexture = new THREE.Texture(this.capeCanvas);\n\t\tthis.capeTexture.magFilter = THREE.NearestFilter;\n\t\tthis.capeTexture.minFilter = THREE.NearestFilter;\n\n\t\tthis.layer1Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, side: THREE.FrontSide });\n\t\tthis.layer2Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 });\n\t\tthis.capeMaterial = new THREE.MeshBasicMaterial({ map: this.capeTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 });\n\n\t\t// scene\n\t\tthis.scene = new THREE.Scene();\n\n\t\t// Use smaller fov to avoid distortion\n\t\tthis.camera = new THREE.PerspectiveCamera(40);\n\t\tthis.camera.position.y = -12;\n\t\tthis.camera.position.z = 60;\n\n\t\tthis.renderer = new THREE.WebGLRenderer({ angleRot: true, alpha: true, antialias: false });\n\t\tthis.renderer.setSize(300, 300); // default size\n\t\tthis.renderer.context.getShaderInfoLog = () => \"\"; // shut firefox up\n\t\tthis.domElement.appendChild(this.renderer.domElement);\n\n\t\tthis.playerObject = new PlayerObject(this.layer1Material, this.layer2Material, this.capeMaterial);\n\t\tthis.scene.add(this.playerObject);\n\n\t\t// texture loading\n\t\tthis.skinImg.crossOrigin = \"anonymous\";\n\t\tthis.skinImg.onerror = () => console.error(\"Failed loading \" + this.skinImg.src);\n\t\tthis.skinImg.onload = () => {\n\t\t\tloadSkinToCanvas(this.skinCanvas, this.skinImg);\n\n\t\t\tif (this.detectModel) {\n\t\t\t\tthis.playerObject.skin.slim = isSlimSkin(this.skinCanvas);\n\t\t\t}\n\n\t\t\tthis.skinTexture.needsUpdate = true;\n\t\t\tthis.layer1Material.needsUpdate = true;\n\t\t\tthis.layer2Material.needsUpdate = true;\n\n\t\t\tthis.playerObject.skin.visible = true;\n\t\t};\n\n\t\tthis.capeImg.crossOrigin = \"anonymous\";\n\t\tthis.capeImg.onerror = () => console.error(\"Failed loading \" + this.capeImg.src);\n\t\tthis.capeImg.onload = () => {\n\t\t\tloadCapeToCanvas(this.capeCanvas, this.capeImg);\n\n\t\t\tthis.capeTexture.needsUpdate = true;\n\t\t\tthis.capeMaterial.needsUpdate = true;\n\n\t\t\tthis.playerObject.cape.visible = true;\n\t\t};\n\n\t\tif (options.skinUrl) this.skinUrl = options.skinUrl;\n\t\tif (options.capeUrl) this.capeUrl = options.capeUrl;\n\t\tif (options.width) this.width = options.width;\n\t\tif (options.height) this.height = options.height;\n\n\t\tlet draw = () => {\n\t\t\tif (this.disposed) return;\n\t\t\twindow.requestAnimationFrame(draw);\n\t\t\tif (!this.animationPaused) {\n\t\t\t\tthis.animationTime++;\n\t\t\t\tif (this.animation) {\n\t\t\t\t\tinvokeAnimation(this.animation, this.playerObject, this.animationTime / 100.0);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.renderer.render(this.scene, this.camera);\n\t\t};\n\t\tdraw();\n\t}\n\n\tsetSize(width, height) {\n\t\tthis.camera.aspect = width / height;\n\t\tthis.camera.updateProjectionMatrix();\n\t\tthis.renderer.setSize(width, height);\n\t}\n\n\tdispose() {\n\t\tthis.disposed = true;\n\t\tthis.domElement.removeChild(this.renderer.domElement);\n\t\tthis.renderer.dispose();\n\t\tthis.skinTexture.dispose();\n\t\tthis.capeTexture.dispose();\n\t}\n\n\tget skinUrl() {\n\t\treturn this.skinImg.src;\n\t}\n\n\tset skinUrl(url) {\n\t\tthis.skinImg.src = url;\n\t}\n\n\tget capeUrl() {\n\t\treturn this.capeImg.src;\n\t}\n\n\tset capeUrl(url) {\n\t\tthis.capeImg.src = url;\n\t}\n\n\tget width() {\n\t\treturn this.renderer.getSize().width;\n\t}\n\n\tset width(newWidth) {\n\t\tthis.setSize(newWidth, this.height);\n\t}\n\n\tget height() {\n\t\treturn this.renderer.getSize().height;\n\t}\n\n\tset height(newHeight) {\n\t\tthis.setSize(this.width, newHeight);\n\t}\n}\n\nexport { SkinViewer };\n","import * as THREE from \"three\";\n\nclass OrbitControls extends THREE.EventDispatcher {\n\t/**\n\t * @preserve\n\t * The code was originally from https://github.com/mrdoob/three.js/blob/d45a042cf962e9b1aa9441810ba118647b48aacb/examples/js/controls/OrbitControls.js\n\t */\n\t/**\n\t * @license\n\t * Copyright (C) 2010-2017 three.js authors\n\t *\n\t * Permission is hereby granted, free of charge, to any person obtaining a copy\n\t * of this software and associated documentation files (the \"Software\"), to deal\n\t * in the Software without restriction, including without limitation the rights\n\t * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n\t * copies of the Software, and to permit persons to whom the Software is\n\t * furnished to do so, subject to the following conditions:\n\t *\n\t * The above copyright notice and this permission notice shall be included in\n\t * all copies or substantial portions of the Software.\n\t *\n\t * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\t * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\t * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\t * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\t * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\t * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n\t * THE SOFTWARE.\n\t *\n\t *\n\t * @author qiao / https://github.com/qiao\n\t * @author mrdoob / http://mrdoob.com\n\t * @author alteredq / http://alteredqualia.com/\n\t * @author WestLangley / http://github.com/WestLangley\n\t * @author erich666 / http://erichaines.com\n\t */\n\n\t// This set of controls performs orbiting, dollying (zooming), and panning.\n\t// Unlike TrackballControls, it maintains the \"up\" direction object.up (+Y by default).\n\t//\n\t// Orbit - left mouse / touch: one finger move\n\t// Zoom - middle mouse, or mousewheel / touch: two finger spread or squish\n\t// Pan - right mouse, or arrow keys / touch: three finger swipe\n\n\tconstructor(object, domElement) {\n\t\tsuper();\n\t\tthis.object = object;\n\t\tthis.domElement = (domElement !== undefined) ? domElement : document;\n\n\t\t// Set to false to disable this control\n\t\tthis.enabled = true;\n\n\t\t// \"target\" sets the location of focus, where the object orbits around\n\t\tthis.target = new THREE.Vector3();\n\n\t\t// How far you can dolly in and out (PerspectiveCamera only)\n\t\tthis.minDistance = 0;\n\t\tthis.maxDistance = Infinity;\n\n\t\t// How far you can zoom in and out (OrthographicCamera only)\n\t\tthis.minZoom = 0;\n\t\tthis.maxZoom = Infinity;\n\n\t\t// How far you can orbit vertically, upper and lower limits.\n\t\t// Range is 0 to Math.PI radians.\n\t\tthis.minPolarAngle = 0; // radians\n\t\tthis.maxPolarAngle = Math.PI; // radians\n\n\t\t// How far you can orbit horizontally, upper and lower limits.\n\t\t// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].\n\t\tthis.minAzimuthAngle = -Infinity; // radians\n\t\tthis.maxAzimuthAngle = Infinity; // radians\n\n\t\t// Set to true to enable damping (inertia)\n\t\t// If damping is enabled, you must call controls.update() in your animation loop\n\t\tthis.enableDamping = false;\n\t\tthis.dampingFactor = 0.25;\n\n\t\t// This option actually enables dollying in and out; left as \"zoom\" for backwards compatibility.\n\t\t// Set to false to disable zooming\n\t\tthis.enableZoom = true;\n\t\tthis.zoomSpeed = 1.0;\n\n\t\t// Set to false to disable rotating\n\t\tthis.enableRotate = true;\n\t\tthis.rotateSpeed = 1.0;\n\n\t\t// Set to false to disable panning\n\t\tthis.enablePan = true;\n\t\tthis.keyPanSpeed = 7.0; // pixels moved per arrow key push\n\n\t\t// Set to true to automatically rotate around the target\n\t\t// If auto-rotate is enabled, you must call controls.update() in your animation loop\n\t\tthis.autoRotate = false;\n\t\tthis.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60\n\n\t\t// Set to false to disable use of the keys\n\t\tthis.enableKeys = true;\n\n\t\t// The four arrow keys\n\t\tthis.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };\n\n\t\t// Mouse buttons\n\t\tthis.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };\n\n\t\t// for reset\n\t\tthis.target0 = this.target.clone();\n\t\tthis.position0 = this.object.position.clone();\n\t\tthis.zoom0 = this.object.zoom;\n\n\t\t//\n\t\t// public methods\n\t\t//\n\t\tthis.getPolarAngle = function () {\n\t\t\treturn spherical.phi;\n\t\t};\n\t\tthis.getAzimuthalAngle = function () {\n\t\t\treturn spherical.theta;\n\t\t};\n\t\tthis.saveState = function () {\n\t\t\tscope.target0.copy(scope.target);\n\t\t\tscope.position0.copy(scope.object.position);\n\t\t\tscope.zoom0 = scope.object.zoom;\n\t\t};\n\t\tthis.reset = function () {\n\t\t\tscope.target.copy(scope.target0);\n\t\t\tscope.object.position.copy(scope.position0);\n\t\t\tscope.object.zoom = scope.zoom0;\n\t\t\tscope.object.updateProjectionMatrix();\n\t\t\tscope.dispatchEvent(changeEvent);\n\t\t\tscope.update();\n\t\t\tstate = STATE.NONE;\n\t\t};\n\n\t\t// this method is exposed, but perhaps it would be better if we can make it private...\n\t\tthis.update = function () {\n\t\t\tlet offset = new THREE.Vector3();\n\t\t\t// so camera.up is the orbit axis\n\t\t\tlet quat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0));\n\t\t\tlet quatInverse = quat.clone().inverse();\n\t\t\tlet lastPosition = new THREE.Vector3();\n\t\t\tlet lastQuaternion = new THREE.Quaternion();\n\t\t\treturn function update() {\n\t\t\t\tlet position = scope.object.position;\n\t\t\t\toffset.copy(position).sub(scope.target);\n\t\t\t\t// rotate offset to \"y-axis-is-up\" space\n\t\t\t\toffset.applyQuaternion(quat);\n\t\t\t\t// angle from z-axis around y-axis\n\t\t\t\tspherical.setFromVector3(offset);\n\t\t\t\tif (scope.autoRotate && state === STATE.NONE) {\n\t\t\t\t\trotateLeft(getAutoRotationAngle());\n\t\t\t\t}\n\t\t\t\tspherical.theta += sphericalDelta.theta;\n\t\t\t\tspherical.phi += sphericalDelta.phi;\n\t\t\t\t// restrict theta to be between desired limits\n\t\t\t\tspherical.theta = Math.max(scope.minAzimuthAngle, Math.min(scope.maxAzimuthAngle, spherical.theta));\n\t\t\t\t// restrict phi to be between desired limits\n\t\t\t\tspherical.phi = Math.max(scope.minPolarAngle, Math.min(scope.maxPolarAngle, spherical.phi));\n\t\t\t\tspherical.makeSafe();\n\t\t\t\tspherical.radius *= scale;\n\t\t\t\t// restrict radius to be between desired limits\n\t\t\t\tspherical.radius = Math.max(scope.minDistance, Math.min(scope.maxDistance, spherical.radius));\n\t\t\t\t// move target to panned location\n\t\t\t\tscope.target.add(panOffset);\n\t\t\t\toffset.setFromSpherical(spherical);\n\t\t\t\t// rotate offset back to \"camera-up-vector-is-up\" space\n\t\t\t\toffset.applyQuaternion(quatInverse);\n\t\t\t\tposition.copy(scope.target).add(offset);\n\t\t\t\tscope.object.lookAt(scope.target);\n\t\t\t\tif (scope.enableDamping === true) {\n\t\t\t\t\tsphericalDelta.theta *= (1 - scope.dampingFactor);\n\t\t\t\t\tsphericalDelta.phi *= (1 - scope.dampingFactor);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\tsphericalDelta.set(0, 0, 0);\n\t\t\t\t}\n\t\t\t\tscale = 1;\n\t\t\t\tpanOffset.set(0, 0, 0);\n\t\t\t\t// update condition is:\n\t\t\t\t// min(camera displacement, camera rotation in radians)^2 > EPS\n\t\t\t\t// using small-angle approximation cos(x/2) = 1 - x^2 / 8\n\t\t\t\tif (zoomChanged ||\n\t\t\t\t\tlastPosition.distanceToSquared(scope.object.position) > EPS ||\n\t\t\t\t\t8 * (1 - lastQuaternion.dot(scope.object.quaternion)) > EPS) {\n\t\t\t\t\tscope.dispatchEvent(changeEvent);\n\t\t\t\t\tlastPosition.copy(scope.object.position);\n\t\t\t\t\tlastQuaternion.copy(scope.object.quaternion);\n\t\t\t\t\tzoomChanged = false;\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}();\n\t\tthis.dispose = function () {\n\t\t\tscope.domElement.removeEventListener(\"contextmenu\", onContextMenu, false);\n\t\t\tscope.domElement.removeEventListener(\"mousedown\", onMouseDown, false);\n\t\t\tscope.domElement.removeEventListener(\"wheel\", onMouseWheel, false);\n\t\t\tscope.domElement.removeEventListener(\"touchstart\", onTouchStart, false);\n\t\t\tscope.domElement.removeEventListener(\"touchend\", onTouchEnd, false);\n\t\t\tscope.domElement.removeEventListener(\"touchmove\", onTouchMove, false);\n\t\t\tdocument.removeEventListener(\"mousemove\", onMouseMove, false);\n\t\t\tdocument.removeEventListener(\"mouseup\", onMouseUp, false);\n\t\t\twindow.removeEventListener(\"keydown\", onKeyDown, false);\n\t\t\t//scope.dispatchEvent({ type: \"dispose\" }); // should this be added here?\n\t\t};\n\t\t//\n\t\t// internals\n\t\t//\n\t\tlet scope = this;\n\t\tlet changeEvent = { type: \"change\" };\n\t\tlet startEvent = { type: \"start\" };\n\t\tlet endEvent = { type: \"end\" };\n\t\tlet STATE = { NONE: -1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY: 4, TOUCH_PAN: 5 };\n\t\tlet state = STATE.NONE;\n\t\tlet EPS = 0.000001;\n\t\t// current position in spherical coordinates\n\t\tlet spherical = new THREE.Spherical();\n\t\tlet sphericalDelta = new THREE.Spherical();\n\t\tlet scale = 1;\n\t\tlet panOffset = new THREE.Vector3();\n\t\tlet zoomChanged = false;\n\t\tlet rotateStart = new THREE.Vector2();\n\t\tlet rotateEnd = new THREE.Vector2();\n\t\tlet rotateDelta = new THREE.Vector2();\n\t\tlet panStart = new THREE.Vector2();\n\t\tlet panEnd = new THREE.Vector2();\n\t\tlet panDelta = new THREE.Vector2();\n\t\tlet dollyStart = new THREE.Vector2();\n\t\tlet dollyEnd = new THREE.Vector2();\n\t\tlet dollyDelta = new THREE.Vector2();\n\t\tfunction getAutoRotationAngle() {\n\t\t\treturn 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;\n\t\t}\n\t\tfunction getZoomScale() {\n\t\t\treturn Math.pow(0.95, scope.zoomSpeed);\n\t\t}\n\t\tfunction rotateLeft(angle) {\n\t\t\tsphericalDelta.theta -= angle;\n\t\t}\n\t\tfunction rotateUp(angle) {\n\t\t\tsphericalDelta.phi -= angle;\n\t\t}\n\t\tlet panLeft = function () {\n\t\t\tlet v = new THREE.Vector3();\n\t\t\treturn function panLeft(distance, objectMatrix) {\n\t\t\t\tv.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix\n\t\t\t\tv.multiplyScalar(-distance);\n\t\t\t\tpanOffset.add(v);\n\t\t\t};\n\t\t}();\n\t\tlet panUp = function () {\n\t\t\tlet v = new THREE.Vector3();\n\t\t\treturn function panUp(distance, objectMatrix) {\n\t\t\t\tv.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix\n\t\t\t\tv.multiplyScalar(distance);\n\t\t\t\tpanOffset.add(v);\n\t\t\t};\n\t\t}();\n\t\t// deltaX and deltaY are in pixels; right and down are positive\n\t\tlet pan = function () {\n\t\t\tlet offset = new THREE.Vector3();\n\t\t\treturn function pan(deltaX, deltaY) {\n\t\t\t\tlet element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\t\t\t\t// perspective\n\t\t\t\t\tlet position = scope.object.position;\n\t\t\t\t\toffset.copy(position).sub(scope.target);\n\t\t\t\t\tlet targetDistance = offset.length();\n\t\t\t\t\t// half of the fov is center to top of screen\n\t\t\t\t\ttargetDistance *= Math.tan((scope.object.fov / 2) * Math.PI / 180.0);\n\t\t\t\t\t// we actually don't use screenWidth, since perspective camera is fixed to screen height\n\t\t\t\t\tpanLeft(2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix);\n\t\t\t\t\tpanUp(2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix);\n\t\t\t\t}\n\t\t\t\telse if (scope.object instanceof THREE.OrthographicCamera) {\n\t\t\t\t\t// orthographic\n\t\t\t\t\tpanLeft(deltaX * (scope.object.right - scope.object.left) / scope.object.zoom / element.clientWidth, scope.object.matrix);\n\t\t\t\t\tpanUp(deltaY * (scope.object.top - scope.object.bottom) / scope.object.zoom / element.clientHeight, scope.object.matrix);\n\t\t\t\t}\n\t\t\t\telse {\n\t\t\t\t\t// camera neither orthographic nor perspective\n\t\t\t\t\tconsole.warn(\"WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.\");\n\t\t\t\t\tscope.enablePan = false;\n\t\t\t\t}\n\t\t\t};\n\t\t}();\n\t\tfunction dollyIn(dollyScale) {\n\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\t\t\tscale /= dollyScale;\n\t\t\t}\n\t\t\telse if (scope.object instanceof THREE.OrthographicCamera) {\n\t\t\t\tscope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom * dollyScale));\n\t\t\t\tscope.object.updateProjectionMatrix();\n\t\t\t\tzoomChanged = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconsole.warn(\"WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.\");\n\t\t\t\tscope.enableZoom = false;\n\t\t\t}\n\t\t}\n\t\tfunction dollyOut(dollyScale) {\n\t\t\tif (scope.object instanceof THREE.PerspectiveCamera) {\n\t\t\t\tscale *= dollyScale;\n\t\t\t}\n\t\t\telse if (scope.object instanceof THREE.OrthographicCamera) {\n\t\t\t\tscope.object.zoom = Math.max(scope.minZoom, Math.min(scope.maxZoom, scope.object.zoom / dollyScale));\n\t\t\t\tscope.object.updateProjectionMatrix();\n\t\t\t\tzoomChanged = true;\n\t\t\t}\n\t\t\telse {\n\t\t\t\tconsole.warn(\"WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.\");\n\t\t\t\tscope.enableZoom = false;\n\t\t\t}\n\t\t}\n\t\t//\n\t\t// event callbacks - update the object state\n\t\t//\n\t\tfunction handleMouseDownRotate(event) {\n\t\t\trotateStart.set(event.clientX, event.clientY);\n\t\t}\n\t\tfunction handleMouseDownDolly(event) {\n\t\t\tdollyStart.set(event.clientX, event.clientY);\n\t\t}\n\t\tfunction handleMouseDownPan(event) {\n\t\t\tpanStart.set(event.clientX, event.clientY);\n\t\t}\n\t\tfunction handleMouseMoveRotate(event) {\n\t\t\trotateEnd.set(event.clientX, event.clientY);\n\t\t\trotateDelta.subVectors(rotateEnd, rotateStart);\n\t\t\tlet element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\t\t// rotating across whole screen goes 360 degrees around\n\t\t\trotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);\n\t\t\t// rotating up and down along whole screen attempts to go 360, but limited to 180\n\t\t\trotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);\n\t\t\trotateStart.copy(rotateEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleMouseMoveDolly(event) {\n\t\t\tdollyEnd.set(event.clientX, event.clientY);\n\t\t\tdollyDelta.subVectors(dollyEnd, dollyStart);\n\t\t\tif (dollyDelta.y > 0) {\n\t\t\t\tdollyIn(getZoomScale());\n\t\t\t}\n\t\t\telse if (dollyDelta.y < 0) {\n\t\t\t\tdollyOut(getZoomScale());\n\t\t\t}\n\t\t\tdollyStart.copy(dollyEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleMouseMovePan(event) {\n\t\t\tpanEnd.set(event.clientX, event.clientY);\n\t\t\tpanDelta.subVectors(panEnd, panStart);\n\t\t\tpan(panDelta.x, panDelta.y);\n\t\t\tpanStart.copy(panEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleMouseUp(event) {\n\t\t}\n\t\tfunction handleMouseWheel(event) {\n\t\t\tif (event.deltaY < 0) {\n\t\t\t\tdollyOut(getZoomScale());\n\t\t\t}\n\t\t\telse if (event.deltaY > 0) {\n\t\t\t\tdollyIn(getZoomScale());\n\t\t\t}\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleKeyDown(event) {\n\t\t\tswitch (event.keyCode) {\n\t\t\t\tcase scope.keys.UP:\n\t\t\t\t\tpan(0, scope.keyPanSpeed);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.keys.BOTTOM:\n\t\t\t\t\tpan(0, -scope.keyPanSpeed);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.keys.LEFT:\n\t\t\t\t\tpan(scope.keyPanSpeed, 0);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.keys.RIGHT:\n\t\t\t\t\tpan(-scope.keyPanSpeed, 0);\n\t\t\t\t\tscope.update();\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tfunction handleTouchStartRotate(event) {\n\t\t\trotateStart.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t}\n\t\tfunction handleTouchStartDolly(event) {\n\t\t\tlet dx = event.touches[0].pageX - event.touches[1].pageX;\n\t\t\tlet dy = event.touches[0].pageY - event.touches[1].pageY;\n\t\t\tlet distance = Math.sqrt(dx * dx + dy * dy);\n\t\t\tdollyStart.set(0, distance);\n\t\t}\n\t\tfunction handleTouchStartPan(event) {\n\t\t\tpanStart.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t}\n\t\tfunction handleTouchMoveRotate(event) {\n\t\t\trotateEnd.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t\trotateDelta.subVectors(rotateEnd, rotateStart);\n\t\t\tlet element = scope.domElement === document ? scope.domElement.body : scope.domElement;\n\t\t\trotateLeft(2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed);\n\t\t\trotateUp(2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed);\n\t\t\trotateStart.copy(rotateEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleTouchMoveDolly(event) {\n\t\t\tlet dx = event.touches[0].pageX - event.touches[1].pageX;\n\t\t\tlet dy = event.touches[0].pageY - event.touches[1].pageY;\n\t\t\tlet distance = Math.sqrt(dx * dx + dy * dy);\n\t\t\tdollyEnd.set(0, distance);\n\t\t\tdollyDelta.subVectors(dollyEnd, dollyStart);\n\t\t\tif (dollyDelta.y > 0) {\n\t\t\t\tdollyOut(getZoomScale());\n\t\t\t}\n\t\t\telse if (dollyDelta.y < 0) {\n\t\t\t\tdollyIn(getZoomScale());\n\t\t\t}\n\t\t\tdollyStart.copy(dollyEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleTouchMovePan(event) {\n\t\t\tpanEnd.set(event.touches[0].pageX, event.touches[0].pageY);\n\t\t\tpanDelta.subVectors(panEnd, panStart);\n\t\t\tpan(panDelta.x, panDelta.y);\n\t\t\tpanStart.copy(panEnd);\n\t\t\tscope.update();\n\t\t}\n\t\tfunction handleTouchEnd(event) {\n\t\t}\n\t\t//\n\t\t// event handlers - FSM: listen for events and reset state\n\t\t//\n\t\tfunction onMouseDown(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (event.button) {\n\t\t\t\tcase scope.mouseButtons.ORBIT:\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseDownRotate(event);\n\t\t\t\t\tstate = STATE.ROTATE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.mouseButtons.ZOOM:\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseDownDolly(event);\n\t\t\t\t\tstate = STATE.DOLLY;\n\t\t\t\t\tbreak;\n\t\t\t\tcase scope.mouseButtons.PAN:\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseDownPan(event);\n\t\t\t\t\tstate = STATE.PAN;\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t\tif (state !== STATE.NONE) {\n\t\t\t\tdocument.addEventListener(\"mousemove\", onMouseMove, false);\n\t\t\t\tdocument.addEventListener(\"mouseup\", onMouseUp, false);\n\t\t\t\tscope.dispatchEvent(startEvent);\n\t\t\t}\n\t\t}\n\t\tfunction onMouseMove(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (state) {\n\t\t\t\tcase STATE.ROTATE:\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseMoveRotate(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase STATE.DOLLY:\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseMoveDolly(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase STATE.PAN:\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleMouseMovePan(event);\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t}\n\t\tfunction onMouseUp(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\thandleMouseUp(event);\n\t\t\tdocument.removeEventListener(\"mousemove\", onMouseMove, false);\n\t\t\tdocument.removeEventListener(\"mouseup\", onMouseUp, false);\n\t\t\tscope.dispatchEvent(endEvent);\n\t\t\tstate = STATE.NONE;\n\t\t}\n\t\tfunction onMouseWheel(event) {\n\t\t\tif (scope.enabled === false || scope.enableZoom === false || (state !== STATE.NONE && state !== STATE.ROTATE))\n\t\t\t\treturn;\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t\thandleMouseWheel(event);\n\t\t\tscope.dispatchEvent(startEvent); // not sure why these are here...\n\t\t\tscope.dispatchEvent(endEvent);\n\t\t}\n\t\tfunction onKeyDown(event) {\n\t\t\tif (scope.enabled === false || scope.enableKeys === false || scope.enablePan === false)\n\t\t\t\treturn;\n\t\t\thandleKeyDown(event);\n\t\t}\n\t\tfunction onTouchStart(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (event.touches.length) {\n\t\t\t\tcase 1:// one-fingered touch: rotate\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleTouchStartRotate(event);\n\t\t\t\t\tstate = STATE.TOUCH_ROTATE;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:// two-fingered touch: dolly\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleTouchStartDolly(event);\n\t\t\t\t\tstate = STATE.TOUCH_DOLLY;\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:// three-fingered touch: pan\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\thandleTouchStartPan(event);\n\t\t\t\t\tstate = STATE.TOUCH_PAN;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tstate = STATE.NONE;\n\t\t\t}\n\t\t\tif (state !== STATE.NONE) {\n\t\t\t\tscope.dispatchEvent(startEvent);\n\t\t\t}\n\t\t}\n\t\tfunction onTouchMove(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\tswitch (event.touches.length) {\n\t\t\t\tcase 1:// one-fingered touch: rotate\n\t\t\t\t\tif (scope.enableRotate === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (state !== STATE.TOUCH_ROTATE)\n\t\t\t\t\t\treturn; // is this needed?...\n\t\t\t\t\thandleTouchMoveRotate(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 2:// two-fingered touch: dolly\n\t\t\t\t\tif (scope.enableZoom === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (state !== STATE.TOUCH_DOLLY)\n\t\t\t\t\t\treturn; // is this needed?...\n\t\t\t\t\thandleTouchMoveDolly(event);\n\t\t\t\t\tbreak;\n\t\t\t\tcase 3:// three-fingered touch: pan\n\t\t\t\t\tif (scope.enablePan === false)\n\t\t\t\t\t\treturn;\n\t\t\t\t\tif (state !== STATE.TOUCH_PAN)\n\t\t\t\t\t\treturn; // is this needed?...\n\t\t\t\t\thandleTouchMovePan(event);\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tstate = STATE.NONE;\n\t\t\t}\n\t\t\tevent.preventDefault();\n\t\t\tevent.stopPropagation();\n\t\t}\n\t\tfunction onTouchEnd(event) {\n\t\t\tif (scope.enabled === false)\n\t\t\t\treturn;\n\t\t\thandleTouchEnd(event);\n\t\t\tscope.dispatchEvent(endEvent);\n\t\t\tstate = STATE.NONE;\n\t\t}\n\t\tfunction onContextMenu(event) {\n\t\t\tif (scope.enabled === false || scope.enablePan === false)\n\t\t\t\treturn;\n\t\t\tevent.preventDefault();\n\t\t}\n\t\t//\n\t\tscope.domElement.addEventListener(\"contextmenu\", onContextMenu, false);\n\t\tscope.domElement.addEventListener(\"mousedown\", onMouseDown, false);\n\t\tscope.domElement.addEventListener(\"wheel\", onMouseWheel, false);\n\t\tscope.domElement.addEventListener(\"touchstart\", onTouchStart, false);\n\t\tscope.domElement.addEventListener(\"touchend\", onTouchEnd, false);\n\t\tscope.domElement.addEventListener(\"touchmove\", onTouchMove, false);\n\t\twindow.addEventListener(\"keydown\", onKeyDown, false);\n\t\t// force an update at start\n\t\tthis.update();\n\t}\n}\n\nfunction createOrbitControls(skinViewer) {\n\tlet control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement);\n\n\t// default configuration\n\tcontrol.enablePan = false;\n\tcontrol.target = new THREE.Vector3(0, -12, 0);\n\tcontrol.minDistance = 10;\n\tcontrol.maxDistance = 256;\n\tcontrol.update();\n\n\treturn control;\n}\n\nexport { OrbitControls, createOrbitControls };\n"],"names":["toFaceVertices","x1","y1","x2","y2","w","h","THREE","toSkinVertices","toCapeVertices","setVertices","box","top","bottom","left","front","right","back","faceVertexUvs","esp","SkinObject","layer1Material","layer2Material","modelListeners","head","headBox","headMesh","add","head2Box","head2Mesh","renderOrder","body","bodyBox","bodyMesh","body2Box","body2Mesh","position","y","rightArm","rightArmPivot","rightArmBox","rightArmMesh","push","scale","x","slim","z","uvsNeedUpdate","elementsNeedUpdate","rightArm2Box","rightArm2Mesh","leftArm","leftArmPivot","leftArmBox","leftArmMesh","leftArm2Box","leftArm2Mesh","rightLeg","rightLegPivot","rightLegBox","rightLegMesh","rightLeg2Box","rightLeg2Mesh","leftLeg","leftLegPivot","leftLegBox","leftLegMesh","leftLeg2Box","leftLeg2Mesh","_slim","value","forEach","listener","CapeObject","capeMaterial","capeBox","cape","PlayerObject","skin","visible","rotation","Math","PI","invokeAnimation","animation","player","time","CompositeAnimation","play","Function","AnimationHandle","paused","_paused","speed","_speed","_lastChange","_lastChangeX","dt","handles","Set","handle","remove","delete","WalkingAnimation","sin","basicArmRotationZ","cos","basicCapeRotationX","RunningAnimation","RotatingAnimation","copyImage","context","sX","sY","dX","dY","flipHorizontal","imgData","getImageData","index","index2","pA1","data","pA2","pA3","pA4","pB1","pB2","pB3","pB4","putImageData","hasTransparency","x0","y0","offset","computeSkinScale","width","fixOpaqueSkin","clearArea","clearRect","convertSkinTo1_8","copySkin","loadSkinToCanvas","canvas","image","isOldFormat","height","getContext","sideLength","drawImage","loadCapeToCanvas","isSlimSkin","canvasOrImage","HTMLCanvasElement","checkArea","HTMLImageElement","document","createElement","SkinViewer","options","domElement","detectModel","animationPaused","animationTime","disposed","skinImg","Image","skinCanvas","skinTexture","magFilter","minFilter","capeImg","capeCanvas","capeTexture","map","side","transparent","opacity","alphaTest","scene","camera","renderer","angleRot","alpha","antialias","setSize","getShaderInfoLog","appendChild","playerObject","crossOrigin","onerror","console","error","src","onload","needsUpdate","skinUrl","capeUrl","draw","requestAnimationFrame","render","aspect","updateProjectionMatrix","removeChild","dispose","url","getSize","newWidth","newHeight","OrbitControls","object","undefined","enabled","target","minDistance","maxDistance","Infinity","minZoom","maxZoom","minPolarAngle","maxPolarAngle","minAzimuthAngle","maxAzimuthAngle","enableDamping","dampingFactor","enableZoom","zoomSpeed","enableRotate","rotateSpeed","enablePan","keyPanSpeed","autoRotate","autoRotateSpeed","enableKeys","keys","LEFT","UP","RIGHT","BOTTOM","mouseButtons","ORBIT","ZOOM","MIDDLE","PAN","target0","clone","position0","zoom0","zoom","getPolarAngle","spherical","phi","getAzimuthalAngle","theta","saveState","copy","scope","reset","dispatchEvent","changeEvent","update","STATE","NONE","quat","setFromUnitVectors","up","quatInverse","inverse","lastPosition","lastQuaternion","sub","applyQuaternion","setFromVector3","state","getAutoRotationAngle","sphericalDelta","max","min","makeSafe","radius","panOffset","setFromSpherical","lookAt","set","zoomChanged","distanceToSquared","EPS","dot","quaternion","removeEventListener","onContextMenu","onMouseDown","onMouseWheel","onTouchStart","onTouchEnd","onTouchMove","onMouseMove","onMouseUp","onKeyDown","type","startEvent","endEvent","ROTATE","DOLLY","TOUCH_ROTATE","TOUCH_DOLLY","TOUCH_PAN","rotateStart","rotateEnd","rotateDelta","panStart","panEnd","panDelta","dollyStart","dollyEnd","dollyDelta","getZoomScale","pow","rotateLeft","angle","rotateUp","panLeft","v","distance","objectMatrix","setFromMatrixColumn","multiplyScalar","panUp","pan","deltaX","deltaY","element","targetDistance","length","tan","fov","clientHeight","matrix","clientWidth","warn","dollyIn","dollyScale","dollyOut","handleMouseDownRotate","event","clientX","clientY","handleMouseDownDolly","handleMouseDownPan","handleMouseMoveRotate","subVectors","handleMouseMoveDolly","handleMouseMovePan","handleMouseWheel","handleKeyDown","keyCode","handleTouchStartRotate","touches","pageX","pageY","handleTouchStartDolly","dx","dy","sqrt","handleTouchStartPan","handleTouchMoveRotate","handleTouchMoveDolly","handleTouchMovePan","button","preventDefault","addEventListener","handleMouseUp","stopPropagation","createOrbitControls","skinViewer","control"],"mappings":"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"} \ No newline at end of file diff --git a/js/dist/animation.d.ts b/js/dist/animation.d.ts new file mode 100644 index 0000000..f4cf943 --- /dev/null +++ b/js/dist/animation.d.ts @@ -0,0 +1,22 @@ +import { PlayerObject } from "./model"; +export interface IAnimation { + play(player: PlayerObject, time: number): void; +} +export declare type AnimationFn = (player: PlayerObject, time: number) => void; +export declare type Animation = AnimationFn | IAnimation; +export declare function invokeAnimation(animation: Animation, player: PlayerObject, time: number): void; +export interface AnimationHandle { + paused: boolean; + speed: number; + readonly animation: Animation; + reset(): void; + remove(): void; +} +export declare class CompositeAnimation implements IAnimation { + readonly handles: Set; + add(animation: Animation): AnimationHandle; + play(player: PlayerObject, time: number): void; +} +export declare const WalkingAnimation: Animation; +export declare const RunningAnimation: Animation; +export declare const RotatingAnimation: Animation; diff --git a/js/dist/model.d.ts b/js/dist/model.d.ts new file mode 100644 index 0000000..33d22c0 --- /dev/null +++ b/js/dist/model.d.ts @@ -0,0 +1,33 @@ +import * as THREE from "three"; +/** + * Notice that innerLayer and outerLayer may NOT be the direct children of the Group. + */ +export declare class BodyPart extends THREE.Group { + readonly innerLayer: THREE.Object3D; + readonly outerLayer: THREE.Object3D; + constructor(innerLayer: THREE.Object3D, outerLayer: THREE.Object3D); +} +export declare class SkinObject extends THREE.Group { + readonly head: BodyPart; + readonly body: BodyPart; + readonly rightArm: BodyPart; + readonly leftArm: BodyPart; + readonly rightLeg: BodyPart; + readonly leftLeg: BodyPart; + private modelListeners; + private _slim; + constructor(layer1Material: THREE.MeshBasicMaterial, layer2Material: THREE.MeshBasicMaterial); + slim: boolean; + private getBodyParts; + setInnerLayerVisible(value: boolean): void; + setOuterLayerVisible(value: boolean): void; +} +export declare class CapeObject extends THREE.Group { + readonly cape: THREE.Mesh; + constructor(capeMaterial: THREE.MeshBasicMaterial); +} +export declare class PlayerObject extends THREE.Group { + readonly skin: SkinObject; + readonly cape: CapeObject; + constructor(layer1Material: THREE.MeshBasicMaterial, layer2Material: THREE.MeshBasicMaterial, capeMaterial: THREE.MeshBasicMaterial); +} diff --git a/js/dist/orbit_controls.d.ts b/js/dist/orbit_controls.d.ts new file mode 100644 index 0000000..0c83f07 --- /dev/null +++ b/js/dist/orbit_controls.d.ts @@ -0,0 +1,123 @@ +import * as THREE from "three"; +import { SkinViewer } from "./viewer"; +export declare class OrbitControls extends THREE.EventDispatcher { + /** + * @preserve + * The code was originally from https://github.com/mrdoob/three.js/blob/d45a042cf962e9b1aa9441810ba118647b48aacb/examples/js/controls/OrbitControls.js + */ + /** + * @license + * Copyright (C) 2010-2017 three.js authors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * + * @author qiao / https://github.com/qiao + * @author mrdoob / http://mrdoob.com + * @author alteredq / http://alteredqualia.com/ + * @author WestLangley / http://github.com/WestLangley + * @author erich666 / http://erichaines.com + */ + object: THREE.Camera; + domElement: HTMLElement | HTMLDocument; + window: Window; + enabled: boolean; + target: THREE.Vector3; + enableZoom: boolean; + zoomSpeed: number; + minDistance: number; + maxDistance: number; + enableRotate: boolean; + rotateSpeed: number; + enablePan: boolean; + keyPanSpeed: number; + autoRotate: boolean; + autoRotateSpeed: number; + minZoom: number; + maxZoom: number; + minPolarAngle: number; + maxPolarAngle: number; + minAzimuthAngle: number; + maxAzimuthAngle: number; + enableKeys: boolean; + keys: { + LEFT: number; + UP: number; + RIGHT: number; + BOTTOM: number; + }; + mouseButtons: { + ORBIT: THREE.MOUSE; + ZOOM: THREE.MOUSE; + PAN: THREE.MOUSE; + }; + enableDamping: boolean; + dampingFactor: number; + private spherical; + private sphericalDelta; + private scale; + private target0; + private position0; + private zoom0; + private state; + private panOffset; + private zoomChanged; + private rotateStart; + private rotateEnd; + private rotateDelta; + private panStart; + private panEnd; + private panDelta; + private dollyStart; + private dollyEnd; + private dollyDelta; + private updateLastPosition; + private updateOffset; + private updateQuat; + private updateLastQuaternion; + private updateQuatInverse; + private panLeftV; + private panUpV; + private panInternalOffset; + private onContextMenu; + private onMouseUp; + private onMouseDown; + private onMouseMove; + private onMouseWheel; + private onTouchStart; + private onTouchEnd; + private onTouchMove; + private onKeyDown; + constructor(object: THREE.Camera, domElement?: HTMLElement, domWindow?: Window); + update(): boolean; + panLeft(distance: number, objectMatrix: any): void; + panUp(distance: number, objectMatrix: any): void; + pan(deltaX: number, deltaY: number): void; + dollyIn(dollyScale: any): void; + dollyOut(dollyScale: any): void; + getAutoRotationAngle(): number; + getZoomScale(): number; + rotateLeft(angle: number): void; + rotateUp(angle: number): void; + getPolarAngle(): number; + getAzimuthalAngle(): number; + dispose(): void; + reset(): void; +} +export declare function createOrbitControls(skinViewer: SkinViewer): OrbitControls; diff --git a/js/dist/revision b/js/dist/revision new file mode 100644 index 0000000..5ac0ce7 --- /dev/null +++ b/js/dist/revision @@ -0,0 +1 @@ +c2d91ca51c2d3b49ab5009593f2d6e96a623dadf diff --git a/js/dist/skinview3d.d.ts b/js/dist/skinview3d.d.ts new file mode 100644 index 0000000..bcad6e7 --- /dev/null +++ b/js/dist/skinview3d.d.ts @@ -0,0 +1,5 @@ +export { SkinObject, BodyPart, CapeObject, PlayerObject } from "./model"; +export { SkinViewer, SkinViewerOptions } from "./viewer"; +export { OrbitControls, createOrbitControls } from "./orbit_controls"; +export { IAnimation, AnimationFn, Animation, invokeAnimation, AnimationHandle, CompositeAnimation, WalkingAnimation, RunningAnimation, RotatingAnimation } from "./animation"; +export { isSlimSkin } from "./utils"; diff --git a/js/dist/skinview3d.js b/js/dist/skinview3d.js new file mode 100644 index 0000000..a114eef --- /dev/null +++ b/js/dist/skinview3d.js @@ -0,0 +1,1234 @@ +/** + * skinview3d (https://github.com/bs-community/skinview3d) + * + * MIT License + */ + +(function (global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('three')) : + typeof define === 'function' && define.amd ? define(['exports', 'three'], factory) : + (factory((global.skinview3d = {}),global.THREE)); +}(this, (function (exports,THREE) { 'use strict'; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + } + + function toFaceVertices(x1, y1, x2, y2, w, h) { + return [ + new THREE.Vector2(x1 / w, 1.0 - y2 / h), + new THREE.Vector2(x2 / w, 1.0 - y2 / h), + new THREE.Vector2(x2 / w, 1.0 - y1 / h), + new THREE.Vector2(x1 / w, 1.0 - y1 / h) + ]; + } + function toSkinVertices(x1, y1, x2, y2) { + return toFaceVertices(x1, y1, x2, y2, 64.0, 64.0); + } + function toCapeVertices(x1, y1, x2, y2) { + return toFaceVertices(x1, y1, x2, y2, 64.0, 32.0); + } + function setVertices(box, top, bottom, left, front, right, back) { + box.faceVertexUvs[0] = []; + box.faceVertexUvs[0][0] = [right[3], right[0], right[2]]; + box.faceVertexUvs[0][1] = [right[0], right[1], right[2]]; + box.faceVertexUvs[0][2] = [left[3], left[0], left[2]]; + box.faceVertexUvs[0][3] = [left[0], left[1], left[2]]; + box.faceVertexUvs[0][4] = [top[3], top[0], top[2]]; + box.faceVertexUvs[0][5] = [top[0], top[1], top[2]]; + box.faceVertexUvs[0][6] = [bottom[0], bottom[3], bottom[1]]; + box.faceVertexUvs[0][7] = [bottom[3], bottom[2], bottom[1]]; + box.faceVertexUvs[0][8] = [front[3], front[0], front[2]]; + box.faceVertexUvs[0][9] = [front[0], front[1], front[2]]; + box.faceVertexUvs[0][10] = [back[3], back[0], back[2]]; + box.faceVertexUvs[0][11] = [back[0], back[1], back[2]]; + } + var esp = 0.002; + /** + * Notice that innerLayer and outerLayer may NOT be the direct children of the Group. + */ + var BodyPart = /** @class */ (function (_super) { + __extends(BodyPart, _super); + function BodyPart(innerLayer, outerLayer) { + var _this = _super.call(this) || this; + _this.innerLayer = innerLayer; + _this.outerLayer = outerLayer; + return _this; + } + return BodyPart; + }(THREE.Group)); + var SkinObject = /** @class */ (function (_super) { + __extends(SkinObject, _super); + function SkinObject(layer1Material, layer2Material) { + var _this = _super.call(this) || this; + _this.modelListeners = []; // called when model(slim property) is changed + _this._slim = false; + // Head + var headBox = new THREE.BoxGeometry(8, 8, 8, 0, 0, 0); + setVertices(headBox, toSkinVertices(8, 0, 16, 8), toSkinVertices(16, 0, 24, 8), toSkinVertices(0, 8, 8, 16), toSkinVertices(8, 8, 16, 16), toSkinVertices(16, 8, 24, 16), toSkinVertices(24, 8, 32, 16)); + var headMesh = new THREE.Mesh(headBox, layer1Material); + var head2Box = new THREE.BoxGeometry(9, 9, 9, 0, 0, 0); + setVertices(head2Box, toSkinVertices(40, 0, 48, 8), toSkinVertices(48, 0, 56, 8), toSkinVertices(32, 8, 40, 16), toSkinVertices(40, 8, 48, 16), toSkinVertices(48, 8, 56, 16), toSkinVertices(56, 8, 64, 16)); + var head2Mesh = new THREE.Mesh(head2Box, layer2Material); + head2Mesh.renderOrder = -1; + _this.head = new BodyPart(headMesh, head2Mesh); + _this.head.add(headMesh, head2Mesh); + _this.add(_this.head); + // Body + var bodyBox = new THREE.BoxGeometry(8, 12, 4, 0, 0, 0); + setVertices(bodyBox, toSkinVertices(20, 16, 28, 20), toSkinVertices(28, 16, 36, 20), toSkinVertices(16, 20, 20, 32), toSkinVertices(20, 20, 28, 32), toSkinVertices(28, 20, 32, 32), toSkinVertices(32, 20, 40, 32)); + var bodyMesh = new THREE.Mesh(bodyBox, layer1Material); + var body2Box = new THREE.BoxGeometry(9, 13.5, 4.5, 0, 0, 0); + setVertices(body2Box, toSkinVertices(20, 32, 28, 36), toSkinVertices(28, 32, 36, 36), toSkinVertices(16, 36, 20, 48), toSkinVertices(20, 36, 28, 48), toSkinVertices(28, 36, 32, 48), toSkinVertices(32, 36, 40, 48)); + var body2Mesh = new THREE.Mesh(body2Box, layer2Material); + _this.body = new BodyPart(bodyMesh, body2Mesh); + _this.body.add(bodyMesh, body2Mesh); + _this.body.position.y = -10; + _this.add(_this.body); + // Right Arm + var rightArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related + var rightArmMesh = new THREE.Mesh(rightArmBox, layer1Material); + _this.modelListeners.push(function () { + rightArmMesh.scale.x = (_this.slim ? 3 : 4) - esp; + rightArmMesh.scale.y = 12 - esp; + rightArmMesh.scale.z = 4 - esp; + if (_this.slim) { + setVertices(rightArmBox, toSkinVertices(44, 16, 47, 20), toSkinVertices(47, 16, 50, 20), toSkinVertices(40, 20, 44, 32), toSkinVertices(44, 20, 47, 32), toSkinVertices(47, 20, 51, 32), toSkinVertices(51, 20, 54, 32)); + } + else { + setVertices(rightArmBox, toSkinVertices(44, 16, 48, 20), toSkinVertices(48, 16, 52, 20), toSkinVertices(40, 20, 44, 32), toSkinVertices(44, 20, 48, 32), toSkinVertices(48, 20, 52, 32), toSkinVertices(52, 20, 56, 32)); + } + rightArmBox.uvsNeedUpdate = true; + rightArmBox.elementsNeedUpdate = true; + }); + var rightArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related + var rightArm2Mesh = new THREE.Mesh(rightArm2Box, layer2Material); + rightArm2Mesh.renderOrder = 1; + _this.modelListeners.push(function () { + rightArm2Mesh.scale.x = (_this.slim ? 3.375 : 4.5) - esp; + rightArm2Mesh.scale.y = 13.5 - esp; + rightArm2Mesh.scale.z = 4.5 - esp; + if (_this.slim) { + setVertices(rightArm2Box, toSkinVertices(44, 32, 47, 36), toSkinVertices(47, 32, 50, 36), toSkinVertices(40, 36, 44, 48), toSkinVertices(44, 36, 47, 48), toSkinVertices(47, 36, 51, 48), toSkinVertices(51, 36, 54, 48)); + } + else { + setVertices(rightArm2Box, toSkinVertices(44, 32, 48, 36), toSkinVertices(48, 32, 52, 36), toSkinVertices(40, 36, 44, 48), toSkinVertices(44, 36, 48, 48), toSkinVertices(48, 36, 52, 48), toSkinVertices(52, 36, 56, 48)); + } + rightArm2Box.uvsNeedUpdate = true; + rightArm2Box.elementsNeedUpdate = true; + }); + var rightArmPivot = new THREE.Group(); + rightArmPivot.add(rightArmMesh, rightArm2Mesh); + rightArmPivot.position.y = -6; + _this.rightArm = new BodyPart(rightArmMesh, rightArm2Mesh); + _this.rightArm.add(rightArmPivot); + _this.rightArm.position.y = -4; + _this.modelListeners.push(function () { + _this.rightArm.position.x = _this.slim ? -5.5 : -6; + }); + _this.add(_this.rightArm); + // Left Arm + var leftArmBox = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related + var leftArmMesh = new THREE.Mesh(leftArmBox, layer1Material); + _this.modelListeners.push(function () { + leftArmMesh.scale.x = (_this.slim ? 3 : 4) - esp; + leftArmMesh.scale.y = 12 - esp; + leftArmMesh.scale.z = 4 - esp; + if (_this.slim) { + setVertices(leftArmBox, toSkinVertices(36, 48, 39, 52), toSkinVertices(39, 48, 42, 52), toSkinVertices(32, 52, 36, 64), toSkinVertices(36, 52, 39, 64), toSkinVertices(39, 52, 43, 64), toSkinVertices(43, 52, 46, 64)); + } + else { + setVertices(leftArmBox, toSkinVertices(36, 48, 40, 52), toSkinVertices(40, 48, 44, 52), toSkinVertices(32, 52, 36, 64), toSkinVertices(36, 52, 40, 64), toSkinVertices(40, 52, 44, 64), toSkinVertices(44, 52, 48, 64)); + } + leftArmBox.uvsNeedUpdate = true; + leftArmBox.elementsNeedUpdate = true; + }); + var leftArm2Box = new THREE.BoxGeometry(1, 1, 1, 0, 0, 0); // w/d/h is model-related + var leftArm2Mesh = new THREE.Mesh(leftArm2Box, layer2Material); + leftArm2Mesh.renderOrder = 1; + _this.modelListeners.push(function () { + leftArm2Mesh.scale.x = (_this.slim ? 3.375 : 4.5) - esp; + leftArm2Mesh.scale.y = 13.5 - esp; + leftArm2Mesh.scale.z = 4.5 - esp; + if (_this.slim) { + setVertices(leftArm2Box, toSkinVertices(52, 48, 55, 52), toSkinVertices(55, 48, 58, 52), toSkinVertices(48, 52, 52, 64), toSkinVertices(52, 52, 55, 64), toSkinVertices(55, 52, 59, 64), toSkinVertices(59, 52, 62, 64)); + } + else { + setVertices(leftArm2Box, toSkinVertices(52, 48, 56, 52), toSkinVertices(56, 48, 60, 52), toSkinVertices(48, 52, 52, 64), toSkinVertices(52, 52, 56, 64), toSkinVertices(56, 52, 60, 64), toSkinVertices(60, 52, 64, 64)); + } + leftArm2Box.uvsNeedUpdate = true; + leftArm2Box.elementsNeedUpdate = true; + }); + var leftArmPivot = new THREE.Group(); + leftArmPivot.add(leftArmMesh, leftArm2Mesh); + leftArmPivot.position.y = -6; + _this.leftArm = new BodyPart(leftArmMesh, leftArm2Mesh); + _this.leftArm.add(leftArmPivot); + _this.leftArm.position.y = -4; + _this.modelListeners.push(function () { + _this.leftArm.position.x = _this.slim ? 5.5 : 6; + }); + _this.add(_this.leftArm); + // Right Leg + var rightLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0); + setVertices(rightLegBox, toSkinVertices(4, 16, 8, 20), toSkinVertices(8, 16, 12, 20), toSkinVertices(0, 20, 4, 32), toSkinVertices(4, 20, 8, 32), toSkinVertices(8, 20, 12, 32), toSkinVertices(12, 20, 16, 32)); + var rightLegMesh = new THREE.Mesh(rightLegBox, layer1Material); + var rightLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0); + setVertices(rightLeg2Box, toSkinVertices(4, 32, 8, 36), toSkinVertices(8, 32, 12, 36), toSkinVertices(0, 36, 4, 48), toSkinVertices(4, 36, 8, 48), toSkinVertices(8, 36, 12, 48), toSkinVertices(12, 36, 16, 48)); + var rightLeg2Mesh = new THREE.Mesh(rightLeg2Box, layer2Material); + rightLeg2Mesh.renderOrder = 1; + var rightLegPivot = new THREE.Group(); + rightLegPivot.add(rightLegMesh, rightLeg2Mesh); + rightLegPivot.position.y = -6; + _this.rightLeg = new BodyPart(rightLegMesh, rightLeg2Mesh); + _this.rightLeg.add(rightLegPivot); + _this.rightLeg.position.y = -16; + _this.rightLeg.position.x = -2; + _this.add(_this.rightLeg); + // Left Leg + var leftLegBox = new THREE.BoxGeometry(4 - esp, 12 - esp, 4 - esp, 0, 0, 0); + setVertices(leftLegBox, toSkinVertices(20, 48, 24, 52), toSkinVertices(24, 48, 28, 52), toSkinVertices(16, 52, 20, 64), toSkinVertices(20, 52, 24, 64), toSkinVertices(24, 52, 28, 64), toSkinVertices(28, 52, 32, 64)); + var leftLegMesh = new THREE.Mesh(leftLegBox, layer1Material); + var leftLeg2Box = new THREE.BoxGeometry(4.5 - esp, 13.5 - esp, 4.5 - esp, 0, 0, 0); + setVertices(leftLeg2Box, toSkinVertices(4, 48, 8, 52), toSkinVertices(8, 48, 12, 52), toSkinVertices(0, 52, 4, 64), toSkinVertices(4, 52, 8, 64), toSkinVertices(8, 52, 12, 64), toSkinVertices(12, 52, 16, 64)); + var leftLeg2Mesh = new THREE.Mesh(leftLeg2Box, layer2Material); + leftLeg2Mesh.renderOrder = 1; + var leftLegPivot = new THREE.Group(); + leftLegPivot.add(leftLegMesh, leftLeg2Mesh); + leftLegPivot.position.y = -6; + _this.leftLeg = new BodyPart(leftLegMesh, leftLeg2Mesh); + _this.leftLeg.add(leftLegPivot); + _this.leftLeg.position.y = -16; + _this.leftLeg.position.x = 2; + _this.add(_this.leftLeg); + _this.slim = false; + return _this; + } + Object.defineProperty(SkinObject.prototype, "slim", { + get: function () { + return this._slim; + }, + set: function (value) { + this._slim = value; + this.modelListeners.forEach(function (listener) { return listener(); }); + }, + enumerable: true, + configurable: true + }); + SkinObject.prototype.getBodyParts = function () { + return this.children.filter(function (it) { return it instanceof BodyPart; }); + }; + SkinObject.prototype.setInnerLayerVisible = function (value) { + this.getBodyParts().forEach(function (part) { return part.innerLayer.visible = value; }); + }; + SkinObject.prototype.setOuterLayerVisible = function (value) { + this.getBodyParts().forEach(function (part) { return part.outerLayer.visible = value; }); + }; + return SkinObject; + }(THREE.Group)); + var CapeObject = /** @class */ (function (_super) { + __extends(CapeObject, _super); + function CapeObject(capeMaterial) { + var _this = _super.call(this) || this; + // back = outside + // front = inside + var capeBox = new THREE.BoxGeometry(10, 16, 1, 0, 0, 0); + setVertices(capeBox, toCapeVertices(1, 0, 11, 1), toCapeVertices(11, 0, 21, 1), toCapeVertices(11, 1, 12, 17), toCapeVertices(12, 1, 22, 17), toCapeVertices(0, 1, 1, 17), toCapeVertices(1, 1, 11, 17)); + _this.cape = new THREE.Mesh(capeBox, capeMaterial); + _this.cape.position.y = -8; + _this.cape.position.z = -0.5; + _this.add(_this.cape); + return _this; + } + return CapeObject; + }(THREE.Group)); + var PlayerObject = /** @class */ (function (_super) { + __extends(PlayerObject, _super); + function PlayerObject(layer1Material, layer2Material, capeMaterial) { + var _this = _super.call(this) || this; + _this.skin = new SkinObject(layer1Material, layer2Material); + _this.skin.visible = false; + _this.add(_this.skin); + _this.cape = new CapeObject(capeMaterial); + _this.cape.position.z = -2; + _this.cape.position.y = -4; + _this.cape.rotation.x = 25 * Math.PI / 180; + _this.cape.visible = false; + _this.add(_this.cape); + return _this; + } + return PlayerObject; + }(THREE.Group)); + + function invokeAnimation(animation, player, time) { + if (animation instanceof Function) { + animation(player, time); + } + else { + // must be IAnimation here + animation.play(player, time); + } + } + var AnimationWrapper = /** @class */ (function () { + function AnimationWrapper(animation) { + this.paused = false; + this.speed = 1.0; + this._paused = false; + this._lastChange = null; + this._speed = 1.0; + this._lastChangeX = null; + this.animation = animation; + } + AnimationWrapper.prototype.play = function (player, time) { + if (this._lastChange === null) { + this._lastChange = time; + this._lastChangeX = 0; + } + else if (this.paused !== this._paused || this.speed !== this._speed) { + var dt = time - this._lastChange; + if (this._paused === false) { + this._lastChangeX += dt * this._speed; + } + this._paused = this.paused; + this._speed = this.speed; + this._lastChange = time; + } + if (this.paused === false) { + var dt = time - this._lastChange; + var x = this._lastChangeX + this.speed * dt; + invokeAnimation(this.animation, player, x); + } + }; + AnimationWrapper.prototype.reset = function () { + this._lastChange = null; + }; + AnimationWrapper.prototype.remove = function () { + // stub get's overriden + }; + return AnimationWrapper; + }()); + var CompositeAnimation = /** @class */ (function () { + function CompositeAnimation() { + this.handles = new Set(); + } + CompositeAnimation.prototype.add = function (animation) { + var _this = this; + var handle = new AnimationWrapper(animation); + handle.remove = function () { return _this.handles.delete(handle); }; + this.handles.add(handle); + return handle; + }; + CompositeAnimation.prototype.play = function (player, time) { + this.handles.forEach(function (handle) { return handle.play(player, time); }); + }; + return CompositeAnimation; + }()); + var WalkingAnimation = function (player, time) { + var skin = player.skin; + // Multiply by animation's natural speed + time *= 8; + // Leg swing + skin.leftLeg.rotation.x = Math.sin(time) * 0.5; + skin.rightLeg.rotation.x = Math.sin(time + Math.PI) * 0.5; + // Arm swing + skin.leftArm.rotation.x = Math.sin(time + Math.PI) * 0.5; + skin.rightArm.rotation.x = Math.sin(time) * 0.5; + var basicArmRotationZ = Math.PI * 0.02; + skin.leftArm.rotation.z = Math.cos(time) * 0.03 + basicArmRotationZ; + skin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.03 - basicArmRotationZ; + // Head shaking with different frequency & amplitude + skin.head.rotation.y = Math.sin(time / 4) * 0.2; + skin.head.rotation.x = Math.sin(time / 5) * 0.1; + // Always add an angle for cape around the x axis + var basicCapeRotationX = Math.PI * 0.06; + player.cape.rotation.x = Math.sin(time / 1.5) * 0.06 + basicCapeRotationX; + }; + var RunningAnimation = function (player, time) { + var skin = player.skin; + time *= 15; + // Leg swing with larger amplitude + skin.leftLeg.rotation.x = Math.cos(time + Math.PI) * 1.3; + skin.rightLeg.rotation.x = Math.cos(time) * 1.3; + // Arm swing + skin.leftArm.rotation.x = Math.cos(time) * 1.5; + skin.rightArm.rotation.x = Math.cos(time + Math.PI) * 1.5; + var basicArmRotationZ = Math.PI * 0.1; + skin.leftArm.rotation.z = Math.cos(time) * 0.1 + basicArmRotationZ; + skin.rightArm.rotation.z = Math.cos(time + Math.PI) * 0.1 - basicArmRotationZ; + // Jumping + player.position.y = Math.cos(time * 2); + // Dodging when running + player.position.x = Math.cos(time) * 0.15; + // Slightly tilting when running + player.rotation.z = Math.cos(time + Math.PI) * 0.01; + // Apply higher swing frequency, lower amplitude, + // and greater basic rotation around x axis, + // to cape when running. + var basicCapeRotationX = Math.PI * 0.3; + player.cape.rotation.x = Math.sin(time * 2) * 0.1 + basicCapeRotationX; + // What about head shaking? + // You shouldn't glance right and left when running dude :P + }; + var RotatingAnimation = function (player, time) { + player.rotation.y = time; + }; + + function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) { + var imgData = context.getImageData(sX, sY, w, h); + if (flipHorizontal) { + for (var y = 0; y < h; y++) { + for (var x = 0; x < (w / 2); x++) { + var index = (x + y * w) * 4; + var index2 = ((w - x - 1) + y * w) * 4; + var pA1 = imgData.data[index]; + var pA2 = imgData.data[index + 1]; + var pA3 = imgData.data[index + 2]; + var pA4 = imgData.data[index + 3]; + var pB1 = imgData.data[index2]; + var pB2 = imgData.data[index2 + 1]; + var pB3 = imgData.data[index2 + 2]; + var 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; + } + } + } + context.putImageData(imgData, dX, dY); + } + function hasTransparency(context, x0, y0, w, h) { + var imgData = context.getImageData(x0, y0, w, h); + for (var x = 0; x < w; x++) { + for (var y = 0; y < h; y++) { + var offset = (x + y * w) * 4; + if (imgData.data[offset + 3] !== 0xff) { + return true; + } + } + } + return false; + } + function computeSkinScale(width) { + return width / 64.0; + } + function fixOpaqueSkin(context, width) { + // Some ancient skins don't have transparent pixels (nor have helm). + // We have to make the helm area transparent, otherwise it will be rendered as black. + if (!hasTransparency(context, 0, 0, width, width / 2)) { + var scale_1 = computeSkinScale(width); + var clearArea = function (x, y, w, h) { return context.clearRect(x * scale_1, y * scale_1, w * scale_1, h * scale_1); }; + clearArea(40, 0, 8, 8); // Helm Top + clearArea(48, 0, 8, 8); // Helm Bottom + clearArea(32, 8, 8, 8); // Helm Right + clearArea(40, 8, 8, 8); // Helm Front + clearArea(48, 8, 8, 8); // Helm Left + clearArea(56, 8, 8, 8); // Helm Back + } + } + function convertSkinTo1_8(context, width) { + var scale = computeSkinScale(width); + var copySkin = function (sX, sY, w, h, dX, dY, flipHorizontal) { return copyImage(context, sX * scale, sY * scale, w * scale, h * scale, dX * scale, dY * scale, flipHorizontal); }; + fixOpaqueSkin(context, width); + copySkin(4, 16, 4, 4, 20, 48, true); // Top Leg + copySkin(8, 16, 4, 4, 24, 48, true); // Bottom Leg + copySkin(0, 20, 4, 12, 24, 52, true); // Outer Leg + copySkin(4, 20, 4, 12, 20, 52, true); // Front Leg + copySkin(8, 20, 4, 12, 16, 52, true); // Inner Leg + copySkin(12, 20, 4, 12, 28, 52, true); // Back Leg + copySkin(44, 16, 4, 4, 36, 48, true); // Top Arm + copySkin(48, 16, 4, 4, 40, 48, true); // Bottom Arm + copySkin(40, 20, 4, 12, 40, 52, true); // Outer Arm + copySkin(44, 20, 4, 12, 36, 52, true); // Front Arm + copySkin(48, 20, 4, 12, 32, 52, true); // Inner Arm + copySkin(52, 20, 4, 12, 44, 52, true); // Back Arm + } + function loadSkinToCanvas(canvas, image) { + var isOldFormat = false; + if (image.width !== image.height) { + if (image.width === 2 * image.height) { + isOldFormat = true; + } + else { + throw new Error("Bad skin size: " + image.width + "x" + image.height); + } + } + var context = canvas.getContext("2d"); + if (isOldFormat) { + var sideLength = image.width; + canvas.width = sideLength; + canvas.height = sideLength; + context.clearRect(0, 0, sideLength, sideLength); + context.drawImage(image, 0, 0, sideLength, sideLength / 2.0); + convertSkinTo1_8(context, sideLength); + } + else { + canvas.width = image.width; + canvas.height = image.height; + context.clearRect(0, 0, image.width, image.height); + context.drawImage(image, 0, 0, canvas.width, canvas.height); + } + } + function loadCapeToCanvas(canvas, image) { + var isOldFormat = false; + if (image.width !== 2 * image.height) { + if (image.width * 17 === image.height * 22) { + // width/height = 22/17 + isOldFormat = true; + } + else { + throw new Error("Bad cape size: " + image.width + "x" + image.height); + } + } + var context = canvas.getContext("2d"); + if (isOldFormat) { + var width = image.width * 64 / 22; + canvas.width = width; + canvas.height = width / 2; + } + else { + canvas.width = image.width; + canvas.height = image.height; + } + context.clearRect(0, 0, canvas.width, canvas.height); + context.drawImage(image, 0, 0, image.width, image.height); + } + function isSlimSkin(canvasOrImage) { + // Detects whether the skin is default or slim. + // + // The right arm area of *default* skins: + // (44,16)->*-------*-------* + // (40,20) |top |bottom | + // \|/ |4x4 |4x4 | + // *-------*-------*-------*-------* + // |right |front |left |back | + // |4x12 |4x12 |4x12 |4x12 | + // *-------*-------*-------*-------* + // The right arm area of *slim* skins: + // (44,16)->*------*------*-* + // (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4] + // \|/ |3x4 |3x4 | | + // *-------*------*------***-----*-* + // |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12] + // |4x12 |3x12 |4x12 |3x12 | | + // *-------*------*-------*------*-* + // Compared with default right arms, slim right arms have 2 unused areas. + // + // The same is true for left arm: + // The left arm area of *default* skins: + // (36,48)->*-------*-------* + // (32,52) |top |bottom | + // \|/ |4x4 |4x4 | + // *-------*-------*-------*-------* + // |right |front |left |back | + // |4x12 |4x12 |4x12 |4x12 | + // *-------*-------*-------*-------* + // The left arm area of *slim* skins: + // (36,48)->*------*------*-* + // (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4] + // \|/ |3x4 |3x4 | | + // *-------*------*------***-----*-* + // |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12] + // |4x12 |3x12 |4x12 |3x12 | | + // *-------*------*-------*------*-* + // + // If there is a transparent pixel in any of the 4 unused areas, the skin must be slim, + // as transparent pixels are not allowed in the first layer. + if (canvasOrImage instanceof HTMLCanvasElement) { + var canvas = canvasOrImage; + var scale_2 = computeSkinScale(canvas.width); + var context_1 = canvas.getContext("2d"); + var checkArea = function (x, y, w, h) { return hasTransparency(context_1, x * scale_2, y * scale_2, w * scale_2, h * scale_2); }; + return checkArea(50, 16, 2, 4) || + checkArea(54, 20, 2, 12) || + checkArea(42, 48, 2, 4) || + checkArea(46, 52, 2, 12); + } + else { + var image = canvasOrImage; + var canvas = document.createElement("canvas"); + loadSkinToCanvas(canvas, image); + return isSlimSkin(canvas); + } + } + + var SkinViewer = /** @class */ (function () { + function SkinViewer(options) { + var _this = this; + this.detectModel = true; + this.animationPaused = false; + this.animationTime = 0; + this.disposed = false; + this.domElement = options.domElement; + this.animation = options.animation || null; + if (options.detectModel === false) { + this.detectModel = false; + } + // texture + this.skinImg = new Image(); + this.skinCanvas = document.createElement("canvas"); + this.skinTexture = new THREE.Texture(this.skinCanvas); + this.skinTexture.magFilter = THREE.NearestFilter; + this.skinTexture.minFilter = THREE.NearestFilter; + this.capeImg = new Image(); + this.capeCanvas = document.createElement("canvas"); + this.capeTexture = new THREE.Texture(this.capeCanvas); + this.capeTexture.magFilter = THREE.NearestFilter; + this.capeTexture.minFilter = THREE.NearestFilter; + this.layer1Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, side: THREE.FrontSide }); + this.layer2Material = new THREE.MeshBasicMaterial({ map: this.skinTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 }); + this.capeMaterial = new THREE.MeshBasicMaterial({ map: this.capeTexture, transparent: true, opacity: 1, side: THREE.DoubleSide, alphaTest: 0.5 }); + // scene + this.scene = new THREE.Scene(); + // Use smaller fov to avoid distortion + this.camera = new THREE.PerspectiveCamera(40); + this.camera.position.y = -12; + this.camera.position.z = 60; + this.renderer = new THREE.WebGLRenderer({ alpha: true, antialias: false }); + this.renderer.setSize(300, 300); // default size + this.renderer.context.getShaderInfoLog = function () { return ""; }; // shut firefox up + this.domElement.appendChild(this.renderer.domElement); + this.playerObject = new PlayerObject(this.layer1Material, this.layer2Material, this.capeMaterial); + this.scene.add(this.playerObject); + // texture loading + this.skinImg.crossOrigin = "anonymous"; + this.skinImg.onerror = function () { return console.error("Failed loading " + _this.skinImg.src); }; + this.skinImg.onload = function () { + loadSkinToCanvas(_this.skinCanvas, _this.skinImg); + if (_this.detectModel) { + _this.playerObject.skin.slim = isSlimSkin(_this.skinCanvas); + } + _this.skinTexture.needsUpdate = true; + _this.layer1Material.needsUpdate = true; + _this.layer2Material.needsUpdate = true; + _this.playerObject.skin.visible = true; + }; + this.capeImg.crossOrigin = "anonymous"; + this.capeImg.onerror = function () { return console.error("Failed loading " + _this.capeImg.src); }; + this.capeImg.onload = function () { + loadCapeToCanvas(_this.capeCanvas, _this.capeImg); + _this.capeTexture.needsUpdate = true; + _this.capeMaterial.needsUpdate = true; + _this.playerObject.cape.visible = true; + }; + if (options.skinUrl) + this.skinUrl = options.skinUrl; + if (options.capeUrl) + this.capeUrl = options.capeUrl; + if (options.width) + this.width = options.width; + if (options.height) + this.height = options.height; + var draw = function () { + if (_this.disposed) + return; + window.requestAnimationFrame(draw); + if (!_this.animationPaused) { + _this.animationTime++; + if (_this.animation) { + invokeAnimation(_this.animation, _this.playerObject, _this.animationTime / 100.0); + } + } + _this.renderer.render(_this.scene, _this.camera); + }; + draw(); + } + SkinViewer.prototype.setSize = function (width, height) { + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + }; + SkinViewer.prototype.dispose = function () { + this.disposed = true; + this.domElement.removeChild(this.renderer.domElement); + this.renderer.dispose(); + this.skinTexture.dispose(); + this.capeTexture.dispose(); + }; + Object.defineProperty(SkinViewer.prototype, "skinUrl", { + get: function () { + return this.skinImg.src; + }, + set: function (url) { + this.skinImg.src = url; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "capeUrl", { + get: function () { + return this.capeImg.src; + }, + set: function (url) { + this.capeImg.src = url; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "width", { + get: function () { + return this.renderer.getSize().width; + }, + set: function (newWidth) { + this.setSize(newWidth, this.height); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "height", { + get: function () { + return this.renderer.getSize().height; + }, + set: function (newHeight) { + this.setSize(this.width, newHeight); + }, + enumerable: true, + configurable: true + }); + return SkinViewer; + }()); + + var STATE = { + NONE: -1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_DOLLY: 4, + TOUCH_PAN: 5 + }; + var CHANGE_EVENT = { type: "change" }; + var START_EVENT = { type: "start" }; + var END_EVENT = { type: "end" }; + var EPS = 0.000001; + var OrbitControls = /** @class */ (function (_super) { + __extends(OrbitControls, _super); + function OrbitControls(object, domElement, domWindow) { + var _this = _super.call(this) || this; + _this.object = object; + _this.domElement = (domElement !== undefined) ? domElement : document; + _this.window = (domWindow !== undefined) ? domWindow : window; + // Set to false to disable this control + _this.enabled = true; + // "target" sets the location of focus, where the object orbits around + _this.target = new THREE.Vector3(); + // How far you can dolly in and out ( PerspectiveCamera only ) + _this.minDistance = 0; + _this.maxDistance = Infinity; + // How far you can zoom in and out ( OrthographicCamera only ) + _this.minZoom = 0; + _this.maxZoom = Infinity; + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + _this.minPolarAngle = 0; // radians + _this.maxPolarAngle = Math.PI; // radians + // How far you can orbit horizontally, upper and lower limits. + // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. + _this.minAzimuthAngle = -Infinity; // radians + _this.maxAzimuthAngle = Infinity; // radians + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + _this.enableDamping = false; + _this.dampingFactor = 0.25; + // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. + // Set to false to disable zooming + _this.enableZoom = true; + _this.zoomSpeed = 1.0; + // Set to false to disable rotating + _this.enableRotate = true; + _this.rotateSpeed = 1.0; + // Set to false to disable panning + _this.enablePan = true; + _this.keyPanSpeed = 7.0; // pixels moved per arrow key push + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + _this.autoRotate = false; + _this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + // Set to false to disable use of the keys + _this.enableKeys = true; + // The four arrow keys + _this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; + // Mouse buttons + _this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT }; + // for reset + _this.target0 = _this.target.clone(); + _this.position0 = _this.object.position.clone(); + _this.zoom0 = _this.object.zoom; + // for update speedup + _this.updateOffset = new THREE.Vector3(); + // so camera.up is the orbit axis + _this.updateQuat = new THREE.Quaternion().setFromUnitVectors(object.up, new THREE.Vector3(0, 1, 0)); + _this.updateQuatInverse = _this.updateQuat.clone().inverse(); + _this.updateLastPosition = new THREE.Vector3(); + _this.updateLastQuaternion = new THREE.Quaternion(); + _this.state = STATE.NONE; + _this.scale = 1; + // current position in spherical coordinates + _this.spherical = new THREE.Spherical(); + _this.sphericalDelta = new THREE.Spherical(); + _this.panOffset = new THREE.Vector3(); + _this.zoomChanged = false; + _this.rotateStart = new THREE.Vector2(); + _this.rotateEnd = new THREE.Vector2(); + _this.rotateDelta = new THREE.Vector2(); + _this.panStart = new THREE.Vector2(); + _this.panEnd = new THREE.Vector2(); + _this.panDelta = new THREE.Vector2(); + _this.dollyStart = new THREE.Vector2(); + _this.dollyEnd = new THREE.Vector2(); + _this.dollyDelta = new THREE.Vector2(); + _this.panLeftV = new THREE.Vector3(); + _this.panUpV = new THREE.Vector3(); + _this.panInternalOffset = new THREE.Vector3(); + // event handlers - FSM: listen for events and reset state + _this.onMouseDown = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + if (event.button === _this.mouseButtons.ORBIT) { + if (_this.enableRotate === false) + return; + _this.rotateStart.set(event.clientX, event.clientY); + _this.state = STATE.ROTATE; + } + else if (event.button === _this.mouseButtons.ZOOM) { + if (_this.enableZoom === false) + return; + _this.dollyStart.set(event.clientX, event.clientY); + _this.state = STATE.DOLLY; + } + else if (event.button === _this.mouseButtons.PAN) { + if (_this.enablePan === false) + return; + _this.panStart.set(event.clientX, event.clientY); + _this.state = STATE.PAN; + } + if (_this.state !== STATE.NONE) { + document.addEventListener("mousemove", _this.onMouseMove, false); + document.addEventListener("mouseup", _this.onMouseUp, false); + _this.dispatchEvent(START_EVENT); + } + }; + _this.onMouseMove = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + if (_this.state === STATE.ROTATE) { + if (_this.enableRotate === false) + return; + _this.rotateEnd.set(event.clientX, event.clientY); + _this.rotateDelta.subVectors(_this.rotateEnd, _this.rotateStart); + var element = _this.domElement === document ? _this.domElement.body : _this.domElement; + // rotating across whole screen goes 360 degrees around + _this.rotateLeft(2 * Math.PI * _this.rotateDelta.x / element.clientWidth * _this.rotateSpeed); + // rotating up and down along whole screen attempts to go 360, but limited to 180 + _this.rotateUp(2 * Math.PI * _this.rotateDelta.y / element.clientHeight * _this.rotateSpeed); + _this.rotateStart.copy(_this.rotateEnd); + _this.update(); + } + else if (_this.state === STATE.DOLLY) { + if (_this.enableZoom === false) + return; + _this.dollyEnd.set(event.clientX, event.clientY); + _this.dollyDelta.subVectors(_this.dollyEnd, _this.dollyStart); + if (_this.dollyDelta.y > 0) { + _this.dollyIn(_this.getZoomScale()); + } + else if (_this.dollyDelta.y < 0) { + _this.dollyOut(_this.getZoomScale()); + } + _this.dollyStart.copy(_this.dollyEnd); + _this.update(); + } + else if (_this.state === STATE.PAN) { + if (_this.enablePan === false) + return; + _this.panEnd.set(event.clientX, event.clientY); + _this.panDelta.subVectors(_this.panEnd, _this.panStart); + _this.pan(_this.panDelta.x, _this.panDelta.y); + _this.panStart.copy(_this.panEnd); + _this.update(); + } + }; + _this.onMouseUp = function (event) { + if (_this.enabled === false) + return; + document.removeEventListener("mousemove", _this.onMouseMove, false); + document.removeEventListener("mouseup", _this.onMouseUp, false); + _this.dispatchEvent(END_EVENT); + _this.state = STATE.NONE; + }; + _this.onMouseWheel = function (event) { + if (_this.enabled === false || _this.enableZoom === false || (_this.state !== STATE.NONE && _this.state !== STATE.ROTATE)) + return; + event.preventDefault(); + event.stopPropagation(); + if (event.deltaY < 0) { + _this.dollyOut(_this.getZoomScale()); + } + else if (event.deltaY > 0) { + _this.dollyIn(_this.getZoomScale()); + } + _this.update(); + _this.dispatchEvent(START_EVENT); // not sure why these are here... + _this.dispatchEvent(END_EVENT); + }; + _this.onKeyDown = function (event) { + if (_this.enabled === false || _this.enableKeys === false || _this.enablePan === false) + return; + switch (event.keyCode) { + case _this.keys.UP: { + _this.pan(0, _this.keyPanSpeed); + _this.update(); + break; + } + case _this.keys.BOTTOM: { + _this.pan(0, -_this.keyPanSpeed); + _this.update(); + break; + } + case _this.keys.LEFT: { + _this.pan(_this.keyPanSpeed, 0); + _this.update(); + break; + } + case _this.keys.RIGHT: { + _this.pan(-_this.keyPanSpeed, 0); + _this.update(); + break; + } + } + }; + _this.onTouchStart = function (event) { + if (_this.enabled === false) + return; + switch (event.touches.length) { + // one-fingered touch: rotate + case 1: { + if (_this.enableRotate === false) + return; + _this.rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); + _this.state = STATE.TOUCH_ROTATE; + break; + } + // two-fingered touch: dolly + case 2: { + if (_this.enableZoom === false) + return; + var dx = event.touches[0].pageX - event.touches[1].pageX; + var dy = event.touches[0].pageY - event.touches[1].pageY; + var distance = Math.sqrt(dx * dx + dy * dy); + _this.dollyStart.set(0, distance); + _this.state = STATE.TOUCH_DOLLY; + break; + } + // three-fingered touch: pan + case 3: { + if (_this.enablePan === false) + return; + _this.panStart.set(event.touches[0].pageX, event.touches[0].pageY); + _this.state = STATE.TOUCH_PAN; + break; + } + default: { + _this.state = STATE.NONE; + } + } + if (_this.state !== STATE.NONE) { + _this.dispatchEvent(START_EVENT); + } + }; + _this.onTouchMove = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + event.stopPropagation(); + switch (event.touches.length) { + // one-fingered touch: rotate + case 1: { + if (_this.enableRotate === false) + return; + if (_this.state !== STATE.TOUCH_ROTATE) + return; // is this needed?... + _this.rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); + _this.rotateDelta.subVectors(_this.rotateEnd, _this.rotateStart); + var element = _this.domElement === document ? _this.domElement.body : _this.domElement; + // rotating across whole screen goes 360 degrees around + _this.rotateLeft(2 * Math.PI * _this.rotateDelta.x / element.clientWidth * _this.rotateSpeed); + // rotating up and down along whole screen attempts to go 360, but limited to 180 + _this.rotateUp(2 * Math.PI * _this.rotateDelta.y / element.clientHeight * _this.rotateSpeed); + _this.rotateStart.copy(_this.rotateEnd); + _this.update(); + break; + } + // two-fingered touch: dolly + case 2: { + if (_this.enableZoom === false) + return; + if (_this.state !== STATE.TOUCH_DOLLY) + return; // is this needed?... + // console.log( "handleTouchMoveDolly" ); + var dx = event.touches[0].pageX - event.touches[1].pageX; + var dy = event.touches[0].pageY - event.touches[1].pageY; + var distance = Math.sqrt(dx * dx + dy * dy); + _this.dollyEnd.set(0, distance); + _this.dollyDelta.subVectors(_this.dollyEnd, _this.dollyStart); + if (_this.dollyDelta.y > 0) { + _this.dollyOut(_this.getZoomScale()); + } + else if (_this.dollyDelta.y < 0) { + _this.dollyIn(_this.getZoomScale()); + } + _this.dollyStart.copy(_this.dollyEnd); + _this.update(); + break; + } + // three-fingered touch: pan + case 3: { + if (_this.enablePan === false) + return; + if (_this.state !== STATE.TOUCH_PAN) + return; // is this needed?... + _this.panEnd.set(event.touches[0].pageX, event.touches[0].pageY); + _this.panDelta.subVectors(_this.panEnd, _this.panStart); + _this.pan(_this.panDelta.x, _this.panDelta.y); + _this.panStart.copy(_this.panEnd); + _this.update(); + break; + } + default: { + _this.state = STATE.NONE; + } + } + }; + _this.onTouchEnd = function (event) { + if (_this.enabled === false) + return; + _this.dispatchEvent(END_EVENT); + _this.state = STATE.NONE; + }; + _this.onContextMenu = function (event) { + event.preventDefault(); + }; + _this.domElement.addEventListener("contextmenu", _this.onContextMenu, false); + _this.domElement.addEventListener("mousedown", _this.onMouseDown, false); + _this.domElement.addEventListener("wheel", _this.onMouseWheel, false); + _this.domElement.addEventListener("touchstart", _this.onTouchStart, false); + _this.domElement.addEventListener("touchend", _this.onTouchEnd, false); + _this.domElement.addEventListener("touchmove", _this.onTouchMove, false); + _this.window.addEventListener("keydown", _this.onKeyDown, false); + // force an update at start + _this.update(); + return _this; + } + OrbitControls.prototype.update = function () { + var position = this.object.position; + this.updateOffset.copy(position).sub(this.target); + // rotate offset to "y-axis-is-up" space + this.updateOffset.applyQuaternion(this.updateQuat); + // angle from z-axis around y-axis + this.spherical.setFromVector3(this.updateOffset); + if (this.autoRotate && this.state === STATE.NONE) { + this.rotateLeft(this.getAutoRotationAngle()); + } + this.spherical.theta += this.sphericalDelta.theta; + this.spherical.phi += this.sphericalDelta.phi; + // restrict theta to be between desired limits + this.spherical.theta = Math.max(this.minAzimuthAngle, Math.min(this.maxAzimuthAngle, this.spherical.theta)); + // restrict phi to be between desired limits + this.spherical.phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.spherical.phi)); + this.spherical.makeSafe(); + this.spherical.radius *= this.scale; + // restrict radius to be between desired limits + this.spherical.radius = Math.max(this.minDistance, Math.min(this.maxDistance, this.spherical.radius)); + // move target to panned location + this.target.add(this.panOffset); + this.updateOffset.setFromSpherical(this.spherical); + // rotate offset back to "camera-up-vector-is-up" space + this.updateOffset.applyQuaternion(this.updateQuatInverse); + position.copy(this.target).add(this.updateOffset); + this.object.lookAt(this.target); + if (this.enableDamping === true) { + this.sphericalDelta.theta *= (1 - this.dampingFactor); + this.sphericalDelta.phi *= (1 - this.dampingFactor); + } + else { + this.sphericalDelta.set(0, 0, 0); + } + this.scale = 1; + this.panOffset.set(0, 0, 0); + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + if (this.zoomChanged || + this.updateLastPosition.distanceToSquared(this.object.position) > EPS || + 8 * (1 - this.updateLastQuaternion.dot(this.object.quaternion)) > EPS) { + this.dispatchEvent(CHANGE_EVENT); + this.updateLastPosition.copy(this.object.position); + this.updateLastQuaternion.copy(this.object.quaternion); + this.zoomChanged = false; + return true; + } + return false; + }; + OrbitControls.prototype.panLeft = function (distance, objectMatrix) { + this.panLeftV.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix + this.panLeftV.multiplyScalar(-distance); + this.panOffset.add(this.panLeftV); + }; + OrbitControls.prototype.panUp = function (distance, objectMatrix) { + this.panUpV.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix + this.panUpV.multiplyScalar(distance); + this.panOffset.add(this.panUpV); + }; + // deltaX and deltaY are in pixels; right and down are positive + OrbitControls.prototype.pan = function (deltaX, deltaY) { + var element = this.domElement === document ? this.domElement.body : this.domElement; + if (this.object instanceof THREE.PerspectiveCamera) { + // perspective + var position = this.object.position; + this.panInternalOffset.copy(position).sub(this.target); + var targetDistance = this.panInternalOffset.length(); + // half of the fov is center to top of screen + targetDistance *= Math.tan((this.object.fov / 2) * Math.PI / 180.0); + // we actually don"t use screenWidth, since perspective camera is fixed to screen height + this.panLeft(2 * deltaX * targetDistance / element.clientHeight, this.object.matrix); + this.panUp(2 * deltaY * targetDistance / element.clientHeight, this.object.matrix); + } + else if (this.object instanceof THREE.OrthographicCamera) { + // orthographic + this.panLeft(deltaX * (this.object.right - this.object.left) / this.object.zoom / element.clientWidth, this.object.matrix); + this.panUp(deltaY * (this.object.top - this.object.bottom) / this.object.zoom / element.clientHeight, this.object.matrix); + } + else { + // camera neither orthographic nor perspective + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."); + this.enablePan = false; + } + }; + OrbitControls.prototype.dollyIn = function (dollyScale) { + if (this.object instanceof THREE.PerspectiveCamera) { + this.scale /= dollyScale; + } + else if (this.object instanceof THREE.OrthographicCamera) { + this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom * dollyScale)); + this.object.updateProjectionMatrix(); + this.zoomChanged = true; + } + else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); + this.enableZoom = false; + } + }; + OrbitControls.prototype.dollyOut = function (dollyScale) { + if (this.object instanceof THREE.PerspectiveCamera) { + this.scale *= dollyScale; + } + else if (this.object instanceof THREE.OrthographicCamera) { + this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / dollyScale)); + this.object.updateProjectionMatrix(); + this.zoomChanged = true; + } + else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); + this.enableZoom = false; + } + }; + OrbitControls.prototype.getAutoRotationAngle = function () { + return 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }; + OrbitControls.prototype.getZoomScale = function () { + return Math.pow(0.95, this.zoomSpeed); + }; + OrbitControls.prototype.rotateLeft = function (angle) { + this.sphericalDelta.theta -= angle; + }; + OrbitControls.prototype.rotateUp = function (angle) { + this.sphericalDelta.phi -= angle; + }; + OrbitControls.prototype.getPolarAngle = function () { + return this.spherical.phi; + }; + OrbitControls.prototype.getAzimuthalAngle = function () { + return this.spherical.theta; + }; + OrbitControls.prototype.dispose = function () { + this.domElement.removeEventListener("contextmenu", this.onContextMenu, false); + this.domElement.removeEventListener("mousedown", this.onMouseDown, false); + this.domElement.removeEventListener("wheel", this.onMouseWheel, false); + this.domElement.removeEventListener("touchstart", this.onTouchStart, false); + this.domElement.removeEventListener("touchend", this.onTouchEnd, false); + this.domElement.removeEventListener("touchmove", this.onTouchMove, false); + document.removeEventListener("mousemove", this.onMouseMove, false); + document.removeEventListener("mouseup", this.onMouseUp, false); + this.window.removeEventListener("keydown", this.onKeyDown, false); + // this.dispatchEvent( { type: "dispose" } ); // should this be added here? + }; + OrbitControls.prototype.reset = function () { + this.target.copy(this.target0); + this.object.position.copy(this.position0); + this.object.zoom = this.zoom0; + this.object.updateProjectionMatrix(); + this.dispatchEvent(CHANGE_EVENT); + this.update(); + this.state = STATE.NONE; + }; + return OrbitControls; + }(THREE.EventDispatcher)); + function createOrbitControls(skinViewer) { + var control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement); + // default configuration + control.enablePan = false; + control.target = new THREE.Vector3(0, -12, 0); + control.minDistance = 10; + control.maxDistance = 256; + control.update(); + return control; + } + + exports.SkinObject = SkinObject; + exports.BodyPart = BodyPart; + exports.CapeObject = CapeObject; + exports.PlayerObject = PlayerObject; + exports.SkinViewer = SkinViewer; + exports.OrbitControls = OrbitControls; + exports.createOrbitControls = createOrbitControls; + exports.invokeAnimation = invokeAnimation; + exports.CompositeAnimation = CompositeAnimation; + exports.WalkingAnimation = WalkingAnimation; + exports.RunningAnimation = RunningAnimation; + exports.RotatingAnimation = RotatingAnimation; + exports.isSlimSkin = isSlimSkin; + + Object.defineProperty(exports, '__esModule', { value: true }); + +}))); diff --git a/js/dist/skinview3d.min.js b/js/dist/skinview3d.min.js new file mode 100644 index 0000000..452294a --- /dev/null +++ b/js/dist/skinview3d.min.js @@ -0,0 +1,7 @@ +/** + * skinview3d (https://github.com/bs-community/skinview3d) + * + * MIT License + */ + +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("three")):"function"==typeof define&&define.amd?define(["exports","three"],t):t(e.skinview3d={},e.THREE)}(this,function(e,U){"use strict";var a=function(e,t){return(a=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var n in t)t.hasOwnProperty(n)&&(e[n]=t[n])})(e,t)};function t(e,t){function n(){this.constructor=e}a(e,t),e.prototype=null===t?Object.create(t):(n.prototype=t.prototype,new n)}function i(e,t,n,a,i,o){return[new U.Vector2(e/i,1-a/o),new U.Vector2(n/i,1-a/o),new U.Vector2(n/i,1-t/o),new U.Vector2(e/i,1-t/o)]}function V(e,t,n,a){return i(e,t,n,a,64,64)}function o(e,t,n,a){return i(e,t,n,a,64,32)}function A(e,t,n,a,i,o,s){e.faceVertexUvs[0]=[],e.faceVertexUvs[0][0]=[o[3],o[0],o[2]],e.faceVertexUvs[0][1]=[o[0],o[1],o[2]],e.faceVertexUvs[0][2]=[a[3],a[0],a[2]],e.faceVertexUvs[0][3]=[a[0],a[1],a[2]],e.faceVertexUvs[0][4]=[t[3],t[0],t[2]],e.faceVertexUvs[0][5]=[t[0],t[1],t[2]],e.faceVertexUvs[0][6]=[n[0],n[3],n[1]],e.faceVertexUvs[0][7]=[n[3],n[2],n[1]],e.faceVertexUvs[0][8]=[i[3],i[0],i[2]],e.faceVertexUvs[0][9]=[i[0],i[1],i[2]],e.faceVertexUvs[0][10]=[s[3],s[0],s[2]],e.faceVertexUvs[0][11]=[s[0],s[1],s[2]]}var C=.002,z=function(a){function e(e,t){var n=a.call(this)||this;return n.innerLayer=e,n.outerLayer=t,n}return t(e,a),e}(U.Group),s=function(D){function e(e,t){var n=D.call(this)||this;n.modelListeners=[],n._slim=!1;var a=new U.BoxGeometry(8,8,8,0,0,0);A(a,V(8,0,16,8),V(16,0,24,8),V(0,8,8,16),V(8,8,16,16),V(16,8,24,16),V(24,8,32,16));var i=new U.Mesh(a,e),o=new U.BoxGeometry(9,9,9,0,0,0);A(o,V(40,0,48,8),V(48,0,56,8),V(32,8,40,16),V(40,8,48,16),V(48,8,56,16),V(56,8,64,16));var s=new U.Mesh(o,t);s.renderOrder=-1,n.head=new z(i,s),n.head.add(i,s),n.add(n.head);var r=new U.BoxGeometry(8,12,4,0,0,0);A(r,V(20,16,28,20),V(28,16,36,20),V(16,20,20,32),V(20,20,28,32),V(28,20,32,32),V(32,20,40,32));var h=new U.Mesh(r,e),c=new U.BoxGeometry(9,13.5,4.5,0,0,0);A(c,V(20,32,28,36),V(28,32,36,36),V(16,36,20,48),V(20,36,28,48),V(28,36,32,48),V(32,36,40,48));var d=new U.Mesh(c,t);n.body=new z(h,d),n.body.add(h,d),n.body.position.y=-10,n.add(n.body);var l=new U.BoxGeometry(1,1,1,0,0,0),p=new U.Mesh(l,e);n.modelListeners.push(function(){p.scale.x=(n.slim?3:4)-C,p.scale.y=12-C,p.scale.z=4-C,n.slim?A(l,V(44,16,47,20),V(47,16,50,20),V(40,20,44,32),V(44,20,47,32),V(47,20,51,32),V(51,20,54,32)):A(l,V(44,16,48,20),V(48,16,52,20),V(40,20,44,32),V(44,20,48,32),V(48,20,52,32),V(52,20,56,32)),l.uvsNeedUpdate=!0,l.elementsNeedUpdate=!0});var u=new U.BoxGeometry(1,1,1,0,0,0),m=new U.Mesh(u,t);m.renderOrder=1,n.modelListeners.push(function(){m.scale.x=(n.slim?3.375:4.5)-C,m.scale.y=13.498,m.scale.z=4.498,n.slim?A(u,V(44,32,47,36),V(47,32,50,36),V(40,36,44,48),V(44,36,47,48),V(47,36,51,48),V(51,36,54,48)):A(u,V(44,32,48,36),V(48,32,52,36),V(40,36,44,48),V(44,36,48,48),V(48,36,52,48),V(52,36,56,48)),u.uvsNeedUpdate=!0,u.elementsNeedUpdate=!0});var f=new U.Group;f.add(p,m),f.position.y=-6,n.rightArm=new z(p,m),n.rightArm.add(f),n.rightArm.position.y=-4,n.modelListeners.push(function(){n.rightArm.position.x=n.slim?-5.5:-6}),n.add(n.rightArm);var y=new U.BoxGeometry(1,1,1,0,0,0),g=new U.Mesh(y,e);n.modelListeners.push(function(){g.scale.x=(n.slim?3:4)-C,g.scale.y=12-C,g.scale.z=4-C,n.slim?A(y,V(36,48,39,52),V(39,48,42,52),V(32,52,36,64),V(36,52,39,64),V(39,52,43,64),V(43,52,46,64)):A(y,V(36,48,40,52),V(40,48,44,52),V(32,52,36,64),V(36,52,40,64),V(40,52,44,64),V(44,52,48,64)),y.uvsNeedUpdate=!0,y.elementsNeedUpdate=!0});var v=new U.BoxGeometry(1,1,1,0,0,0),w=new U.Mesh(v,t);w.renderOrder=1,n.modelListeners.push(function(){w.scale.x=(n.slim?3.375:4.5)-C,w.scale.y=13.498,w.scale.z=4.498,n.slim?A(v,V(52,48,55,52),V(55,48,58,52),V(48,52,52,64),V(52,52,55,64),V(55,52,59,64),V(59,52,62,64)):A(v,V(52,48,56,52),V(56,48,60,52),V(48,52,52,64),V(52,52,56,64),V(56,52,60,64),V(60,52,64,64)),v.uvsNeedUpdate=!0,v.elementsNeedUpdate=!0});var b=new U.Group;b.add(g,w),b.position.y=-6,n.leftArm=new z(g,w),n.leftArm.add(b),n.leftArm.position.y=-4,n.modelListeners.push(function(){n.leftArm.position.x=n.slim?5.5:6}),n.add(n.leftArm);var M=new U.BoxGeometry(4-C,12-C,4-C,0,0,0);A(M,V(4,16,8,20),V(8,16,12,20),V(0,20,4,32),V(4,20,8,32),V(8,20,12,32),V(12,20,16,32));var x=new U.Mesh(M,e),E=new U.BoxGeometry(4.498,13.498,4.498,0,0,0);A(E,V(4,32,8,36),V(8,32,12,36),V(0,36,4,48),V(4,36,8,48),V(8,36,12,48),V(12,36,16,48));var L=new U.Mesh(E,t);L.renderOrder=1;var S=new U.Group;S.add(x,L),S.position.y=-6,n.rightLeg=new z(x,L),n.rightLeg.add(S),n.rightLeg.position.y=-16,n.rightLeg.position.x=-2,n.add(n.rightLeg);var P=new U.BoxGeometry(4-C,12-C,4-C,0,0,0);A(P,V(20,48,24,52),V(24,48,28,52),V(16,52,20,64),V(20,52,24,64),V(24,52,28,64),V(28,52,32,64));var O=new U.Mesh(P,e),k=new U.BoxGeometry(4.498,13.498,4.498,0,0,0);A(k,V(4,48,8,52),V(8,48,12,52),V(0,52,4,64),V(4,52,8,64),V(8,52,12,64),V(12,52,16,64));var I=new U.Mesh(k,t);I.renderOrder=1;var j=new U.Group;return j.add(O,I),j.position.y=-6,n.leftLeg=new z(O,I),n.leftLeg.add(j),n.leftLeg.position.y=-16,n.leftLeg.position.x=2,n.add(n.leftLeg),n.slim=!1,n}return t(e,D),Object.defineProperty(e.prototype,"slim",{get:function(){return this._slim},set:function(e){this._slim=e,this.modelListeners.forEach(function(e){return e()})},enumerable:!0,configurable:!0}),e.prototype.getBodyParts=function(){return this.children.filter(function(e){return e instanceof z})},e.prototype.setInnerLayerVisible=function(t){this.getBodyParts().forEach(function(e){return e.innerLayer.visible=t})},e.prototype.setOuterLayerVisible=function(t){this.getBodyParts().forEach(function(e){return e.outerLayer.visible=t})},e}(U.Group),r=function(a){function e(e){var t=a.call(this)||this,n=new U.BoxGeometry(10,16,1,0,0,0);return A(n,o(1,0,11,1),o(11,0,21,1),o(11,1,12,17),o(12,1,22,17),o(0,1,1,17),o(1,1,11,17)),t.cape=new U.Mesh(n,e),t.cape.position.y=-8,t.cape.position.z=-.5,t.add(t.cape),t}return t(e,a),e}(U.Group),h=function(i){function e(e,t,n){var a=i.call(this)||this;return a.skin=new s(e,t),a.skin.visible=!1,a.add(a.skin),a.cape=new r(n),a.cape.position.z=-2,a.cape.position.y=-4,a.cape.rotation.x=25*Math.PI/180,a.cape.visible=!1,a.add(a.cape),a}return t(e,i),e}(U.Group);function c(e,t,n){e instanceof Function?e(t,n):e.play(t,n)}var d=function(){function e(e){this.paused=!1,this.speed=1,this._paused=!1,this._lastChange=null,this._speed=1,this._lastChangeX=null,this.animation=e}return e.prototype.play=function(e,t){if(null===this._lastChange)this._lastChange=t,this._lastChangeX=0;else if(this.paused!==this._paused||this.speed!==this._speed){var n=t-this._lastChange;!1===this._paused&&(this._lastChangeX+=n*this._speed),this._paused=this.paused,this._speed=this.speed,this._lastChange=t}if(!1===this.paused){n=t-this._lastChange;var a=this._lastChangeX+this.speed*n;c(this.animation,e,a)}},e.prototype.reset=function(){this._lastChange=null},e.prototype.remove=function(){},e}(),n=function(){function e(){this.handles=new Set}return e.prototype.add=function(e){var t=this,n=new d(e);return n.remove=function(){return t.handles.delete(n)},this.handles.add(n),n},e.prototype.play=function(t,n){this.handles.forEach(function(e){return e.play(t,n)})},e}();function l(e,t,n,a,i){for(var o=e.getImageData(t,n,a,i),s=0;s*-------*-------* + // (40,20) |top |bottom | + // \|/ |4x4 |4x4 | + // *-------*-------*-------*-------* + // |right |front |left |back | + // |4x12 |4x12 |4x12 |4x12 | + // *-------*-------*-------*-------* + // The right arm area of *slim* skins: + // (44,16)->*------*------*-* + // (40,20) |top |bottom| |<----[x0=50,y0=16,w=2,h=4] + // \|/ |3x4 |3x4 | | + // *-------*------*------***-----*-* + // |right |front |left |back | |<----[x0=54,y0=20,w=2,h=12] + // |4x12 |3x12 |4x12 |3x12 | | + // *-------*------*-------*------*-* + // Compared with default right arms, slim right arms have 2 unused areas. + // + // The same is true for left arm: + // The left arm area of *default* skins: + // (36,48)->*-------*-------* + // (32,52) |top |bottom | + // \|/ |4x4 |4x4 | + // *-------*-------*-------*-------* + // |right |front |left |back | + // |4x12 |4x12 |4x12 |4x12 | + // *-------*-------*-------*-------* + // The left arm area of *slim* skins: + // (36,48)->*------*------*-* + // (32,52) |top |bottom| |<----[x0=42,y0=48,w=2,h=4] + // \|/ |3x4 |3x4 | | + // *-------*------*------***-----*-* + // |right |front |left |back | |<----[x0=46,y0=52,w=2,h=12] + // |4x12 |3x12 |4x12 |3x12 | | + // *-------*------*-------*------*-* + // + // If there is a transparent pixel in any of the 4 unused areas, the skin must be slim, + // as transparent pixels are not allowed in the first layer. + if (canvasOrImage instanceof HTMLCanvasElement) { + var canvas = canvasOrImage; + var scale_2 = computeSkinScale(canvas.width); + var context_1 = canvas.getContext("2d"); + var checkArea = function (x, y, w, h) { return hasTransparency(context_1, x * scale_2, y * scale_2, w * scale_2, h * scale_2); }; + return checkArea(50, 16, 2, 4) || + checkArea(54, 20, 2, 12) || + checkArea(42, 48, 2, 4) || + checkArea(46, 52, 2, 12); + } + else { + var image = canvasOrImage; + var canvas = document.createElement("canvas"); + loadSkinToCanvas(canvas, image); + return isSlimSkin(canvas); + } +} + +var SkinViewer = /** @class */ (function () { + function SkinViewer(options) { + var _this = this; + this.detectModel = true; + this.animationPaused = false; + this.animationTime = 0; + this.disposed = false; + this.domElement = options.domElement; + this.animation = options.animation || null; + if (options.detectModel === false) { + this.detectModel = false; + } + // texture + this.skinImg = new Image(); + this.skinCanvas = document.createElement("canvas"); + this.skinTexture = new Texture(this.skinCanvas); + this.skinTexture.magFilter = NearestFilter; + this.skinTexture.minFilter = NearestFilter; + this.capeImg = new Image(); + this.capeCanvas = document.createElement("canvas"); + this.capeTexture = new Texture(this.capeCanvas); + this.capeTexture.magFilter = NearestFilter; + this.capeTexture.minFilter = NearestFilter; + this.layer1Material = new MeshBasicMaterial({ map: this.skinTexture, side: FrontSide }); + this.layer2Material = new MeshBasicMaterial({ map: this.skinTexture, transparent: true, opacity: 1, side: DoubleSide, alphaTest: 0.5 }); + this.capeMaterial = new MeshBasicMaterial({ map: this.capeTexture, transparent: true, opacity: 1, side: DoubleSide, alphaTest: 0.5 }); + // scene + this.scene = new Scene(); + // Use smaller fov to avoid distortion + this.camera = new PerspectiveCamera(40); + this.camera.position.y = -12; + this.camera.position.z = 60; + this.renderer = new WebGLRenderer({ alpha: true, antialias: false }); + this.renderer.setSize(300, 300); // default size + this.renderer.context.getShaderInfoLog = function () { return ""; }; // shut firefox up + this.domElement.appendChild(this.renderer.domElement); + this.playerObject = new PlayerObject(this.layer1Material, this.layer2Material, this.capeMaterial); + this.scene.add(this.playerObject); + // texture loading + this.skinImg.crossOrigin = "anonymous"; + this.skinImg.onerror = function () { return console.error("Failed loading " + _this.skinImg.src); }; + this.skinImg.onload = function () { + loadSkinToCanvas(_this.skinCanvas, _this.skinImg); + if (_this.detectModel) { + _this.playerObject.skin.slim = isSlimSkin(_this.skinCanvas); + } + _this.skinTexture.needsUpdate = true; + _this.layer1Material.needsUpdate = true; + _this.layer2Material.needsUpdate = true; + _this.playerObject.skin.visible = true; + }; + this.capeImg.crossOrigin = "anonymous"; + this.capeImg.onerror = function () { return console.error("Failed loading " + _this.capeImg.src); }; + this.capeImg.onload = function () { + loadCapeToCanvas(_this.capeCanvas, _this.capeImg); + _this.capeTexture.needsUpdate = true; + _this.capeMaterial.needsUpdate = true; + _this.playerObject.cape.visible = true; + }; + if (options.skinUrl) + this.skinUrl = options.skinUrl; + if (options.capeUrl) + this.capeUrl = options.capeUrl; + if (options.width) + this.width = options.width; + if (options.height) + this.height = options.height; + var draw = function () { + if (_this.disposed) + return; + window.requestAnimationFrame(draw); + if (!_this.animationPaused) { + _this.animationTime++; + if (_this.animation) { + invokeAnimation(_this.animation, _this.playerObject, _this.animationTime / 100.0); + } + } + _this.renderer.render(_this.scene, _this.camera); + }; + draw(); + } + SkinViewer.prototype.setSize = function (width, height) { + this.camera.aspect = width / height; + this.camera.updateProjectionMatrix(); + this.renderer.setSize(width, height); + }; + SkinViewer.prototype.dispose = function () { + this.disposed = true; + this.domElement.removeChild(this.renderer.domElement); + this.renderer.dispose(); + this.skinTexture.dispose(); + this.capeTexture.dispose(); + }; + Object.defineProperty(SkinViewer.prototype, "skinUrl", { + get: function () { + return this.skinImg.src; + }, + set: function (url) { + this.skinImg.src = url; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "capeUrl", { + get: function () { + return this.capeImg.src; + }, + set: function (url) { + this.capeImg.src = url; + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "width", { + get: function () { + return this.renderer.getSize().width; + }, + set: function (newWidth) { + this.setSize(newWidth, this.height); + }, + enumerable: true, + configurable: true + }); + Object.defineProperty(SkinViewer.prototype, "height", { + get: function () { + return this.renderer.getSize().height; + }, + set: function (newHeight) { + this.setSize(this.width, newHeight); + }, + enumerable: true, + configurable: true + }); + return SkinViewer; +}()); + +var STATE = { + NONE: -1, + ROTATE: 0, + DOLLY: 1, + PAN: 2, + TOUCH_ROTATE: 3, + TOUCH_DOLLY: 4, + TOUCH_PAN: 5 +}; +var CHANGE_EVENT = { type: "change" }; +var START_EVENT = { type: "start" }; +var END_EVENT = { type: "end" }; +var EPS = 0.000001; +var OrbitControls = /** @class */ (function (_super) { + __extends(OrbitControls, _super); + function OrbitControls(object, domElement, domWindow) { + var _this = _super.call(this) || this; + _this.object = object; + _this.domElement = (domElement !== undefined) ? domElement : document; + _this.window = (domWindow !== undefined) ? domWindow : window; + // Set to false to disable this control + _this.enabled = true; + // "target" sets the location of focus, where the object orbits around + _this.target = new Vector3(); + // How far you can dolly in and out ( PerspectiveCamera only ) + _this.minDistance = 0; + _this.maxDistance = Infinity; + // How far you can zoom in and out ( OrthographicCamera only ) + _this.minZoom = 0; + _this.maxZoom = Infinity; + // How far you can orbit vertically, upper and lower limits. + // Range is 0 to Math.PI radians. + _this.minPolarAngle = 0; // radians + _this.maxPolarAngle = Math.PI; // radians + // How far you can orbit horizontally, upper and lower limits. + // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. + _this.minAzimuthAngle = -Infinity; // radians + _this.maxAzimuthAngle = Infinity; // radians + // Set to true to enable damping (inertia) + // If damping is enabled, you must call controls.update() in your animation loop + _this.enableDamping = false; + _this.dampingFactor = 0.25; + // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. + // Set to false to disable zooming + _this.enableZoom = true; + _this.zoomSpeed = 1.0; + // Set to false to disable rotating + _this.enableRotate = true; + _this.rotateSpeed = 1.0; + // Set to false to disable panning + _this.enablePan = true; + _this.keyPanSpeed = 7.0; // pixels moved per arrow key push + // Set to true to automatically rotate around the target + // If auto-rotate is enabled, you must call controls.update() in your animation loop + _this.autoRotate = false; + _this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 + // Set to false to disable use of the keys + _this.enableKeys = true; + // The four arrow keys + _this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; + // Mouse buttons + _this.mouseButtons = { ORBIT: MOUSE.LEFT, ZOOM: MOUSE.MIDDLE, PAN: MOUSE.RIGHT }; + // for reset + _this.target0 = _this.target.clone(); + _this.position0 = _this.object.position.clone(); + _this.zoom0 = _this.object.zoom; + // for update speedup + _this.updateOffset = new Vector3(); + // so camera.up is the orbit axis + _this.updateQuat = new Quaternion().setFromUnitVectors(object.up, new Vector3(0, 1, 0)); + _this.updateQuatInverse = _this.updateQuat.clone().inverse(); + _this.updateLastPosition = new Vector3(); + _this.updateLastQuaternion = new Quaternion(); + _this.state = STATE.NONE; + _this.scale = 1; + // current position in spherical coordinates + _this.spherical = new Spherical(); + _this.sphericalDelta = new Spherical(); + _this.panOffset = new Vector3(); + _this.zoomChanged = false; + _this.rotateStart = new Vector2(); + _this.rotateEnd = new Vector2(); + _this.rotateDelta = new Vector2(); + _this.panStart = new Vector2(); + _this.panEnd = new Vector2(); + _this.panDelta = new Vector2(); + _this.dollyStart = new Vector2(); + _this.dollyEnd = new Vector2(); + _this.dollyDelta = new Vector2(); + _this.panLeftV = new Vector3(); + _this.panUpV = new Vector3(); + _this.panInternalOffset = new Vector3(); + // event handlers - FSM: listen for events and reset state + _this.onMouseDown = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + if (event.button === _this.mouseButtons.ORBIT) { + if (_this.enableRotate === false) + return; + _this.rotateStart.set(event.clientX, event.clientY); + _this.state = STATE.ROTATE; + } + else if (event.button === _this.mouseButtons.ZOOM) { + if (_this.enableZoom === false) + return; + _this.dollyStart.set(event.clientX, event.clientY); + _this.state = STATE.DOLLY; + } + else if (event.button === _this.mouseButtons.PAN) { + if (_this.enablePan === false) + return; + _this.panStart.set(event.clientX, event.clientY); + _this.state = STATE.PAN; + } + if (_this.state !== STATE.NONE) { + document.addEventListener("mousemove", _this.onMouseMove, false); + document.addEventListener("mouseup", _this.onMouseUp, false); + _this.dispatchEvent(START_EVENT); + } + }; + _this.onMouseMove = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + if (_this.state === STATE.ROTATE) { + if (_this.enableRotate === false) + return; + _this.rotateEnd.set(event.clientX, event.clientY); + _this.rotateDelta.subVectors(_this.rotateEnd, _this.rotateStart); + var element = _this.domElement === document ? _this.domElement.body : _this.domElement; + // rotating across whole screen goes 360 degrees around + _this.rotateLeft(2 * Math.PI * _this.rotateDelta.x / element.clientWidth * _this.rotateSpeed); + // rotating up and down along whole screen attempts to go 360, but limited to 180 + _this.rotateUp(2 * Math.PI * _this.rotateDelta.y / element.clientHeight * _this.rotateSpeed); + _this.rotateStart.copy(_this.rotateEnd); + _this.update(); + } + else if (_this.state === STATE.DOLLY) { + if (_this.enableZoom === false) + return; + _this.dollyEnd.set(event.clientX, event.clientY); + _this.dollyDelta.subVectors(_this.dollyEnd, _this.dollyStart); + if (_this.dollyDelta.y > 0) { + _this.dollyIn(_this.getZoomScale()); + } + else if (_this.dollyDelta.y < 0) { + _this.dollyOut(_this.getZoomScale()); + } + _this.dollyStart.copy(_this.dollyEnd); + _this.update(); + } + else if (_this.state === STATE.PAN) { + if (_this.enablePan === false) + return; + _this.panEnd.set(event.clientX, event.clientY); + _this.panDelta.subVectors(_this.panEnd, _this.panStart); + _this.pan(_this.panDelta.x, _this.panDelta.y); + _this.panStart.copy(_this.panEnd); + _this.update(); + } + }; + _this.onMouseUp = function (event) { + if (_this.enabled === false) + return; + document.removeEventListener("mousemove", _this.onMouseMove, false); + document.removeEventListener("mouseup", _this.onMouseUp, false); + _this.dispatchEvent(END_EVENT); + _this.state = STATE.NONE; + }; + _this.onMouseWheel = function (event) { + if (_this.enabled === false || _this.enableZoom === false || (_this.state !== STATE.NONE && _this.state !== STATE.ROTATE)) + return; + event.preventDefault(); + event.stopPropagation(); + if (event.deltaY < 0) { + _this.dollyOut(_this.getZoomScale()); + } + else if (event.deltaY > 0) { + _this.dollyIn(_this.getZoomScale()); + } + _this.update(); + _this.dispatchEvent(START_EVENT); // not sure why these are here... + _this.dispatchEvent(END_EVENT); + }; + _this.onKeyDown = function (event) { + if (_this.enabled === false || _this.enableKeys === false || _this.enablePan === false) + return; + switch (event.keyCode) { + case _this.keys.UP: { + _this.pan(0, _this.keyPanSpeed); + _this.update(); + break; + } + case _this.keys.BOTTOM: { + _this.pan(0, -_this.keyPanSpeed); + _this.update(); + break; + } + case _this.keys.LEFT: { + _this.pan(_this.keyPanSpeed, 0); + _this.update(); + break; + } + case _this.keys.RIGHT: { + _this.pan(-_this.keyPanSpeed, 0); + _this.update(); + break; + } + } + }; + _this.onTouchStart = function (event) { + if (_this.enabled === false) + return; + switch (event.touches.length) { + // one-fingered touch: rotate + case 1: { + if (_this.enableRotate === false) + return; + _this.rotateStart.set(event.touches[0].pageX, event.touches[0].pageY); + _this.state = STATE.TOUCH_ROTATE; + break; + } + // two-fingered touch: dolly + case 2: { + if (_this.enableZoom === false) + return; + var dx = event.touches[0].pageX - event.touches[1].pageX; + var dy = event.touches[0].pageY - event.touches[1].pageY; + var distance = Math.sqrt(dx * dx + dy * dy); + _this.dollyStart.set(0, distance); + _this.state = STATE.TOUCH_DOLLY; + break; + } + // three-fingered touch: pan + case 3: { + if (_this.enablePan === false) + return; + _this.panStart.set(event.touches[0].pageX, event.touches[0].pageY); + _this.state = STATE.TOUCH_PAN; + break; + } + default: { + _this.state = STATE.NONE; + } + } + if (_this.state !== STATE.NONE) { + _this.dispatchEvent(START_EVENT); + } + }; + _this.onTouchMove = function (event) { + if (_this.enabled === false) + return; + event.preventDefault(); + event.stopPropagation(); + switch (event.touches.length) { + // one-fingered touch: rotate + case 1: { + if (_this.enableRotate === false) + return; + if (_this.state !== STATE.TOUCH_ROTATE) + return; // is this needed?... + _this.rotateEnd.set(event.touches[0].pageX, event.touches[0].pageY); + _this.rotateDelta.subVectors(_this.rotateEnd, _this.rotateStart); + var element = _this.domElement === document ? _this.domElement.body : _this.domElement; + // rotating across whole screen goes 360 degrees around + _this.rotateLeft(2 * Math.PI * _this.rotateDelta.x / element.clientWidth * _this.rotateSpeed); + // rotating up and down along whole screen attempts to go 360, but limited to 180 + _this.rotateUp(2 * Math.PI * _this.rotateDelta.y / element.clientHeight * _this.rotateSpeed); + _this.rotateStart.copy(_this.rotateEnd); + _this.update(); + break; + } + // two-fingered touch: dolly + case 2: { + if (_this.enableZoom === false) + return; + if (_this.state !== STATE.TOUCH_DOLLY) + return; // is this needed?... + // console.log( "handleTouchMoveDolly" ); + var dx = event.touches[0].pageX - event.touches[1].pageX; + var dy = event.touches[0].pageY - event.touches[1].pageY; + var distance = Math.sqrt(dx * dx + dy * dy); + _this.dollyEnd.set(0, distance); + _this.dollyDelta.subVectors(_this.dollyEnd, _this.dollyStart); + if (_this.dollyDelta.y > 0) { + _this.dollyOut(_this.getZoomScale()); + } + else if (_this.dollyDelta.y < 0) { + _this.dollyIn(_this.getZoomScale()); + } + _this.dollyStart.copy(_this.dollyEnd); + _this.update(); + break; + } + // three-fingered touch: pan + case 3: { + if (_this.enablePan === false) + return; + if (_this.state !== STATE.TOUCH_PAN) + return; // is this needed?... + _this.panEnd.set(event.touches[0].pageX, event.touches[0].pageY); + _this.panDelta.subVectors(_this.panEnd, _this.panStart); + _this.pan(_this.panDelta.x, _this.panDelta.y); + _this.panStart.copy(_this.panEnd); + _this.update(); + break; + } + default: { + _this.state = STATE.NONE; + } + } + }; + _this.onTouchEnd = function (event) { + if (_this.enabled === false) + return; + _this.dispatchEvent(END_EVENT); + _this.state = STATE.NONE; + }; + _this.onContextMenu = function (event) { + event.preventDefault(); + }; + _this.domElement.addEventListener("contextmenu", _this.onContextMenu, false); + _this.domElement.addEventListener("mousedown", _this.onMouseDown, false); + _this.domElement.addEventListener("wheel", _this.onMouseWheel, false); + _this.domElement.addEventListener("touchstart", _this.onTouchStart, false); + _this.domElement.addEventListener("touchend", _this.onTouchEnd, false); + _this.domElement.addEventListener("touchmove", _this.onTouchMove, false); + _this.window.addEventListener("keydown", _this.onKeyDown, false); + // force an update at start + _this.update(); + return _this; + } + OrbitControls.prototype.update = function () { + var position = this.object.position; + this.updateOffset.copy(position).sub(this.target); + // rotate offset to "y-axis-is-up" space + this.updateOffset.applyQuaternion(this.updateQuat); + // angle from z-axis around y-axis + this.spherical.setFromVector3(this.updateOffset); + if (this.autoRotate && this.state === STATE.NONE) { + this.rotateLeft(this.getAutoRotationAngle()); + } + this.spherical.theta += this.sphericalDelta.theta; + this.spherical.phi += this.sphericalDelta.phi; + // restrict theta to be between desired limits + this.spherical.theta = Math.max(this.minAzimuthAngle, Math.min(this.maxAzimuthAngle, this.spherical.theta)); + // restrict phi to be between desired limits + this.spherical.phi = Math.max(this.minPolarAngle, Math.min(this.maxPolarAngle, this.spherical.phi)); + this.spherical.makeSafe(); + this.spherical.radius *= this.scale; + // restrict radius to be between desired limits + this.spherical.radius = Math.max(this.minDistance, Math.min(this.maxDistance, this.spherical.radius)); + // move target to panned location + this.target.add(this.panOffset); + this.updateOffset.setFromSpherical(this.spherical); + // rotate offset back to "camera-up-vector-is-up" space + this.updateOffset.applyQuaternion(this.updateQuatInverse); + position.copy(this.target).add(this.updateOffset); + this.object.lookAt(this.target); + if (this.enableDamping === true) { + this.sphericalDelta.theta *= (1 - this.dampingFactor); + this.sphericalDelta.phi *= (1 - this.dampingFactor); + } + else { + this.sphericalDelta.set(0, 0, 0); + } + this.scale = 1; + this.panOffset.set(0, 0, 0); + // update condition is: + // min(camera displacement, camera rotation in radians)^2 > EPS + // using small-angle approximation cos(x/2) = 1 - x^2 / 8 + if (this.zoomChanged || + this.updateLastPosition.distanceToSquared(this.object.position) > EPS || + 8 * (1 - this.updateLastQuaternion.dot(this.object.quaternion)) > EPS) { + this.dispatchEvent(CHANGE_EVENT); + this.updateLastPosition.copy(this.object.position); + this.updateLastQuaternion.copy(this.object.quaternion); + this.zoomChanged = false; + return true; + } + return false; + }; + OrbitControls.prototype.panLeft = function (distance, objectMatrix) { + this.panLeftV.setFromMatrixColumn(objectMatrix, 0); // get X column of objectMatrix + this.panLeftV.multiplyScalar(-distance); + this.panOffset.add(this.panLeftV); + }; + OrbitControls.prototype.panUp = function (distance, objectMatrix) { + this.panUpV.setFromMatrixColumn(objectMatrix, 1); // get Y column of objectMatrix + this.panUpV.multiplyScalar(distance); + this.panOffset.add(this.panUpV); + }; + // deltaX and deltaY are in pixels; right and down are positive + OrbitControls.prototype.pan = function (deltaX, deltaY) { + var element = this.domElement === document ? this.domElement.body : this.domElement; + if (this.object instanceof PerspectiveCamera) { + // perspective + var position = this.object.position; + this.panInternalOffset.copy(position).sub(this.target); + var targetDistance = this.panInternalOffset.length(); + // half of the fov is center to top of screen + targetDistance *= Math.tan((this.object.fov / 2) * Math.PI / 180.0); + // we actually don"t use screenWidth, since perspective camera is fixed to screen height + this.panLeft(2 * deltaX * targetDistance / element.clientHeight, this.object.matrix); + this.panUp(2 * deltaY * targetDistance / element.clientHeight, this.object.matrix); + } + else if (this.object instanceof OrthographicCamera) { + // orthographic + this.panLeft(deltaX * (this.object.right - this.object.left) / this.object.zoom / element.clientWidth, this.object.matrix); + this.panUp(deltaY * (this.object.top - this.object.bottom) / this.object.zoom / element.clientHeight, this.object.matrix); + } + else { + // camera neither orthographic nor perspective + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - pan disabled."); + this.enablePan = false; + } + }; + OrbitControls.prototype.dollyIn = function (dollyScale) { + if (this.object instanceof PerspectiveCamera) { + this.scale /= dollyScale; + } + else if (this.object instanceof OrthographicCamera) { + this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom * dollyScale)); + this.object.updateProjectionMatrix(); + this.zoomChanged = true; + } + else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); + this.enableZoom = false; + } + }; + OrbitControls.prototype.dollyOut = function (dollyScale) { + if (this.object instanceof PerspectiveCamera) { + this.scale *= dollyScale; + } + else if (this.object instanceof OrthographicCamera) { + this.object.zoom = Math.max(this.minZoom, Math.min(this.maxZoom, this.object.zoom / dollyScale)); + this.object.updateProjectionMatrix(); + this.zoomChanged = true; + } + else { + console.warn("WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled."); + this.enableZoom = false; + } + }; + OrbitControls.prototype.getAutoRotationAngle = function () { + return 2 * Math.PI / 60 / 60 * this.autoRotateSpeed; + }; + OrbitControls.prototype.getZoomScale = function () { + return Math.pow(0.95, this.zoomSpeed); + }; + OrbitControls.prototype.rotateLeft = function (angle) { + this.sphericalDelta.theta -= angle; + }; + OrbitControls.prototype.rotateUp = function (angle) { + this.sphericalDelta.phi -= angle; + }; + OrbitControls.prototype.getPolarAngle = function () { + return this.spherical.phi; + }; + OrbitControls.prototype.getAzimuthalAngle = function () { + return this.spherical.theta; + }; + OrbitControls.prototype.dispose = function () { + this.domElement.removeEventListener("contextmenu", this.onContextMenu, false); + this.domElement.removeEventListener("mousedown", this.onMouseDown, false); + this.domElement.removeEventListener("wheel", this.onMouseWheel, false); + this.domElement.removeEventListener("touchstart", this.onTouchStart, false); + this.domElement.removeEventListener("touchend", this.onTouchEnd, false); + this.domElement.removeEventListener("touchmove", this.onTouchMove, false); + document.removeEventListener("mousemove", this.onMouseMove, false); + document.removeEventListener("mouseup", this.onMouseUp, false); + this.window.removeEventListener("keydown", this.onKeyDown, false); + // this.dispatchEvent( { type: "dispose" } ); // should this be added here? + }; + OrbitControls.prototype.reset = function () { + this.target.copy(this.target0); + this.object.position.copy(this.position0); + this.object.zoom = this.zoom0; + this.object.updateProjectionMatrix(); + this.dispatchEvent(CHANGE_EVENT); + this.update(); + this.state = STATE.NONE; + }; + return OrbitControls; +}(EventDispatcher)); +function createOrbitControls(skinViewer) { + var control = new OrbitControls(skinViewer.camera, skinViewer.renderer.domElement); + // default configuration + control.enablePan = false; + control.target = new Vector3(0, -12, 0); + control.minDistance = 10; + control.maxDistance = 256; + control.update(); + return control; +} + +export { SkinObject, BodyPart, CapeObject, PlayerObject, SkinViewer, OrbitControls, createOrbitControls, invokeAnimation, CompositeAnimation, WalkingAnimation, RunningAnimation, RotatingAnimation, isSlimSkin }; diff --git a/js/dist/utils.d.ts b/js/dist/utils.d.ts new file mode 100644 index 0000000..fddaf88 --- /dev/null +++ b/js/dist/utils.d.ts @@ -0,0 +1,3 @@ +export declare function loadSkinToCanvas(canvas: HTMLCanvasElement, image: HTMLImageElement): void; +export declare function loadCapeToCanvas(canvas: HTMLCanvasElement, image: HTMLImageElement): void; +export declare function isSlimSkin(canvasOrImage: HTMLCanvasElement | HTMLImageElement): boolean; diff --git a/js/dist/viewer.d.ts b/js/dist/viewer.d.ts new file mode 100644 index 0000000..6a89653 --- /dev/null +++ b/js/dist/viewer.d.ts @@ -0,0 +1,39 @@ +import * as THREE from "three"; +import { PlayerObject } from "./model"; +export interface SkinViewerOptions { + domElement: Node; + animation?: Animation; + skinUrl?: string; + capeUrl?: string; + width?: number; + height?: number; + detectModel?: boolean; +} +export declare class SkinViewer { + readonly domElement: Node; + animation: Animation | null; + detectModel: boolean; + animationPaused: boolean; + animationTime: number; + disposed: boolean; + readonly skinImg: HTMLImageElement; + readonly skinCanvas: HTMLCanvasElement; + readonly skinTexture: THREE.Texture; + readonly capeImg: HTMLImageElement; + readonly capeCanvas: HTMLCanvasElement; + readonly capeTexture: THREE.Texture; + readonly layer1Material: THREE.MeshBasicMaterial; + readonly layer2Material: THREE.MeshBasicMaterial; + readonly capeMaterial: THREE.MeshBasicMaterial; + readonly scene: THREE.Scene; + readonly camera: THREE.PerspectiveCamera; + readonly renderer: THREE.WebGLRenderer; + readonly playerObject: PlayerObject; + constructor(options: SkinViewerOptions); + setSize(width: any, height: any): void; + dispose(): void; + skinUrl: string; + capeUrl: string; + width: number; + height: number; +} diff --git a/js/example.js b/js/example.js index ea135d1..30d05eb 100644 --- a/js/example.js +++ b/js/example.js @@ -2,85 +2,121 @@ var skinViewer, control, handles = {}, globalAnimationSpeed = 1; +var skinParts = {} + function el(id) { - return document.getElementById(id); + return document.getElementById(id); } function initSkinViewer() { - if (skinViewer instanceof skinview3d.SkinViewer) { - skinViewer.dispose(); - handles = {}; - control = undefined; - } + if (skinViewer instanceof skinview3d.SkinViewer) { + skinViewer.dispose(); + handles = {}; + control = undefined; + } - // Reset animation speed - el('speed').value = globalAnimationSpeed = 1; + // Reset animation speed + el('speed').value = globalAnimationSpeed = 1; - skinViewer = new skinview3d.SkinViewer({ - domElement: el("skin_container"), - width: el('width').value, - height: el('height').value, - skinUrl: el('skin_url').value, - capeUrl: el('cape_url').value - }); + skinViewer = new skinview3d.SkinViewer({ + domElement: el("skin_container"), + width: el('width').value, + height: el('height').value, + skinUrl: el('skin_url').value, + capeUrl: el('cape_url').value || null + }); - skinViewer.camera.position.z = 70; - skinViewer.animation = new skinview3d.CompositeAnimation(); + skinViewer.camera.position.z = 70; + skinViewer.animation = new skinview3d.CompositeAnimation(); + + control = skinview3d.createOrbitControls(skinViewer); + + var parts = skinViewer.playerObject.skin; + + // set inner parts + skinParts.head = parts.head.innerLayer; + skinParts.body = parts.body.innerLayer; + skinParts.leftArm = parts.leftArm.innerLayer; + skinParts.rightArm = parts.rightArm.innerLayer; + skinParts.leftLeg = parts.leftLeg.innerLayer; + skinParts.rightLeg = parts.rightLeg.innerLayer; + + // set outter parts + skinParts.head2 = parts.head.outerLayer; + skinParts.body2 = parts.body.outerLayer; + skinParts.leftArm2 = parts.leftArm.outerLayer; + skinParts.rightArm2 = parts.rightArm.outerLayer; + skinParts.leftLeg2 = parts.leftLeg.outerLayer; + skinParts.rightLeg2 = parts.rightLeg.outerLayer; - control = skinview3d.createOrbitControls(skinViewer); } function hotReloadTextures() { - skinViewer.skinUrl = el('skin_url').value; - skinViewer.capeUrl = el('cape_url').value; + var capeObject = skinViewer.playerObject.cape; + var cape = el('cape_url').value; + var skin = el('skin_url').value; + + // I've noted there is not a good way to set the cape to null + // so we hide it as work around + if (cape === "") { + capeObject.visible = false; + return; + } + + skinViewer.skinUrl = skin; + skinViewer.capeUrl = cape; } function resizeSkinViewer() { - skinViewer.width = el('width').value; - skinViewer.height = el('height').value; + skinViewer.width = el('width').value; + skinViewer.height = el('height').value; } function pause() { - skinViewer.animationPaused = !skinViewer.animationPaused; + skinViewer.animationPaused = !skinViewer.animationPaused; } function walk() { - if (handles.run) { - handles.run.remove(); - delete handles.run; - } + if (handles.run) { + handles.run.remove(); + delete handles.run; + } - handles.walk = handles.walk || skinViewer.animation.add(skinview3d.WalkingAnimation); - handles.walk.speed = globalAnimationSpeed; + handles.walk = handles.walk || skinViewer.animation.add(skinview3d.WalkingAnimation); + handles.walk.speed = globalAnimationSpeed; } function run() { - if (handles.walk) { - handles.walk.remove(); - delete handles.walk; - } + if (handles.walk) { + handles.walk.remove(); + delete handles.walk; + } - handles.run = handles.run || skinViewer.animation.add(skinview3d.RunningAnimation); - handles.run.speed = globalAnimationSpeed; + handles.run = handles.run || skinViewer.animation.add(skinview3d.RunningAnimation); + handles.run.speed = globalAnimationSpeed; } function rotate() { - if (handles.rotate) { - handles.rotate.paused = !handles.rotate.paused; - } else { - handles.rotate = skinViewer.animation.add(skinview3d.RotatingAnimation); - handles.rotate.speed = globalAnimationSpeed; - } + if (handles.rotate) { + handles.rotate.paused = !handles.rotate.paused; + } else { + handles.rotate = skinViewer.animation.add(skinview3d.RotatingAnimation); + handles.rotate.speed = globalAnimationSpeed; + } +} + +function togglePart(partName) { + skinParts[partName].visible = !skinParts[partName].visible; } function setGlobalAnimationSpeed() { - var currentSpeed = el('speed').value; + var currentSpeed = el('speed').value; - if (! isNaN(currentSpeed)) { - globalAnimationSpeed = currentSpeed; + if (!isNaN(currentSpeed)) { + globalAnimationSpeed = currentSpeed; - for (var key in handles) { - handles[key].speed = currentSpeed; - } - } + for (var key in handles) { + handles[key].speed = currentSpeed; + } + } } diff --git a/update-codebase.sh b/update-codebase.sh index aab1bfd..21c2eab 100755 --- a/update-codebase.sh +++ b/update-codebase.sh @@ -6,7 +6,7 @@ if [ ! -d ".git" ];then fi checkout_dir="_ignore/master" -output_dir="js/build" +output_dir="js/dist" revision_file="$output_dir/revision" if [ -f "$revision_file" ];then @@ -27,10 +27,11 @@ cd -- $checkout_dir echo "> Building" npm install +npm run build echo "> Copying build outputs" cd -- $original_dir rm -rf -- $output_dir -cp -r -- "$checkout_dir/build" $output_dir +cp -r -- "$checkout_dir/dist" $output_dir echo "$master_revision" > $revision_file echo "> New revison of build outputs: $master_revision"