CocoClass = require 'core/CocoClass' module.exports = class Dimmer extends CocoClass subscriptions: 'level:disable-controls': 'onDisableControls' 'level:enable-controls': 'onEnableControls' 'sprite:highlight-sprites': 'onHighlightSprites' 'sprite:speech-updated': 'onSpriteSpeechUpdated' 'surface:frame-changed': 'onFrameChanged' 'camera:zoom-updated': 'onZoomUpdated' constructor: (options) -> super() options ?= {} @camera = options.camera @layer = options.layer console.error @toString(), 'needs a camera.' unless @camera console.error @toString(), 'needs a layer.' unless @layer @build() @updateDimMask = _.throttle @updateDimMask, 10 @highlightedThangIDs = [] @sprites = {} toString: -> '' build: -> @dimLayer = new createjs.Container() @dimLayer.mouseEnabled = @dimLayer.mouseChildren = false @dimLayer.addChild @dimScreen = 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 @dimMask.compositeOperation = 'destination-out' @dimLayer.cache 0, 0, @camera.canvasWidth, @camera.canvasHeight onDisableControls: (e) -> return if @on or (e.controls and not ('surface' in e.controls)) @dim() onEnableControls: (e) -> return if not @on or (e.controls and not ('surface' in e.controls)) @undim() onSpriteSpeechUpdated: (e) -> @updateDimMask() if @on onFrameChanged: (e) -> @updateDimMask() if @on onZoomUpdated: (e) -> @updateDimMask() if @on onHighlightSprites: (e) -> @highlightedThangIDs = e.thangIDs ? [] @updateDimMask() if @on setSprites: (@sprites) -> dim: -> @on = true @layer.addChild @dimLayer @layer.updateLayerOrder() sprite.setDimmed true for thangID, sprite of @sprites @updateDimMask() undim: -> @on = false @layer.removeChild @dimLayer sprite.setDimmed false for thangID, sprite of @sprites updateDimMask: => @dimMask.graphics.clear() for thangID, sprite of @sprites continue unless (thangID in @highlightedThangIDs) or sprite.isTalking?() sup = x: sprite.sprite.x, y: sprite.sprite.y cap = @camera.surfaceToCanvas sup r = 50 * @camera.zoom # TODO: find better way to get the radius based on the sprite's size @dimMask.graphics.beginRadialGradientFill(['rgba(0,0,0,1)', 'rgba(0,0,0,0)'], [0.5, 1], cap.x, cap.y, 0, cap.x, cap.y, r).drawCircle(cap.x, cap.y, r) @dimLayer.updateCache 0, 0, @camera.canvasWidth, @camera.canvasHeight