MODULE*************************************************************************** TypeLineTypeProp EXPORTSLineTypeProp ,LineTypePropPrivate ,LineTypePropProxy ; IMPORT Anim3D, AnimHandle, AnimHandlePrivate, AnimRequestQueue, AnimRequestQueuePrivate, AnimServer, GraphicsBase, GraphicsBasePrivate, Prop, PropPrivate;
Name
***************************************************************************
REVEAL Name = PrivateName BRANDED OBJECT default : Kind; OVERRIDES init := InitName; bind := BindName; makeProxy := MakeProxyName; push := PushName; pop := PopName; newStack := NewStack; getState := GetState; END; PROCEDURE*************************************************************************** TypeInitName (self : Name; default : Kind) : Name = BEGIN EVAL Prop.Name.init (self); self.default := default; IF NamePM # NIL THEN NamePM (self); END; RETURN self; END InitName; PROCEDUREBindName (self : Name; val : Val) : Prop.T = BEGIN RETURN NEW (Prop.T).init (self, val); END BindName; PROCEDUREMakeProxyName (self : Name) = BEGIN IF self.proxy = NIL AND NamePM # NIL THEN NamePM (self); END; END MakeProxyName; PROCEDUREPushName (self : Name; state : GraphicsBase.T; pv : Prop.Val) = BEGIN WITH stack = NARROW (state.stacks[self.id], Stack), val = NARROW (pv, Val).val DO stack.push (val); END; END PushName; PROCEDUREPopName (self : Name; state : GraphicsBase.T) = BEGIN EVAL NARROW (state.stacks[self.id], Stack).pop (); END PopName; PROCEDURENewStack (self : Name) : PropPrivate.Stack = BEGIN RETURN NEW (Stack).init (self.default); END NewStack; PROCEDUREGetState (self: Name; state : GraphicsBase.T) : Kind = BEGIN RETURN NARROW (state.stacks[self.id], Stack).top; END GetState;
Val
***************************************************************************
REVEAL Val = PrivateVal BRANDED OBJECT OVERRIDES init := InitVal; get := GetVal; value := ValueVal; adjust := AdjustVal; END; PROCEDURE*************************************************************************** TypeInitVal (self : Val; beh : Beh) : Val = BEGIN self.beh := beh; self.time := Anim3D.Now () - 10.0d0; IF ValPM # NIL THEN ValPM (self); END; RETURN self; END InitVal; PROCEDUREGetVal (self : Val) : Kind RAISES {Prop.BadMethod} = BEGIN RETURN self.beh.value (Anim3D.Now ()); END GetVal; PROCEDUREValueVal (self : Val; time : LONGREAL) : Kind RAISES {Prop.BadMethod} = BEGIN IF time = self.time THEN RETURN self.val; ELSE RETURN self.beh.value (time); END; END ValueVal; PROCEDUREAdjustVal (self : Val; time : LONGREAL) : BOOLEAN RAISES {Prop.BadMethod} = BEGIN IF time # self.time THEN WITH val = self.beh.value (time) DO self.damaged := val # self.val; self.time := time; self.val := val; END; END; RETURN self.damaged; END AdjustVal;
Beh
***************************************************************************
REVEAL Beh = PrivateBeh BRANDED OBJECT OVERRIDES init := InitBeh; END; PROCEDURE*************************************************************************** TypeInitBeh (self : Beh) : Beh = BEGIN RETURN self; END InitBeh;
ConstBeh
***************************************************************************
REVEAL ConstBeh = PublicConstBeh BRANDED OBJECT kind : Kind; OVERRIDES init := InitConstBeh; set := SetConstBeh; value := ValueConstBeh; END; PROCEDURE*************************************************************************** TypeInitConstBeh (self : ConstBeh; kind : Kind) : ConstBeh = BEGIN EVAL Beh.init (self); self.kind := kind; IF ConstBehPM # NIL THEN ConstBehPM (self); END; RETURN self; END InitConstBeh; PROCEDURESetConstBeh (self : ConstBeh; kind : Kind) = BEGIN self.kind := kind; END SetConstBeh; PROCEDUREValueConstBeh ( self : ConstBeh; <* UNUSED *> time : LONGREAL) : Kind = BEGIN RETURN self.kind; END ValueConstBeh; PROCEDURENewConst (kind : Kind) : Val = BEGIN RETURN NEW (Val).init (NEW (ConstBeh).init (kind)); END NewConst;
AsyncBeh
***************************************************************************
REVEAL AsyncBeh = PublicAsyncBeh BRANDED OBJECT OVERRIDES init := InitAsyncBeh; value := ValueAsyncBeh; compute := ComputeAsyncBeh; END; PROCEDURE*************************************************************************** TypeInitAsyncBeh (self : AsyncBeh) : AsyncBeh = BEGIN EVAL Beh.init (self); IF AsyncBehPM # NIL THEN AsyncBehPM (self); END; RETURN self; END InitAsyncBeh; PROCEDUREValueAsyncBeh (self : AsyncBeh; time : LONGREAL) : Kind RAISES {Prop.BadMethod} = BEGIN RETURN self.compute (time); END ValueAsyncBeh; PROCEDUREComputeAsyncBeh (self : AsyncBeh; time : LONGREAL) : Kind RAISES {Prop.BadMethod} = BEGIN IF self.proxy # NIL THEN RETURN NARROW (self.proxy, AsyncBehProxy).compute (time); ELSE RAISE Prop.BadMethod("LineTypeProp.AsyncBeh.compute method is undefined"); END; END ComputeAsyncBeh; PROCEDURENewAsync (b : AsyncBeh) : Val = BEGIN RETURN NEW (Val).init (b); END NewAsync;
DepBeh
***************************************************************************
REVEAL DepBeh = PublicDepBeh BRANDED OBJECT hot : BOOLEAN; OVERRIDES init := InitDepBeh; value := ValueDepBeh; compute := ComputeDepBeh; END; PROCEDURE*************************************************************************** TypeInitDepBeh (self : DepBeh) : DepBeh = BEGIN EVAL Beh.init (self); self.hot := FALSE; IF DepBehPM # NIL THEN DepBehPM (self); END; RETURN self; END InitDepBeh; PROCEDUREValueDepBeh (self : DepBeh; time : LONGREAL) : Kind RAISES {Prop.BadMethod} = BEGIN (* "hot" is set to true while the value of the behavior is computed. So, if "hot" is currently true, we have cyclic dependencies. If unchecked, this would lead to an infinite recursion. We raise an exception instead. *) IF self.hot THEN RAISE Prop.BadMethod("LineTypeProp.DepBeh occurs in a dependency cycle"); END; TRY self.hot := TRUE; RETURN self.compute (time); FINALLY self.hot := FALSE; END; END ValueDepBeh; PROCEDUREComputeDepBeh (self : DepBeh; time : LONGREAL) : Kind RAISES {Prop.BadMethod} = BEGIN IF self.proxy # NIL THEN RETURN NARROW (self.proxy, DepBehProxy).compute (time); ELSE RAISE Prop.BadMethod("LineTypeProp.DepBeh.compute method is undefined"); END; END ComputeDepBeh; PROCEDURENewDep (b : DepBeh) : Val = BEGIN RETURN NEW (Val).init (b); END NewDep;
SyncBeh
***************************************************************************
REVEAL SyncBeh = PublicSyncBeh BRANDED OBJECT queue : MyAnimRequestQueue; OVERRIDES init := InitSyncBeh; value := ValueSyncBeh; addRequest := AddRequest; change := Change; END; PROCEDURE*************************************************************************** Request Subtypes ***************************************************************************InitSyncBeh (self : SyncBeh; ah : AnimHandle.T; kind : Kind) : SyncBeh = BEGIN EVAL Beh.init (self); self.queue := NEW (MyAnimRequestQueue).init (ah, kind); IF SyncBehPM # NIL THEN SyncBehPM (self); END; RETURN self; END InitSyncBeh; PROCEDUREValueSyncBeh (self : SyncBeh; time : LONGREAL) : Kind RAISES {Prop.BadMethod} = BEGIN RETURN self.queue.value (time); END ValueSyncBeh; PROCEDUREAddRequest (self : SyncBeh; r : Request) RAISES {Prop.BadInterval} = BEGIN self.queue.insert (r); END AddRequest; PROCEDUREChange (self : SyncBeh; kind : Kind; start : REAL) RAISES {Prop.BadInterval} = BEGIN self.queue.insert (NEW (ChangeReq).init (start, 0.0, kind)); END Change; PROCEDURENewSync (ah : AnimHandle.T; kind : Kind) : Val = BEGIN RETURN NEW (Val).init (NEW (SyncBeh).init (ah, kind)); END NewSync;
REVEAL Request = PublicRequest BRANDED OBJECT OVERRIDES init := InitRequest; value := ValueRequest; END; PROCEDURE*************************************************************************** Animation queue for synchronous line type property value behavior ***************************************************************************InitRequest (self : Request; start, dur : REAL) : Request = BEGIN EVAL Prop.Request.init (self, start, dur); IF RequestPM # NIL THEN RequestPM (self); END; RETURN self; END InitRequest; PROCEDUREValueRequest (self : Request; startval : Kind; reltime : REAL) : Kind RAISES {Prop.BadMethod} = BEGIN IF self.proxy # NIL THEN RETURN NARROW (self.proxy, RequestProxy).value (startval, reltime); ELSE RAISE Prop.BadMethod("LineTypeProp.Request.value method is undefined"); END; END ValueRequest; TYPE ChangeReq = Request BRANDED OBJECT kind : Kind; METHODS init (start, dur : REAL; val : Kind) : ChangeReq := ChangeReqInit; OVERRIDES value := ChangeReqValue; END; PROCEDUREChangeReqInit (self : ChangeReq; start, dur : REAL; val : Kind) : ChangeReq = BEGIN EVAL Request.init (self, start, dur); self.kind := val; RETURN self; END ChangeReqInit; PROCEDUREChangeReqValue ( self : ChangeReq; <* UNUSED *> startkind : Kind; reltime : REAL) : Kind = BEGIN <* ASSERT reltime >= self.start AND reltime <= self.start + self.dur *> RETURN self.kind; END ChangeReqValue;
TYPE MyAnimRequestQueue = AnimRequestQueue.T BRANDED OBJECT kind : Kind; (* The initial value of the pv *) METHODS init (ah : AnimHandle.T; kind : Kind) : MyAnimRequestQueue := MyAnimRequestQueue_Init; value (time : LONGREAL) : Kind RAISES {Prop.BadMethod} := MyAnimRequestQueue_Value; OVERRIDES flush := MyAnimRequestQueue_Flush; END; PROCEDURE*************************************************************************** Stack ***************************************************************************MyAnimRequestQueue_Init (self : MyAnimRequestQueue; ah : AnimHandle.T; kind : Kind) : MyAnimRequestQueue = BEGIN EVAL AnimRequestQueue.T.init (self, ah); self.kind := kind; RETURN self; END MyAnimRequestQueue_Init; PROCEDUREMyAnimRequestQueue_Value (self : MyAnimRequestQueue; time : LONGREAL) : Kind RAISES {Prop.BadMethod} = VAR l := self.list; req : Request; kind : Kind; reltime : REAL; BEGIN IF self.ah.activated THEN reltime := FLOAT (time - self.ah.starttime); kind := self.kind; WHILE l # NIL DO req := l.req; IF reltime < req.start THEN RETURN kind; ELSIF reltime < req.start + req.dur THEN RETURN req.value (kind, reltime); ELSE kind := req.value (kind, req.start + req.dur); l := l.next; END; END; RETURN kind; ELSE RETURN self.kind; END; END MyAnimRequestQueue_Value; PROCEDUREMyAnimRequestQueue_Flush (self : MyAnimRequestQueue) = VAR req : Request; BEGIN WHILE self.list # NIL DO req := self.list.req; TRY self.kind := req.value (self.kind, req.start + req.dur); EXCEPT Prop.BadMethod (msg) => AnimServer.ReportError (msg); END; self.list := self.list.next; END; END MyAnimRequestQueue_Flush;
REVEAL Stack = PublicStack BRANDED OBJECT cnt : INTEGER; vals : REF ARRAY OF Kind; METHODS init (top : Kind) : Stack := InitStack; OVERRIDES push := PushStack; pop := PopStack; END; PROCEDUREInitStack (self : Stack; top : Kind) : Stack = BEGIN self.cnt := 0; self.vals := NEW (REF ARRAY OF Kind, 10); self.top := top; RETURN self; END InitStack; PROCEDUREPushStack (self : Stack; val : Kind) = BEGIN IF self.cnt >= LAST (self.vals^) THEN WITH tmp = NEW (REF ARRAY OF Kind, 2 * NUMBER (self.vals^)) DO SUBARRAY (tmp^, 0, NUMBER (self.vals^)) := self.vals^; self.vals := tmp; END; END; self.vals[self.cnt] := self.top; self.top := val; INC (self.cnt); END PushStack; PROCEDUREPopStack (self : Stack) : Kind = BEGIN DEC (self.cnt); self.top := self.vals[self.cnt]; RETURN self.top; END PopStack; BEGIN END LineTypeProp.