MODULE*************************************************************************** TypeRealProp EXPORTSRealProp ,RealPropPrivate ,RealPropProxy ; IMPORT Anim3D, AnimHandle, AnimHandlePrivate, AnimRequestQueue, AnimRequestQueuePrivate, AnimServer, GraphicsBase, GraphicsBasePrivate, Prop, PropPrivate;
Name
***************************************************************************
REVEAL Name = PrivateName BRANDED OBJECT default : Base; OVERRIDES init := InitName; bind := BindName; makeProxy := MakeProxyName; push := PushName; pop := PopName; newStack := NewStack; getState := GetState; END; PROCEDURE*************************************************************************** TypeInitName (self : Name; default : Base) : 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) : Base = 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) : Base RAISES {Prop.BadMethod} = BEGIN RETURN self.beh.value (Anim3D.Now ()); END GetVal; PROCEDUREValueVal (self : Val; time : LONGREAL) : Base 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 p : Base; OVERRIDES init := InitConstBeh; set := SetConstBeh; value := ValueConstBeh; END; PROCEDURE*************************************************************************** TypeInitConstBeh (self : ConstBeh; p : Base) : ConstBeh = BEGIN EVAL Beh.init (self); self.p := p; IF ConstBehPM # NIL THEN ConstBehPM (self); END; RETURN self; END InitConstBeh; PROCEDURESetConstBeh (self : ConstBeh; p : Base) = BEGIN self.p := p; END SetConstBeh; PROCEDUREValueConstBeh ( self : ConstBeh; <* UNUSED *> time : LONGREAL) : Base = BEGIN RETURN self.p; END ValueConstBeh; PROCEDURENewConst (p : Base) : Val = BEGIN RETURN NEW (Val).init (NEW (ConstBeh).init (p)); 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) : Base RAISES {Prop.BadMethod} = BEGIN RETURN self.compute (time); END ValueAsyncBeh; PROCEDUREComputeAsyncBeh (self : AsyncBeh; time : LONGREAL) : Base RAISES {Prop.BadMethod} = BEGIN IF self.proxy # NIL THEN RETURN NARROW (self.proxy, AsyncBehProxy).compute (time); ELSE RAISE Prop.BadMethod("RealProp.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) : Base 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("RealProp.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) : Base RAISES {Prop.BadMethod} = BEGIN IF self.proxy # NIL THEN RETURN NARROW (self.proxy, DepBehProxy).compute (time); ELSE RAISE Prop.BadMethod("RealProp.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; linChangeTo := LinChangeTo; linChangeBy := LinChangeBy; END; PROCEDURE*************************************************************************** Request Subtypes ***************************************************************************InitSyncBeh (self : SyncBeh; ah : AnimHandle.T; p : Base) : SyncBeh = BEGIN EVAL Beh.init (self); self.queue := NEW (MyAnimRequestQueue).init (ah, p); IF SyncBehPM # NIL THEN SyncBehPM (self); END; RETURN self; END InitSyncBeh; PROCEDUREValueSyncBeh (self : SyncBeh; time : LONGREAL) : Base 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; PROCEDURELinChangeTo (self : SyncBeh; p : Base; start : REAL; dur : REAL) RAISES {Prop.BadInterval} = BEGIN self.queue.insert (NEW (LinChangeToReq).init (start, dur, p)); END LinChangeTo; PROCEDURELinChangeBy (self : SyncBeh; p : Base; start : REAL; dur : REAL) RAISES {Prop.BadInterval} = BEGIN self.queue.insert (NEW (LinChangeByReq).init (start, dur, p)); END LinChangeBy; PROCEDURENewSync (ah : AnimHandle.T; p : Base) : Val = BEGIN RETURN NEW (Val).init (NEW (SyncBeh).init (ah, p)); END NewSync;
REVEAL Request = PublicRequest BRANDED OBJECT OVERRIDES init := InitRequest; value := ValueRequest; END; PROCEDURE*************************************************************************** Animation queue for synchronous real 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 : Base; reltime : REAL) : Base RAISES {Prop.BadMethod} = BEGIN IF self.proxy # NIL THEN RETURN NARROW (self.proxy, RequestProxy).value (startval, reltime); ELSE RAISE Prop.BadMethod("BooleanProp.Request.value method is undefined"); END; END ValueRequest; TYPE LinChangeToReq = Request BRANDED OBJECT p : Base; METHODS init (start, dur : REAL; val : Base) : LinChangeToReq := LinChangeToReqInit; OVERRIDES value := LinChangeToReqValue; END; PROCEDURELinChangeToReqInit (self : LinChangeToReq; start, dur : REAL; val : Base) : LinChangeToReq = BEGIN EVAL Request.init (self, start, dur); self.p := val; RETURN self; END LinChangeToReqInit; PROCEDURELinChangeToReqValue (self : LinChangeToReq; startval : Base; reltime : REAL) : Base = VAR fraction : REAL; BEGIN IF self.dur # 0.0 THEN fraction := (reltime - self.start) / self.dur; ELSE fraction := 1.0; END; RETURN startval + (self.p - startval) * fraction; END LinChangeToReqValue; TYPE LinChangeByReq = Request BRANDED OBJECT p : Base; METHODS init (start, dur : REAL; val : Base) : LinChangeByReq := LinChangeByReqInit; OVERRIDES value := LinChangeByReqValue; END; PROCEDURELinChangeByReqInit (self : LinChangeByReq; start, dur : REAL; val : Base) : LinChangeByReq = BEGIN EVAL Request.init (self, start, dur); self.p := val; RETURN self; END LinChangeByReqInit; PROCEDURELinChangeByReqValue (self : LinChangeByReq; startval : Base; reltime : REAL) : Base = VAR fraction : REAL; BEGIN IF self.dur # 0.0 THEN fraction := (reltime - self.start) / self.dur; ELSE fraction := 1.0; END; RETURN startval + self.p * fraction; END LinChangeByReqValue;
TYPE MyAnimRequestQueue = AnimRequestQueue.T BRANDED OBJECT p : Base; (* The initial value of the pv *) METHODS init (ah : AnimHandle.T; p : Base) : MyAnimRequestQueue := MyAnimRequestQueue_Init; value (time : LONGREAL) : Base RAISES {Prop.BadMethod} := MyAnimRequestQueue_Value; OVERRIDES flush := MyAnimRequestQueue_Flush; END; PROCEDURE*************************************************************************** Stack ***************************************************************************MyAnimRequestQueue_Init (self : MyAnimRequestQueue; ah : AnimHandle.T; p : Base) : MyAnimRequestQueue = BEGIN EVAL AnimRequestQueue.T.init (self, ah); self.p := p; RETURN self; END MyAnimRequestQueue_Init; PROCEDUREMyAnimRequestQueue_Value (self : MyAnimRequestQueue; time : LONGREAL) : Base RAISES {Prop.BadMethod} = VAR l := self.list; req : Request; p : Base; reltime : REAL; BEGIN IF self.ah.activated THEN reltime := FLOAT (time - self.ah.starttime); p := self.p; WHILE l # NIL DO req := l.req; IF reltime < req.start THEN RETURN p; ELSIF reltime < req.start + req.dur THEN RETURN req.value (p, reltime); ELSE p := req.value (p, req.start + req.dur); l := l.next; END; END; RETURN p; ELSE RETURN self.p; END; END MyAnimRequestQueue_Value; PROCEDUREMyAnimRequestQueue_Flush (self : MyAnimRequestQueue) = VAR req : Request; BEGIN WHILE self.list # NIL DO req := self.list.req; TRY self.p := req.value (self.p, 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 Base; METHODS init (top : Base) : Stack := InitStack; OVERRIDES push := PushStack; pop := PopStack; END; PROCEDUREInitStack (self : Stack; top : Base) : Stack = BEGIN self.cnt := 0; self.vals := NEW (REF ARRAY OF Base, 10); self.top := top; RETURN self; END InitStack; PROCEDUREPushStack (self : Stack; val : Base) = BEGIN IF self.cnt >= LAST (self.vals^) THEN WITH tmp = NEW (REF ARRAY OF Base, 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) : Base = BEGIN DEC (self.cnt); self.top := self.vals[self.cnt]; RETURN self.top; END PopStack; BEGIN END RealProp.