2 parent scripts which together act as a timeout deluxe
TimeOut idle

  timing tasks
>It would be nice to have
>an alternative to stepframe which doesn't call on an
>updatestage, but in the absence of that, can anyone think of a workround?
>The only possibility I can think of is to use a global fake actorlist and
>call all objects in it on every exitframe (or enterframe), but it's a bit

The timeoutScript could be used for that.
Another possible source of regular events would be the idle event which
occurs quite often. In fact, much to often for most practical purposes, so
you will need some sort of filter which enables you to act only on every
nth idle event, or better: act on the first event after some dt duration of
time has passed.

Below are 2 parent scripts which together act as a timeout deluxe.

The first script represents the job to be done. You create it with a
property list specifying the task to be done and an ObjReference as

-- parent script -----

-- Job - Objekt

-- Aufruf:
-- new (script "JobObj",[#task:"doAble" oder #sendAble, #caller:<ObjRef>, 
       #Param: (optional),#msFrist:100,#Type:#single/#period/Integer],<ObjRef>)
-- i.e.
-- new (script "JobObj",[#task:#blink, #caller:new(script "blinkObj",1), 
       #msFrist:200, #Param: #red,#Type:#period], gObjRef)
-- new (script "JobObj",[#task:"set the text of member 7 = the time", 
       #caller:"", #msFrist:60000, #Type:#single], gObjRef)


property  myLpParam

on new me, LpParam,CustomTimerObj
  me.init (LpParam,CustomTimerObj)
  return me

on init me,LpParam,CustomTimerObj


on subscribe me,CustomTimerObj
  if ilk(CustomTimerObj)<>#instance then return #error_missingObjRef
  dMoment=the milliseconds + msFrist

on timeKick me,dObj
  dType = myLpParam.getaprop(#type)

  -- NewEntry  
  if dType <> #single then
    if (IntegerP(dType) and dType>0) then myLpParam.setaProp (#Type,dType-1)
    if dType <> 0 then me.subscribe(dObj)
  end if

  -- PayLoad


on payLoad me
  dTask   = myLpParam.getaProp(#task)
  dCaller = myLpParam.getaProp(#caller)
  dParam  = myLpParam.getaProp(#param)

  if stringP(dTask) then
    do dTask
    if symbolP(dTask) and objectP(dCaller) then
      call (dTask,dCaller,dParam)
    end if
  end if

-- EoS

The second script queues the waiting jobs, checks if their time has come
and if so, triggers their execution. This is the one which is called with
every idle event. While I create a new instance of the jobObj for any new
task scheduled there is only 1 instance of this object which is stored
globally. Its reference is the second parameter when birthing a new jobObj.

-- parent script CustomTimer - Objekt

-- Aufruf:
--new script "CustomTimerObj"


property  myLpKicks,myActive

on new me
  return me

on init me
  sort myLpKicks


on Kick me
  if myActive then
    if myLpKicks.Count > 0 then
      dMsecs = myLpKicks.getPropAt(1)
      if the milliseconds >= dMsecs then
        dObj = myLpKicks[1]
        if objectP(dObj) then dObj.timeKick()
      end if
    end if
  end if

on AddKick me, dTicks,dObj
  myLpKicks.addProp( dTicks,dObj )
  return TRUE

on setActive me,dVal
  if voidP(dVal) then dVal = TRUE
  myActive = dVal

on diag me
  addprop erg,#JobsWaiting,Count(myLpKicks)
  return erg

-- EoS

The third element is to direct idle events to the CustomTimerObj like:

on idle
  global gCustomTimerObj
  if gCustomTimerObj.ilk = #instance then gCustomTimerObj.Kick()

The object has a setActive method which allows to switch it off and on again.
There are two supported ways to define a task when subscribing a new Job:
you can make it as a call of a handler of some script instance or formulate
it as a doAble string

ie, if you had a parent script blinkObj with a handler 'on blink me,dColor'
you could make it blink red continuosly 5 times a second by:

 new (script "JobObj",[#task:#blink, #caller:new(script "blinkObj",1), 
       #msFrist:200, #Param: #red,#Type:#period], gObjRef)

Birthing a new jobObj returns a obj reference but you need not store it
somewhere, or rather, you shouldn't. The new job stores itself at the
global obj it gets passed at birth and survives the garbage collection
thanks to beeing referenced there. When its time has come the
customTimerObj deletes the refernce so the object representing the job
vanishes instantly after the task has been done.

caveat: I did some editing in the emailer, translated handlerNames etc so I
may have added errors to it.

Daniel Plaenitz

Home shock + cgi Bits 'n pieces Director Lingo Shocklets Contact