From 838ccfe6c2125e464d3c95c6e222e7e762dc8fd2 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Tue, 12 Aug 2014 18:19:33 -0400 Subject: undo stack for undo/redo --- public/assets/javascripts/rectangles/models/wall.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'public/assets/javascripts/rectangles/models/wall.js') diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 027d5f5..91e7c18 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -146,8 +146,6 @@ window.Wall = (function(){ if (shouldFlip) { sortedWalls = sortedWalls.reverse() } - -console.log(sortedWalls.map(function(z){return useX ? z.x : z.z}).join(" ")) var len = sortedWalls.length -- cgit v1.2.3-70-g09d2 From 90cb5b343f3d56372f9b43faf215ed80dd879fe1 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Wed, 13 Aug 2014 16:12:02 -0400 Subject: undo for scenery stuff --- .../javascripts/rectangles/engine/map/ui_editor.js | 16 +++---- .../rectangles/engine/scenery/_scenery.js | 9 +++- .../javascripts/rectangles/engine/scenery/move.js | 20 +++++++++ .../rectangles/engine/scenery/resize.js | 13 +++++- .../javascripts/rectangles/engine/scenery/undo.js | 20 +++++++++ .../assets/javascripts/rectangles/models/wall.js | 8 +++- public/assets/javascripts/rectangles/util/undo.js | 52 ---------------------- .../javascripts/rectangles/util/undostack.js | 52 ++++++++++++++++++++++ public/assets/javascripts/ui/editor/MediaEditor.js | 8 ++-- public/assets/javascripts/ui/lib/Parser.js | 2 - test/09-test-undo.js | 16 +++---- views/partials/scripts.ejs | 2 +- 12 files changed, 139 insertions(+), 79 deletions(-) delete mode 100644 public/assets/javascripts/rectangles/util/undo.js create mode 100644 public/assets/javascripts/rectangles/util/undostack.js (limited to 'public/assets/javascripts/rectangles/models/wall.js') diff --git a/public/assets/javascripts/rectangles/engine/map/ui_editor.js b/public/assets/javascripts/rectangles/engine/map/ui_editor.js index c5c996c..9a557b9 100644 --- a/public/assets/javascripts/rectangles/engine/map/ui_editor.js +++ b/public/assets/javascripts/rectangles/engine/map/ui_editor.js @@ -58,8 +58,8 @@ Map.UI.Editor = function(map){ UndoStack.push({ type: "destroy-room", - prev: room.copy(), - next: { id: room.id }, + undo: room.copy(), + redo: { id: room.id }, }) Rooms.remove(room) @@ -164,8 +164,8 @@ Map.UI.Editor = function(map){ UndoStack.push({ type: "create-room", - prev: { id: room.id }, - next: room.copy() + undo: { id: room.id }, + redo: room.copy() }) app.tube("builder-pick-room", room) @@ -185,8 +185,8 @@ Map.UI.Editor = function(map){ UndoStack.push({ type: "update-room", - prev: oldState, - next: base.dragging.copy() + undo: oldState, + redo: base.dragging.copy() }) } @@ -211,8 +211,8 @@ Map.UI.Editor = function(map){ wheelTimeout = setTimeout(function(){ UndoStack.push({ type: "update-room", - prev: wheelState, - next: intersects[0].copy() + undo: wheelState, + redo: intersects[0].copy() }) Rooms.clipper.update() wheelState = null diff --git a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js index fe5f037..c96885c 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js +++ b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js @@ -30,10 +30,15 @@ var Scenery = new function(){ } base.addNextToWall = function(wall){ - base.add(wall, base.nextMedia) + var media = base.add(wall, base.nextMedia) base.nextMedia = null + return media } - + + base.find = function(id){ + return base.list[id] || null + } + base.remove = function(id){ var media = base.list[id] delete base.list[id] diff --git a/public/assets/javascripts/rectangles/engine/scenery/move.js b/public/assets/javascripts/rectangles/engine/scenery/move.js index 94a4e52..ef9bc32 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/move.js +++ b/public/assets/javascripts/rectangles/engine/scenery/move.js @@ -3,6 +3,7 @@ Scenery.move = function(base){ var x, y, z, bounds var dragging = false + var oldState this.bind = function(){ Scenery.mouse.bind_el(base.mx.el) @@ -23,6 +24,12 @@ Scenery.move = function(base){ function down (e, cursor){ if (e.target != base.mx.el) return; if (editor.permissions.destroy) { + UndoStack.push({ + type: 'destroy-scenery', + undo: base.serialize(), + redo: { id: base.id }, + }) + Scenery.remove(base.id) return } @@ -39,6 +46,7 @@ Scenery.move = function(base){ y = base.mx.y z = base.mx.z bounds = base.bounds + oldState = base.serialize() document.body.classList.add("dragging") } @@ -63,8 +71,20 @@ Scenery.move = function(base){ } function up (e, cursor){ + if (! dragging || ! oldState) return + dragging = false document.body.classList.remove("dragging") + + console.log("pushing", oldState, base.serialize()) + + UndoStack.push({ + type: 'update-scenery', + undo: oldState, + redo: base.serialize(), + }) + + oldState = null } function switch_wall (e, new_wall, cursor){ diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js index df058bb..c5c754a 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/resize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js @@ -7,6 +7,7 @@ Scenery.resize = new function(){ var x, y, z, bounds var dragging = false var dimensions, position, scale + var oldState var dots = [], dot, selected_dot @@ -54,7 +55,7 @@ Scenery.resize = new function(){ } // move all the dots to the object's current position - base.move_dots = function(){ + base.move_dots = function(){ x = obj.mx.x + sin(rotationY) * dot_distance_from_picture y = obj.mx.y z = obj.mx.z - cos(rotationY) * dot_distance_from_picture @@ -88,7 +89,7 @@ Scenery.resize = new function(){ // pick a new object to focus on and show the dots base.show = function(new_object) { - if (obj === new_object) return + // if (obj === new_object) return obj = new_object base.add_dots() @@ -151,6 +152,7 @@ Scenery.resize = new function(){ dimensions = obj.dimensions position = new vec3(obj.mx.x, obj.mx.y, obj.mx.z) scale = obj.mx.scale + oldState = obj.serialize() document.body.classList.add("dragging") } @@ -191,6 +193,13 @@ Scenery.resize = new function(){ if (! editor.permissions.resize) { return } obj.scale = obj.mx.ops.scale = obj.mx.scale obj.set_wall() + + UndoStack.push({ + type: 'update-scenery', + undo: oldState, + redo: obj.serialize(), + }) + document.body.classList.remove("dragging") } diff --git a/public/assets/javascripts/rectangles/engine/scenery/undo.js b/public/assets/javascripts/rectangles/engine/scenery/undo.js index 4bdb2c4..7798550 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/undo.js +++ b/public/assets/javascripts/rectangles/engine/scenery/undo.js @@ -3,22 +3,42 @@ { type: "create-scenery", undo: function(state){ + Scenery.remove(state.id) }, redo: function(state){ + Scenery.deserialize([ state ]) }, }, { type: "update-scenery", undo: function(state){ + var scenery = Scenery.find(state.id) + scenery.deserialize(state) + scenery.set_wall(Rooms.walls[ state.wall_id ]) + + if (editor.permissions.resize) { + Scenery.resize.show(scenery) + } }, redo: function(state){ + var scenery = Scenery.find(state.id) + scenery.deserialize(state) + scenery.set_wall(Rooms.walls[ state.wall_id ]) + + if (editor.permissions.resize) { + Scenery.resize.show(scenery) + Scenery.resize.rotate_dots() + Scenery.resize.move_dots() + } }, }, { type: "destroy-scenery", undo: function(state){ + Scenery.deserialize([ state ]) }, redo: function(state){ + Scenery.remove(state.id) }, }, diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 91e7c18..6e2c728 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -43,7 +43,13 @@ window.Wall = (function(){ // base.randomize_colors() // console.log(sidesToString(base.side)) if (Scenery.nextMedia) { - Scenery.addNextToWall(base) + var scenery = Scenery.addNextToWall(base) + + UndoStack.push({ + type: 'create-scenery', + undo: { id: scenery.id }, + redo: scenery.serialize(), + }) } else if (Scenery.nextWallpaper) { base.wallpaper() diff --git a/public/assets/javascripts/rectangles/util/undo.js b/public/assets/javascripts/rectangles/util/undo.js deleted file mode 100644 index dfc74dc..0000000 --- a/public/assets/javascripts/rectangles/util/undo.js +++ /dev/null @@ -1,52 +0,0 @@ -(function(){ - - var UndoStack = function(){ - this.debug = true - this.stack = [] - this.types = {} - this.pointer = -1 - } - UndoStack.prototype.push = function(action){ - this.pointer++ - this.stack[this.pointer] = action - this.purge() - } - UndoStack.prototype.purge = function(){ - if (this.stack.length-1 == this.pointer) return - this.stack.length = this.pointer+1 - } - UndoStack.prototype.undo = function(){ - if (this.pointer == -1) return false - var action = this.stack[this.pointer] - this.debug && console.log("undo", action.type) - this.types[ action.type ].undo(action.prev) - this.pointer-- - return this.pointer > -1 - } - UndoStack.prototype.redo = function(){ - if (this.pointer == this.stack.length-1) return false - this.pointer++ - var action = this.stack[this.pointer] - this.debug && console.log("redo", action.type) - this.types[ action.type ].redo(action.next) - return this.pointer < this.stack.length-1 - } - UndoStack.prototype.register = function(actionType){ - if (actionType.length) { - actionType.forEach(this.registerOne.bind(this)) - } - else { - this.registerOne(actionType) - } - } - UndoStack.prototype.registerOne = function(actionType){ - this.types[ actionType.type ] = actionType - } - if ('window' in this) { - window.UndoStack = new UndoStack - } - else { - module.exports = new UndoStack - } - -})() diff --git a/public/assets/javascripts/rectangles/util/undostack.js b/public/assets/javascripts/rectangles/util/undostack.js new file mode 100644 index 0000000..b93c79e --- /dev/null +++ b/public/assets/javascripts/rectangles/util/undostack.js @@ -0,0 +1,52 @@ +(function(){ + + var UndoStack = function(){ + this.debug = true + this.stack = [] + this.types = {} + this.pointer = -1 + } + UndoStack.prototype.push = function(action){ + this.pointer++ + this.stack[this.pointer] = action + this.purge() + } + UndoStack.prototype.purge = function(){ + if (this.stack.length-1 == this.pointer) return + this.stack.length = this.pointer+1 + } + UndoStack.prototype.undo = function(){ + if (this.pointer == -1) return false + var action = this.stack[this.pointer] + this.debug && console.log("undo", action.type) + this.types[ action.type ].undo(action.undo) + this.pointer-- + return this.pointer > -1 + } + UndoStack.prototype.redo = function(){ + if (this.pointer == this.stack.length-1) return false + this.pointer++ + var action = this.stack[this.pointer] + this.debug && console.log("redo", action.type) + this.types[ action.type ].redo(action.redo) + return this.pointer < this.stack.length-1 + } + UndoStack.prototype.register = function(actionType){ + if (actionType.length) { + actionType.forEach(this.registerOne.bind(this)) + } + else { + this.registerOne(actionType) + } + } + UndoStack.prototype.registerOne = function(actionType){ + this.types[ actionType.type ] = actionType + } + if ('window' in this) { + window.UndoStack = new UndoStack + } + else { + module.exports = new UndoStack + } + +})() diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js index b9eb8fc..e3a8f2e 100644 --- a/public/assets/javascripts/ui/editor/MediaEditor.js +++ b/public/assets/javascripts/ui/editor/MediaEditor.js @@ -139,12 +139,14 @@ var MediaEditor = FormView.extend({ }, unbind: function(){ - this.scenery.mx.bound = false - this.scenery = null + if (this.scenery && this.scenery.mx) { + this.scenery.mx.bound = false + } + this.scenery = null }, destroy: function(){ - ConfirmModal.confirm("Are you sure you want to this media?", function(){ + ConfirmModal.confirm("Are you sure you want delete to this media?", function(){ var scenery = this.scenery this.hide() Scenery.remove(scenery.id) diff --git a/public/assets/javascripts/ui/lib/Parser.js b/public/assets/javascripts/ui/lib/Parser.js index 8867c0b..1cf0418 100644 --- a/public/assets/javascripts/ui/lib/Parser.js +++ b/public/assets/javascripts/ui/lib/Parser.js @@ -84,8 +84,6 @@ var Parser = { type: 'GET', url: 'http://vimeo.com/api/v2/video/' + id + '.json', success: function(result){ - console.log(result) - // embed_privacy: "nowhere" if (result.length == 0) { return done(id, "", 640, 360) } var res = result[0] if (res.embed_privacy != "anywhere") { diff --git a/test/09-test-undo.js b/test/09-test-undo.js index f774c04..dbca90e 100644 --- a/test/09-test-undo.js +++ b/test/09-test-undo.js @@ -34,22 +34,22 @@ describe('undo', function(){ UndoStack.push({ type: "demo", - prev: state, - next: "one" + undo: state, + redo: "one" }) state = "one" UndoStack.push({ type: "demo", - prev: state, - next: "two" + undo: state, + redo: "two" }) state = "two" UndoStack.push({ type: "demo", - prev: state, - next: "three" + undo: state, + redo: "three" }) state = "three" @@ -123,8 +123,8 @@ describe('undo', function(){ UndoStack.push({ type: "demo", - prev: state, - next: "four" + undo: state, + redo: "four" }) state = "four" diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index 087c0d7..dfb3a83 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -29,7 +29,7 @@ - + -- cgit v1.2.3-70-g09d2 From 410607684c7273a61f937635b41397208e245473 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 14 Aug 2014 13:57:42 -0400 Subject: autosave --- .../javascripts/rectangles/engine/scenery/move.js | 8 ++- .../rectangles/engine/scenery/resize.js | 3 + .../javascripts/rectangles/engine/scenery/undo.js | 18 ++++++ .../assets/javascripts/rectangles/models/wall.js | 3 + .../assets/javascripts/rectangles/util/minotaur.js | 67 ++++++++++++---------- .../javascripts/ui/builder/BuilderSettings.js | 3 + .../assets/javascripts/ui/editor/EditorSettings.js | 10 +++- public/assets/javascripts/ui/editor/MediaEditor.js | 1 + public/assets/javascripts/ui/lib/FormView.js | 28 +++++++-- public/assets/javascripts/ui/lib/View.js | 17 +++--- views/partials/scripts.ejs | 1 + 11 files changed, 111 insertions(+), 48 deletions(-) (limited to 'public/assets/javascripts/rectangles/models/wall.js') diff --git a/public/assets/javascripts/rectangles/engine/scenery/move.js b/public/assets/javascripts/rectangles/engine/scenery/move.js index c3f78d7..edeb24b 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/move.js +++ b/public/assets/javascripts/rectangles/engine/scenery/move.js @@ -30,6 +30,9 @@ Scenery.move = function(base){ redo: { id: base.id }, }) + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + Scenery.remove(base.id) return } @@ -81,7 +84,10 @@ Scenery.move = function(base){ undo: oldState, redo: base.serialize(), }) - + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + oldState = null } diff --git a/public/assets/javascripts/rectangles/engine/scenery/resize.js b/public/assets/javascripts/rectangles/engine/scenery/resize.js index c5c754a..6b2e52c 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/resize.js +++ b/public/assets/javascripts/rectangles/engine/scenery/resize.js @@ -200,6 +200,9 @@ Scenery.resize = new function(){ redo: obj.serialize(), }) + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) + document.body.classList.remove("dragging") } diff --git a/public/assets/javascripts/rectangles/engine/scenery/undo.js b/public/assets/javascripts/rectangles/engine/scenery/undo.js index 7798550..54ab755 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/undo.js +++ b/public/assets/javascripts/rectangles/engine/scenery/undo.js @@ -4,9 +4,15 @@ type: "create-scenery", undo: function(state){ Scenery.remove(state.id) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, redo: function(state){ Scenery.deserialize([ state ]) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, }, { @@ -19,6 +25,9 @@ if (editor.permissions.resize) { Scenery.resize.show(scenery) } + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, redo: function(state){ var scenery = Scenery.find(state.id) @@ -30,15 +39,24 @@ Scenery.resize.rotate_dots() Scenery.resize.move_dots() } + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, }, { type: "destroy-scenery", undo: function(state){ Scenery.deserialize([ state ]) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, redo: function(state){ Scenery.remove(state.id) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) }, }, diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index 6e2c728..fa09444 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -50,6 +50,9 @@ window.Wall = (function(){ undo: { id: scenery.id }, redo: scenery.serialize(), }) + + // TODO: watch individual scenery object here + Minotaur.watch( app.router.editorView.settings ) } else if (Scenery.nextWallpaper) { base.wallpaper() diff --git a/public/assets/javascripts/rectangles/util/minotaur.js b/public/assets/javascripts/rectangles/util/minotaur.js index 6eb36ec..039a053 100644 --- a/public/assets/javascripts/rectangles/util/minotaur.js +++ b/public/assets/javascripts/rectangles/util/minotaur.js @@ -1,54 +1,59 @@ (function(){ var Monitor = function () { - var base = this; - base.$el = $("#minotaur"); - base.timeout = null; - base.delay = 500; - base.objects = {}; + var base = this + base.$el = $("#minotaur") + base.timeout = null + base.delay = 500 + base.objects = {} base.init = function () { - base.$el.addClass('saved'); - base.$el.click(base.save); + base.$el.removeClass() + base.$el.click(base.save) } base.watch = function (object) { - base.objects[object.type] = base.objects[object.type] || {}; - base.objects[object.type][object.id] = object; - base.clear(); - base.timeout = setTimeout(base.save, base.delay); + base.objects[object.type] = base.objects[object.type] || {} + base.objects[object.type][object._id] = object + base.clear() + base.timeout = setTimeout(base.save, base.delay) + } + + base.unwatch = function (object) { + if (base.objects[object.type] && base.objects[object.type][object._id]) { + delete base.objects[object.type][object._id] + } } base.clear = function () { - if (base.timeout) clearTimeout(base.timeout); - base.timeout = false; + if (base.timeout) clearTimeout(base.timeout) + base.timeout = false } base.save = function () { - var saving = false; - base.clear(); + var saving = false + base.clear() for (var type in base.objects) { for (var id in base.objects[type]) { - if (base.timeout) - return; - var obj = base.objects[type][id]; - if (obj) obj.save(function(){ - base.$el.removeClass('unsaved saving').addClass('saved'); - saving = true; - }); - base.objects[type][id] = false; + var obj = base.objects[type][id] + if (obj) { + obj.save(null, function(){ base.hide() }, function(){}) + } + delete base.objects[type][id] + saving = true } } - if (saving) { - base.$el.removeClass('unsaved saved').addClass('saving'); - } - else { - base.$el.removeClass('unsaved saving').addClass('saved'); - } - - base.objects = {}; + saving ? base.show() : base.hide() + } + + base.show = function () { + base.$el.removeClass().addClass('saving') + } + + base.hide = function () { + base.$el.removeClass() } base.init(); diff --git a/public/assets/javascripts/ui/builder/BuilderSettings.js b/public/assets/javascripts/ui/builder/BuilderSettings.js index c551f95..0091454 100644 --- a/public/assets/javascripts/ui/builder/BuilderSettings.js +++ b/public/assets/javascripts/ui/builder/BuilderSettings.js @@ -122,6 +122,9 @@ var BuilderSettings = FormView.extend({ this.$name.val(data.name) this.action = this.updateAction + Minotaur.unwatch(this) + Minotaur.hide() + window.history.pushState(null, document.title, "/layout/" + data.slug) }, diff --git a/public/assets/javascripts/ui/editor/EditorSettings.js b/public/assets/javascripts/ui/editor/EditorSettings.js index d6a79fb..9d75f66 100644 --- a/public/assets/javascripts/ui/editor/EditorSettings.js +++ b/public/assets/javascripts/ui/editor/EditorSettings.js @@ -5,7 +5,7 @@ var EditorSettings = FormView.extend({ createAction: "/api/project/new", updateAction: "/api/project/edit", destroyAction: "/api/project/destroy", - + events: { "keydown": 'stopPropagation', "keydown [name=name]": 'enterSubmit', @@ -32,7 +32,10 @@ var EditorSettings = FormView.extend({ data.rooms && Rooms.deserialize(data.rooms) data.startPosition && scene.camera.move(data.startPosition) - if (! data.isNew) { + if (data.isNew) { + this.$name.val( "Room " + moment().format("DD/MM/YYYY ha") ) + } + else { // console.log(data) this.$id.val( data._id ) @@ -130,6 +133,9 @@ var EditorSettings = FormView.extend({ this.$name.val(data.name) this.action = this.updateAction + Minotaur.unwatch(this) + Minotaur.hide() + window.history.pushState(null, document.title, "/project/" + data.slug + "/edit") }, diff --git a/public/assets/javascripts/ui/editor/MediaEditor.js b/public/assets/javascripts/ui/editor/MediaEditor.js index e3a8f2e..cc924da 100644 --- a/public/assets/javascripts/ui/editor/MediaEditor.js +++ b/public/assets/javascripts/ui/editor/MediaEditor.js @@ -4,6 +4,7 @@ var MediaEditor = FormView.extend({ events: { "keydown": 'stopPropagation', + "focus [name]": "clearMinotaur", "click [data-role=play-media]": "togglePaused", "mousedown [name=keyframe]": "stopPropagation", "mousedown": "stopPropagation", diff --git a/public/assets/javascripts/ui/lib/FormView.js b/public/assets/javascripts/ui/lib/FormView.js index 219952d..ab33bc0 100644 --- a/public/assets/javascripts/ui/lib/FormView.js +++ b/public/assets/javascripts/ui/lib/FormView.js @@ -54,15 +54,20 @@ var FormView = View.extend({ return fd }, - save: function(e){ - e.preventDefault() + save: function(e, successCallback, errorCallback){ + e && e.preventDefault() this.$errors.hide().css("opacity", 0.0); if (this.validate) { var errors = this.validate() if (errors && errors.length) { - this.showErrors(errors) + if (errorCallback) { + errorCallback(errors) + } + else { + this.showErrors(errors) + } return } } @@ -74,18 +79,29 @@ var FormView = View.extend({ dataType: "json", processData: false, contentType: false, - }); + }) + request.done($.proxy(function (response) { if (response.error) { var errors = [] for (var key in response.error.errors) { errors.push(response.error.errors[key].message); } - this.showErrors(errors) + if (errorCallback) { + errorCallback(errors) + } + else { + this.showErrors(errors) + } return } else { - this.success && this.success(response) + if (successCallback) { + successCallback(response) + } + if (this.success) { + this.success(response) + } } }, this)); } diff --git a/public/assets/javascripts/ui/lib/View.js b/public/assets/javascripts/ui/lib/View.js index 999a0e5..d94e6db 100644 --- a/public/assets/javascripts/ui/lib/View.js +++ b/public/assets/javascripts/ui/lib/View.js @@ -1,13 +1,14 @@ var View = (function($, _){ var View = function(options) { - this.cid = _.uniqueId('view'); + this._id = _.uniqueId('view') + this.type = "view" options || (options = {}); - _.extend(this, _.pick(options, viewOptions)); - this._ensureElement(); - this.initialize.apply(this, arguments); - this.delegateEvents(); - }; + _.extend(this, _.pick(options, viewOptions)) + this._ensureElement() + this.initialize.apply(this, arguments) + this.delegateEvents() + } var delegateEventSplitter = /^(\S+)\s*(.*)$/; @@ -58,7 +59,7 @@ var View = (function($, _){ var match = key.match(delegateEventSplitter); var eventName = match[1], selector = match[2]; method = _.bind(method, this); - eventName += '.delegateEvents' + this.cid; + eventName += '.delegateEvents' + this._id; if (selector === '') { this.$el.on(eventName, method); } else { @@ -70,7 +71,7 @@ var View = (function($, _){ // Clears all callbacks previously bound to the view with `delegateEvents`. undelegateEvents: function() { - this.$el.off('.delegateEvents' + this.cid); + this.$el.off('.delegateEvents' + this._id); return this; }, diff --git a/views/partials/scripts.ejs b/views/partials/scripts.ejs index dfb3a83..4839de8 100644 --- a/views/partials/scripts.ejs +++ b/views/partials/scripts.ejs @@ -30,6 +30,7 @@ + -- cgit v1.2.3-70-g09d2 From 8ed5bf2ceba8e85be9c911f8b33483242e979ab7 Mon Sep 17 00:00:00 2001 From: Jules Laplace Date: Thu, 14 Aug 2014 17:45:08 -0400 Subject: fix last wrinkle in grouper --- .../javascripts/rectangles/engine/rooms/grouper.js | 73 +++++++++++++--------- .../rectangles/engine/scenery/_scenery.js | 4 +- .../rectangles/engine/scenery/types/_object.js | 4 +- .../rectangles/engine/scenery/types/image.js | 8 ++- .../rectangles/engine/scenery/types/video.js | 8 ++- .../assets/javascripts/rectangles/models/wall.js | 19 +++--- test/06-test-grouper.js | 15 ++--- test/09-test-undo.js | 2 +- 8 files changed, 79 insertions(+), 54 deletions(-) (limited to 'public/assets/javascripts/rectangles/models/wall.js') diff --git a/public/assets/javascripts/rectangles/engine/rooms/grouper.js b/public/assets/javascripts/rectangles/engine/rooms/grouper.js index 4ad3bd8..cde9fbb 100644 --- a/public/assets/javascripts/rectangles/engine/rooms/grouper.js +++ b/public/assets/javascripts/rectangles/engine/rooms/grouper.js @@ -1,6 +1,6 @@ (function(){ - var vec2, Rect, Rooms, UidGenerator, Wall, Surface, sort + var vec2, Rect, Rooms, UidGenerator, Wall, Surface, sort, _ if ('window' in this) { vec2 = window.vec2 Rect = window.Rect @@ -9,6 +9,7 @@ UidGenerator = window.UidGenerator Wall = window.Wall sort = window.sort + _ = window._ } else { Rooms = require('./_rooms') @@ -18,6 +19,7 @@ Wall = require('../../models/wall') Surface = require('../../models/surface') sort = require('../../util/sort') + _ = require('lodash') FRONT = 0x1, BACK = 0x2, LEFT = 0x4, RIGHT = 0x8, FLOOR = 0x10, CEILING = 0x20 PI = Math.PI HALF_PI = PI/2 @@ -82,6 +84,7 @@ collection.sort( useX ? sort.compare_zx : sort.compare_xz ) collection.forEach(function(mx){ if (last_mx && last_mx.rect.eq(mx.rect)) { + // culls half-walls if (last_mx.rect.id == mx.rect.id) { last_mx.height += mx.height/2 last_mx.y += mx.height/4 @@ -103,41 +106,53 @@ } base.group = function(walls, collections, side){ var collection = collections[side] - var wall var useX = side & FRONT_BACK - var useA = side & (FRONT | RIGHT) + var useA = side & (FRONT | LEFT) // collection.sort( useX ? sort.compare_zx : sort.compare_xz ) + var planes = {} + collection.forEach(function(mx){ if (mx.culled) return - var coplanar = wall && wall.edge == mx.rect[useX ? 'y': 'x'][useA ? 'a': 'b'] - - if (wall && coplanar) { - if (useX && wall.vec.b == mx.rect.x.a) { - wall.vec.b = mx.rect.x.b - wall.mx.push(mx) - wall.surface.add(mx.face) - return - } - else if (! useX && wall.vec.b == mx.rect.y.a) { - wall.vec.b = mx.rect.y.b - wall.mx.push(mx) - wall.surface.add(mx.face) - return - } - } - wall = new Wall ({ - id: base.uid(), - side: side, - mx: [ mx ], - surface: new Surface( mx.face ), - vec: mx.rect[ useX ? 'x' : 'y' ].clone(), - edge: mx.rect[ useX ? 'y' : 'x' ][ useA ? 'a' : 'b' ], - }) - walls.push(wall) + var edge = mx.rect[useX ? 'y': 'x'][ useA ? 'a': 'b'] + planes[edge] = planes[edge] || [] + planes[edge].push(mx) }) - + + var edges = _.keys(planes) + edges.forEach(function(edge){ + + var wall + + planes[edge].forEach(function(mx){ + + if (wall) { + if (useX && wall.vec.b == mx.rect.x.a) { + wall.vec.b = mx.rect.x.b + wall.mx.push(mx) + wall.surface.add(mx.face) + return + } + else if (! useX && wall.vec.b == mx.rect.y.a) { + wall.vec.b = mx.rect.y.b + wall.mx.push(mx) + wall.surface.add(mx.face) + return + } + } + wall = new Wall ({ + id: base.uid(), + side: side, + mx: [ mx ], + surface: new Surface( mx.face ), + vec: mx.rect[ useX ? 'x' : 'y' ].clone(), + edge: mx.rect[ useX ? 'y' : 'x' ][ useA ? 'a' : 'b' ], + }) + walls.push(wall) + }) + }) + return walls } diff --git a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js index c43ef14..b4a38f8 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/_scenery.js +++ b/public/assets/javascripts/rectangles/engine/scenery/_scenery.js @@ -14,7 +14,7 @@ var Scenery = new function(){ base.add = function(opt){ var scene_media - switch (media.type) { + switch (opt.media.type) { case 'image': scene_media = new Scenery.types.image (opt) break @@ -74,11 +74,11 @@ var Scenery = new function(){ scenery_data.forEach(function(data){ var wall = Rooms.walls[data.wall_id] var scene_media = base.add({ + data: data, wall: wall, media: data.media, id: data.id }) - scene_media.deserialize(data) }) } diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/_object.js b/public/assets/javascripts/rectangles/engine/scenery/types/_object.js index 46bc0e7..3a2dcc2 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/_object.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/_object.js @@ -62,8 +62,8 @@ Scenery.types.base = Fiber.extend(function(base){ set_wall: function(wall, mx){ this.wall = wall || this.wall - this.bounds = this.wall.bounds_for(this.media, this.scale) - this.center = this.wall.center() + // this.bounds = this.wall.bounds_for(this.media, this.scale) + // this.center = this.wall.center() }, set_scale: function(scale){ diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/image.js b/public/assets/javascripts/rectangles/engine/scenery/types/image.js index 99c1810..576242e 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/image.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/image.js @@ -10,7 +10,13 @@ Scenery.types.image = Scenery.types.base.extend(function(base){ this.build() this.bind() this.set_wall() - this.recenter() + + if (opt.data) { + this.deserialize(opt.data) + } + else { + this.recenter() + } }, build: function(){ diff --git a/public/assets/javascripts/rectangles/engine/scenery/types/video.js b/public/assets/javascripts/rectangles/engine/scenery/types/video.js index a8df875..0bd5c06 100644 --- a/public/assets/javascripts/rectangles/engine/scenery/types/video.js +++ b/public/assets/javascripts/rectangles/engine/scenery/types/video.js @@ -10,7 +10,13 @@ Scenery.types.video = Scenery.types.base.extend(function(base){ this.build() this.bind() this.set_wall() - this.recenter() + + if (opt.data) { + this.deserialize(opt.data) + } + else { + this.recenter() + } }, build: function(){ diff --git a/public/assets/javascripts/rectangles/models/wall.js b/public/assets/javascripts/rectangles/models/wall.js index b66d5f5..460963b 100644 --- a/public/assets/javascripts/rectangles/models/wall.js +++ b/public/assets/javascripts/rectangles/models/wall.js @@ -144,18 +144,15 @@ Wall.prototype.wallpaper = function(){ var useX = this.side & FRONT_BACK var shouldFlip = this.side & (LEFT | BACK) - this.siblings().forEach(function(w){ - w.mx.forEach(function(mx){ - - var partitionOffset = useX ? mx.x : mx.z - if (shouldFlip) partitionOffset *= -1 - partitionOffset += mx.width/2 - var floorOffset = mx.y + mx.height/2 + this.mx.forEach(function(mx){ + var partitionOffset = useX ? mx.x : mx.z + if (shouldFlip) partitionOffset *= -1 + partitionOffset += mx.width/2 + var floorOffset = mx.y + mx.height/2 - mx.el.style.backgroundImage = Scenery.nextWallpaper - mx.el.style.backgroundPosition = (~~partitionOffset) + "px " + (~~floorOffset) + "px" - }) - }) + mx.el.style.backgroundImage = Scenery.nextWallpaper + mx.el.style.backgroundPosition = (~~partitionOffset) + "px " + (~~floorOffset) + "px" + }) } Wall.prototype.outline = function(){ diff --git a/test/06-test-grouper.js b/test/06-test-grouper.js index 0f14217..184a3d7 100644 --- a/test/06-test-grouper.js +++ b/test/06-test-grouper.js @@ -194,8 +194,8 @@ describe('grouper(rect,corner,peninsula)', function(){ it("left has 3 walls", function(){ assert.equal(3, left_walls.length) }) - it("right has 4 walls", function(){ - assert.equal(4, right_walls.length) + it("right has 3 walls", function(){ + assert.equal(3, right_walls.length) }) it("front has 2 walls", function(){ assert.equal(2, front_walls.length) @@ -229,14 +229,15 @@ describe('grouper(rect,corner,peninsula_taller)', function(){ var front_walls = Rooms.grouper.group([], collections, FRONT) var back_walls = Rooms.grouper.group([], collections, BACK) var left_walls = Rooms.grouper.group([], collections, LEFT) + Rooms.grouper.debug = true var right_walls = Rooms.grouper.group([], collections, RIGHT) + Rooms.grouper.debug = false - it("left has 4 walls", function(){ - assert.equal(4, left_walls.length) + it("left has 3 walls", function(){ + assert.equal(3, left_walls.length) }) - it("right has 5 walls", function(){ - assert.equal(5, right_walls.length) - // console.log(right_walls.map(function(m){ return m.vec + " " + m.edge + " " + m.surface +"" })) + it("right has 3 walls", function(){ + assert.equal(3, right_walls.length) }) it("front has 3 walls", function(){ assert.equal(3, front_walls.length) diff --git a/test/09-test-undo.js b/test/09-test-undo.js index dbca90e..60fbbb6 100644 --- a/test/09-test-undo.js +++ b/test/09-test-undo.js @@ -1,5 +1,5 @@ var assert = require("assert") -var UndoStack = require("../public/assets/javascripts/rectangles/util/undo.js") +var UndoStack = require("../public/assets/javascripts/rectangles/util/undostack.js") UndoStack.debug = false describe('undo', function(){ -- cgit v1.2.3-70-g09d2