Skip to content

Instantly share code, notes, and snippets.

@Alliline
Forked from fpigerre/animation.js
Created December 8, 2015 17:30
Show Gist options
  • Save Alliline/ff726fe160a6e18195ae to your computer and use it in GitHub Desktop.
Save Alliline/ff726fe160a6e18195ae to your computer and use it in GitHub Desktop.

Revisions

  1. @PSGS PSGS created this gist May 17, 2014.
    713 changes: 713 additions & 0 deletions animation.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,713 @@
    /**
    * Code by djazz as part of his Minecraft Skin Viewer
    * http://djazz.mine.nu/apps/MinecraftSkin/
    */
    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');

    var cw = 400, ch = 550;
    var tileUvWidth = 1 / 64;
    var tileUvHeight = 1 / 32;


    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;

    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(
    THREE.ImageUtils.loadTexture('images/minecraftskinpurple.png'),
    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();

    // 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, 3);

    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);

    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;

    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});
    }
    else {
    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(global.document.createElement('br'));

    var spinBox = global.document.createElement('input');
    spinBox.type = 'checkbox';
    spinBox.checked = false;
    spinBox.id = 'msp_spinbox';
    var spinBoxLabel = global.document.createElement('label');
    spinBoxLabel.textContent = "Freeze rotating";
    spinBoxLabel.setAttribute('for', spinBox.id);
    container.appendChild(spinBox);
    container.appendChild(spinBoxLabel);

    spinBox.addEventListener('change', function () {
    isRotating = !spinBox.checked;
    }, false);

    container.appendChild(global.document.createElement('br'));

    var moveBox = global.document.createElement('input');
    moveBox.type = 'checkbox';
    moveBox.checked = false;
    moveBox.id = 'msp_movebox';
    var moveBoxLabel = global.document.createElement('label');
    moveBoxLabel.textContent = "Freeze movements";
    moveBoxLabel.setAttribute('for', moveBox.id);
    container.appendChild(moveBox);
    container.appendChild(moveBoxLabel);

    moveBox.addEventListener('change', function () {

    isPaused = moveBox.checked;

    // \o/
    if (isPaused) {
    pausedTime = Date.now() - startTime;
    }
    else {
    startTime = Date.now() - pausedTime;
    }
    }, false);

    container.appendChild(global.document.createElement('br'));

    var yFreezeBox = global.document.createElement('input');
    yFreezeBox.type = 'checkbox';
    yFreezeBox.checked = false;
    yFreezeBox.id = 'msp_yfreezebox';
    var yFreezeBoxLabel = global.document.createElement('label');
    yFreezeBoxLabel.textContent = "Freeze camera";
    yFreezeBoxLabel.setAttribute('for', yFreezeBox.id);
    container.appendChild(yFreezeBox);
    container.appendChild(yFreezeBoxLabel);

    yFreezeBox.addEventListener('change', function () {
    isYfreezed = yFreezeBox.checked;
    }, false);

    container.appendChild(global.document.createElement('br'));

    var capeBox = global.document.createElement('input');
    capeBox.type = 'checkbox';
    capeBox.checked = true;
    capeBox.id = 'msp_capebox';
    var capeBoxLabel = global.document.createElement('label');
    capeBoxLabel.textContent = "Show capes";
    capeBoxLabel.setAttribute('for', capeBox.id);
    container.appendChild(capeBox);
    container.appendChild(capeBoxLabel);

    capeBox.addEventListener('change', function () {
    if (capeBox.checked) {
    capeOrigo.add(capemesh);
    }
    else {
    capeOrigo.remove(capemesh);
    }
    }, false);

    container.appendChild(global.document.createElement('br'));

    var runBox = global.document.createElement('input');
    runBox.type = 'checkbox';
    runBox.checked = false;
    runBox.id = 'msp_runbox';
    var runBoxLabel = global.document.createElement('label');
    runBoxLabel.textContent = "Classic running";
    runBoxLabel.setAttribute('for', runBox.id);
    container.appendChild(runBox);
    container.appendChild(runBoxLabel);

    runBox.addEventListener('change', function () {
    isFunnyRunning = runBox.checked;
    }, false);

    container.appendChild(global.document.createElement('br'));

    container.appendChild(skinBig);

    render();

    var skin = new Image();

    skin.onload = function () {

    skinc.clearRect(0, 0, 64, 32);

    skinc.drawImage(skin, 0, 0);

    var imgdata = skinc.getImageData(0, 0, 64, 32);
    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 () {

    capec.clearRect(0, 0, 64, 32);

    capec.drawImage(cape, 0, 0);

    capeMaterial.map.needsUpdate = true;
    capemesh.visible = true;
    };
    cape.onerror = function () {
    capemesh.visible = false;
    };

    var defaultImages = [
    'simon.png',
    'char.png',
    'link.png',
    'DefMenge.png',
    'cod.png'
    ];

    skin.src = defaultImages[Math.floor(Math.random() * defaultImages.length)];

    var handleFiles = function (files) {
    if (files.length > 0) {
    var file = files[0];
    if (file.type === 'image/png') {
    var fr = new FileReader();
    fr.onload = function (e) {
    var img = new Image();
    img.onload = function () {
    if (this.width === 64 && this.height === 32) {
    skin.src = img.src;
    }
    else {
    alert("Error: The image must be 64x32 pixels!");
    }
    };
    img.onerror = function () {
    alert("Error: Not an image or unknown file format");
    };
    img.src = this.result;
    };
    fr.readAsDataURL(file);
    }
    else {
    alert("Error: This is not a PNG image!");
    }
    }
    };

    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);

    global.document.forms.imageform.fileinput.addEventListener('change', function () {
    var files = this.files;
    handleFiles(files);
    }, false);

    return {
    changeSkin: function (url) {
    skin.src = url;
    },
    changeCape: function (url) {
    cape.src = url;
    },
    setEars: function (val) {
    leftear.visible = rightear.visible = val;
    }
    };
    }(this));