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!
------------------------------------------------- -- 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
An example of adding a marker and a callback handler:
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
Below is a demonstration of how the script works: