diff options
Diffstat (limited to 'basicsuite/webengine/content/rubiks/js/rubik.js')
-rw-r--r-- | basicsuite/webengine/content/rubiks/js/rubik.js | 492 |
1 files changed, 0 insertions, 492 deletions
diff --git a/basicsuite/webengine/content/rubiks/js/rubik.js b/basicsuite/webengine/content/rubiks/js/rubik.js deleted file mode 100644 index 72dbae7..0000000 --- a/basicsuite/webengine/content/rubiks/js/rubik.js +++ /dev/null @@ -1,492 +0,0 @@ -Array.prototype.clone = function() { - var c = []; - var len = this.length; - for (var i=0;i<len;i++) { c.push(this[i]); } - return c; -} - -Array.prototype.random = function() { - return this[Math.floor(Math.random()*this.length)]; -} - -var Face = OZ.Class(); -Face.SIZE = 100; -Face.LEFT = 0; -Face.RIGHT = 1; -Face.TOP = 2; -Face.BOTTOM = 3; -Face.FRONT = 4; -Face.BACK = 5; - -Face.ROTATION = [ - [Face.TOP, Face.FRONT, Face.BOTTOM, Face.BACK].reverse(), - [Face.LEFT, Face.BACK, Face.RIGHT, Face.FRONT].reverse(), - [Face.LEFT, Face.BOTTOM, Face.RIGHT, Face.TOP].reverse() -]; - -Face.prototype.init = function(cube, type) { - this._cube = cube; - this._type = type; - this._color = null; - this._node = OZ.DOM.elm("div", {className:"face face"+type, width:Face.SIZE+"px", height:Face.SIZE+"px", position:"absolute", left:"0px", top:"0px"}); - OZ.CSS3.set(this._node, "box-sizing", "border-box"); - OZ.CSS3.set(this._node, "backface-visibility", "hidden"); - - switch (type) { - case Face.LEFT: - OZ.CSS3.set(this._node, "transform-origin", "100% 50%"); - OZ.CSS3.set(this._node, "transform", "translate3d(-"+Face.SIZE+"px, 0px, 0px) rotateY(-90deg)"); - break; - case Face.RIGHT: - OZ.CSS3.set(this._node, "transform-origin", "0% 50%"); - OZ.CSS3.set(this._node, "transform", "translate3d("+Face.SIZE+"px, 0px, 0px) rotateY(90deg)"); - break; - case Face.TOP: - OZ.CSS3.set(this._node, "transform-origin", "50% 100%"); - OZ.CSS3.set(this._node, "transform", "translate3d(0px, -"+Face.SIZE+"px, 0px) rotateX(90deg)"); - break; - case Face.BOTTOM: - OZ.CSS3.set(this._node, "transform-origin", "50% 0%"); - OZ.CSS3.set(this._node, "transform", "translate3d(0px, "+Face.SIZE+"px, 0px) rotateX(-90deg)"); - break; - case Face.FRONT: - break; - case Face.BACK: - OZ.CSS3.set(this._node, "transform", "translate3d(0px, 0px, -"+Face.SIZE+"px) rotateY(180deg)"); - break; - } -} - -Face.prototype.getCube = function() { - return this._cube; -} - -Face.prototype.getNode = function() { - return this._node; -} - -Face.prototype.getType = function() { - return this._type; -} - -Face.prototype.setColor = function(color) { - this._color = color; - this._node.style.backgroundColor = color; -} - -Face.prototype.getColor = function() { - return this._color; -} - -var Cube = OZ.Class(); -Cube.prototype.init = function(position) { - this._rotation = null; - this._position = position; - this._node = OZ.DOM.elm("div", {className:"cube", position:"absolute", width:Face.SIZE+"px", height:Face.SIZE+"px"}); - this._faces = {}; - this._tmpFaces = {}; - OZ.CSS3.set(this._node, "transform-style", "preserve-3d"); - - this._update(); -} - -Cube.prototype.getFaces = function() { - return this._faces; -} - -Cube.prototype.setFace = function(type, color) { - if (!(type in this._faces)) { - var face = new Face(this, type); - this._node.appendChild(face.getNode()); - this._faces[type] = face; - } - this._faces[type].setColor(color); -} - -Cube.prototype.setRotation = function(rotation) { - this._rotation = rotation; - this._update(); -} - -Cube.prototype.complete = function() { - for (var i=0;i<6;i++) { - if (i in this._faces) { continue; } - this.addFace(i, "black"); - } -} - -Cube.prototype.prepareColorChange = function(sourceCube, rotation) { - this._tmpFaces = {}; - var sourceFaces = sourceCube.getFaces(); - for (var p in sourceFaces) { - var sourceType = parseInt(p); - var targetType = this._rotateType(sourceType, rotation); - this._tmpFaces[targetType] = sourceFaces[sourceType].getColor(); - } -} - -Cube.prototype.commitColorChange = function() { - var parent = this._node.parentNode; - parent.removeChild(this._node); - - OZ.DOM.clear(this._node); - this._faces = {}; - for (var p in this._tmpFaces) { - var type = parseInt(p); - this.setFace(type, this._tmpFaces[p]); - } - this._tmpFaces = {}; - - this._rotation = null; - this._update(); - parent.appendChild(this._node); -} - -Cube.prototype._rotateType = function(type, rotation) { - for (var i=0;i<3;i++) { - if (!rotation[i]) { continue; } - var faces = Face.ROTATION[i]; - var index = faces.indexOf(type); - if (index == -1) { continue; } /* no rotation available */ - index = (index + rotation[i] + faces.length) % faces.length; - return faces[index]; - } - - return type; -} - -Cube.prototype._update = function() { - var transform = ""; - transform += "translate3d("+(-Face.SIZE/2)+"px, "+(-Face.SIZE/2)+"px, "+(-Face.SIZE/2)+"px) "; - if (this._rotation) { transform += this._rotation + " "; } - - var half = Math.floor(Rubik.SIZE/2); - var x = this._position[0]; - var y = this._position[1]; - var z = -this._position[2]; - x -= half; - y -= half; - z += half + 1/2; - transform += "translate3d("+(x*Face.SIZE)+"px, "+(y*Face.SIZE)+"px, "+(z*Face.SIZE)+"px)"; - - var prop = OZ.CSS3.getProperty("transform"); - var val = this._rotation ? prop + " 300ms" : ""; - OZ.CSS3.set(this._node, "transition", val); - - OZ.CSS3.set(this._node, "transform", transform); -} - -Cube.prototype.getPosition = function() { - return this._position; -} - -Cube.prototype.getNode = function() { - return this._node; -} - -Cube.prototype.getFaces = function() { - return this._faces; -} - -var Rubik = OZ.Class(); -Rubik.SIZE = 3; -Rubik.prototype.init = function() { - this._cubes = []; - this._faces = []; - this._faceNodes = []; - this._help = {}; - this._drag = { - ec: [], - mouse: [], - face: null - }; - - this._rotation = Quaternion.fromRotation([1, 0, 0], -35).multiply(Quaternion.fromRotation([0, 1, 0], 45)); - this._node = OZ.DOM.elm("div", {position:"absolute", left:"50%", top:"55%", width:"0px", height:"0px"}); - document.body.appendChild(this._node); - - OZ.CSS3.set(document.body, "perspective", "460px"); - OZ.CSS3.set(this._node, "transform-style", "preserve-3d"); - - this._build(); - this._update(); - OZ.Event.add(document.body, "mousedown touchstart", this._dragStart.bind(this)); - - setTimeout(this.randomize.bind(this), 500); -} - -Rubik.prototype.randomize = function() { - var remain = 10; - var cb = function() { - remain--; - if (remain > 0) { - this._rotateRandom(); - } else { - OZ.Event.remove(e); - - this._help.a = OZ.DOM.elm("p", {innerHTML:"Drag or swipe the background to rotate the whole cube."}); - this._help.b = OZ.DOM.elm("p", {innerHTML:"Drag or swipe the cube to rotate its layers."}); - document.body.appendChild(this._help.a); - document.body.appendChild(this._help.b); - OZ.CSS3.set(this._help.a, "transition", "opacity 500ms"); - OZ.CSS3.set(this._help.b, "transition", "opacity 500ms"); - - } - } - var e = OZ.Event.add(null, "rotated", cb.bind(this)); - this._rotateRandom(); -} - -Rubik.prototype._rotateRandom = function() { - var method = "_rotate" + ["X", "Y", "Z"].random(); - var dir = [-1, 1].random(); - var layer = Math.floor(Math.random()*Rubik.SIZE); - this[method](dir, layer); -} - -Rubik.prototype._update = function() { - OZ.CSS3.set(this._node, "transform", "translateZ(" + (-Face.SIZE/2 - Face.SIZE) + "px) " + this._rotation.toRotation() + " translateZ("+(Face.SIZE/2)+"px)"); -} - -Rubik.prototype._eventToFace = function(e) { - if (document.elementFromPoint) { - e = (e.touches ? e.touches[0] : e); - var node = document.elementFromPoint(e.clientX, e.clientY); - } else { - var node = OZ.Event.target(e); - } - var index = this._faceNodes.indexOf(node); - if (index == -1) { return null; } - return this._faces[index]; -} - -Rubik.prototype._dragStart = function(e) { - this._faces = []; - this._faceNodes = []; - for (var i=0;i<this._cubes.length;i++) { - var faces = this._cubes[i].getFaces(); - for (var p in faces) { - this._faces.push(faces[p]); - this._faceNodes.push(faces[p].getNode()); - } - } - - OZ.Event.prevent(e); - this._drag.face = this._eventToFace(e); - e = (e.touches ? e.touches[0] : e); - this._drag.mouse = [e.clientX, e.clientY]; - - this._drag.ec.push(OZ.Event.add(document.body, "mousemove touchmove", this._dragMove.bind(this))); - this._drag.ec.push(OZ.Event.add(document.body, "mouseup touchend", this._dragEnd.bind(this))); -} - -Rubik.prototype._dragMove = function(e) { - if (e.touches && e.touches.length > 1) { return; } - - if (this._drag.face) { /* check second face for rotation */ - var thisFace = this._eventToFace(e); - if (!thisFace || thisFace == this._drag.face) { return; } - this._dragEnd(); - this._rotate(this._drag.face, thisFace); - } else { /* rotate cube */ - e = (e.touches ? e.touches[0] : e); - var mouse = [e.clientX, e.clientY]; - var dx = mouse[0] - this._drag.mouse[0]; - var dy = mouse[1] - this._drag.mouse[1]; - var norm = Math.sqrt(dx*dx+dy*dy); - if (!norm) { return; } - var N = [-dy/norm, dx/norm]; - - this._drag.mouse = mouse; - this._rotation = Quaternion.fromRotation([N[0], N[1], 0], norm/2).multiply(this._rotation); - this._update(); - } -} - -Rubik.prototype._dragEnd = function(e) { - while (this._drag.ec.length) { OZ.Event.remove(this._drag.ec.pop()); } - - if (!this._drag.face && this._help.a) { - this._help.a.style.opacity = 0; - this._help.a = null; - } -} - -Rubik.prototype._rotate = function(face1, face2) { - var t1 = face1.getType(); - var t2 = face2.getType(); - var pos1 = face1.getCube().getPosition(); - var pos2 = face2.getCube().getPosition(); - - /* find difference between cubes */ - var diff = 0; - var diffIndex = -1; - for (var i=0;i<3;i++) { - var d = pos1[i]-pos2[i]; - if (d) { - if (diffIndex != -1) { return; } /* different in >1 dimensions */ - diff = (d > 0 ? 1 : -1); - diffIndex = i; - } - } - - if (t1 == t2) { /* same face => diffIndex != -1 */ - switch (t1) { - case Face.FRONT: - case Face.BACK: - var coef = (t1 == Face.FRONT ? 1 : -1); - if (diffIndex == 0) { this._rotateY(coef*diff, pos1[1]); } else { this._rotateX(coef*diff, pos1[0]); } - break; - - case Face.LEFT: - case Face.RIGHT: - var coef = (t1 == Face.LEFT ? 1 : -1); - if (diffIndex == 2) { this._rotateY(-coef*diff, pos1[1]); } else { this._rotateZ(coef*diff, pos1[2]); } - break; - - case Face.TOP: - case Face.BOTTOM: - var coef = (t1 == Face.TOP ? 1 : -1); - if (diffIndex == 0) { this._rotateZ(-coef*diff, pos1[2]); } else { this._rotateX(-coef*diff, pos1[0]); } - break; - } - return; - } - - switch (t1) { /* different face => same cube, diffIndex == 1 */ - case Face.FRONT: - case Face.BACK: - var coef = (t1 == Face.FRONT ? 1 : -1); - if (t2 == Face.LEFT) { this._rotateY(1 * coef, pos1[1]); } - if (t2 == Face.RIGHT) { this._rotateY(-1 * coef, pos1[1]); } - if (t2 == Face.TOP) { this._rotateX(1 * coef, pos1[0]); } - if (t2 == Face.BOTTOM) { this._rotateX(-1 * coef, pos1[0]); } - break; - - case Face.LEFT: - case Face.RIGHT: - var coef = (t1 == Face.LEFT ? 1 : -1); - if (t2 == Face.FRONT) { this._rotateY(-1 * coef, pos1[1]); } - if (t2 == Face.BACK) { this._rotateY(1 * coef, pos1[1]); } - if (t2 == Face.TOP) { this._rotateZ(1 * coef, pos1[2]); } - if (t2 == Face.BOTTOM) { this._rotateZ(-1 * coef, pos1[2]); } - break; - - case Face.TOP: - case Face.BOTTOM: - var coef = (t1 == Face.TOP ? 1 : -1); - if (t2 == Face.FRONT) { this._rotateX(-1 * coef, pos1[0]); } - if (t2 == Face.BACK) { this._rotateX(1 * coef, pos1[0]); } - if (t2 == Face.LEFT) { this._rotateZ(-1 * coef, pos1[2]); } - if (t2 == Face.RIGHT) { this._rotateZ(1 * coef, pos1[2]); } - break; - } - -} - -Rubik.prototype._rotateX = function(dir, layer) { - var cubes = []; - for (var i=0;i<Rubik.SIZE*Rubik.SIZE;i++) { - cubes.push(this._cubes[layer + i*Rubik.SIZE]); - } - this._rotateCubes(cubes, [dir, 0, 0]); -} - -Rubik.prototype._rotateY = function(dir, layer) { - var cubes = []; - for (var i=0;i<Rubik.SIZE;i++) { - for (var j=0;j<Rubik.SIZE;j++) { - cubes.push(this._cubes[j + layer*Rubik.SIZE + i*Rubik.SIZE*Rubik.SIZE]); - } - } - this._rotateCubes(cubes, [0, -dir, 0]); -} - -Rubik.prototype._rotateZ = function(dir, layer) { - var cubes = []; - var offset = layer * Rubik.SIZE * Rubik.SIZE; - for (var i=0;i<Rubik.SIZE*Rubik.SIZE;i++) { - cubes.push(this._cubes[offset+i]); - } - this._rotateCubes(cubes, [0, 0, dir]); -} - -Rubik.prototype._rotateCubes = function(cubes, rotation) { - var suffixes = ["X", "Y", ""]; - - var prefix = OZ.CSS3.getPrefix("transition"); - if (prefix === null) { - this._finalizeRotation(cubes, rotation); - } else { - var cb = function() { - OZ.Event.remove(e); - this._finalizeRotation(cubes, rotation); - } - var e = OZ.Event.add(document.body, "webkitTransitionEnd transitionend MSTransitionEnd oTransitionEnd", cb.bind(this)); - - var str = ""; - for (var i=0;i<3;i++) { - if (!rotation[i]) { continue; } - str = "rotate" + suffixes[i] + "(" + (90*rotation[i]) + "deg)"; - } - for (var i=0;i<cubes.length;i++) { cubes[i].setRotation(str); } - } - -} - -/** - * Remap colors - */ -Rubik.prototype._finalizeRotation = function(cubes, rotation) { - var direction = 0; - for (var i=0;i<3;i++) { - if (rotation[i]) { direction = rotation[i]; } - } - - if (rotation[0]) { direction *= -1; } /* FIXME wtf */ - - var half = Math.floor(Rubik.SIZE/2); - - for (var i=0;i<cubes.length;i++) { - var x = i % Rubik.SIZE - half; - var y = Math.floor(i / Rubik.SIZE) - half; - - var source = [y*direction + half, -x*direction + half]; - var sourceIndex = source[0] + Rubik.SIZE*source[1]; - - cubes[i].prepareColorChange(cubes[sourceIndex], rotation); - } - - for (var i=0;i<cubes.length;i++) { cubes[i].commitColorChange(); } - - setTimeout(function() { - if (this._help.b) { - this._help.b.style.opacity = 0; - this._help.b = null; - } - - this.dispatch("rotated"); - }.bind(this), 100); -} - -Rubik.prototype._build = function() { - for (var z=0;z<Rubik.SIZE;z++) { - for (var y=0;y<Rubik.SIZE;y++) { - for (var x=0;x<Rubik.SIZE;x++) { - var cube = new Cube([x, y, z]); - this._cubes.push(cube); - - if (z == 0) { cube.setFace(Face.FRONT, "red"); } - if (z == 2) { cube.setFace(Face.BACK, "blue"); } - - if (x == 0) { cube.setFace(Face.LEFT, "green"); } - if (x == 2) { cube.setFace(Face.RIGHT, "yellow"); } - - if (y == 0) { cube.setFace(Face.TOP, "cyan"); } - if (y == 2) { cube.setFace(Face.BOTTOM, "teal"); } - this._node.appendChild(cube.getNode()); - } - } - } - -} |