G3dToolCmdsImpl.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, October 20, 1992 10:39 pm PDT
Heckbert, August 9, 1988 5:51:51 pm PDT
Glassner, July 9, 1990 3:50:53 pm PDT
Shoemake, November 7, 1989 0:15:49 am PST
DIRECTORY ColumnLs, Commander, CommanderOps, Convert, FileNames, FS, G2dBasic, G3dBasic, G3dTimeTrees, G3dTool, IO, PFS, PreDebug, Real, Rope, UserProfile, ViewerOps;
G3dToolCmdsImpl: CEDAR PROGRAM
IMPORTS ColumnLs, Commander, CommanderOps, Convert, FileNames, FS, G3dTimeTrees, G3dTool, IO, PFS, PreDebug, Real, Rope, UserProfile, ViewerOps
EXPORTS G3dTool
~ BEGIN
Imported Types
ROPE: TYPE ~ Rope.ROPE;
Tool: TYPE ~ G3dTool.Tool;
3d Registration and Dispatch
Op:   TYPE ~ RECORD [proc: Commander.CommandProc, name, usage: ROPE];
OpSequence:  TYPE ~ RECORD [length: NAT ¬ 0, s: SEQUENCE maxLength: NAT OF Op];
ops:   REF OpSequence ¬ NIL;
Eq: PROC [r1, r2: ROPE] RETURNS [BOOL] ~ {RETURN[Rope.Equal[r1, r2, FALSE]]};
Register: PUBLIC PROC [name: ROPE, proc: Commander.CommandProc, usage: ROPE] ~ {
op: Op ¬ [proc, name, usage];
IF proc # NIL THEN op.usage ¬ Rope.Concat[" ", usage];
IF ops # NIL THEN
FOR n: NAT IN [0..ops.length) DO
IF NOT Eq[name, ops[n].name] THEN LOOP;
ops[n] ¬ op;
RETURN;
ENDLOOP;
IF ops = NIL THEN ops ¬ NEW[OpSequence[10]];
IF ops.length = ops.maxLength THEN {
old: REF OpSequence ~ ops;
ops ¬ NEW[OpSequence[Real.Round[1.3*old.length]]];
FOR i: NAT IN [0..old.length) DO ops[i] ¬ old[i]; ENDLOOP;
ops.length ¬ old.length;
};
ops[ops.length] ¬ op;
ops.length ¬ ops.length+1;
};
PrintOps: PROC [cmd: Commander.Handle ¬ NIL] ~ {
IF ops = NIL
THEN IO.PutRope[cmd.out, "no registered commands\n"]
ELSE {
Alphabetize: PROC [ropes: LIST OF ROPE] RETURNS [ret: LIST OF ROPE] ~ {
IF ropes # NIL THEN {
l: LIST OF ROPE ¬ ropes.rest;
ret ¬ LIST[ropes.first];
WHILE l # NIL DO
name: ROPE ¬ l.first;
rest: LIST OF ROPE ¬ l.rest;
IF Rope.Compare[ret.first, name, FALSE] = greater
THEN ret ¬ CONS[name, ret]
ELSE FOR r: LIST OF ROPE ¬ ret, r.rest DO
IF r.rest = NIL OR Rope.Compare[r.rest.first, name, FALSE] = greater
THEN {l.rest ¬ r.rest; r.rest ¬ l; EXIT};
ENDLOOP;
l ¬ rest;
ENDLOOP;
};
};
names: LIST OF ROPE;
FOR n: NAT IN [0..ops.length) DO
IF ops[n].proc # NIL THEN names ¬ CONS[ops[n].name, names];
ENDLOOP;
IO.PutF[cmd.out, "\t\t\t\t\t\t\t%l3d commands%l\n\n", IO.rope["bz"], IO.rope["BZ"]];
ColumnLs.ColumnateNames[cmd, Alphabetize[names],, fixed, TRUE,, " "];
IO.PutRope[cmd.out, "\n"];
};
};
3d Imaging Commands Using G3dTool
IsItError: ERROR = CODE;
ToolCmd: Commander.CommandProc ~ {
t: Tool;
{
ENABLE {
UNCAUGHT => {msg ¬ "unknown error"; GOTO Failure};
IsItError => {msg ¬ usage; GOTO Failure};
PFS.Error => {msg ¬ error.explanation; GOTO Failure};
Convert.Error => {msg ¬ "Conversion error"; GOTO Failure};
};
GetInteger: PROC [index: INT] RETURNS [i: INT] ~ {i ¬ Convert.IntFromRope[args[index]]};
IsIt: PROC [rope: ROPE, argsNeeded: INT] RETURNS [b: BOOL] ~ {
IF index >= args.argc THEN RETURN[FALSE];
b ¬ Eq[rope, args[index]];
IF b AND args.argc <= index+argsNeeded THEN ERROR IsItError;
};
SkipArgs: PROC [nSkip: INT] ~ {index ¬ index+nSkip};
scene, shape, funct: ROPE;
index, nViews: INTEGER ¬ 1;
arcBalls: BOOL ¬ UserProfile.Boolean["3dTool.ArcBalls", TRUE];
args: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd];
WHILE index < args.argc DO
SELECT TRUE FROM
IsIt["-shape", 1]   => {shape ¬ args[index+1];      SkipArgs[2]};
IsIt["-scene", 1]   => {scene ¬ args[index+1];      SkipArgs[2]};
IsIt["-noArcBalls", 0] => {arcBalls ¬ FALSE;        SkipArgs[1]};
IsIt["-useArcBalls", 0] => {arcBalls ¬ TRUE;        SkipArgs[1]};
IsIt["-nViews", 1]  => {nViews ¬ GetInteger[index+1];    SkipArgs[2]};
ENDCASE     => {IF funct = NIL THEN funct ¬ args[index]; SkipArgs[1]};
ENDLOOP;
IF funct # NIL
THEN {
Reject: PROC [why: ROPE] RETURNS [reject: BOOL ¬ FALSE] ~ {
msg ¬ why;
result ¬ $Failure;
};
DoOp: PROC ~ {
RemoveArgument: PROC [key: ROPE] ~ {
once: BOOL ¬ FALSE;
tmp: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd];
cmd.commandLine ¬ NIL;
FOR i: INTEGER IN [1..tmp.argc) DO -- args[0] is command name
IF NOT once AND Eq[tmp[i], key]
THEN once ¬ TRUE
ELSE cmd.commandLine ¬ Rope.Cat[cmd.commandLine, " ", tmp[i]]
ENDLOOP;
};
cmd.command ¬ funct;
RemoveArgument["3d"];
RemoveArgument[funct];
[result, msg] ¬ op.proc[cmd];
};
FunctArg: PROC RETURNS [r: ROPE ¬ NIL] ~ {
FOR i: INT IN [0..args.argc-1) DO
IF Eq[args[i], funct] THEN RETURN[args[i+1]];
ENDLOOP;
};
op: Op;
IF ops # NIL THEN FOR i: INTEGER IN [0..ops.length) DO
IF Eq[funct, ops[i].name] THEN {op ¬ ops[i]; EXIT};
ENDLOOP;
SELECT TRUE FROM
Eq[funct, "?"] => PrintOps[cmd];
op.proc = NIL => RETURN[$Failure, Rope.Concat["no such funct: ", funct]];
Eq[FunctArg[], "?"] AND NOT Eq[op.name, "UseCG6"] =>
RETURN[$Failure, Rope.Concat["Usage:", op.usage]];
ENDCASE => [] ¬ PreDebug.Protect[DoOp, Reject];
}
ELSE {
name: ROPE ¬ Rope.Substr[cmd.command, Rope.FindBackward[cmd.command, "/"]+1];
IF shape # NIL THEN name ¬ Rope.Concat["3d ", shape];
t ¬ G3dTool.MakeTool[name:name, nViews:nViews, noOpen:TRUE, useArcBalls:arcBalls];
IF shape # NIL THEN {
s: ROPE ¬ FileNames.ResolveRelativePath[shape];
IF (msg ¬ G3dTool.ReadFromShapeFile[t, s, TRUE]) # NIL THEN GOTO Failure;
G3dTool.GetShape[t, FileNames.GetShortName[shape]].selected ¬ TRUE;
};
t.cmd ¬ cmd;
IF scene # NIL AND NOT DoScene[scene, cmd, t] THEN RETURN[$Failure];
ViewerOps.OpenIcon[t.outer];
};
EXITS Failure => {
IF t # NIL THEN ViewerOps.DestroyViewer[t.outer];
result ¬ $Failure;
};
};
};
DoScene: PROC [sceneFile: ROPE, cmd: Commander.Handle, t: Tool ¬ NIL]
RETURNS [ok: BOOL ¬ TRUE]
~ {
ENABLE {
FS.Error => {IO.PutF1[cmd.out, "%g\n", IO.rope[error.explanation]]; ok ¬ FALSE; CONTINUE};
G3dScene.ParseError => {
ok ← FALSE;
IO.PutF[cmd.out, Rope.Cat[explanation, "\n"]];
ViewerOps.DestroyViewer[t.outer];
CONTINUE};
};
ps: G3dScene.ParseState;
op: ROPE ¬ PFS.RopeOpen[PFS.PathFromRope[sceneFile]].rope; -- ignore Tioga comments
IF t = NIL THEN t ¬ G3dTool.MakeTool[
name: Rope.Concat["3dScene ", sceneFile], nViews: 0, useArcBalls: TRUE];
t.cmd ¬ cmd;
G3dTool.Context3dOk[t];
G3dScene.RegisterProc["Draw", Draw, t];
ps ← G3dScene.Parse[t.context3d, op, cmd.out,,, sceneFile];
t.timeTree ← ps.timeTree;
t.focusNode ← ps.timeTree.root;
t.shapes ← ps.context3d.shapes;
G3dTimeTrees.ReportTimeTree[t.timeTree];
G3dTool.PrepareForDrawing[t];
G3dTool.UpdateCamera[t];
};
Start Code
usage: ROPE ~
"Usage: 3d [function] [tool option]
 no specified function creates a generic 3d tool
 type '3d ?' to list functions
 tool options include:
  -shape  <shape file>
  -scene  <scene description file>
  -nViews  <number of viewports>
  -noArcBalls [default false or as given by user profile]
  -useArcBalls [default true or as given by user profile]";
Commander.Register["3d", ToolCmd, Rope.Concat["\n", usage]];
END.
..
The Wayside
lineTool: BOOL ← Rope.Equal[name, "3dLine", FALSE];
ops: IF lineTool
THEN [animation: TRUE, stop: TRUE, lf: TRUE, shape: TRUE, interpress: TRUE]
ELSE [TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE],
IF interpret.rope # NIL THEN t.client ← [data: G3dInterpret.MakeInterpretTool[
interpret.rope, right, TRUE, t ! G3dInterpret.Error => {msg ← reason; GOTO Quit}]];
sceneUsage: ROPE ~ "Usage: 3dScene <Scene Filename>
 Parse the scene file.";
SceneCmd: Commander.CommandProc ~ {
argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd];
SELECT TRUE FROM
argv.argc # 2 => RETURN[$Failure, sceneUsage];
Rope.Equal[argv[1], "?"] => RETURN[msg: sceneUsage];
ENDCASE => [] ¬ DoScene[argv[1], cmd];
};
Draw: G3dScene.SceneProc ~ {G3dTool.Repaint[NARROW[data]]};
InterpretCmd: Commander.CommandProc ~ {
mesa, noLog: Args.Arg;
[mesa, noLog] ← Args.ArgsGet[cmd, "[s-noLog%b" !
Args.Error => {msg ← reason; GOTO Bad}];
IF mesa.rope = NIL THEN RETURN[$Failure, interpretUsage];
IF Rope.Equal[mesa.rope, "?"] THEN RETURN[msg: interpretUsage];
[] ← G3dInterpret.MakeInterpretTool[mesa.rope, left, NOT noLog.bool
! G3dInterpret.Error => {msg ← reason; GOTO Bad}];
EXITS Bad => RETURN[$Failure, msg];
};
interpretUsage: ROPE ~ "Usage: 3dInterpret <Mesa Filename> [-noLog]
 Interpret the mesa file.";
Register["Scene",  SceneCmd,  Rope.Cat["\n", sceneUsage]];
Register["3dTest",  ToolCmd,   Rope.Cat["\n", toolUsage]];
Register["3dLine",  ToolCmd,   Rope.Cat["\n", toolUsage]];
Register["3dInterpret", InterpretCmd, Rope.Cat["\n", interpretUsage]];