2014-01-03 10:32:13 -08:00
CocoClass = require ' lib/CocoClass '
Camera = require ' ./Camera '
2014-03-06 15:52:09 -08:00
ThangType = require ' models/ThangType '
markThangTypes = { }
2014-01-03 10:32:13 -08:00
module.exports = class Mark extends CocoClass
subscriptions: { }
constructor: (options) ->
super ( )
options ? = { }
@name = options . name
@sprite = options . sprite
@camera = options . camera
@layer = options . layer
@thangType = options . thangType
console . error @ toString ( ) , " needs a name. " unless @ name
console . error @ toString ( ) , " needs a camera. " unless @ camera
console . error @ toString ( ) , " needs a layer. " unless @ layer
@ build ( )
destroy: ->
@ mark ? . parent ? . removeChild @ mark
2014-02-11 15:38:36 -08:00
@ markSprite ? . destroy ( )
2014-03-06 15:52:09 -08:00
@ thangType ? . off ' sync ' , @ onLoadedThangType , @
2014-02-11 15:38:36 -08:00
@sprite = null
2014-02-14 10:57:47 -08:00
super ( )
2014-01-03 10:32:13 -08:00
toString: -> " <Mark #{ @ name } : Sprite #{ @ sprite ? . thang ? . id ? ' None ' } > "
toggle: (to) ->
return @ if to is @ on
2014-03-06 15:52:09 -08:00
return @toggleTo = to unless @ mark
2014-01-03 10:32:13 -08:00
@on = to
2014-03-06 15:52:09 -08:00
delete @ toggleTo
2014-01-03 10:32:13 -08:00
if @ on
@ layer . addChild @ mark
@ layer . updateLayerOrder ( )
else
@ layer . removeChild @ mark
if @ highlightTween
@highlightDelay = @highlightTween = null
createjs . Tween . removeTweens @ mark
@mark.visible = true
@
setSprite: (sprite) ->
return if sprite is @ sprite
@sprite = sprite
@ build ( )
@
build: ->
unless @ mark
if @ name is ' bounds ' then @ buildBounds ( )
2014-02-24 17:53:35 -08:00
else if @ name is ' shadow ' then @ buildShadow ( )
2014-01-03 10:32:13 -08:00
else if @ name is ' debug ' then @ buildDebug ( )
else if @ thangType then @ buildSprite ( )
else console . error " Don ' t know how to build mark for " , @ name
2014-03-06 15:52:09 -08:00
@ mark ? . mouseEnabled = false
2014-01-03 10:32:13 -08:00
@
buildBounds: ->
@mark = new createjs . Container ( )
@mark.mouseChildren = false
# Confusingly make some semi-random colors that'll be consistent based on the drawsBoundsIndex
index = @ sprite . thang . drawsBoundsIndex
colors = ( 128 + Math . floor ( ( ' 0. ' + Math . sin ( 3 * index + i ) . toString ( ) . substr ( 6 ) ) * 128 ) for i in [ 1 . . . 4 ] )
color = " rgba( #{ colors [ 0 ] } , #{ colors [ 1 ] } , #{ colors [ 2 ] } , 0.5) "
shape = new createjs . Shape ( )
shape . graphics . setStrokeStyle 5
shape . graphics . beginStroke color
shape . graphics . beginFill color . replace ( ' 0.5 ' , ' 0.25 ' )
[ w , h ] = [ @ sprite . thang . width * Camera . PPM , @ sprite . thang . height * Camera . PPM * @ camera . y2x ]
if @ sprite . thang . shape in [ " ellipsoid " , " disc " ]
shape . drawEllipse 0 , 0 , w , h
else
shape . graphics . drawRect - w / 2 , - h / 2 , w , h
shape . graphics . endStroke ( )
shape . graphics . endFill ( )
2014-03-14 19:44:19 -07:00
text = new createjs . Text " " + index , " 40px Arial " , color . replace ( ' 0.5 ' , ' 1 ' )
2014-01-03 10:32:13 -08:00
text.regX = text . getMeasuredWidth ( ) / 2
text.regY = text . getMeasuredHeight ( ) / 2
text.shadow = new createjs . Shadow ( " # 000000 " , 1 , 1 , 0 )
@ mark . addChild shape , text
if w > 0 and h > 0
@ mark . cache - w / 2 , - h / 2 , w , h , 2
@lastWidth = @ sprite . thang . width
@lastHeight = @ sprite . thang . height
2014-02-24 17:53:35 -08:00
buildShadow: ->
width = ( @ sprite . thang ? . width ? 0 ) + 0.5
height = ( @ sprite . thang ? . height ? 0 ) + 0.5
longest = Math . max width , height
actualLongest = @ sprite . thangType . get ( ' shadow ' ) ? longest
width = width * actualLongest / longest
height = height * actualLongest / longest
width *= Camera . PPM
height *= Camera . PPM * @ camera . y2x # TODO: doesn't work with rotation
2014-01-03 10:32:13 -08:00
@mark = new createjs . Shape ( )
@mark.mouseEnabled = false
@ mark . graphics . beginFill " black "
2014-02-24 17:53:35 -08:00
if @ sprite . thang . shape in [ ' ellipsoid ' , ' disc ' ]
@ mark . graphics . drawEllipse 0 , 0 , width , height
else
@ mark . graphics . drawRect 0 , 0 , width , height
2014-01-03 10:32:13 -08:00
@ mark . graphics . endFill ( )
2014-02-24 17:53:35 -08:00
@mark.regX = width / 2
@mark.regY = height / 2
2014-01-03 10:32:13 -08:00
@mark.layerIndex = 10
#@mark.cache 0, 0, diameter, diameter # not actually faster than simple ellipse draw
2014-02-24 17:53:35 -08:00
buildRadius: ->
return # not implemented
2014-01-03 10:32:13 -08:00
buildDebug: ->
@mark = new createjs . Shape ( )
PX = 3
[ w , h ] = [ Math . max ( PX , @ sprite . thang . width * Camera . PPM ) , Math . max ( PX , @ sprite . thang . height * Camera . PPM ) * @ camera . y2x ]
@mark.alpha = 0.5
@ mark . graphics . beginFill ' # abcdef '
if @ sprite . thang . shape in [ " ellipsoid " , " disc " ]
[ w , h ] = [ Math . max ( PX , w , h ) , Math . max ( PX , w , h ) ]
@ mark . graphics . drawCircle 0 , 0 , w / 2
else
@ mark . graphics . drawRect - w / 2 , - h / 2 , w , h
@ mark . graphics . endFill ( )
buildSprite: ->
2014-03-06 15:52:09 -08:00
if _ . isString @ thangType
thangType = markThangTypes [ @ thangType ]
return @ loadThangType ( ) if not thangType
@thangType = thangType
return @ thangType . once ' sync ' , @ onLoadedThangType , @ if not @ thangType . loaded
2014-01-03 10:32:13 -08:00
CocoSprite = require ' ./CocoSprite '
2014-01-14 13:16:30 -08:00
markSprite = new CocoSprite @ thangType , @ thangType . spriteOptions
markSprite . queueAction ' idle '
2014-01-03 10:32:13 -08:00
@mark = markSprite . displayObject
2014-02-11 15:38:36 -08:00
@markSprite = markSprite
2014-01-03 10:32:13 -08:00
2014-03-06 15:52:09 -08:00
loadThangType: ->
name = @ thangType
@thangType = new ThangType ( )
@thangType.url = -> " /db/thang.type/ #{ name } "
@ thangType . once ' sync ' , @ onLoadedThangType , @
@ thangType . fetch ( )
markThangTypes [ name ] = @ thangType
window . mtt = markThangTypes
2014-03-07 21:02:10 -08:00
2014-03-06 15:52:09 -08:00
onLoadedThangType: ->
@ build ( )
@ toggle ( @ toggleTo ) if @ toggleTo ?
2014-03-12 10:08:57 -07:00
Backbone . Mediator . publish ' sprite:loaded '
2014-03-06 15:52:09 -08:00
2014-01-03 10:32:13 -08:00
update: (pos=null) ->
2014-03-06 15:52:09 -08:00
return false unless @ on and @ mark
2014-03-07 21:02:10 -08:00
@mark.visible = not @ hidden
2014-01-03 10:32:13 -08:00
@ updatePosition pos
@ updateRotation ( )
@ updateScale ( )
@ mark . advance ? ( )
if @ name is ' highlight ' and @ highlightDelay and not @ highlightTween
@mark.visible = false
@highlightTween = createjs . Tween . get ( @ mark ) . to ( { } , @ highlightDelay ) . call =>
@mark.visible = true
@highlightDelay = @highlightTween = null
true
updatePosition: (pos) ->
if @ name in [ ' shadow ' , ' debug ' ]
pos = @ camera . worldToSurface x: @ sprite . thang . pos . x , y: @ sprite . thang . pos . y
if @ name is ' shadow '
2014-01-31 10:21:32 -08:00
worldZ = @ sprite . thang . pos . z - @ sprite . thang . depth / 2 + @ sprite . getBobOffset ( )
2014-01-03 10:32:13 -08:00
@mark.alpha = 0.451 / Math . sqrt ( worldZ / 2 + 1 )
else
2014-01-21 09:03:04 -08:00
pos ? = @ sprite ? . displayObject
2014-01-03 10:32:13 -08:00
@mark.x = pos . x
@mark.y = pos . y
2014-03-06 15:52:09 -08:00
if @ statusEffect or @ name is ' highlight '
2014-01-03 10:32:13 -08:00
offset = @ sprite . getOffset ' aboveHead '
@ mark . x += offset . x
@ mark . y += offset . y
2014-03-06 15:52:09 -08:00
@ mark . y -= 3 if @ statusEffect
2014-01-03 10:32:13 -08:00
updateRotation: ->
2014-02-24 17:53:35 -08:00
if @ name is ' debug ' or ( @ name is ' shadow ' and @ sprite . thang ? . shape in [ " rectangle " , " box " ] )
2014-01-03 10:32:13 -08:00
@mark.rotation = @ sprite . thang . rotation * 180 / Math . PI
updateScale: ->
if @ name is ' bounds ' and ( @ sprite . thang . width isnt @ lastWidth or @ sprite . thang . height isnt @ lastHeight )
oldMark = @ mark
@ buildBounds ( )
oldMark . parent . addChild @ mark
oldMark . parent . swapChildren oldMark , @ mark
oldMark . parent . removeChild oldMark
return unless @ name in [ " selection " , " target " , " repair " , " highlight " ]
scale = 0.5
if @ sprite
size = @ sprite . getAverageDimension ( )
size += 60 if @ name is ' selection '
size += 60 if @ name is ' repair '
scale = size / { selection: 128 , target: 128 , repair: 320 , highlight: 160 } [ @ name ]
2014-01-30 14:21:58 -08:00
if @ sprite ? . thang . spriteName . search ( /(dungeon|indoor).wall/i ) isnt - 1
2014-01-03 10:32:13 -08:00
scale *= 2
@mark.scaleX = @mark.scaleY = Math . min 1 , scale
if @ name in [ ' selection ' , ' target ' , ' repair ' ]
@ mark . scaleY *= @ camera . y2x # code applies perspective
2014-02-24 14:40:28 -08:00
stop: -> @ markSprite ? . stop ( )
play: -> @ markSprite ? . play ( )
2014-03-06 15:52:09 -08:00
hide: -> @hidden = true
show: -> @hidden = false