import Promise from 'bluebird' import { EventEmitter, Mixin, Property } from '@avocado/composition' import {Rectangle, Vector} from '@avocado/math' import {Resource} from '@avocado/resource' import {setterName} from '@avocado/string' import { TimedIndexMixin as TimedIndex } from './timed-index' export class Animation extends Mixin(Resource).with( EventEmitter Property 'direction', default: 0 Property 'directionCount', default: 1 TimedIndex 'frame' Property 'frameSize', default: [0, 0] Property 'imageUri', default: '' Vector.Mixin( 'position', 'x', 'y' x: default: 0 y: default: 0 ) Property 'sourceRectangle', default: [0, 0, 0, 0] Property 'uri', default: '' ) @load: @createLoad Animation @reduce: (O) -> O = Object.assign (new Animation()).toJSON(), O O.directionCount = parseInt O.directionCount O.direction = parseInt O.direction ? 0 O.frameCount = parseInt O.frameCount O.frameRate = parseInt O.frameRate O.frameSize = O.frameSize.map (x) -> parseInt x O.uri or= '' O.imageUri or= O.uri.replace '.animation.json', '.png' return O constructor: -> super() @on [ 'directionChanged', 'frameSizeChanged', 'indexChanged' ], => @setSourceRectangle @rawSourceRectangle @index() @on 'directionCountChanged', => @setDirection @direction() clampDirection: (direction) -> return 0 if @directionCount() is 1 direction = Math.min 7, Math.max direction, 0 direction = { 4: 1 5: 1 6: 3 7: 3 }[direction] if @directionCount() is 4 and direction > 3 direction # Only mutates if not Vector.equals size, [0, 0] deriveFrameSize: (size) -> return frameSize unless Vector.isZero frameSize = @frameSize() ? [0, 0] return [0, 0] if Vector.isZero size return [0, 0] if @directionCount() is 0 return [0, 0] if @frameCount() is 0 # If the frame size isn't explicitly given, then calculate the # size of one frame using the total number of frames and the total # spritesheet size. Width is calculated by dividing the total # spritesheet width by the number of frames, and the height is the # height of the spritesheet divided by the number of directions # in the animation. return Vector.div size, [@frameCount(), @directionCount()] rawSourceRectangle: (index) -> return [0, 0, 0, 0] unless frameCount = @frameCount() frameSize = @frameSize() Rectangle.compose( Vector.mul frameSize, [ (index ? @index()) % frameCount @direction() ] frameSize ) setDirection: (direction) -> super @clampDirection parseInt direction setDirectionCount: (directionCount) -> super parseInt directionCount toJSON: -> defaultImageUri = @uri().replace '.animation.json', '.png' directionCount: @directionCount() frameRate: @frameRate() frameCount: @frameCount() frameSize: @frameSize() imageUri: @imageUri() if @imageUri() isnt defaultImageUri