File: SVEventImplB.mesa
Author: Eric Bier in October 1982
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by Bier on September 24, 1987 1:39:38 pm PDT
Contents: Code to respond to button presses made in an SVViewer
Bloomenthal, June 16, 1987 7:56:05 pm PDT
DIRECTORY
Atom, AtomButtonsTypes, BasicTime, Buttons, SVCastRays, Containers, SVCoordSys, SVRay, SVGraphics, SVSceneToTree, Feedback, FS, Imager, ImagerInterpress, InputFocus, IO, Labels, SVMatrix3d, Menus, MessageWindow, SVPreprocess3d, Random, Rope, SV2d, SV3d, SVAssembly, SVBasicTypes, SVCaret, SVEditUser, SVEvent, SVFileoutPoly, SVFiles, SVImage, SVInterfaceTypes, SVModelTypes, SVRefresh, SVScene, SVSceneTypes, SVSelect, SVSelections, SVCatScan, SVTransforms, SVUtility, SVViewersOnScene, SVViewerTool, SVViewerTools, SVWindow, SVParseOut, ViewerClasses, ViewerTools;
SVEventImplB: CEDAR PROGRAM
IMPORTS Atom, BasicTime, Buttons, SVCaret, SVCastRays, SVCoordSys, SVRay, SVGraphics, SVSceneToTree, Feedback, FS, Imager, ImagerInterpress, InputFocus, IO, Labels, SVMatrix3d, MessageWindow, SVPreprocess3d, Random, Rope, SVAssembly, SVEditUser, SVFileoutPoly, SVFiles, SVImage, SVRefresh, SVScene, SVSelect, SVSelections, SVTransforms, SVUtility, SVViewersOnScene, SVViewerTools, SVWindow, SVParseOut, ViewerTools
EXPORTS SVEvent =
BEGIN
Slice: TYPE = SVSceneTypes.Slice;
BoundBox: TYPE = SVBasicTypes.BoundBox;
Camera: TYPE = SVModelTypes.Camera;
CatScan: TYPE = SVCatScan.CatScan;
Classification: TYPE = SVSceneTypes.Classification;
Color: TYPE = Imager.Color;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
CSGTree: TYPE = SVSceneTypes.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 = SVSceneTypes.Primitive;
Ray: TYPE = SVSceneTypes.Ray;
Scene: TYPE = SVSceneTypes.Scene;
Selection: TYPE = SVInterfaceTypes.Selection;
SelectionGenerator: TYPE = SVInterfaceTypes.SelectionGenerator;
SelectionType: TYPE = SVInterfaceTypes.SelectionType;
Skitter: TYPE = SVSceneTypes.Skitter;
SkitterMode: TYPE = SVSceneTypes.SkitterMode;
Sphere: TYPE = SV3d.Sphere;
ToolData: TYPE = SVSceneTypes.ToolData;
Vector3d: TYPE = SV3d.Vector3d;
Viewer: TYPE = ViewerClasses.Viewer;
SVData: TYPE = SVInterfaceTypes.SVData;
DCProc: TYPE = SVInterfaceTypes.DCProc;
GLOBAL VARIABLES
globalSceneStyleCount: NAT = 4;
globalSceneStyleArray: ARRAY[1..globalSceneStyleCount] OF Rope.ROPE
["WireFrame", "Shaded", "HiddenLine", "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.ROPENARROW[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
ToIPLit: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = {
DoMakeInterpress: PROC [dc: Imager.Context] = {
switched: BOOLFALSE;
tempQuality ← svData.camera.quality;
svData.camera.quality ← showall;
tempStyle ← svData.camera.displayStyle;
svData.camera.displayStyle ← print;
IF NOT SVState.GetShowColors[svData] THEN {
SVEvent.ToggleShowColors[svData, NIL];
switched ← TRUE;
};
Feedback.Append[svData.feedback, startRope, begin];
Imager.ScaleT[dc, metersPerPixel];
SVRefresh.InterpressEntireScene[dc, svData];
svData.camera.quality ← tempQuality;
svData.camera.displayStyle ← tempStyle;
IF switched THEN SVEvent.ToggleShowColors[svData, NIL];
};
ipRef: ImagerInterpress.Ref;
fullName: Rope.ROPE;
success: BOOL;
TIMING VARIABLES
startTime: BasicTime.GMT;
endTime: BasicTime.GMT;
totalTime: INT;
startRope, endRope: Rope.ROPE;
tempQuality: SVModelTypes.QualityMode;
tempStyle: SVModelTypes.DisplayStyle;
ipName: Rope.ROPE ← "litshot.ip";
[fullName, success] ← SVUtility.GetInterpressFileName[ipName, svData.currentWDir, svData.feedback];
IF NOT success THEN RETURN;
ipRef ← ImagerInterpress.Create[fullName];
startRope ← IO.PutFR["Writing to IP file: %g . . . ", [rope[fullName]]];
START TIMING
startTime ← BasicTime.Now[];
ImagerInterpress.DoPage[ipRef, DoMakeInterpress, 1.0];
ImagerInterpress.Close[ipRef];
endTime ← BasicTime.Now[];
totalTime ← BasicTime.Period[startTime, endTime];
endRope ← IO.PutFR[" Done in time (%r)", [integer[totalTime]]];
Feedback.Append[svData.feedback, Rope.Concat[startRope, endRope], oneLiner];
};
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 ← SVMatrix3d.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;
"HiddenLine" => style ← hiddenLine;
"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;
"HiddenLine" => newStyle ← hiddenLine;
"Normals" => newStyle ← normals;
"RayCast" => newStyle ← rayCast;
ENDCASE => ERROR;
svData.camera.style ← newStyle;
};
ON/OFF SWITCHES
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 ← SVSceneToTree.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]]]];
SVParseOut.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 "SVCoordSys", 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 ← SVSceneToTree.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: Sphere;
tree ← SVSceneToTree.AssemblyToTree[scene.assembly, scene, camera];
[boundBox, boundSphere] ← SVPreprocess3d.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];
SVCaret.Kill[editToolData.skitter];
};
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;
SVCaret.Kill[svData.editToolData.skitter];
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;
SVCaret.Kill[svData.editToolData.skitter];
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];
SVCaret.Kill[svData.editToolData.skitter];
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];
SVCaret.Kill[svData.editToolData.skitter];
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];
SVCaret.Kill[svData.editToolData.skitter];
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];
SVCaret.Kill[svData.editToolData.skitter];
SVViewersOnScene.PaintSceneAllViewers[$SelectionChanged, svData.editToolData, scene];
};
tightrope => {
coincident ← SVSelections.AddFloaterFromSkitter[editToolData];
movee ← SVSelections.CreateCoordSysMovee[coincident, svData];
SVSelections.PushMovee[movee];
SVCaret.Kill[svData.editToolData.skitter];
svData.refresh.addedObject ← coincident;
SVViewersOnScene.PaintSceneAllViewers[$ObjectAdded, svData.editToolData, scene];
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[editToolData];
movee ← SVSelections.CreateCoordSysMovee[coincident, svData];
SVSelections.PushMovee[movee];
SVCaret.Kill[svData.editToolData.skitter];
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];
SVCaret.Kill[svData.editToolData.skitter];
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];
SVCaret.Kill[svData.editToolData.skitter];
svData.refresh.addedObject ← coincident;
SVViewersOnScene.PaintSceneAllViewers[$ObjectAdded, svData.editToolData, scene];
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[editToolData];
targetSel ← SVSelections.CreateCoordSysTarget[coincident, svData];
SVSelections.PushTarget[targetSel];
SVCaret.Kill[svData.editToolData.skitter];
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];
SVCaret.Kill[svData.editToolData.skitter];
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];
SVCaret.Kill[svData.editToolData.skitter];
svData.refresh.addedObject ← coincident;
SVViewersOnScene.PaintSceneAllViewers[$ObjectAdded, svData.editToolData, scene];
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[editToolData];
planeSel ← SVSelections.CreatePlaneSelection[coincident, svData];
SVSelections.PushPlane[planeSel];
SVCaret.Kill[svData.editToolData.skitter];
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: REALNARROW[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 ← SVMatrix3d.MakeRotateYMat[180]; -- mushroom placement
coordSys => relativeMat ← SVMatrix3d.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 ← SVMatrix3d.Identity[]; -- will think about this some more.
coordSys => relativeMat ← SVMatrix3d.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];
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.
};
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 ← svData.editToolData;
scene: Scene ← svData.scene;
assembly, parent: Slice;
prim: Primitive;
assemblyName: Rope.ROPE;
success: BOOL;
skitter: Skitter ← editToolData.skitter;
[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;
};
SVCaret.SetAssemblyAndPrimitive[skitter, parent, prim];
};
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 ← svData.editToolData;
scene: Scene ← svData.scene;
assembly, realAssembly, parent: Slice;
prim: Primitive;
skitter: Skitter ← editToolData.skitter;
[realAssembly, prim, svData] ← SVSelections.GetSkitterData[editToolData];
IF realAssembly = NIL THEN RETURN;
[assembly, parent] ← SVScene.FindAssemblyFromName[realAssembly.name, scene];
IF assembly # realAssembly THEN ERROR;
IF parent#NIL THEN SVCaret.SetAssemblyAndPrimitive[skitter, parent, prim];
};
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;
skitter: Skitter ← editToolData.skitter;
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 ← SVCoordSys.FindAInTermsOfB[sourceSel.coincident.coordSys, planeSel.coincident.coordSys];
originPlane ← SVMatrix3d.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 ← SVCoordSys.WRTWorld[planeSel.coincident.coordSys];
selectionMat ← SVMatrix3d.LocalTranslate[selectionMat, interceptPlane[1], interceptPlane[2], interceptPlane[3]];
SVCaret.SetAssemblyAndPrimitive[skitter, NIL, NIL];
SVCaret.PositionFromMatrix[svData.editToolData.skitter, [0,0], selectionMat];
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.