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
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];