SpriteBuilder = require('./SpriteBuilder') ThangType = require('models/ThangType') CocoClass = require('core/CocoClass') class SpriteExporter extends CocoClass ''' To be used by the ThangTypeEditView to export ThangTypes to single sprite sheets which can be uploaded to GridFS and used in gameplay, avoiding rendering vector images. Code has been copied and reworked and simplified from LayerAdapter. Some shared code has been refactored into ThangType, but more work could be done to rethink and reorganize Sprite rendering. ''' constructor: (thangType, options) -> @thangType = thangType options ?= {} @colorConfig = options.colorConfig or {} @resolutionFactor = options.resolutionFactor or 1 @actionNames = options.actionNames or (action.name for action in @thangType.getDefaultActions()) super() build: (renderType) -> spriteSheetBuilder = new createjs.SpriteSheetBuilder() if (renderType or @thangType.get('spriteType') or 'segmented') is 'segmented' @renderSegmentedThangType(spriteSheetBuilder) else @renderSingularThangType(spriteSheetBuilder) try spriteSheetBuilder.buildAsync() catch e @resolutionFactor *= 0.9 return @build() spriteSheetBuilder.on 'complete', @onBuildSpriteSheetComplete, @, true, spriteSheetBuilder @asyncBuilder = spriteSheetBuilder renderSegmentedThangType: (spriteSheetBuilder) -> containersToRender = @thangType.getContainersForActions(@actionNames) spriteBuilder = new SpriteBuilder(@thangType, {colorConfig: @colorConfig}) for containerGlobalName in containersToRender container = spriteBuilder.buildContainerFromStore(containerGlobalName) frame = spriteSheetBuilder.addFrame(container, null, @resolutionFactor * (@thangType.get('scale') or 1)) spriteSheetBuilder.addAnimation(containerGlobalName, [frame], false) renderSingularThangType: (spriteSheetBuilder) -> actionObjects = _.values(@thangType.getActions()) animationActions = [] for a in actionObjects continue unless a.animation continue unless a.name in @actionNames animationActions.push(a) spriteBuilder = new SpriteBuilder(@thangType, {colorConfig: @colorConfig}) animationGroups = _.groupBy animationActions, (action) -> action.animation for animationName, actions of animationGroups scale = actions[0].scale or @thangType.get('scale') or 1 mc = spriteBuilder.buildMovieClip(animationName, null, null, null, {'temp':0}) spriteSheetBuilder.addMovieClip(mc, null, scale * @resolutionFactor) frames = spriteSheetBuilder._animations['temp'].frames framesMap = _.zipObject _.range(frames.length), frames for action in actions if action.frames frames = (framesMap[parseInt(frame)] for frame in action.frames.split(',')) else frames = _.sortBy(_.values(framesMap)) next = @nextForAction(action) spriteSheetBuilder.addAnimation(action.name, frames, next) containerActions = [] for a in actionObjects continue unless a.container continue unless a.name in @actionNames containerActions.push(a) containerGroups = _.groupBy containerActions, (action) -> action.container for containerName, actions of containerGroups container = spriteBuilder.buildContainerFromStore(containerName) scale = actions[0].scale or @thangType.get('scale') or 1 frame = spriteSheetBuilder.addFrame(container, null, scale * @resolutionFactor) for action in actions spriteSheetBuilder.addAnimation(action.name, [frame], false) onBuildSpriteSheetComplete: (e, builder) -> if builder.spriteSheet._images.length > 1 total = 0 # get a rough estimate of how much smaller the spritesheet needs to be for image, index in builder.spriteSheet._images total += image.height / builder.maxHeight @resolutionFactor /= (Math.max(1.1, Math.sqrt(total))) @_renderNewSpriteSheet(e.async) return @trigger 'build', { spriteSheet: builder.spriteSheet } module.exports = SpriteExporter