Replace three.msp.js with skinview3d
This commit is contained in:
parent
2d43a05a54
commit
0bb3ef55b3
|
|
@ -120,7 +120,11 @@ gulp.task('publish-vendor', ['compile-es6'], callback => {
|
|||
gulp.src('node_modules/admin-lte/dist/css/skins/*.min.css')
|
||||
.pipe(gulp.dest(`${distPath}/css/skins/`));
|
||||
// 3D skin preview
|
||||
gulp.src(['skin-preview/**', 'Chart.min.js'].map(path => `${srcPath}/vendor/${path}`))
|
||||
gulp.src(convertNpmRelativePath(['three/build/three.min.js', 'skinview3d/build/skinview3d.min.js']))
|
||||
.pipe(concat('skinview3d.js'))
|
||||
.pipe(gulp.dest(`${distPath}/js/`));
|
||||
// TODO: remove this
|
||||
gulp.src(['Chart.min.js'].map(path => `${srcPath}/vendor/${path}`))
|
||||
.pipe(gulp.dest(`${distPath}/js/`));
|
||||
|
||||
callback();
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@
|
|||
"jqPaginator": "^1.2.0",
|
||||
"jquery": "^3.3.1",
|
||||
"regenerator": "^0.12.3",
|
||||
"skinview3d": "^1.1.0-alpha.2",
|
||||
"sweetalert2": "^6.11.5",
|
||||
"toastr": "^2.1.4"
|
||||
},
|
||||
|
|
|
|||
57
resources/assets/src/js/common/skinview3d.js
Normal file
57
resources/assets/src/js/common/skinview3d.js
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/* global skinview3d */
|
||||
|
||||
$.msp = {};
|
||||
$.msp.handles = {};
|
||||
$.msp.control = null;
|
||||
$.msp.config = {
|
||||
domElement: document.getElementById('skin_container'),
|
||||
slim: false,
|
||||
width: $('#skin_container').width(),
|
||||
height: $('#skin_container').height(),
|
||||
skinUrl: '',
|
||||
capeUrl: ''
|
||||
};
|
||||
|
||||
function initSkinViewer(cameraPositionZ = 70) {
|
||||
disposeSkinViewer();
|
||||
|
||||
$.msp.viewer = new skinview3d.SkinViewer($.msp.config);
|
||||
$.msp.viewer.camera.position.z = cameraPositionZ;
|
||||
|
||||
$.msp.viewer.animation = new skinview3d.CompositeAnimation();
|
||||
|
||||
// Init all available animations and pause them
|
||||
$.msp.handles.walk = $.msp.viewer.animation.add(skinview3d.WalkingAnimation);
|
||||
$.msp.handles.run = $.msp.viewer.animation.add(skinview3d.RunningAnimation);
|
||||
$.msp.handles.rotate = $.msp.viewer.animation.add(skinview3d.RotatingAnimation);
|
||||
$.msp.handles.walk.paused = $.msp.handles.run.paused = $.msp.handles.rotate.paused = true;
|
||||
|
||||
$.msp.control = skinview3d.createOrbitControls($.msp.viewer);
|
||||
}
|
||||
|
||||
function disposeSkinViewer() {
|
||||
if ($.msp.viewer instanceof skinview3d.SkinViewer) {
|
||||
$.msp.viewer.dispose();
|
||||
$.msp.handles = {};
|
||||
$.msp.control = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function initAnimationControllers() {
|
||||
$('.fa-pause').click(function () {
|
||||
$.msp.viewer.animationPaused = !$.msp.viewer.animationPaused;
|
||||
$(this).toggleClass('fa-pause').toggleClass('fa-play');
|
||||
});
|
||||
|
||||
$('.fa-forward').click(function () {
|
||||
$.msp.handles.run.paused = !$.msp.handles.run.paused;
|
||||
$.msp.handles.walk.paused = !$.msp.handles.run.paused;
|
||||
});
|
||||
|
||||
$('.fa-repeat').click(() => ($.msp.handles.rotate.paused = !$.msp.handles.rotate.paused));
|
||||
$('.fa-stop').click(() => initSkinViewer());
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
module.exports = { initSkinViewer, initAnimationControllers };
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
/* global MSP */
|
||||
|
||||
class TexturePreview {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {'steve'|'alex'|'cape'} type
|
||||
* @param {number} tid
|
||||
* @param {'default'|'slim'} preference
|
||||
*/
|
||||
constructor(type, tid, preference) {
|
||||
this.tid = tid;
|
||||
this.type = type;
|
||||
/**
|
||||
* @type {JQuery<HTMLImageElement>}
|
||||
*/
|
||||
this.selector = $(`#${type}`);
|
||||
/**
|
||||
* @type {'default'|'slim'}
|
||||
*/
|
||||
this.preference = (type === 'steve') ? 'default' : 'slim';
|
||||
this.playerPreference = preference;
|
||||
}
|
||||
|
||||
change2dPreview() {
|
||||
this.selector
|
||||
.attr('src', url(`preview/200/${this.tid}.png`))
|
||||
.show()
|
||||
.parent().attr('href', url(`skinlib/show/${this.tid}`))
|
||||
.next().hide();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
async change3dPreview() {
|
||||
if (this.playerPreference === this.preference || this.type === 'cape') {
|
||||
try {
|
||||
const { hash } = await fetch({
|
||||
type: 'GET',
|
||||
url: url(`skinlib/info/${this.tid}`),
|
||||
dataType: 'json'
|
||||
});
|
||||
|
||||
const textureUrl = url(`textures/${hash}`);
|
||||
|
||||
if (this.type === 'cape') {
|
||||
MSP.changeCape(textureUrl);
|
||||
} else {
|
||||
MSP.changeSkin(textureUrl);
|
||||
}
|
||||
} catch (error) {
|
||||
showAjaxError(error);
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
showNotUploaded() {
|
||||
this.selector.hide().parent().next().show();
|
||||
|
||||
// clear 3D preview of cape
|
||||
if (this.type === 'cape') {
|
||||
MSP.changeCape('');
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static init3dPreview() {
|
||||
if (TexturePreview.previewType === '2D') return;
|
||||
|
||||
$('#preview-2d').hide();
|
||||
|
||||
let canvas = null;
|
||||
|
||||
if ($(window).width() < 800) {
|
||||
canvas = MSP.get3dSkinCanvas($('#skinpreview').width(), $('#skinpreview').width());
|
||||
$('#skinpreview').append($(canvas).prop('id', 'canvas3d'));
|
||||
} else {
|
||||
canvas = MSP.get3dSkinCanvas(350, 350);
|
||||
$('#skinpreview').append($(canvas).prop('id', 'canvas3d'));
|
||||
}
|
||||
}
|
||||
|
||||
static show3dPreview() {
|
||||
TexturePreview.previewType = '3D';
|
||||
|
||||
TexturePreview.init3dPreview();
|
||||
$('#preview-2d').hide();
|
||||
$('.operations').show();
|
||||
$('#preview-switch').html(trans('user.switch2dPreview'));
|
||||
}
|
||||
|
||||
static show2dPreview() {
|
||||
TexturePreview.previewType = '2D';
|
||||
|
||||
$('#canvas3d').remove();
|
||||
$('.operations').hide();
|
||||
$('#preview-2d').show();
|
||||
$('#preview-switch').html(trans('user.switch3dPreview')).attr('onclick', 'show3dPreview();');
|
||||
}
|
||||
}
|
||||
|
||||
TexturePreview.previewType = '3D';
|
||||
|
||||
// change 3D preview status
|
||||
$('.fa-pause').click(function () {
|
||||
MSP.setStatus('rotation', ! MSP.getStatus('rotation'));
|
||||
MSP.setStatus('movements', ! MSP.getStatus('movements'));
|
||||
|
||||
$(this).toggleClass('fa-pause').toggleClass('fa-play');
|
||||
});
|
||||
|
||||
$('.fa-forward').click(() => MSP.setStatus('running', ! MSP.getStatus('running')));
|
||||
$('.fa-repeat' ).click(() => MSP.setStatus('rotation', ! MSP.getStatus('rotation')));
|
||||
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
module.exports = TexturePreview;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,674 +0,0 @@
|
|||
/* Created by djazz
|
||||
* http://djazz.mine.nu/
|
||||
* @daniel_hede on Twitter
|
||||
* daniel_hede in Minecraft
|
||||
*
|
||||
* https://github.com/daniel-j/chrome-minecraft-skin-preview/blob/master/skin.js
|
||||
*
|
||||
* Editted by printempw
|
||||
* https://prinzeugen.net
|
||||
* Added support for high-resolution skin & capes,
|
||||
* also added external interfaces
|
||||
*/
|
||||
|
||||
var MSP = (function (global, undefined) {
|
||||
'use strict';
|
||||
// shim layer with setTimeout fallback
|
||||
window.requestAnimFrame = (function(){
|
||||
return window.requestAnimationFrame ||
|
||||
window.webkitRequestAnimationFrame ||
|
||||
window.mozRequestAnimationFrame ||
|
||||
window.oRequestAnimationFrame ||
|
||||
window.msRequestAnimationFrame ||
|
||||
function(/* function */ callback, /* DOMElement */ element) {
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
})();
|
||||
|
||||
var supportWebGL = !!global.WebGLRenderingContext && (!!global.document.createElement('canvas').getContext('experimental-webgl') || !!global.document.createElement('canvas').getContext('webgl'));
|
||||
|
||||
var container = global.document.querySelector('#skinpreview');
|
||||
|
||||
// Width and height
|
||||
var cw = 300, ch = 300;
|
||||
var tileUvWidth = 1/64;
|
||||
var tileUvHeight = 1/32;
|
||||
|
||||
// Init <canvas>
|
||||
var skinBig = global.document.createElement('canvas');
|
||||
var sbc = skinBig.getContext('2d');
|
||||
var sizeRatio = 8;
|
||||
skinBig.width = 64*sizeRatio;
|
||||
skinBig.height = 32*sizeRatio;
|
||||
|
||||
var skincanvas = global.document.createElement('canvas');
|
||||
var skinc = skincanvas.getContext('2d');
|
||||
skincanvas.width = 64;
|
||||
skincanvas.height = 32;
|
||||
var capecanvas = global.document.createElement('canvas');
|
||||
var capec = capecanvas.getContext('2d');
|
||||
capecanvas.width = 64;
|
||||
capecanvas.height = 32;
|
||||
|
||||
// You can change these value via external interface
|
||||
var isRotating = true;
|
||||
var isPaused = false;
|
||||
var isYfreezed = false;
|
||||
var isFunnyRunning = false;
|
||||
|
||||
var getMaterial = function (img, trans) {
|
||||
var material = new THREE.MeshBasicMaterial({
|
||||
map: new THREE.Texture(
|
||||
img,
|
||||
new THREE.UVMapping(),
|
||||
THREE.ClampToEdgeWrapping,
|
||||
THREE.ClampToEdgeWrapping,
|
||||
THREE.NearestFilter,
|
||||
THREE.NearestFilter,
|
||||
(trans? THREE.RGBAFormat : THREE.RGBFormat)
|
||||
),
|
||||
transparent: trans
|
||||
});
|
||||
material.map.needsUpdate = true;
|
||||
return material;
|
||||
};
|
||||
var uvmap = function (mesh, face, x, y, w, h, rotateBy) {
|
||||
if(!rotateBy) rotateBy = 0;
|
||||
var uvs = mesh.geometry.faceVertexUvs[0][face];
|
||||
var tileU = x;
|
||||
var tileV = y;
|
||||
|
||||
uvs[ (0 + rotateBy) % 4 ].u = tileU * tileUvWidth;
|
||||
uvs[ (0 + rotateBy) % 4 ].v = tileV * tileUvHeight;
|
||||
uvs[ (1 + rotateBy) % 4 ].u = tileU * tileUvWidth;
|
||||
uvs[ (1 + rotateBy) % 4 ].v = tileV * tileUvHeight + h * tileUvHeight;
|
||||
uvs[ (2 + rotateBy) % 4 ].u = tileU * tileUvWidth + w * tileUvWidth;
|
||||
uvs[ (2 + rotateBy) % 4 ].v = tileV * tileUvHeight + h * tileUvHeight;
|
||||
uvs[ (3 + rotateBy) % 4 ].u = tileU * tileUvWidth + w * tileUvWidth;
|
||||
uvs[ (3 + rotateBy) % 4 ].v = tileV * tileUvHeight;
|
||||
};
|
||||
var cubeFromPlanes = function (size, mat) {
|
||||
var cube = new THREE.Object3D();
|
||||
var meshes = [];
|
||||
for(var i=0; i < 6; i++) {
|
||||
var mesh = new THREE.Mesh(new THREE.PlaneGeometry(size, size), mat);
|
||||
mesh.doubleSided = true;
|
||||
cube.add(mesh);
|
||||
meshes.push(mesh);
|
||||
}
|
||||
// Front
|
||||
meshes[0].rotation.x = Math.PI/2;
|
||||
meshes[0].rotation.z = -Math.PI/2;
|
||||
meshes[0].position.x = size/2;
|
||||
|
||||
// Back
|
||||
meshes[1].rotation.x = Math.PI/2;
|
||||
meshes[1].rotation.z = Math.PI/2;
|
||||
meshes[1].position.x = -size/2;
|
||||
|
||||
// Top
|
||||
meshes[2].position.y = size/2;
|
||||
|
||||
// Bottom
|
||||
meshes[3].rotation.y = Math.PI;
|
||||
meshes[3].rotation.z = Math.PI;
|
||||
meshes[3].position.y = -size/2;
|
||||
|
||||
// Left
|
||||
meshes[4].rotation.x = Math.PI/2;
|
||||
meshes[4].position.z = size/2;
|
||||
|
||||
// Right
|
||||
meshes[5].rotation.x = -Math.PI/2;
|
||||
meshes[5].rotation.y = Math.PI;
|
||||
meshes[5].position.z = -size/2;
|
||||
|
||||
return cube;
|
||||
};
|
||||
|
||||
|
||||
var charMaterial = getMaterial(skincanvas, false);
|
||||
var charMaterialTrans = getMaterial(skincanvas, true);
|
||||
var capeMaterial = getMaterial(capecanvas, false);
|
||||
|
||||
var camera = new THREE.PerspectiveCamera(35, cw / ch, 1, 1000);
|
||||
camera.position.z = 50;
|
||||
//camera.target.position.y = -2;
|
||||
var scene = new THREE.Scene();
|
||||
scene.add(camera);
|
||||
|
||||
var headgroup = new THREE.Object3D();
|
||||
var upperbody = new THREE.Object3D();
|
||||
|
||||
//Light
|
||||
var pointLightA = new THREE.DirectionalLight(0xFFFFFF, 1);
|
||||
var pointLightB = new THREE.DirectionalLight(0x666666, 1);
|
||||
var environmentalLight = new THREE.AmbientLight(0x555555);
|
||||
pointLightA.position.set(100, 120, 80);
|
||||
pointLightB.position.set(-100, -40, -80);
|
||||
scene.add(pointLightA);
|
||||
scene.add(pointLightB);
|
||||
scene.add(environmentalLight);
|
||||
|
||||
// Left leg
|
||||
var leftleggeo = new THREE.CubeGeometry(4, 12, 4);
|
||||
for(var i=0; i < 8; i+=1) {
|
||||
leftleggeo.vertices[i].y -= 6;
|
||||
}
|
||||
var leftleg = new THREE.Mesh(leftleggeo, charMaterial);
|
||||
leftleg.position.z = -2;
|
||||
leftleg.position.y = -6;
|
||||
uvmap(leftleg, 0, 8, 20, -4, 12);
|
||||
uvmap(leftleg, 1, 16, 20, -4, 12);
|
||||
uvmap(leftleg, 2, 4, 16, 4, 4, 3);
|
||||
uvmap(leftleg, 3, 8, 20, 4, -4, 1);
|
||||
uvmap(leftleg, 4, 12, 20, -4, 12);
|
||||
uvmap(leftleg, 5, 4, 20, -4, 12);
|
||||
|
||||
// Right leg
|
||||
var rightleggeo = new THREE.CubeGeometry(4, 12, 4);
|
||||
for(var i=0; i < 8; i+=1) {
|
||||
rightleggeo.vertices[i].y -= 6;
|
||||
}
|
||||
var rightleg = new THREE.Mesh(rightleggeo, charMaterial);
|
||||
rightleg.position.z = 2;
|
||||
rightleg.position.y = -6;
|
||||
uvmap(rightleg, 0, 4, 20, 4, 12);
|
||||
uvmap(rightleg, 1, 12, 20, 4, 12);
|
||||
uvmap(rightleg, 2, 8, 16, -4, 4, 3);
|
||||
uvmap(rightleg, 3, 12, 20, -4, -4, 1);
|
||||
uvmap(rightleg, 4, 0, 20, 4, 12);
|
||||
uvmap(rightleg, 5, 8, 20, 4, 12);
|
||||
|
||||
// Body
|
||||
var bodygeo = new THREE.CubeGeometry(4, 12, 8);
|
||||
var bodymesh = new THREE.Mesh(bodygeo, charMaterial);
|
||||
uvmap(bodymesh, 0, 20, 20, 8, 12);
|
||||
uvmap(bodymesh, 1, 32, 20, 8, 12);
|
||||
uvmap(bodymesh, 2, 20, 16, 8, 4, 1);
|
||||
uvmap(bodymesh, 3, 28, 16, 8, 4, 3);
|
||||
uvmap(bodymesh, 4, 16, 20, 4, 12);
|
||||
uvmap(bodymesh, 5, 28, 20, 4, 12);
|
||||
upperbody.add(bodymesh);
|
||||
|
||||
// Left arm
|
||||
var leftarmgeo = new THREE.CubeGeometry(4, 12, 4);
|
||||
for(var i=0; i < 8; i+=1) {
|
||||
leftarmgeo.vertices[i].y -= 4;
|
||||
}
|
||||
var leftarm = new THREE.Mesh(leftarmgeo, charMaterial);
|
||||
leftarm.position.z = -6;
|
||||
leftarm.position.y = 4;
|
||||
leftarm.rotation.x = Math.PI/32;
|
||||
uvmap(leftarm, 0, 48, 20, -4, 12);
|
||||
uvmap(leftarm, 1, 56, 20, -4, 12);
|
||||
uvmap(leftarm, 2, 48, 16, -4, 4, 1);
|
||||
uvmap(leftarm, 3, 52, 16, -4, 4, 3);
|
||||
uvmap(leftarm, 4, 52, 20, -4, 12);
|
||||
uvmap(leftarm, 5, 44, 20, -4, 12);
|
||||
upperbody.add(leftarm);
|
||||
|
||||
// Right arm
|
||||
var rightarmgeo = new THREE.CubeGeometry(4, 12, 4);
|
||||
for(var i=0; i < 8; i+=1) {
|
||||
rightarmgeo.vertices[i].y -= 4;
|
||||
}
|
||||
var rightarm = new THREE.Mesh(rightarmgeo, charMaterial);
|
||||
rightarm.position.z = 6;
|
||||
rightarm.position.y = 4;
|
||||
rightarm.rotation.x = -Math.PI/32;
|
||||
uvmap(rightarm, 0, 44, 20, 4, 12);
|
||||
uvmap(rightarm, 1, 52, 20, 4, 12);
|
||||
uvmap(rightarm, 2, 44, 16, 4, 4, 1);
|
||||
uvmap(rightarm, 3, 48, 16, 4, 4, 3);
|
||||
uvmap(rightarm, 4, 40, 20, 4, 12);
|
||||
uvmap(rightarm, 5, 48, 20, 4, 12);
|
||||
upperbody.add(rightarm);
|
||||
|
||||
//Head
|
||||
var headgeo = new THREE.CubeGeometry(8, 8, 8);
|
||||
var headmesh = new THREE.Mesh(headgeo, charMaterial);
|
||||
headmesh.position.y = 2;
|
||||
uvmap(headmesh, 0, 8, 8, 8, 8);
|
||||
uvmap(headmesh, 1, 24, 8, 8, 8);
|
||||
|
||||
uvmap(headmesh, 2, 8, 0, 8, 8, 1);
|
||||
uvmap(headmesh, 3, 16, 0, 8, 8, 1);
|
||||
|
||||
uvmap(headmesh, 4, 0, 8, 8, 8);
|
||||
uvmap(headmesh, 5, 16, 8, 8, 8);
|
||||
headgroup.add(headmesh);
|
||||
|
||||
// Helmet/hat
|
||||
var helmetgeo = new THREE.CubeGeometry(9, 9, 9);
|
||||
var helmetmesh = new THREE.Mesh(helmetgeo, charMaterialTrans);
|
||||
helmetmesh.doubleSided = true;
|
||||
helmetmesh.position.y = 2;
|
||||
uvmap(helmetmesh, 0, 32+8, 8, 8, 8);
|
||||
uvmap(helmetmesh, 1, 32+24, 8, 8, 8);
|
||||
|
||||
uvmap(helmetmesh, 2, 32+8, 0, 8, 8, 1);
|
||||
uvmap(helmetmesh, 3, 32+16, 0, 8, 8, 3);
|
||||
|
||||
uvmap(helmetmesh, 4, 32+0, 8, 8, 8);
|
||||
uvmap(helmetmesh, 5, 32+16, 8, 8, 8);
|
||||
headgroup.add(helmetmesh);
|
||||
|
||||
var helmet = cubeFromPlanes(9, charMaterialTrans);
|
||||
helmet.position.y = 2;
|
||||
uvmap(helmet.children[0], 0, 32+8, 8, 8, 8);
|
||||
uvmap(helmet.children[1], 0, 32+24, 8, 8, 8);
|
||||
uvmap(helmet.children[2], 0, 32+8, 0, 8, 8, 1);
|
||||
uvmap(helmet.children[3], 0, 32+16, 0, 8, 8, 3);
|
||||
uvmap(helmet.children[4], 0, 32+0, 8, 8, 8);
|
||||
uvmap(helmet.children[5], 0, 32+16, 8, 8, 8);
|
||||
|
||||
headgroup.add(helmet);
|
||||
|
||||
/* ===== Ears Start (作者的彩蛋,没啥卵用) ===== */
|
||||
var ears = new THREE.Object3D();
|
||||
|
||||
var eargeo = new THREE.CubeGeometry(1, (9/8)*6, (9/8)*6);
|
||||
var leftear = new THREE.Mesh(eargeo, charMaterial);
|
||||
var rightear = new THREE.Mesh(eargeo, charMaterial);
|
||||
|
||||
leftear.position.y = 2+(9/8)*5;
|
||||
rightear.position.y = 2+(9/8)*5;
|
||||
leftear.position.z = -(9/8)*5;
|
||||
rightear.position.z = (9/8)*5;
|
||||
|
||||
// Right ear share same geometry, same uv-maps
|
||||
uvmap(leftear, 0, 25, 1, 6, 6); // Front side
|
||||
uvmap(leftear, 1, 32, 1, 6, 6); // Back side
|
||||
|
||||
uvmap(leftear, 2, 25, 0, 6, 1, 1); // Top edge
|
||||
uvmap(leftear, 3, 31, 0, 6, 1, 1); // Bottom edge
|
||||
|
||||
uvmap(leftear, 4, 24, 1, 1, 6); // Left edge
|
||||
uvmap(leftear, 5, 31, 1, 1, 6); // Right edge
|
||||
|
||||
ears.add(leftear);
|
||||
ears.add(rightear);
|
||||
|
||||
leftear.visible = rightear.visible = false;
|
||||
|
||||
headgroup.add(ears);
|
||||
headgroup.position.y = 8;
|
||||
/* ================ Ears End ================== */
|
||||
|
||||
// Init cape
|
||||
var capeOrigo = new THREE.Object3D();
|
||||
var capegeo = new THREE.CubeGeometry(1, 16, 10);
|
||||
var capemesh = new THREE.Mesh(capegeo, capeMaterial);
|
||||
capemesh.position.y = -8;
|
||||
capemesh.visible = false;
|
||||
|
||||
uvmap(capemesh, 0, 1, 1, 10, 16); // Front side
|
||||
uvmap(capemesh, 1, 12, 1, 10, 16); // Back side
|
||||
|
||||
uvmap(capemesh, 2, 1, 0, 10, 1); // Top edge
|
||||
uvmap(capemesh, 3, 11, 0, 10, 1, 1); // Bottom edge
|
||||
|
||||
uvmap(capemesh, 4, 0, 1, 1, 16); // Left edge
|
||||
uvmap(capemesh, 5, 11, 1, 1, 16); // Right edge
|
||||
|
||||
|
||||
capeOrigo.rotation.y = Math.PI;
|
||||
|
||||
capeOrigo.position.x = -2;
|
||||
capeOrigo.position.y = 6;
|
||||
|
||||
capeOrigo.add(capemesh);
|
||||
|
||||
|
||||
var playerModel = new THREE.Object3D();
|
||||
|
||||
playerModel.add(leftleg);
|
||||
playerModel.add(rightleg);
|
||||
|
||||
playerModel.add(upperbody);
|
||||
playerModel.add(headgroup);
|
||||
|
||||
playerModel.add(capeOrigo);
|
||||
|
||||
playerModel.position.y = 6;
|
||||
|
||||
|
||||
var playerGroup = new THREE.Object3D();
|
||||
|
||||
playerGroup.add(playerModel);
|
||||
|
||||
|
||||
scene.add(playerGroup);
|
||||
|
||||
|
||||
var mouseX = 0;
|
||||
var mouseY = 0.1;
|
||||
var originMouseX = 0;
|
||||
var originMouseY = 0;
|
||||
|
||||
var rad = 0;
|
||||
|
||||
var isMouseOver = false;
|
||||
var isMouseDown = false;
|
||||
|
||||
var counter = 0;
|
||||
var firstRender = true;
|
||||
|
||||
var startTime = Date.now();
|
||||
var pausedTime = 0;
|
||||
|
||||
var render = function () {
|
||||
requestAnimFrame(render, renderer.domElement);
|
||||
var oldRad = rad;
|
||||
|
||||
var time = (Date.now() - startTime)/1000;
|
||||
|
||||
if(!isMouseDown) {
|
||||
//mouseX*=0.95;
|
||||
if(!isYfreezed) {
|
||||
mouseY*=0.97;
|
||||
}
|
||||
if(isRotating) {
|
||||
rad += 2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
rad = mouseX;
|
||||
}
|
||||
if(mouseY > 500) {
|
||||
mouseY = 500;
|
||||
}
|
||||
else if(mouseY < -500) {
|
||||
mouseY = -500;
|
||||
}
|
||||
camera.position.x = -Math.cos(rad/(cw/2)+(Math.PI/0.9));
|
||||
camera.position.z = -Math.sin(rad/(cw/2)+(Math.PI/0.9));
|
||||
camera.position.y = (mouseY/(ch/2))*1.5+0.2;
|
||||
camera.position.setLength(70);
|
||||
camera.lookAt(new THREE.Vector3(0, 1.5, 0));
|
||||
|
||||
|
||||
if(!isPaused) {
|
||||
counter+=0.01;
|
||||
headgroup.rotation.y = Math.sin(time*1.5)/5;
|
||||
headgroup.rotation.z = Math.sin(time)/6;
|
||||
|
||||
if(isFunnyRunning) {
|
||||
|
||||
rightarm.rotation.z = 2 * Math.cos(0.6662 * time*10 + Math.PI);
|
||||
rightarm.rotation.x = 1 * (Math.cos(0.2812 * time*10) - 1);
|
||||
leftarm.rotation.z = 2 * Math.cos(0.6662 * time*10);
|
||||
leftarm.rotation.x = 1 * (Math.cos(0.2312 * time*10) + 1);
|
||||
|
||||
rightleg.rotation.z = 1.4 * Math.cos(0.6662 * time*10);
|
||||
leftleg.rotation.z = 1.4 * Math.cos(0.6662 * time*10 + Math.PI);
|
||||
|
||||
playerGroup.position.y = -6+1 * Math.cos(0.6662 * time*10 * 2); // Jumping
|
||||
playerGroup.position.z = 0.15 * Math.cos(0.6662 * time*10); // Dodging when running
|
||||
playerGroup.rotation.x = 0.01 * Math.cos(0.6662 * time*10 + Math.PI); // Slightly tilting when running
|
||||
|
||||
capeOrigo.rotation.z = 0.1 * Math.sin(0.6662 * time*10 * 2)+Math.PI/2.5;
|
||||
|
||||
}
|
||||
else {
|
||||
leftarm.rotation.z = -Math.sin(time*3)/2;
|
||||
leftarm.rotation.x = (Math.cos(time*3)+Math.PI/2)/30;
|
||||
rightarm.rotation.z = Math.sin(time*3)/2;
|
||||
rightarm.rotation.x = -(Math.cos(time*3)+Math.PI/2)/30;
|
||||
|
||||
leftleg.rotation.z = Math.sin(time*3)/3;
|
||||
rightleg.rotation.z = -Math.sin(time*3)/3;
|
||||
capeOrigo.rotation.z = Math.sin(time*2)/15+Math.PI/15;
|
||||
|
||||
playerGroup.position.y = -6; // Not jumping
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
renderer.render(scene, camera);
|
||||
};
|
||||
if(supportWebGL) {
|
||||
var renderer = new THREE.WebGLRenderer({antialias: true,precision:'highp'});
|
||||
}
|
||||
else {
|
||||
var renderer = new THREE.CanvasRenderer({antialias: true});
|
||||
}
|
||||
var threecanvas = renderer.domElement;
|
||||
renderer.setSize(cw, ch);
|
||||
//renderer.setClearColorHex(0x000000, 0.25);
|
||||
|
||||
// container.appendChild(threecanvas);
|
||||
|
||||
var onMouseMove = function (e) {
|
||||
if(isMouseDown) {
|
||||
mouseX = (e.pageX - threecanvas.offsetLeft - originMouseX);
|
||||
mouseY = (e.pageY - threecanvas.offsetTop - originMouseY);
|
||||
}
|
||||
};
|
||||
|
||||
threecanvas.addEventListener('mousedown', function (e) {
|
||||
e.preventDefault();
|
||||
originMouseX = (e.pageX - threecanvas.offsetLeft) - rad;
|
||||
originMouseY = (e.pageY - threecanvas.offsetTop) - mouseY;
|
||||
isMouseDown = true;
|
||||
isMouseOver = true;
|
||||
onMouseMove(e);
|
||||
}, false);
|
||||
global.addEventListener('mouseup', function (e) {
|
||||
isMouseDown = false;
|
||||
}, false);
|
||||
global.addEventListener('mousemove', onMouseMove, false);
|
||||
threecanvas.addEventListener('mouseout', function (e) {
|
||||
isMouseOver = false;
|
||||
}, false);
|
||||
|
||||
// container.appendChild(skinBig);
|
||||
|
||||
/* ============================================================ */
|
||||
|
||||
// 默认开始渲染的地方
|
||||
render();
|
||||
|
||||
var skin = new Image();
|
||||
|
||||
skin.onload = function () {
|
||||
/* 高清皮肤支持 */
|
||||
skincanvas.width = skin.width;
|
||||
skincanvas.height = skin.width/2;
|
||||
|
||||
skinc.clearRect(0, 0, skincanvas.width, skincanvas.height);
|
||||
|
||||
//DEBUG
|
||||
//console.log(skin.width+" "+skin.height);
|
||||
|
||||
if(skin.width==skin.height){
|
||||
var ratio=skin.width/64;
|
||||
skinc.drawImage(skin, 0 *ratio, 0 *ratio, 64*ratio, 32*ratio, 0 *ratio, 0 *ratio, 64*ratio, 32*ratio);
|
||||
skinc.drawImage(skin, 0 *ratio, 32*ratio, 64*ratio, 16*ratio, 0 *ratio, 16*ratio, 64*ratio, 16*ratio);
|
||||
}else{
|
||||
skinc.drawImage(skin, 0, 0);
|
||||
}
|
||||
|
||||
var imgdata = skinc.getImageData(0, 0, skincanvas.width, skincanvas.height);
|
||||
var pixels = imgdata.data;
|
||||
|
||||
|
||||
|
||||
sbc.clearRect(0, 0, skinBig.width, skinBig.height);
|
||||
sbc.save();
|
||||
|
||||
var isOnecolor = true;
|
||||
|
||||
var colorCheckAgainst = [40, 0];
|
||||
var colorIndex = (colorCheckAgainst[0]+colorCheckAgainst[1]*64)*4;
|
||||
|
||||
var isPixelDifferent = function (x, y) {
|
||||
if(pixels[(x+y*64)*4+0] !== pixels[colorIndex+0] || pixels[(x+y*64)*4+1] !== pixels[colorIndex+1] || pixels[(x+y*64)*4+2] !== pixels[colorIndex+2] || pixels[(x+y*64)*4+3] !== pixels[colorIndex+3]) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Check if helmet/hat is a solid color
|
||||
// Bottom row
|
||||
for(var i=32; i < 64; i+=1) {
|
||||
for(var j=8; j < 16; j+=1) {
|
||||
if(isPixelDifferent(i, j)) {
|
||||
isOnecolor = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!isOnecolor) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!isOnecolor) {
|
||||
// Top row
|
||||
for(var i=40; i < 56; i+=1) {
|
||||
for(var j=0; j < 8; j+=1) {
|
||||
if(isPixelDifferent(i, j)) {
|
||||
isOnecolor = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!isOnecolor) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
for(var i=0; i < 64; i+=1) {
|
||||
for(var j=0; j < 32; j+=1) {
|
||||
|
||||
if(isOnecolor && ((i >= 32 && i < 64 && j >= 8 && j < 16) || (i >= 40 && i < 56 && j >= 0 && j < 8))) {
|
||||
pixels[(i+j*64)*4+3] = 0;
|
||||
}
|
||||
sbc.fillStyle = 'rgba('+pixels[(i+j*64)*4+0]+', '+pixels[(i+j*64)*4+1]+', '+pixels[(i+j*64)*4+2]+', '+pixels[(i+j*64)*4+3]/255+')';
|
||||
sbc.fillRect(i*sizeRatio, j*sizeRatio, sizeRatio, sizeRatio);
|
||||
}
|
||||
}
|
||||
sbc.restore();
|
||||
|
||||
skinc.putImageData(imgdata, 0, 0);
|
||||
|
||||
charMaterial.map.needsUpdate = true;
|
||||
charMaterialTrans.map.needsUpdate = true;
|
||||
};
|
||||
|
||||
var cape = new Image();
|
||||
|
||||
cape.onload = function () {
|
||||
/* 高清披风支持 */
|
||||
capecanvas.width = cape.width;
|
||||
capecanvas.height = cape.height;
|
||||
|
||||
capec.clearRect(0, 0, 64, 32);
|
||||
|
||||
capec.drawImage(cape, 0, 0);
|
||||
|
||||
capeMaterial.map.needsUpdate = true;
|
||||
capemesh.visible = true;
|
||||
};
|
||||
cape.onerror = function () {
|
||||
capemesh.visible = false;
|
||||
};
|
||||
|
||||
threecanvas.addEventListener('dragenter', function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
threecanvas.className = "dragenter";
|
||||
}, false);
|
||||
threecanvas.addEventListener('dragleave', function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
threecanvas.className = "";
|
||||
}, false);
|
||||
threecanvas.addEventListener('dragover', function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
}, false);
|
||||
threecanvas.addEventListener('drop', function (e) {
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
threecanvas.className = "";
|
||||
|
||||
var dt = e.dataTransfer;
|
||||
var files = dt.files;
|
||||
handleFiles(files);
|
||||
}, false);
|
||||
|
||||
// 定义外部接口
|
||||
return {
|
||||
getStatus: function(key) {
|
||||
switch(key) {
|
||||
case "rotation":
|
||||
return isRotating;
|
||||
break;
|
||||
case "movements":
|
||||
return !isPaused;
|
||||
break;
|
||||
case "camera":
|
||||
return !isYfreezed;
|
||||
break;
|
||||
case "running":
|
||||
return isFunnyRunning;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
},
|
||||
setStatus: function(key, value) {
|
||||
switch(key) {
|
||||
case "rotation":
|
||||
isRotating = value;
|
||||
return isRotating;
|
||||
break;
|
||||
case "movements":
|
||||
isPaused = !value;
|
||||
// \o/
|
||||
if(isPaused) {
|
||||
pausedTime = Date.now() - startTime;
|
||||
} else {
|
||||
startTime = Date.now() - pausedTime;
|
||||
}
|
||||
return !isPaused;
|
||||
break;
|
||||
case "camera":
|
||||
isYfreezed = !value;
|
||||
return !isYfreezed;
|
||||
break;
|
||||
case "running":
|
||||
isFunnyRunning = value;
|
||||
return isFunnyRunning;
|
||||
break;
|
||||
default:
|
||||
}
|
||||
},
|
||||
showCape: function(val) {
|
||||
if(val) {
|
||||
capeOrigo.add(capemesh);
|
||||
} else {
|
||||
capeOrigo.remove(capemesh);
|
||||
}
|
||||
},
|
||||
changeSkin: function(url) {
|
||||
skin.src = url;
|
||||
},
|
||||
changeCape: function(url) {
|
||||
cape.src = url;
|
||||
},
|
||||
clear: function() {
|
||||
skin.src = dskin;
|
||||
cape.src = "";
|
||||
},
|
||||
get3dSkinCanvas: function(width, height) {
|
||||
renderer.setSize(width, height);
|
||||
return threecanvas;
|
||||
},
|
||||
// 作者的彩蛋(笑
|
||||
setEars: function (val) {
|
||||
leftear.visible = rightear.visible = val;
|
||||
}
|
||||
};
|
||||
}(this));
|
||||
10
yarn.lock
10
yarn.lock
|
|
@ -5311,6 +5311,12 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
|
|||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
|
||||
skinview3d@^1.1.0-alpha.2:
|
||||
version "1.1.0-alpha.2"
|
||||
resolved "https://registry.yarnpkg.com/skinview3d/-/skinview3d-1.1.0-alpha.2.tgz#81a7e8377878f5acaf10cbc2833ecc156aa9f84e"
|
||||
dependencies:
|
||||
three "^0.89.0"
|
||||
|
||||
slash@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55"
|
||||
|
|
@ -5671,6 +5677,10 @@ text-table@~0.2.0:
|
|||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
|
||||
|
||||
three@^0.89.0:
|
||||
version "0.89.0"
|
||||
resolved "https://registry.yarnpkg.com/three/-/three-0.89.0.tgz#4442d819a6168871b8d2cb37ad12a24310c170f5"
|
||||
|
||||
throat@^3.0.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/throat/-/throat-3.2.0.tgz#50cb0670edbc40237b9e347d7e1f88e4620af836"
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user