summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bower.json3
-rw-r--r--public/assets/img/text-cursor.pngbin0 -> 1622 bytes
-rw-r--r--public/assets/javascripts/defaults.js5
-rw-r--r--public/assets/javascripts/mx/extensions/mx.movements.js8
-rw-r--r--public/assets/javascripts/mx/primitives/mx.text.js73
-rw-r--r--public/assets/javascripts/rectangles/engine/rooms/projector.js30
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/_scenery.js4
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/resize.js16
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/types/image.js2
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/types/text.js75
-rw-r--r--public/assets/javascripts/rectangles/engine/scenery/types/video.js2
-rw-r--r--public/assets/javascripts/rectangles/models/mat4.js78
-rw-r--r--public/assets/javascripts/rectangles/models/wall.js95
-rw-r--r--public/assets/javascripts/ui/editor/EditorToolbar.js3
-rw-r--r--public/assets/javascripts/ui/editor/EditorView.js14
-rw-r--r--public/assets/javascripts/ui/editor/LightControl.js33
-rw-r--r--public/assets/javascripts/ui/editor/MediaEditor.js15
-rw-r--r--public/assets/javascripts/ui/editor/TextEditor.js107
-rw-r--r--public/assets/javascripts/ui/reader/MediaPlayer.js4
-rw-r--r--public/assets/javascripts/ui/reader/ReaderView.js4
-rwxr-xr-xpublic/assets/stylesheets/app.css45
-rw-r--r--public/assets/test/bg.html114
-rw-r--r--views/controls/editor/light-control.ejs10
-rw-r--r--views/controls/editor/text-editor.ejs10
-rw-r--r--views/controls/editor/toolbar.ejs18
-rw-r--r--views/partials/scripts.ejs14
26 files changed, 566 insertions, 216 deletions
diff --git a/bower.json b/bower.json
index faffbfb..5f35d6c 100644
--- a/bower.json
+++ b/bower.json
@@ -8,6 +8,7 @@
"lodash": "",
"fiber": "",
"jquery-jsonview": "1.2.0",
- "prefixfree": ""
+ "prefixfree": "",
+ "marked": "0.3.2"
}
}
diff --git a/public/assets/img/text-cursor.png b/public/assets/img/text-cursor.png
new file mode 100644
index 0000000..66e9e0d
--- /dev/null
+++ b/public/assets/img/text-cursor.png
Binary files differ
diff --git a/public/assets/javascripts/defaults.js b/public/assets/javascripts/defaults.js
index 038a882..9ba0b4d 100644
--- a/public/assets/javascripts/defaults.js
+++ b/public/assets/javascripts/defaults.js
@@ -12,3 +12,8 @@ app.defaults = {
ceiling: [255,255,255],
},
}
+
+marked.setOptions({
+ sanitize: true,
+ smartypants: true,
+})
diff --git a/public/assets/javascripts/mx/extensions/mx.movements.js b/public/assets/javascripts/mx/extensions/mx.movements.js
index 4627cd3..f94bbc2 100644
--- a/public/assets/javascripts/mx/extensions/mx.movements.js
+++ b/public/assets/javascripts/mx/extensions/mx.movements.js
@@ -51,7 +51,6 @@ MX.Movements = function (cam) {
moveForward = true
break
- case 37: // left
case 65: // a
moveLeft = true
break
@@ -61,15 +60,16 @@ MX.Movements = function (cam) {
moveBackward = true
break
- case 39: // right
case 68: // d
moveRight = true
break
+ case 37: // left
case 81: // q
turnLeft = true
break
+ case 39: // right
case 69: // e
turnRight = true
break
@@ -132,7 +132,6 @@ MX.Movements = function (cam) {
moveForward = false
break
- case 37: // left
case 65: // a
moveLeft = false
break
@@ -142,15 +141,16 @@ MX.Movements = function (cam) {
moveBackward = false
break
- case 39: // right
case 68: // d
moveRight = false
break
+ case 37: // left
case 81: // q
turnLeft = false
break
+ case 39: // right
case 69: // e
turnRight = false
break
diff --git a/public/assets/javascripts/mx/primitives/mx.text.js b/public/assets/javascripts/mx/primitives/mx.text.js
index 9c7af5c..1d975ec 100644
--- a/public/assets/javascripts/mx/primitives/mx.text.js
+++ b/public/assets/javascripts/mx/primitives/mx.text.js
@@ -3,34 +3,55 @@ MX.Text = MX.Object3D.extend({
init: function (ops) {
this.type = "Text"
-
- var layer = new MX.Object3D('text')
- layer.width = ops.width || 100
- layer.height = ops.height || 50
- layer.x = ops.x || 0
- layer.y = ops.y || 0
- layer.z = ops.z || 0
- layer.scale = ops.scale || 1
- layer.el.innerHTML = ops.value || ""
- if (ops.id) layer.el.id = ops.id;
- if (ops.background) layer.el.style.background = ops.background;
- if (ops.color) layer.el.style.color = ops.color;
- if (ops.fontSize) layer.el.style.fontSize = ops.fontSize + "px";
- this.add(layer)
+ this.type = "Image"
+ 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
- this.children.forEach(function (c, i) {
- if (ops.classname) {
- c.el.classList.add(ops.classname)
- }
- else {
- }
- c.el.style.backgroundRepeat = 'no-repeat'
- })
+ this.scale = ops.scale || 1
+ 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
+
+ ops.className && this.el.classList.add(ops.className)
+ this.backface && this.el.classList.add("backface-visible")
+ this.el.classList.add("mx-text")
+ this.el.classList.add("mx-scenery")
+
+ this.inner = document.createElement("div")
+ this.inner.classList.add("inner")
+ this.el.appendChild(this.inner)
+
+ this.load(ops)
+ },
+
+ load: function(ops){
+ var media = ops.media
+ if (media.color) this.el.style.color = media.color;
+ if (media.font) this.setFont(media.font)
- this.dirty = true
- this.updateChildren = true
- this.update()
- }
+ this.setText( media.description )
+ },
+
+ setFont: function(font){
+ this.inner.style.fontFamily = "'" + font.family + "',sans-serif"
+ this.el.style.fontSize = (2 * font.size) + "pt"
+ this.el.style.textAlign = font.align
+ },
+
+ setText: function(text){
+ this.inner.innerHTML = marked( text || "" )
+ },
})
diff --git a/public/assets/javascripts/rectangles/engine/rooms/projector.js b/public/assets/javascripts/rectangles/engine/rooms/projector.js
deleted file mode 100644
index 2eac314..0000000
--- a/public/assets/javascripts/rectangles/engine/rooms/projector.js
+++ /dev/null
@@ -1,30 +0,0 @@
-
-rooms.projector = new function(){
-
- projector = new THREE.Projector();
- vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
- projector.unprojectVector( vector, camera );
-
- raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
- intersects = raycaster.intersectObjects( scene.children, true );
-
-}
-
-
-
-THREE.Projector = function () {
-
- _viewProjectionMatrix = new THREE.Matrix4(),
-
- this.unprojectVector = function ( vector, camera ) {
- camera.projectionMatrixInverse.getInverse( camera.projectionMatrix );
-
- _viewProjectionMatrix.multiplyMatrices(
- camera.matrixWorld,
- camera.projectionMatrixInverse
- );
-
- return vector.applyProjection( _viewProjectionMatrix );
- };
-
-}
diff --git a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js
index 69e9ba7..3d3067f 100644
--- a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js
+++ b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js
@@ -24,6 +24,10 @@ var Scenery = new function(){
case 'vimeo':
scene_media = new Scenery.types.video (opt)
break
+
+ case 'text':
+ scene_media = new Scenery.types.text (opt)
+ break
}
base.list[scene_media.id] = scene_media
return scene_media
diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js
index 893237c..0ce976e 100644
--- a/public/assets/javascripts/rectangles/engine/scenery/resize.js
+++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js
@@ -117,22 +117,13 @@ Scenery.resize = new function(){
base.bind = function(){
dots.forEach(function(dot){
Scenery.mouse.bind_el(dot.el)
- $(dot.el).bind({
- mouseenter: function(e){
-// Scenery.resize.hovering = true
- },
- mouseleave: function(e){
-// Scenery.resize.hovering = false
-// base.defer_hide()
- }
- })
})
Scenery.mouse.on("down", down)
Scenery.mouse.on("drag", drag)
Scenery.mouse.on("up", up)
}
- this.unbind = function(){
+ base.unbind = function(){
dots.forEach(function(dot){
Scenery.mouse.unbind_el(dot.el)
})
@@ -151,7 +142,6 @@ Scenery.resize = new function(){
naturalDimension = obj.naturalDimensions
dimension = obj.dimensions
position = new vec3(obj.mx.x, obj.mx.y, obj.mx.z)
- scale = obj.mx.scale
oldState = obj.serialize()
document.body.classList.add("dragging")
@@ -165,7 +155,6 @@ Scenery.resize = new function(){
var width = cursor.x.magnitude()
var height = cursor.y.magnitude()
var mag = cursor.magnitude()
- var old_width = dimension.a * scale
if (abs(width) > abs(height)) {
mag = x_sign * mag * sign(width)
@@ -175,9 +164,6 @@ Scenery.resize = new function(){
}
obj.set_scale( ( dimension.a + mag ) / naturalDimension.a )
- // dimension.a // scale * (old_width + mag) / old_width
-
-// console.log(scale, obj.mx.scale, dimension.a + mag, naturalDimension.a)
if (selected_dot.side & LEFT_RIGHT) {
obj.mx.x = position.a + cos(rotationY) * mag/2 * (x_sign)
diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/image.js b/public/assets/javascripts/rectangles/engine/scenery/types/image.js
index aa43341..bed847b 100644
--- a/public/assets/javascripts/rectangles/engine/scenery/types/image.js
+++ b/public/assets/javascripts/rectangles/engine/scenery/types/image.js
@@ -3,6 +3,8 @@ Scenery.types.image = Scenery.types.base.extend(function(base){
var exports = {
+ type: 'image',
+
init: function(opt){
opt.scale = opt.scale || (opt.data && opt.data.scale) || 300 / max(300, opt.media.width)
diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/text.js b/public/assets/javascripts/rectangles/engine/scenery/types/text.js
new file mode 100644
index 0000000..a10a332
--- /dev/null
+++ b/public/assets/javascripts/rectangles/engine/scenery/types/text.js
@@ -0,0 +1,75 @@
+
+Scenery.types.text = Scenery.types.base.extend(function(base){
+
+ var exports = {
+
+ type: 'text',
+
+ init: function(opt){
+
+ opt.scale = 0.5
+
+ base.init.call(this, opt)
+
+ this.build()
+ this.bind()
+
+ if (opt.data) {
+ if (opt.wall) {
+ var position = opt.wall.mxToPosition(opt.data.position)
+ opt.index = opt.wall.surface.index_for_x( position.a, 0 )
+ }
+ this.set_wall(opt)
+ this.deserialize(opt.data)
+ }
+ else {
+ this.set_wall(opt)
+ if (this.bounds) {
+ this.recenter()
+ if (opt.position) {
+ this.translateTo(opt.position)
+ }
+ var mx_position = this.wall.positionToMx( this.position, this.dimensions )
+ this.mx.move(mx_position)
+ }
+ }
+ },
+
+ build: function(){
+ this.mx = new MX.Text({
+ scale: this.scale,
+ media: this.media,
+ y: this.scale * this.media.height/2,
+ backface: false,
+ })
+ scene.add( this.mx )
+ },
+
+ setText: function(text){
+ this.media.description = text
+ this.mx.setText( text )
+ },
+
+ setFont: function(style){
+ for (var i in style) {
+ if (style.hasOwnProperty(i)) {
+ this.media.font[i] = style[i]
+ }
+ }
+ this.mx.setFont(this.media.font)
+ },
+
+ serialize: function(){
+ var data = base.serialize.call(this)
+ return data
+ },
+
+ deserialize: function(data){
+ this.mx.move(data.position)
+ this.mx.ops.width = data.dimensions.a
+ this.mx.ops.height = data.dimensions.b
+ },
+ }
+
+ return exports
+})
diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/video.js b/public/assets/javascripts/rectangles/engine/scenery/types/video.js
index 2ef6ec3..b723f56 100644
--- a/public/assets/javascripts/rectangles/engine/scenery/types/video.js
+++ b/public/assets/javascripts/rectangles/engine/scenery/types/video.js
@@ -2,6 +2,8 @@
Scenery.types.video = Scenery.types.base.extend(function(base){
var exports = {
+
+ type: 'video',
init: function(opt){
opt.scale = opt.scale || (opt.data && opt.data.scale) || 300 / max(300, opt.media.width)
diff --git a/public/assets/javascripts/rectangles/models/mat4.js b/public/assets/javascripts/rectangles/models/mat4.js
deleted file mode 100644
index b061199..0000000
--- a/public/assets/javascripts/rectangles/models/mat4.js
+++ /dev/null
@@ -1,78 +0,0 @@
-function mat4(e){
- this.elements = [ 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1 ]
- return this
-}
-mat4.prototype.set = function (a) {
- var els = this.elements
- a.forEach(function(n,i){ els[i] = n })
- return this
-}
-mat4.prototype.clone = function(){
- return (new mat4).set(this.els)
-}
-mat4.prototype.identity = function () {
- this.set([
- 1, 0, 0, 0,
- 0, 1, 0, 0,
- 0, 0, 1, 0,
- 0, 0, 0, 1
- ]);
- return this;
-}
-mat4.prototype.getInverse = function (m, throwOnInvertible) {
-
- // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
- var te = this.elements;
- var me = m.elements;
-
- var n11 = me[0], n12 = me[4], n13 = me[8], n14 = me[12];
- var n21 = me[1], n22 = me[5], n23 = me[9], n24 = me[13];
- var n31 = me[2], n32 = me[6], n33 = me[10], n34 = me[14];
- var n41 = me[3], n42 = me[7], n43 = me[11], n44 = me[15];
-
- te[0] = n23*n34*n42 - n24*n33*n42 + n24*n32*n43 - n22*n34*n43 - n23*n32*n44 + n22*n33*n44;
- te[4] = n14*n33*n42 - n13*n34*n42 - n14*n32*n43 + n12*n34*n43 + n13*n32*n44 - n12*n33*n44;
- te[8] = n13*n24*n42 - n14*n23*n42 + n14*n22*n43 - n12*n24*n43 - n13*n22*n44 + n12*n23*n44;
- te[12] = n14*n23*n32 - n13*n24*n32 - n14*n22*n33 + n12*n24*n33 + n13*n22*n34 - n12*n23*n34;
- te[1] = n24*n33*n41 - n23*n34*n41 - n24*n31*n43 + n21*n34*n43 + n23*n31*n44 - n21*n33*n44;
- te[5] = n13*n34*n41 - n14*n33*n41 + n14*n31*n43 - n11*n34*n43 - n13*n31*n44 + n11*n33*n44;
- te[9] = n14*n23*n41 - n13*n24*n41 - n14*n21*n43 + n11*n24*n43 + n13*n21*n44 - n11*n23*n44;
- te[13] = n13*n24*n31 - n14*n23*n31 + n14*n21*n33 - n11*n24*n33 - n13*n21*n34 + n11*n23*n34;
- te[2] = n22*n34*n41 - n24*n32*n41 + n24*n31*n42 - n21*n34*n42 - n22*n31*n44 + n21*n32*n44;
- te[6] = n14*n32*n41 - n12*n34*n41 - n14*n31*n42 + n11*n34*n42 + n12*n31*n44 - n11*n32*n44;
- te[10] = n12*n24*n41 - n14*n22*n41 + n14*n21*n42 - n11*n24*n42 - n12*n21*n44 + n11*n22*n44;
- te[14] = n14*n22*n31 - n12*n24*n31 - n14*n21*n32 + n11*n24*n32 + n12*n21*n34 - n11*n22*n34;
- te[3] = n23*n32*n41 - n22*n33*n41 - n23*n31*n42 + n21*n33*n42 + n22*n31*n43 - n21*n32*n43;
- te[7] = n12*n33*n41 - n13*n32*n41 + n13*n31*n42 - n11*n33*n42 - n12*n31*n43 + n11*n32*n43;
- te[11] = n13*n22*n41 - n12*n23*n41 - n13*n21*n42 + n11*n23*n42 + n12*n21*n43 - n11*n22*n43;
- te[15] = n12*n23*n31 - n13*n22*n31 + n13*n21*n32 - n11*n23*n32 - n12*n21*n33 + n11*n22*n33;
-
- var det = n11 * te[ 0 ] + n21 * te[ 4 ] + n31 * te[ 8 ] + n41 * te[ 12 ];
-
- if ( det == 0 ) {
- var msg = "Matrix4.getInverse(): can't invert matrix, determinant is 0";
-
- if ( throwOnInvertible || false ) {
- throw new Error( msg )
- }
- else {
- console.warn( msg )
- }
- this.identity();
- return this
- }
- this.multiplyScalar( 1 / det );
- return this
-}
-mat4.prototype.multiplyScalar = function (n) {
- var els = this.elements
- els[0] *= n; els[4] *= n; els[8] *= n; els[12] *= n
- els[1] *= n; els[5] *= n; els[9] *= n; els[13] *= n
- els[2] *= n; els[6] *= n; els[10] *= n; els[14] *= n
- els[3] *= n; els[7] *= n; els[11] *= n; els[15] *= n
- return this
-}
-
diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js
index fdc8d8c..820fb5f 100644
--- a/public/assets/javascripts/rectangles/models/wall.js
+++ b/public/assets/javascripts/rectangles/models/wall.js
@@ -68,14 +68,12 @@
},
*/
mousedown: function(e){
- if (Scenery.nextText) {
- }
- else if (Scenery.nextMedia) {
- var offset = offsetFromPoint(e, mx.el)
- if (! offset) { return }
+ var offset = offsetFromPoint(e, mx.el)
+ if (! offset) { return }
- var pos = base.mxOffsetToPosition( offset, index )
+ var pos = base.mxOffsetToPosition( offset, index )
+ if (Scenery.nextMedia) {
var scenery = Scenery.addNextToWall({
wall: base,
index: index,
@@ -91,13 +89,15 @@
app.controller.toolbar.resetPermissions()
Scenery.resize.show(scenery)
Scenery.hovering = true
+
+ app.controller.pick(scenery)
UndoStack.push({
type: 'create-scenery',
undo: { id: scenery.id },
redo: scenery.serialize(),
})
-
+
// TODO: watch individual scenery object here
Minotaur.watch( app.router.editorView.settings )
}
@@ -116,7 +116,7 @@
Minotaur.watch( app.router.editorView.settings )
}
else {
- app.controller.hideExtras()
+ app.controller.pickWall(base, pos)
}
}
})
@@ -214,22 +214,79 @@
}
Wall.prototype.wallpaper = function(background){
- var useX = this.side & FRONT_BACK
- var shouldFlip = this.side & (LEFT | BACK)
-
- this.background = background || "none"
+ if (! background) {
+ background = { src: "none" }
+ }
+ else if (typeof background == "string") {
+ background = { src: background }
+ }
+ else if (! background.src) {
+ background = { src: "none" }
+ }
+ background.x = background.x || 0
+ background.y = background.y || 0
+ background.scale = background.scale || 1
+
+ this.background = background
+ this.background.src = this.background.src.replace("url(","").replace(")","")
+
+ if (this.background.src == "none") {
+ this.wallpaperLoad(this.background.src)
+ return
+ }
+ var img = new Image ()
+ img.onload = function(){
+ this.backgroundImage = img
+ this.wallpaperLoad(this.background.src)
+ this.wallpaperPosition(background)
+ }.bind(this)
+ img.src = this.background.src
+ img.complete && img.onload()
+ }
+
+ Wall.prototype.wallpaperLoad = function(url){
+ if (url !== "none") {
+ url = "url(" + url + ")"
+ }
this.mx.forEach(function(mx){
- var partitionOffset = useX ? mx.x : mx.z
- if (shouldFlip) partitionOffset *= -1
- partitionOffset += mx.width/2
- var floorOffset = mx.y + mx.height/2
-
- mx.el.style.backgroundImage = background
- mx.el.style.backgroundPosition = (~~partitionOffset) + "px " + (~~floorOffset) + "px"
+ mx.el.style.backgroundImage = url
})
}
+
+ Wall.prototype.wallpaperPosition = function(background){
+ if (this.background.src == "none") { return }
+ this.background.x = background.x || this.background.x
+ this.background.y = background.y || this.background.y
+ this.background.scale = background.scale || this.background.scale || 1
+
+ var useX = this.side & FRONT_BACK
+ var shouldFlip = this.side & (LEFT | BACK)
+
+ var mx, dx, dy
+ var w = Math.round( this.backgroundImage.naturalWidth * this.background.scale )
+ var h = Math.round( this.backgroundImage.naturalHeight * this.background.scale )
+
+ this.surface.faces.forEach(function(face, i){
+
+ if (shouldFlip) {
+ mx = this.mx[this.mx.length-1-i]
+ dx = Math.round( this.background.x + face.x.a )
+ dy = Math.round( this.background.y + face.y.b )
+ }
+ else {
+ mx = this.mx[i]
+ dx = Math.round( this.background.x - face.x.b )
+ dy = Math.round( this.background.y + face.y.b )
+ }
+
+ mx.el.style.backgroundPosition = dx + 'px ' + dy + 'px'
+ mx.el.style.backgroundSize = w + 'px ' + h + 'px'
+ }.bind(this))
+ bbb = this
+ }
+
Wall.prototype.outline = function(wallColor, outlineColor){
var useX = this.side & FRONT_BACK
var mx = this.mx
diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js
index 513306d..49decc2 100644
--- a/public/assets/javascripts/ui/editor/EditorToolbar.js
+++ b/public/assets/javascripts/ui/editor/EditorToolbar.js
@@ -3,6 +3,7 @@ var EditorToolbar = View.extend({
el: "#editorToolbar",
events: {
+ "mousedown": 'stopPropagation',
"click [data-role='toggle-map-view']": 'toggleMap',
"click [data-role='toggle-project-settings']": 'toggleSettings',
"click [data-role='open-media-viewer']": 'openMediaViewer',
@@ -42,6 +43,7 @@ var EditorToolbar = View.extend({
// this.resizeMedia(true)
// this.destroyMedia(false)
$(".inuse").removeClass("inuse")
+ $("body").removeClass("addText")
this.parent.hideExtras()
this.resetPermissions()
},
@@ -131,6 +133,7 @@ var EditorToolbar = View.extend({
$("[data-role='toggle-text-editor']").toggleClass("inuse", state)
this.parent.mediaEditor.hide()
this.parent.wallpaperPicker.hide()
+ this.parent.lightControl.hide()
this.parent.settings.hide()
this.parent.textEditor.toggle(state)
},
diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js
index 83db532..f95d909 100644
--- a/public/assets/javascripts/ui/editor/EditorView.js
+++ b/public/assets/javascripts/ui/editor/EditorView.js
@@ -42,11 +42,23 @@ var EditorView = View.extend({
},
pick: function(scenery){
- this.mediaEditor.pick(scenery)
+ if (scenery.type == "text") {
+ this.mediaEditor.hide()
+ this.textEditor.pick(scenery)
+ }
+ else {
+ this.textEditor.hide()
+ this.mediaEditor.pick(scenery)
+ }
+ },
+
+ pickWall: function(wall, pos){
+ this.hideExtras()
},
hideExtras: function(){
this.mediaEditor.hide()
+ this.textEditor.hide()
Scenery.resize.hide()
Scenery.hovering = false
}
diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js
index 3eb2861..2b7cfaa 100644
--- a/public/assets/javascripts/ui/editor/LightControl.js
+++ b/public/assets/javascripts/ui/editor/LightControl.js
@@ -10,6 +10,7 @@ var LightControl = View.extend({
"input #brightness-control": "updateBrightness",
"input #outline-hue": "updateShadow",
"input #wall-hue": "updateShadow",
+ "click .presets span": "selectPreset",
},
initialize: function(){
@@ -114,6 +115,38 @@ var LightControl = View.extend({
this.setMode(mode)
},
+ presets: {
+ wireframe: {
+ wall: [255,255,255],
+ outline: [0,0,0],
+ floor: [246,246,246],
+ ceiling: [255,255,255],
+ },
+ shaded: {
+ wall: [205,205,204],
+ outline: [0,0,0],
+ floor: [109,116,106],
+ ceiling: [159,163,157],
+ },
+ pfunk: {
+ wall: [255,63,78],
+ outline: [255,246,0],
+ floor: [255,255,0],
+ ceiling: [225,118,252],
+ },
+ seapunk: {
+ wall: [110,255,255],
+ outline: [146,133,255],
+ floor: [89,221,255],
+ ceiling: [139,255,173],
+ },
+ },
+ selectPreset: function(e){
+ var preset = $(e.currentTarget).data('preset')
+ if (! this.presets[preset]) return
+ this.load(this.presets[preset])
+ },
+
beginBrightness: function(){
this.begin()
$(window).one("mouseup", this.finalize.bind(this))
diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js
index e4f93df..9b81db1 100644
--- a/public/assets/javascripts/ui/editor/MediaEditor.js
+++ b/public/assets/javascripts/ui/editor/MediaEditor.js
@@ -76,7 +76,6 @@ var MediaEditor = FormView.extend({
case "image":
this.$(".image").show()
this.$(".video").hide()
-
break
case "youtube":
@@ -90,7 +89,6 @@ var MediaEditor = FormView.extend({
this.$loop.prop('checked', !! media.loop)
this.$mute.prop('checked', !! media.mute)
this.$keyframe.val( Number(media.keyframe || 0) )
-
break
}
},
@@ -162,11 +160,12 @@ var MediaEditor = FormView.extend({
},
unbind: function(){
- if (this.scenery && this.tainted) {
- this.scenery.media.title = this.$name.val()
- this.scenery.media.description = this.$description.val()
- Minotaur.watch( app.router.editorView.settings )
-
+ if (this.scenery) {
+ if (this.tainted) {
+ this.scenery.media.title = this.$name.val()
+ this.scenery.media.description = this.$description.val()
+ Minotaur.watch( app.router.editorView.settings )
+ }
if (this.scenery.mx) {
this.scenery.mx.bound = false
this.scenery.mx.el.classList.remove("picked")
@@ -177,8 +176,6 @@ var MediaEditor = FormView.extend({
},
destroy: function(){
-// ConfirmModal.confirm("Are you sure you want delete this object?", function(){
-// }.bind(this))
var scenery = this.scenery
this.hide()
Scenery.remove(scenery.id)
diff --git a/public/assets/javascripts/ui/editor/TextEditor.js b/public/assets/javascripts/ui/editor/TextEditor.js
index 0319a31..1e35c12 100644
--- a/public/assets/javascripts/ui/editor/TextEditor.js
+++ b/public/assets/javascripts/ui/editor/TextEditor.js
@@ -1,6 +1,8 @@
var TextEditor = FormView.extend({
el: "#textEditor",
+ tainted: false,
+ scenery: null,
events: {
"keydown": 'taint',
@@ -8,21 +10,103 @@ var TextEditor = FormView.extend({
"mousedown": "stopPropagation",
"change [name=font-family]": 'changeFontFamily',
"change [name=font-size]": 'changeFontSize',
+ "change [name=text-align]": 'changeTextAlign',
"input [name=text-body]": 'changeText',
- "click [data-role=destroy-media]": "destroy",
+ "click [data-role=destroy-text]": "destroy",
},
initialize: function(opt){
this.parent = opt.parent
this.__super__.initialize.call(this)
+ this.$settings = this.$(".setting")
+ this.$noTextMessage = this.$(".no-text")
this.$fontFamily = this.$("[name=font-family]")
this.$fontSize = this.$("[name=font-size]")
this.$textBody = this.$("[name=text-body]")
+ this.$textAlign = this.$("[name=text-align]")
},
toggle: function(state){
- this.$el.toggleClass("active", state);
+ $("#keyhint").fadeOut(200)
+
+ this.$el.toggleClass("active", state)
+ if (state) {
+ Scenery.nextMedia = {
+ type: 'text',
+ width: 600,
+ height: 450,
+ scale: 0.5,
+ font: { family: 'Lato', size: 12, align: 'left' },
+ }
+
+ this.createMode(true)
+ }
+ },
+
+ hide: function(scenery){
+ if (this.scenery) {
+ this.unbind()
+ }
+ this.toggle(false)
+ },
+
+ taint: function(e){
+ e.stopPropagation()
+ this.tainted = true
+ },
+
+ bind: function(scenery){
+ this.tainted = false
+ this.scenery = scenery
+ this.scenery.mx.bound = true
+ this.scenery.mx.el.classList.add("picked")
+ },
+
+ unbind: function(){
+ if (this.scenery) {
+ if (this.tainted) {
+ Minotaur.watch( app.router.editorView.settings )
+ }
+
+ if (this.scenery.mx) {
+ this.scenery.mx.bound = false
+ this.scenery.mx.el.classList.remove("picked")
+ }
+ }
+ this.tainted = false
+ this.scenery = null
+ },
+
+ createMode: function(state){
+ this.$settings.toggle(! state)
+ this.$noTextMessage.toggle(!! state)
+ $("body").toggleClass("addText", !! state)
+ },
+
+ pick: function(scenery){
+ if (this.scenery) {
+ this.unbind()
+ }
+
+ Scenery.resize.show(scenery)
+ Scenery.hovering = true
+
+ this.bind(scenery)
+ this.$el.toggleClass("active", true)
+ this.$textBody.val( this.scenery.media.description )
+
+ this.$fontFamily.val( this.scenery.media.font.family )
+ this.$fontSize.val( this.scenery.media.font.size )
+ this.$textAlign.val( this.scenery.media.font.align )
+
+ this.createMode(false)
+
+ if (! this.scenery.media.description) {
+ setTimeout(function(){
+ this.$textBody.focus()
+ }.bind(this), 100)
+ }
},
taint: function(e){
@@ -30,12 +114,29 @@ var TextEditor = FormView.extend({
},
changeFontFamily: function(){
+ this.scenery.setFont({ family: this.$fontFamily.val() })
+ },
+
+ changeTextAlign: function(){
+ this.scenery.setFont({ align: this.$textAlign.val() })
},
changeFontSize: function(){
+ var size = parseInt( this.$fontSize.val() )
+ size && this.scenery.setFont({ size: size })
},
- changeText: function(){
+ changeText: function(e){
+ e.stopPropagation()
+ var text = this.$textBody.val()
+ this.scenery.setText(text)
},
+
+ destroy: function(){
+ var scenery = this.scenery
+ this.hide()
+ Scenery.remove(scenery.id)
+ Scenery.resize.hide()
+ },
})
diff --git a/public/assets/javascripts/ui/reader/MediaPlayer.js b/public/assets/javascripts/ui/reader/MediaPlayer.js
index df2d075..6195ab6 100644
--- a/public/assets/javascripts/ui/reader/MediaPlayer.js
+++ b/public/assets/javascripts/ui/reader/MediaPlayer.js
@@ -53,8 +53,8 @@ var MediaPlayer = FormView.extend({
this.bind(scenery)
this.$el.addClass("active")
- this.$name.html(media.title)
- this.$description.html(media.description)
+ this.$name.html( sanitize(media.title) )
+ this.$description.html( marked(media.description) )
switch (media.type) {
case "image":
diff --git a/public/assets/javascripts/ui/reader/ReaderView.js b/public/assets/javascripts/ui/reader/ReaderView.js
index 82db048..5f2db0f 100644
--- a/public/assets/javascripts/ui/reader/ReaderView.js
+++ b/public/assets/javascripts/ui/reader/ReaderView.js
@@ -78,6 +78,10 @@ var ReaderView = View.extend({
app.tube("pick-scenery", { scenery: scenery })
},
+ pickWall: function(wall, pos){
+ this.hideExtras()
+ },
+
hideExtras: function(){
this.mediaPlayer.hide()
app.tube("close-scenery")
diff --git a/public/assets/stylesheets/app.css b/public/assets/stylesheets/app.css
index 988dd89..6a034ea 100755
--- a/public/assets/stylesheets/app.css
+++ b/public/assets/stylesheets/app.css
@@ -4,9 +4,11 @@
margin:0;
padding:0;
outline:0;
- font-family: 'Lato', sans-serif;
-webkit-font-smoothing: subpixel-antialiased;
}
+body,textarea,input {
+ font-family: 'Lato', sans-serif;
+}
*, *:before, *:after {
moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box;
@@ -412,12 +414,16 @@ iframe.embed {
.page h1 {
font-size: 80px;
font-weight: 100;
- padding: 20px 0 25px 0;
+ padding: 60px 0 25px 0;
float: left;
width: 100%;
border-top: 1px solid;
}
+.page p {
+ margin: 20px;
+}
+
/* DOCUMENTATION / ABOUT SECTION / FAQ PAGES */
.docs .content {
@@ -667,9 +673,12 @@ iframe.embed {
-webkit-box-sizing: content-box;
box-sizing: content-box;
}
-.destroyActive .mx-scene, .destroyActive .mx-object3d.image, .menu span.inuse[data-role="destroy-media"] {
+.destroyActive .mx-scene, .destroyActive .mx-object3d.image {
cursor:url(/assets/img/delete-cursor.png), auto;
}
+.addText .mx-scene, .menu span.inuse[data-role="toggle-text-editor"] {
+ cursor:url(/assets/img/text-cursor.png), auto;
+}
.mx-scenery:active {
cursor: pointer;
@@ -695,6 +704,16 @@ iframe.embed {
.mx-object3d video {
pointer-events: none;
}
+.mx-text {
+ overflow: hidden;
+}
+.mx-text .inner {
+ width: 100%;
+ pointer-events: none;
+}
+.mx-text p {
+ margin-bottom: 1em;
+}
#keyhint {
position: fixed;
bottom:0;
@@ -1410,6 +1429,7 @@ h4 {
input[type=range] {
-webkit-appearance: none;
-moz-appearance: none;
+ cursor: pointer;
background-color: black;
width: 180px;
height:3px;
@@ -1455,13 +1475,17 @@ input[type="range"]::-webkit-slider-thumb {
.color-swatches {
margin-top: 10px;
}
-.color-swatches.defaults {
+.presets {
margin-top: 10px;
}
-.color-swatches.defaults span{
+.presets span {
font-size:12px;
font-weight:500;
+ display: inline-block;
+ width: 50%;
+ float:left;
+ cursor:pointer;
}
.color-swatches span {
display: inline-block;
@@ -1517,13 +1541,14 @@ input[type="range"]::-webkit-slider-thumb {
.settings {
padding: 10px 12px 12px 12px;
- bottom: 20px;
+ bottom: 10px;
right: 10px;
font-size: 12px;
-webkit-transform: translateY(450px);
-webkit-transition: -webkit-transform 0.2s ease-in-out;
transform: translateY(450px);
transition: -webkit-transform 0.2s ease-in-out;
+ width: 210px;
}
.settings.active {
@@ -1575,6 +1600,7 @@ input[type="range"]::-webkit-slider-thumb {
.settings input[type="text"] {
border: 1px solid #000;
font-size: 15px;
+ max-width: 100%;
padding: 5px;
}
@@ -1584,7 +1610,10 @@ input[type="range"]::-webkit-slider-thumb {
font-size: 12px;
width: 100%;
max-height: 200px;
- max-width: 180px;
+}
+#textEditor.settings textarea {
+ max-height: none;
+ height: 290px;
}
.settings input[type="text"]:focus{
@@ -2114,7 +2143,7 @@ a[data-role="forgot-password"] {
background: white;
padding: 10px;
margin: 20px auto;
-position: relative;
+ position: relative;
}
.collaborators button {
diff --git a/public/assets/test/bg.html b/public/assets/test/bg.html
new file mode 100644
index 0000000..cd7eaa8
--- /dev/null
+++ b/public/assets/test/bg.html
@@ -0,0 +1,114 @@
+<div id="scene"></div>
+<div style="position:fixed;top:419px;left:10px;">
+<input id="url" value="http://i.asdf.us/im/97/imgrid_1400887539_xx_abridged___dmgk.png">
+<input id="scale" type="range" min="0.01" max="10.0" step="0.1" value="1.0">
+<div id="cursor" style="width:30px;height:30px;background:blue;display:inline-block;"></div>
+</div>
+<script src="/assets/javascripts/util.js"></script>
+<script src="/assets/javascripts/vendor/tube.js"></script>
+<script src="/assets/javascripts/vendor/loader.js"></script>
+<script src="/assets/javascripts/rectangles/util/constants.js"></script>
+<script src="/assets/javascripts/rectangles/util/mouse.js"></script>
+<script src="/assets/javascripts/rectangles/models/vec2.js"></script>
+<script src="/assets/javascripts/rectangles/models/rect.js"></script>
+<script src="/assets/javascripts/rectangles/models/surface.js"></script>
+<script>
+
+var w = scene.width = 600
+var h = scene.height = 400
+
+var surface = new Surface ()
+surface.add( new Rect( new vec2(10, 100), new vec2(0, 400) ) )
+surface.add( new Rect( new vec2(100, 300), new vec2(200, 400) ) )
+surface.add( new Rect( new vec2(300, 400), new vec2(0, 300) ) )
+surface.add( new Rect( new vec2(400, 500), new vec2(0, 400) ) )
+
+var colors = "#f00 #ff0 #0ff #00f #f0f".split(" ")
+surface.faces.forEach(function(face, i){
+ var el = document.createElement("div")
+ el.style.position = "absolute"
+ el.style.backgroundColor = colors[i%colors.length]
+ el.style.top = face.y.a + "px"
+ el.style.left = face.x.a + "px"
+ el.style.width = face.width() + "px"
+ el.style.height = face.height() + "px"
+ scene.appendChild(el)
+ face.el = el
+})
+
+url.addEventListener("input", updateBackgroundImage)
+scale.addEventListener("input", updateScale)
+
+var bg_w = 1, bg_h = 1, x = 0, y = 0, s = 1
+function updateBackgroundImage(){
+ var img = new Image ()
+ img.onload = function(){
+ x0 = 0
+ y0 = 0
+ bg_w = img.naturalWidth
+ bg_h = img.naturalHeight
+ surface.faces.forEach(function(face, i){
+ face.el.style.backgroundImage = 'url(' + url.value + ')'
+ })
+ update(x,y,bg_w,bg_h)
+ }
+ img.src = url.value
+ img.complete && img.onload()
+}
+function update(x,y,w,h){
+ dx = x
+ dy = y
+ surface.faces.forEach(function(face, i){
+ dx = x-face.x.a
+ dy = y-face.y.a
+ face.el.style.backgroundPosition = dx + 'px ' + dy + 'px'
+ face.el.style.backgroundSize = w*s + 'px ' + h*s + 'px'
+// console.log(x,y,' ',dx,dy)
+ })
+}
+updateBackgroundImage()
+
+function updateScale(){
+ s = parseFloat(scale.value)
+ console.log(scale.value, s)
+ update(x,y,bg_w,bg_h)
+}
+
+var leftOffset = 0
+
+var position = new vec2( 40, 40 )
+var dimension = new vec2( 50, 80 )
+var bounds = surface.bounds_at_index_with_dimensions(0, dimension)
+
+var delta = new vec2( 0, 0 )
+
+var dragging = false
+
+var x0 = 0, y0 = 0
+var mymouse = new mouse({
+ el: cursor,
+ down: function(e, cursor){
+ console.log(cursor.x.a, cursor.y.a)
+ dragging = true
+ },
+ drag: function(e, cursor){
+ if (! dragging) return
+ delta = cursor.delta()
+ delta.a = - delta.a
+ x0 = delta.a*s
+ y0 = delta.b*s
+// console.log(x0,y0)
+ update(x+x0,y+y0,bg_w,bg_h)
+ },
+ up: function(e, cursor, new_cursor){
+ x += delta.a*s
+ y += delta.b*s
+ delta.zero()
+ dragging = false
+ },
+})
+
+
+
+
+</script>
diff --git a/views/controls/editor/light-control.ejs b/views/controls/editor/light-control.ejs
index fdf95a7..1fc4484 100644
--- a/views/controls/editor/light-control.ejs
+++ b/views/controls/editor/light-control.ejs
@@ -23,17 +23,17 @@
</div>
<h4>Preset Styles</h4>
- <div class="color-swatches defaults">
- <span>
+ <div class="presets">
+ <span data-preset="wireframe">
Wireframe
</span>
- <span>
+ <span data-preset="shaded">
Shaded
</span>
- <span>
+ <span data-preset="pfunk">
P.Funk
</span>
- <span>
+ <span data-preset="seapunk">
SeaPunk
</span>
</div>
diff --git a/views/controls/editor/text-editor.ejs b/views/controls/editor/text-editor.ejs
index 205fbdf..3a367d5 100644
--- a/views/controls/editor/text-editor.ejs
+++ b/views/controls/editor/text-editor.ejs
@@ -1,6 +1,10 @@
<div class="vvbox settings" id="textEditor">
<h4>Edit Text</h4>
+ <div class="no-text">
+ Click a wall to add text.
+ </div>
+
<div class="setting">
<select name="font-family">
<option>Helvetica</option>
@@ -17,6 +21,12 @@
<option value="36">36pt</option>
<option value="72">72pt</option>
</select>
+ <select name="text-align">
+ <option value="left">Left</option>
+ <option value="center">Center</option>
+ <option value="right">Right</option>
+ <option value="justify">Justify</option>
+ </select>
</div>
<div class="setting">
diff --git a/views/controls/editor/toolbar.ejs b/views/controls/editor/toolbar.ejs
index 7d53315..f9d91af 100644
--- a/views/controls/editor/toolbar.ejs
+++ b/views/controls/editor/toolbar.ejs
@@ -3,39 +3,39 @@
<span
data-role='open-media-viewer'
data-info="add media"
- class="ion-ios7-photos-outline"></span>
+ class="icon-ios7-photos-outline"></span>
<!--
<span
data-role='resize-media'
data-info="resize media"
- class="ion-arrow-resize"></span>
+ class="icon-arrow-resize"></span>
<span
data-role='destroy-media'
data-info="delete media"
- class="ion-ios7-trash-outline"></span>
+ class="icon-ios7-trash-outline"></span>
<span
data-role='toggle-text-editor'
data-info="edit wall text"
- class="ion-ios7-compose-outline"></span>
+ class="icon-ios7-compose-outline"></span>
-->
<span
data-role='toggle-wallpaper-panel'
data-info="add wallpaper"
- class="ion-ios7-keypad-outline"></span>
+ class="icon-ios7-keypad-outline"></span>
<span
data-role='toggle-light-control'
data-info="edit room colors"
- class="ion-ios7-sunny-outline"></span>
+ class="icon-ios7-sunny-outline"></span>
[[ if (user.username == "test12343") { ]]
<span
data-role='toggle-text-editor'
- data-info="edit wall text"
- class="ion-ios7-compose-outline"></span>
+ data-info="add text to wall"
+ class="icon-ios7-compose-outline"></span>
[[ } ]]
<span
data-role='toggle-project-settings'
data-info="room settings"
- class="ion-key"></span>
+ class="icon-key"></span>
</div>
diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs
index 4af9938..f768160 100644
--- a/views/partials/scripts.ejs
+++ b/views/partials/scripts.ejs
@@ -3,6 +3,7 @@
<script type="text/javascript" src="/assets/javascripts/vendor/bower_components/momentjs/min/moment.min.js"></script>
<script type="text/javascript" src="/assets/javascripts/vendor/bower_components/fiber/src/fiber.min.js"></script>
<script type="text/javascript" src="/assets/javascripts/vendor/bower_components/prefixfree/prefixfree.min.js"></script>
+<script type="text/javascript" src="/assets/javascripts/vendor/bower_components/marked/lib/marked.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>
@@ -17,6 +18,7 @@
<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.text.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>
<script type="text/javascript" src="/assets/javascripts/mx/primitives/mx.vimeo.js"></script>
@@ -27,19 +29,18 @@
<script type="text/javascript" src="/assets/javascripts/rectangles/util/colors.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/util/coords.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/util/debug.js"></script>
-<script type="text/javascript" src="/assets/javascripts/rectangles/util/permissions.js"></script>
+<script type="text/javascript" src="/assets/javascripts/rectangles/util/keys.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/util/measurement.js"></script>
+<script type="text/javascript" src="/assets/javascripts/rectangles/util/minotaur.js"></script>
+<script type="text/javascript" src="/assets/javascripts/rectangles/util/mouse.js"></script>
+<script type="text/javascript" src="/assets/javascripts/rectangles/util/permissions.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/util/sort.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/util/uid.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/util/undostack.js"></script>
-<script type="text/javascript" src="/assets/javascripts/rectangles/util/minotaur.js"></script>
+<script type="text/javascript" src="/assets/javascripts/rectangles/util/wheel.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/models/rect.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/models/surface.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/models/tree.js"></script>
@@ -60,6 +61,7 @@
<script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/undo.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/types/_object.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/types/image.js"></script>
+<script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/types/text.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/engine/scenery/types/video.js"></script>
<script type="text/javascript" src="/assets/javascripts/rectangles/engine/map/_map.js"></script>