G3dVolumeCmdsAImpl.mesa
Copyright Ó 1985, 1992 by Xerox Corporation. All rights reserved.
Bloomenthal, November 21, 1992 3:04 pm PST
DIRECTORY Commander, CommanderOps, Controls, Draw2d, G3dBasic, G3dCubeDraw, G3dDraw, G3dMatrix, G3dOctree, G3dTool, Imager, MessageWindow, Rope, ViewerClasses;
G3dVolumeCmdsAImpl:
CEDAR
PROGRAM
IMPORTS CommanderOps, Controls, G3dCubeDraw, G3dDraw, G3dOctree, G3dTool, Draw2d, Imager, MessageWindow, Rope
~
BEGIN
OPEN G3dOctree;
Viewer: TYPE ~ ViewerClasses.Viewer;
Context: TYPE ~ Imager.Context;
Control: TYPE ~ Controls.Control;
ClickProc: TYPE ~ Controls.ClickProc;
Matrix: TYPE ~ G3dMatrix.Matrix;
Cube Drawing
DrawData: TYPE ~ REF DrawDataRec;
DrawDataRec:
TYPE ~
RECORD [
tool: G3dTool.Tool ¬ NIL, -- parent viewer
pendant: BOOL ¬ FALSE, -- if desired
labels: BOOL ¬ FALSE, -- if desired
lineThickness: Control ¬ NIL, -- line drawing thickness
cube: Cube ¬ NIL, -- the parent cube
fancy: BOOL ¬ FALSE -- draw it fancy or simple?
];
G3dCubeDrawCube: Commander.CommandProc ~ {
argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd];
d: DrawData ~ NEW[DrawDataRec];
d.fancy ¬ argv.argc =2 AND Rope.Find[argv[1], "-Fancy", 0, FALSE] # -1;
d.lineThickness ¬ Controls.NewControl["line",, d,, 10.0, 1.0, LineThickness];
d.tool ¬ G3dTool.MakeTool[
name: IF d.fancy THEN "A Fancy Volume Cube" ELSE "A Simple Volume Cube",
extraButtons:
LIST[
B["Pendant-Off", TogglePendant, d],
B["Labels-Off", ToggleLabels, d]],
graphicsHeight: 400,
client: [draw: Draw, data: d]];
d.cube ¬ G3dOctree.NewCube[0.4, [-0.15, 0.0, 0.]];
};
LineThickness: Controls.ControlProc ~ {
d: DrawData ~ NARROW[control.clientData];
IF control.mouse.button = right THEN G3dTool.Repaint[d.tool];
};
ToggleLabels: ClickProc ~ {
d: DrawData ~ NARROW[clientData];
d.labels ¬ NOT d.labels;
Controls.ButtonToggle[d.tool.outerData, d.labels, "Labels-On", "Labels-Off"];
IF mouseButton = blue THEN G3dTool.Repaint[d.tool];
};
TogglePendant: ClickProc ~ {
d: DrawData ~ NARROW[clientData];
d.pendant ¬ NOT d.pendant;
Controls.ButtonToggle[d.tool.outerData, d.pendant, "Pendant-On", "Pendant-Off"];
IF mouseButton = blue THEN G3dTool.Repaint[d.tool];
};
Draw: G3dTool.DrawProc ~ {
d: DrawData ~ NARROW[clientData];
IF d.lineThickness.value # 1.0 THEN Imager.SetStrokeWidth[context, d.lineThickness.value];
IF d.fancy
THEN G3dCubeDraw.FancyCube[context, d.cube, view, vp, d.labels]
ELSE {
pairs: OctantPairs ¬ G3dCubeDraw.TransformOctants[d.cube, view];
G3dCubeDraw.SimpleCubeFromPairs[context, pairs, d.cube];
IF d.labels THEN G3dCubeDraw.LabelOctants[context, pairs];
};
IF d.pendant
THEN G3dDraw.Pendant[context, view, 0.07, 0.5, 0.35, ["r", "t", "f", "l", "b", "n"]];
};
Reading a Volume
ReadData: TYPE ~ REF ReadDataRec;
ReadDataRec:
TYPE ~
RECORD [
tool: G3dTool.Tool ¬ NIL, -- viewer for graphical display
root: Cube ¬ NIL -- the parent cube
];
VolumeRead: Commander.CommandProc ~ {
argv: CommanderOps.ArgumentVector ¬ CommanderOps.Parse[cmd];
IF argv.argc # 2
THEN RETURN[$Failure, "usage: VolumeRead <fileName>"]
ELSE {
d: ReadData ~ NEW[ReadDataRec];
d.root ¬ G3dOctree.ReadCubesFromFile[argv[1]];
IF d.root = NIL THEN RETURN[$Failure, Rope.Cat["Can't read ", argv[1], "."]];
d.tool ¬ G3dTool.MakeTool[
name: Rope.Concat["Volume Read ", argv[1]],
graphicsHeight: 400,
client: [draw: ReadDrawProc, data: d]];
};
};
ReadDrawProc: G3dTool.DrawProc ~ {
Action:
PROC ~ {
cubeProc: CubeProc ~ {
G3dCubeDraw.SimpleCube[
context, cube, view, vp, TRUE, IF cube.terminal THEN solid ELSE dashed];
};
G3dOctree.Apply[d.root, cubeProc];
};
d: ReadData ~ NARROW[clientData];
Draw2d.DoWithBuffer[context, Action];
};
A Cube's Neighborhood
NeighborsData: TYPE ~ REF NeighborsDataRec;
NeighborsDataRec:
TYPE ~
RECORD [
tool: G3dTool.Tool,
parent: Cube ¬ NIL, -- the parent cube
new: Neighborhood, -- the moving cube
old: Neighborhood -- where it last was
];
VolumeNeighbors: Commander.CommandProc ~ {
d: NeighborsData ~ NEW[NeighborsDataRec];
G3dOctree.RecursivelySubdivide[d.parent, 2];
d.new ¬ G3dOctree.Move[d.new[c] ¬ G3dOctree.FirstTerminalKid[d.parent], c];
d.tool ¬ G3dTool.MakeTool[
name: "Volume Neighbors",
extraButtons: LIST[
B["l",Nmov,d],B["r",Nmov,d],B["b",Nmov,d],B["t",Nmov,d],B["n",Nmov,d],B["f",Nmov,d]],
graphicsHeight: 400,
client: [draw: NeighborsDrawProc, data: d]];
};
NeighborsDrawProc: G3dTool.DrawProc ~ {
Show:
PROC [color: Imager.Color, n: Neighborhood] ~ {
IF n[c] = NIL THEN RETURN;
Imager.SetColor[context, color];
G3dCubeDraw.SimpleCube[context, n[c], view, vp, FALSE, solid];
G3dCubeDraw.LabelCube[context, n[c], c, view, vp];
};
d: NeighborsData ~ NARROW[clientData];
IF whatChanged =
NIL
THEN {
G3dCubeDraw.RecursiveCubes[context, d.parent, view, vp, solid, FALSE];
G3dCubeDraw.LabelOctants[context, G3dCubeDraw.TransformOctants[d.parent, view]];
}
ELSE Show[Imager.white, d.old];
Show[Imager.black, d.new];
};
NeighborsCamera: Controls.ControlProc ~ {
d: NeighborsData ~ NARROW[clientData];
IF RespondNow[control] THEN G3dTool.Repaint[d.tool];
};
Nmov: ClickProc ~ {
d: NeighborsData ~ NARROW[clientData];
direction: Direction ~ G3dOctree.DirectionFromRope[NARROW[parent, Viewer].name];
newer: Neighborhood ~ G3dOctree.Move[d.new[c], direction];
IF newer[c] = NIL THEN Flash["Can't move in that direction."]
ELSE {
d.old ¬ d.new;
d.new ¬ newer;
G3dTool.Repaint[d.tool];
};
};
Adding/Deleting a Cube
AddDelData: TYPE ~ REF AddDelDataRec;
AddDelDataRec:
TYPE ~
RECORD [
tool: G3dTool.Tool ¬ NIL, -- parent viewer
root: Cube ¬ NIL, -- the parent cube
cube: Cube ¬ NIL -- the moving cube
];
VolumeAddDel: Commander.CommandProc ~ {
L: PROC [r: ROPE] RETURNS [Controls.Button] ~ {RETURN[B[r, Amov, d]]};
d: AddDelData ~ NEW[AddDelDataRec];
d.root ¬ G3dOctree.NewCube[0.4];
G3dOctree.RecursivelySubdivide[d.root, 1];
d.cube ¬ G3dOctree.FirstTerminalKid[d.root];
d.tool ¬ G3dTool.MakeTool[
name: "Volume AddDel",
extraButtons: LIST[L["L"], L["R"], L["B"], L["T"], L["N"], L["F"],B["Add", Add], B["Del", Del]],
graphicsHeight: 400,
client: [draw: AddDelDrawProc, data: d]];
};
AddDelDrawProc: G3dTool.DrawProc ~ {
cubeProc: CubeProc ~ {G3dCubeDraw.SimpleCube[context, cube, view]};
d: AddDelData ~ NARROW[clientData];
G3dOctree.ApplyToTerminal[d.root, cubeProc];
G3dCubeDraw.SimpleCube[context, d.cube, view, vp, FALSE, solid];
G3dDraw.Pendant[context, view, .07, .7, .7, ["r", "t", "f", "l", "b", "n"]];
};
Amov: ClickProc ~ {
d: AddDelData ~ NARROW[clientData];
direction: Direction ~ G3dOctree.DirectionFromRope[NARROW[parent, Viewer].name];
cube: Cube ~ G3dOctree.Neighbor[d.cube, direction];
IF cube = NIL THEN Flash["Can't move in that direction."]
ELSE {
d.cube ¬ cube;
G3dTool.Repaint[d.tool];
};
};
GetFace:
PROC [t: G3dTool.Tool]
RETURNS [face: Face] ~ {
Controls.TypescriptWrite[t.typescript, "Face: "];
face ¬ G3dOctree.FaceFromRope[Controls.TypescriptRead[t.typescript]];
};
Add: ClickProc ~ {
d: AddDelData ~ NARROW[clientData];
face: Face ¬ GetFace[d.tool];
cube: Cube ¬ G3dOctree.AddCube[d.cube, face];
IF cube = NIL THEN Flash["No cube in that direction."]
ELSE {
d.cube ¬ cube;
G3dTool.Repaint[d.tool];
};
};
Del: ClickProc ~ {
d: AddDelData ~ NARROW[clientData];
face: Face ¬ GetFace[d.tool];
cube: Cube ¬ G3dOctree.FaceNeighbor[d.cube, face];
IF cube = NIL THEN Flash["No cube in that direction."]
ELSE {
G3dOctree.DeleteCube[cube];
G3dTool.Repaint[d.tool];
};
};
Support Procedures
B:
PROC [
name: ROPE ¬ NIL,
proc: ClickProc ¬ NIL,
data: REF ANY ¬ NIL,
row, x, y, w, h: INTEGER ¬ 0,
fork: BOOL ¬ TRUE,
doc: ROPE ¬ NIL,
guarded: BOOL ¬ FALSE,
font: Imager.Font ¬ NIL,
style: ATOM ¬ $BlackOnWhite]
RETURNS [b: Controls.Button]
~ {
b ¬ Controls.ClickButton[name, proc, data, row, x, y, w, h, fork, guarded, doc, font, style];
};
RespondNow:
PROC [control: Control]
RETURNS [
BOOL] ~ {
RETURN[control.mouse.button = right AND control.mouse.state # up];
};
Flash:
PROC [message:
ROPE] ~ {
MessageWindow.Append[message, TRUE];
MessageWindow.Blink[];
};
Start Code
G3dTool.Register["VolumeAddDel", VolumeAddDel, "add/delete a cube."];
G3dTool.Register["CubeDraw", G3dCubeDrawCube, "draw a cube [-fancy]."];
G3dTool.Register["VolumeNeighbors", VolumeNeighbors, "show cube's neighbors."];
G3dTool.Register["VolumeRead", VolumeRead, "VolumeRead <fileName>."];