MODULEAnimHandle EXPORTSAnimHandle ,AnimHandlePrivate ,AnimHandleProxy ; IMPORT Anim3D, AnimRequestQueue, AnimServer, Thread; REVEAL T = Private BRANDED OBJECT list : List; OVERRIDES init := Init; attach := Attach; animate := Animate; END; TYPE List = REF RECORD head : AnimRequestQueue.T; tail : List; END; PROCEDUREInit (self : T) : T = BEGIN self.mu := NEW (MUTEX); self.cv := NEW (Thread.Condition); self.list := NIL; self.activated := FALSE; IF MkProxyT # NIL THEN MkProxyT (self); END; RETURN self; END Init; PROCEDURENew () : T = BEGIN RETURN NEW (T).init (); END New; PROCEDUREAttach (self : T; q : AnimRequestQueue.T) = PROCEDURE AddIfNew (VAR list : List) = BEGIN IF list = NIL THEN list := NEW (List, head := q, tail := list); ELSIF list.head # q THEN AddIfNew (list.tail); END; END AddIfNew; BEGIN AddIfNew (self.list); END Attach; PROCEDUREAnimate (self : T) = VAR max := 0.0; tmp : List; BEGIN LOCK self.mu DO tmp := self.list; self.activated := TRUE; self.starttime := Anim3D.Now (); WHILE tmp # NIL DO max := MAX (max, tmp.head.duration ()); tmp := tmp.tail; END; self.endtime := self.starttime + FLOAT (max, LONGREAL); AnimServer.PauseAnimHandle (self); self.activated := FALSE; (* Flush all the animation request queues attached to the animation handle. *) tmp := self.list; WHILE tmp # NIL DO tmp.head.flush (); tmp := tmp.tail; END; END; END Animate; BEGIN END AnimHandle.