File: SVEventImplB.mesa
Author: Eric Bier in October 1982
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by Bier on May 26, 1987 8:30:03 pm PDT
Contents: Code to respond to button presses made in an SVViewer
DIRECTORY
Atom, AtomButtonsTypes, BasicTime, Buttons, SVCastRays, Containers, CoordSys, SVRay, SVGraphics, DisplayListToTree, Feedback, FS, Imager, ImagerInterpress, InputFocus, IO, Labels, Matrix3d, Menus, MessageWindow, Preprocess3d, Random, Rope, SV2d, SV3d, SVAssembly, SVBasicTypes, SVEditUser, SVEvent, SVFileoutPoly, SVFiles, SVImage, SVInterfaceTypes, SVModelTypes, SVRayTypes, SVRefresh, SVScene, SVSceneTypes, SVSelect, SVSelections, SVCatScan, SVTransforms, SVUtility, SVViewersOnScene, SVViewerTool, SVViewerTools, SVWindow, TFO3d, ViewerClasses, ViewerTools;
SVEventImplB:
CEDAR
PROGRAM
IMPORTS Atom, BasicTime, Buttons, SVCastRays, CoordSys, SVRay, SVGraphics, DisplayListToTree, Feedback, FS, Imager, ImagerInterpress, InputFocus, IO, Labels, Matrix3d, MessageWindow, Preprocess3d, Random, Rope, SVAssembly, SVEditUser, SVFileoutPoly, SVFiles, SVImage, SVRefresh, SVScene, SVSelect, SVSelections, SVTransforms, SVUtility, SVViewersOnScene, SVViewerTools, SVWindow, TFO3d, ViewerTools
EXPORTS SVEvent =
BEGIN
Slice: TYPE = SVSceneTypes.Slice;
BoundBox: TYPE = SVBasicTypes.BoundBox;
BoundSphere: TYPE = SVBasicTypes.BoundSphere;
Camera: TYPE = SVModelTypes.Camera;
Classification: TYPE = SVRayTypes.Classification;
Color: TYPE = Imager.Color;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
CSGTree: TYPE = SVRayTypes.CSGTree;
DrawStyle: TYPE = SVModelTypes.DrawStyle;
EditToolData: TYPE = SVInterfaceTypes.EditToolData;
FeedbackData: TYPE = AtomButtonsTypes.FeedbackData;
Matrix4by4: TYPE = SV3d.Matrix4by4;
MouseButton: TYPE = Menus.MouseButton;
Point2d: TYPE = SV2d.Point2d;
Point3d: TYPE = SV3d.Point3d;
Primitive: TYPE = SVRayTypes.Primitive;
Ray: TYPE = SVRayTypes.Ray;
Scene: TYPE = SVSceneTypes.Scene;
Selection: TYPE = SVInterfaceTypes.Selection;
SelectionGenerator: TYPE = SVInterfaceTypes.SelectionGenerator;
SelectionType: TYPE = SVInterfaceTypes.SelectionType;
SkitterMode: TYPE = SVSceneTypes.SkitterMode;
CatScan: TYPE = SVCatScan.CatScan;
ToolData: TYPE = SVSceneTypes.ToolData;
Vector3d: TYPE = SV3d.Vector3d;
Viewer: TYPE = ViewerClasses.Viewer;
SVData: TYPE = SVInterfaceTypes.SVData;
DCProc: TYPE = SVInterfaceTypes.DCProc;
globalSceneStyleCount: NAT = 3;
globalSceneStyleArray:
ARRAY[1..globalSceneStyleCount]
OF Rope.
ROPE ←
["WireFrame", "Shaded", "Normals"];
ToIP:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
DoMakeInterpress:
SAFE
PROC [dc: Imager.Context] = {
pixelsPerMeter: REAL = 0.0254 / 72.0;
Imager.ScaleT[dc, pixelsPerMeter];
SVGraphics.Clip[dc, camera];
SVGraphics.SetQualityCamera[camera, quality]; -- make a high quality image
SVGraphics.ColorFilmCamera[camera, TRUE]; -- in color
SVRefresh.InterpressEntireScene[dc, svData];
SVGraphics.SetQualityCamera[camera, fast]; -- restore to fast mode for interactive editting
};
ipName: Rope.ROPE ← NARROW[event.rest.first];
camera: Camera ← svData.camera;
ToIPAux[svData, ipName, NARROW[event.first], DoMakeInterpress];
};
ToIPAux:
PUBLIC
PROC [svData: SVData, ipName: Rope.
ROPE, actionAtom:
ATOM, makeInterpress:
PROC [Imager.Context]] = {
ipRef: ImagerInterpress.Ref;
fullName: Rope.ROPE;
success: BOOL;
Timing Varables
startTime: BasicTime.GMT;
endTime: BasicTime.GMT;
totalTime: INT;
[fullName, success] ← SVUtility.GetInterpressFileName[ipName, svData.editToolData.originalWorkingDirectory, svData.feedback];
IF NOT success THEN RETURN;
ipRef ← ImagerInterpress.Create[fullName];
[fullName] ← FS.FileInfo[fullName]; -- append the version number
Feedback.PutF[svData.feedback, begin, "%g %g . . . ", [rope[Atom.GetPName[actionAtom]]], [rope[fullName]]];
startTime ← BasicTime.Now[];
ImagerInterpress.DoPage[ipRef, makeInterpress, 1.0];
ImagerInterpress.Close[ipRef];
endTime ← BasicTime.Now[];
totalTime ← BasicTime.Period[startTime, endTime];
Feedback.PutF[svData.feedback, end, " Done in time (%r)", [integer[totalTime]]];
};
StorePoly:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
editToolData: EditToolData ← NARROW[svData.editToolData];
wdir: Rope.ROPE;
success, confirmation: BOOL;
f: IO.STREAM;
picName: Rope.ROPE ← ViewerTools.GetSelectionContents[];
fullName: Rope.ROPE;
scene: Scene ← svData.scene;
IF Rope.Length[picName] = 0 THEN RETURN;
wdir ← editToolData.originalWorkingDirectory;
success ← TRUE;
[fullName,,] ←
FS.ExpandName[picName, wdir
!
FS.Error =>
IF error.group = user
THEN {
success ← FALSE;
CONTINUE;
}
];
IF NOT success THEN RETURN;
IF SVFiles.FileExists[fullName]
THEN {
confirmation ← MessageWindow.Confirm["Confirm overwrite of existing pic file"];
IF confirmation
THEN
f ← FS.StreamOpen[fullName, $create]
ELSE RETURN;
}
ELSE f ← FS.StreamOpen[fullName, $create];
Feedback.PutF[svData.feedback, begin, "Writing scene: %g to file: %g...", [rope[fullName]], [rope[fullName]]];
IF NOT success THEN RETURN;
SVFileoutPoly.StorePolyScene[scene, f, fullName];
Feedback.Append[svData.feedback, "Done", end];
}; -- end of StorePoly
Move: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = {
newMat: Matrix4by4;
target, movee: Selection;
target ← SVEditUser.GetTargetSelection[];
movee ← SVEditUser.GetMoveeSelection[];
IF target = NIL THEN ERROR;
IF target.assembly = NIL THEN RETURN;
IF movee = NIL THEN ERROR;
IF movee.assembly = NIL THEN RETURN;
If the two selections are in different viewers, then see if these viewers refer to different scenes. If so do a scene to scene copy before doing any aligning and abutting.
IF target.svData # movee.svData THEN {
targetPicture: ViewerPictureData ← NARROW[target.svData.viewerPicture.data];
moveePicture: ViewerPictureData ← NARROW[movee.svData.viewerPicture.data];
IF targetPicture.scene # moveePicture.scene THEN {
copyAssembly: Slice ← SVScene.MergeAssemblyIntoScene[movee.assembly, moveePicture.scene, targetPicture.scene.assembly, targetPicture.scene];
The new assembly has the same relationship to scene assembly as the last assembly had to its parent. This will do for now.
SVEvent.SceneNewVersion[target.svData];
SVEvent.DrawSceneInternal[NIL, target.svData, red, FALSE, FALSE];
SVEvent.DrawSceneInternal[NIL, movee.svData, red, FALSE, FALSE];
RETURN;
};
};
newMat ← Matrix3d.MakeRotateYMat[180];
SVTransforms.TugTransf[movee.assembly.coordSys, movee.coordSys, target.coordSys, newMat];
Rotate them so they are tangent in an exterior fashion.
SVEvent.SceneNewVersion[target.svData];
SVEvent.DrawSceneInternal[NIL, target.svData, red, FALSE, FALSE];
};
DrawColor:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
parent is the DrawColor button
SVWindow.RestoreScreenAndInvariants[$DrawColor, svData];
}; -- end of DrawColor
DrawBlackAndWhite:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVWindow.RestoreScreenAndInvariants[$DrawBlackAndWhite, svData];
}; -- end of DrawBlackAndWhite
SetFocalLength: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = {
svData.camera.focalLength ← SVViewerTools.GetReal[svData.textSection.focalLength, 1800];
}; -- end of SetFocalLength
PROMPTS
XYZPrompt:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
ViewerTools.SetSelection[svData.textSection.xyz];
};
PROMPTS WHICH CYCLE THROUGH POSSIBILITIES
CurrentStyle:
PUBLIC
PROC [svData: SVData]
RETURNS [style: DrawStyle] = {
SELECT globalSceneStyleArray[svData.sceneStyleIndex]
FROM
"WireFrame" => style ← wire;
"Shaded" => style ← shaded;
"Normals" => style ← normals;
"RayCast" => style ← rayCast;
ENDCASE => ERROR;
};
StylePrompt:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
newStyle: DrawStyle;
scene: Scene ← svData.scene;
svData.sceneStyleIndex ← IF svData.sceneStyleIndex = globalSceneStyleCount THEN 1 ELSE svData.sceneStyleIndex + 1;
Labels.Set[svData.textSection.viewStyle, globalSceneStyleArray[svData.sceneStyleIndex]];
SELECT globalSceneStyleArray[svData.sceneStyleIndex]
FROM
"WireFrame" => newStyle ← wire;
"Shaded" => newStyle ← shaded;
"Normals" => newStyle ← normals;
"RayCast" => newStyle ← rayCast;
ENDCASE => ERROR;
svData.camera.style ← newStyle;
};
ON/OFF SWITCHES
DoubleBuffer:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
button: Buttons.Button ← NARROW[svData.textSection.doubleBuffer];
IF svData.doubleBuffer
THEN {
svData.doubleBuffer ← NOT svData.doubleBuffer;
Buttons.SetDisplayStyle[button, $BlackOnWhite];
}
ELSE {
svData.doubleBuffer ← NOT svData.doubleBuffer;
Buttons.SetDisplayStyle[button, $WhiteOnBlack];
};
}; -- end of DoubleBuffer
ShowCoordsMode:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
button: Buttons.Button ← NARROW[svData.textSection.showCoords];
IF svData.showCoordSys
THEN {
svData.showCoordSys ← NOT svData.showCoordSys;
Buttons.SetDisplayStyle[button, $BlackOnWhite];
}
ELSE {
svData.showCoordSys ← NOT svData.showCoordSys;
Buttons.SetDisplayStyle[button, $WhiteOnBlack];
};
}; -- end of ShowCoordsMode
UTILITIES
Selected:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
This window has been selected. Show its Selected button as WhiteOnBlack.
solidViewer: Viewer ← svData.actionArea;
InputFocus.SetInputFocus[solidViewer];
SVViewersOnScene.ReSelectViewer[svData];
};
Deselected:
PUBLIC
PROC [svData: SVData] = {
This window has been deselected. Show its Selected button as BlackOnWhite.
IF svData = NIL THEN RETURN;
svData.textSection.isSelected ← FALSE;
Labels.SetDisplayStyle[svData.textSection.selected, $BlackOnWhite, TRUE];
};
KillSelectionsButton:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVSelections.KillSkitterAndSelections[svData.editToolData];
SVSelect.DeselectAll[svData.scene, normal];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, svData.scene];
};
DeleteJacksButton:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
scene: Scene ← svData.scene;
SVScene.DeleteAllPrimitivesOfClass["jack", scene, svData.feedback];
SVViewersOnScene.PaintSceneAllViewers[$PaintEntireScene, svData.editToolData, scene];
};
Input Notify Procs
SingleRay:
PUBLIC
PROC [svData: SVData, cameraPoint: Point2d] = {
color: Color;
xInt, yInt: INTEGER;
tree: CSGTree;
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
class: Classification;
rayWorld: Ray;
f: IO.STREAM ← Feedback.GetTypescriptStream[$Solidviews];
tree ← DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera];
color ← SVCastRays.SingleRay[cameraPoint, tree, scene.lightSources, camera, svData.feedback, TRUE];
f.PutF["[%g,%g]: ",[real[cameraPoint[1]]], [real[cameraPoint[2]]]];
TFO3d.FileoutColor[f, color];
f.PutChar[IO.CR];
[class, rayWorld] ← SVCastRays.SingleRay2[[xInt, yInt], tree, camera, TRUE, NIL, FALSE];
ClassToStream[f, class];
f.PutChar[IO.CR];
SVCastRays.SortClassByPrimitive[class];
ClassToStream[f, class];
f.PutChar[IO.CR];
SVRay.ReturnRayToPool[rayWorld];
f.PutChar[IO.CR];
SVCastRays.ReturnClassToPool[class];
};
ClassToStream:
PROC [f:
IO.
STREAM, class: Classification] = {
FOR i:
NAT
IN [1..class.count]
DO
f.PutF["(%g, %g) ", IO.rope[class.primitives[i].name], IO.real[class.params[i]]];
ENDLOOP;
};
PointAt: PUBLIC PROC [svData: SVData, cameraPoint: Point2d] = {
Adds a new assembly to the scene of class "CoordSys", isTool is true. The first one will be pointer.0, the second pointer.1 and so on. Pointer will be defined with respect to the parent of the assembly which we are pointing at. If we are not pointing at anything, don't create a pointer. Just return.
f: IO.STREAM ← Feedback.GetErrorStream[];
tree: CSGTree;
normal: Vector3d;
prim: Primitive;
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
class: Classification;
tree ← DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera];
class ← SVCastRays.SingleRay2[cameraPoint, tree, camera, TRUE, TRUE, f];
IF class.count = 0 THEN RETURN;
prim ← class.primitives[1];
normal ← class.normals[1];
};
DrawCatScan:
PUBLIC
PROC [svData: SVData, catScan: CatScan] = {
SVWindow.RestoreScreenAndInvariants[$DrawCatScan, svData];
};
DrawSelection:
PROC [dc: Imager.Context, svData: SVData, selection: Selection, selectionType: SelectionType, color: Color] = {
SVTransforms.TellAboutParent[selection.coordSys];
[] ← Imager.SetPaintMode[dc, invert];
Imager.SetColor[dc, color];
IF selectionType = movee THEN SVEvent.DrawOneCS[dc, svData, selection.coordSys]
ELSE SVEvent.DrawOneTargetCS[dc, svData, selection.coordSys];
};
RayCastProgress:
PUBLIC SVCastRays.NotifyOfProgressProc = {
PROC [currentY, minX, minY, maxX, maxY: REAL, clientData: REF ANY];
Draw a box of width 10 and length currentY-minY+1 with origin at (minX, minY)
svData: SVData ← NARROW[clientData];
svData.refresh.currentY ← currentY;
svData.refresh.minX ← minX;
svData.refresh.minY ← minY;
svData.refresh.maxX ← maxX;
svData.refresh.maxY ← maxY;
SVWindow.RestoreScreenAndInvariants[$DrawRayCastProgress, svData];
};
HowBigWillImageBe:
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
editToolData: EditToolData ← NARROW[svData.editToolData];
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
tree: CSGTree;
boundBox: BoundBox;
xSamples, ySamples: NAT;
boundSphere: BoundSphere;
tree ← DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera];
[boundBox, boundSphere] ← Preprocess3d.PreprocessForImage[tree, camera];
IF camera.frame.fullScreen
AND boundBox =
NIL
THEN {
ComplainInfiniteScene[svData.feedback]; RETURN};
[xSamples, ySamples] ← SVImage.CountSamples[boundBox.loX, boundBox.loY, boundBox.hiX, boundBox.hiY, camera.resolution];
Feedback.PutF[svData.feedback, oneLiner, "(%g lines by %g samples) is the current ray tracing size",
[integer[ySamples]], [integer[xSamples]]];
};
ComplainInfiniteScene:
PROC [feedback: FeedbackData] = {
Feedback.Append[feedback, "Infinite Scene. Please define a bounding frame.", oneLiner];
Feedback.Blink[feedback];
};
SkitterMakes:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
editToolData: EditToolData ← svData.editToolData;
[----,----,svData] ← SVSelections.GetSkitterData[editToolData];
[] ← SkitterMakesAux[svData];
SVSelections.KillSkitter[editToolData];
};
SkitterMakesAux:
PROC [svData: SVData]
RETURNS [coincident: Slice] = {
Depending on the mode of the skitter, we either create a hook, a floater, or nothing.
editToolData: EditToolData ← svData.editToolData;
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[editToolData];
SELECT skitterMode FROM
surface => {
coincident ← SVSelections.AddHookFromSkitter[editToolData];
svData.refresh.addedObject ← coincident;
SVViewersOnScene.PaintSceneAllViewers[$ObjectAdded, svData.editToolData, scene];
};
tightrope => {
coincident ← SVSelections.AddFloaterFromSkitter[editToolData];
SVEvent.ComplementAssembly[svData, coincident]; -- Draw the floater
SVViewersOnScene.PaintSceneAllViewers[$ObjectAdded, svData.editToolData, scene];
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[editToolData];
};
ENDCASE => ERROR;
};
SkitterMakesSource:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
First do a SkitterMakes. Take the coordinate system of the resulting assembly and select it as a movee. This requires creating a new selection object, pointing it at the selected object, and adding the selection to the appropriate list.
editToolData: EditToolData ← svData.editToolData;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[editToolData];
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
coincident: Slice;
movee: Selection;
coincident ← SkitterMakesAux[svData];
IF coincident =
NIL
THEN
RETURN;
Will draw the new Jack (if any) into the given viewer.
SELECT skitterMode FROM
surface => {
skitterAssem: Slice;
[skitterAssem,----,----] ← SVSelections.GetSkitterData[editToolData];
movee ← SVSelections.CreateHookMovee[coincident, skitterAssem, svData];
SVSelections.PushMovee[movee];
};
tightrope => {
movee ← SVSelections.CreateCoordSysMovee[coincident, svData];
SVSelections.PushMovee[movee];
};
coordframe => {
movee ← SVSelections.CreateCoordSysMovee[coincident, svData];
SVSelections.PushMovee[movee];
};
ENDCASE => ERROR;
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
SkitterMakesTarget:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
First do a SkitterMakes. Take the coordinate system of the resulting assembly and select it as a target. This requires creating a new selection object, pointing it at the selected object, and adding the selection to the appropriate list.
editToolData: EditToolData ← svData.editToolData;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[editToolData];
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
coincident: Slice;
target: Selection;
coincident ← SkitterMakesAux[svData]; -- create and draw the jack
IF coincident = NIL THEN RETURN;
SELECT skitterMode FROM
surface => {
skitterAssem: Slice;
[skitterAssem,----,----] ← SVSelections.GetSkitterData[editToolData];
target ← SVSelections.CreateHookTarget[coincident, skitterAssem, svData];
SVSelections.PushTarget[target];
};
tightrope => {
target ← SVSelections.CreateCoordSysTarget[coincident, svData];
SVSelections.PushTarget[target];
};
coordframe => {
target ← SVSelections.CreateCoordSysTarget[coincident, svData];
SVSelections.PushTarget[target];
};
ENDCASE => ERROR;
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
SkitterMakesPlane:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
The current skitter assembly should now become a plane selection. Plane selections draw themselves as a square aligned with the plane of the selected object.
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
coincident: Slice;
planeSel: Selection;
coincident ← SkitterMakesAux[svData];
IF coincident =
NIL
THEN
RETURN;
Will draw the new Jack (if any) into the given viewer.
planeSel ← SVSelections.CreatePlaneSelection[coincident, svData];
SVSelections.PushPlane[planeSel];
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
SkitterMakesSourceIndirect:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Like SkitterMakesSource, except that we expect the skitter mode to be "coordframe", and we don't make any Jacks. Instead, we look to see if the skitterAssembly is sitting on another assembly. If so, we create a hook movee selection. If any of these conditions fail, complain and do nothing.
editToolData: EditToolData ← svData.editToolData;
skitterAssem: Slice;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[editToolData];
indirect: Slice;
sourceSel: Selection;
camera: Camera ← svData.camera;
scene: Scene ← svData.scene;
found: BOOL;
IF skitterMode # coordframe
THEN {
Feedback.Append[svData.feedback, "Can only select indirect with a coordframe skitter.", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
[skitterAssem,----,----] ← SVSelections.GetSkitterData[editToolData];
IF skitterAssem.sittingOn =
NIL
THEN {
Feedback.Append[svData.feedback, Rope.Concat[skitterAssem.name, " is not sitting on anything."], oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
[indirect, ----, found] ← SVScene.FindAssemblyFromName[skitterAssem.sittingOn, scene];
IF NOT found THEN RETURN;
sourceSel ← SVSelections.CreateHookMovee[skitterAssem, indirect, svData];
SVSelections.PushMovee[sourceSel];
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
SkitterMakesTargetIndirect:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Like SkitterMakesTarget, except that we expect the skitter mode to be "coordframe", and we don't make any Jacks. Instead, we look to see if the skitterAssembly is sitting on another assembly. If so, we create a hook target selection. If any of these conditions fail, complain and do nothing.
editToolData: EditToolData ← svData.editToolData;
skitterAssem: Slice;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[editToolData];
indirect: Slice;
targetSel: Selection;
camera: Camera ← svData.camera;
scene: Scene ← svData.scene;
found: BOOL;
IF skitterMode # coordframe
THEN {
Feedback.Append[svData.feedback, "Can only select indirect with a coordframe skitter.", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
[skitterAssem,----,----] ← SVSelections.GetSkitterData[editToolData];
IF skitterAssem.sittingOn =
NIL
THEN {
Feedback.Append[svData.feedback, Rope.Concat[skitterAssem.name, " is not sitting on anything."], oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
[indirect, ----, found] ← SVScene.FindAssemblyFromName[skitterAssem.sittingOn, scene];
IF NOT found THEN RETURN;
targetSel ← SVSelections.CreateHookTarget[skitterAssem, indirect, svData];
SVSelections.PushTarget[targetSel];
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
SkitterMakesSourceIndirectOnly:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Like SkitterMakesSource, except that we don't make any Jacks. Instead, we make a source selection on the skitterAssembly.
editToolData: EditToolData ← svData.editToolData;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[editToolData];
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
coincident: Slice;
movee: Selection;
SELECT skitterMode FROM
surface => {
skitterAssem: Slice;
[skitterAssem,----,----] ← SVSelections.GetSkitterData[editToolData];
SVSelect.SelectEntireSlice[skitterAssem, scene, normal];
movee ← SVSelections.CreateCoordSysMovee[skitterAssem, svData];
SVSelections.PushMovee[movee];
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
tightrope => {
coincident ← SVSelections.AddFloaterFromSkitter[editToolData];
movee ← SVSelections.CreateCoordSysMovee[coincident, svData];
SVSelections.PushMovee[movee];
SVSelections.KillSkitter[svData.editToolData];
svData.refresh.addedObject ← coincident;
SVViewersOnScene.PaintSceneAllViewers[$ObjectAdded, svData.editToolData, scene];
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[editToolData];
movee ← SVSelections.CreateCoordSysMovee[coincident, svData];
SVSelections.PushMovee[movee];
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
ENDCASE => ERROR;
};
SkitterMakesTargetIndirectOnly:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Like SkitterMakesTarget, except that we don't make any Jacks for surface skitters. Instead, we make a target selection on the skitterAssembly.
editToolData: EditToolData ← svData.editToolData;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[editToolData];
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
coincident: Slice;
targetSel: Selection;
SELECT skitterMode FROM
surface => {
skitterAssem: Slice;
[skitterAssem,----,----] ← SVSelections.GetSkitterData[editToolData];
targetSel ← SVSelections.CreateCoordSysTarget[skitterAssem, svData];
SVSelections.PushTarget[targetSel];
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
tightrope => {
coincident ← SVSelections.AddFloaterFromSkitter[editToolData];
SVEvent.ComplementAssembly[svData, coincident]; -- Draw the floater
targetSel ← SVSelections.CreateCoordSysTarget[coincident, svData];
SVSelections.PushTarget[targetSel];
SVSelections.KillSkitter[svData.editToolData];
svData.refresh.addedObject ← coincident;
SVViewersOnScene.PaintSceneAllViewers[$ObjectAdded, svData.editToolData, scene];
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[editToolData];
targetSel ← SVSelections.CreateCoordSysTarget[coincident, svData];
SVSelections.PushTarget[targetSel];
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
ENDCASE => ERROR;
};
SkitterMakesPlaneIndirectOnly:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Like SkitterMakesPlane, except that we don't make any Jacks for surface skitters. Instead, we make a plane selection on the skitterAssembly.
editToolData: EditToolData ← svData.editToolData;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[editToolData];
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
coincident: Slice;
planeSel: Selection;
SELECT skitterMode FROM
surface => {
skitterAssem: Slice;
[skitterAssem,----,----] ← SVSelections.GetSkitterData[editToolData];
planeSel ← SVSelections.CreatePlaneSelection[skitterAssem, svData];
SVSelections.PushPlane[planeSel];
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
tightrope => {
coincident ← SVSelections.AddFloaterFromSkitter[editToolData];
SVEvent.ComplementAssembly[svData, coincident]; -- Draw the floater
planeSel ← SVSelections.CreatePlaneSelection[coincident, svData];
SVSelections.PushPlane[planeSel];
SVSelections.KillSkitter[svData.editToolData];
svData.refresh.addedObject ← coincident;
SVViewersOnScene.PaintSceneAllViewers[$ObjectAdded, svData.editToolData, scene];
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[editToolData];
planeSel ← SVSelections.CreatePlaneSelection[coincident, svData];
SVSelections.PushPlane[planeSel];
SVSelections.KillSkitter[svData.editToolData];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
ENDCASE => ERROR;
};
MoveToTarget:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Move the distinguished source to the distinguished target.
source: Slice;
dockCS: CoordSystem;
moveeSel, targetSel: Selection;
relativeMat: Matrix4by4;
editToolData: EditToolData ← svData.editToolData;
scene: Scene ← svData.scene;
moveeSel ← SVSelections.TopMovee[];
IF moveeSel = NIL THEN RETURN;
targetSel ← SVSelections.TopTarget[];
IF targetSel = NIL THEN RETURN;
IF moveeSel.svData # targetSel.svData
THEN {
Feedback.Append[svData.feedback, "Move from viewer to viewer not yet implemented.", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
dockCS ← targetSel.coincident.coordSys;
[----, relativeMat] ← ParentAndPosition[moveeSel, targetSel, scene];
SELECT moveeSel.referentType
FROM
hook => {
source ← moveeSel.indirect;
SVAssembly.TugTransfLeaveTug[source, scene, moveeSel.coincident.coordSys, relativeMat, dockCS];
};
coordSys => {
source ← moveeSel.coincident;
SVAssembly.AbsTransf[source, scene, relativeMat, dockCS];
};
ENDCASE => ERROR;
SVSelections.ClearMoveeStack[editToolData];
SVSelections.ClearTargetStack[editToolData];
SVViewersOnScene.SceneNewVersion[svData];
SVViewersOnScene.PaintSceneAllViewers[$PaintEntireScene, editToolData, scene];
There may be more than one new scene, but for now we'll just repaint the last one.
};
SourceRotX:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
RotateAux[event, svData, 1];
};
SourceRotY:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
RotateAux[event, svData, 2];
};
SourceRotZ:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
RotateAux[event, svData, 3];
};
RotateAux:
PROC [event:
LIST
OF
REF
ANY, svData: SVData, axis: [1..3]] = {
degrees: REAL ← NARROW[event.rest.first, REF REAL]^;
sourceSel: Selection;
scene: Scene;
editToolData: EditToolData;
jack, indirect: Slice;
sourceSel ← SVSelections.TopMovee[];
IF sourceSel = NIL THEN RETURN;
svData ← sourceSel.svData;
editToolData ← svData.editToolData;
SELECT sourceSel.referentType FROM
hook => {
jack ← sourceSel.coincident;
indirect ← sourceSel.indirect;
};
coordSys => {
jack ← sourceSel.coincident;
indirect ← sourceSel.coincident;
};
ENDCASE => ERROR;
scene ← svData.scene;
SVTransforms.Rotate[indirect, scene, axis, degrees, jack.coordSys, TRUE];
svData.refresh.addedObject ← indirect;
SVViewersOnScene.PaintSceneAllViewers[$ObjectChangedBoundBoxProvided, editToolData, scene];
};
CopyToAllTargets:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Take the distinguished movee object. Make a copy at the exact same place for each target. Perform a TugRotX[180], etc. to make movee-copy tangent to target-referee at target. Each copy becomes attached to the parent of the target object.
moveeCopy, moveeOriginal, parent, moveeParent: Slice;
moveeSel: Selection;
editToolData: EditToolData ← svData.editToolData;
oldScene, newScene: Scene;
dockCS: CoordSystem;
relativeMat: Matrix4by4;
targets: SelectionGenerator;
targetsExist: BOOL;
moveeSel ← SVSelections.TopMovee[];
IF moveeSel = NIL THEN RETURN;
oldScene ← moveeSel.svData.scene;
SELECT moveeSel.referentType
FROM
hook => moveeOriginal ← moveeSel.indirect;
coordSys => moveeOriginal ← moveeSel.coincident;
ENDCASE => ERROR;
[----, moveeParent] ← SVScene.FindAssemblyFromName[moveeOriginal.name, oldScene];
IF moveeParent =
NIL
THEN moveeParent ← moveeOriginal;
If moveeOriginal is the sceneAssembly, then use the sceneAssembly as the new parent as well.
[targets, targetsExist] ← SVSelections.GetSelectionGenerator[target];
IF
NOT targetsExist
THEN {
Feedback.Append[svData.feedback, "Please make some targets to copy to.", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
FOR targetSel: Selection ← SVSelections.NextSelection[targets], SVSelections.NextSelection[targets]
UNTIL targetSel =
NIL
DO
newScene ← targetSel.svData.scene;
IF newScene = oldScene
THEN {
parent ← moveeParent;
[----, relativeMat] ← ParentAndPosition[moveeSel, targetSel, newScene];
}
ELSE [
parent,
relativeMat] ← ParentAndPosition[moveeSel, targetSel, newScene];
dockCS ← targetSel.coincident.coordSys;
moveeCopy ← SVScene.CopyAssemblyAndSonsUniqueNames[moveeOriginal, oldScene, newScene, parent, svData.feedback];
SVTransforms.Normalize[moveeCopy, newScene, moveeOriginal.coordSys];
SELECT moveeSel.referentType FROM
hook => SVAssembly.TugTransfLeaveTug[moveeCopy, newScene, moveeSel.coincident.coordSys, relativeMat, dockCS];
coordSys => SVAssembly.AbsTransf[moveeCopy, newScene, relativeMat, dockCS];
ENDCASE => ERROR;
ENDLOOP;
SVSelections.ClearTargetStack[editToolData];
SVViewersOnScene.SceneNewVersion[svData];
SVViewersOnScene.PaintSceneAllViewers[$PaintEntireScene, editToolData, newScene];
There may be more than one new scene, but for now we'll just repaint the last one.
};
CopyRotate:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Copy the distinguished source to a set of positions in a circle whose center is the origin of the distinguished target and whose cicumference includes the origin of the source.
copy, moveeOriginal, moveeParent: Slice;
sourceSel, planeSel: Selection;
planeAssem: Slice;
sourceCS, planeCS: CoordSystem;
editToolData: EditToolData;
scene: Scene;
numberOfCopies: NAT;
numberOfCopiesReal: REAL;
degrees, deltaDegrees, realI: REAL;
toolData: ToolData;
sourceSel ← SVSelections.PopMovee[];
IF sourceSel = NIL THEN RETURN;
planeSel ← SVSelections.PopPlane[];
IF planeSel = NIL THEN RETURN;
planeAssem ← planeSel.coincident;
IF planeAssem.toolMasterObject = NIL OR planeAssem.toolMasterObject.mainBody = NIL THEN ERROR;
toolData ← NARROW[planeAssem.toolMasterObject.mainBody];
IF
sourceSel.svData # planeSel.svData
THEN {
Feedback.Append[svData.feedback, "Can't copy rotate between viewers.", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
svData ← sourceSel.svData;
scene ← svData.scene;
editToolData ← svData.editToolData;
sourceCS ← sourceSel.coincident.coordSys;
planeCS ← planeSel.coincident.coordSys;
numberOfCopies ← SVViewerTools.GetNat[svData.textSection.xyz];
numberOfCopiesReal ← numberOfCopies;
SELECT sourceSel.referentType
FROM
hook => moveeOriginal ← sourceSel.indirect;
coordSys => moveeOriginal ← sourceSel.coincident;
ENDCASE => ERROR;
[----, moveeParent] ← SVScene.FindAssemblyFromName[moveeOriginal.name, scene];
deltaDegrees ← 360/numberOfCopiesReal;
FOR i:
NAT
IN [1..numberOfCopies-1]
DO
realI ← i;
degrees ← i*deltaDegrees;
copy ← SVScene.CopyAssemblyAndSonsUniqueNames[moveeOriginal, scene, scene, moveeParent, svData.feedback];
SVTransforms.Normalize[copy, scene, moveeOriginal.coordSys];
SVTransforms.Rotate[copy, scene, MIN[toolData.plane, 3], degrees, planeCS];
ENDLOOP;
SVViewersOnScene.SceneNewVersion[svData];
SVViewersOnScene.PaintSceneAllViewers[$PaintEntireScene, editToolData, scene];
There may be more than one new scene, but for now we'll just repaint the last one.
}; -- end of CopyRotate
CopyToAllTargetsTree:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Just like CopyToAllTargets except that we always use the parent of the target as the parent of each copy (good for making tree structures).
moveeCopy, moveeOriginal, parent, moveeParent: Slice;
moveeSel: Selection;
editToolData: EditToolData ← svData.editToolData;
oldScene, newScene: Scene;
dockCS: CoordSystem;
relativeMat: Matrix4by4;
targets: SelectionGenerator;
targetsExist: BOOL;
moveeSel ← SVSelections.TopMovee[];
IF moveeSel = NIL THEN RETURN;
oldScene ← moveeSel.svData.scene;
SELECT moveeSel.referentType
FROM
hook => moveeOriginal ← moveeSel.indirect;
coordSys => moveeOriginal ← moveeSel.coincident;
ENDCASE => ERROR;
[----, moveeParent] ← SVScene.FindAssemblyFromName[moveeOriginal.name, oldScene];
[targets, targetsExist] ← SVSelections.GetSelectionGenerator[target];
IF
NOT targetsExist
THEN {
Feedback.Append[svData.feedback, "Please make some targets to copy to.", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
FOR targetSel: Selection ← SVSelections.NextSelection[targets], SVSelections.NextSelection[targets]
UNTIL targetSel =
NIL
DO
newScene ← targetSel.svData.scene;
[
parent,
relativeMat] ← ParentAndPosition[moveeSel, targetSel, newScene];
dockCS ← targetSel.coincident.coordSys;
moveeCopy ← SVScene.CopyAssemblyAndSonsUniqueNames[moveeOriginal, oldScene, newScene, parent, svData.feedback];
SVTransforms.Normalize[moveeCopy, newScene, moveeOriginal.coordSys];
SELECT moveeSel.referentType FROM
hook => SVAssembly.TugTransfLeaveTug[moveeCopy, newScene, moveeSel.coincident.coordSys, relativeMat, dockCS];
coordSys => SVAssembly.AbsTransf[moveeCopy, newScene, relativeMat, dockCS];
ENDCASE => ERROR;
ENDLOOP;
SVSelections.ClearTargetStack[editToolData];
SVViewersOnScene.SceneNewVersion[svData];
SVViewersOnScene.PaintSceneAllViewers[$PaintEntireScene, editToolData, newScene];
There may be more than one new scene, but for now we'll just repaint the last one.
};
ParentAndPosition:
PRIVATE
PROC [moveeSel, targetSel: Selection, newScene: Scene]
RETURNS [parent: Slice,
relativeMat: Matrix4by4] = {
target: Slice;
SELECT targetSel.referentType FROM
hook => {
[target, parent] ← SVScene.FindAssemblyFromName[targetSel.indirect.name, newScene];
IF target # targetSel.indirect THEN ERROR;
SELECT moveeSel.referentType
FROM
hook => relativeMat ← Matrix3d.MakeRotateYMat[180]; -- mushroom placement
coordSys => relativeMat ← Matrix3d.Identity[]; -- antenae placement
ENDCASE => ERROR;
};
coordSys => {
[target, parent] ← SVScene.FindAssemblyFromName[targetSel.coincident.name, newScene];
IF Rope.Equal[targetSel.coincident.name, "sceneAssembly", TRUE] THEN parent ← targetSel.coincident;
IF target # targetSel.coincident THEN ERROR;
SELECT moveeSel.referentType
FROM
hook => relativeMat ← Matrix3d.Identity[]; -- will think about this some more.
coordSys => relativeMat ← Matrix3d.Identity[];
ENDCASE => ERROR;
};
ENDCASE => ERROR;
};
RandomAngle:
PRIVATE
PROC []
RETURNS [degrees:
REAL] = {
Returns an angle evenly distributed in [0..360).
randomNat: NAT ← Random.ChooseInt[NIL, 0, 9999];
degrees ← (randomNat/10000.0)*360.0;
};
RandomScalar:
PRIVATE
PROC [min, max:
REAL]
RETURNS [scalar:
REAL] = {
Returns a scalar evenly distributed in [min..max).
randomNat: NAT ← Random.ChooseInt[NIL, 0, 9999];
scalar ← (randomNat/10000.0)*(max-min)+min;
};
CopyRandomToAllTargets:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Just like CopyToAllTargets except that a random rotation and scaling is applied to each copy with respect to the dock coordsys.
moveeCopy, moveeOriginal, parent, moveeParent: Slice;
moveeSel: Selection;
editToolData: EditToolData ← svData.editToolData;
oldScene, newScene: Scene;
dockCS: CoordSystem;
relativeMat: Matrix4by4;
targets: SelectionGenerator;
targetsExist: BOOL;
min, max, randomScalar, randomDegrees: REAL;
moveeSel ← SVSelections.TopMovee[];
IF moveeSel = NIL THEN RETURN;
oldScene ← moveeSel.svData.scene;
[min, max, ----] ← SVViewerTools.GetThreeReals[editToolData.transformSection.scaleXYZ];
SELECT moveeSel.referentType
FROM
hook => moveeOriginal ← moveeSel.indirect;
coordSys => moveeOriginal ← moveeSel.coincident;
ENDCASE => ERROR;
[----, moveeParent] ← SVScene.FindAssemblyFromName[moveeOriginal.name, oldScene];
[targets, targetsExist] ← SVSelections.GetSelectionGenerator[target];
IF
NOT targetsExist
THEN {
Feedback.Append[svData.feedback, "Please make some targets to copy to.", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
FOR targetSel: Selection ← SVSelections.NextSelection[targets], SVSelections.NextSelection[targets]
UNTIL targetSel =
NIL
DO
newScene ← targetSel.svData.scene;
IF newScene = oldScene
THEN {
parent ← moveeParent;
[----, relativeMat] ← ParentAndPosition[moveeSel, targetSel, newScene];
}
ELSE [
parent,
relativeMat] ← ParentAndPosition[moveeSel, targetSel, newScene];
dockCS ← targetSel.coincident.coordSys;
moveeCopy ← SVScene.CopyAssemblyAndSonsUniqueNames[moveeOriginal, oldScene, newScene, parent, svData.feedback];
SELECT moveeSel.referentType
FROM
hook => SVAssembly.TugTransfLeaveTug[moveeCopy, newScene, moveeSel.coincident.coordSys, relativeMat, dockCS];
coordSys => SVAssembly.AbsTransf[moveeCopy, newScene, relativeMat, dockCS];
ENDCASE => ERROR;
randomDegrees ← RandomAngle[];
randomScalar ← RandomScalar[min, max];
SVTransforms.Rotate[moveeCopy, newScene, 3, randomDegrees, dockCS];
SVTransforms.ScaleEven[moveeCopy, newScene, randomScalar, dockCS];
SVSelections.ClearTargetStack[editToolData];
SVViewersOnScene.SceneNewVersion[svData];
SVViewersOnScene.PaintSceneAllViewers[$PaintEntireScene, editToolData, newScene];
There may be more than one new scene, but for now we'll just repaint the last one.
};
ExtendCurrent:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Find parent of skitter.assembly if any. Set skitter.assembly to this value. Indicate the selection by changing the name in the "Current:" slot of the edittool.
editToolData: EditToolData;
scene: Scene;
assembly, parent: Slice;
prim: Primitive;
assemblyName: Rope.ROPE;
success: BOOL;
editToolData ← svData.editToolData;
scene ← svData.scene;
[assembly, prim, svData] ← SVSelections.GetSkitterData[editToolData];
IF assembly = NIL THEN RETURN;
assemblyName ← assembly.name;
[assembly, parent, success] ← SVScene.FindAssemblyFromName[assemblyName, scene];
IF
NOT success
THEN {
Feedback.Append[svData.feedback, Rope.Cat["ExtendCurrent: assembly ", assemblyName, " not found."], oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
SVSelections.UpdateSkitter[parent, prim, svData];
};
ParentOfSkitter:
PROC [] = {
Find parent of skitter.assembly if any. Set skitter.assembly to this value. Indicate the selection by changing the name in the "Current:" slot of the edittool.
svData: SVData;
editToolData: EditToolData;
scene: Scene;
assembly, realAssembly, parent: Slice;
prim: Primitive;
[realAssembly, prim, svData] ← SVSelections.GetSkitterData[editToolData];
editToolData ← svData.editToolData;
scene ← svData.scene;
IF realAssembly = NIL THEN RETURN;
[assembly, parent] ← SVScene.FindAssemblyFromName[realAssembly.name, scene];
IF assembly # realAssembly THEN ERROR;
IF parent#NIL THEN SVSelections.UpdateSkitter[parent, prim, svData];
};
SetTool:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
The current movee selection assembly is now a tool. It will appear as a simple rectangle and ray traces as a simple rectangle.
editToolData: EditToolData;
planeAssem: Slice;
planeSel: Selection;
scene: Scene;
planeSel ← SVSelections.TopPlane[];
IF planeSel =
NIL
THEN {
Feedback.Append[svData.feedback, "SetTool: Make a plane selection first", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
planeAssem ← planeSel.coincident;
svData ← planeSel.svData;
scene ← svData.scene;
editToolData ← NARROW[svData.editToolData];
planeAssem.showAs ← tool;
SVScene.AddOrResizeToolToAssembly[planeAssem, scene];
SVViewersOnScene.PaintSceneAllViewers[$PaintEntireScene, editToolData, scene];
}; -- end of SetTool
ResetTool:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
The current movee selection assembly is now a non-tool. It will once again appear as its regular shape.
editToolData: EditToolData;
planeAssem: Slice;
planeSel: Selection;
scene: Scene;
planeSel ← SVSelections.TopPlane[];
IF planeSel =
NIL
THEN {
Feedback.Append[svData.feedback, "ResetTool: Make a plane selection first", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
planeAssem ← planeSel.coincident;
svData ← planeSel.svData;
scene ← svData.scene;
editToolData ← NARROW[svData.editToolData];
planeAssem.showAs ← normal;
SVViewersOnScene.SceneNewVersion[svData];
SVViewersOnScene.PaintSceneAllViewers[$PaintEntireScene, editToolData, scene];
};
CycleTool:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Cycle through the 3 planes of the tool. Change the appearance of the plane selection and output a description of the current plane, as feedback.
editToolData: EditToolData;
planeAssem: Slice;
planeSel: Selection;
scene: Scene;
camera: Camera;
toolData: ToolData;
planeSel ← SVSelections.TopPlane[];
IF planeSel =
NIL
THEN {
Feedback.Append[svData.feedback, "CycleTool: Make a plane selection first", oneLiner];
Feedback.Blink[svData.feedback];
RETURN;
};
planeAssem ← planeSel.coincident;
svData ← planeSel.svData;
camera ← svData.camera;
scene ← svData.scene;
editToolData ← NARROW[svData.editToolData];
IF planeAssem.toolMasterObject =
NIL
OR planeAssem.toolMasterObject.mainBody =
NIL
THEN
SVScene.AddOrResizeToolToAssembly[planeAssem, scene];
toolData ← NARROW[planeAssem.toolMasterObject.mainBody];
toolData.plane ←
IF toolData.plane = 3
THEN 1
ELSE toolData.plane + 1;
Indicate the currently selected plane in the message window.
SELECT toolData.plane FROM
1 => Feedback.Append[svData.feedback, Rope.Cat["x = 0 plane of ", planeAssem.name, " now selected."], oneLiner];
2 => Feedback.Append[svData.feedback, Rope.Cat["y = 0 plane of ", planeAssem.name, " now selected."], oneLiner];
3 => Feedback.Append[svData.feedback, Rope.Cat["z = 0 plane of ", planeAssem.name, " now selected."], oneLiner];
4 => Feedback.Append[svData.feedback, Rope.Cat["All planes of ", planeAssem.name, " now selected."], oneLiner];
ENDCASE => ERROR;
IF planeAssem.showAs = tool
OR planeAssem.showAs = both
THEN
SVViewersOnScene.PaintSceneAllViewers[$PaintEntireScene, editToolData, scene];
};
DropPerpendicular:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
editToolData: EditToolData ← svData.editToolData;
sourceSel, planeSel: Selection;
toolData: ToolData;
planeAssem: Slice;
scene: Scene;
camera: Camera;
selectionMat, sourcePlane: Matrix4by4;
interceptPlane, originPlane: Point3d;
sourceSel ← SVSelections.TopMovee[];
IF sourceSel = NIL THEN RETURN;
planeSel ← SVSelections.TopPlane[];
IF planeSel = NIL THEN RETURN;
planeAssem ← planeSel.coincident;
svData ← planeSel.svData;
camera ← svData.camera;
scene ← svData.scene;
IF planeAssem.toolMasterObject =
NIL
OR planeAssem.toolMasterObject.mainBody =
NIL
THEN
SVScene.AddOrResizeToolToAssembly[planeAssem, scene];
toolData ← NARROW[planeAssem.toolMasterObject.mainBody];
sourcePlane ← CoordSys.FindAInTermsOfB[sourceSel.coincident.coordSys, planeSel.coincident.coordSys];
originPlane ← Matrix3d.OriginOfMatrix[sourcePlane];
interceptPlane ← originPlane;
SELECT
toolData.plane
FROM
1 => interceptPlane[1] ← 0.0;
2 => interceptPlane[2] ← 0.0;
3 => interceptPlane[3] ← 0.0;
4 => Who knows.
ENDCASE => ERROR;
selectionMat ← CoordSys.WRTWorld[planeSel.coincident.coordSys];
selectionMat ← Matrix3d.LocalTranslate[selectionMat, interceptPlane[1], interceptPlane[2], interceptPlane[3]];
SVSelections.UpdateSkitter[NIL, NIL, svData];
SVSelections.PositionSkitterFromFrame[svData, [0,0], selectionMat]; -- update skitterWORLD
SVSelections.SetModeSkitter[svData, tightrope];
SkitterMakes[event, svData]; -- sceneAssembly will be the parent of the new jack.
};
Delete:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
scene: Scene ← svData.scene;
SVEditUser.Delete[event, svData];
};
SetBoundingSpheres:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
camera: Camera ← svData.camera;
camera.useBoundBoxes ← FALSE;
};
SetSphereShadows:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
camera: Camera ← svData.camera;
camera.useBoundSpheresForShadows ← TRUE;
};
ResetSpheres:
PUBLIC PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
camera: Camera ← svData.camera;
camera.useBoundBoxes ← TRUE;
camera.useBoundSpheresForShadows ← FALSE;
};
END.