diff --git a/app/lib/surface/CoordinateDisplay.coffee b/app/lib/surface/CoordinateDisplay.coffee index 155f7e7ac..8d235cec9 100644 --- a/app/lib/surface/CoordinateDisplay.coffee +++ b/app/lib/surface/CoordinateDisplay.coffee @@ -11,7 +11,9 @@ module.exports = class CoordinateDisplay extends createjs.Container super() @initialize() @camera = options.camera - console.error 'CoordinateDisplay needs camera.' unless @camera + @layer = options.layer + console.error @toString(), 'needs a camera.' unless @camera + console.error @toString(), 'needs a layer.' unless @layer @build() @show = _.debounce @show, 125 Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions @@ -21,6 +23,8 @@ module.exports = class CoordinateDisplay extends createjs.Container @show = null @destroyed = true + toString: -> '<CoordinateDisplay>' + build: -> @mouseEnabled = @mouseChildren = false @addChild @background = new createjs.Shape() @@ -30,6 +34,7 @@ module.exports = class CoordinateDisplay extends createjs.Container @label.shadow = new createjs.Shadow('#000000', 1, 1, 0) @background.name = 'Coordinate Display Background' @pointMarker.name = 'Point Marker' + @layer.addChild @ onMouseOver: (e) -> @mouseInBounds = true onMouseOut: (e) -> @mouseInBounds = false diff --git a/app/lib/surface/CoordinateGrid.coffee b/app/lib/surface/CoordinateGrid.coffee new file mode 100644 index 000000000..7535ccf6d --- /dev/null +++ b/app/lib/surface/CoordinateGrid.coffee @@ -0,0 +1,102 @@ +CocoClass = require 'lib/CocoClass' + +module.exports = class CoordinateGrid extends CocoClass + subscriptions: + 'level-toggle-grid': 'onToggleGrid' + 'level-set-grid': 'onSetGrid' + + shortcuts: + 'ctrl+g, ⌘+g': 'onToggleGrid' + + constructor: (options, worldSize) -> + super() + options ?= {} + @camera = options.camera + @layer = options.layer + @textLayer = options.textLayer + console.error @toString(), 'needs a camera.' unless @camera + console.error @toString(), 'needs a layer.' unless @layer + console.error @toString(), 'needs a textLayer.' unless @textLayer + @build worldSize + + destroy: -> + super() + + toString: -> '<CoordinateGrid>' + + build: (worldSize) -> + worldWidth = worldSize[0] ? 80 + worldHeight = worldSize[1] ? 68 + @gridContainer = new createjs.Container() + @gridShape = new createjs.Shape() + @gridContainer.addChild @gridShape + @gridContainer.mouseEnabled = false + @gridShape.alpha = 0.125 + @gridShape.graphics.setStrokeStyle 1 + @gridShape.graphics.beginStroke 'blue' + gridSize = Math.round(worldWidth / 20) + wopStart = x: 0, y: 0 + wopEnd = x: worldWidth, y: worldHeight + supStart = @camera.worldToSurface wopStart + supEnd = @camera.worldToSurface wopEnd + wop = x: wopStart.x, y: wopStart.y + @labels = [] + linesDrawn = 0 + while wop.x <= wopEnd.x + sup = @camera.worldToSurface wop + @gridShape.graphics.mt(sup.x, supStart.y).lt(sup.x, supEnd.y) + if ++linesDrawn % 2 + t = new createjs.Text(wop.x.toFixed(0), '16px Arial', 'blue') + t.textAlign = 'center' + t.textBaseline = 'bottom' + t.x = sup.x + t.y = supStart.y + t.alpha = 0.75 + @labels.push t + wop.x += gridSize + if wopEnd.x < wop.x <= wopEnd.x - gridSize / 2 + wop.x = wopEnd.x + linesDrawn = 0 + while wop.y <= wopEnd.y + sup = @camera.worldToSurface wop + @gridShape.graphics.mt(supStart.x, sup.y).lt(supEnd.x, sup.y) + if ++linesDrawn % 2 + t = new createjs.Text(wop.y.toFixed(0), '16px Arial', 'blue') + t.textAlign = 'left' + t.textBaseline = 'middle' + t.x = 0 + t.y = sup.y + t.alpha = 0.75 + @labels.push t + wop.y += gridSize + console.log wop.y, wopEnd.y, gridSize + if wopEnd.y < wop.y <= wopEnd.y - gridSize / 2 + wop.y = wopEnd.y + @gridShape.graphics.endStroke() + bounds = x: supStart.x, y: supEnd.y, width: supEnd.x - supStart.x, height: supStart.y - supEnd.y + return unless bounds?.width and bounds.height + @gridContainer.cache bounds.x, bounds.y, bounds.width, bounds.height + + showGrid: -> + return if @gridShowing() + @layer.addChild @gridContainer + @textLayer.addChild label for label in @labels + + hideGrid: -> + return unless @gridShowing() + @layer.removeChild @gridContainer + @textLayer.removeChild label for label in @labels + + gridShowing: -> + @gridContainer?.parent? + + onToggleGrid: (e) -> + # TODO: figure out a better way of managing grid / debug so it's not split across PlaybackView and Surface + e?.preventDefault?() + if @gridShowing() then @hideGrid() else @showGrid() + flag = $('#grid-toggle i.icon-ok') + flag.toggleClass 'invisible', not @gridShowing() + + onSetGrid: (e) -> + if e.grid then @showGrid() else @hideGrid() + diff --git a/app/lib/surface/Surface.coffee b/app/lib/surface/Surface.coffee index 013c6801f..9ba6ab0b6 100644 --- a/app/lib/surface/Surface.coffee +++ b/app/lib/surface/Surface.coffee @@ -12,6 +12,7 @@ CountdownScreen = require './CountdownScreen' PlaybackOverScreen = require './PlaybackOverScreen' DebugDisplay = require './DebugDisplay' CoordinateDisplay = require './CoordinateDisplay' +CoordinateGrid = require './CoordinateGrid' SpriteBoss = require './SpriteBoss' PointChooser = require './PointChooser' RegionChooser = require './RegionChooser' @@ -24,7 +25,7 @@ module.exports = Surface = class Surface extends CocoClass surfaceLayer: null surfaceTextLayer: null screenLayer: null - gridLayer: null # TODO: maybe + gridLayer: null spriteBoss: null @@ -56,8 +57,6 @@ module.exports = Surface = class Surface extends CocoClass 'level-set-playing': 'onSetPlaying' 'level-set-debug': 'onSetDebug' 'level-toggle-debug': 'onToggleDebug' - 'level-set-grid': 'onSetGrid' - 'level-toggle-grid': 'onToggleGrid' 'level-toggle-pathfinding': 'onTogglePathFinding' 'level-set-time': 'onSetTime' 'level-set-surface-camera': 'onSetCamera' @@ -75,7 +74,6 @@ module.exports = Surface = class Surface extends CocoClass shortcuts: 'ctrl+\\, ⌘+\\': 'onToggleDebug' - 'ctrl+g, ⌘+g': 'onToggleGrid' 'ctrl+o, ⌘+o': 'onTogglePathFinding' # external functions @@ -103,6 +101,8 @@ module.exports = Surface = class Surface extends CocoClass @dimmer?.destroy() @countdownScreen?.destroy() @playbackOverScreen?.destroy() + @coordinateDisplay?.destroy() + @coordinateGrid?.destroy() @stage.clear() @musicPlayer?.destroy() @stage.removeAllChildren() @@ -126,10 +126,6 @@ module.exports = Surface = class Surface extends CocoClass @showLevel() @updateState true if @loaded - # TODO: synchronize both ways of choosing whether to show coords (@world via UI System or @options via World Select modal) - if @world.showCoordinates and @options.coords and not @coordinateDisplay - @coordinateDisplay = new CoordinateDisplay camera: @camera - @surfaceTextLayer.addChild @coordinateDisplay @onFrameChanged() Backbone.Mediator.publish 'surface:world-set-up' @@ -364,6 +360,9 @@ module.exports = Surface = class Surface extends CocoClass onNewWorld: (event) -> return unless event.world.name is @world.name + @onStreamingWorldUpdated event + + onStreamingWorldUpdated: (event) -> @casting = false @spriteBoss.play() @@ -390,22 +389,21 @@ module.exports = Surface = class Surface extends CocoClass # initialization initEasel: -> - # takes DOM objects, not jQuery objects - @stage = new createjs.Stage(@canvas[0]) + @stage = new createjs.Stage(@canvas[0]) # Takes DOM objects, not jQuery objects. canvasWidth = parseInt @canvas.attr('width'), 10 canvasHeight = parseInt @canvas.attr('height'), 10 - @camera?.destroy() - @camera = new Camera @canvas - AudioPlayer.camera = @camera + @camera = AudioPlayer.camera = new Camera @canvas @layers.push @surfaceLayer = new Layer name: 'Surface', layerPriority: 0, transform: Layer.TRANSFORM_SURFACE, camera: @camera @layers.push @surfaceTextLayer = new Layer name: 'Surface Text', layerPriority: 1, transform: Layer.TRANSFORM_SURFACE_TEXT, camera: @camera - @layers.push @screenLayer = new Layer name: 'Screen', layerPriority: 2, transform: Layer.TRANSFORM_SCREEN, camera: @camera + @layers.push @gridLayer = new Layer name: 'Grid', layerPriority: 2, transform: Layer.TRANSFORM_SURFACE, camera: @camera + @layers.push @screenLayer = new Layer name: 'Screen', layerPriority: 3, transform: Layer.TRANSFORM_SCREEN, camera: @camera @stage.addChild @layers... @surfaceLayer.addChild @cameraBorder = new CameraBorder bounds: @camera.bounds @screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight @spriteBoss = new SpriteBoss camera: @camera, surfaceLayer: @surfaceLayer, surfaceTextLayer: @surfaceTextLayer, world: @world, thangTypes: @options.thangTypes, choosing: @options.choosing, navigateToSelection: @options.navigateToSelection, showInvisible: @options.showInvisible - @countdownScreen ?= new CountdownScreen camera: @camera, layer: @screenLayer - @playbackOverScreen ?= new PlaybackOverScreen camera: @camera, layer: @screenLayer + @countdownScreen = new CountdownScreen camera: @camera, layer: @screenLayer + @playbackOverScreen = new PlaybackOverScreen camera: @camera, layer: @screenLayer + @initCoordinates() @stage.enableMouseOver(10) @stage.addEventListener 'stagemousemove', @onMouseMove @stage.addEventListener 'stagemousedown', @onMouseDown @@ -416,6 +414,11 @@ module.exports = Surface = class Surface extends CocoClass createjs.Ticker.setFPS @options.frameRate @onResize() + initCoordinates: -> + @coordinateGrid ?= new CoordinateGrid {camera: @camera, layer: @gridLayer, textLayer: @surfaceTextLayer}, @world.size() + @coordinateGrid.showGrid() if @world.showGrid or @options.grid + @coordinateDisplay ?= new CoordinateDisplay camera: @camera, layer: @surfaceTextLayer if @world.showCoordinates or @options.coords + onResize: (e) => return if @destroyed oldWidth = parseInt @canvas.attr('width'), 10 @@ -450,7 +453,6 @@ module.exports = Surface = class Surface extends CocoClass Backbone.Mediator.publish 'registrar-echo-states' @updateState true @drawCurrentFrame() - @showGrid() if @options.grid # TODO: pay attention to world grid setting (which we only know when world simulates) createjs.Ticker.addEventListener 'tick', @tick Backbone.Mediator.publish 'level:started' @@ -460,67 +462,6 @@ module.exports = Surface = class Surface extends CocoClass initAudio: -> @musicPlayer = new MusicPlayer() - # grid; should probably refactor into separate class - - showGrid: -> - return if @gridShowing() - unless @gridLayer - @gridLayer = new createjs.Container() - @gridShape = new createjs.Shape() - @gridLayer.addChild @gridShape - @gridLayer.z = 90019001 - @gridLayer.mouseEnabled = false - @gridShape.alpha = 0.125 - @gridShape.graphics.beginStroke 'blue' - gridSize = Math.round(@world.size()[0] / 20) - unless gridSize > 0.1 - return console.error 'Grid size is', gridSize, 'so we can\'t draw a grid.' - wopStart = x: 0, y: 0 - wopEnd = x: @world.size()[0], y: @world.size()[1] - supStart = @camera.worldToSurface wopStart - supEnd = @camera.worldToSurface wopEnd - wop = x: wopStart.x, y: wopStart.y - while wop.x < wopEnd.x - sup = @camera.worldToSurface wop - @gridShape.graphics.mt(sup.x, supStart.y).lt(sup.x, supEnd.y) - t = new createjs.Text(wop.x.toFixed(0), '16px Arial', 'blue') - t.x = sup.x - t.getMeasuredWidth() / 2 - t.y = supStart.y - 10 - t.getMeasuredHeight() / 2 - t.alpha = 0.75 - @gridLayer.addChild t - wop.x += gridSize - while wop.y < wopEnd.y - sup = @camera.worldToSurface wop - @gridShape.graphics.mt(supStart.x, sup.y).lt(supEnd.x, sup.y) - t = new createjs.Text(wop.y.toFixed(0), '16px Arial', 'blue') - t.x = 10 - t.getMeasuredWidth() / 2 - t.y = sup.y - t.getMeasuredHeight() / 2 - t.alpha = 0.75 - @gridLayer.addChild t - wop.y += gridSize - @gridShape.graphics.endStroke() - bounds = @gridLayer.getBounds() - return unless bounds?.width and bounds.height - @gridLayer.cache bounds.x, bounds.y, bounds.width, bounds.height - @surfaceLayer.addChild @gridLayer - - hideGrid: -> - return unless @gridShowing() - @gridLayer.parent.removeChild @gridLayer - - gridShowing: -> - @gridLayer?.parent? - - onToggleGrid: (e) -> - # TODO: figure out a better way of managing grid / debug so it's not split across PlaybackView and Surface - e?.preventDefault?() - if @gridShowing() then @hideGrid() else @showGrid() - flag = $('#grid-toggle i.icon-ok') - flag.toggleClass 'invisible', not @gridShowing() - - onSetGrid: (e) -> - if e.grid then @showGrid() else @hideGrid() - onToggleDebug: (e) -> e?.preventDefault?() Backbone.Mediator.publish 'level-set-debug', {debug: not @debug} diff --git a/app/locale/en.coffee b/app/locale/en.coffee index ee033e20d..fc7fe48b5 100644 --- a/app/locale/en.coffee +++ b/app/locale/en.coffee @@ -355,7 +355,6 @@ play_level: done: "Done" - grid: "Grid" customize_wizard: "Customize Wizard" home: "Home" stop: "Stop" diff --git a/app/templates/play/level/playback.jade b/app/templates/play/level/playback.jade index afcbd8276..f0c83859b 100644 --- a/app/templates/play/level/playback.jade +++ b/app/templates/play/level/playback.jade @@ -37,10 +37,6 @@ button.btn.btn-xs.btn-inverse#music-button(title="Toggle Music") li.selectable#view-keyboard-shortcuts i.icon-info-sign span(data-i18n="play_level.keyboard_shortcuts") Key Shortcuts - li(title="Ctrl/Cmd + G: Toggle grid display").selectable#grid-toggle - i.icon-th - span(data-i18n="play_level.grid") Grid - i.icon-ok.secret.invisible li.selectable#edit-wizard-settings i.icon-user span(data-i18n="play_level.customize_wizard") Customize Wizard diff --git a/app/views/play/level/LevelPlaybackView.coffee b/app/views/play/level/LevelPlaybackView.coffee index b783d3db4..deddab970 100644 --- a/app/views/play/level/LevelPlaybackView.coffee +++ b/app/views/play/level/LevelPlaybackView.coffee @@ -18,8 +18,6 @@ module.exports = class LevelPlaybackView extends CocoView 'level-scrub-back': 'onScrubBack' 'level-set-volume': 'onSetVolume' 'level-set-debug': 'onSetDebug' - 'level-set-grid': 'onSetGrid' - 'level-toggle-grid': 'onToggleGrid' 'surface:frame-changed': 'onFrameChanged' 'god:new-world-created': 'onNewWorld' 'god:streaming-world-updated': 'onNewWorld' @@ -30,7 +28,6 @@ module.exports = class LevelPlaybackView extends CocoView events: 'click #debug-toggle': 'onToggleDebug' - 'click #grid-toggle': 'onToggleGrid' 'click #edit-wizard-settings': 'onEditWizardSettings' 'click #edit-editor-config': 'onEditEditorConfig' 'click #view-keyboard-shortcuts': 'onViewKeyboardShortcuts' @@ -188,11 +185,6 @@ module.exports = class LevelPlaybackView extends CocoView flag = $('#debug-toggle i.icon-ok') Backbone.Mediator.publish('level-set-debug', {debug: flag.hasClass('invisible')}) - onToggleGrid: -> - return if @shouldIgnore() - flag = $('#grid-toggle i.icon-ok') - Backbone.Mediator.publish('level-set-grid', {grid: flag.hasClass('invisible')}) - onEditWizardSettings: -> Backbone.Mediator.publish 'edit-wizard-settings' @@ -316,10 +308,6 @@ module.exports = class LevelPlaybackView extends CocoView flag = $('#debug-toggle i.icon-ok') flag.toggleClass 'invisible', not e.debug - onSetGrid: (e) -> - flag = $('#grid-toggle i.icon-ok') - flag.toggleClass 'invisible', not e.grid - # to refactor hookUpScrubber: ->