Merge branch 'master' into production

This commit is contained in:
Nick Winter 2014-08-28 17:08:22 -07:00
commit 7d5bcc6365
14 changed files with 73 additions and 61 deletions

View file

@ -53,6 +53,7 @@ module.exports = class CoordinateDisplay extends createjs.Container
wop = @camera.screenToWorld x: e.x, y: e.y wop = @camera.screenToWorld x: e.x, y: e.y
wop.x = Math.round wop.x wop.x = Math.round wop.x
wop.y = Math.round wop.y wop.y = Math.round wop.y
Backbone.Mediator.publish 'tome:focus-editor', {}
Backbone.Mediator.publish 'surface:coordinate-selected', wop Backbone.Mediator.publish 'surface:coordinate-selected', wop
onZoomUpdated: (e) -> onZoomUpdated: (e) ->

View file

@ -26,7 +26,6 @@ module.exports = class Dimmer extends CocoClass
build: -> build: ->
@dimLayer = new createjs.Container() @dimLayer = new createjs.Container()
@dimLayer.mouseEnabled = @dimLayer.mouseChildren = false @dimLayer.mouseEnabled = @dimLayer.mouseChildren = false
@dimLayer.layerIndex = -10
@dimLayer.addChild @dimScreen = new createjs.Shape() @dimLayer.addChild @dimScreen = new createjs.Shape()
@dimLayer.addChild @dimMask = new createjs.Shape() @dimLayer.addChild @dimMask = new createjs.Shape()
@dimScreen.graphics.beginFill('rgba(0,0,0,0.5)').rect 0, 0, @camera.canvasWidth, @camera.canvasHeight @dimScreen.graphics.beginFill('rgba(0,0,0,0.5)').rect 0, 0, @camera.canvasWidth, @camera.canvasHeight

View file

@ -45,6 +45,13 @@ module.exports = class Mark extends CocoClass
@mark.visible = true @mark.visible = true
@ @
setLayer: (layer) ->
return if layer is @layer
wasOn = @on
@toggle false
@layer = layer
@toggle true if wasOn
setSprite: (sprite) -> setSprite: (sprite) ->
return if sprite is @sprite return if sprite is @sprite
@sprite = sprite @sprite = sprite
@ -131,7 +138,6 @@ module.exports = class Mark extends CocoClass
@mark.graphics.endFill() @mark.graphics.endFill()
@mark.regX = width / 2 @mark.regX = width / 2
@mark.regY = height / 2 @mark.regY = height / 2
@mark.layerIndex = 10
@mark.cache -1, -1, width + 2, height + 2 # not actually faster than simple ellipse draw @mark.cache -1, -1, width + 2, height + 2 # not actually faster than simple ellipse draw
buildRadius: (range) -> buildRadius: (range) ->

View file

@ -15,7 +15,6 @@ module.exports = class PlaybackOverScreen extends CocoClass
build: -> build: ->
@dimLayer = new createjs.Container() @dimLayer = new createjs.Container()
@dimLayer.mouseEnabled = @dimLayer.mouseChildren = false @dimLayer.mouseEnabled = @dimLayer.mouseChildren = false
@dimLayer.layerIndex = -12
@dimLayer.addChild @dimScreen = new createjs.Shape() @dimLayer.addChild @dimScreen = new createjs.Shape()
@dimScreen.graphics.beginFill('rgba(0,0,0,0.4)').rect 0, 0, @camera.canvasWidth, @camera.canvasHeight @dimScreen.graphics.beginFill('rgba(0,0,0,0.4)').rect 0, 0, @camera.canvasWidth, @camera.canvasHeight
@dimLayer.cache 0, 0, @camera.canvasWidth, @camera.canvasHeight @dimLayer.cache 0, 0, @camera.canvasWidth, @camera.canvasHeight

View file

@ -21,7 +21,6 @@ module.exports = class PointChooser extends CocoClass
@shape.mouseEnabled = false @shape.mouseEnabled = false
@shape.graphics.setStrokeStyle(1, 'round').beginStroke('#000000').beginFill('#fedcba') @shape.graphics.setStrokeStyle(1, 'round').beginStroke('#000000').beginFill('#fedcba')
@shape.graphics.drawCircle(0, 0, 4).endFill() @shape.graphics.drawCircle(0, 0, 4).endFill()
@shape.layerIndex = 100
onMouseDown: (e) => onMouseDown: (e) =>
return unless key.shift return unless key.shift

View file

@ -373,6 +373,11 @@ module.exports = class SpriteBoss extends CocoClass
@updateTarget() @updateTarget()
return unless @selectionMark return unless @selectionMark
@selectedSprite = null if @selectedSprite and (@selectedSprite.destroyed or not @selectedSprite.thang) @selectedSprite = null if @selectedSprite and (@selectedSprite.destroyed or not @selectedSprite.thang)
# The selection mark should be on the ground layer, unless we're not a normal sprite (like a wall), in which case we'll place it higher so we can see it.
if @selectedSprite and @selectedSprite.imageObject.parent isnt @spriteLayers.Default
@selectionMark.setLayer @spriteLayers.Default
else if @selectedSprite
@selectionMark.setLayer @spriteLayers.Ground
@selectionMark.toggle @selectedSprite? @selectionMark.toggle @selectedSprite?
@selectionMark.setSprite @selectedSprite @selectionMark.setSprite @selectedSprite
@selectionMark.update() @selectionMark.update()

View file

@ -483,11 +483,13 @@ module.exports = Surface = class Surface extends CocoClass
worldPos = @camera.screenToWorld x: e.stageX, y: e.stageY worldPos = @camera.screenToWorld x: e.stageX, y: e.stageY
event = onBackground: onBackground, x: e.stageX, y: e.stageY, originalEvent: e, worldPos: worldPos event = onBackground: onBackground, x: e.stageX, y: e.stageY, originalEvent: e, worldPos: worldPos
Backbone.Mediator.publish 'surface:stage-mouse-down', event Backbone.Mediator.publish 'surface:stage-mouse-down', event
Backbone.Mediator.publish 'tome:focus-editor', {}
onMouseUp: (e) => onMouseUp: (e) =>
return if @disabled return if @disabled
onBackground = not @stage.hitTest e.stageX, e.stageY onBackground = not @stage.hitTest e.stageX, e.stageY
Backbone.Mediator.publish 'surface:stage-mouse-up', onBackground: onBackground, x: e.stageX, y: e.stageY, originalEvent: e Backbone.Mediator.publish 'surface:stage-mouse-up', onBackground: onBackground, x: e.stageX, y: e.stageY, originalEvent: e
Backbone.Mediator.publish 'tome:focus-editor', {}
onMouseWheel: (e) => onMouseWheel: (e) =>
# https://github.com/brandonaaron/jquery-mousewheel # https://github.com/brandonaaron/jquery-mousewheel

View file

@ -92,60 +92,58 @@ module.exports.consolidateThangs = consolidateThangs = (thangs) ->
padding = 0 padding = 0
console.log 'got max width', width, 'height', height, 'left', left, 'bottom', bottom, 'of thangs', thangs.length, 'structural', structural.length if debug console.log 'got max width', width, 'height', height, 'left', left, 'bottom', bottom, 'of thangs', thangs.length, 'structural', structural.length if debug
grid = new Grid structural, width, height, padding, left, bottom grid = new Grid structural, width, height, padding, left, bottom
console.log grid.toString() if debug
# Approach: start at bottom left. Go right, then up. At each occupied grid square, find the largest rectangle we can make starting at that corner, add a corresponding Thang to the grid, and unmark all occupied grid squares.
# Since it's not like we're going to do any of these:
# http://stackoverflow.com/questions/5919298/algorithm-for-finding-the-fewest-rectangles-to-cover-a-set-of-rectangles
# http://stackoverflow.com/questions/4701887/find-the-set-of-largest-contiguous-rectangles-to-cover-multiple-areas
dissection = [] dissection = []
for y in grid.columns bottom, height addStructuralThang = (rect) ->
for x in grid.rows left, width thang = structural[dissection.length] # Grab one we already know is configured properly.
continue unless grid.grid[y][x].length console.error 'Hmm, our dissection has more Thangs than the original structural Thangs?', dissection.length unless thang
rect = largestRectangle grid, y, x, false, debug thang.pos.x = rect.x
vertices = rect.vertices() thang.pos.y = rect.y
for y2 in [vertices[0].y ... vertices[1].y] # maybe ..? thang.width = rect.width
for x2 in [vertices[0].x ... vertices[2].x] # maybe ..? thang.height = rect.height
grid.grid[y2][x2] = [] thang.createBodyDef()
console.log grid.toString() if debug dissection.push thang
thang = structural[dissection.length] # grab one we already know is configured properly
console.error 'Hmm, our dissection has more Thangs than the original structural Thangs?', dissection.length unless thang dissectRectangles grid, addStructuralThang, false, debug
thang.width = rect.width
thang.height = rect.height # Now add the new structural thangs back to thangs and return the ones not in the dissection.
thang.pos.x = rect.x
thang.pos.y = rect.y
thang.createBodyDef()
dissection.push thang
console.log 'Turned', structural.length, 'structural Thangs into', dissection.length, 'dissecting Thangs.' console.log 'Turned', structural.length, 'structural Thangs into', dissection.length, 'dissecting Thangs.'
thangs.push dissection... thangs.push dissection...
structural[dissection.length ... structural.length] structural[dissection.length ... structural.length]
module.exports.largestRectangle = largestRectangle = (grid, bottomY, leftX, wantEmpty, debug) ->
# If wantEmpty, then we try to cover empty rectangles. module.exports.dissectRectangles = dissectRectangles = (grid, rectangleCallback, wantEmpty, debug) ->
# Otherwise, we try to cover occupied rectangles. # Mark Maxham's fast sweeper approach: https://github.com/codecombat/codecombat/issues/1090
coveredRows = [] console.log grid.toString() if debug
shortestCoveredRow = grid.width - leftX for x in grid.rows grid.left, grid.left + grid.width
for y in grid.columns bottomY, grid.height y = grid.clampColumn grid.bottom
coveredRow = 0 while y < grid.clampColumn grid.bottom + grid.height
for x in grid.rows leftX, leftX + shortestCoveredRow y2 = y # Note our current y.
if Boolean(grid.grid[y][x].length) isnt wantEmpty ++y2 until occ x, y2, grid, wantEmpty # Sweep through y to expand 1xN rect.
++coveredRow if y2 > y # If we get a hit, sweep X with that swath.
else x2 = x + 1
break ++x2 until occCol x2, y, y2, grid, wantEmpty
break unless coveredRow w = x2 - x
coveredRows.push coveredRow h = y2 - y
shortestCoveredRow = Math.min(shortestCoveredRow, coveredRow) rect = addRect grid, x, y, w, h, wantEmpty
console.log 'largestRectangle() for', bottomY, leftX, 'got coveredRows', coveredRows if debug rectangleCallback rect
[maxArea, maxAreaRows, maxAreaRowLength, shortestRow] = [0, 0, 0, 0] console.log grid.toString() if debug
for rowLength, rowIndex in coveredRows y = y2
shortestRow ||= rowLength ++y
area = rowLength * (rowIndex + 1)
if area > maxArea occ = (x, y, grid, wantEmpty) ->
maxAreaRows = rowIndex + 1 return true if y > grid.bottom + grid.height or x > grid.left + grid.width
maxAreaRowLength = shortestRow console.error 'trying to check invalid coordinates', x, y, 'from grid', grid.bottom, grid.left, grid.width, grid.height unless grid.grid[y]?[x]
maxArea = area Boolean(grid.grid[y][x].length) is wantEmpty
shortestRow = Math.min(rowLength, shortestRow)
console.log 'So largest rect has area', maxArea, 'with', maxAreaRows, 'rows of length', maxAreaRowLength if debug occCol = (x, y1, y2, grid, wantEmpty) ->
rect = new Rectangle leftX + maxAreaRowLength / 2, bottomY + maxAreaRows / 2, maxAreaRowLength, maxAreaRows for j in [y1 ... y2]
console.log 'That corresponds to a rectangle', rect.toString() if debug if occ(x, j, grid, wantEmpty)
rect return true
false
addRect = (grid, leftX, bottomY, width, height, wantEmpty) ->
for x in [leftX ... leftX + width]
for y in [bottomY ... bottomY + height]
grid.grid[y][x] = if wantEmpty then [true] else []
new Rectangle leftX + width / 2, bottomY + height / 2, width, height

View file

@ -23,5 +23,5 @@ module.exports =
bus: {$ref: 'bus'} bus: {$ref: 'bus'}
'bus:player-states-changed': c.object {title: 'Player state changes', description: 'State of the players has changed'}, 'bus:player-states-changed': c.object {title: 'Player state changes', description: 'State of the players has changed'},
states: c.array {}, {type: 'object'} states: {type: 'object', additionalProperties: {type: 'object'}}
bus: {$ref: 'bus'} bus: {$ref: 'bus'}

View file

@ -66,6 +66,7 @@ module.exports = # /app/lib/surface
'surface:coordinate-selected': c.object {required: ['x', 'y']}, 'surface:coordinate-selected': c.object {required: ['x', 'y']},
x: {type: 'number'} x: {type: 'number'}
y: {type: 'number'} y: {type: 'number'}
z: {type: 'number'}
'surface:coordinates-shown': c.object {} 'surface:coordinates-shown': c.object {}
@ -76,12 +77,14 @@ module.exports = # /app/lib/surface
point: c.object {required: ['x', 'y']}, point: c.object {required: ['x', 'y']},
x: {type: 'number'} x: {type: 'number'}
y: {type: 'number'} y: {type: 'number'}
z: {type: 'number'}
'surface:choose-region': c.object {required: ['points']}, 'surface:choose-region': c.object {required: ['points']},
points: c.array {minItems: 2, maxItems: 2}, points: c.array {minItems: 2, maxItems: 2},
c.object {required: ['x', 'y']}, c.object {required: ['x', 'y']},
x: {type: 'number'} x: {type: 'number'}
y: {type: 'number'} y: {type: 'number'}
z: {type: 'number'}
'surface:new-thang-added': c.object {required: ['thang', 'sprite']}, 'surface:new-thang-added': c.object {required: ['thang', 'sprite']},
thang: {type: 'object'} thang: {type: 'object'}

View file

@ -6,7 +6,7 @@ module.exports = class LevelSearchView extends SearchView
model: require 'models/Level' model: require 'models/Level'
modelURL: '/db/level' modelURL: '/db/level'
tableTemplate: require 'templates/editor/level/table' tableTemplate: require 'templates/editor/level/table'
page: 'editor' page: 'level'
getRenderData: -> getRenderData: ->
context = super() context = super()

View file

@ -50,10 +50,11 @@ module.exports = class WizardSettingsModal extends ModalView
res.error => res.error =>
errors = JSON.parse(res.responseText) errors = JSON.parse(res.responseText)
console.warn 'Got errors saving user:', errors console.warn 'Got errors saving user:', errors
return if @destroyed
forms.applyErrorsToForm(@$el, errors) forms.applyErrorsToForm(@$el, errors)
@disableModalInProgress(@$el) @disableModalInProgress(@$el)
res.success (model, response, options) => res.success (model, response, options) =>
@hide() @hide() unless @destroyed
@enableModalInProgress(@$el) @enableModalInProgress(@$el)

View file

@ -221,7 +221,6 @@ module.exports = class SpectateLevelView extends RootView
else else
console.log 'World scripts don\'t exist!' console.log 'World scripts don\'t exist!'
nonVictoryPlaybackScripts = [] nonVictoryPlaybackScripts = []
console.log nonVictoryPlaybackScripts
@scriptManager = new ScriptManager({scripts: nonVictoryPlaybackScripts, view:@, session: @session}) @scriptManager = new ScriptManager({scripts: nonVictoryPlaybackScripts, view:@, session: @session})
@scriptManager.loadFromSession() @scriptManager.loadFromSession()

View file

@ -234,7 +234,7 @@ module.exports = class LevelPlaybackView extends CocoView
button.addClass(classes[2]) if e.volume >= 1.0 button.addClass(classes[2]) if e.volume >= 1.0
onScrub: (e, options) -> onScrub: (e, options) ->
e?.preventDefault() e?.preventDefault?()
options.scrubDuration = 500 options.scrubDuration = 500
Backbone.Mediator.publish('level:set-time', options) Backbone.Mediator.publish('level:set-time', options)
@ -347,7 +347,7 @@ module.exports = class LevelPlaybackView extends CocoView
shouldIgnore: -> return @disabled or @realTime shouldIgnore: -> return @disabled or @realTime
onTogglePlay: (e) -> onTogglePlay: (e) ->
e?.preventDefault() e?.preventDefault?()
return if @shouldIgnore() return if @shouldIgnore()
button = $('#play-button') button = $('#play-button')
willPlay = button.hasClass('paused') or button.hasClass('ended') willPlay = button.hasClass('paused') or button.hasClass('ended')