G3dAnimateImpl.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, July 22, 1992 11:18 pm PDT
DIRECTORY BasicTime, CedarProcess, Commander, CommandTool, Convert, G3dAnimate, IO, Process, Rope, ThisMachine;
G3dAnimateImpl: CEDAR MONITOR
IMPORTS BasicTime, CedarProcess, Commander, CommandTool, Convert, IO, Process, Rope, ThisMachine
EXPORTS G3dAnimate
~ BEGIN
Types
ROPE:     TYPE ~ Rope.ROPE;
Status:    TYPE ~ RECORD [
start, finish:     BasicTime.GMT ¬ BasicTime.nullGMT,
done:       BOOL ¬ FALSE];
StatusSequence:  TYPE ~ REF StatusSequenceRep;
StatusSequenceRep: TYPE ~ RECORD [element: SEQUENCE length: CARDINAL OF Status];
Registration:   TYPE ~ REF RegistrationRep;
RegistrationRep:  TYPE ~ RECORD [
name:       ROPE ¬ NIL,
estMinutesPerFrame:  NAT ¬ 60,
status:       StatusSequence ¬ NIL];
Errors
Error:     PUBLIC SIGNAL [code: ATOM, reason: ROPE] = CODE;
Animation Control
GetRegistration: PROC [animationName: ROPE] RETURNS [r: Registration ¬ NIL] ~ {
FOR l: LIST OF Registration ¬ registry, l.rest WHILE l # NIL DO
IF Rope.Equal[l.first.name, animationName, FALSE] THEN RETURN[l.first];
ENDLOOP;
};
GetFrameNumber: PUBLIC ENTRY PROC [masterMachineName, animationName: ROPE]
RETURNS [INTEGER]
~ {
IF Rope.Equal[ThisMachine.Name[], masterMachineName]
THEN {
r: Registration ¬ GetRegistration[animationName];
IF r = NIL THEN Error[$NoSuchAnimation, Rope.Cat[animationName, " isn't registered"]];
FOR n: NAT IN [0..r.status.length) DO
IF r.status[n].start # BasicTime.nullGMT THEN LOOP;
r.status[n].start ¬ BasicTime.Now[];
RETURN[n];
ENDLOOP;
RETURN[-1];
}
ELSE {
Do RPC of GetFrameNumber on masterMachineName
RETURN[-1];
};
};
FrameDone: PUBLIC ENTRY PROC [masterMachineName, animationName: ROPE, frame: NAT] ~ {
IF Rope.Equal[ThisMachine.Name[], masterMachineName]
THEN {
r: Registration ¬ GetRegistration[animationName];
IF r = NIL THEN Error[$NoSuchAnimation, Rope.Cat[animationName, " isn't registered"]];
IF frame >= r.status.length THEN Error[$BadFrame, IO.PutFR["%g is too large; %g has only %g frames", IO.int[frame], IO.rope[animationName], IO.int[r.status.length]]];
r.status[frame].done ¬ TRUE;
r.status[frame].finish ¬ BasicTime.Now[];
RETURN;
}
ELSE {
Do RPC of FrameDone on masterMachineName
};
};
RegisterAnimation: PUBLIC ENTRY PROC [name: ROPE, nFrames, estMinutesPerFrame: NAT] ~ {
r: Registration ¬ NEW[RegistrationRep ¬ [name, estMinutesPerFrame]];
r.status ¬ NEW[StatusSequenceRep[nFrames]];
FOR l: LIST OF Registration ¬ registry, l.rest WHILE l # NIL DO
IF Rope.Equal[l.first.name, name, FALSE] THEN {l.first ¬ r; RETURN};
IF l.rest = NIL THEN {l.rest ¬ LIST[r]; RETURN};
ENDLOOP;
};
UnRegisterAnimation: PUBLIC ENTRY PROC [name: ROPE] ~ {
previous: LIST OF Registration ¬ NIL;
FOR l: LIST OF Registration ¬ registry, l.rest WHILE l # NIL DO
IF NOT Rope.Equal[l.first.name, name, FALSE] THEN {previous ¬ l; LOOP};
IF previous = NIL THEN registry ¬ l.rest ELSE previous.rest ¬ l.rest;
RETURN;
ENDLOOP;
};
Watch: CedarProcess.ForkableProc ~ { -- reset status to unstarted if computation takes too long
DO
now: BasicTime.GMT ¬ BasicTime.Now[];
Process.Pause[Process.SecondsToTicks[300]];
FOR l: LIST OF Registration ¬ registry, l.rest WHILE l # NIL DO
FOR n: NAT IN [0..l.first.status.length) DO
s: Status ¬ l.first.status[n];
IF s.done OR s.start = BasicTime.nullGMT THEN LOOP;
IF BasicTime.Period[s.start, now] > 2.0*l.first.estMinutesPerFrame
THEN l.first.status[n].start ¬ BasicTime.nullGMT;
ENDLOOP;
ENDLOOP;
ENDLOOP;
};
Commands
registry: LIST OF Registration ¬ NIL;
AnimateMasterCmd: Commander.CommandProc ~ {
ENABLE Convert.Error => {msg ¬ "Bad conversion"; GOTO Bad};
a: CommandTool.ArgumentVector ¬ CommandTool.Parse[cmd];
IF a.argc # 3
THEN RETURN[$Failure, usage]
ELSE RegisterAnimation[a[1], Convert.IntFromRope[a[2]], Convert.IntFromRope[a[3]]];
EXITS Bad => RETURN [$Failure, msg];
};
Start Code
usage: ROPE ~
"Usage: 3dAnimateMaster <animation name> <# frames> <estMinutesPerFrame>
If initializing, just specify number of frames for this animation";
G3dTool.Register["3dAnimateMaster", AnimateMasterCmd, usage];
[] ¬ CedarProcess.Fork[Watch];
END.