Extended Filmloop

Here is another script trying to solve the problems which arise when one is using a #filmloop. How to pause a #filmloop? How to affect the speed of its performance? How to make a #filmloop to be played (for instance) in 1.5 seconds? The answers of these and many other questions are here!

Show code

[php]
————————————————-
— PROPERTIES
————————————————-
on ___________________________PROPERTIES
end

property _id
property _cnt
property _blend
property _tempo
property _frame
property _sprite
property _paused
property _markers
property _reversed
property _callbacks
property _maxframes
property _lastframe
property _framecount
property _blendLevels
property _channelcount
property _useTime
property _time
property _delay
property _lastMS

————————————————-
— SYSTEM EVENT HANDLERS
————————————————-
on ___________________________SYSTEM_EVENT_HANDLERS
end
on isOkToAttach( me, aSpriteType, aSpriteNum )
ok = FALSE
if ( aSpriteType = #graphic ) then
if ( [ #filmLoop, #movie ].getPos( sprite( aSpriteNum ).member.type ) > 0 ) then
ok = TRUE
end if
end if
return( ok )
end isOkToAttach

on getPropertyDescriptionList( me )
pdl = propList()
pdl.addProp( #_id, [ #format:#symbol, #default:symbol( "loop" && _player.currentSpriteNum ), #comment:"Loop ID:" ] )
pdl.addProp( #_reversed, [ #format:#boolean, #default:FALSE, #comment:"Reversed?" ] )
pdl.addProp( #_tempo, [ #format:#integer, #default:100, #range:[#min:10, #max:100], #comment:"Speed (100 = the movie tempo)" ] )
pdl.addProp( #_useTime, [ #format:#boolean, #default:TRUE, #comment:"Use Time?" ] )
pdl.addProp( #_time, [ #format:#integer, #default:1000, #comment:"Time to play (in milliseconds):" ] )
pdl.addProp( #_paused, [ #format:#boolean, #default:TRUE, #comment:"Paused on start?" ] )
pdl.addProp( #_blend, [ #format:#integer, #default:255, #range:[#min:0, #max:255], #comment:"Blend Level:" ])
return pdl
end getPropertyDescriptionList

on beginSprite( me )
_sprite = sprite( me.spritenum )
m = _sprite.member
_cnt = 0
_frame = 1
_maxframes = 1
_lastframe = 0
_blendLevels = list()
_markers = propList()
_callbacks = propList()
tell _sprite
_framecount = _movie.lastFrame
_channelcount = _movie.lastChannel
repeat with i = 1 to _channelcount
_blendLevels.append( sprite(i).blendLevel )
end repeat
end tell
me.speed( _tempo )
me.blendLevel( _blend )
if( _movie.actorList.getPos( me ) = 0 ) then
_movie.actorList.append( me )
end if
_useTime = ( _useTime = TRUE )
_time = integer( max( 10, _time ) )
_delay = integer( _time / float( _framecount ) )
_lastMS = _system.milliseconds
sendAllSprites( #loopReady, [ #sender:me, #args:[ #id:_id, #framecount:_framecount, #currentframe:_frame, #reversed:_reversed, #paused:_paused ] ] )
end beginSprite

on endSprite( me )
if( _movie.actorList.getPos( me ) > 0 ) then
_movie.actorList.deleteOne( me )
end if
end endSprite

on stepFrame( me )
if( _useTime ) then
me._calculateTime()
else
me._calculateCurrentFrame()
end if
if( not _paused ) then
if( not voidP( _callbacks[ #update ] ) ) then
call( _callbacks.update.handler, _callbacks.update.object, [ #id:_id, #frame:_frame ] )
end if
if( not voidP( _callbacks[ #marker ] ) ) then
pos = _markers.getPos( _frame )
if( pos > 0 ) then
if( _frame <>_lastframe ) then
call( _callbacks.marker.handler, _callbacks.marker.object, [ #id:_id, #marker:_markers.getPropAt( pos ) ] )
_lastframe = _frame
end if
else
_lastframe = 0
end if
end if
end if
tell _sprite
repeat with i = 1 to _channelcount
sprite( i ).blendLevel = integer( _blendLevels[i] * ( _blend/ 256.0 ) )
end repeat
_movie.go( _frame )
end tell
end stepFrame

————————————————-
— PUBLIC METHODS
————————————————-
on ___________________________PUBLIC_METHODS
end

on play( me )
_paused = FALSE
end play

on stop( me )
_paused = TRUE
end stop

on go( me, val )
if( ilk( val ) <> #string and ilk( val ) <> #integer ) then me._debug( "This method receives integers and strings only." )
if( ilk( val ) = #string ) then
if ( voidP( _markers[ val ] ) ) then
me._debug( "Bad marker name." )
else
_frame = _markers[ val ]
end if
end if
if( ilk( val ) = #integer ) then
if( val < 1 or val > _framecount ) then
me._debug( "Bad frame number." )
else
_frame = val
end if
end if
if( not voidP( _callbacks[ #update ] ) ) then
call( _callbacks.update.handler, _callbacks.update.object, [ #id:_id, #frame:_frame ] )
end if
end go

on goToAndStop( me, val )
me.go( val )
_paused = TRUE
end goToAndStop

on addMarker( me, aname, aframe )
f = 0
if( ilk( aname ) <> #string ) then f = me._debug( "Bad marker name." )
if( ilk( aframe ) <> #integer or ( aframe < 1 or aframe > _framecount ) ) then f = me._debug( "Bad frame number." )
if( not voidP( _markers[ aname ] ) ) then f = me._debug( "This marker name alredy exists." )
if( _markers.getPos( aframe ) > 0 ) then f = me._debug( "A marker already exists on this frame." )
if( f = 0 ) then _markers.addProp( aname, aframe )
end addMarker

on removeMarker( me, aname )
_markers.deleteProp( aname )
end removeMarker

on clearMarkers( me )
_markers.deleteAll()
end clearMarkers

on addCallback( me, event, ahandler, aobject )
if( [#update, #marker].getPos( event ) = 0 ) then me._debug( "Bad event name." )
if( ilk( ahandler ) <> #symbol ) then me._debug( "Bad handler name." )
if( ( ilk( aobject ) <> #instance and ilk( aobject ) <> #script ) or aobject.handlers().getPos( ahandler ) = 0 ) then me._debug( "Bad object." )
_callbacks[ event ] = [ #handler:ahandler, #object:aobject ]
end addCallback

on removeCallback( me, event )
if( [#update, #marker].getPos( event ) = 0 ) then me._debug( "Bad event name." )
_callbacks.deleteProp( event )
end removeCallback

on clearCallbacks( me )
_callbacks.deleteAll()
end clearCallbacks

————————————————-
— GETTERS / SETTERS
————————————————-
on ___________________________GETTERS_SETTERS
end

on speed( me, val )
if voidP( val ) then return 100 / float( _maxframes )
val = max( 1, min( val, 100 ) )
_maxframes = integer( 100 / float( val ) )
_cnt = 0
end speed

on time( me, val )
if voidP( val ) then return _time
_time = val
_delay = integer( _time / float( _framecount ) )
_lastMS = _system.milliseconds
end time

on paused( me, val )
if voidP( val ) then return _paused
_paused = ( val = true )
end paused

on progress( me, val )
if voidP( val ) then return _frame / float( _framecount )
_frame = integer( _framecount * val )
end progress

on blendLevel( me, val )
if voidP( val ) then return _blend
_blend = max( 0, min( val, 255 ) )
end blendLevel

on loop( me )
return _sprite.member.loop
end loop

on crop( me )
return _sprite.member.crop
end crop

on center( me, val )
return _sprite.member.center
end center

on reversed( me, val )
if voidP( val ) then return _reversed
_reversed = ( val = TRUE )
end setRate

————————————————-
— PRIVATE METHODS
————————————————-
on ___________________________PRIVATE_METHODS
end
on _calculateTime( me )
if( _paused ) then return
if( _system.milliseconds >= _lastMS + _delay ) then
if( not _reversed ) then
if( _frame < _framecount ) then
_frame = _frame + 1
else
_frame = 1
end if
else
if( _frame > 1 ) then
_frame = _frame – 1
else
_frame = _framecount
end if
end if
_lastMS = _system.milliseconds
end if
end _calculateTime

on _calculateCurrentFrame( me )
if( _paused ) then return
_cnt = _cnt + 1
if( _cnt = _maxframes ) then
if( not _reversed ) then
if( _frame < _framecount ) then
_frame = _frame + 1
else
_frame = 1
end if
else
if( _frame > 1 ) then
_frame = _frame – 1
else
_frame = _framecount
end if
end if
_cnt = 0
end if
end _calculateCurrentFrame

on _debug( me, msg )
if( _system.environmentPropList.runMode contains "author" ) then
_player.alert( msg )
else
trace( msg )
end if
return 1
end _debug

on ___________________________END_XLOOP
end
[/php]

An example of adding a marker and a callback handler:

Show code

[code lang=”lingo” gutter=”true” toolbar=”false”]
property loopA
property loopB

on loopReady( me, event )
case( event.args.id ) of
#loop1:
loopA = event.sender
loopA.addMarker( "end", 12 )
loopA.addCallback( #update, #updateSlider, me )
loopA.addCallback( #marker, #stopOnEnd, me )
#loop2:
loopB = event.sender
loopB.addCallback( #update, #updateSlider, me )
end case
end loopReady

on stopOnEnd( me, args )
loopA.stop()
loopA.removeCallback( #marker )
sprite("INSTRUCTION").visible = TRUE
end stopOnEnd

[/code]

Below is a demonstration of how the script works:

Extended Filmloop demo
 
Comments

No comments yet.

Leave a Reply