summaryrefslogtreecommitdiff
path: root/public/assets/javascripts/ui/editor
diff options
context:
space:
mode:
Diffstat (limited to 'public/assets/javascripts/ui/editor')
-rw-r--r--public/assets/javascripts/ui/editor/Collaborators.js1
-rw-r--r--public/assets/javascripts/ui/editor/ColorControl.js153
-rw-r--r--public/assets/javascripts/ui/editor/EditorSettings.js109
-rw-r--r--public/assets/javascripts/ui/editor/EditorToolbar.js154
-rw-r--r--public/assets/javascripts/ui/editor/EditorView.js54
-rw-r--r--public/assets/javascripts/ui/editor/HelpCursor.js79
-rw-r--r--public/assets/javascripts/ui/editor/LightControl.js280
-rw-r--r--public/assets/javascripts/ui/editor/MediaEditor.js63
-rw-r--r--public/assets/javascripts/ui/editor/MediaTumblr.js53
-rw-r--r--public/assets/javascripts/ui/editor/MediaUpload.js19
-rw-r--r--public/assets/javascripts/ui/editor/MediaViewer.js193
-rw-r--r--public/assets/javascripts/ui/editor/Presets.js122
-rw-r--r--public/assets/javascripts/ui/editor/SculptureEditor.js237
-rw-r--r--public/assets/javascripts/ui/editor/TextEditor.js238
-rw-r--r--public/assets/javascripts/ui/editor/WallpaperPicker.js229
15 files changed, 1534 insertions, 450 deletions
diff --git a/public/assets/javascripts/ui/editor/Collaborators.js b/public/assets/javascripts/ui/editor/Collaborators.js
index 452ad15..b57510d 100644
--- a/public/assets/javascripts/ui/editor/Collaborators.js
+++ b/public/assets/javascripts/ui/editor/Collaborators.js
@@ -9,6 +9,7 @@ var Collaborators = ModalFormView.extend({
destroyAction: function(){ return "/api/collaborator/" + this.parent.data.slug + "/destroy" },
events: {
+ "mousedown": "stopPropagation",
"keydown [name=email]": "enterSubmit",
"click [data-role=destroy-collaborator]": "destroy",
},
diff --git a/public/assets/javascripts/ui/editor/ColorControl.js b/public/assets/javascripts/ui/editor/ColorControl.js
new file mode 100644
index 0000000..54a6a2e
--- /dev/null
+++ b/public/assets/javascripts/ui/editor/ColorControl.js
@@ -0,0 +1,153 @@
+
+var ColorControl = View.extend({
+ el: ".colorcontrol",
+
+ events: {
+ "mousedown": "stopPropagation",
+ "click .color-swatches span": "setSurface",
+ "click .colors span": "setHue",
+ },
+
+ colors: [
+ [255,94,58],
+ [255,149,0],
+ [255,219,76],
+ [76,217,100],
+ [52,170,220],
+ [29,98,240],
+ [198,68,252],
+ [0,0,0],
+ [74,74,74],
+ [125,126,127],
+ [209,211,212],
+ [235,235,235],
+ [255,255,255],
+ ],
+
+ initialize: function(opt){
+ this.parent = opt.parent
+
+ this.colorPicker = new LabColorPicker(this, 155, 155)
+ this.$(".color-picker").append( this.colorPicker.canvas )
+ this.$(".color-picker").append( this.colorPicker.cursor )
+ this.$(".slider").append( this.colorPicker.brightness )
+
+ this.$swatches = this.$(".swatch")
+ this.$labels = this.$(".swatch + label")
+ this.$swatch = {
+ wall: this.$("#wall-color"),
+ outline: this.$("#outline-color"),
+ floor: this.$("#floor-color"),
+ ceiling: this.$("#ceiling-color"),
+ }
+
+ this.$colors = this.$(".colors")
+ this.colors.forEach(function(color){
+ var $swatch = $("<span>")
+ $swatch.css("background-color","rgb(" + color + ")")
+ $swatch.data('color', color)
+ this.$colors.append($swatch)
+ }.bind(this))
+
+ if ($.browser.mozilla) {
+ $("#floor-color").parent().hide()
+ $("#ceiling-color").parent().hide()
+ }
+ },
+
+ modes: [ "wall", "outline", "floor", "ceiling" ],
+
+ load: function(data){
+ this.modes.forEach(function(mode){
+ Walls.setColor[mode](data[mode])
+ this.$swatch[ mode ].css("background-color", rgb_string(data[mode]))
+ }.bind(this))
+ this.setMode("wall")
+ },
+
+ loadDefaults: function(){
+ var colors = {
+ wall: app.defaults.colors.wall.slice(),
+ outline: app.defaults.colors.outline.slice(),
+ floor: app.defaults.colors.floor.slice(),
+ ceiling: app.defaults.colors.ceiling.slice(),
+ }
+ this.load(colors)
+ },
+
+ toggle: function(state){
+ if (state) {
+ this.parent.cursor.message("colors")
+ }
+ this.$el.toggleClass("active", state);
+ },
+
+ show: function(){
+ this.toggle(true)
+ },
+
+ hide: function(){
+ this.toggle(false)
+ },
+
+ pickColor: function(rgb, Lab){
+ this.labColor = Lab
+ this.setSwatchColor(this.mode, rgb)
+ // console.log(rgb)
+ Walls.setColor[ this.mode ](rgb)
+ this.parent.presets.modified = true
+ },
+
+ setSwatchColor: function(mode, rgb) {
+ this.$swatch[ mode ].css("background-color", rgb_string(rgb))
+ },
+
+ initialState: null,
+
+ begin: function(){
+ this.initialState = this.serialize()
+ },
+
+ serialize: function(){
+ return {
+ mode: this.mode,
+ rgb: Walls.colors[ this.mode ]
+ }
+ },
+
+ finalize: function(){
+ if (! this.initialState) { return }
+ UndoStack.push({
+ type: 'update-colors',
+ undo: this.initialState,
+ redo: this.serialize(),
+ })
+
+ this.initialState = null
+
+ // TODO: watch individual wall object here
+ Minotaur.watch( app.router.editorView.settings )
+ },
+
+ setMode: function (mode) {
+ var color, brightness
+ this.mode = mode
+ this.$(".active").removeClass("active")
+ this.$swatch[ mode ].parent().addClass("active")
+ color = Walls.colors[ mode ]
+
+ this.labColor = this.colorPicker.load(color)
+ },
+
+ setSurface: function(e){
+ var mode = $('.swatch', e.currentTarget).data('mode')
+ this.setMode(mode)
+ },
+
+ setHue: function(e){
+ var color = $(e.currentTarget).data('color')
+ this.labColor = this.colorPicker.load(color)
+ this.pickColor(color, this.labColor)
+ }
+
+})
diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js
index 8a88f7a..5aa88e9 100644
--- a/public/assets/javascripts/ui/editor/EditorSettings.js
+++ b/public/assets/javascripts/ui/editor/EditorSettings.js
@@ -5,8 +5,11 @@ var EditorSettings = FormView.extend({
createAction: "/api/project/new",
updateAction: "/api/project/edit",
destroyAction: "/api/project/destroy",
+
+ useMinotaur: true,
events: {
+ "mousedown": "stopPropagation",
"keydown": 'stopPropagation',
"keydown [name=name]": 'enterSubmit',
"click [data-role='show-collaborators']": 'showCollaborators',
@@ -14,6 +17,12 @@ var EditorSettings = FormView.extend({
"click [data-role='clone-project']": 'clone',
"click [data-role='clear-project']": 'clear',
"click [data-role='destroy-project']": 'destroy',
+ "click [data-role='toggle-map']": 'toggleMap',
+ "click [data-role='view-project']": 'viewProject',
+ "click #startText": "setStartPosition",
+ "click #moveText": "confirmStartPosition",
+ "click #confirmText": "setStartPosition",
+ "click #goText": "goToStartPosition",
},
initialize: function(opt){
@@ -25,21 +34,30 @@ var EditorSettings = FormView.extend({
this.$name = this.$("[name=name]")
this.$description = this.$("[name=description]")
this.$privacy = this.$("[name=privacy]")
+ this.$startPoint = this.$("#startpoint")
},
load: function(data){
this.action = data.isNew ? this.createAction : this.updateAction
this.parent.data = data
- data.rooms && Rooms.deserialize(data.rooms)
- data.walls && Walls.deserialize(data.walls)
- data.startPosition && scene.camera.move(data.startPosition)
+ if (data.shapes && data.shapes.length) {
+ Rooms.deserializeFromShapes(data, data.walls)
+ }
+ else if (data.rooms) {
+ Rooms.deserialize(data.rooms, data.walls)
+ }
+ if (data.startPosition) {
+ scene.camera.move(data.startPosition)
+ this.startPosition = data.startPosition
+ this.$startPoint.addClass("confirmed")
+ }
if (data.colors && data.colors.wall) {
- this.parent.lightControl.load(data.colors)
+ this.parent.colorControl.load(data.colors)
}
else {
- this.parent.lightControl.loadDefaults()
+ this.parent.colorControl.loadDefaults()
}
if (data.walls) {
@@ -53,7 +71,7 @@ var EditorSettings = FormView.extend({
}
if (data.isNew) {
- this.$name.val( "Untitled Room" )
+ this.$name.val( "Untitled" )
}
else {
this.thumbnailIsStale()
@@ -64,6 +82,7 @@ var EditorSettings = FormView.extend({
data.privacy && this.$privacy.find("[value=" + data.privacy + "]").prop("checked", "checked")
data.media && Scenery.deserialize(data.media)
+ data.sculpture && Sculpture.deserialize(data.sculpture)
}
},
@@ -72,7 +91,14 @@ var EditorSettings = FormView.extend({
this.parent.collaborators.show()
},
- clone: function(){
+ toggleMap: function(e){
+ e.preventDefault()
+ app.controller.toolbar.toggleMap()
+ },
+
+ clone: function(e){
+ e.preventDefault()
+
var names = this.$name.val().split(" ")
if ( ! isNaN(Number( names[names.length-1] )) ) {
names[names.length-1] = Number( names[names.length-1] ) + 1
@@ -84,12 +110,15 @@ var EditorSettings = FormView.extend({
this.$id.val('new')
this.$name.val( names.join(" ") )
this.action = this.createAction
+ this.thumbnailState = null
- window.history.pushState(null, document.title, "/builder/new")
+ window.history.pushState(null, document.title, "/project/new")
},
- clear: function(){
- Rooms.removeAll()
+ clear: function(e){
+ e.preventDefault()
+ Scenery.removeAll()
+ Sculpture.removeAll()
},
destroy: function(){
@@ -100,7 +129,7 @@ var EditorSettings = FormView.extend({
type: "delete",
data: { _id: this.$id.val(), _csrf: this.$csrf.val() },
success: function(data){
- window.location.href = "/project"
+ window.location.href = "/profile"
}
})
}.bind(this))
@@ -109,8 +138,12 @@ var EditorSettings = FormView.extend({
toggle: function(state){
var state = typeof state == 'boolean' ? state : ! this.$el.hasClass("active")
this.$el.toggleClass("active", state)
-
+
+ $(".inuse").removeClass("inuse")
$("[data-role='toggle-project-settings']").toggleClass("inuse", state)
+ if (state) {
+ this.parent.cursor.message("settings")
+ }
},
enterSubmit: function (e) {
@@ -140,22 +173,43 @@ var EditorSettings = FormView.extend({
ErrorModal.alert($errors)
},
+ startPosition: null,
+ setStartPosition: function(){
+ this.$startPoint.addClass("active").removeClass("confirmed")
+ },
+ confirmStartPosition: function(){
+ this.$startPoint.removeClass("active").addClass("confirmed")
+ this.startPosition = app.position(scene.camera)
+ },
+ goToStartPosition: function(){
+ if (! this.startPosition) return
+ scene.camera.move(this.startPosition)
+ },
+
serialize: function(){
- map.draw.render()
var fd = new FormData()
fd.append( "_csrf", this.$csrf.val() )
fd.append( "_id", this.$id.val() )
fd.append( "name", this.$name.val() )
fd.append( "description", this.$description.val() )
fd.append( "privacy", this.$privacy.filter(":checked").val() == "private" )
- fd.append( "rooms", JSON.stringify( Rooms.serialize() ) )
+ fd.append( "viewHeight", window.viewHeight )
+ if (Rooms.shapesMode) {
+ fd.append( "shapes", JSON.stringify( shapes.serialize() ) )
+ }
+ else {
+ fd.append( "rooms", JSON.stringify( Rooms.serialize() ) )
+ }
fd.append( "walls", JSON.stringify( Walls.serialize() ) )
fd.append( "colors", JSON.stringify( Walls.colors ) )
fd.append( "media", JSON.stringify( Scenery.serialize() ) )
- fd.append( "startPosition", JSON.stringify( app.position(scene.camera) ) )
+ fd.append( "sculpture", JSON.stringify( Sculpture.serialize() ) )
+ fd.append( "startPosition", JSON.stringify( this.startPosition || false ) )
+ fd.append( "lastPosition", JSON.stringify( app.position(scene.camera) ) )
if (this.thumbnailIsStale()) {
- fd.append( "thumbnail", dataUriToBlob(map.canvas.toDataURL()) )
+ var thumbnail = map.draw.render()
+ fd.append( "thumbnail", dataUriToBlob(thumbnail.toDataURL()) )
}
return fd
},
@@ -174,6 +228,16 @@ var EditorSettings = FormView.extend({
clickSave: function(){
this.toggle(false)
this.save()
+ this.isVisible = true
+ },
+
+ viewAfterSave: false,
+ viewProject: function(e){
+ e.preventDefault()
+ Minotaur.unwatch(this)
+ Minotaur.hide()
+ this.viewAfterSave = true
+ this.save()
},
success: function(data){
@@ -181,11 +245,22 @@ var EditorSettings = FormView.extend({
this.$name.val(data.name)
this.action = this.updateAction
+ if (this.viewAfterSave) {
+ window.location.pathname = "/project/" + data.slug
+ return
+ }
+
Minotaur.unwatch(this)
Minotaur.hide()
window.history.pushState(null, document.title, "/project/" + data.slug + "/edit")
-
+
+ this.parent.share.setLink( "http://vvalls.com/project/" + data.slug )
+ if (this.isVisible) {
+ this.isVisible = false
+ this.parent.share.show()
+ }
+
this.parent.data = data
},
diff --git a/public/assets/javascripts/ui/editor/EditorToolbar.js b/public/assets/javascripts/ui/editor/EditorToolbar.js
index e91da0f..a5ad2dd 100644
--- a/public/assets/javascripts/ui/editor/EditorToolbar.js
+++ b/public/assets/javascripts/ui/editor/EditorToolbar.js
@@ -3,86 +3,86 @@ var EditorToolbar = View.extend({
el: "#editorToolbar",
events: {
+ "mousedown": 'stopPropagation',
+ "mouseenter": 'mouseenter',
+ "mouseleave": 'mouseleave',
+ "click [data-role='undo']": 'undo',
"click [data-role='toggle-map-view']": 'toggleMap',
"click [data-role='toggle-project-settings']": 'toggleSettings',
"click [data-role='open-media-viewer']": 'openMediaViewer',
- "click [data-role='resize-media']": 'resizeMedia',
- "click [data-role='destroy-media']": 'destroyMedia',
+ "click [data-role='toggle-presets']": 'togglePresets',
"click [data-role='toggle-wallpaper-panel']": 'toggleWallpaper',
- "click [data-role='toggle-light-control']": 'toggleLightControl',
- "click [data-role='edit-wall-text']": 'editWallText',
+ "click [data-role='toggle-color-control']": 'toggleColorControl',
+ "click [data-role='toggle-text-editor']": 'toggleTextEditor',
},
initialize: function(opt){
this.parent = opt.parent
},
- toggleMap: function(){
- map.toggle()
- // $("#minimap").toggleClass("hide");
+ undo: function(e){
+ if (e.shiftKey) {
+ var canRedo = UndoStack.redo()
+ console.log("can redo", canRedo)
+ }
+ else {
+ var canUndo = UndoStack.undo()
+ console.log("can undo", canUndo)
+ }
+ },
+
+ toggleMap: function(state){
+// if (typeof state != "boolean") {
+// state = ! $("[data-role='toggle-map-view']").hasClass("inuse")
+// this.resetControls()
+// }
+// $("[data-role='toggle-map-view']").toggleClass("inuse", state)
+ var state = map.toggle(state)
+ if (state) { map.ui.blur() }
+ $("#minimap").toggleClass("hide", state)
+ this.parent.info.toggle(state)
},
toggleSettings: function(){
- this.resetMode()
- $(".inuse").removeClass("inuse")
- this.parent.lightControl.hide()
+// this.resetMode()
+ this.toggleMap(false)
+ this.parent.textEditor.hide()
+ this.parent.presets.hide()
+ this.parent.colorControl.hide()
this.parent.wallpaperPicker.hide()
this.parent.mediaEditor.hide()
this.parent.settings.toggle()
},
openMediaViewer: function(){
- this.parent.mediaViewer.show()
- this.parent.mediaUpload.show()
this.resetMode()
this.resetControls()
+ this.toggleMap(false)
+ this.parent.mediaViewer.show()
},
-
+
resetMode: function(){
- this.resizeMedia(false)
- this.destroyMedia(false)
+ $(".inuse").removeClass("inuse")
+ $("body").removeClass("addText")
+ this.parent.hideExtras()
+ this.resetPermissions()
},
resetControls: function(){
+ $(".inuse").removeClass("inuse")
+ this.toggleMap(false)
+ this.parent.textEditor.hide()
this.parent.wallpaperPicker.hide()
- this.parent.lightControl.hide()
- },
-
- resizeMedia: function(e, state){
- this.resetControls()
- if (! state && typeof e == "boolean") {
- state = e
- editor.permissions.assign("resize", state)
- }
- else {
- state = editor.permissions.toggle("resize")
- }
- ! state && editor.permissions.assign("move", true)
- $(".inuse").removeClass("inuse")
- $("[data-role='resize-media']").toggleClass("inuse", state)
- if (state) {
- if (this.parent.mediaEditor.scenery) {
- Scenery.resize.show( this.parent.mediaEditor.scenery )
- }
- }
- else {
- Scenery.resize.hide()
- }
+ this.parent.presets.hide()
+ this.parent.colorControl.hide()
+ this.parent.settings.hide()
},
- destroyMedia: function(e, state){
- this.resetControls()
- if (! state && typeof e == "boolean") {
- state = e
- editor.permissions.assign("destroy", state)
- }
- else {
- state = editor.permissions.toggle("destroy")
- }
- ! state && editor.permissions.assign("move", true)
- $(".inuse").removeClass("inuse")
- $("[data-role='destroy-media']").toggleClass("inuse", state)
- $("body").toggleClass("destroyActive", state)
+ resetPermissions: function(){
+ editor.permissions.add("pick")
+ editor.permissions.add("move")
+ editor.permissions.add("resize")
+ editor.permissions.remove("destroy")
},
toggleWallpaper: function(){
@@ -90,31 +90,67 @@ var EditorToolbar = View.extend({
this.resetMode()
$("[data-role='toggle-wallpaper-panel']").toggleClass("inuse", state)
this.parent.mediaEditor.hide()
- this.parent.lightControl.hide()
+ this.parent.colorControl.hide()
+ this.parent.textEditor.hide()
this.parent.settings.hide()
+ this.parent.presets.hide()
+ this.toggleMap(false)
this.parent.wallpaperPicker.toggle(state)
},
- toggleLightControl: function(){
- var state = ! $("[data-role='toggle-light-control']").hasClass("inuse")
+ toggleColorControl: function(){
+ var state = ! $("[data-role='toggle-color-control']").hasClass("inuse")
this.resetMode()
- $("[data-role='toggle-light-control']").toggleClass("inuse", state)
+ $("[data-role='toggle-color-control']").toggleClass("inuse", state)
this.parent.mediaEditor.hide()
this.parent.wallpaperPicker.hide()
+ this.parent.textEditor.hide()
this.parent.settings.hide()
- this.parent.lightControl.toggle(state)
+ this.parent.presets.hide()
+ this.toggleMap(false)
+ this.parent.colorControl.toggle(state)
},
- editWallText: function(){
- },
+ toggleTextEditor: function(){
+ var state = ! $("[data-role='toggle-text-editor']").hasClass("inuse")
+ this.resetMode()
+ $("[data-role='toggle-text-editor']").toggleClass("inuse", state)
+ this.parent.mediaEditor.hide()
+ this.parent.wallpaperPicker.hide()
+ this.parent.colorControl.hide()
+ this.parent.settings.hide()
+ this.parent.presets.hide()
+ this.toggleMap(false)
+ this.parent.textEditor.toggle(state)
+ },
+ togglePresets: function(){
+ var state = ! $("[data-role='toggle-presets']").hasClass("inuse")
+ this.resetMode()
+ $("[data-role='toggle-presets']").toggleClass("inuse", state)
+ this.parent.mediaEditor.hide()
+ this.parent.wallpaperPicker.hide()
+ this.parent.textEditor.hide()
+ this.parent.settings.hide()
+ this.parent.colorControl.hide()
+ this.toggleMap(false)
+ this.parent.presets.toggle(state)
+ },
+
+ mouseenter: function(){
+ this.parent.cursor.hide()
+ },
+
+ mouseleave: function(){
+ this.parent.cursor.show()
+ },
})
var editor = new function(){
this.permissions = new Permissions({
'pick': true,
'move': true,
- 'resize': false,
+ 'resize': true,
'destroy': false,
})
} \ No newline at end of file
diff --git a/public/assets/javascripts/ui/editor/EditorView.js b/public/assets/javascripts/ui/editor/EditorView.js
index e11f189..c05b373 100644
--- a/public/assets/javascripts/ui/editor/EditorView.js
+++ b/public/assets/javascripts/ui/editor/EditorView.js
@@ -2,6 +2,7 @@
var EditorView = View.extend({
el: "#editorView",
+ blueprintAction: "/api/blueprint/user/",
projectAction: "/api/project/",
layoutAction: "/api/layout/",
@@ -9,14 +10,21 @@ var EditorView = View.extend({
},
initialize: function(){
+ this.cursor = new HelpCursor ({ parent: this })
this.toolbar = new EditorToolbar ({ parent: this })
this.settings = new EditorSettings ({ parent: this })
+ this.info = new BuilderInfo ({ parent: this })
this.mediaViewer = new MediaViewer ({ parent: this })
this.mediaUpload = new MediaUpload ({ parent: this })
+ this.mediaTumblr = new MediaTumblr ({ parent: this })
this.mediaEditor = new MediaEditor ({ parent: this })
+ this.sculptureEditor = new SculptureEditor ({ parent: this })
this.wallpaperPicker = new WallpaperPicker ({ parent: this })
- this.lightControl = new LightControl ({ parent: this })
+ this.colorControl = new ColorControl ({ parent: this })
+ this.textEditor = new TextEditor ({ parent: this })
this.collaborators = new Collaborators ({ parent: this })
+ this.presets = new Presets ({ parent: this })
+ this.share = new ShareView ({ parent: this })
},
load: function(name){
@@ -25,27 +33,65 @@ var EditorView = View.extend({
},
loadLayout: function(layout){
+ if (layout == "empty") {
+ this.readyLayout({})
+ this.toolbar.toggleMap()
+ return
+ }
layout = sanitize(layout)
$.get(this.layoutAction + layout, this.readyLayout.bind(this))
},
+ loadBlueprint: function(blueprint){
+ $.get(this.blueprintAction + blueprint, this.readyLayout.bind(this))
+ },
+
ready: function(data){
$("#map").hide()
-
+
+ this.data = data
+
this.settings.load(data)
+ this.info.load(data)
},
readyLayout: function(data){
data.isNew = true
+ // $('#help-button').trigger("click")
this.ready(data)
},
pick: function(scenery){
- this.mediaEditor.pick(scenery)
+ if (scenery.isSculpture) {
+ this.mediaEditor.hide()
+ this.textEditor.hide()
+ this.sculptureEditor.pick(scenery)
+ }
+ else if (scenery.type == "text") {
+ this.mediaEditor.hide()
+ this.sculptureEditor.hide()
+ this.textEditor.pick(scenery)
+ }
+ else {
+ this.textEditor.hide()
+ this.sculptureEditor.hide()
+ this.mediaEditor.pick(scenery)
+ }
+ },
+
+ pickWall: function(wall, pos){
+ this.hideExtras()
+ this.wallpaperPicker.pickWall(wall)
},
hideExtras: function(){
+ this.sculptureEditor.hide()
this.mediaEditor.hide()
- }
+ this.textEditor.hide()
+ this.share.hide()
+ Sculpture.resize.hide()
+ Scenery.resize.hide()
+ Scenery.hovering = false
+ }
})
diff --git a/public/assets/javascripts/ui/editor/HelpCursor.js b/public/assets/javascripts/ui/editor/HelpCursor.js
new file mode 100644
index 0000000..4c8ff0c
--- /dev/null
+++ b/public/assets/javascripts/ui/editor/HelpCursor.js
@@ -0,0 +1,79 @@
+
+var HelpCursor = View.extend({
+ el: "#helpCursor",
+
+ active: false,
+
+ messages: {
+ start: "Welcome to VValls! Click one of the tools at right to learn about it.",
+ media: "This is where you pick media to go on the walls. You can upload media and paste links.",
+ addmedia: "Great, now click a wall to place this image.",
+ resize: "Drag the image to position it, or use the dots to resize.",
+ presets: "These are some basic presets to get you started. Click em! :-)",
+ wallpaper: "Click the wallpaper you want then apply it to the walls. Feel free to upload your own too!",
+ colors: "Use these colors to change the color of the walls, floor, and ceiling.",
+ settings: "This is where you publish your project. Give it a name, hit save, and you'll have a URL you can share with your friends.",
+ builder: "This is a map of your rooms. Draw new boxes, or move and resize the ones that are there. Hit ESCAPE to toggle the map.",
+ },
+
+ initialize: function(){
+ this.helpButton = $('#help-button')
+
+ this.helpButton.click(this.toggle.bind(this))
+ this.$el.html(this.messages['start'])
+ },
+
+ toggle: function(){
+ this.active ? this.stop() : this.start()
+ },
+
+ start: function(){
+ if (this.active) return
+ this.active = true
+ this.helpButton.addClass('active')
+ this.$el.show()
+ this.move({ pageX: -1000, pageY: -10000 })
+ this.moveFn = this.move.bind(this)
+ document.addEventListener("mousemove", this.moveFn)
+ },
+
+ stop: function(){
+ this.active = false
+ this.$el.hide()
+ this.helpButton.removeClass('active')
+ document.removeEventListener("mousemove", this.moveFn)
+ },
+
+ offset: 100,
+ lastPosition: { pageX: 0, pageY: 0 },
+ move: function(e){
+ this.el.style.right = clamp(window.innerWidth - e.pageX, this.offset, window.innerWidth) + "px"
+ this.el.style.top = e.pageY + "px"
+ this.lastPosition = e
+ },
+
+ show: function(name){
+ if (this.active) {
+ this.$el.show()
+ }
+ },
+ hide: function(){
+ this.$el.hide()
+ },
+
+ message: function(name){
+ if (! this.active) return
+ if (name == "start" || name == "media" || name == "settings") {
+ this.offset = 100
+ }
+ else if (name == "colors") {
+ this.offset = 270
+ }
+ else {
+ this.offset = 290
+ }
+ this.move(this.lastPosition)
+ this.$el.html(this.messages[name])
+ },
+
+})
diff --git a/public/assets/javascripts/ui/editor/LightControl.js b/public/assets/javascripts/ui/editor/LightControl.js
deleted file mode 100644
index 3eb2861..0000000
--- a/public/assets/javascripts/ui/editor/LightControl.js
+++ /dev/null
@@ -1,280 +0,0 @@
-
-var LightControl = View.extend({
- el: ".lightcontrol",
-
- events: {
- "mousedown": "stopPropagation",
- "click .color-swatches span": "select",
- "input #shadow-control": "updateShadow",
- "mousedown #brightness-control": "beginBrightness",
- "input #brightness-control": "updateBrightness",
- "input #outline-hue": "updateShadow",
- "input #wall-hue": "updateShadow",
- },
-
- initialize: function(){
-
- this.colorPicker = new LabColorPicker(this, 180, 180)
- this.$("#color-picker").append( this.colorPicker.canvas )
- this.$("#color-picker").append( this.colorPicker.cursor )
-
- this.$swatches = this.$(".swatch")
- this.$labels = this.$(".swatch + label")
- this.$swatch = {
- wall: this.$("#wall-color"),
- outline: this.$("#outline-color"),
- floor: this.$("#floor-color"),
- ceiling: this.$("#ceiling-color"),
- }
- this.$brightnessControl = this.$("#brightness-control")
- },
-
- modes: [ "wall", "outline", "floor", "ceiling" ],
-
- load: function(data){
- this.modes.forEach(function(mode){
- Walls.setColor[mode](data[mode])
- this.$swatch[ mode ].css("background-color", rgb_string(data[mode]))
- }.bind(this))
- this.setMode("wall")
- },
-
- loadDefaults: function(){
- var colors = {
- wall: app.defaults.colors.wall.slice(),
- outline: app.defaults.colors.outline.slice(),
- floor: app.defaults.colors.floor.slice(),
- ceiling: app.defaults.colors.ceiling.slice(),
- }
- this.load(colors)
- },
-
- toggle: function(state){
- this.$el.toggleClass("active", state);
- },
-
- show: function(){
- this.toggle(true)
- },
-
- hide: function(){
- this.toggle(false)
- },
-
- pick: function(rgb, Lab){
- this.labColor = Lab
- this.setSwatchColor(this.mode, rgb)
- Walls.setColor[ this.mode ](rgb)
- },
-
- setSwatchColor: function(mode, rgb) {
- this.$swatch[ mode ].css("background-color", rgb_string(rgb))
- },
-
- initialState: null,
-
- begin: function(){
- this.initialState = this.serialize()
- },
-
- serialize: function(){
- return {
- mode: this.mode,
- rgb: Walls.colors[ this.mode ]
- }
- },
-
- finalize: function(){
- if (! this.initialState) { return }
- UndoStack.push({
- type: 'update-colors',
- undo: this.initialState,
- redo: this.serialize(),
- })
-
- this.initialState = null
-
- // TODO: watch individual wall object here
- Minotaur.watch( app.router.editorView.settings )
- },
-
- setMode: function (mode) {
- var color, brightness
- this.mode = mode
- this.$(".active").removeClass("active")
- this.$swatch[ mode ].parent().addClass("active")
- color = Walls.colors[ mode ]
-
- this.labColor = this.colorPicker.load(color)
- this.$brightnessControl.val( this.labColor[0] )
- },
-
- select: function(e){
- var mode = $('.swatch', e.currentTarget).data('mode')
- this.setMode(mode)
- },
-
- beginBrightness: function(){
- this.begin()
- $(window).one("mouseup", this.finalize.bind(this))
- },
-
- updateBrightness: function(){
- this.labColor[0] = parseFloat( this.$brightnessControl.val() )
- var rgb = this.colorPicker.setLab( this.labColor )
- this.pick(rgb, this.labColor)
- },
-
-})
-
-var LabColorPicker = function (parent, w, h) {
- var base = this
- var canvas = this.canvas = document.createElement('canvas')
- var ctx = this.ctx = canvas.getContext('2d')
- var imageData = ctx.createImageData(w,h)
- var data = imageData.data
-
- var cursor = this.cursor = document.createElement("div")
- cursor.className = "colorPickerCursor"
-
- canvas.width = w
- canvas.height = h
- canvas.className = "colorPicker"
-
- var ww = w-1
- var hh = h-1
-
- var L_range = [0, 110]
- var a_range = [-86.185, 98.254]
- var b_range = [-107.863, 94.482]
-
- var rgb = [0,0,0]
-
- var val = 80
-
- this.mouse = new mouse({
- el: canvas,
- down: function(e, cursor){
- parent.begin()
- cursor.x.a = -cursor.x.a
- base.pick(cursor.x.a, cursor.y.a)
- },
- drag: function(e, cursor){
- cursor.x.b = -cursor.x.b
- base.pick(cursor.x.b, cursor.y.b)
- },
- up: function(){
- parent.finalize()
- }
- })
-
- this.setLab = function(Lab) {
- val = Lab[0]
- this.paint()
- var rgb = xyz2rgb(hunterlab2xyz(Lab[0], Lab[1], Lab[2])).map(Math.round)
- return rgb
- }
- this.pick = function(i, j){
- i = clamp(i, 0, w)
- j = clamp(j, 0, h)
- var x = mix( i/ww, a_range[0], a_range[1] )
- var y = mix( j/hh, b_range[0], b_range[1] )
- var rgb = xyz2rgb(hunterlab2xyz(val, x, y)).map(Math.round)
- this.moveCursor(i, j)
- parent.pick( rgb, [val,x,y] )
- }
- this.load = function(rgba){
- var Lab = xyz2hunterlab(rgb2xyz(rgba))
- var val = clamp( Lab[0], L_range[0], L_range[1] )
- var x = mix( norm(Lab[1], a_range[0], a_range[1]), 0, ww )
- var y = mix( norm(Lab[2], b_range[0], b_range[1]), 0, hh )
-
- this.moveCursor(x,y)
- this.setLab(Lab)
- return Lab
- }
- this.moveCursor = function(x,y){
- cursor.style.left = x + "px"
- cursor.style.top = y + "px"
- }
- this.paint = function() {
- val = clamp(val, L_range[0], L_range[1])
- var x, y, t
- for (var i = 0; i < w; i++) {
- for (var j = 0; j < h; j++) {
- x = mix( i/ww, a_range[0], a_range[1] )
- y = mix( j/hh, b_range[0], b_range[1] )
- t = (j*w + i) * 4
- rgb = xyz2rgb(hunterlab2xyz(val, x, y))
- data[t] = Math.round( rgb[0] )
- data[t+1] = Math.round( rgb[1] )
- data[t+2] = Math.round( rgb[2] )
- data[t+3] = 255
- }
- }
- ctx.putImageData(imageData,0,0)
- }
-
- function hunterlab2xyz (L,a,b) {
- var_Y = L / 10
- var_X = a / 17.5 * L / 10
- var_Z = b / 7 * L / 10
-
- Y = Math.pow(var_Y, 2)
- X = ( var_X + Y ) / 1.02
- Z = -( var_Z - Y ) / 0.847
- xyz = [X,Y,Z]
- }
- function xyz2rgb(){
- var var_X = xyz[0] / 100 //X from 0 to 95.047 (Observer = 2°, Illuminant = D65)
- var var_Y = xyz[1] / 100 //Y from 0 to 100.000
- var var_Z = xyz[2] / 100 //Z from 0 to 108.883
-
- var_R = var_X * 3.2406 + var_Y * -1.5372 + var_Z * -0.4986
- var_G = var_X * -0.9689 + var_Y * 1.8758 + var_Z * 0.0415
- var_B = var_X * 0.0557 + var_Y * -0.2040 + var_Z * 1.0570
-
- if ( var_R > 0.0031308 ) var_R = 1.055 * Math.pow( var_R, 1 / 2.4 ) - 0.055
- else var_R = 12.92 * var_R
- if ( var_G > 0.0031308 ) var_G = 1.055 * Math.pow( var_G, 1 / 2.4 ) - 0.055
- else var_G = 12.92 * var_G
- if ( var_B > 0.0031308 ) var_B = 1.055 * Math.pow( var_B, 1 / 2.4 ) - 0.055
- else var_B = 12.92 * var_B
-
- rgb[0] = clamp(var_R * 255, 0, 255)
- rgb[1] = clamp(var_G * 255, 0, 255)
- rgb[2] = clamp(var_B * 255, 0, 255)
- return rgb
- }
- function rgb2xyz(RGB){
- var var_R = ( RGB[0] / 255 ) // R from 0 to 255
- var var_G = ( RGB[1] / 255 ) // G from 0 to 255
- var var_B = ( RGB[2] / 255 ) // B from 0 to 255
-
- if ( var_R > 0.04045 ) var_R = Math.pow( ( var_R + 0.055 ) / 1.055, 2.4)
- else var_R = var_R / 12.92
- if ( var_G > 0.04045 ) var_G = Math.pow( ( var_G + 0.055 ) / 1.055, 2.4)
- else var_G = var_G / 12.92
- if ( var_B > 0.04045 ) var_B = Math.pow( ( var_B + 0.055 ) / 1.055, 2.4)
- else var_B = var_B / 12.92
-
- var_R = var_R * 100
- var_G = var_G * 100
- var_B = var_B * 100
-
- //Observer. = 2°, Illuminant = D65
- var x = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
- var y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
- var z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505
- return [x,y,z]
- }
- function xyz2hunterlab (XYZ) {
- var X = XYZ[0]
- var Y = XYZ[1] || 1e-6 // otherwise divide-by-zero error when converting rgb(0,0,0)
- var Z = XYZ[2]
- var L = 10 * sqrt( Y )
- var a = 17.5 * ( ( ( 1.02 * X ) - Y ) / sqrt( Y ) )
- var b = 7 * ( ( Y - ( 0.847 * Z ) ) / sqrt( Y ) )
- return [L,a,b]
- }
-}
diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js
index 9b20a43..6068c48 100644
--- a/public/assets/javascripts/ui/editor/MediaEditor.js
+++ b/public/assets/javascripts/ui/editor/MediaEditor.js
@@ -3,7 +3,7 @@ var MediaEditor = FormView.extend({
el: "#mediaEditor",
events: {
- "keydown": 'stopPropagation',
+ "keydown": 'taint',
"focus [name]": "clearMinotaur",
"click [data-role=play-media]": "togglePaused",
"mousedown [name=keyframe]": "stopPropagation",
@@ -51,40 +51,56 @@ var MediaEditor = FormView.extend({
},
pick: function(scenery) {
- if (this.scenery) {
+ if (this.scenery && scenery !== this.scenery) {
this.unbind()
}
this.bind(scenery)
this.$el.addClass("active")
+// app.controller.toolbar.resetMode()
+ app.controller.toolbar.resetControls()
+ Scenery.resize.show(scenery)
+ Scenery.hovering = true
+
var media = scenery.media
- this.$name.val(media.title)
+ // console.log(media)
+
+ this.$name.val(media.title) // || filenameFromUrl(media.url) )
this.$description.val(media.description)
this.setDimensions()
this.$units.val( "ft" )
switch (media.type) {
case "image":
- this.$(".image").show()
this.$(".video").hide()
-
+ this.$(".audio").hide()
+ this.$(".image").show()
break
case "youtube":
case "vimeo":
case "video":
- this.$(".video").show()
this.$(".image").hide()
+ this.$(".audio").hide()
+ this.$(".video").show()
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
+
+ case "soundcloud":
+ this.$(".image").hide()
+ this.$(".video").hide()
+ this.$(".audio").show()
+ this.$playButton.toggleClass("paused", ! this.scenery.paused())
+ this.$autoplay.prop('checked', !! media.autoplay)
+ this.$loop.prop('checked', !! media.loop)
+ break
}
},
@@ -98,12 +114,14 @@ var MediaEditor = FormView.extend({
seek: function(){
var n = parseFloat( this.$keyframe.val() )
this.scenery.seek(n)
+ this.tainted = true
this.scenery.media.keyframe = n
},
setAutoplay: function(){
var checked = this.$autoplay.prop('checked')
this.scenery.media.autoplay = checked
+ this.tainted = true
if (checked && this.scenery.paused()) {
this.togglePaused()
}
@@ -111,17 +129,20 @@ var MediaEditor = FormView.extend({
setLoop: function(){
var checked = this.$loop.prop('checked')
this.scenery.setLoop(checked)
+ this.tainted = true
},
setMute: function(){
var checked = this.$mute.prop('checked')
this.scenery.media.mute = checked
this.scenery.mute(checked)
+ this.tainted = true
},
setDimensions: function(){
if (! this.scenery) return
this.$width.unitVal( Number(this.scenery.naturalDimensions.a * this.scenery.scale) || "" )
this.$height.unitVal( Number(this.scenery.naturalDimensions.b * this.scenery.scale) || "" )
+ this.tainted = true
},
changeWidth: function(e){
e.stopPropagation()
@@ -137,6 +158,11 @@ var MediaEditor = FormView.extend({
app.units = this.$units.val()
this.$('.units').resetUnitVal()
},
+
+ taint: function(e){
+ e.stopPropagation()
+ this.tainted = true
+ },
bind: function(scenery){
this.scenery = scenery
@@ -146,24 +172,29 @@ var MediaEditor = FormView.extend({
unbind: function(){
if (this.scenery) {
- this.scenery.media.title = this.$name.val()
- this.scenery.media.description = this.$description.val()
- Minotaur.watch( app.router.editorView.settings )
-
+ this.scenery.focused = false
+ if (this.tainted && this.scenery.media) {
+ 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")
}
}
+ this.tainted = false
this.scenery = null
},
destroy: function(){
- ConfirmModal.confirm("Are you sure you want delete to this media?", function(){
- var scenery = this.scenery
- this.hide()
- Scenery.remove(scenery.id)
- }.bind(this))
+ var scenery = this.scenery
+ this.hide()
+
+ scenery.remove()
+
+ this.tainted = false
+ this.scenery = null
},
})
diff --git a/public/assets/javascripts/ui/editor/MediaTumblr.js b/public/assets/javascripts/ui/editor/MediaTumblr.js
new file mode 100644
index 0000000..47419ae
--- /dev/null
+++ b/public/assets/javascripts/ui/editor/MediaTumblr.js
@@ -0,0 +1,53 @@
+
+var MediaTumblr = ModalView.extend({
+ el: "#tumblrUpload",
+
+ events: {
+ 'mousedown': "stopPropagation",
+ "keydown .url": "enterSubmit",
+ "click .exampleTumblr": "loadExample",
+ },
+
+ initialize: function(opt){
+ this.__super__.initialize.call(this)
+ this.parent = opt.parent
+ this.$url = this.$(".url")
+ },
+
+ show: function(){
+ this.$el.addClass("active")
+ this.$url.val("")
+ },
+
+ hide: function(){
+ this.$el.removeClass("active")
+ },
+
+ enterSubmit: function(e){
+ e.stopPropagation()
+ if (e.keyCode == 13) {
+ e.preventDefault()
+ var url = this.$tumblrUrl.val()
+ this.loadTumblr(url)
+ }
+ },
+
+ loadTumblr: function(url){
+ Parser.tumblr(url, function(media_list){
+ console.log(media_list)
+ this.parent.mediaViewer.$foundMediaContainer.empty()
+ media_list.reverse().forEach(function(media){
+ this.parent.mediaViewer.add(media, this.parent.mediaViewer.$foundMediaContainer)
+ }.bind(this))
+ }.bind(this))
+ },
+
+ loadExample: function(e){
+ e.preventDefault()
+ var name = $(e.currentTarget).html()
+ var url = "http://" + name + ".tumblr.com/"
+ this.$url.val(url)
+ this.loadTumblr(url)
+ },
+
+}) \ No newline at end of file
diff --git a/public/assets/javascripts/ui/editor/MediaUpload.js b/public/assets/javascripts/ui/editor/MediaUpload.js
index 92cf2bd..d09e38c 100644
--- a/public/assets/javascripts/ui/editor/MediaUpload.js
+++ b/public/assets/javascripts/ui/editor/MediaUpload.js
@@ -1,11 +1,12 @@
var MediaUpload = UploadView.extend({
- el: ".fileUpload",
+ el: "#fileUpload",
createAction: "/api/media/new",
uploadAction: "/api/media/upload",
events: {
+ 'mousedown': "stopPropagation",
"keydown .url": "enterSubmit",
},
@@ -25,6 +26,7 @@ var MediaUpload = UploadView.extend({
},
enterSubmit: function(e){
+ e.stopPropagation()
if (e.keyCode == 13) {
e.preventDefault()
this.parse()
@@ -34,7 +36,10 @@ var MediaUpload = UploadView.extend({
parse: function(){
var url = this.$url.val()
this.$url.val("")
-
+ this.parseUrl(url)
+ },
+
+ parseUrl: function(url){
Parser.parse(url, function(media){
if (! media) {
alert("Not a valid image/video link")
@@ -42,7 +47,6 @@ var MediaUpload = UploadView.extend({
}
media._csrf = $("[name=_csrf]").val()
- console.log(media)
var request = $.ajax({
type: "post",
@@ -52,10 +56,15 @@ var MediaUpload = UploadView.extend({
request.done(this.add.bind(this))
}.bind(this))
},
-
+
add: function(media){
console.log(media)
- this.parent.mediaViewer.add(media)
+ this.parent.mediaViewer.addUploadedMedia(media)
+ },
+
+ error: function(error){
+ console.log(error)
+ alert(error.errors.media.message)
},
beforeUpload: function(){
diff --git a/public/assets/javascripts/ui/editor/MediaViewer.js b/public/assets/javascripts/ui/editor/MediaViewer.js
index 436c0cb..2ae5104 100644
--- a/public/assets/javascripts/ui/editor/MediaViewer.js
+++ b/public/assets/javascripts/ui/editor/MediaViewer.js
@@ -3,44 +3,82 @@ var MediaViewer = ModalView.extend({
el: ".mediaDrawer.mediaViewer",
destroyAction: "/api/media/destroy",
usesFileUpload: true,
-
+ loaded: false,
+ perPage: 12,
+ offset: 0,
+ fixedClose: true,
+
events: {
+ 'mousedown': "stopPropagation",
'click .foundToggle': "foundToggle",
'click .userToggle': "userToggle",
'click #deleteMedia': "deleteArmed",
+ 'click #randomize': "randomize",
'click .mediaContainer': "pick",
+ 'click .viewMore': "load",
+ 'keydown #tumblr-url': 'enterTumblrUrl',
},
initialize: function(opt){
this.__super__.initialize.call(this)
this.parent = opt.parent
+
+ this.$myMedia = this.$(".myMedia").addClass('active')
+ this.$myMediaContainer = this.$(".myMedia > .container")
+ this.$userToggle = this.$(".userToggle")
+
this.$foundMedia = this.$(".foundMedia")
- this.$myMedia = this.$(".myMedia")
+ this.$foundMediaContainer = this.$(".foundMedia > .container")
this.$foundToggle = this.$(".foundToggle")
- this.$userToggle = this.$(".userToggle")
+
+ this.$wallpaperMedia = this.$(".wallpaperMedia")
+ this.$wallpaperMediaContainer = this.$(".wallpaperMedia > .container")
+ this.$wallpaperToggle = this.$(".wallpaperToggle")
+
this.$deleteMedia = this.$("#deleteMedia")
- },
+ this.$viewMore = this.$(".viewMore")
+ this.$noMedia = this.$(".noMedia")
+ },
+ mode: "user",
+ wallpaperToggle: function(){
+ this.mode = "wallpaper"
+ this.$wallpaperMedia.addClass("active")
+ this.$foundMedia.addClass("inactive")
+ this.$myMedia.addClass("inactive").removeClass('active')
+ this.$("a").removeClass("active")
+ this.$foundToggle.addClass("active")
+ },
+
foundToggle: function(){
- this.foundMedia.addClass("active");
- this.myMedia.addClass("inactive");
- this.$("a").removeClass("active");
- this.foundToggle.addClass("active");
+ this.mode = "found"
+ this.$wallpaperMedia.removeClass("active")
+ this.$foundMedia.addClass("active")
+ this.$myMedia.addClass("inactive").removeClass('active')
+ this.$("a").removeClass("active")
+ this.$foundToggle.addClass("active")
+ this.parent.mediaUpload.hide()
+ this.parent.mediaTumblr.show()
},
userToggle: function(){
- this.foundMedia.removeClass("active");
- this.myMedia.removeClass("inactive");
- this.$("a").removeClass("active");
- this.userToggle.addClass("active");
+ this.mode = "user"
+ this.$wallpaperMedia.removeClass("active")
+ this.$foundMedia.removeClass("active")
+ this.$myMedia.removeClass("inactive").addClass('active')
+ this.$("a").removeClass("active")
+ this.$userToggle.addClass("active")
+ this.parent.mediaUpload.show()
+ this.parent.mediaTumblr.hide()
},
show: function(){
if (! this.loaded) {
this.load()
+ // this.loadTrending()
}
else {
- this.__super__.show.call(this)
+ this.reallyShow()
}
},
@@ -48,24 +86,110 @@ var MediaViewer = ModalView.extend({
this.__super__.hide.call(this)
this.deleteArmed(false)
this.parent.mediaUpload.hide()
+ this.parent.mediaTumblr.hide()
+ this.parent.cursor.message('start')
+ },
+
+ reallyShow: function(){
+ this.__super__.show.call(this)
+ if (this.mode == "user") {
+ this.userToggle()
+ }
+ else {
+ this.foundToggle()
+ }
+ this.parent.cursor.message("media")
},
load: function(){
- $.get("/api/media/user", this.populate.bind(this))
+ $.get("/api/media/user", { offset: this.offset, limit: this.perPage }, this.populate.bind(this))
+ },
+
+/*
+ loadTrending: function(){
+ var trending_imagery = [
+ 'https://d1ycxz9plii3tb.cloudfront.net/post_images/52ec0e20c9dc24f1d8000067/large.jpg',
+ 'https://d1ycxz9plii3tb.cloudfront.net/additional_images/4e6bf67bc23f490001004579/1/tall.jpg',
+ 'https://d1ycxz9plii3tb.cloudfront.net/additional_images/52dcca28139b2135030002a8/tall.jpg',
+ 'https://d1ycxz9plii3tb.cloudfront.net/additional_images/52927bb2b202a3669d000704/larger.jpg',
+ 'https://d1ycxz9plii3tb.cloudfront.net/additional_images/4f9f3a3ce262e60001000fb3/large.jpg',
+ 'http://2.bp.blogspot.com/-GD6IxUvsdOo/UdrcMFLVYNI/AAAAAAAAF2E/kbRfxMxiUlQ/s1600/okeeffe.jpg',
+ 'http://www.bobkessel.com/wordpress/wp-content/uploads/2009/10/moma-bob-kessel-410.jpg',
+ 'http://static1.artsy.net/partner_show_images/52f28f348b3b81f2fc000364/large.jpg',
+ 'http://static3.artsy.net/partner_show_images/52e83674c9dc24397f0000d8/large.jpg',
+ 'http://static0.artsy.net/partner_show_images/52d96d484b84801ef0000273/large.jpg',
+ 'http://static1.artsy.net/partner_show_images/52778616275b24f95c00011d/1/large.jpg',
+ 'http://static1.artsy.net/partner_show_images/52dc65311a1e86be6b000205/large.jpg',
+ ]
+ trending_imagery.forEach(function(url){
+ var loaded = false
+ var img = new Image ()
+ img.onload = function(){
+ if (loaded) return
+ loaded = true
+ var media = {
+ type: 'image',
+ url: url,
+ width: img.naturalWidth,
+ height: img.naturalHeight,
+ }
+ this.add(media, this.$foundMediaContainer)
+ }.bind(this)
+ img.src = url
+ if (img.complete && ! loaded) { img.onload() }
+ }.bind(this))
},
+*/
+
+ randomize: function(){
+ var $divs = this.$(".active .container").find(".mediaContainer").toArray()
+ if ($divs.length < 3) {
+ $divs = $divs.concat( this.$foundMediaContainer.find(".mediaContainer").toArray() )
+ }
+ var media_objs = $divs.map(function(el){
+ return $(el).data("media")
+ })
+ Scenery.randomize.add( media_objs )
+ this.hide()
+ },
populate: function(data){
- this.loaded = true
+ var scrollTop = this.loaded ? $('.myMedia .container').height() : 0
if (data && data.length) {
- data.forEach(this.add.bind(this))
+ if (data.length < this.perPage) {
+ this.$viewMore.hide()
+ }
+ data.forEach(function(media){
+ this.add(media, this.$myMediaContainer)
+ this.offset += 1
+ }.bind(this))
+ this.$noMedia.hide()
+ this.$deleteMedia.show()
}
else {
+ this.$viewMore.hide()
+ this.$noMedia.show()
this.$deleteMedia.hide()
}
- this.__super__.show.call(this)
+ if (this.loaded) {
+ this.$el.delay(300).animate({ scrollTop: scrollTop }, 200)
+ }
+ else {
+ this.loaded = true
+ this.reallyShow()
+ }
+ },
+
+ addUploadedMedia: function(media){
+ this.$deleteMedia.show()
+ this.$noMedia.hide()
+ this.add(media, this.$myMedia, true) // prepend
+ this.userToggle()
+ this.$el.scrollTop(0)
+ this.offset += 1
},
- add: function(media){
+ add: function(media, $container, prepend){
var image = new Image ()
var $span = $("<span>")
$span.addClass("mediaContainer")
@@ -87,13 +211,17 @@ var MediaViewer = ModalView.extend({
image.src = media.url
image.load()
break
+
+ case 'soundcloud':
+ image.src = media.thumbnail
+ break
}
$span.data("media", media)
$span.append(image)
- this.$(".myMedia").prepend($span)
- this.$deleteMedia.show()
+ if (prepend) $container.prepend($span)
+ else $container.append($span)
},
deleteIsArmed: false,
@@ -131,35 +259,23 @@ var MediaViewer = ModalView.extend({
if ($(".myMedia .mediaContainer").length == 0) {
this.$deleteMedia.hide()
+ this.$noMedia.show()
this.deleteArmed(false)
}
return
}
-// else {
-// this.picked = {}
-// this.picked.media = media
-// this.picked.image = image
-// }
-// },
-//
-// drag: function(e){
-// if (! this.pickedMedia) return
-// var media = this.picked.media
-// var image = this.picked.image
-// this.picked = null
-
this.hide()
-
+ this.parent.cursor.message('addmedia')
+
var $ants = $('.ants');
var $floatingImg = $('.floatingImg');
Scenery.nextMedia = media
-// console.log(media.type)
-
switch (media.type) {
case "video":
+ case "soundcloud":
$floatingImg.attr('src', '/assets/img/playbutton.png')
break
@@ -185,12 +301,15 @@ var MediaViewer = ModalView.extend({
$floatingImg.attr('src', '')
$(window).off('mousemove', _followCursor)
$(window).off('mousedown', _hideCursor)
+ app.off('cancel-scenery', _hideCursor)
$floatingImg.parent().removeClass('edit')
+ app.controller.cursor.message('resize')
}
$(window).on('mousemove', _followCursor)
$(window).on('mousedown', _hideCursor)
+ app.on('cancel-scenery', _hideCursor)
$ants.addClass('edit')
_followCursor(e)
},
-
+
})
diff --git a/public/assets/javascripts/ui/editor/Presets.js b/public/assets/javascripts/ui/editor/Presets.js
new file mode 100644
index 0000000..5f5ac35
--- /dev/null
+++ b/public/assets/javascripts/ui/editor/Presets.js
@@ -0,0 +1,122 @@
+var Presets = View.extend({
+ el: "#presets",
+
+ events: {
+ "mousedown": "stopPropagation",
+ "click .presets span": "selectPreset",
+ },
+
+ 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],
+ background: [109,116,106],
+ },
+ "P.Funk": {
+ wall: [255,63,78],
+ outline: [255,246,0],
+ floor: [255,255,0],
+ ceiling: [225,118,252],
+ },
+ inverse: {
+ wall: [0,0,0],
+ outline: [255,255,255],
+ floor: [0,0,0],
+ ceiling: [0,0,0],
+ },
+ matrix: {
+ wall: { src: "http://dumpfm.s3.amazonaws.com/images/20130225/1361818675427-dumpfm-melipone-matrixremixtransfast.gif", scale: 4.0, color: [0,0,0] },
+ outline: [0,0,0],
+ floor: [10,15,10],
+ ceiling: [0,0,0],
+ },
+ },
+
+ initialize: function(opt){
+ this.parent = opt.parent
+
+ this.$presets = this.$(".presets")
+ _.keys(this.presets).forEach(function(name){
+ var $swatch = $("<span>")
+ $swatch.html(capitalize(name))
+ $swatch.data('preset', name)
+ this.$presets.append($swatch)
+ }.bind(this))
+ },
+
+ modified: true,
+ lastPreset: "wireframe",
+
+ toggle: function(state){
+ this.$el.toggleClass("active", state)
+ this.parent.cursor.message(state ? "presets" : "start")
+ if (this.modified) {
+ this.$(".active").removeClass('active')
+ }
+ },
+
+ show: function(){
+ this.toggle(true)
+ },
+
+ hide: function(){
+ this.toggle(false)
+ },
+
+ selectPreset: function(e){
+ var preset = $(e.currentTarget).data('preset')
+ if (! this.presets[preset]) return
+ this.$(".active").removeClass('active')
+ $(e.currentTarget).addClass('active')
+ if (this.modified) {
+ UndoStack.push({
+ type: "choose-preset",
+ undo: { walls: Walls.serialize(), colors: Walls.copyColors(Walls.colors) },
+ redo: preset,
+ })
+ Minotaur.watch( app.router.editorView.settings )
+ }
+ else {
+ UndoStack.push({
+ type: "choose-another-preset",
+ undo: this.lastPreset,
+ redo: preset,
+ })
+ Minotaur.watch( app.router.editorView.settings )
+ }
+ this.lastPreset = preset
+ this.load(this.presets[preset])
+ this.modified = false
+ },
+
+ loadByName: function(name){
+ var preset = this.presets[name]
+ this.load(preset)
+ },
+ load: function(preset){
+ this.parent.colorControl.modes.forEach(function(mode){
+ var color
+ if (! preset[mode].length) {
+ Walls.setWallpaper[mode](preset[mode])
+ color = preset[mode].color
+ }
+ else {
+ Walls.clearWallpaper[mode]()
+ color = preset[mode]
+ }
+ Walls.setColor[mode](color)
+ this.parent.colorControl.$swatch[ mode ].css("background-color", rgb_string(color))
+ }.bind(this))
+ this.parent.colorControl.setMode(preset.wall.color ? "wall" : "floor")
+ Walls.setBodyColor()
+ },
+
+}) \ No newline at end of file
diff --git a/public/assets/javascripts/ui/editor/SculptureEditor.js b/public/assets/javascripts/ui/editor/SculptureEditor.js
new file mode 100644
index 0000000..953260c
--- /dev/null
+++ b/public/assets/javascripts/ui/editor/SculptureEditor.js
@@ -0,0 +1,237 @@
+
+var SculptureEditor = FormView.extend({
+ el: "#sculptureEditor",
+
+ events: {
+ "keydown": 'taint',
+ "focus [name]": "clearMinotaur",
+ "click [data-role=play-media]": "togglePaused",
+ "mousedown [name=keyframe]": "stopPropagation",
+ "mousedown": "stopPropagation",
+ "change [name=keyframe]": "seek",
+ "change [name=autoplay]": "setAutoplay",
+ "change [name=billboard]": "setBillboard",
+ "change [name=outline]": "setOutline",
+ "change [name=outlineColor]": "setOutlineColor",
+ "change [name=loop]": "setLoop",
+ "change [name=mute]": "setMute",
+ "change [name=width]": 'changeWidth',
+ "change [name=height]": 'changeHeight',
+ "change [name=depth]": 'changeDepth',
+ "change [name=units]": 'changeUnits',
+ "click [data-role=destroy-sculpture]": "destroy",
+ },
+
+ initialize: function(opt){
+ this.parent = opt.parent
+ this.__super__.initialize.call(this)
+
+ this.$name = this.$("[name=name]")
+ this.$description = this.$("[name=description]")
+
+ this.$billboard = this.$("[name=billboard]")
+ this.$outline = this.$("[name=outline]")
+ this.$outlineColor = this.$("[name=outlineColor]")
+
+ // image fields
+ this.$width = this.$("[name=width]")
+ this.$height = this.$("[name=height]")
+ this.$depth = this.$("[name=depth]")
+ 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) {
+ if (state) {
+ this.parent.settings.toggle()
+ }
+ this.$el.toggleClass("active", state);
+ },
+
+ togglePaused: function(state){
+ var state = this.sculpture.toggle(state)
+ this.$playButton.toggleClass("paused", ! state)
+ },
+
+ pick: function(sculpture) {
+ if (this.sculpture && sculpture !== this.sculpture) {
+ this.unbind()
+ }
+
+ this.bind(sculpture)
+ this.$el.addClass("active")
+
+// app.controller.toolbar.resetMode()
+ app.controller.toolbar.resetControls()
+ Sculpture.resize.show(sculpture)
+ Sculpture.hovering = true
+
+ var media = sculpture.media
+
+ // console.log(media)
+ this.$name.val(media.title || "") // || filenameFromUrl(media.url) )
+ this.$description.val(media.description || "")
+ this.setDimensions()
+ this.$units.val( "ft" )
+
+ this.$outline.prop( 'checked', !! sculpture.outline )
+ this.$outlineColor.val( sculpture.outlineColor || "#000000" )
+ this.$billboard.prop( 'checked', !! sculpture.billboard )
+
+ switch (media.type) {
+ case "image":
+ this.$(".video").hide()
+ this.$(".audio").hide()
+ this.$(".image").show()
+ break
+
+ case "youtube":
+ case "vimeo":
+ case "video":
+ this.$(".image").hide()
+ this.$(".audio").hide()
+ this.$(".video").show()
+
+ this.$playButton.toggleClass("paused", ! this.sculpture.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
+
+ case "soundcloud":
+ this.$(".image").hide()
+ this.$(".video").hide()
+ this.$(".audio").show()
+ this.$playButton.toggleClass("paused", ! this.sculpture.paused())
+ this.$autoplay.prop('checked', !! media.autoplay)
+ this.$loop.prop('checked', !! media.loop)
+ break
+ }
+ },
+
+ hide: function(sculpture){
+ if (this.sculpture) {
+ this.unbind()
+ }
+ this.toggle(false)
+ },
+
+ seek: function(){
+ var n = parseFloat( this.$keyframe.val() )
+ this.sculpture.seek(n)
+ this.tainted = true
+
+ this.sculpture.media.keyframe = n
+ },
+ setAutoplay: function(){
+ var checked = this.$autoplay.prop('checked')
+ this.sculpture.media.autoplay = checked
+ this.tainted = true
+ if (checked && this.sculpture.paused()) {
+ this.togglePaused()
+ }
+ },
+ setLoop: function(){
+ var checked = this.$loop.prop('checked')
+ this.sculpture.setLoop(checked)
+ this.tainted = true
+ },
+ setMute: function(){
+ var checked = this.$mute.prop('checked')
+ this.sculpture.media.mute = checked
+ this.sculpture.mute(checked)
+ this.tainted = true
+ },
+
+ setBillboard: function(){
+ var checked = this.$billboard.prop('checked')
+ this.sculpture.setBillboard(checked)
+ this.tainted = true
+ },
+ setOutline: function(){
+ var checked = this.$outline.prop('checked')
+ this.sculpture.setOutline(checked)
+ this.tainted = true
+ },
+ setOutlineColor: function(){
+ var color = this.$outlineColor.val()
+ this.sculpture.setOutlineColor(color)
+ this.tainted = true
+ },
+
+ setDimensions: function(){
+ if (! this.sculpture) return
+ this.$width.unitVal( Number(this.sculpture.naturalDimensions.a * this.sculpture.scale) || "" )
+ this.$height.unitVal( Number(this.sculpture.naturalDimensions.b * this.sculpture.scale) || "" )
+ this.$depth.unitVal( Number(this.sculpture.naturalDimensions.c * this.sculpture.scale) || "" )
+ this.tainted = true
+ },
+ changeWidth: function(e){
+ e.stopPropagation()
+ this.sculpture.set_scale( this.$width.unitVal() / this.sculpture.naturalDimensions.a )
+ this.setDimensions()
+ this.sculpture.updateOutline()
+ },
+ changeHeight: function(e){
+ e.stopPropagation()
+ this.sculpture.set_scale( this.$height.unitVal() / this.sculpture.naturalDimensions.b )
+ this.setDimensions()
+ this.sculpture.updateOutline()
+ },
+ changeDepth: function(e){
+ e.stopPropagation()
+ this.sculpture.set_depth( this.$depth.unitVal() )
+ this.$depth.unitVal( Number(this.sculpture.naturalDimensions.c * this.sculpture.scale) || "" )
+ this.sculpture.updateOutline()
+ },
+ changeUnits: function(){
+ app.units = this.$units.val()
+ this.$('.units').resetUnitVal()
+ },
+
+ taint: function(e){
+ e.stopPropagation()
+ this.tainted = true
+ },
+
+ bind: function(sculpture){
+ this.sculpture = sculpture
+ this.sculpture.mx.bound = true
+ this.sculpture.mx.el.classList.add("picked")
+ },
+
+ unbind: function(){
+ if (this.sculpture) {
+ this.sculpture.focused = false
+ if (this.tainted && this.sculpture.media) {
+ this.sculpture.media.title = this.$name.val()
+ this.sculpture.media.description = this.$description.val()
+ Minotaur.watch( app.router.editorView.settings )
+ }
+ if (this.sculpture.mx) {
+ this.sculpture.mx.bound = false
+ this.sculpture.mx.el.classList.remove("picked")
+ }
+ }
+ this.tainted = false
+ this.sculpture = null
+ },
+
+ destroy: function(){
+ var sculpture = this.sculpture
+ this.hide()
+
+ sculpture.remove()
+
+ this.tainted = false
+ this.sculpture = null
+ },
+
+})
diff --git a/public/assets/javascripts/ui/editor/TextEditor.js b/public/assets/javascripts/ui/editor/TextEditor.js
new file mode 100644
index 0000000..53d5b9f
--- /dev/null
+++ b/public/assets/javascripts/ui/editor/TextEditor.js
@@ -0,0 +1,238 @@
+
+var TextEditor = FormView.extend({
+ el: "#textEditor",
+ tainted: false,
+ scenery: null,
+
+ events: {
+ "keydown": 'taint',
+ "focus [name]": "clearMinotaur",
+ "mousedown": "stopPropagation",
+ "change [name=font-family]": 'changeFontFamily',
+ "change [name=font-size]": 'changeFontSize',
+ "change [name=text-align]": 'changeTextAlign',
+ "click .swatch": 'showColorPicker',
+ "click [data-role=hide-color-picker]": 'hideColorPicker',
+ "click [data-role=hide-text-editor]": 'hide',
+ "input [name=text-body]": 'changeText',
+ "click [data-role=destroy-text]": "destroy",
+ "click .colors span": "setHue",
+ },
+
+ initialize: function(opt){
+ this.parent = opt.parent
+ this.__super__.initialize.call(this)
+
+ this.$textSettings = this.$(".text-setting")
+ this.$colorSettings = this.$(".color-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]")
+ this.$swatch = this.$(".swatch")
+
+ this.colorPicker = new LabColorPicker(this, 155, 155)
+ this.$(".color-picker").append( this.colorPicker.canvas )
+ this.$(".color-picker").append( this.colorPicker.cursor )
+ this.$(".slider").append( this.colorPicker.brightness )
+
+ this.$colors = this.$(".colors")
+ this.parent.colorControl.colors.forEach(function(color){
+ var $swatch = $("<span>")
+ $swatch.css("background-color","rgb(" + color + ")")
+ $swatch.data('color', color)
+ this.$colors.append($swatch)
+ }.bind(this))
+
+ this.$(".setting").hide()
+
+ app.on("cancel-scenery", function(){
+ this.createMode(true)
+ $("body").toggleClass("addText", false)
+ }.bind(this))
+
+ },
+
+ toggle: function(state){
+ this.$el.toggleClass("active", state)
+ if (state) {
+ $("#keyhint").fadeOut(200)
+ Scenery.nextMedia = {
+ type: 'text',
+ width: 600,
+ height: 450,
+ scale: 0.5,
+ font: { family: 'Lato', size: 24, align: 'left', color: "#000" },
+ }
+ this.createMode(true)
+ }
+ else {
+ $("[data-role='toggle-text-editor']").removeClass("inuse")
+ }
+ },
+
+ hide: function(scenery){
+ Scenery.nextMedia = null
+ if (this.scenery) {
+ this.unbind()
+ }
+ Scenery.resize.hide()
+ 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")
+ this.scenery.media.font.color = this.scenery.media.font.color || [0,0,0]
+ },
+
+ unbind: function(){
+ if (this.scenery) {
+ this.scenery.focused = false
+ 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")
+ }
+ if (! this.scenery.media || ! this.scenery.media.description || this.scenery.media.description == "") {
+ this.scenery.remove()
+ }
+ }
+ this.tainted = false
+ this.scenery = null
+ },
+
+ createMode: function(state){
+ this.hideColorPicker()
+ this.$textSettings.toggle(! state)
+ this.$noTextMessage.toggle(!! state)
+ $("body").toggleClass("addText", !! state)
+ },
+
+ pick: function(scenery){
+ if (this.scenery && scenery !== this.scenery) {
+ this.unbind()
+ }
+
+ this.parent.settings.hide()
+ 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.setSwatchColor( this.scenery.media.font.color )
+
+ this.createMode(false)
+
+ if (! this.scenery.media.description) {
+ setTimeout(function(){
+ this.$textBody.focus()
+ }.bind(this), 100)
+ }
+ },
+
+ taint: function(e){
+ e.stopPropagation()
+ },
+
+ 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(e){
+ e.stopPropagation()
+ var text = this.$textBody.val()
+ this.scenery.setText(text)
+ },
+
+ destroy: function(){
+ this.tainted = false
+ this.scenery.remove()
+ this.hide()
+ },
+
+ setSwatchColor: function(rgb){
+ this.$swatch.css("background-color", rgb_string(rgb))
+ },
+ showColorPicker: function(){
+ this.$textSettings.hide()
+ this.$colorSettings.show()
+
+ var color = this.scenery.media.font.color
+ this.labColor = this.colorPicker.load(color)
+ this.pickColor(color, this.labColor)
+
+ this.$el.addClass("color-mode")
+ },
+
+ hideColorPicker: function(e){
+ e && e.preventDefault()
+ this.$textSettings.show()
+ this.$colorSettings.hide()
+ this.$el.removeClass("color-mode")
+ },
+
+ pickColor: function(rgb, Lab){
+ this.labColor = Lab
+ this.setSwatchColor(rgb)
+ this.scenery.setFont({ color: rgb })
+ this.tainted = true
+ },
+
+ setHue: function(e){
+ var color = $(e.currentTarget).data('color')
+ this.labColor = this.colorPicker.load(color)
+ this.pickColor(color, this.labColor)
+ },
+
+ initialState: null,
+
+ begin: function(){
+ // this.initialState = this.serialize()
+ },
+
+ serialize: function(){
+ return {
+ rgb: Walls.colors[ this.mode ]
+ }
+ },
+
+ finalize: function(){
+ if (! this.initialState) { return }
+ UndoStack.push({
+ type: 'update-colors',
+ undo: this.initialState,
+ redo: this.serialize(),
+ })
+
+ this.initialState = null
+
+ // TODO: watch individual wall object here
+ Minotaur.watch( app.router.editorView.settings )
+ },
+
+})
diff --git a/public/assets/javascripts/ui/editor/WallpaperPicker.js b/public/assets/javascripts/ui/editor/WallpaperPicker.js
index 0dd2921..3640d6d 100644
--- a/public/assets/javascripts/ui/editor/WallpaperPicker.js
+++ b/public/assets/javascripts/ui/editor/WallpaperPicker.js
@@ -3,34 +3,57 @@ var WallpaperPicker = UploadView.extend({
el: ".wallpaper",
mediaTag: "wallpaper",
+ createAction: "/api/media/new",
uploadAction: "/api/media/upload",
+ destroyAction: "/api/media/destroy",
events: {
+ "contextmenu": 'contextmenu',
+ "mousedown": 'stopPropagation',
"click .swatch": 'pick',
"click .wallpaperRemove": 'remove',
+ "input [data-role='wallpaper-scale']": 'updateScale',
+ "change .url": "enterUrl",
+ "keydown .url": "enterSetUrl",
},
- initialize: function(){
+ initialize: function(opt){
+ this.parent = opt.parent
this.__super__.initialize.call(this)
this.$swatches = this.$(".swatches")
this.$remove = this.$(".wallpaperRemove")
- this.$remove.hide()
+
+ this.$url = this.$(".url")
+
+ this.$position = this.$("[data-role='wallpaper-position']")
+ this.$scale = this.$("[data-role='wallpaper-scale']")
+
+ this.$wallpaperResizeControls = this.$(".wallpaperResizeControls")
+ this.$wallpaperResizeControls.addClass('disabled')
+
+ this.initializePositionCursor()
},
loaded: false,
show: function(){
- if (! this.loaded) {
- this.load()
- }
- else {
- this.toggle(true)
- }
+ this.toggle(true)
},
-
hide: function(){
- this.__super__.hide.call(this)
+ this.toggle(false)
},
-
+
+ toggle: function (state) {
+ Scenery.nextWallpaper = null
+ app.tube('cancel-wallpaper')
+ this.$el.toggleClass("active", state)
+ if (state) {
+ this.parent.cursor.message("wallpaper")
+ if (! this.loaded) {
+ this.load()
+ }
+ }
+ },
+
load: function(){
$.get("/api/media/user", { tag: this.mediaTag }, this.populate.bind(this))
},
@@ -39,49 +62,98 @@ var WallpaperPicker = UploadView.extend({
this.loaded = true
if (data && data.length) {
data.forEach(this.add.bind(this))
+ this.$(".txt").hide()
+ }
+ else {
+ this.$(".txt").show()
}
this.toggle(true)
},
+ seenWallpapers: {},
add: function (media) {
if (media.type !== "image") { return }
+ if (this.seenWallpapers[ media.url ]) { return }
var swatch = document.createElement("div")
swatch.className = "swatch"
swatch.style.backgroundImage = "url(" + media.url + ")"
+ swatch.setAttribute("data-id", media._id)
this.$swatches.append(swatch)
this.$swatches.show()
- },
-
- toggle: function (state) {
- if (state && ! this.loaded) {
- this.show()
- }
- else {
- this.$el.toggleClass("active", state)
- }
- // toggle the class that makes the cursor a paintbucket
- // $("body").removeClass("pastePaper")
+ this.$(".txt").hide()
+ this.seenWallpapers[ media.url ] = true
},
- hide: function(){
- this.toggle(false)
+ addUrl: function (url){
+ Parser.loadImage(url, function(media){
+ if (! media) return
+ media._csrf = $("[name=_csrf]").val()
+ media.tag = this.mediaTag
+
+ var request = $.ajax({
+ type: "post",
+ url: this.createAction,
+ data: media,
+ })
+ request.done(this.add.bind(this))
+
+ }.bind(this))
},
-
+
beforeUpload: function(){
},
pick: function(e){
var $swatch = $(e.currentTarget)
- this.follow( e, $swatch.css('background-image') )
- this.$remove.show()
+ if (Scenery.nextWallpaper == "none") {
+ var _id = $swatch[0].getAttribute("data-id")
+ $swatch.remove()
+ this.destroy(_id, function(){})
+ }
+ else {
+ app.tube('cancel-wallpaper')
+ this.follow( e, $swatch.css('background-image') )
+ this.parent.presets.modified = true
+ }
},
remove: function(e){
- this.follow( e, "none" )
- $(".floatingSwatch").addClass("scissors")
+ if (Scenery.nextWallpaper) {
+ // remove red class to the wallpaper
+ Scenery.nextWallpaper = null
+ app.tube('cancel-wallpaper')
+ }
+ else {
+ // add red class to the wallpaper
+ this.follow( e, "none" )
+ $(".floatingSwatch").addClass("scissors")
+ this.$el.addClass("deleteArmed")
+ }
+ },
+
+ destroy: function(_id, cb){
+ $.ajax({
+ type: "delete",
+ url: this.destroyAction,
+ data: { _id: _id, _csrf: $("[name=_csrf]").val() }
+ }).complete(cb || function(){})
+ },
+
+ contextmenu: function(e){
+ if (Scenery.nextWallpaper) {
+ e.preventDefault()
+ this.cancel()
+ }
+ },
+ cancel: function(){
+ if (Scenery.nextWallpaper) {
+ Scenery.nextWallpaper = null
+ app.tube('cancel-wallpaper')
+ }
},
follow: function(e, wallpaper, icon){
+ var base = this
icon = icon || wallpaper
var $floatingSwatch = $(".floatingSwatch")
@@ -90,6 +162,8 @@ var WallpaperPicker = UploadView.extend({
Scenery.nextWallpaper = wallpaper
+ $(".floodMessage").show()
+
setTimeout(function(){
function _followCursor(e) {
$floatingSwatch.css({
@@ -97,14 +171,105 @@ var WallpaperPicker = UploadView.extend({
left: (e.pageX + 10) + 'px',
});
}
- $(window).on('mousemove', _followCursor)
- $(window).one('click', function () {
+ function _hideCursor (e) {
+ $(window).off('keydown', _floodRoom)
$(window).off('mousemove', _followCursor)
+ app.off('cancel-wallpaper', _hideCursor)
$floatingSwatch.removeClass("scissors").hide()
- });
+ $(".floodMessage").hide()
+ base.$el.removeClass("deleteArmed")
+ }
+ function _floodRoom (e) {
+ if (e.keyCode == 13) {
+ base.flood()
+ }
+ }
+ $(window).on('keydown', _floodRoom)
+ $(window).on('mousemove', _followCursor)
+ // $(window).one('click', _hideCursor);
+ app.on('cancel-wallpaper', _hideCursor)
$floatingSwatch.show()
_followCursor(e);
})
},
+ wall: null,
+ pickWall: function(wall){
+ if (! wall.background || wall.background.src == "none") {
+ this.$wallpaperResizeControls.addClass('disabled')
+ this.$scale.val( 0.0 )
+ return;
+ }
+ this.$wallpaperResizeControls.removeClass('disabled')
+ this.wall = wall
+ this.$scale.val( Math.log( this.wall.background.scale ) )
+ },
+
+ scaleTimeout: null,
+ updateScale: function(){
+ if (! this.wall) return;
+ var scale = Math.exp( parseFloat(this.$scale.val()) )
+ this.wall.wallpaperPosition({ scale: scale })
+
+ clearTimeout(this.scaleTimeout)
+ this.scaleTimeout = setTimeout(function(){
+
+ // TODO: watch individual scenery object here
+ Minotaur.watch( app.router.editorView.settings )
+
+ }.bind(this), 500)
+ },
+
+ enterUrl: function(){
+ var url = this.$url.sanitize()
+ this.addUrl(url)
+ this.$url.val("")
+ },
+ enterSetUrl: function (e) {
+ e.stopPropagation()
+ if (e.keyCode == 13) {
+ setTimeout(this.enterUrl.bind(this), 100)
+ }
+ },
+
+ flood: function(url){
+ url = url || Scenery.nextWallpaper
+ if (! url) return
+ Walls.setWallpaper.wall({ src: url })
+ Walls.setWallpaper.floor({ src: url })
+ Walls.setWallpaper.ceiling({ src: url })
+ this.cancel()
+ },
+
+ initializePositionCursor: function(){
+ var base = this
+ var dx = 0, dy = 0, dragging = false, delta
+ var x = 0, y = 0, s = 1
+ var mymouse = new mouse({
+ el: this.$position[0],
+ down: function(e, cursor){
+ if (! base.wall) return
+ dragging = true
+ // s = parseFloat( base.$scale.val() )
+ x = base.wall.background.x
+ y = base.wall.background.y
+ },
+ drag: function(e, cursor){
+ if (! dragging) return
+ delta = cursor.delta()
+ delta.a = - delta.a
+ dx = delta.a*s
+ dy = delta.b*s
+ base.wall.wallpaperPosition({
+ // scale: s,
+ x: x+dx,
+ y: y+dy,
+ })
+ },
+ up: function(e, cursor, new_cursor){
+ dragging = false
+ },
+ })
+ },
+
})