summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--public/assets/javascripts/app.js17
-rw-r--r--public/assets/javascripts/mx/extensions/mx.movementsMobile.js124
-rw-r--r--public/assets/javascripts/rectangles/models/rect.js4
-rw-r--r--public/assets/javascripts/rectangles/models/vec2.js3
-rw-r--r--public/assets/javascripts/rectangles/util/undo.js42
-rw-r--r--public/assets/javascripts/ui/_router.js22
-rw-r--r--public/assets/javascripts/ui/editor/EditorSettings.js2
-rw-r--r--public/assets/javascripts/ui/editor/EditorToolbar.js15
-rw-r--r--public/assets/javascripts/ui/editor/LightControl.js10
-rw-r--r--public/assets/javascripts/ui/editor/WallpaperPicker.js10
-rw-r--r--public/assets/javascripts/ui/lib/Router.js21
-rw-r--r--public/assets/javascripts/ui/site/LayoutsModal.js8
-rw-r--r--public/assets/javascripts/util.js2
-rw-r--r--server/index.js3
-rw-r--r--server/lib/views.js2
-rw-r--r--test/00-setup.js1
-rw-r--r--test/09-test-undo.js163
-rw-r--r--views/partials/scripts.ejs1
18 files changed, 411 insertions, 39 deletions
diff --git a/public/assets/javascripts/app.js b/public/assets/javascripts/app.js
index 1419d1d..ad3c601 100644
--- a/public/assets/javascripts/app.js
+++ b/public/assets/javascripts/app.js
@@ -27,11 +27,7 @@ app.init = function () {
}
app.launch = function () {
- var mainbox,
- coords,
- box, size,
- floor,
- movements
+ var movements
scene = new MX.Scene().addTo('#scene')
scene.width = window.innerWidth
@@ -50,14 +46,19 @@ app.launch = function () {
if (MX.Map) map = app.map = new MX.Map()
- movements = app.movements = new MX.Movements(cam, viewHeight)
- movements.init()
+ if (is_mobile) {
+ app.movements = new MX.MobileMovements(cam, viewHeight)
+ }
+ else {
+ app.movements = new MX.Movements(cam, viewHeight)
+ }
+ app.movements.init()
function animate (t) {
requestAnimationFrame(animate)
environment.update(t)
window.path && path.update(t)
- movements.update()
+ app.movements.update()
scene.update()
}
diff --git a/public/assets/javascripts/mx/extensions/mx.movementsMobile.js b/public/assets/javascripts/mx/extensions/mx.movementsMobile.js
new file mode 100644
index 0000000..994c8d7
--- /dev/null
+++ b/public/assets/javascripts/mx/extensions/mx.movementsMobile.js
@@ -0,0 +1,124 @@
+
+MX.MobileMovements = function (cam) {
+
+ var touching = true,
+ moving = false,
+ startTime = null,
+ v = 12,
+ vr = Math.PI * 0.012,
+ vx = vy = vz = 0;
+
+ var directionLocked = false,
+ directionLockThreshold = 5
+
+ var pos = { x: 0, y: viewHeight, z: 0, rotationX: 0, rotationY: 0 }
+
+ var pointX, pointY, deltaX, deltaY, distX = 0, distY = 0, absDistX = 0, absDistY = 0, startTime
+
+ return {
+
+ init: function () {
+ document.addEventListener("touchstart", function(e){
+ if (e.touches.length == 1) {
+ touching = true
+
+ startTime = Date.now()
+
+ var point = event.touches[0]
+ pointX = point.pageX
+ pointY = point.pageY
+ distX = distY = 0
+ pos.x = cam.x
+ pos.z = cam.z
+ pos.rotationY = cam.rotationY
+ }
+ })
+ document.addEventListener("touchmove", function(e){
+ e.preventDefault()
+ if (e.touches.length == 1) {
+
+ var timestamp = Date.now()
+ var point = event.touches[0]
+ deltaX = point.pageX - pointX
+ deltaY = point.pageY - pointY
+
+ pointX = point.pageX
+ pointY = point.pageY
+
+ distX += deltaX
+ distY += deltaY
+ absDistX = abs(distX)
+ absDistY = abs(distY)
+ }
+ })
+ document.addEventListener("touchend", function(e){
+ e.preventDefault()
+ if (e.touches.length == 0) {
+ touching = directionLocked = false
+ var timestamp = Date.now()
+ var duration = startTime - timestamp
+ if (duration < 300) {
+ }
+ }
+ })
+ },
+
+ update: function () {
+ if (distX || distY) {
+ var oldDistY = absDistY, oldDistX = absDistX
+ absDistY = avg(absDistY, 0, 5)
+ var dy = (oldDistY - absDistY) * sign(distY) * 2
+
+ absDistX = avg(absDistX, 0, 5)
+ var dx = (oldDistX - absDistX) * sign(distX) * 2
+
+ distY = sign(distY) * absDistY
+ distX = sign(distX) * absDistX
+
+ pos.x -= dy * Math.cos(pos.rotationY + Math.PI / 2)
+ pos.z -= dy * Math.sin(pos.rotationY + Math.PI / 2)
+ pos.rotationY += dx / (window.innerWidth) * Math.PI / 2
+ cam.rotationY = pos.rotationY
+
+ app.tube("move", pos)
+ }
+ },
+
+ lock: function(){ locked = true },
+ unlock: function(){ locked = false },
+ scale: function(n){ if (n) scale = n; return scale },
+ resetScale: function(n){ scale = DEFAULT_SCALE },
+ gravity: function(g){ return typeof g == "boolean" ? gravity = g : gravity },
+ velocity: function(n){ v = clamp(n, 1, 50) },
+ jumpVelocity: function(n){ jumpV = clamp(n, 1, 50) },
+ }
+
+}
+
+
+// function momentum (current, start, time, lowerMargin, wrapperSize, deceleration) {
+// var distance = current - start,
+// speed = Math.abs(distance) / time,
+// destination,
+// duration;
+//
+// deceleration = deceleration === undefined ? 0.0006 : deceleration;
+//
+// destination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );
+// duration = speed / deceleration;
+//
+// if ( destination < lowerMargin ) {
+// destination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;
+// distance = Math.abs(destination - current);
+// duration = distance / speed;
+// } else if ( destination > 0 ) {
+// destination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;
+// distance = Math.abs(current) + destination;
+// duration = distance / speed;
+// }
+//
+// return {
+// destination: Math.round(destination),
+// duration: duration
+// };
+// }
diff --git a/public/assets/javascripts/rectangles/models/rect.js b/public/assets/javascripts/rectangles/models/rect.js
index 500ee6d..ec32ab7 100644
--- a/public/assets/javascripts/rectangles/models/rect.js
+++ b/public/assets/javascripts/rectangles/models/rect.js
@@ -110,6 +110,10 @@
Rect.prototype.fits = function(v){
return this.x.length() >= v.a && this.y.length() >= v.b
}
+ Rect.prototype.zero = function(){
+ this.a.zero()
+ this.b.zero()
+ }
Rect.prototype.nearEdge = function (x, y, r) {
var edges = 0
if (x < this.x.a+r) {
diff --git a/public/assets/javascripts/rectangles/models/vec2.js b/public/assets/javascripts/rectangles/models/vec2.js
index 2bf286b..104c6f7 100644
--- a/public/assets/javascripts/rectangles/models/vec2.js
+++ b/public/assets/javascripts/rectangles/models/vec2.js
@@ -55,6 +55,9 @@
this.b /= n
return this
}
+ vec2.prototype.zero = function(){
+ this.a = this.b = 0
+ }
vec2.prototype.setPosition = function(n){
var len = this.length()
this.a = n
diff --git a/public/assets/javascripts/rectangles/util/undo.js b/public/assets/javascripts/rectangles/util/undo.js
new file mode 100644
index 0000000..3700817
--- /dev/null
+++ b/public/assets/javascripts/rectangles/util/undo.js
@@ -0,0 +1,42 @@
+(function(){
+
+ var UndoStack = function(){
+ this.stack = []
+ this.types = {}
+ this.pointer = -1
+ }
+ UndoStack.prototype.push = function(action){
+ this.pointer++
+ this.stack[this.pointer] = action
+ this.purge()
+ }
+ UndoStack.prototype.purge = function(){
+ if (this.stack.length-1 == this.pointer) return
+ this.stack.length = this.pointer+1
+ }
+ UndoStack.prototype.undo = function(){
+ if (this.pointer == -1) return false
+ var action = this.stack[this.pointer]
+ this.types[ action.type ].undo(action)
+ this.pointer--
+ return this.pointer > -1
+ }
+ UndoStack.prototype.redo = function(){
+ if (this.pointer == this.stack.length-1) return false
+ this.pointer++
+ var action = this.stack[this.pointer]
+ this.types[ action.type ].redo(action)
+ return this.pointer < this.stack.length-1
+ }
+ UndoStack.prototype.register = function(actionType){
+ this.types[ actionType.type ] = actionType
+ }
+
+ if ('window' in this) {
+ window.UndoStack = new UndoStack
+ }
+ else {
+ module.exports = new UndoStack
+ }
+
+})()
diff --git a/public/assets/javascripts/ui/_router.js b/public/assets/javascripts/ui/_router.js
index 4ff3581..d07810e 100644
--- a/public/assets/javascripts/ui/_router.js
+++ b/public/assets/javascripts/ui/_router.js
@@ -36,11 +36,18 @@ var SiteRouter = Router.extend({
"/project": 'projectPicker',
"/project/new": 'newProject',
"/project/new/:layout": 'projectNewWithLayout',
- "/project/:name": 'project',
+ "/project/:name": 'projectViewer',
+ "/project/:name/edit": 'projectEditor',
"/project/:name/view": 'projectViewer',
"/test/wallpaper": 'testWallpaper',
},
+
+ mobileRoutes: {
+ "/": 'home',
+ "/profile": 'profile',
+ "/project/:name": 'projectViewer',
+ },
initialize: function(){
this.signUpModal = new SignUpModal()
@@ -56,6 +63,11 @@ var SiteRouter = Router.extend({
this.route()
+ if (is_mobile) {
+ $(".topLinks").hide()
+ $(".share").hide()
+ }
+
$("body").removeClass("loading")
},
@@ -123,14 +135,6 @@ var SiteRouter = Router.extend({
this.readerView.load(name)
},
-/*
- editProject: function(e){
- e && e.preventDefault()
- window.history.pushState(null, document.title, "/project/edit")
- this.editProjectModal.load()
- },
-*/
-
signup: function(e){
e && e.preventDefault()
window.history.pushState(null, document.title, "/signup")
diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js
index 13a6f60..d6a79fb 100644
--- a/public/assets/javascripts/ui/editor/EditorSettings.js
+++ b/public/assets/javascripts/ui/editor/EditorSettings.js
@@ -130,7 +130,7 @@ var EditorSettings = FormView.extend({
this.$name.val(data.name)
this.action = this.updateAction
- window.history.pushState(null, document.title, "/project/" + data.slug)
+ window.history.pushState(null, document.title, "/project/" + data.slug + "/edit")
},
})
diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js
index a3abc5a..5e0da7e 100644
--- a/public/assets/javascripts/ui/editor/EditorToolbar.js
+++ b/public/assets/javascripts/ui/editor/EditorToolbar.js
@@ -30,6 +30,7 @@ var EditorToolbar = View.extend({
this.parent.mediaViewer.show()
this.parent.mediaUpload.show()
this.resetMode()
+ this.resetControls()
},
resetMode: function(){
@@ -43,6 +44,7 @@ var EditorToolbar = View.extend({
},
resizeMedia: function(e, state){
+ this.resetControls()
if (! state && typeof e == "boolean") {
state = e
editor.permissions.assign("resize", state)
@@ -59,6 +61,7 @@ var EditorToolbar = View.extend({
},
destroyMedia: function(e, state){
+ this.resetControls()
if (! state && typeof e == "boolean") {
state = e
editor.permissions.assign("destroy", state)
@@ -73,11 +76,19 @@ var EditorToolbar = View.extend({
},
toggleWallpaper: function(){
- this.parent.wallpaperPicker.toggle()
+ var state = ! $("[data-role='toggle-wallpaper-panel']").hasClass("inuse")
+ this.resetMode()
+ $("[data-role='toggle-wallpaper-panel']").toggleClass("inuse", state)
+ this.parent.lightControl.hide()
+ this.parent.wallpaperPicker.toggle(state)
},
toggleLightControl: function(){
- this.parent.lightControl.toggle()
+ var state = ! $("[data-role='toggle-light-control']").hasClass("inuse")
+ this.resetMode()
+ $("[data-role='toggle-light-control']").toggleClass("inuse", state)
+ this.parent.wallpaperPicker.hide()
+ this.parent.lightControl.toggle(state)
},
editWallText: function(){
diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js
index 93d97ed..c3e80c2 100644
--- a/public/assets/javascripts/ui/editor/LightControl.js
+++ b/public/assets/javascripts/ui/editor/LightControl.js
@@ -6,12 +6,18 @@ var LightControl = View.extend({
"mousedown": "stopPropagation",
},
- toggle: function(){
- this.$el.toggleClass("active");
+ toggle: function(state){
+ this.$el.toggleClass("active", state);
// toggle the class that makes the cursor a paintbucket
// $("body").removeClass("pastePaper");
},
+ show: function(){
+ this.toggle(true)
+ },
+ hide: function(){
+ this.toggle(false)
+ },
/*
$("#shadow-control").on({
diff --git a/public/assets/javascripts/ui/editor/WallpaperPicker.js b/public/assets/javascripts/ui/editor/WallpaperPicker.js
index cb1e361..9ee441b 100644
--- a/public/assets/javascripts/ui/editor/WallpaperPicker.js
+++ b/public/assets/javascripts/ui/editor/WallpaperPicker.js
@@ -23,11 +23,17 @@ var WallpaperPicker = View.extend({
wm.init()
},
- toggle: function(){
- this.$el.toggleClass("active");
+ toggle: function(state){
+ this.$el.toggleClass("active", state);
// toggle the class that makes the cursor a paintbucket
// $("body").removeClass("pastePaper");
},
+ show: function(){
+ this.toggle(true)
+ },
+ hide: function(){
+ this.toggle(false)
+ },
pick: function(e){
var $swatch = $(e.currentTarget)
diff --git a/public/assets/javascripts/ui/lib/Router.js b/public/assets/javascripts/ui/lib/Router.js
index 5877f93..0b6385c 100644
--- a/public/assets/javascripts/ui/lib/Router.js
+++ b/public/assets/javascripts/ui/lib/Router.js
@@ -4,7 +4,8 @@ var Router = View.extend({
this.originalPath = window.location.pathname
- var pathname = window.location.pathname,
+ var routes = is_mobile ? this.mobileRoutes : this.routes,
+ pathname = window.location.pathname,
path = pathname.split("/");
for (var i = 0; i < path.length; i++) {
@@ -13,7 +14,7 @@ var Router = View.extend({
}
}
- if (pathname in this.routes) {
+ if (pathname in routes) {
this[this.routes[pathname]](null)
}
@@ -21,35 +22,39 @@ var Router = View.extend({
path.pop()
}
- for (var route in this.routes) {
+ for (var route in routes) {
var routePath = route.split("/")
if (routePath[1] == path[1]) {
if (routePath[2] && routePath[2].indexOf(":") !== -1 && path[2] && (path[3] === routePath[3]) ) {
this[this.routes[route]](null, path[2])
- break;
+ return
}
else if (routePath[2] == path[2]) {
if (routePath[3] && path[3]) {
if (routePath[3].indexOf(":") !== -1) {
this[this.routes[route]](null, path[3])
- break;
+ return
}
else if (routePath[3] == path[3]) {
this[this.routes[route]](null)
- break;
+ return
}
}
else if (! routePath[3] && ! path[3]) {
this[this.routes[route]](null)
- break;
+ return
}
}
else if (! routePath[2] && (! path[2].length || ! path[2])) {
this[this.routes[route]](null)
- break;
+ return
}
}
}
+
+ if (is_mobile) {
+ window.location.href = "/"
+ }
}
})
diff --git a/public/assets/javascripts/ui/site/LayoutsModal.js b/public/assets/javascripts/ui/site/LayoutsModal.js
index 4948b0e..f109ec3 100644
--- a/public/assets/javascripts/ui/site/LayoutsModal.js
+++ b/public/assets/javascripts/ui/site/LayoutsModal.js
@@ -19,6 +19,7 @@ var LayoutsIndex = View.extend({
this.$form.hide()
this.$noTemplates.show()
}
+ this.$templates.empty()
data.forEach(function(room){
var $span = $("<span>")
// $span.html(JSON.stringify(room))
@@ -58,7 +59,7 @@ var ProjectsModal = ModalView.extend(LayoutsIndex.prototype).extend({
$layout.addClass("active")
// actually do
- window.location.pathname = "/project/" + $layout.data("slug")
+ window.location.pathname = "/project/" + $layout.data("slug") + "/edit"
},
newProject: function(e){
@@ -103,7 +104,7 @@ var NewProjectModal = ModalView.extend(LayoutsIndex.prototype).extend({
action: "/api/layout",
events: {
- "click .templates span": 'toggleActive',
+ "click .templates span": 'choose',
"submit form": 'choose',
},
@@ -115,7 +116,8 @@ var NewProjectModal = ModalView.extend(LayoutsIndex.prototype).extend({
choose: function(e){
e && e.preventDefault()
- var layout = this.$(".templates .active").data("slug")
+// var layout = this.$(".templates .active").data("slug")
+ var layout = $(e.currentTarget).data("slug")
if (! layout || ! layout.length) return
window.location.pathname = "/project/new/" + layout
}
diff --git a/public/assets/javascripts/util.js b/public/assets/javascripts/util.js
index 58dcc3a..b92dcf3 100644
--- a/public/assets/javascripts/util.js
+++ b/public/assets/javascripts/util.js
@@ -31,7 +31,7 @@ function quantize(n,a){ return round(n / a) * a }
function max(a,b){ return Math.max(a,b) }
function min(a,b){ return Math.min(a,b) }
function abs(n){ return Math.abs(n) }
-function sign(n){ return Math.abs(n)/n }
+function sign(n){ return n ? Math.abs(n)/n : 0 }
function pow(n,b) { return Math.pow(n,b) }
function exp(n) { return Math.exp(n) }
function log(n){ return Math.log(n) }
diff --git a/server/index.js b/server/index.js
index ad437ff..e6afdb8 100644
--- a/server/index.js
+++ b/server/index.js
@@ -120,8 +120,9 @@ site.route = function () {
app.get('/project', middleware.ensureAuthenticated, views.modal)
app.get('/project/new', middleware.ensureAuthenticated, views.modal)
app.get('/project/new/:layout', middleware.ensureAuthenticated, views.editor)
- app.get('/project/:slug', middleware.ensureProject, views.editor)
+ app.get('/project/:slug', middleware.ensureProject, views.reader)
app.get('/project/:slug/view', middleware.ensureProject, views.reader)
+ app.get('/project/:slug/edit', middleware.ensureProject, views.editor)
app.get('/api/layout', middleware.ensureAuthenticated, api.layouts.index)
app.get('/api/layout/:slug', middleware.ensureAuthenticated, api.layouts.show)
diff --git a/server/lib/views.js b/server/lib/views.js
index 81e2ced..27b7446 100644
--- a/server/lib/views.js
+++ b/server/lib/views.js
@@ -45,7 +45,7 @@ views.editor = function (req, res) {
}
views.reader = function (req, res) {
- if (! req.user && ! req.project) {
+ if (! req.project) {
res.redirect('/')
}
User.findOne({ _id: req.project.user_id }, function(err, user) {
diff --git a/test/00-setup.js b/test/00-setup.js
index 78ad2c4..20f9d66 100644
--- a/test/00-setup.js
+++ b/test/00-setup.js
@@ -1,2 +1 @@
Error.stackTraceLimit = 5
-
diff --git a/test/09-test-undo.js b/test/09-test-undo.js
new file mode 100644
index 0000000..84b5d09
--- /dev/null
+++ b/test/09-test-undo.js
@@ -0,0 +1,163 @@
+var assert = require("assert")
+var UndoStack = require("../public/assets/javascripts/rectangles/util/undo.js")
+
+describe('undo', function(){
+
+ var state = "zero"
+
+ describe('#register()', function(){
+
+ UndoStack.register({
+ type: "demo",
+ undo: function(action){
+ state = action.prev
+ },
+ redo: function(action){
+ state = action.next
+ },
+ })
+
+ it('registers undoable actions', function(){
+ assert( UndoStack.types.hasOwnProperty("demo") )
+ })
+ })
+
+ describe('#push()', function(){
+
+ it('starts empty', function(){
+ assert.equal(0, UndoStack.stack.length)
+ assert.equal(-1, UndoStack.pointer)
+ })
+
+ it('pushes some actions', function(){
+
+ UndoStack.push({
+ type: "demo",
+ prev: state,
+ next: "one"
+ })
+ state = "one"
+
+ UndoStack.push({
+ type: "demo",
+ prev: state,
+ next: "two"
+ })
+ state = "two"
+
+ UndoStack.push({
+ type: "demo",
+ prev: state,
+ next: "three"
+ })
+ state = "three"
+
+ assert.equal(3, UndoStack.stack.length)
+ assert.equal(2, UndoStack.pointer)
+ })
+ })
+
+ describe('#undo()', function(){
+
+ it('retrieves old state', function(){
+ assert.equal("three", state)
+ UndoStack.undo()
+ assert.equal("two", state)
+ assert.equal(1, UndoStack.pointer)
+ })
+
+ it('can only undo so far', function(){
+ var canUndo
+
+ canUndo = UndoStack.undo()
+ assert.equal("one", state)
+ assert.equal(0, UndoStack.pointer)
+ assert.equal(true, canUndo)
+
+ canUndo = UndoStack.undo()
+ assert.equal("zero", state)
+ assert.equal(-1, UndoStack.pointer)
+ assert.equal(false, canUndo)
+
+ canUndo = UndoStack.undo()
+ assert.equal("zero", state)
+ assert.equal(-1, UndoStack.pointer)
+ assert.equal(false, canUndo)
+ })
+
+ })
+
+ describe('#redo()', function(){
+
+ it('reassigns new state', function(){
+ UndoStack.redo()
+ assert.equal("one", state)
+ })
+
+ it('can only redo so far', function(){
+ var canRedo
+
+ canRedo = UndoStack.redo()
+ assert.equal("two", state)
+ assert.equal(true, canRedo)
+
+ canRedo = UndoStack.redo()
+ assert.equal("three", state)
+ assert.equal(false, canRedo)
+
+ canRedo = UndoStack.redo()
+ assert.equal("three", state)
+ assert.equal(false, canRedo)
+ })
+
+ it('clobbers old state if we undo then do something else', function(){
+ UndoStack.undo()
+ assert.equal("two", state)
+ assert.equal(1, UndoStack.pointer)
+
+ UndoStack.undo()
+ assert.equal("one", state)
+ assert.equal(0, UndoStack.pointer)
+ assert.equal(3, UndoStack.stack.length)
+
+ UndoStack.push({
+ type: "demo",
+ prev: state,
+ next: "four"
+ })
+ state = "four"
+
+ assert.equal(1, UndoStack.pointer)
+ assert.equal(2, UndoStack.stack.length)
+
+ UndoStack.undo()
+ assert.equal("one", state)
+ assert.equal(0, UndoStack.pointer)
+ assert.equal(2, UndoStack.stack.length)
+
+ UndoStack.redo()
+ assert.equal("four", state)
+ assert.equal(1, UndoStack.pointer)
+ assert.equal(2, UndoStack.stack.length)
+ })
+ })
+
+})
+
+// 1) push action
+// 2) push action
+// 3) push action
+// undo 3
+// undo 2
+// undo 1
+// undo * can't undo anymore
+// redo 1
+// redo 2
+// redo 3
+// redo * can't redo anymore
+// undo 3
+// 4) push action (clobbers action 3)
+// undo 4
+// undo 2
+// redo 2
+// redo 4
diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs
index acb3bff..3d783b0 100644
--- a/views/partials/scripts.ejs
+++ b/views/partials/scripts.ejs
@@ -12,6 +12,7 @@
<script type="text/javascript" src="/assets/javascripts/mx/mx.js"></script>
<script type="text/javascript" src="/assets/javascripts/mx/extensions/mx.scene.js"></script>
<script type="text/javascript" src="/assets/javascripts/mx/extensions/mx.movements.js"></script>
+<script type="text/javascript" src="/assets/javascripts/mx/extensions/mx.movementsMobile.js"></script>
<script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.image.js"></script>
<script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.video.js"></script>
<script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.youtube.js"></script>