Refactored portraits to be built in sprite sheets separately.

This commit is contained in:
Scott Erickson 2014-01-04 08:55:12 -08:00
parent 674ba86479
commit c4bfcd5c2d
2 changed files with 66 additions and 57 deletions
app
models
views/editor/thang

View file

@ -21,6 +21,7 @@ module.exports = class ThangType extends CocoModel
requiredRawAnimations: -> requiredRawAnimations: ->
required = [] required = []
for name, action of @get('actions') for name, action of @get('actions')
continue if name is 'portrait'
allActions = [action].concat(_.values (action.relatedActions ? {})) allActions = [action].concat(_.values (action.relatedActions ? {}))
for a in allActions when a.animation for a in allActions when a.animation
scale = if name is 'portrait' then a.scale or 1 else a.scale or @get('scale') or 1 scale = if name is 'portrait' then a.scale or 1 else a.scale or @get('scale') or 1
@ -59,80 +60,87 @@ module.exports = class ThangType extends CocoModel
options options
buildSpriteSheet: (options) -> buildSpriteSheet: (options) ->
options = @fillOptions options @initBuild(options)
# @options.portraitOnly = true
@addGeneralFrames() unless @options.portraitOnly
@addPortrait()
@finishBuild()
initBuild: (options) ->
@buildActions() if not @actions @buildActions() if not @actions
unless @requiredRawAnimations().length or _.find @actions, 'container' @options = @fillOptions options
return null if @.get('name') is 'Invisible' @vectorParser = new SpriteBuilder(@)
console.warn "Can't build a CocoSprite with no animations or containers!", @ @builder = new createjs.SpriteSheetBuilder()
@builder.padding = 2
@frames = {}
addPortrait: ->
# The portrait is built very differently than the other animations, so it gets a separate function.
portrait = @actions.portrait
return unless portrait
scale = portrait.scale or 1
pt = portrait.positions?.registration
rect = new createjs.Rectangle(pt?.x/scale or 0, pt?.y/scale or 0, 100/scale, 100/scale)
if portrait.animation
mc = @vectorParser.buildMovieClip portrait.animation
mc.nominalBounds = mc.frameBounds = null # override what the movie clip says on bounding
@builder.addMovieClip(mc, rect, scale)
frames = @builder._animations[portrait.animation].frames
frames = @normalizeFrames(portrait.frames, frames[0]) if portrait.frames?
portrait.frames = frames
@builder.addAnimation 'portrait', frames, true
else if portrait.container
s = @vectorParser.buildContainerFromStore(portrait.container)
frame = @builder.addFrame(s, rect, scale)
@builder.addAnimation 'portrait', [frame], false
vectorParser = new SpriteBuilder(@) addGeneralFrames: ->
builder = new createjs.SpriteSheetBuilder()
builder.padding = 2
# First we add the frames from the raw animations to the sprite sheet builder
framesMap = {} framesMap = {}
for animation in @requiredRawAnimations() for animation in @requiredRawAnimations()
name = animation.animation name = animation.animation
movieClip = vectorParser.buildMovieClip name mc = @vectorParser.buildMovieClip name
if animation.portrait @builder.addMovieClip mc, null, animation.scale * @options.resolutionFactor
movieClip.nominalBounds = null framesMap[animation.scale + "_" + name] = @builder._animations[name].frames
movieClip.frameBounds = null
pt = @actions.portrait.positions?.registration
rect = new createjs.Rectangle(pt?.x/animation.scale or 0, pt?.y/animation.scale or 0, 100/animation.scale, 100/animation.scale)
builder.addMovieClip(movieClip, rect, animation.scale)
else
builder.addMovieClip movieClip, null, animation.scale * options.resolutionFactor
framesMap[animation.scale + "_" + name] = builder._animations[name].frames
# Then we add real animations for our actions with our desired configuration
for name, action of @actions when action.animation for name, action of @actions when action.animation
if name is 'portrait' continue if name is 'portrait'
scale = action.scale ? 1 scale = action.scale ? @get('scale') ? 1
else frames = framesMap[scale + "_" + action.animation]
scale = action.scale ? @get('scale') ? 1 frames = @mapFrames(action.frames, frames[0]) if action.frames?
keptFrames = framesMap[scale + "_" + action.animation] action.frames = frames # Keep generated frame numbers around
if action.frames
frames = action.frames
frames = frames.split(',') if _.isString(frames)
newFrames = (parseInt(f, 10) for f in frames)
keptFrames = (f + keptFrames[0] for f in newFrames)
action.frames = keptFrames # Keep generated frame numbers around
next = true next = true
if action.goesTo next = action.goesTo if action.goesTo
console.warn "Haven't figured out what action.goesTo should do yet" next = false if action.loops is false
next = action.goesTo # TODO: what should this be? action? animation? @builder.addAnimation name, frames, next
else if action.loops is false
next = false
builder.addAnimation name, keptFrames, next
for name, action of @actions when action.container and not action.animation for name, action of @actions when action.container and not action.animation
scale = options.resolutionFactor * (action.scale or @get('scale') or 1) continue if name is 'portrait'
s = vectorParser.buildContainerFromStore(action.container) scale = @options.resolutionFactor * (action.scale or @get('scale') or 1)
if action.name is 'portrait' s = @vectorParser.buildContainerFromStore(action.container)
scale = action.scale or 1 frame = @builder.addFrame(s, s.bounds, scale)
pt = action?.positions?.registration @builder.addAnimation name, [frame], false
rect = new createjs.Rectangle(pt?.x/scale or 0, pt?.y/scale or 0, 100/scale, 100/scale)
frame = builder.addFrame(s, rect, scale) mapFrames: (frames, frameOffset) ->
else return frames unless _.isString(frames) # don't accidentally do this again
frame = builder.addFrame(s, s.bounds, scale) (parseInt(f, 10) + frameOffset for f in frames.split(','))
builder.addAnimation name, [frame], false
finishBuild: ->
return if _.isEmpty(@builder._animations)
key = @spriteSheetKey(@options)
spriteSheet = null spriteSheet = null
if options.async if @options.async
builder.buildAsync() @builder.buildAsync()
builder.on 'complete', @onBuildSpriteSheetComplete, @, true, @spriteSheetKey(options) @builder.on 'complete', @onBuildSpriteSheetComplete, @, true, key
return true return true
else
console.warn 'Building', @get('name'), 'and blocking the main thread. LevelLoader should have it built asynchronously instead.' console.warn 'Building', @get('name'), 'and blocking the main thread. LevelLoader should have it built asynchronously instead.'
spriteSheet = builder.build() spriteSheet = @builder.build()
@spriteSheets[@spriteSheetKey(options)] = spriteSheet @spriteSheets[key] = spriteSheet
# console.log "Generated fresh spritesheet", @spriteSheetKey(options)
spriteSheet spriteSheet
onBuildSpriteSheetComplete: (e, key) -> onBuildSpriteSheetComplete: (e, key) ->
@spriteSheets[key] = e.target.spriteSheet @spriteSheets[key] = e.target.spriteSheet
@trigger 'build-complete' @trigger 'build-complete'
# $('body').append(@getPortrait(key))
spriteSheetKey: (options) -> spriteSheetKey: (options) ->
"#{@get('name')} - #{options.resolutionFactor}" "#{@get('name')} - #{options.resolutionFactor}"

View file

@ -180,6 +180,7 @@ module.exports = class ThangTypeEditView extends View
@thangType.resetSpriteSheetCache() @thangType.resetSpriteSheetCache()
spriteSheet = @thangType.buildSpriteSheet(options) spriteSheet = @thangType.buildSpriteSheet(options)
$('#canvases').empty() $('#canvases').empty()
return unless spriteSheet
for image in spriteSheet._images for image in spriteSheet._images
$('#canvases').append(image) $('#canvases').append(image)
@showAnimation() @showAnimation()