diff options
Diffstat (limited to 'public')
64 files changed, 1590 insertions, 1828 deletions
diff --git a/public/assets/img/palette.gif b/public/assets/img/palette.gif Binary files differnew file mode 100644 index 0000000..39c134f --- /dev/null +++ b/public/assets/img/palette.gif diff --git a/public/assets/javascripts/app.js b/public/assets/javascripts/app.js index 3d0d3c4..1419d1d 100644 --- a/public/assets/javascripts/app.js +++ b/public/assets/javascripts/app.js @@ -17,8 +17,6 @@ else { var scene, cam, map; -var viewHeight = window.viewHeight || 150 - var app = new function(){} app.mode = { editor: false, builder: false } @@ -99,4 +97,11 @@ app.position = function(obj){ return pos } +app.defaults = { + viewHeight: window.viewHeight = 186, + units: app.units = "ft", + footResolution: 36, + meterResolution: 100, +} + document.addEventListener('DOMContentLoaded', app.init) diff --git a/public/assets/javascripts/environments/app.js b/public/assets/javascripts/environments/app.js deleted file mode 100644 index cdc104b..0000000 --- a/public/assets/javascripts/environments/app.js +++ /dev/null @@ -1,28 +0,0 @@ -var scrubber, fish, floor - -var environment = new function(){} -environment.init = function(){ - - scene.camera.move({ - "x": 0, - "y": 0, - "z": 0, - "rotationX": 0.085, - "rotationY": 0.025 - }) - map && map.zoom(3.00) && map.recenter() - - // - // intro floor, models, etc - -} - - -environment.update = function(t){ - - // add continuous animations and stuff here - - map && map.update() - -} - diff --git a/public/assets/javascripts/environments/tableaux/_empty.js b/public/assets/javascripts/environments/tableaux/_empty.js deleted file mode 100644 index b69fa78..0000000 --- a/public/assets/javascripts/environments/tableaux/_empty.js +++ /dev/null @@ -1,32 +0,0 @@ -/* - -MX.Tableaux.Foo = MX.Tableau.extend({ - - init: function (opt) { - - this.opt = opt = defaults(opt, { - width: 100, - height: 100, - depth: 100, - x: 0, - y: 0, - z: 0, - rotationY: 0, - rotationX: 0, - scale: 1, - }) - - }, - - animate: function() { - }, - - show: function(){ - }, - - hide: function(){ - }, - -}) - -*/ diff --git a/public/assets/javascripts/environments/tableaux/columns.js b/public/assets/javascripts/environments/tableaux/columns.js deleted file mode 100644 index e961315..0000000 --- a/public/assets/javascripts/environments/tableaux/columns.js +++ /dev/null @@ -1,36 +0,0 @@ -MX.Tableaux.Columns = MX.Tableau.extend({ - - init: function (opt) { - - this.opt = opt = defaults(opt, { - width: 10, - height: 10, - depth: 10, - x: 0, - y: 0, - z: 0, - rotationY: 0, - rotationX: 0, - scale: 1, - count: 3, - spacingX: 0, - spacingZ: 100, - }) - - for (var i = 0; i < opt.count; i++) { - var scalebox = new MX.ScaleBox({ - "width": opt.width, - "height": opt.height, - "depth": opt.depth, - "x": opt.x + opt.spacingX * i, - "y": opt.y, - "z": opt.z + opt.spacingZ * i, - "color": opt.color, - "sides": "top bottom left right front back" - }); - scene.add(scalebox) - } - - } - -}) diff --git a/public/assets/javascripts/environments/tableaux/columns_circle.js b/public/assets/javascripts/environments/tableaux/columns_circle.js deleted file mode 100644 index 1816e51..0000000 --- a/public/assets/javascripts/environments/tableaux/columns_circle.js +++ /dev/null @@ -1,42 +0,0 @@ -MX.Tableaux.ColumnsCircle = MX.Tableau.extend({ - - init: function (opt) { - - this.opt = opt = defaults(opt, { - width: 10, - height: 10, - depth: 10, - radius: 10, - theta: 0, - skip: 0, - x: 0, - y: 0, - z: 0, - rotationY: 0, - rotationX: 0, - scale: 1, - count: 3, - }) - - var scalebox, theta - var radius = opt.radius - - for (var i = opt.skip; i < opt.count; i++) { - theta = i/opt.count * TWO_PI + opt.theta - scalebox = new MX.ScaleBox({ - "width": opt.width, - "height": opt.height, - "depth": opt.depth, - "x": opt.x + sin(theta) * radius, - "y": opt.y, - "z": opt.z + cos(theta) * radius, - "rotationY": PI - theta, - "color": opt.color, - "sides": "top bottom left right front back" - }); - scene.add(scalebox) - } - - } - -}) diff --git a/public/assets/javascripts/environments/tableaux/columns_split.js b/public/assets/javascripts/environments/tableaux/columns_split.js deleted file mode 100644 index b9981d6..0000000 --- a/public/assets/javascripts/environments/tableaux/columns_split.js +++ /dev/null @@ -1,63 +0,0 @@ -MX.Tableaux.ColumnsSplit = MX.Tableau.extend({ - - init: function (opt) { - - this.opt = opt = defaults(opt, { - width: 100, - height: 100, - depth: 100, - norm: 0.5, - gap: 5, - x: 0, - y: 0, - z: 0, - rotationY: 0, - scale: 1, - count: 1, - }) - - opt.colorBottom = opt.colorBottom || opt.color - - if ( ! (opt.norm instanceof Array) ) { - opt.norm = [ opt.norm, opt.norm ] - } - - var norm, spacingX, spacingZ, scalebox - - for (var i = 0; i < opt.count; i++) { - - norm = lerp( i/(opt.count-1), opt.norm[0], opt.norm[1] ) - - spacingX = opt.spacingX * i - spacingZ = opt.spacingZ * i - - scalebox = new MX.ScaleBox({ - "width": opt.width, - "height": opt.height * norm, - "depth": opt.depth, - "x": opt.x + spacingX, - "y": opt.y + opt.gap, - "z": opt.z + spacingZ, - "color": opt.color, - "sides": "top bottom left right front back", - "rotationY": opt.rotationY, - }); - scene.add(scalebox) - - scalebox = new MX.ScaleBox({ - "width": opt.width, - "height": opt.height * (1 - norm), - "depth": opt.depth, - "x": opt.x + spacingX, - "y": opt.y - opt.height * (1 - norm) - opt.gap, - "z": opt.z + spacingZ, - "color": opt.colorBottom, - "sides": "top bottom left right front back", - "rotationY": opt.rotationY, - }); - scene.add(scalebox) - } - - } - -}) diff --git a/public/assets/javascripts/map/map.js b/public/assets/javascripts/map/map.js deleted file mode 100644 index a90963f..0000000 --- a/public/assets/javascripts/map/map.js +++ /dev/null @@ -1,337 +0,0 @@ - -MX.Map = function(){ - var base = this; - - var parent = document.querySelector("#map") - var canvas = document.createElement("canvas") - var ctx = canvas.getContext("2d") - var w, h - - var visible = parent.style.display == "block" - if (visible) resize() - - var center = {x:0,y:0} - var gridSpace; - var zoom = 3.0 - - var gridStroke = '#ddd' - var boxFill = '#fff' - var boxStroke = '#000' - var playerColor = '#888' - - var xmin, xmax, ymin, ymax, xpos, ypos, scale, side; - - var tube = base.tube = new Tube () - - this.zoom = function(n){ if (n) zoom = n; return zoom } - this.recenter = function(){ center.x = cam.x; center.y = cam.z } - - function resize(){ - var rect = parent.getBoundingClientRect() - w = canvas.width = ~~rect.width - h = canvas.height = ~~rect.height - } - - this.on = function(){ - base.tube.on.apply(base.tube, arguments) - } - this.off = function(){ - base.tube.off.apply(base.tube, arguments) - } - - this.update = function(){ - if (! visible) return; - this.draw() - } - - this.bounds = function(){ - gridSpace = pow(10, ~~(zoom-0.25) + 0.25) - side = Math.pow(10, zoom+1) - scale = w / side - xpos = center.x // -cam.x - ypos = center.y // cam.z - - xmin = side/-2 - xpos - xmax = side/2 - xpos - ymin = side/-2 - ypos - ymax = side/2 - ypos - } - - this.draw = function(){ - ctx.clearRect(0,0,w,h) - - ctx.fillStyle = "#fff" - ctx.fillRect(0,0,w,h) - this.bounds() - this.grid() - this.boxes() - this.player() - } - - this.grid = function(){ - ctx.strokeStyle = gridStroke - ctx.lineWidth = 1 - ctx.fillStyle = "transparent" - - var x0 = norm(0, xmin, xmax) - var y0 = norm(0, ymin, ymax) - - var xg = norm(gridSpace, xmin, xmax) - var yg = norm(gridSpace, ymin, ymax) - - var xgw = (xg-x0) - - var xmod = mod(x0, xgw) - var ymod = mod(y0, xgw) - - var xend = 1 + xgw - var yend = h/w + xgw - - var xline, yline; - for (var x = -xmod; x < xend; x += xgw) { - xline = x * w - line(xline, 0, xline, h) - } - for (var y = -ymod; y < yend; y += xgw) { - yline = y * w - line(0, yline, w, yline) - } - - function line(x0,y0,x1,y1) { - ctx.beginPath() - ctx.moveTo(x0, y0) - ctx.lineTo(x1, y1) - ctx.stroke() - } - } - this.player = function(){ - ctx.save() - - ctx.translate(~~(w/2),~~(h/2)); - ctx.lineWidth = 0.5 - var tx = ((-xpos) * scale), - ty = ((-ypos) * scale); - ctx.translate(tx, ty) - - var obj_scale = (1) * scale - - var tx = ~~((cam.x) * obj_scale), - ty = ~~((cam.z) * obj_scale); - ctx.translate(-tx, ty) - ctx.rotate(-cam.rotationY) - - var radius = 5 - - ctx.fillStyle = playerColor; - - ctx.beginPath(); - ctx.arc(0, 0, radius, 0, 2*Math.PI, false); - ctx.fill(); - - ctx.beginPath(); - ctx.moveTo(0,0) - ctx.lineTo(-radius,0) - ctx.lineTo(0,radius*3) - ctx.lineTo(radius,0) - ctx.moveTo(0,0) - ctx.fill() - - ctx.fillStyle = "transparent" - ctx.restore() - } - - this.boxes = function(){ - - ctx.save() - ctx.translate(~~(w/2),~~(h/2)); - ctx.lineWidth = 0.5 - var tx = ((-xpos) * scale), - ty = ((-ypos) * scale); - ctx.translate(tx, ty) - - scene.inner.children.forEach(function(obj){ - if (obj.type == "BoxDimensions" || obj.type == "ScaleBox") { - - ctx.save() - ctx.fillStyle = obj.color - ctx.strokeStyle = "#222" - - var obj_scale = (obj.scale || 1) * scale - - var tx = ~~((obj.x) * scale), - ty = ~~((obj.z) * scale); - ctx.translate(-tx, ty) - ctx.rotate(-obj.rotationY) - - var ww = ~~(obj.width/2 * obj_scale) - var hh = ~~(obj.depth/2 * obj_scale) - ctx.beginPath(); - ctx.moveTo(ww, hh) - - ctx.lineTo(ww, -hh) - ctx.lineTo(-ww, -hh) - ctx.lineTo(-ww, hh) - ctx.closePath() - ctx.fill() - ctx.stroke() - ctx.restore() - } - if (obj.type == "Image" || obj.type == "Cutout") { - ctx.save() - ctx.strokeStyle = "#444" - - var obj_scale = (obj.scale || 1) * scale - - var tx = ~~((obj.x) * scale), - ty = ~~((obj.z) * scale); - ctx.translate(-tx, ty) - ctx.rotate(-obj.rotationY) - - var ww = ~~(obj.width/2 * obj_scale) - ctx.beginPath(); - ctx.moveTo(ww, 0) - ctx.lineTo(-ww, 0) - ctx.closePath() - ctx.stroke() - ctx.restore() - } - }) - ctx.restore() - } - - - var dragging = false, mx = 0, my = 0, mdx = 0, mdy = 0, cx, cy, - creating = false, moving = false; - - function positionFromMouse(e) { - var rect = canvas.getBoundingClientRect() - cx = center.x - cy = center.y - mx = e.pageX - rect.left - my = e.pageY - rect.top - mdx = (mx - w/2) / scale + cx - mdy = (my - h/2) / scale + cy - } - - canvas.addEventListener("mousedown", function(e){ - e.stopPropagation() - dragging = true - - positionFromMouse(e) - - if (e.shiftKey) { - creating = true - } - - hud.update( mdx, mdy ) - - base.tube("mousedown", e, -mdx, mdy) - }) - document.addEventListener("mousemove", function(e){ - if (dragging) { - e.stopPropagation() - - var rect = canvas.getBoundingClientRect() - var mnx = e.pageX - rect.left - var mny = e.pageY - rect.top - - mdx = (mnx - mx) / scale - mdy = (mny - my) / scale - - if (creating) { - hud.update( mdx, mdy ) - } - else if (moving) { - cam.x = cx - mdx - cam.z = cy + mdy - } - else { - center.x = cx - mdx - center.y = cy - mdy - hud.update(center.x, center.y) - } - - base.tube("mousedrag", e, -mdx, mdy) - } - else { - positionFromMouse(e) - hud.update( mdx, mdy ) - base.tube("mousemove", e, -mdx, mdy) - } - }) - document.addEventListener("mouseup", function(e){ - creating = dragging = moving = false; - base.tube("mouseup", e) - }) - - canvas.addEventListener("contextmenu", function(e){ - e.preventDefault() - e.stopPropagation() - dragging = true - - positionFromMouse(e) - - moving = true - cx = cam.x = -mdx - cy = cam.z = mdy - - hud.update( mdx, mdy ) - - base.tube("contextmenu", e) - }) - - canvas.addEventListener( 'mousewheel', onDocumentMouseWheel, false ); - canvas.addEventListener( 'DOMMouseScroll', onDocumentMouseWheel, false); - function onDocumentMouseWheel (e) { - e.preventDefault() - e.stopPropagation() - var delta = 0 - - // WebKit - if ( event.wheelDeltaY ) { - delta = - event.wheelDeltaY * 0.0003; - } - // Opera / Explorer 9 - else if ( event.wheelDelta ) { - delta = - event.wheelDelta * 0.0003; - } - // Firefox - else if ( event.detail ) { - delta = event.detail * 0.01; - } - - if (! e.shiftKey) { - zoom += delta - } - - positionFromMouse(e) - base.tube("mousewheel", e, mdx, mdy, delta) - - map.update() - } - - window.addEventListener('resize', resize) - - this.toggle = function(){ - (visible = ! visible) ? base.show() : base.hide() - } - this.show = function(){ - parent.style.display = "block" - resize() - } - this.hide = function(){ - parent.style.display = "none" - } - - var hud = new function(){ - var el = document.querySelector("#map .hud") - this.update = function(){ - el.innerHTML = Array.prototype.slice.call(arguments,0).map(function(s){ return typeof s == "number" ? Math.round(s) : s }).join(" ") - } - } - hud.update() - - this.update() - document.querySelector("#map .el").appendChild(canvas) -} - diff --git a/public/assets/javascripts/map/map_editor.js b/public/assets/javascripts/map/map_editor.js deleted file mode 100644 index 754172b..0000000 --- a/public/assets/javascripts/map/map_editor.js +++ /dev/null @@ -1,102 +0,0 @@ -var editor = new function (){ - - var base = this; - - var cube = null - var cx, cy - - base.init = function(){ - map.on("mousedown", base.mousedown) - map.on("mousemove", base.mousemove) - map.on("mousedrag", base.mousedrag) - map.on("mouseup", base.mouseup) - map.on("mousewheel", base.mousewheel) - document.getElementById("export").addEventListener("keydown", base.stopPropagation) - document.getElementById("export").addEventListener("mousedown", base.stopPropagation) - document.getElementById("export").addEventListener("mousemove", base.stopPropagation) - document.getElementById("export").addEventListener("mouseup", base.stopPropagation) - window.addEventListener('keydown', base.keydown) - } - - base.mousedown = function(e,x,y) { - if (! e.shiftKey) return - cx = x - cy = y - cube = new MX.BoxDimensions({ - x: cx, - y: -10, - z: cy, - width: 1, - height: 1, - depth: 1, - borderWidth: 1, - borderColor: "#000", - color: "#fff" - }) - cube.persisted = false - scene.add( cube ); - } - - base.mousemove = function(e,x,y) { - } - - base.mousedrag = function(e,dx,dy) { - if (! cube) return - cube.x = cx + dx/2 - cube.z = cy + dy/2 - cube.setWidth( abs(dx) ) - cube.setDepth( abs(dy) ) - cube.setHeight( max( cube.width, cube.depth ) ) - cube.update() - } - - base.mouseup = function(e){ - cube = null - } - - base.mousewheel = function(e,x,z,delta){ - if (! e.shiftKey) return; - - scene.inner.children.some(function(s){ - if (s.contains(-x, null, z)) { - s.y += delta * 1000 - s.persisted = false - console.log(s.id) - return true - } - return false - }) - - } - - base.stopPropagation = function(e){ e.stopPropagation() } - - base.exportObjects = function(){ - var s = scene.inner.children - .filter(function(s){ return ! s.persisted }) - .map(function(s){ return s.toString() }) - .join("\n\n") - document.getElementById("export").value = s - } - - base.exportCamera = function(){ - var s = scene.camera.toString() - document.getElementById("export").value = s - console.log(s) - } - - base.keydown = function(e){ - switch (e.keyCode) { - - case 67: // c - base.exportCamera() - break; - - case 86: // v - base.exportObjects() - break; - - } - } - -} diff --git a/public/assets/javascripts/mx/extensions/mx.movements.js b/public/assets/javascripts/mx/extensions/mx.movements.js index f176e8b..191088f 100644 --- a/public/assets/javascripts/mx/extensions/mx.movements.js +++ b/public/assets/javascripts/mx/extensions/mx.movements.js @@ -1,6 +1,6 @@ -MX.Movements = function (cam, viewHeight) { +MX.Movements = function (cam) { var moveForward, moveLeft, diff --git a/public/assets/javascripts/mx/mx.js b/public/assets/javascripts/mx/mx.js index 496aec0..6b36392 100644 --- a/public/assets/javascripts/mx/mx.js +++ b/public/assets/javascripts/mx/mx.js @@ -452,6 +452,16 @@ var MX = MX || (function (undefined) { return this }, + move: function(ops){ + var layer = this + layer.ops = defaults(ops, layer.ops) + for (var i in ops) { + layer[i] = ops[i] + } + layer.dirty = true + layer.update() + }, + onTransitionEnd: function (callback) { this.cancelTransitionEnd() var el = this.el diff --git a/public/assets/javascripts/mx/mx.minimap.js b/public/assets/javascripts/mx/mx.minimap.js deleted file mode 100644 index 252305c..0000000 --- a/public/assets/javascripts/mx/mx.minimap.js +++ /dev/null @@ -1,211 +0,0 @@ -MX.Minimap = function () { - var canvas = document.createElement("canvas") - var ctx = canvas.getContext("2d") - var w = canvas.width = 200 - var h = canvas.height = 200 - - var gridSpace; - var zoom = 2.7 - - var gridStroke = '#ddd' - var boxFill = '#fff' - var boxStroke = '#000' - var playerColor = '#888' - - var xmin, xmax, ymin, ymax, xpos, ypos, scale, side; - - this.update = function(){ - this.draw() - } - - this.bounds = function(){ - gridSpace = Math.pow(10, ~~(zoom-0.5)+0.5) - side = Math.pow(10, zoom+1) - scale = w / side - xpos = -cam.x - ypos = cam.z - - xmin = side/-2 - xpos - xmax = side/2 - xpos - ymin = side/-2 - ypos - ymax = side/2 - ypos - } - - this.draw = function(){ - ctx.clearRect(0,0,w,h) - - ctx.fillStyle = "#fff" - ctx.fillRect(0,0,w,h) - this.bounds() - this.grid() - this.boxes() - this.player() - } - - this.grid = function(){ - ctx.strokeStyle = gridStroke - ctx.lineWidth = 1 - ctx.fillStyle = "transparent" - - var xmod = xmin-(xmin % gridSpace) - var ymod = ymin-(ymin % gridSpace) - - for (var x = xmin; x < xmax+gridSpace; x += gridSpace) { - var xline = (x-xmod) * scale - line(xline, 0, xline, h) - } - for (var y = ymin; y < ymax+gridSpace; y += gridSpace) { - var yline = (y-ymod) * scale - line(0, yline, w, yline) - } - - function line(x0,y0,x1,y1) { - ctx.beginPath() - ctx.moveTo(x0, y0) - ctx.lineTo(x1, y1) - ctx.stroke() - } - } - this.player = function(){ - ctx.save() - - ctx.translate(~~(w/2),~~(h/2)); - ctx.rotate(-cam.rotationY) - - var radius = 5 - - ctx.fillStyle = playerColor; - - ctx.beginPath(); - ctx.arc(0, 0, radius, 0, 2*Math.PI, false); - ctx.fill(); - - ctx.beginPath(); - ctx.moveTo(0,0) - ctx.lineTo(-radius,0) - ctx.lineTo(0,radius*3) - ctx.lineTo(radius,0) - ctx.moveTo(0,0) - ctx.fill() - - ctx.fillStyle = "transparent" - ctx.restore() - } - - this.boxes = function(){ - - ctx.save() - ctx.translate(~~(w/2),~~(h/2)); - ctx.lineWidth = 0.5 - var tx = ((-xpos) * scale), - ty = ((-ypos) * scale); - ctx.translate(tx, ty) - - scene.inner.children.forEach(function(obj){ - if (obj.type == "BoxDimensions") { - - ctx.save() - ctx.fillStyle = obj.color - ctx.strokeStyle = obj.borderColor - - var obj_scale = (obj.scale || 1) * scale - - var tx = ~~((obj.x) * obj_scale), - ty = ~~((obj.z) * obj_scale); - ctx.translate(-tx, ty) - ctx.rotate(-obj.rotationY) - - var ww = ~~(obj.width/2 * obj_scale) - var hh = ~~(obj.depth/2 * obj_scale) - ctx.beginPath(); - ctx.moveTo(ww, hh) - - ctx.lineTo(ww, -hh) - ctx.lineTo(-ww, -hh) - ctx.lineTo(-ww, hh) - ctx.closePath() - ctx.fill() - ctx.stroke() - ctx.restore() - } - if (obj.type == "Image") { - - ctx.save() - ctx.strokeStyle = "#444" - - var obj_scale = (obj.scale || 1) * scale - - var tx = ~~((obj.x) * obj_scale), - ty = ~~((obj.z) * obj_scale); - ctx.translate(-tx, ty) - ctx.rotate(-obj.rotationY) - - var ww = ~~(obj.width/2 * obj_scale) - ctx.beginPath(); - ctx.moveTo(ww, 0) - ctx.lineTo(-ww, 0) - ctx.closePath() - ctx.stroke() - ctx.restore() - } - }) - ctx.restore() - } - - var dragging = false, mx = 0, my = 0, mdx = 0, mdy = 0, cx, cy; - canvas.addEventListener("mousedown", function(e){ - e.stopPropagation() - var rect = canvas.getBoundingClientRect() - dragging = true; - mx = e.pageX - rect.left - my = e.pageY - rect.top - mdx = (mx - w/2) / scale - mdy = (my - h/2) / scale - cx = cam.x // -= mdx - cy = cam.z // += mdy - - minimap.update() - }) - document.addEventListener("mousemove", function(e){ - if (dragging) { - e.stopPropagation() - var rect = canvas.getBoundingClientRect() - var mnx = e.pageX - rect.left - var mny = e.pageY - rect.top - mdx = (mnx - mx) / scale - mdy = (mny - my) / scale - - cam.x = cx + mdx - cam.z = cy - mdy - minimap.update() - } - }) - document.addEventListener("mouseup", function(e){ - dragging = false; - }) - - canvas.addEventListener( 'mousewheel', onDocumentMouseWheel, false ); - canvas.addEventListener( 'DOMMouseScroll', onDocumentMouseWheel, false); - function onDocumentMouseWheel (e) { - e.preventDefault() - e.stopPropagation() - // WebKit - if ( event.wheelDeltaY ) { - zoom -= event.wheelDeltaY * 0.0003; - } - // Opera / Explorer 9 - else if ( event.wheelDelta ) { - zoom -= event.wheelDelta * 0.0003; - } - // Firefox - else if ( event.detail ) { - zoom += event.detail * 0.01; - } - minimap.update() - } - - this.draw() - document.querySelector("#minimap .el").appendChild(canvas) - - return this; -}
\ No newline at end of file diff --git a/public/assets/javascripts/mx/primitives/mx.box.js b/public/assets/javascripts/mx/primitives/mx.box.js deleted file mode 100644 index dfe3f5e..0000000 --- a/public/assets/javascripts/mx/primitives/mx.box.js +++ /dev/null @@ -1,62 +0,0 @@ -MX.Box = MX.Object3D.extend({ - - // this will be called within the contructor - init: function (size, color, borderColor) { - - this.type = "Box" - - size = size || 100 - color = color || 'rgba(0, 255, 122, .1)' - borderColor = borderColor || '#0f3' - - // an Object3D's associated DOM node is the "el" property - this.el.classList.add('box') - - var angle = MX.rotationUnit === 'deg' ? 90 : (Math.PI / 2) - - var top = this.top = new MX.Object3D('.face') - top.rotationX = angle - top.y = size / 2 - - var bottom = this.bottom = new MX.Object3D('.face') - bottom.rotationX = -angle - bottom.y = -size / 2 - - var left = this.left = new MX.Object3D('.face') - left.rotationY = -angle - left.x = -size / 2 - - var right = this.right = new MX.Object3D('.face') - right.rotationY = angle - right.x = size / 2 - - var front = this.front = new MX.Object3D('.face') - front.z = -size / 2 - - var back = this.back = new MX.Object3D('.face') - back.rotationY = angle * 2 - back.z = size / 2 - - // adding children, must also be instances of Object3D - this.add(top, bottom, left, right, front, back) - - this.children.forEach(function (face) { - face.width = size - 2 - face.height = size - 2 - face.el.style.backgroundColor = color - face.el.style.border = '1px solid ' + borderColor - }) - - // this applies the updated CSS style - // required for any change to take effect - // when a parent object's update() is called - // all its children will be updated as well - this.update() - - // if this object's children won't move by themselves - this.updateChildren = false - } - - // other properties will be mixed into the prototype of the new constructor - -})
\ No newline at end of file diff --git a/public/assets/javascripts/mx/primitives/mx.boxDimensions.js b/public/assets/javascripts/mx/primitives/mx.boxDimensions.js deleted file mode 100644 index 1d457ae..0000000 --- a/public/assets/javascripts/mx/primitives/mx.boxDimensions.js +++ /dev/null @@ -1,154 +0,0 @@ -MX.BoxDimensions = MX.Object3D.extend({ - - // this will be called within the contructor - init: function (opt) { - - var base = this - - this.type = "BoxDimensions" - - var id = this.id = opt.id || _.uniqueId() - this.x = opt.x || 0 - this.y = opt.y || 0 - this.z = opt.z || 0 - // this.scale = opt.scale || 1 - var scale = opt.scale || 1 - this.rotationX = opt.rotationX || 0 - this.rotationY = opt.rotationY || 0 - this.rotationZ = opt.rotationZ || 0 - var width = this.width = opt.width || 100 - var height = this.height = opt.height || 100 - var depth = this.depth = opt.depth || 100 - var color = this.color = opt.color || 'rgba(0, 255, 122, .1)' - var backgroundImage = this.backgroundImage = opt.backgroundImage; - var borderColor = this.borderColor = opt.borderColor || '#0f3' - var borderWidth = this.borderWidth = typeof opt.borderWidth !== 'undefined' ? opt.borderWidth : 3; - var borderRadius = this.borderRadius = typeof opt.borderRadius !== 'undefined' ? opt.borderRadius : undefined; - var sides = this.sides = opt.sides || "top bottom left right front back" - var className = this.className = opt.className || null - - // an Object3D's associated DOM node is the "el" property - this.el.classList.add('box') - - var angle = MX.rotationUnit === 'deg' ? 90 : (Math.PI / 2) - - this.top = this.bottom = this.left = this.right = this.front = this.back = null - if (-1 != sides.indexOf("top")) { - var top = this.top = new MX.Object3D('.face.top') - top.rotationX = angle - top.width = width - top.height = depth - top.y = height * scale - top.scale = scale - this.add(top) - } - if (-1 != sides.indexOf("bottom")) { - var bottom = this.bottom = new MX.Object3D('.face.bottom') - bottom.rotationX = -angle - bottom.width = width - bottom.height = depth - bottom.y = 0 - bottom.scale = scale - this.add(bottom) - } - if (-1 != sides.indexOf("left")) { - var left = this.left = new MX.Object3D('.face.left') - left.rotationY = -angle - left.width = depth - left.height = height - left.x = -width/2 * scale - left.y = height/2 * scale - left.scale = scale - this.add(left) - } - if (-1 != sides.indexOf("right")) { - var right = this.right = new MX.Object3D('.face.right') - right.rotationY = angle - right.width = depth - right.height = height - right.x = width/2 * scale - right.y = height/2 * scale - right.scale = scale - this.add(right) - } - if (-1 != sides.indexOf("front")) { - var front = this.front = new MX.Object3D('.face.front') - front.width = width - front.height = height - front.z = -depth/2 * scale - front.y = height/2 * scale - front.scale = scale - this.add(front) - } - if (-1 != sides.indexOf("back")) { - var back = this.back = new MX.Object3D('.face.back') - back.width = width - back.height = height - back.rotationY = angle * 2 - back.z = depth/2 * scale - back.y = height/2 * scale - back.scale = scale - this.add(back) - } - - this.children.forEach(function (face) { - if (borderRadius) { - face.el.style.borderRadius = borderRadius + "px" - } - if (className) { - face.el.classList.add(className) - } - else { - if (backgroundImage) { - face.el.style.backgroundImage = "url(" + backgroundImage + ")" - } - else if (color) { - face.el.style.backgroundColor = color - } - if (borderWidth) { - face.el.style.border = borderWidth + 'px solid ' + borderColor - } - } - }) - - // bottom.el.style.border = "0" - - // this applies the updated CSS style - // required for any change to take effect - // when a parent object's update() is called - // all its children will be updated as well - this.update() - - // if this object's children won't move by themselves - this.updateChildren = true - - this.setWidth = function(w){ - base.width = top.width = bottom.width = front.width = back.width = w - left.x = -w/2 - right.x = w/2 - base.dirty = true - } - this.setHeight = function(h){ - base.height = left.height = right.height = front.height = back.height = h - bottom.y = 0 - left.y = right.y = front.y = back.y = h/2 - top.y = h - base.dirty = true - } - this.setDepth = function(d){ - base.depth = top.height = bottom.height = left.width = right.width = d - front.z = -d/2 - back.z = d/2 - base.dirty = true - } - - }, - - toString: function(){ - var params = "id width height depth x y z rotationX rotationY scale color borderColor borderWidth backgroundImage borderRadius sides".split(" ") - return this.__toString(params) - }, - - // other properties will be mixed into the prototype of the new constructor - -})
\ No newline at end of file diff --git a/public/assets/javascripts/mx/primitives/mx.coords.js b/public/assets/javascripts/mx/primitives/mx.coords.js deleted file mode 100644 index 80b148c..0000000 --- a/public/assets/javascripts/mx/primitives/mx.coords.js +++ /dev/null @@ -1,61 +0,0 @@ -MX.Coords = (function () { - - var colors = { - x: '#f33', - y: '#3f3', - z: '#66f' - } - - var Axis = MX.Object3D.extend({ - init: function (axis, size) { - - var label = document.createElement('span') - label.textContent = axis.toUpperCase() - label.style.position = 'absolute' - label.style.right = '0px' - label.style.bottom = '3px' - label.style.fontSize = Math.round(size / 10) + 'px' - this.el.appendChild(label) - - var faceA = new MX.Object3D(), - faceB = new MX.Object3D() - faceA.rotationX = 90 - this.add(faceA, faceB) - - this.el.style.color = - faceA.el.style.backgroundColor = - faceB.el.style.backgroundColor = colors[axis] - - this.width = - faceA.width = - faceB.width = size - - this.height = - faceA.height = - faceB.height = Math.round(size / 100) - - var angle = MX.rotationUnit === 'deg' ? 90 : (Math.PI / 2) - - if (axis === 'y') { - this.rotationZ = -angle - } else if (axis === 'z') { - this.rotationY = angle - } - } - }) - - var Coords = MX.Object3D.extend({ - init: function (size) { - size = size || 100 - var x = new Axis('x', size), - y = new Axis('y', size), - z = new Axis('z', size) - this.add(x, y, z) - this.update() - this.updateChildren = false - } - }) - - return Coords - -})()
\ No newline at end of file diff --git a/public/assets/javascripts/mx/primitives/mx.cutout.js b/public/assets/javascripts/mx/primitives/mx.cutout.js deleted file mode 100644 index 9d9043f..0000000 --- a/public/assets/javascripts/mx/primitives/mx.cutout.js +++ /dev/null @@ -1,66 +0,0 @@ -MX.Cutout = MX.Object3D.extend({ - init: function (ops) { - - this.type = "Cutout" - - var layer = this - layer.width = 0 - layer.height = 0 - - if (ops.src) this.loadTexture(ops) - - if (ops.texture) { - } - else if (ops.classname) { - layer.el.classList.add(ops.classname) - } - else { - } - layer.el.style.backgroundRepeat = 'no-repeat' - - this.dirty = true - this.updateChildren = true - this.update() - }, - - loadTexture: function(ops){ - var layer = this - var image = new Image() - var pattern = ops.pattern - var texture = ops.texture - - image.onload = function(){ - var canvas = document.createElement("canvas") - var ctx = canvas.getContext('2d') - - layer.width = canvas.width = image.naturalWidth - layer.height = canvas.height = image.naturalHeight - - ctx.drawImage(image, 0, 0, canvas.width, canvas.height) - ctx.globalCompositeOperation = "source-in" - - if (texture) { - ctx.fillStyle = ctx.createPattern(texture, 'repeat') - ctx.fillRect(0, 0, canvas.width, canvas.height) - } - if (pattern) { - ctx.fillStyle = ctx.createPattern(pattern, 'repeat') - ctx.fillRect(0, 0, canvas.width, canvas.height) - } - - layer.scale = ops.scale || 1 - layer.x = ops.x || 0 - layer.y = (ops.y || 0) + layer.height/2 + 1 - layer.z = ops.z || 0 - layer.rotationX = ops.rotationX || 0 - layer.rotationY = ops.rotationY || 0 - layer.el.appendChild(canvas) - - layer.el.classList.add('image') - ops.className && layer.el.classList.add(ops.className) - layer.dirty = true - layer.update() - } - image.src = ops.src; - } -}) diff --git a/public/assets/javascripts/mx/primitives/mx.face.js b/public/assets/javascripts/mx/primitives/mx.face.js deleted file mode 100644 index ac47ab4..0000000 --- a/public/assets/javascripts/mx/primitives/mx.face.js +++ /dev/null @@ -1,41 +0,0 @@ -MX.Face = MX.Object3D.extend({ - - // this will be called within the contructor - init: function (size, color, borderColor) { - - size = size || 100 - color = color || 'rgba(0, 255, 122, .1)' - borderColor = borderColor || '#0f3' - - // an Object3D's associated DOM node is the "el" property - this.el.classList.add('face') - - var angle = MX.rotationUnit === 'deg' ? 90 : (Math.PI / 2) - - var top = this.top = new MX.Object3D('.face') - top.rotationX = angle - top.y = size / 2 - - // adding children, must also be instances of Object3D - this.add(top) - - this.children.forEach(function (face) { - face.width = size - 2 - face.height = size - 2 - face.el.style.backgroundColor = color - face.el.style.border = '1px solid ' + borderColor - }) - - // this applies the updated CSS style - // required for any change to take effect - // when a parent object's update() is called - // all its children will be updated as well - this.update() - - // if this object's children won't move by themselves - this.updateChildren = false - } - - // other properties will be mixed into the prototype of the new constructor - -}) diff --git a/public/assets/javascripts/mx/primitives/mx.image.js b/public/assets/javascripts/mx/primitives/mx.image.js index e36c857..278fa1e 100644 --- a/public/assets/javascripts/mx/primitives/mx.image.js +++ b/public/assets/javascripts/mx/primitives/mx.image.js @@ -2,39 +2,28 @@ MX.Image = MX.Object3D.extend({ init: function (ops) { this.type = "Image" - - var layer = this - layer.width = 0 - layer.height = 0 - layer.x = ops.x || 0 - layer.y = ops.y || 0 - layer.z = ops.z || 0 - layer.scale = ops.scale || 1 - layer.backface = ops.backface || false - layer.media = ops.media + this.media = ops.media + this.width = 0 + this.height = 0 + this.x = ops.x || 0 + this.y = ops.y || 0 + this.z = ops.z || 0 + this.scale = ops.scale || 1 + this.backface = ops.backface || false - if (layer.backface) { - layer.el.classList.add("backface-visible") - } + ops.className && this.el.classList.add(ops.className) + this.backface && this.el.classList.add("backface-visible") + this.el.classList.add("image") - if (ops.src) { - this.loadTexture(ops) - } + this.el.style.backgroundRepeat = 'no-repeat' - if (ops.className) { - layer.el.classList.add(ops.className) - } - layer.el.style.backgroundRepeat = 'no-repeat' - - this.dirty = true - this.updateChildren = true - this.update() + this.load(ops) }, - loadTexture: function(ops){ + load: function(ops){ var layer = this layer.ops = defaults(ops, layer.ops) - console.log(layer.ops.y, layer.y) + var image = new Image() image.onload = function(){ layer.scale = layer.ops.scale || 1 @@ -53,20 +42,5 @@ MX.Image = MX.Object3D.extend({ } image.src = ops.src; }, - - move: function(ops){ - var layer = this - layer.ops = defaults(ops, layer.ops) - for (var i in ops) { - layer[i] = ops[i] - } - layer.dirty = true - layer.update() - }, - - toString: function(){ - var params = "id src width height depth x y z rotationX rotationY rotationZ scale".split(" ") - return this.__toString(params) - }, }) diff --git a/public/assets/javascripts/mx/primitives/mx.scaleBox.js b/public/assets/javascripts/mx/primitives/mx.scaleBox.js deleted file mode 100644 index f635345..0000000 --- a/public/assets/javascripts/mx/primitives/mx.scaleBox.js +++ /dev/null @@ -1,140 +0,0 @@ -MX.ScaleBox = MX.Object3D.extend({ - - // this will be called within the contructor - init: function (opt) { - - var base = this - - this.type = "ScaleBox" - - var id = this.id = opt.id || _.uniqueId() - this.x = opt.x || 0 - this.y = opt.y || 0 - this.z = opt.z || 0 - this.rotationX = opt.rotationX || 0 - this.rotationY = opt.rotationY || 0 - this.rotationZ = opt.rotationZ || 0 - var scale = this.scale = opt.scale || 1 - var width = this.width = scale * (opt.width || 100) - var height = this.height = scale * (opt.height || 100) - var depth = this.depth = scale * (opt.depth || 100) - var color = this.color = opt.color || 'rgba(0, 255, 122, .1)' - var sides = this.sides = opt.sides || "top bottom left right front back" - - // an Object3D's associated DOM node is the "el" property - this.el.classList.add('box') - - var angle = MX.rotationUnit === 'deg' ? 90 : (Math.PI / 2) - - var top = this.top = new MX.Object3D('.face.top') - top.rotationX = angle - top.width = 1 - top.height = 1 - top.scaleX = width - top.scaleY = 1 - top.scaleZ = depth - top.y = height - - var bottom = this.bottom = new MX.Object3D('.face.bottom') - bottom.rotationX = -angle - bottom.width = 1 - bottom.height = 1 - bottom.scaleX = width - bottom.scaleY = 1 - bottom.scaleZ = depth - bottom.y = 0 - - var left = this.left = new MX.Object3D('.face.left') - left.rotationY = -angle - left.width = 1 - left.height = 1 - left.scaleX = 1 - left.scaleY = height - left.scaleZ = depth - left.x = -width/2 - left.y = height/2 - - var right = this.right = new MX.Object3D('.face.right') - right.rotationY = angle - right.width = 1 - right.height = 1 - right.scaleX = 1 - right.scaleY = height - right.scaleZ = depth - right.x = width/2 - right.y = height/2 - - var front = this.front = new MX.Object3D('.face.front') - front.width = 1 - front.height = 1 - front.scaleX = width - front.scaleY = height - front.scaleZ = 1 - front.z = -depth/2 - front.y = height/2 - - var back = this.back = new MX.Object3D('.face.back') - back.width = 1 - back.height = 1 - back.scaleX = width - back.scaleY = height - back.scaleZ = 1 - back.rotationY = angle * 2 - back.z = depth/2 - back.y = height/2 - - // adding children, must also be instances of Object3D - if (-1 != sides.indexOf("top")) this.add(top) - if (-1 != sides.indexOf("bottom")) this.add(bottom) - if (-1 != sides.indexOf("left")) this.add(left) - if (-1 != sides.indexOf("right")) this.add(right) - if (-1 != sides.indexOf("front")) this.add(front) - if (-1 != sides.indexOf("back")) this.add(back) - - this.children.forEach(function (face) { - face.el.style.backgroundColor = color - }) - - // this applies the updated CSS style - // required for any change to take effect - // when a parent object's update() is called - // all its children will be updated as well - this.update() - - // if this object's children won't move by themselves - this.updateChildren = true - - this.setWidth = function(w){ - base.width = top.width = bottom.width = front.width = back.width = w - left.x = -w/2 - right.x = w/2 - base.dirty = true - } - this.setHeight = function(h){ - base.height = left.height = right.height = front.height = back.height = h - bottom.y = 0 - left.y = right.y = front.y = back.y = h/2 - top.y = h - base.dirty = true - } - this.setDepth = function(d){ - base.depth = top.height = bottom.height = left.width = right.width = d - front.z = -d/2 - back.z = d/2 - base.dirty = true - } - - }, - - toString: function(){ - var params = "id width height depth x y z rotationX rotationY color sides".split(" ") - return this.__toString(params) - }, - - clone: function(){ - return new MX[this.type] (this) - } - - // other properties will be mixed into the prototype of the new constructor - -}) diff --git a/public/assets/javascripts/mx/primitives/mx.tableau.js b/public/assets/javascripts/mx/primitives/mx.tableau.js deleted file mode 100644 index 514e206..0000000 --- a/public/assets/javascripts/mx/primitives/mx.tableau.js +++ /dev/null @@ -1,48 +0,0 @@ - - -var Tableau = function(){ - this.extend = extend.bind(Tableau) - - function extend (props) { - var Super = this - var ExtendedTableau = function () { - Super.call(this) - props.init && props.init.apply(this, arguments) - } - ExtendedTableau.prototype = Object.create(Tableau.prototype) - for (var prop in props) { - if (props.hasOwnProperty(prop) && prop !== 'init') { - ExtendedTableau.prototype[prop] = props[prop] - } - } - ExtendedTableau.extend = extend.bind(ExtendedTableau) - return ExtendedTableau - } -} - -Tableau.prototype.init = function(opt){} -Tableau.prototype.animate = function(t){} -Tableau.prototype.show = function(){} -Tableau.prototype.hide = function(){} - -MX.Tableau = new Tableau() -MX.Tableaux = {} - -/* - -MX.Tableaux.Foo = MX.Tableau.extend({ - // this will be called within the contructor - init: function (opt) { - }, - - show: function(){ - }, - - hide: function(){ - }, - - animate: function() { - } -}) - -*/ diff --git a/public/assets/javascripts/mx/primitives/mx.text.js b/public/assets/javascripts/mx/primitives/mx.text.js index 0c278a9..9c7af5c 100644 --- a/public/assets/javascripts/mx/primitives/mx.text.js +++ b/public/assets/javascripts/mx/primitives/mx.text.js @@ -1,4 +1,5 @@ MX.Text = MX.Object3D.extend({ + init: function (ops) { this.type = "Text" @@ -31,4 +32,5 @@ MX.Text = MX.Object3D.extend({ this.updateChildren = true this.update() } + }) diff --git a/public/assets/javascripts/mx/primitives/mx.texturedBox.js b/public/assets/javascripts/mx/primitives/mx.texturedBox.js deleted file mode 100644 index daec2d8..0000000 --- a/public/assets/javascripts/mx/primitives/mx.texturedBox.js +++ /dev/null @@ -1,121 +0,0 @@ -// Creates a box using a given texture image. -// Uses a texture image like this: -// -// ---------- ---------- -// | | | -// | top | bottom | -// | | | -// ---------- ---------- ---------- ---------- -// | | | | | -// | left | front | right | back | -// | | | | | -// ---------- ---------- ---------- ---------- -// -// See `examples/images/skins/` for some minecraft skin examples. - -// Options: -// -// - {number} `width` -// - {number} `height` -// - {number} `depth` -// - {string} `texture` path to texture image -// - {string} `classname` class to be added to dom element - -MX.TexturedBox = MX.Object3D.extend({ - - init: function (ops) { - - this.type = "TexturedBox" - - if (!ops.width || !ops.height || !ops.depth || (!ops.texture && !ops.classname)) { - console.warn('TextureBox: missing arguments') - return - } - - // faces - var angle = MX.rotationUnit === 'deg' ? 90 : (Math.PI / 2), - offsetX = ops.offset ? (ops.offset.x || 0) : 0, - offsetY = ops.offset ? (ops.offset.y || 0) : 0, - overlap = ops.overlap ? ops.overlap : 0 - var multiTexture = typeof ops.texture == "object"; - - var top = this.top = new MX.Object3D() - top.width = ops.width - top.height = ops.depth - top.rotationX = angle - top.y = ops.height / 2 - overlap - if (!multiTexture) - top.el.style.backgroundPosition = - (-(offsetX + ops.depth) + 'px ') + - (-offsetY + 'px') - - var bottom = this.bottom = new MX.Object3D() - bottom.width = ops.width - bottom.height = ops.depth - bottom.rotationX = -angle - bottom.y = -ops.height / 2 + overlap - if (!multiTexture) - bottom.el.style.backgroundPosition = - (-(offsetX + ops.depth + ops.width) + 'px ') + - (-offsetY + 'px') - - var left = this.left = new MX.Object3D() - left.width = ops.depth - left.height = ops.height - left.rotationY = -angle - left.x = -ops.width / 2 + overlap - if (!multiTexture) - left.el.style.backgroundPosition = - (-offsetX + 'px ') + - (-(offsetY + ops.depth) + 'px') - - var right = this.right = new MX.Object3D() - right.width = ops.depth - right.height = ops.height - right.rotationY = angle - right.x = ops.width / 2 - overlap - if (!multiTexture) - right.el.style.backgroundPosition = - (-(offsetX + ops.depth + ops.width) + 'px ') + - (-(offsetY + ops.depth) + 'px') - - var front = this.front = new MX.Object3D() - front.width = ops.width - front.height = ops.height - front.z = -ops.depth / 2 + overlap - if (!multiTexture) - front.el.style.backgroundPosition = - (-(offsetX + ops.depth) + 'px ') + - (-(offsetY + ops.depth) + 'px') - - var back = this.back = new MX.Object3D() - back.width = ops.width - back.height = ops.height - back.rotationY = angle * 2 - back.z = ops.depth / 2 - overlap - if (!multiTexture) - back.el.style.backgroundPosition = - (-(offsetX + ops.depth * 2 + ops.width) + 'px ') + - (-(offsetY + ops.depth) + 'px') - - this.add(top, bottom, left, right, front, back) - - this.children.forEach(function (c,i) { - if (multiTexture) { - c.el.style.backgroundImage = 'url(' + ops.texture[i] + ')' - } - else if (ops.texture) { - c.el.style.backgroundImage = 'url(' + ops.texture + ')' - } - if (ops.classname) { - c.el.classList.add(ops.classname) - } - c.el.style.backgroundRepeat = 'no-repeat' - }) - - this.update() - this.updateChildren = false - - } - -}) diff --git a/public/assets/javascripts/mx/primitives/mx.video.js b/public/assets/javascripts/mx/primitives/mx.video.js new file mode 100644 index 0000000..b28204d --- /dev/null +++ b/public/assets/javascripts/mx/primitives/mx.video.js @@ -0,0 +1,102 @@ +MX.Video = MX.Object3D.extend({ + + init: function (ops) { + + this.type = "Video" + + this.media = ops.media + this.width = ops.media.width + this.height = ops.media.height + this.x = ops.x || 0 + this.y = ops.y || 0 + this.z = ops.z || 0 + this.rotationX = ops.rotationX || 0 + this.rotationY = ops.rotationY || 0 + this.rotationZ = ops.rotationZ || 0 + this.scale = ops.scale || 1 + this.backface = ops.backface || false + + ops.className && this.el.classList.add(ops.className) + this.backface && this.el.classList.add("backface-visible") + this.el.classList.add("video") + this.paused = !! this.media.autoplay + this.muted = app.muted || !! this.media.mute + + this.load() + }, + + load: function(ops){ + this.paused = true + + this.player = document.createElement('video') + this.player.addEventListener("loadedmetadata", this.ready.bind(this)) + this.player.addEventListener("error", this.error.bind(this)) + this.player.addEventListener("ended", this.finished.bind(this)) + this.player.width = this.width + this.player.height = this.height + this.player.src = this.media.url + this.player.load() + + this.el.appendChild(this.player) + }, + + ready: function(){ + this.seek( this.media.keyframe || 0 ) + + if (this.media.mute) { + this.mute() + } + + if (this.media.autoplay) { + this.play() + } + }, + + error: function(err){ + console.log("video error", err) + }, + + play: function(){ + this.paused = false + this.player.play() + }, + + pause: function(){ + this.paused = true + this.player.pause() + }, + + seek: function(n){ + if (n < 1) { + n = n * this.duration() + } + this.player.currentTime = n + }, + + mute: function(){ + this.player.muted = true + this.muted = true + }, + + unmute: function(){ + this.player.muted = false + this.muted = false + }, + + duration: function(){ + return this.player.duration + }, + + finished: function(){ + console.log("video finished") + if (this.media.loop) { + this.seek(0) + this.play() + } + else if (this.bound) { + $(".playButton").removeClass('playing') + } + }, + + +}) diff --git a/public/assets/javascripts/mx/primitives/mx.vimeo.js b/public/assets/javascripts/mx/primitives/mx.vimeo.js new file mode 100644 index 0000000..7a5327e --- /dev/null +++ b/public/assets/javascripts/mx/primitives/mx.vimeo.js @@ -0,0 +1,142 @@ +MX.Vimeo = MX.Object3D.extend({ + + init: function (ops) { + + this.type = "Vimeo" + + this.media = ops.media + this.width = ops.media.width + this.height = ops.media.height + this.x = ops.x || 0 + this.y = ops.y || 0 + this.z = ops.z || 0 + this.rotationX = ops.rotationX || 0 + this.rotationY = ops.rotationY || 0 + this.rotationZ = ops.rotationZ || 0 + this.scale = ops.scale || 1 + this.backface = ops.backface || false + + ops.className && this.el.classList.add(ops.className) + this.backface && this.el.classList.add("backface-visible") + this.el.classList.add("video") + this.paused = !! this.media.autoplay + this.muted = app.muted || !! this.media.mute + + this.load() + }, + + load: function (ops) { + var uid = 'player-' + Uid () + var preload = document.createElement("iframe") + preload.id = uid + preload.setAttribute("src", "//player.vimeo.com/video/" + this.media.token + "?api=1&badge=0&controls=0branding=0&byline=0&player_id=" + uid) + preload.style.backgroundImage = "url(" + this.media.thumbnail + ")" + preload.style.width = this.media.width + "px" + preload.style.height = this.media.height + "px" + preload.style.border = "0" + preload.style.pointerEvents = "none" + preload.className = "preload" + this.el.appendChild(preload) + this.player = $f(preload) + + this.player.addEvent('ready', this.ready.bind(this)) + }, + + ready: function(){ + console.log("vimeo ready") + + // wait until ready before binding events. other events: play, pause + this.player.addEvent('play', this.onPlay.bind(this)) + this.player.addEvent('pause', this.onPause.bind(this)) + this.player.addEvent('finish', this.finished.bind(this)) + + // this is async on vimeo so call it asap + this.player.api('getDuration', function(n){ + console.log("vimeo duration", n) + this.player.duration = n + }.bind(this)) + + if (this.media.mute) { + this.mute() + } + + this.seek( this.media.keyframe || 0 ) + + if (this.media.autoplay) { + this.play() + } + }, + + error: function(err){ + console.log("vimeo error", err) + }, + + play: function(){ + this.paused = false + this.player.api('play') + }, + + pause: function(){ + this.paused = true + this.player.api('pause') + }, + + seek: function(n){ + // defer seek until we have duration + if (! this.duration()) { + setTimeout(function(){ + this.seek(n) + }.bind(this), 300) + return + } + + if (n < 1) { + n = n * this.duration() + } + this.player.api('seekTo', max(0, n-1)) + if (this.paused) { + this.paused = false + this.play() + setTimeout(function(){ + this.pause() + }.bind(this), 1000) + } + }, + + duration: function(){ + return this.player.duration + }, + + mute: function(){ + this.player.api('setVolume', 0.0) + this.muted = true + }, + + unmute: function(){ + this.player.api('setVolume', 0.8) + this.muted = false + }, + + onPlay: function(){ + if (this.paused) { + this.pause() + } + }, + + onPause: function(){ + if (! this.paused) { + this.play() + } + }, + + finished: function(){ + if (this.media.loop) { + this.seek(0) + this.play() + } + else if (this.bound) { + $(".playButton").removeClass('playing') + } + } + +}) diff --git a/public/assets/javascripts/mx/primitives/mx.youtube.js b/public/assets/javascripts/mx/primitives/mx.youtube.js new file mode 100644 index 0000000..47d5507 --- /dev/null +++ b/public/assets/javascripts/mx/primitives/mx.youtube.js @@ -0,0 +1,168 @@ +MX.Youtube = MX.Object3D.extend({ + + init: function (ops) { + + this.type = "Youtube" + + this.media = ops.media + this.width = ops.media.width + this.height = ops.media.height + this.x = ops.x || 0 + this.y = ops.y || 0 + this.z = ops.z || 0 + this.rotationX = ops.rotationX || 0 + this.rotationY = ops.rotationY || 0 + this.rotationZ = ops.rotationZ || 0 + this.scale = ops.scale || 1 + this.backface = ops.backface || false + + ops.className && this.el.classList.add(ops.className) + this.backface && this.el.classList.add("backface-visible") + this.el.classList.add("video") + this.paused = !! this.media.autoplay + this.muted = app.muted || !! this.media.mute + + this.load() + }, + + load: function (ops) { + var base = this + var uid = 'player-' + Uid () + var preload = document.createElement("div") + preload.id = uid + preload.style.backgroundImage = "url(" + this.media.thumbnail + ")" + preload.style.width = this.media.width + "px" + preload.style.height = this.media.height + "px" + preload.style.pointerEvents = "none" + preload.className = "preload" + this.el.appendChild(preload) + + this.defer(uid) + }, + + defer: function (uid){ + if (! YT || ! YT.loaded) { + setTimeout(function(){ + this.defer(uid) + }.bind(this), 300) + } + else { + this.build(uid) + } + }, + + build: function(uid){ + this.player = new YT.Player(uid, { + videoId: this.media.token, + width: this.width, + height: this.height, + events: { + onReady: this.ready.bind(this), + onError: this.error.bind(this), + onStateChange: this.statechange.bind(this), + }, + playerVars: { + autohide: 1, + autoplay: 0, + disablekb: 1, + controls: 0, + enablejsapi: 1, + fs: 0, + modestbranding: 1, + iv_load_policy: 3, // no annotations + loop: 0, + showinfo: 0, + rel: 0, + wmode: 'opaque', + }, + }) + }, + + ready: function(){ + console.log("youtube ready") + + if (this.media.autoplay) { + this.play() + } + + if (this.media.mute) { + this.mute() + } + + this.seek( this.media.keyframe || 0 ) + }, + + error: function(err){ + console.log("youtube error", err) + }, + + statechange: function(e){ + switch (e.data) { + case -1: // unstarted + break + case 0: // finished + this.finished() + break + case 1: // play + if (this.paused) { + this.pause() + } + break + case 2: // pause + break + case 3: // buffering + break + case 5: // cued + break + } + }, + + play: function(){ + this.paused = false + this.player.playVideo() + }, + + pause: function(){ + this.paused = true + this.player.pauseVideo() + }, + + seek: function(n, allowSeekAhead){ + if (n < 1) { + n = n * this.duration() + } + allowSeekAhead = typeof allowSeekAhead == "boolean" ? allowSeekAhead : true + this.player.seekTo(n, true) // set to false if seeking manually + }, + + duration: function(){ + return this.player.getDuration() + }, + + mute: function(){ + this.player.mute() + this.muted = true + }, + + unmute: function(){ + this.player.unMute() + this.player.setVolume(80) + this.muted = false + }, + + finished: function(){ + console.log("youtube finished") + if (this.media.loop) { + this.seek(0) + this.play() + } + else if (this.bound) { + $(".playButton").removeClass('playing') + } + } + +}) + +window.onYouTubePlayerAPIReady = function(){ + // console.log("youtube api ready") +} diff --git a/public/assets/javascripts/rectangles/engine/map/ui_editor.js b/public/assets/javascripts/rectangles/engine/map/ui_editor.js index ea7a356..577ea32 100644 --- a/public/assets/javascripts/rectangles/engine/map/ui_editor.js +++ b/public/assets/javascripts/rectangles/engine/map/ui_editor.js @@ -53,16 +53,21 @@ Map.UI.Editor = function(map){ if (intersects.length && base.permissions.destroy) { base.mouse.down = false Rooms.remove(intersects[0]) + app.tube("builder-destroy-room", intersects[0]) return } else if (intersects.length && (base.permissions.move || base.permissions.resize)) { base.dragging = intersects[0] base.resizing = base.permissions.resize && base.dragging.rect.nearEdge(cursor.x.a, cursor.y.a, resize_margin / map.zoom) base.dragging.rect.translation.sides = base.resizing + app.tube("builder-pick-room", intersects[0]) } else if (base.permissions.create) { base.creating = true } + else if (intersects.length) { + app.tube("builder-pick-room", intersects[0]) + } if (e.shiftKey && base.dragging) { base.dragging.rect.quantize(10/map.zoom) @@ -109,7 +114,8 @@ Map.UI.Editor = function(map){ if (cursor.height() > side_min && cursor.width() > side_min) { cursor.x.abs().quantize(1) cursor.y.abs().quantize(1) - Rooms.add_with_rect( cursor ) + var room = Rooms.add_with_rect( cursor ) + app.tube("builder-pick-room", room) } } diff --git a/public/assets/javascripts/rectangles/engine/rooms/_rooms.js b/public/assets/javascripts/rectangles/engine/rooms/_rooms.js index 48931e9..e0033e3 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/_rooms.js +++ b/public/assets/javascripts/rectangles/engine/rooms/_rooms.js @@ -26,6 +26,7 @@ var Rooms = new function(){ height: 500 }) base.add(room) + return room } base.remove = function(room){ diff --git a/public/assets/javascripts/rectangles/engine/rooms/builder.js b/public/assets/javascripts/rectangles/engine/rooms/builder.js index e6625ec..49e55dc 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/builder.js +++ b/public/assets/javascripts/rectangles/engine/rooms/builder.js @@ -20,8 +20,8 @@ Rooms.builder = new function(){ } } function build (){ - Rooms.regions.forEach(function(room){ - build_walls(room).forEach(function(el){ + Rooms.regions.forEach(function(region){ + build_walls(region).forEach(function(el){ els.push(el) scene.add(el) }) diff --git a/public/assets/javascripts/rectangles/engine/rooms/clipper.js b/public/assets/javascripts/rectangles/engine/rooms/clipper.js index eb467cd..e2bb894 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/clipper.js +++ b/public/assets/javascripts/rectangles/engine/rooms/clipper.js @@ -20,12 +20,15 @@ Rooms.clipper = new function(){ // Given a set of overlapping rooms, clip any intersections, then cull any duplicate polygons base.solve_rects = function(){ - if (Rooms.count() == 0) return + if (Rooms.count() == 0) { + Rooms.regions = regions = [] + return + } base.reset_rects() base.clip_rects() base.cull_rects() - + Rooms.regions = sort_rects_by_position(regions) } diff --git a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js index 74801e9..1493fc6 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js +++ b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js @@ -19,6 +19,7 @@ var Scenery = new function(){ scene_media = new Scenery.types.image ({ media: media, wall: wall, id: id }) break + case 'video': case 'youtube': case 'vimeo': scene_media = new Scenery.types.video ({ media: media, wall: wall, id: id }) diff --git a/public/assets/javascripts/rectangles/engine/scenery/move.js b/public/assets/javascripts/rectangles/engine/scenery/move.js index bad0a55..94a4e52 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/move.js +++ b/public/assets/javascripts/rectangles/engine/scenery/move.js @@ -26,6 +26,10 @@ Scenery.move = function(base){ Scenery.remove(base.id) return } + + // load the modal + app.controller.pick(base) + if (! (editor.permissions.move || editor.permissions.resize) ) { e.clickAccepted = false return diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/_object.js b/public/assets/javascripts/rectangles/engine/scenery/types/_object.js index 05c760b..65f3a94 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/_object.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/_object.js @@ -35,6 +35,9 @@ Scenery.types.base = Fiber.extend(function(base){ destroy: function(){ this.unbind() scene.remove(this.mx) + this.mx.media = null + this.mx.ops = null + this.mx = null this.move = null this.media = null this.dimensions = null diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/image.js b/public/assets/javascripts/rectangles/engine/scenery/types/image.js index b668e6a..99c1810 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/image.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/image.js @@ -17,6 +17,7 @@ Scenery.types.image = Scenery.types.base.extend(function(base){ this.mx = new MX.Image({ src: this.media.url, scale: this.scale, + media: this.media, y: this.scale * this.media.height/2, backface: false, }) diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/video.js b/public/assets/javascripts/rectangles/engine/scenery/types/video.js index b34e55c..d3e2e76 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/video.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/video.js @@ -14,13 +14,73 @@ Scenery.types.video = Scenery.types.base.extend(function(base){ }, build: function(){ - this.mx = new MX.Image({ - src: this.media.url, + switch (this.media.type) { + case 'video': + this.mxType = MX.Video + break + case 'vimeo': + this.mxType = MX.Vimeo + break + case 'youtube': + this.mxType = MX.Youtube + break + } + if (app.muted) { + this.media.mute = true + } + this.mx = new this.mxType({ + media: this.media, + scale: this.scale, y: this.scale * this.media.height/2, backface: false, }) scene.add( this.mx ) }, + + play: function(){ + this.mx.play() + }, + + pause: function(){ + this.mx.pause() + }, + + toggle: function(shouldPause){ + if (typeof shouldPause !== "boolean") { + shouldPause = ! this.mx.paused + } + shouldPause ? this.mx.pause() : this.mx.play() + return shouldPause + }, + + toggleMuted: function(shouldMute){ + if (typeof shouldMute !== "boolean") { + shouldMute = ! this.mx.muted + } + shouldMute ? this.mx.mute() : this.mx.unmute() + return shouldMute + }, + + paused: function(){ + return this.mx.paused + }, + + muted: function(){ + return this.mx.muted + }, + + seek: function(n){ + this.mx.seek(n) + }, + + mute: function(muted){ + if (muted) { + this.mx.mute() + } + else { + this.mx.unmute() + } + }, serialize: function(){ var data = base.serialize.call(this) diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index b2a5b12..7ff4ccb 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -45,6 +45,12 @@ window.Wall = (function(){ if (Scenery.nextMedia) { Scenery.addNextToWall(base) } + else if (Scenery.nextWallpaper) { + base.wallpaper() + } + else { + app.controller.hideExtras() + } } }) } @@ -109,6 +115,10 @@ window.Wall = (function(){ this.$walls && this.$walls.css("background-color", color) } + Wall.prototype.wallpaper = function(){ + this.$walls.css("background-image", Scenery.nextWallpaper) + } + Wall.prototype.siblings = function(){ var base = this var match = base.side | base.half_side diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js index 6d41d5b..d070d55 100644 --- a/public/assets/javascripts/ui/_router.js +++ b/public/assets/javascripts/ui/_router.js @@ -5,6 +5,7 @@ var SiteRouter = Router.extend({ events: { "click [data-role='show-signup-modal']": 'signup', "click [data-role='show-signin-modal']": 'signin', + "click [data-role='forgot-password']": 'passwordForgot', "click [data-role='new-project-modal']": 'newProject', "click [data-role='edit-project-modal']": 'editProject', "click [data-role='edit-profile-modal']": 'editProfile', @@ -18,6 +19,11 @@ var SiteRouter = Router.extend({ routes: { "/login": 'signin', "/signup": 'signup', + + "/auth/usernameTaken": 'usernameTaken', + "/auth/password": 'passwordReset', + "/auth/forgotPassword": 'passwordForgot', + "/profile": 'profile', "/profile/edit": 'editProfile', "/about/:name/edit": 'editDocument', @@ -29,7 +35,10 @@ var SiteRouter = Router.extend({ "/project": 'projectPicker', "/project/new": 'newProject', "/project/new/:layout": 'projectNewWithLayout', - "/project/:name": 'projectEditor', + "/project/:name": 'project', + "/project/:name/view": 'projectViewer', + + "/test/wallpaper": 'testWallpaper', }, initialize: function(){ @@ -40,7 +49,9 @@ var SiteRouter = Router.extend({ this.newProjectModal = new NewProjectModal() this.editProjectModal = new EditProjectModal() this.editProfileModal = new EditProfileModal() + this.passwordForgotModal = new PasswordForgot() this.documentModal = new DocumentModal() + this.profileView = new ProfileView() this.route() @@ -52,7 +63,7 @@ var SiteRouter = Router.extend({ app.mode.builder = true app.launch() - this.builderView = new BuilderView() + this.builderView = app.controller = new BuilderView() this.builderView.load(name) }, @@ -83,25 +94,35 @@ var SiteRouter = Router.extend({ layout = slugify(layout) window.history.pushState(null, document.title, "/project/new/" + layout) - this.editorView = new EditorView() + this.editorView = app.controller = new EditorView() this.editorView.loadLayout(layout) }, - projectEditor: function(e, name){ - app.mode.editor = true - app.launch() - + project: function(e, name){ if ($(".aboutRoom").length) { - this.readerView = new ReaderView() - this.readerView.load(name) + this.projectViewer(e, name) } else { - this.editorView = new EditorView() - this.editorView.load(name) + this.projectEditor(e, name) } }, + projectEditor: function(e, name){ + app.mode.editor = true + app.launch() + + this.editorView = app.controller = new EditorView() + this.editorView.load(name) + }, + projectViewer: function(e, name){ + app.mode.editor = true + app.launch() + + this.readerView = app.controller = new ReaderView() + this.readerView.load(name) + }, + /* editProject: function(e){ e && e.preventDefault() @@ -122,14 +143,23 @@ var SiteRouter = Router.extend({ this.signInModal.load() }, - profile: function(e){ - var classes = ['one', 'two', 'three', 'four', - 'five', 'six', 'seven', 'eight', - 'nine', 'ten', 'eleven', 'twelve', - 'thirteen']; - $(".bio").addClass(choice(classes)); + usernameTaken: function(e){ + this.usernameTakenModal = new UsernameTaken () + this.usernameTakenModal.load() + }, + passwordForgot: function(e){ + e && e.preventDefault() + window.history.pushState(null, document.title, "/auth/forgotPassword") + this.passwordForgotModal.load() + }, + passwordReset: function(e){ + this.passwordResetModal = new PasswordReset () + this.passwordResetModal.load() }, + profile: function(e){ + this.profileView.load() + }, editProfile: function(e){ e && e.preventDefault() window.history.pushState(null, document.title, "/profile/edit") @@ -160,16 +190,41 @@ var SiteRouter = Router.extend({ var name = e ? $(e.currentTarget).data("name") : name - confirmModal.confirm("Are you sure you want to delete " + name + "?", $.proxy(function(){ - this.documentModal.destroy(name, $.proxy(function(){ - AlertModal.alert("Document deleted!", $.proxy(function(){ + ConfirmModal.confirm("Are you sure you want to delete " + name + "?", function(){ + this.documentModal.destroy(name, function(){ + AlertModal.alert("Document deleted!", function(){ window.location.href = "/about" - }, this)) - }, this)) - }, this)) + }.bind(this)) + }.bind(this)) + }.bind(this)) // this.documentModal.destroy(name) }, + + testWallpaper: function(e){ + var content = document.getElementById("content") + content.style.width = "680px" + content.style.margin = "0 auto" + var wm = new WallpaperManager() + app.on('wallpaper-ready', function(){ + var black = [0,0,0,0] + var white = [255,255,255,1.0] + var swatches = wm.buildSwatches(black, white, 4) + document.body.style.backgroundColor = "#eee" + swatches.forEach(function(swatch){ + swatch.style.margin = "4px" + swatch.style.border = "1px solid lime" + swatch.style.backgroundColor = "#888" + content.appendChild(swatch) + swatch.onclick = function(){ + dataUrl = swatch.toDataURL() + document.body.style.backgroundImage = "url(" + dataUrl + ")" + } + }) + }) + wm.init() + }, + }) diff --git a/public/assets/javascripts/ui/builder/BuilderInfo.js b/public/assets/javascripts/ui/builder/BuilderInfo.js new file mode 100644 index 0000000..9bbd385 --- /dev/null +++ b/public/assets/javascripts/ui/builder/BuilderInfo.js @@ -0,0 +1,160 @@ + +var BuilderInfo = View.extend({ + el: "#builderInfo", + + events: { + "keydown": 'stopPropagation', + "change [name=x]": 'changePosition', + "change [name=y]": 'changePosition', + "change [name=width]": 'changeDimensions', + "change [name=depth]": 'changeDimensions', + "change [name=height]": 'changeDimensions', + "change [name=units]": 'changeUnits', + "change [name=resolution]": 'changeResolution', + "change [name=viewHeight]": 'changeViewHeight', + }, + + initialize: function(opt){ + this.parent = opt.parent + this.$x = this.$("[name=x]") + this.$y = this.$("[name=y]") + this.$width = this.$("[name=width]") + this.$depth = this.$("[name=depth]") + this.$height = this.$("[name=height]") + this.$units = this.$("[name=units]") + this.$viewHeight = this.$("[name=viewHeight]") + this.$unitName = this.$(".unitName") + app.on("builder-pick-room", this.pick.bind(this)) + app.on("builder-destroy-room", this.destroy.bind(this)) + }, + + load: function(data){ + this.$viewHeight.unitVal( data.viewHeight || app.defaults.viewHeight ) + this.$units.val( "ft" ) + this.$unitName.html( "ft" ) + this.$resolution.val( app.defaults.footResolution ) + }, + + toggle: function(state){ + this.$el.toggleClass("active", state) + }, + + show: function(){ + this.toggle(true) + }, + + hide: function(){ + this.toggle(false) + }, + + room: null, + + pick: function(room){ + this.room = room + this.$width.unitVal( room.rect.x.length() ) + this.$depth.unitVal( room.rect.y.length() ) + this.$height.unitVal( room.height ) + this.$x.unitVal( room.rect.x.a ) + this.$y.unitVal( room.rect.y.a ) + + console.log(room) + }, + + destroy: function(room){ + this.room = null + this.hide() + }, + + changeDimensions: function(){ +// this.$width.unitVal( room.rect.x.length() ) +// this.$depth.unitVal( room.rect.y.length() ) +// this.$height.unitVal( room.height ) + }, + + changeUnits: function(){ + app.units = this.$units.val() + this.$('.units').resetUnitVal() + }, + + changeViewHeight: function(){ + window.viewHeight = this.$viewHeight.unitVal( ) + }, + +}) + +$.fn.resetUnitVal = function(){ + this.each(function(){ + var n = $(this).data("px") + $(this).unitVal(n) + }); +} + +$.fn.unitVal = function(n){ + var s + if (typeof n === "undefined") { + s = $(this).val() + n = stringToMeasurement( s ) + } + s = measurementToString( n ) + $(this).val( s ).data("px", n) + return n +} + +function measurementToString( n ) { + var s, ft, inch + switch (app.units) { + case 'm': + s = round(n/36 * 0.3048 * 100) / 100 + " m" + break + case 'ft': + ft = floor(n / 36) + inch = abs(round((n % 36) / 3)) + s = ft + "'" + if (inch > 0) { + s += " " + inch + '"' + } + break + case 'px': + default: + s = round(n) + " px" + break + } + return s +} +function stringToMeasurement( s ) { + var ft, inch, ft_in, type + if (s.indexOf("'") !== -1 || s.indexOf('"') !== -1 || s.indexOf('ft') !== -1) { + ft_in = s.match(/[0-9.]+/g) + if (ft_in.length >= 2) { + ft = parseFloat( ft_in[0] ) + inch = parseFloat( ft_in[1] ) + } + else if (ft_in.length == 1) { + if (s.indexOf('"') !== -1) { + ft = 0 + inch = parseFloat( ft_in[0] ) + } + else { + ft = parseFloat( ft_in[0] ) + inch = 0 + } + } + else { + ft = inch = 0 + } + n = ft * 36 + inch * 3 + } + else if (type === "m") { + n = parseFloat(s.match(/[0-9.]+/)) * 36 / 0.3048 + } + else if (s.indexOf("px") !== -1) { + n = parseFloat(s.match(/[0-9.]+/)) + } + else { + n = abs( stringToMeasurement( s + app.units ) ) + } + if (s.indexOf('-') !== -1) { + n *= -1 + } + return n +}
\ No newline at end of file diff --git a/public/assets/javascripts/ui/builder/BuilderSettings.js b/public/assets/javascripts/ui/builder/BuilderSettings.js index 9b2f753..c551f95 100644 --- a/public/assets/javascripts/ui/builder/BuilderSettings.js +++ b/public/assets/javascripts/ui/builder/BuilderSettings.js @@ -2,11 +2,12 @@ var BuilderSettings = FormView.extend({ el: "#builderSettings", - createAction: "/api/layouts/new", - updateAction: "/api/layouts/edit", - destroyAction: "/api/layouts/destroy", + createAction: "/api/layout/new", + updateAction: "/api/layout/edit", + destroyAction: "/api/layout/destroy", events: { + "keydown": 'stopPropagation', "keydown [name=name]": 'enterSubmit', "click [data-role='save-layout']": 'save', "click [data-role='clone-layout']": 'clone', @@ -57,7 +58,7 @@ var BuilderSettings = FormView.extend({ destroy: function(){ var msg = "Are you sure you want to delete the layout " + sanitize(this.$name.val()) + "?" - ConfirmModal.confirm(msg, $.proxy(function(){ + ConfirmModal.confirm(msg, function(){ $.ajax({ url: this.destroyAction, type: "delete", @@ -66,11 +67,11 @@ var BuilderSettings = FormView.extend({ window.location.href = "/layout" } }) - }, this)) + }.bind(this)) }, - toggle: function(){ - this.$el.toggleClass("active") + toggle: function(state){ + this.$el.toggleClass("active", state) }, enterSubmit: function (e) { diff --git a/public/assets/javascripts/ui/builder/BuilderView.js b/public/assets/javascripts/ui/builder/BuilderView.js index 33aface..555cd58 100644 --- a/public/assets/javascripts/ui/builder/BuilderView.js +++ b/public/assets/javascripts/ui/builder/BuilderView.js @@ -2,12 +2,13 @@ var BuilderView = View.extend({ el: "#builderView", - action: "/api/layouts/", + action: "/api/layout/", events: { }, initialize: function(){ + this.info = new BuilderInfo ({ parent: this }) this.toolbar = new BuilderToolbar ({ parent: this }) this.settings = new BuilderSettings ({ parent: this }) }, @@ -20,11 +21,15 @@ var BuilderView = View.extend({ name = sanitize(name) - $.get(this.action + name, $.proxy(this.ready, this)) + $.get(this.action + name, this.ready.bind(this)) }, ready: function(data){ this.settings.load(data) + this.info.load(data) }, + + hideExtras: function(){ + } }) diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index b9f4560..13a6f60 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -2,11 +2,12 @@ var EditorSettings = FormView.extend({ el: "#editorSettings", - createAction: "/api/projects/new", - updateAction: "/api/projects/edit", - destroyAction: "/api/projects/destroy", + createAction: "/api/project/new", + updateAction: "/api/project/edit", + destroyAction: "/api/project/destroy", events: { + "keydown": 'stopPropagation', "keydown [name=name]": 'enterSubmit', "click [data-role='save-project']": 'save', "click [data-role='clone-project']": 'clone', @@ -32,7 +33,7 @@ var EditorSettings = FormView.extend({ data.startPosition && scene.camera.move(data.startPosition) if (! data.isNew) { - console.log(data) + // console.log(data) this.$id.val( data._id ) this.$name.val( data.name ) @@ -65,7 +66,7 @@ var EditorSettings = FormView.extend({ destroy: function(){ var msg = "Are you sure you want to delete the project " + sanitize(this.$name.val()) + "?" - ConfirmModal.confirm(msg, $.proxy(function(){ + ConfirmModal.confirm(msg, function(){ $.ajax({ url: this.destroyAction, type: "delete", @@ -74,7 +75,7 @@ var EditorSettings = FormView.extend({ window.location.href = "/project" } }) - }, this)) + }.bind(this)) }, toggle: function(){ diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js index 210ef6c..a3abc5a 100644 --- a/public/assets/javascripts/ui/editor/EditorToolbar.js +++ b/public/assets/javascripts/ui/editor/EditorToolbar.js @@ -87,6 +87,7 @@ var EditorToolbar = View.extend({ var editor = new function(){ this.permissions = new Permissions({ + 'pick': true, 'move': true, 'resize': false, 'destroy': false, diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js index b87ac83..4067c4d 100644 --- a/public/assets/javascripts/ui/editor/EditorView.js +++ b/public/assets/javascripts/ui/editor/EditorView.js @@ -2,8 +2,8 @@ var EditorView = View.extend({ el: "#editorView", - projectAction: "/api/projects/", - layoutAction: "/api/layouts/", + projectAction: "/api/project/", + layoutAction: "/api/layout/", events: { }, @@ -13,18 +13,19 @@ var EditorView = View.extend({ this.settings = new EditorSettings ({ parent: this }) this.mediaViewer = new MediaViewer ({ parent: this }) this.mediaUpload = new MediaUpload ({ parent: this }) + this.mediaEditor = new MediaEditor ({ parent: this }) this.wallpaperPicker = new WallpaperPicker ({ parent: this }) this.lightControl = new LightControl ({ parent: this }) }, load: function(name){ name = sanitize(name) - $.get(this.projectAction + name, $.proxy(this.ready, this)) + $.get(this.projectAction + name, this.ready.bind(this)) }, loadLayout: function(layout){ layout = sanitize(layout) - $.get(this.layoutAction + layout, $.proxy(this.readyLayout, this)) + $.get(this.layoutAction + layout, this.readyLayout.bind(this)) }, ready: function(data){ @@ -36,7 +37,14 @@ var EditorView = View.extend({ readyLayout: function(data){ data.isNew = true this.ready(data) + }, + + pick: function(scenery){ + this.mediaEditor.pick(scenery) + }, + + hideExtras: function(){ + this.mediaEditor.hide() } }) - diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js index 20c3577..93d97ed 100644 --- a/public/assets/javascripts/ui/editor/LightControl.js +++ b/public/assets/javascripts/ui/editor/LightControl.js @@ -3,6 +3,7 @@ var LightControl = View.extend({ el: ".lightcontrol", events: { + "mousedown": "stopPropagation", }, toggle: function(){ diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js new file mode 100644 index 0000000..a075e6b --- /dev/null +++ b/public/assets/javascripts/ui/editor/MediaEditor.js @@ -0,0 +1,134 @@ + +var MediaEditor = FormView.extend({ + el: "#mediaEditor", + + events: { + "keydown": 'stopPropagation', + "click [data-role=play-media]": "togglePaused", + "mousedown [name=keyframe]": "stopPropagation", + "mousedown": "stopPropagation", + "change [name=keyframe]": "seek", + "change [name=autoplay]": "setAutoplay", + "change [name=loop]": "setLoop", + "change [name=mute]": "setMute", + "click [data-role=destroy-media]": "destroy", + }, + + initialize: function(opt){ + this.parent = opt.parent + this.__super__.initialize.call(this) + + this.$name = this.$("[name=name]") + this.$description = this.$("[name=description]") + + // image fields + this.$widthDimension = this.$("[name=width]") + this.$heightDimension = this.$("[name=height]") + this.$units = this.$("[name=units]") + + // video fields + this.$playButton = this.$("[data-role=play-media]") + this.$autoplay = this.$("[name=autoplay]") + this.$loop = this.$("[name=loop]") + this.$mute = this.$("[name=mute]") + this.$keyframe = this.$("[name=keyframe]") + }, + + toggle: function(state) { + this.$el.toggleClass("active", state); + }, + + togglePaused: function(state){ + var state = this.scenery.toggle(state) + this.$playButton.toggleClass("paused", ! state) + }, + + pick: function(scenery) { + if (this.scenery) { + this.unbind() + } + + this.bind(scenery) + this.$el.addClass("active") + + var media = scenery.media + + this.$name.val(media.title) + this.$description.val(media.description) + + switch (media.type) { + case "image": + this.$(".image").show() + this.$(".video").hide() + + this.$widthDimension.val( Number(media.widthDimension) || "" ) + this.$heightDimension.val( Number(media.heightDimension) || "" ) + this.$units.val( media.units || "cm" ) + + break + + case "youtube": + case "vimeo": + case "video": + this.$(".video").show() + this.$(".image").hide() + + this.$playButton.toggleClass("paused", ! this.scenery.paused()) + this.$autoplay.prop('checked', !! media.autoplay) + this.$loop.prop('checked', !! media.loop) + this.$mute.prop('checked', !! media.mute) + this.$keyframe.val( Number(media.keyframe || 0) ) + + break + } + }, + + hide: function(scenery){ + if (this.scenery) { + this.unbind() + } + this.toggle(false) + }, + + seek: function(){ + var n = parseFloat( this.$keyframe.val() ) + this.scenery.seek(n) + + this.scenery.media.keyframe = n + }, + setAutoplay: function(){ + var checked = this.$autoplay.prop('checked') + this.scenery.media.autoplay = checked + if (checked && this.scenery.paused()) { + this.togglePaused() + } + }, + setLoop: function(){ + var checked = this.$loop.prop('checked') + this.scenery.media.loop = checked + }, + setMute: function(){ + var checked = this.$mute.prop('checked') + this.scenery.media.mute = checked + this.scenery.mute(checked) + }, + + bind: function(scenery){ + this.scenery = scenery + this.scenery.mx.bound = true + }, + + unbind: function(){ + this.scenery.mx.bound = false + this.scenery = null + }, + + destroy: function(){ + ConfirmModal.confirm("Are you sure you want to this media?", function(){ + var scenery = this.scenery + this.hide() + Scenery.remove(scenery.id) + }.bind(this)) + }, + +}) diff --git a/public/assets/javascripts/ui/editor/MediaUpload.js b/public/assets/javascripts/ui/editor/MediaUpload.js index b7fea07..86bf767 100644 --- a/public/assets/javascripts/ui/editor/MediaUpload.js +++ b/public/assets/javascripts/ui/editor/MediaUpload.js @@ -39,7 +39,7 @@ var MediaUpload = View.extend({ var url = this.$url.val() this.$url.val("") - Parser.parse(url, $.proxy(function(media){ + Parser.parse(url, function(media){ if (! media) { alert("Not a valid image/video link") return @@ -53,8 +53,8 @@ var MediaUpload = View.extend({ url: this.createAction, data: media, }) - request.done($.proxy(this.add, this)) - }, this)) + request.done(this.add.bind(this)) + }.bind(this)) }, handleFileSelect: function(e) { @@ -109,7 +109,7 @@ var MediaUpload = View.extend({ processData: false, contentType: false, }) - request.done($.proxy(this.add, this)) + request.done(this.add.bind(this)) }, add: function(media){ diff --git a/public/assets/javascripts/ui/editor/MediaViewer.js b/public/assets/javascripts/ui/editor/MediaViewer.js index 2535f1b..264ed7c 100644 --- a/public/assets/javascripts/ui/editor/MediaViewer.js +++ b/public/assets/javascripts/ui/editor/MediaViewer.js @@ -40,12 +40,12 @@ var MediaViewer = ModalView.extend({ }, load: function(){ - $.get("/api/media/user", $.proxy(this.populate, this)) + $.get("/api/media/user", this.populate.bind(this)) }, populate: function(data){ this.loaded = true - data && data.forEach($.proxy(this.add, this)) + data && data.forEach(this.add.bind(this)) this.__super__.show.call(this) }, @@ -62,6 +62,15 @@ var MediaViewer = ModalView.extend({ case 'vimeo': image.src = media.thumbnail break + + case 'video': + image = document.createElement('video') + image.addEventListener("loadedmetadata", function(){ + image.currentTime = image.duration * 1/3 + }) + image.src = media.url + image.load() + break } $span.data("media", media) @@ -124,7 +133,16 @@ var MediaViewer = ModalView.extend({ var $floatingImg = $('.floatingImg'); Scenery.nextMedia = media - $floatingImg.attr('src', image.attr('src')); + + switch (media.type) { + case "video": + $floatingImg.attr('src', 'http://www.rawrcast.com/wp-content/uploads/2010/02/BluePlayButton.png') + break + + default: + $floatingImg.attr('src', image.attr('src')) + break + } var height = $floatingImg.height() var width = $floatingImg.width() diff --git a/public/assets/javascripts/ui/editor/WallpaperPicker.js b/public/assets/javascripts/ui/editor/WallpaperPicker.js index ffbd935..cb1e361 100644 --- a/public/assets/javascripts/ui/editor/WallpaperPicker.js +++ b/public/assets/javascripts/ui/editor/WallpaperPicker.js @@ -3,7 +3,24 @@ var WallpaperPicker = View.extend({ el: ".wallpaper", events: { - "click .paper1": 'pick', + "click .swatch": 'pick', + }, + + initialize: function(){ + var wm = new WallpaperManager() + app.on('wallpaper-ready', function(){ + var black = [0,0,0,1.0] + var white = [255,255,255,1.0] + var swatches = wm.buildSwatches(black, white, 2) + swatches.forEach(function(swatch){ + var dataUrl = swatch.toDataURL() + var span = document.createElement('span') + span.style.backgroundImage = "url(" + dataUrl + ")" + span.className = "swatch" + this.$el.append(span) + }.bind(this)) + }.bind(this)) + wm.init() }, toggle: function(){ @@ -13,8 +30,116 @@ var WallpaperPicker = View.extend({ }, pick: function(e){ - $("body").toggleClass("pastePaper"); - $(e.currentTarget).toggleClass("active"); + var $swatch = $(e.currentTarget) + var $floatingSwatch = $(".floatingSwatch") + + $floatingSwatch.css('background-image', $swatch.css('background-image')) + + Scenery.nextWallpaper = $swatch.css('background-image') + + setTimeout(function(){ + function _followCursor(e) { + $floatingSwatch.css({ + top: (e.pageY + 10) + 'px', + left: (e.pageX + 10) + 'px' + }); + } + $(window).on('mousemove', _followCursor); + $(window).one('click', function () { + $(window).off('mousemove', _followCursor); + $floatingSwatch.hide(); + }); + $floatingSwatch.show() + _followCursor(e); + }) } }) + +// pattern +// scale +// foreground +// background + +var WallpaperManager = function () { + + var image = new Image () + var imageData + var w, h + + this.masks = [] + + this.init = function(){ + this.load() + } + + this.load = function(){ + image.onload = function(){ + this.loadImageData() + this.buildMasks() + app.tube('wallpaper-ready') + }.bind(this) + + image.src = "/assets/img/palette.gif" + } + + this.loadImageData = function(){ + var canvas = document.createElement('canvas') + var ctx = canvas.getContext('2d') + w = canvas.width = image.naturalWidth + h = canvas.height = image.naturalHeight + ctx.drawImage(image, 0,0) + imageData = ctx.getImageData(0,0,image.naturalWidth,image.naturalHeight).data + } + + this.buildMasks = function(){ + var mask + for (var y = 0; y < 6; y++) { + for (var x = 0; x < 16; x++) { + mask = this.buildMask(x,y) + this.masks.push(mask) + } + } + } + + this.buildMask = function(x,y){ + // add the offset of the top-left swatch + x = (x * 18) + 15 + y = (y * 16) + 5 + + var mask = new Array(64) + var t = 0 + for (var i = 0; i < 8; i++) { + for (var j = 0; j < 8; j++) { + t = ( w*(y+j) + x+i ) * 4 + mask[j*8+i] = imageData[t] === 0 + } + } + return mask + } + + this.buildSwatches = function(black, white, scale) { + var swatches = this.masks.map(function(mask){ + return this.buildSwatch(mask,black,white,scale) + }.bind(this)) + + return swatches + } + + this.buildSwatch = function(mask,black,white,scale){ + black = 'rgba(' + black.join(',') + ')' + white = 'rgba(' + white.join(',') + ')' + var canvas = document.createElement("canvas") + canvas.width = 8*scale + canvas.height = 8*scale + var ctx = canvas.getContext('2d') + for (var i = 0; i < 8; i++) { + for (var j = 0; j < 8; j++) { + ctx.fillStyle = mask[j*8+i] ? black : white + ctx.fillRect(i*scale, j*scale, scale, scale) + } + } + return canvas + } + +}
\ No newline at end of file diff --git a/public/assets/javascripts/ui/lib/FormView.js b/public/assets/javascripts/ui/lib/FormView.js index 0106ce0..219952d 100644 --- a/public/assets/javascripts/ui/lib/FormView.js +++ b/public/assets/javascripts/ui/lib/FormView.js @@ -26,9 +26,9 @@ var FormView = View.extend({ this.$errorList.append('<div>' + errors[i] + '</div>'); } this.$errors.css("opacity", 1.0); - setTimeout($.proxy(function(){ + setTimeout(function(){ this.$errors.show().css("opacity", 1.0); - }, this), 200) + }.bind(this), 200) } }, diff --git a/public/assets/javascripts/ui/lib/Parser.js b/public/assets/javascripts/ui/lib/Parser.js index 705ff04..dfff7b2 100644 --- a/public/assets/javascripts/ui/lib/Parser.js +++ b/public/assets/javascripts/ui/lib/Parser.js @@ -2,12 +2,18 @@ var Parser = { integrations: [{ type: 'image', regex: /\.(jpeg|jpg|gif|png|svg)(\?.*)?$/i, - async: false, fetch: function(url, done) { var img = new Image () img.onload = function(){ - done("", "", img.naturalWidth, img.naturalHeight, "") + var width = img.naturalWidth, height = img.naturalHeight img = null + done({ + token: "", + thumbnail: "", + title: "", + width: width, + height: height, + }) } img.src = url if (img.complete) { @@ -18,9 +24,30 @@ var Parser = { return '<img src="' + media.url + '" onerror="imgError(this);">'; } }, { + type: 'video', + regex: /\.(mp4|webm)(\?.*)?$/i, + fetch: function(url, done) { + var video = document.createElement("video") + video.addEventListener("loadedmetadata", function(){ + var width = video.videoWidth, height = video.videoHeight + video = null + done({ + token: "", + thumbnail: "", + title: "", + width: width, + height: height, + }) + }) + video.src = url + video.load() + }, + tag: function (media) { + return '<video src="' + media.url + '" onerror="imgError(this);">'; + } + }, { type: 'youtube', regex: /(?:youtube\.com\/(?:[^\/]+\/.+\/|(?:v|e(?:mbed)?)\/|.*[?&]v=)|youtu\.be\/)([^"&?\/ ]{11})/i, - async: false, fetch: function(url, done) { var id = (url.match(/v=([-_a-zA-Z0-9]{11})/i) || url.match(/youtu.be\/([-_a-zA-Z0-9]{11})/i) || url.match(/embed\/([-_a-zA-Z0-9]{11})/i))[1].split('&')[0]; var thumb = "http://i.ytimg.com/vi/" + id + "/hqdefault.jpg" @@ -34,8 +61,14 @@ var Parser = { part: "id,contentDetails,snippet,status", }, success: function(result){ - var res = res.items[0] - done(id, thumb, 640, 360, res.snippet.title); + var res = result.items[0] + done({ + token: id, + thumbnail: thumb, + title: res.snippet.title, + width: 640, + height: 360, + }) } }) }, @@ -45,7 +78,6 @@ var Parser = { }, { type: 'vimeo', regex: /vimeo.com\/\d+$/i, - async: true, fetch: function(url, done) { var id = url.match(/\d+$/i)[0]; $.ajax({ @@ -54,7 +86,13 @@ var Parser = { success: function(result){ if (result.length == 0) { return done(id, "", 640, 360) } var res = result[0] - done(id, res.thumbnail_large, res.width, res.height, res.title) + done({ + token: id, + thumbnail: res.thumbnail_large, + title: res.title, + width: res.width, + height: res.height, + }) } }) }, @@ -66,7 +104,6 @@ var Parser = { { type: 'soundcloud', regex: /soundcloud.com\/[-a-zA-Z0-9]+\/[-a-zA-Z0-9]+\/?$/i, - async: true, fetch: function (url, done) { $.ajax({ type: 'GET', @@ -75,7 +112,13 @@ var Parser = { + '&client_id=' + '0673fbe6fc794a7750f680747e863b10', success: function(result) { - done(result.id, ""); + done({ + token: result.id, + thumbnail: "", + title: "", + width: 100, + height: 100, + }) } }); }, @@ -87,9 +130,14 @@ var Parser = { }, { type: 'link', regex: /^http.+/i, - async: false, fetch: function(url, done) { - done("", "") + done({ + token: "", + thumbnail: "", + title: "", + width: 100, + height: 100, + }) }, tag: function (media) { return '<a href="' + media.url + '" target="_blank">' + media.url + '</a>' @@ -101,16 +149,10 @@ var Parser = { parse: function (url, cb) { var matched = Parser.integrations.some(function(integration){ if (integration.regex.test(url)) { - integration.fetch(url, function(token, thumbnail, width, height, title){ - cb({ - token: token, - thumbnail: thumbnail, - type: integration.type, - title: title, - width: width, - height: height, - url: url, - }) + integration.fetch(url, function(res){ + res.url = url + res.type = integration.type + cb(res) }) return true } diff --git a/public/assets/javascripts/ui/lib/Router.js b/public/assets/javascripts/ui/lib/Router.js index 214603c..d27654a 100644 --- a/public/assets/javascripts/ui/lib/Router.js +++ b/public/assets/javascripts/ui/lib/Router.js @@ -10,6 +10,10 @@ var Router = View.extend({ path[i] = null } } + + if (path[path.length-1] == null) { + path.pop() + } for (var route in this.routes) { var routePath = route.split("/") diff --git a/public/assets/javascripts/ui/lib/View.js b/public/assets/javascripts/ui/lib/View.js index 5fc6736..999a0e5 100644 --- a/public/assets/javascripts/ui/lib/View.js +++ b/public/assets/javascripts/ui/lib/View.js @@ -84,7 +84,11 @@ var View = (function($, _){ preventDefault: function(e){ e && e.preventDefault() - } + }, + + stopPropagation: function(e){ + e && e.stopPropagation() + }, }); diff --git a/public/assets/javascripts/ui/reader/MediaPlayer.js b/public/assets/javascripts/ui/reader/MediaPlayer.js new file mode 100644 index 0000000..df2d075 --- /dev/null +++ b/public/assets/javascripts/ui/reader/MediaPlayer.js @@ -0,0 +1,100 @@ + +var MediaPlayer = FormView.extend({ + el: "#mediaPlayer", + + events: { + "click [data-role=play-media]": "togglePaused", + "click [data-role=mute-media]": "toggleMuted", + "mousedown": "stopPropagation", + }, + + initialize: function(opt){ + this.parent = opt.parent + this.__super__.initialize.call(this) + + this.$name = this.$(".name") + this.$description = this.$(".description") + + // image fields + this.$dimensions = this.$(".dimensions") + + // video fields + this.$playButton = this.$("[data-role=play-media]") + this.$muteButton = this.$("[data-role=mute-media]") + }, + + toggle: function(state) { + this.$el.toggleClass("active", state); + }, + + togglePaused: function(state){ + var state = this.scenery.toggle(state) + this.$playButton.toggleClass("paused", ! state) + }, + + toggleMuted: function(state){ + var state = this.scenery.toggleMuted(state) + this.$muteButton.toggleClass("muted", state) + }, + + pick: function(scenery) { + var media = scenery.media + + if (this.scenery) { + this.unbind() + } + if (media.type == "image") { + if ((! media.title || ! media.title.length) && (! media.description || ! media.description.length)) { + this.hide() + return + } + } + + this.bind(scenery) + this.$el.addClass("active") + + this.$name.html(media.title) + this.$description.html(media.description) + + switch (media.type) { + case "image": + this.$(".image").show() + this.$(".video").hide() + +// this.$widthDimension.html( Number(media.widthDimension) || "" ) +// this.$heightDimension.html( Number(media.heightDimension) || "" ) +// this.$units.html( media.units || "cm" ) + + break + + case "youtube": + case "vimeo": + case "video": + this.$(".video").show() + this.$(".image").hide() + + this.$playButton.toggleClass("paused", ! this.scenery.paused()) + this.$muteButton.toggleClass("muted", this.scenery.muted()) + + break + } + }, + + hide: function(scenery){ + if (this.scenery) { + this.unbind() + } + this.toggle(false) + }, + + bind: function(scenery){ + this.scenery = scenery + this.scenery.mx.bound = true + }, + + unbind: function(){ + this.scenery.mx.bound = false + this.scenery = null + }, + +}) diff --git a/public/assets/javascripts/ui/reader/ReaderView.js b/public/assets/javascripts/ui/reader/ReaderView.js index 001d097..9d38daa 100644 --- a/public/assets/javascripts/ui/reader/ReaderView.js +++ b/public/assets/javascripts/ui/reader/ReaderView.js @@ -2,17 +2,24 @@ var ReaderView = View.extend({ el: "#readerView", - projectAction: "/api/projects/", + projectAction: "/api/project/", events: { }, initialize: function(){ + this.mediaPlayer = new MediaPlayer ({ parent: this }) }, load: function(name){ + if (window.location.search.indexOf("noui") !== -1) { + $(".logo,.topLinks,#editorView").hide() + } + if (window.location.search.indexOf("mute") !== -1) { + app.muted = true + } name = sanitize(name) - $.get(this.projectAction + name, $.proxy(this.ready, this)) + $.get(this.projectAction + name, this.ready.bind(this)) }, ready: function(data){ @@ -23,6 +30,45 @@ var ReaderView = View.extend({ data.startPosition && scene.camera.move(data.startPosition) editor.permissions.clear() + + this.listen() + }, + + listen: function(){ + var base = this + + $(window).on('message', function(event){ + if (event.originalEvent.origin !== window.location.origin) { + return + } + var message = event.originalEvent.data + switch (message) { + case "spin-on": + base.spinning = true + break + case "spin-off": + base.spinning = false + break + } + }) + + requestAnimationFrame(this.spin.bind(this)) + }, + + spinning: false, + spin: function(){ + requestAnimationFrame(this.spin.bind(this)) + if (this.spinning) { + scene.camera.rotationY -= 1/180 + } + }, + + pick: function(scenery){ + this.mediaPlayer.pick(scenery) + }, + + hideExtras: function(){ + this.mediaPlayer.hide() } }) diff --git a/public/assets/javascripts/ui/site/DocumentModal.js b/public/assets/javascripts/ui/site/DocumentModal.js index 6f16169..067977d 100644 --- a/public/assets/javascripts/ui/site/DocumentModal.js +++ b/public/assets/javascripts/ui/site/DocumentModal.js @@ -20,7 +20,7 @@ var DocumentModal = ModalFormView.extend({ this.action = this.updateAction - $.get("/api/docs", { name: name }, $.proxy(function(data){ + $.get("/api/docs", { name: name }, function(data){ if (data.isNew) { this.action = this.createAction } @@ -31,7 +31,7 @@ var DocumentModal = ModalFormView.extend({ this.$("[name='new_name']").val(name) this.show() - }, this)) + }.bind(this)) }, success: function(res){ diff --git a/public/assets/javascripts/ui/site/EditProfileModal.js b/public/assets/javascripts/ui/site/EditProfileModal.js index 6b89ad8..b023923 100644 --- a/public/assets/javascripts/ui/site/EditProfileModal.js +++ b/public/assets/javascripts/ui/site/EditProfileModal.js @@ -6,7 +6,7 @@ var EditProfileModal = ModalFormView.extend({ load: function(){ this.reset() - $.get("/api/profile", $.proxy(function(data){ + $.get("/api/profile", function(data){ console.log(data) for (var i in data) { @@ -23,7 +23,7 @@ var EditProfileModal = ModalFormView.extend({ } this.show() - }, this)) + }.bind(this)) }, validate: function(){ diff --git a/public/assets/javascripts/ui/site/EditProjectModal.js b/public/assets/javascripts/ui/site/EditProjectModal.js index 356d8b7..20baa54 100644 --- a/public/assets/javascripts/ui/site/EditProjectModal.js +++ b/public/assets/javascripts/ui/site/EditProjectModal.js @@ -31,7 +31,7 @@ var EditProjectModal = ModalView.extend({ var fields = this.$form.serializeArray() var request = $.post(this.action, $.param(fields)); - request.done($.proxy(function (response) { + request.done(function (response) { if (response.error) { this.$errors.show(); for (var key in response.error.errors) { @@ -42,7 +42,7 @@ var EditProjectModal = ModalView.extend({ else { window.location.href = "/profile" } - }, this)); + }.bind(this)); } }) diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js index 46ed634..4948b0e 100644 --- a/public/assets/javascripts/ui/site/LayoutsModal.js +++ b/public/assets/javascripts/ui/site/LayoutsModal.js @@ -3,23 +3,30 @@ var LayoutsIndex = View.extend({ initialize: function(){ this.$templates = this.$(".templates") + this.$noTemplates = this.$(".no-templates") + this.$form = this.$("form") }, load: function(type){ this.$templates.children("span").remove() - $.get(this.action, $.proxy(this.populate, this)) + $.get(this.action, this.populate.bind(this)) }, populate: function(data){ - data.forEach($.proxy(function(room){ + if (! data.length) { + this.$templates.hide() + this.$form.hide() + this.$noTemplates.show() + } + data.forEach(function(room){ var $span = $("<span>") // $span.html(JSON.stringify(room)) $span.data("slug", room.slug) $span.css("background-image", "url(" + room.photo + ")") this.$templates.append($span) - }, this)) + }.bind(this)) this.show() } @@ -28,7 +35,7 @@ var LayoutsIndex = View.extend({ var ProjectsModal = ModalView.extend(LayoutsIndex.prototype).extend({ el: ".mediaDrawer.projects", - action: "/api/projects", + action: "/api/project", events: { "click .templates span": 'toggleActive', @@ -65,7 +72,7 @@ var ProjectsModal = ModalView.extend(LayoutsIndex.prototype).extend({ var LayoutsModal = ModalView.extend(LayoutsIndex.prototype).extend({ el: ".mediaDrawer.layouts", - action: "/api/layouts", + action: "/api/layout", events: { "click .templates span": 'toggleActive', @@ -93,7 +100,7 @@ var LayoutsModal = ModalView.extend(LayoutsIndex.prototype).extend({ var NewProjectModal = ModalView.extend(LayoutsIndex.prototype).extend({ el: ".mediaDrawer.newProject", - action: "/api/layouts", + action: "/api/layout", events: { "click .templates span": 'toggleActive', diff --git a/public/assets/javascripts/ui/site/PasswordForgot.js b/public/assets/javascripts/ui/site/PasswordForgot.js new file mode 100644 index 0000000..ecbfc07 --- /dev/null +++ b/public/assets/javascripts/ui/site/PasswordForgot.js @@ -0,0 +1,26 @@ +var PasswordForgot = ModalFormView.extend({ + el: ".mediaDrawer.passwordForgot", + action: "/auth/forgotPassword", + + validate: function(){ + var errors = [] + + var email = this.$("#emailInput").val() + + if (! email.length) { + errors.push("Please enter your email address"); + } + if (email.indexOf("@") === -1) { + errors.push("Sorry, that is not a valid email address"); + } + + return errors + }, + + success: function(res){ + AlertModal.alert("Check your email, you should receive further instructions momentarily.", function(e){ + window.location.href = "/" + }) + }, + +}) diff --git a/public/assets/javascripts/ui/site/PasswordReset.js b/public/assets/javascripts/ui/site/PasswordReset.js new file mode 100644 index 0000000..9b87d37 --- /dev/null +++ b/public/assets/javascripts/ui/site/PasswordReset.js @@ -0,0 +1,31 @@ +var PasswordReset = ModalFormView.extend({ + el: ".mediaDrawer.passwordReset", + action: "/auth/password", + + load: function(){ + var opt = JSON.parse( $("#opt").html() ) + this.$("[name=nonce]").val( opt.nonce ) + this.__super__.load.call(this) + }, + + validate: function(){ + var errors = [] + + var pw1 = this.$("#passwordInput1").val() + var pw2 = this.$("#passwordInput2").val() + + if (! pw1.length) { + errors.push("Please enter a password"); + } + if (pw1 !== pw2) { + errors.push("Passwords don't match"); + } + + return errors + }, + + success: function(res){ + window.location.href = "/profile" + } + +}) diff --git a/public/assets/javascripts/ui/site/ProfileView.js b/public/assets/javascripts/ui/site/ProfileView.js new file mode 100644 index 0000000..8661bcd --- /dev/null +++ b/public/assets/javascripts/ui/site/ProfileView.js @@ -0,0 +1,28 @@ + +var ProfileView = View.extend({ + + initialize: function() { + }, + + load: function() { + var classes = ['one', 'two', 'three', 'four', + 'five', 'six', 'seven', 'eight', + 'nine', 'ten', 'eleven', 'twelve', + 'thirteen']; + $(".bio").addClass(choice(classes)); + + $("td.border").each(function() { + var iframe = $(this).find("iframe").get('0') + if (! iframe) return + $(this).on({ + mouseenter: function(e){ + iframe.contentWindow.postMessage("spin-on", window.location.origin) + }, + mouseleave: function(e){ + iframe.contentWindow.postMessage("spin-off", window.location.origin) + } + }) + }) + } + +}) diff --git a/public/assets/javascripts/ui/site/UsernameTaken.js b/public/assets/javascripts/ui/site/UsernameTaken.js new file mode 100644 index 0000000..fc9f50a --- /dev/null +++ b/public/assets/javascripts/ui/site/UsernameTaken.js @@ -0,0 +1,27 @@ +var UsernameTaken = ModalFormView.extend({ + el: ".mediaDrawer.usernameTaken", + action: "/auth/usernameTaken", + + load: function(){ + var opt = JSON.parse( $("#opt").html() ) + this.$("#usernameThatIsTaken").html( opt.username ) + this.__super__.load.call(this) + }, + + validate: function(){ + var errors = [] + + var username = this.$("#usernameInput").val() + + if (! username.length) { + errors.push("Please enter a username"); + } + + return errors + }, + + success: function(res){ + window.location.href = "/profile" + } + +}) diff --git a/public/assets/javascripts/util.js b/public/assets/javascripts/util.js index b58da1f..58dcc3a 100644 --- a/public/assets/javascripts/util.js +++ b/public/assets/javascripts/util.js @@ -176,4 +176,3 @@ function bitcount(v) { v = (v & 0x33333333) + ((v >>> 2) & 0x33333333); return ((v + (v >>> 4) & 0xF0F0F0F) * 0x1010101) >>> 24; } - diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css index 77b1d04..61a4fa9 100755 --- a/public/assets/stylesheets/app.css +++ b/public/assets/stylesheets/app.css @@ -58,6 +58,17 @@ a{ } +.floatingSwatch { + width: 50px; + height: 50px; + position:absolute; + border: 2px solid black; + box-shadow: -2px 2px #fff; + display: none; + z-index: 10; + pointer-events: none; +} + .ants { max-width:320px; height: auto; @@ -158,10 +169,21 @@ h5 { .page table.showcase { height:70vh; } -.page table td.border{ - border-right:1px solid; +.page table td.border { + position: relative; + border-right: 1px solid; +} +iframe.embed { + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + border: 0; + z-index: -1; + pointer-events: none; } -.page table td{ +.page table td { width: 33.3333%; background-size: cover; background-repeat: no-repeat; @@ -169,7 +191,7 @@ h5 { border-bottom:1px solid black; } -.page table.showcase td{ +.page table.showcase td { height: 70vh; background-size: cover; } @@ -208,6 +230,7 @@ h5 { color:white; } +/* .room1 { position: relative; overflow: hidden; @@ -261,6 +284,7 @@ h5 { -webkit-transform:translateY(0); transform:translateY(0); } +*/ .page .questions { background: #55efcb; @@ -445,6 +469,9 @@ h5 { .templates { } +.no-templates { + display: none; +} .templates span{ background-position: center; @@ -511,19 +538,27 @@ h5 { cursor: -webkit-grabbing; cursor: -moz-grabbing; } -.mx-object3d.image, .mx-object3d canvas, +.mx-object3d.image, +.mx-object3d.video, +.mx-object3d canvas, .mx-object3d.backface-hidden { -webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; -ms-backface-visibility: hidden; backface-visibility: hidden; } -.mx-object3d.backface-visible, .mx-object3d.backface-visible canvas{ +.mx-object3d.backface-visible, +.mx-object3d.backface-visible canvas{ -webkit-backface-visibility: visible; -moz-backface-visibility: visible; -ms-backface-visibility: visible; backface-visibility: visible; } +.mx-object3d iframe, +.mx-object3d video { + pointer-events: none; +} + #hud { position: fixed; top:0;left:0; @@ -721,8 +756,10 @@ h5 { -webkit-transform:translateY(0%); transform:translateY(0%); } +.mediaDrawer.table, .mediaDrawer.error, .mediaDrawer.signin, .mediaDrawer.signup, -.mediaDrawer.alert, .mediaDrawer.confirm, .mediaDrawer.error, +.mediaDrawer.alert, .mediaDrawer.confirm, +.mediaDrawer.passwordForgot, .mediaDrawer.passwordReset, .mediaDrawer.usernameTaken, .mediaDrawer.layouts, .mediaDrawer.projects, .mediaDrawer.newProject { display:table; } @@ -968,7 +1005,7 @@ h5 { border:1px dashed black; cursor:pointer; } -.mediaContainer img{ +.mediaContainer img, .mediaContainer video { max-width:100%; } @@ -1083,7 +1120,7 @@ input[type=range] { -webkit-appearance: none; -moz-appearance: none; background-color: black; - width: 200px; + width: 180px; height:3px; } @@ -1096,6 +1133,11 @@ input[type="range"]::-webkit-slider-thumb { cursor:pointer; } +.settings.info { + right: auto; + left: 10px; +} + .settings { padding: 20px; bottom: 20px; @@ -1153,13 +1195,15 @@ input[type="range"]::-webkit-slider-thumb { #startpoint.active:hover { text-decoration:none; } -.settings input[type="text"], textarea{ +.settings input[type="text"] { border: 1px solid #000; font-size: 15px; padding: 5px; } .settings textarea { + border: 1px solid #000; + padding: 5px; font-size: 12px; width: 100%; max-height: 200px; @@ -1170,7 +1214,7 @@ input[type="range"]::-webkit-slider-thumb { border: 1px solid #000; } -.settings .setting{ +.settings .setting { margin-bottom:10px; } .setting.subButtons { @@ -1187,6 +1231,77 @@ input[type="range"]::-webkit-slider-thumb { .settings .setting:last-child{ margin-bottom:0px; } +.settings input[type="text"].number { + width: 60px; +} + +.setting label { + font-size: 12px; + font-weight: 300; + padding-right: 5px; +} +.setting.number label { + width: 50px; + display: inline-block; + float: left; + position: relative; + top: 5px; +} +.setting.number.halflines { + height: 30px; +} +.setting.number.halflines input[type=text] { + float: left; + width: 60px; +} +.setting.number.halflines label:nth-of-type(2) { + text-align: center; + width: 30px; +} + +.setting.number input[type=text] { + width: 150px; +} +.setting.number.twoline label { + top: 0px; +} + +.playButton,.muteButton { + color: white; + background: black; + border-radius: 50px; + font-size: 22px; + padding: 4px 2px 3px 6px; + cursor: pointer; + margin-right: 5px; +} +.playButton .on { + display: inline; +} +.playButton.paused .on { + display: none; +} +.playButton .off { + display: none; +} +.playButton.paused .off { + display: inline; +} + +.muteButton .on { + display: inline; + padding-right: 3px; +} +.muteButton.muted .on { + display: none; +} +.muteButton .off { + display: none; +} +.muteButton.muted .off { + display: inline; + padding-right: 3px; +} button { padding: 8px; @@ -1266,7 +1381,6 @@ button:hover { form { max-width: 440px; margin: 0 auto; - } form div { float:right; @@ -1350,23 +1464,23 @@ form li textarea { margin-top: 20px; } -.video { +.demo .video { height:80vh; min-height:300px; } -.video span { +.demo .video span { font-size:100px; color:white; cursor:pointer; } -.video span.videoTitle { +.demo .video span.videoTitle { font-size: 29px; font-weight: 300; padding: 3px 7px; } -.video span.icon-ios7-play-outline:hover { +.demo .video span.icon-ios7-play-outline:hover { color:lightgreen; } @@ -1406,7 +1520,7 @@ form li textarea { background:lightgreen; } */ -.box b.info { +.box b.signin-tagline { display: inline-block; width: 100%; margin-bottom: 18px; @@ -1456,6 +1570,7 @@ form li textarea { bottom: 10px; padding-right:10px; background:rgba(255,255,255,0.95); + z-index: 2; } .share h2 { diff --git a/public/rectangles.html b/public/rectangles.html deleted file mode 100644 index befe15c..0000000 --- a/public/rectangles.html +++ /dev/null @@ -1,124 +0,0 @@ -<!doctype html> -<html> -<head> - <link rel="stylesheet" type="text/css" href="assets/stylesheets/css.css"> -<style type="text/css"> -body { background: #fff; } -body > div { - float: left; -} -#info { - padding: 30px; -} -#hud { - position: absolute; - top:0;left:0; - z-index: 10; -} -.face { - background-color: #fff; - transition: 0.1s background-color ease; -} -.front { background-color: #fff; } -.back { background-color: #fff; } -.left { background-color: #fff; } -.right { background-color: #fff; } -.floor { background-color: #eee; } -.ceiling { background-color: rgba(230,230,255,0.3); } - -.active.floor { background-color: #ffe; } -.active.ceiling { background-color: rgba(230,230,255,0.3); } - -.dragging .mx-object3d.image { - pointer-events: none; -} - -.dot { - background:white; - border-radius:20px; - border: 1px solid black; -} - -.image { - background-size: 100% 100%; -} - -/* -.face { - background-image: url(http://i.asdf.us/im/6f/bgdither_1398274442_jules.gif); - background-color: transparent; -} - */ - -#map canvas { - border-bottom: 2px solid #ddd; - border-right: 2px solid #ddd; -} -</style> -</head> -<body> - <div id="bg"></div> - <div id="scene"></div> - - <div id="hud"> - <div id="map" style="display: block"> - </div> - - <div id="info"> - <select id="palette"> - <option>colors</option> - <option>redblue</option> - <option>gray</option> - <option selected>bone</option> - <option>alpha</option> - <option>white</option> - <option>black</option> - </select> - <div id="intersects"></div> - </div> - </div> - -</body> -<script src="assets/javascripts/vendor/jquery.min.js"></script> -<script type="text/javascript" src="assets/javascripts/vendor/tube.js"></script> -<script type="text/javascript" src="assets/javascripts/vendor/loader.js"></script> -<script type="text/javascript" src="assets/javascripts/vendor/polyfill.js"></script> -<script type="text/javascript" src="assets/javascripts/util.js"></script> - -<script type="text/javascript" src="assets/javascripts/rectangles/_env.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/util/colors.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/util/constants.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/util/debug.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/util/sort.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/util/wheel.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/util/mouse.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/util/keys.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/models/room.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/models/wall.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/models/tree.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/models/rect.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/models/vec2.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/models/vec3.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/models/mat4.js"></script> - -<script type="text/javascript" src="assets/javascripts/rectangles/engine/rooms/_rooms.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/engine/rooms/builder.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/engine/rooms/clipper.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/engine/rooms/mover.js"></script> - -<script type="text/javascript" src="assets/javascripts/rectangles/engine/scenery/_scenery.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/engine/scenery/image/_image.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/engine/scenery/image/move.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/engine/scenery/image/resize.js"></script> - -<script type="text/javascript" src="assets/javascripts/rectangles/engine/map/_map.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/engine/map/ui.js"></script> -<script type="text/javascript" src="assets/javascripts/rectangles/engine/map/draw.js"></script> - -<script src="assets/javascripts/mx/mx.js"></script> -<script src="assets/javascripts/mx/extensions/mx.scene.js"></script> -<script src="assets/javascripts/mx/extensions/mx.movements.js"></script> -<script src="assets/javascripts/mx/primitives/mx.image.js"></script> -<script src="assets/javascripts/app.js"></script> - -</html> |
