CustomTimerObj

  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
>messy.
>

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
parameters.

-- 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
end


on init me,LpParam,CustomTimerObj
  myLpParam=LpParam
  me.subscribe(CustomTimerObj)
end


------------------------

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

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
  me.payLoad()

end


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

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

-- 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
  me.init()
  return me
end


on init me
  myLpKicks=[:]
  sort myLpKicks
  myActive=TRUE
end


------------------------

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

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

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

--------------------
on diag me
  erg=[:]
  addprop erg,#JobsWaiting,Count(myLpKicks)
  return erg
end

-- EoS


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

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


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










pageID=l_CustomTimerObj