diff options
Diffstat (limited to 'public/assets/javascripts/ui/editor')
| -rw-r--r-- | public/assets/javascripts/ui/editor/Collaborators.js | 1 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/ColorControl.js | 153 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/EditorSettings.js | 109 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/EditorToolbar.js | 154 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/EditorView.js | 54 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/HelpCursor.js | 79 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/LightControl.js | 280 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/MediaEditor.js | 63 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/MediaTumblr.js | 53 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/MediaUpload.js | 19 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/MediaViewer.js | 193 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/Presets.js | 122 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/SculptureEditor.js | 237 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/TextEditor.js | 238 | ||||
| -rw-r--r-- | public/assets/javascripts/ui/editor/WallpaperPicker.js | 229 |
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 + }, + }) + }, + }) |
