File: SVViewerInputImplA.mesa
Last edited by Bier on August 1, 1985 6:02:20 pm PDT
Copyright © 1984 by Xerox Corporation. All rights reserved.
Contents: Procedures for responding to button clicks made in a solidviewer.
DIRECTORY
BasicObject3d,
CoordSys,
DisplayList3d,
Imager,
Matrix3d,
Random,
Rope,
SV2d,
SV3d,
SVEditUser,
SVError,
SVInputMonitor,
SVInterfaceTypes,
SVModelTypes,
SVRayTypes,
SVSceneTypes,
SVSelections,
SVTransforms,
SVViewer,
SVViewerInput,
SVViewerTools,
SVViewerUser,
TIPUser,
ViewerClasses;
SVViewerInputImplA:
PROGRAM
IMPORTS CoordSys, DisplayList3d, Matrix3d, Random, Rope, SVEditUser, SVError, SVInputMonitor, SVSelections, SVTransforms, SVViewer, SVViewerInput, SVViewerTools, SVViewerUser
EXPORTS SVViewerInput =
BEGIN
Artwork: TYPE = SVModelTypes.Artwork;
ArtworkToolData: TYPE = SVInterfaceTypes.ArtworkToolData;
Assembly: TYPE = SVSceneTypes.Assembly;
AssemblyList: TYPE = SVSceneTypes.AssemblyList;
BoundBox: TYPE = SVModelTypes.BoundBox;
BoundSphere: TYPE = SVModelTypes.BoundSphere;
Camera: TYPE = SVModelTypes.Camera;
Classification: TYPE = SVRayTypes.Classification;
Color: TYPE = Imager.Color;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
CSGTree: TYPE = SVRayTypes.CSGTree;
CylinderRec: TYPE = BasicObject3d.CylinderRec;
EditToolData: TYPE = SVInterfaceTypes.EditToolData;
FileCamera: TYPE = SVSceneTypes.FileCamera;
FrameBox: TYPE = SVModelTypes.FrameBox;
MasterObject: TYPE = SVSceneTypes.MasterObject;
Matrix4by4: TYPE = SV3d.Matrix4by4;
Point2d: TYPE = SV2d.Point2d;
Point3d: TYPE = SV3d.Point3d;
Primitive: TYPE = SVRayTypes.Primitive;
Ray: TYPE = SVRayTypes.Ray;
Scene: TYPE = SVSceneTypes.Scene;
SearchDepth: TYPE = SVInterfaceTypes.SearchDepth;
Selection: TYPE = SVInterfaceTypes.Selection;
SelectionGenerator: TYPE = SVInterfaceTypes.SelectionGenerator;
Shape: TYPE = SVSceneTypes.Shape;
SkitterMode: TYPE = SVInterfaceTypes.SkitterMode;
ToolData: TYPE = SVSceneTypes.ToolData;
TrigLine: TYPE = SV2d.TrigLine;
Vector: TYPE = SV3d.Vector;
ViewerToolData: TYPE = SVInterfaceTypes.ViewerToolData;
InputNotify:
PUBLIC
SAFE
PROCEDURE [self: ViewerClasses.Viewer, input:
LIST
OF
REF
ANY] =
TRUSTED {
Self is a viewer picture.
viewerToolData: ViewerToolData ← NARROW[self.data];
IF
ISTYPE[input.first, TIPUser.TIPScreenCoords]
THEN {
controlPoint: Point2d;
camera: Camera ← viewerToolData.camera;
mousePlace: TIPUser.TIPScreenCoords ← NARROW[input.first];
controlPoint[1] ← mousePlace.mouseX; -- this is a fix to float conversion
controlPoint[2] ← mousePlace.mouseY;
controlPoint ← CoordSys.ScreenToCamera[controlPoint, camera.screenCS];
Convert to camera coordinates.
IF ISTYPE[input.rest.first, ATOM] THEN
SELECT input.rest.first
FROM
$StartDrag, $SetDrag, $EndDrag => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$StartCameraDrag, $SetCameraDrag, $EndCameraDrag => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$SingleRay => SVViewerUser.SingleRay[viewerToolData, controlPoint];
$FrameUpLeft, $FrameDownRightMove, $FrameDownRightEnd, $DeleteFrame => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$StartSkitter, $DuringSkitter, $EndSkitter => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$StartBackSkitter, $DuringBackSkitter, $EndBackSkitter => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$StartTopLevelSkitter, $DuringTopLevelSkitter, $EndTopLevelSkitter => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$StartCoordSkitter, $DuringCoordSkitter, $EndCoordSkitter => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$StartTightRope, $DuringTightRope, $EndTightRope => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$StartWallWalk, $DuringWallWalk, $EndWallWalk =>
SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$Paint => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$ExtendSkitter => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
$ExtendCoordSkitter => SVInputMonitor.NewMotion[controlPoint, NARROW[input.rest.first], viewerToolData];
ENDCASE => {
SVError.Append["Solid viewer: Unknown mouse action.", TRUE, TRUE];
SVError.Blink[];
}
} -- is a Mousepoint
ELSE {
-- not a mouse-point dependent operation
SELECT input.first FROM
$ExtendCurrent => ExtendCurrent[viewerToolData];
$ReloadTipTable => SVViewer.ReloadTipTable[viewerToolData];
$RestartProcess => SVInputMonitor.Restart[];
$ClearAllSelections => SVSelections.KillSkitterAndSelections[viewerToolData.editToolData];
$DeleteSources => DeleteSources[viewerToolData];
$NoOp => {};
$AddCylinder => SVViewerInput.AddCylinder[];
$Skewer => SVViewerInput.Skewer[];
$MoveUntilTouch => SVViewerInput.MoveUntilTouch[];
$ArrowShoot => SVViewerInput.ArrowShoot[];
$DropPerpendicular => DropPerpendicular[];
$VolleyShoot => {};
$JackPivotX => SVViewerInput.JackPivotX[viewerToolData, 90];
$JackPivotY => SVViewerInput.JackPivotY[viewerToolData, 90];
$JackPivotZ => SVViewerInput.JackPivotZ[viewerToolData, 90];
$JackPivotXInverse => SVViewerInput.JackPivotX[viewerToolData, -90];
$JackPivotYInverse => SVViewerInput.JackPivotY[viewerToolData, -90];
$JackPivotZInverse => SVViewerInput.JackPivotZ[viewerToolData, -90];
$SourcePivotX => SVViewerInput.SourcePivotX[viewerToolData, 90];
$SourcePivotY => SVViewerInput.SourcePivotY[viewerToolData, 90];
$SourcePivotZ => SVViewerInput.SourcePivotZ[viewerToolData, 90];
$SourcePivotXInverse => SVViewerInput.SourcePivotX[viewerToolData, -90];
$SourcePivotYInverse => SVViewerInput.SourcePivotY[viewerToolData, -90];
$SourcePivotZInverse => SVViewerInput.SourcePivotZ[viewerToolData, -90];
$SourceRotX => SourceRotX[10];
$SourceRotY => SourceRotY[10];
$SourceRotZ => SourceRotZ[10];
$SourceRotXInverse => SourceRotX[-10];
$SourceRotYInverse => SourceRotY[-10];
$SourceRotZInverse => SourceRotZ[-10];
$CopyRandomToAllTargets => CopyRandomToAllTargets[viewerToolData];
$CopyToAllTargets => CopyToAllTargets[viewerToolData];
$CopyToAllTargetsTree => CopyToAllTargetsTree[viewerToolData];
$MoveToTarget => MoveToTarget[viewerToolData];
$CopyRotate => CopyRotate[];
$CycleTool => CycleTool[];
$SetTool => SetTool[];
$ResetTool => ResetTool[];
$ResetSpheres => ResetSpheres[viewerToolData];
$SetBoundingSpheres => SetBoundingSpheres[viewerToolData];
$SetSphereShadows => SetSphereShadows[viewerToolData];
$SkitterMakes => SkitterMakes[];
$SkitterMakesSource => SkitterMakesSource[viewerToolData];
$SkitterMakesTarget => SkitterMakesTarget[viewerToolData];
$SkitterMakesPlane => SkitterMakesPlane[viewerToolData];
$SkitterMakesSourceIndirect => SkitterMakesSourceIndirect[viewerToolData];
$SkitterMakesTargetIndirect => SkitterMakesTargetIndirect[viewerToolData];
$SkitterMakesSourceIndirectOnly => SkitterMakesSourceIndirectOnly[viewerToolData];
$SkitterMakesTargetIndirectOnly => SkitterMakesTargetIndirectOnly[viewerToolData];
$SkitterMakesPlaneIndirectOnly => SkitterMakesPlaneIndirectOnly[viewerToolData];
ENDCASE => {
SVError.Append["Solid viewer: Unknown command.", TRUE, TRUE];
SVError.Blink[];
}
};
}; -- end of InputNotify
DeleteSources:
PROC [viewerToolData: ViewerToolData] = {
scene: Scene ← viewerToolData.scene;
SVEditUser.DeleteSources[viewerToolData.editToolData];
};
SetBoundingSpheres:
PROC [viewerToolData: ViewerToolData] = {
camera: Camera ← viewerToolData.camera;
camera.useBoundBoxes ← FALSE;
};
SetSphereShadows:
PROC [viewerToolData: ViewerToolData] = {
camera: Camera ← viewerToolData.camera;
camera.useBoundSpheresForShadows ← TRUE;
};
ResetSpheres:
PROC [viewerToolData: ViewerToolData] = {
camera: Camera ← viewerToolData.camera;
camera.useBoundBoxes ← TRUE;
camera.useBoundSpheresForShadows ← FALSE;
};
ComplementSkitter:
PUBLIC
PROC [] = {
viewerToolData: ViewerToolData;
camera: Camera;
DoComplementSkitter:
PROC [dc: Imager.Context] = {
SVSelections.ComplementSkitter[dc, camera];
};
IF NOT SVSelections.IsAliveSkitter[] THEN RETURN;
[----,----,viewerToolData] ← SVSelections.GetSkitterData[];
IF viewerToolData = NIL THEN ERROR;
camera ← viewerToolData.camera;
SVViewerUser.Painter[DoComplementSkitter, viewerToolData];
};
SkitterMakes:
PUBLIC PROC [] = {
viewerToolData: ViewerToolData;
[----,----,viewerToolData] ← SVSelections.GetSkitterData[];
[] ← SkitterMakesAux[viewerToolData];
ComplementSkitter[]; -- erase the skitter
SVSelections.KillSkitter[viewerToolData.editToolData];
};
SkitterMakesAux:
PROC [viewerToolData: ViewerToolData]
RETURNS [coincident: Assembly] = {
Depending on the mode of the skitter, we either create a hook, a floater, or nothing.
scene: Scene ← viewerToolData.scene;
camera: Camera ← viewerToolData.camera;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[];
SELECT skitterMode FROM
surface => {
coincident ← SVSelections.AddHookFromSkitter[];
SVViewerUser.ComplementAssembly[viewerToolData, coincident]; -- Draw the hook
};
tightrope => {
coincident ← SVSelections.AddFloaterFromSkitter[];
SVViewerUser.ComplementAssembly[viewerToolData, coincident]; -- Draw the floater
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[];
};
ENDCASE => ERROR;
};
SkitterMakesSource:
PROC [viewerToolData: ViewerToolData] = {
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.
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[];
scene: Scene ← viewerToolData.scene;
camera: Camera ← viewerToolData.camera;
coincident: Assembly;
movee: Selection;
DrawLatestMovee:
PROC [dc: Imager.Context] = {
SVSelections.ComplementReferentDC[dc, movee, viewerToolData]; -- erase the Jack if any
SVSelections.ComplementSelectionDC[dc, movee, viewerToolData]; -- draw selection instead.
};
coincident ← SkitterMakesAux[viewerToolData];
IF coincident =
NIL
THEN
RETURN;
Will draw the new Jack (if any) into the given viewer.
SELECT skitterMode FROM
surface => {
skitterAssem: Assembly;
[skitterAssem,----,----] ← SVSelections.GetSkitterData[];
movee ← SVSelections.CreateHookMovee[coincident, skitterAssem, viewerToolData];
SVSelections.PushMovee[movee];
};
tightrope => {
movee ← SVSelections.CreateCoordSysMovee[coincident, viewerToolData];
SVSelections.PushMovee[movee];
};
coordframe => {
movee ← SVSelections.CreateCoordSysMovee[coincident, viewerToolData];
SVSelections.PushMovee[movee];
};
ENDCASE => ERROR;
ComplementSkitter[];
SVSelections.KillSkitter[viewerToolData.editToolData];
SVViewerUser.Painter[DrawLatestMovee, viewerToolData];
};
SkitterMakesTarget:
PROC [viewerToolData: ViewerToolData] = {
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.
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[];
scene: Scene ← viewerToolData.scene;
camera: Camera ← viewerToolData.camera;
coincident: Assembly;
target: Selection;
DrawLatestTarget:
PROC [dc: Imager.Context] = {
SVSelections.ComplementReferentDC[dc, target, viewerToolData];
SVSelections.ComplementSelectionDC[dc, target, viewerToolData];
};
coincident ← SkitterMakesAux[viewerToolData]; -- create and draw the jack
IF coincident = NIL THEN RETURN;
SELECT skitterMode FROM
surface => {
skitterAssem: Assembly;
[skitterAssem,----,----] ← SVSelections.GetSkitterData[];
target ← SVSelections.CreateHookTarget[coincident, skitterAssem, viewerToolData];
SVSelections.PushTarget[target];
};
tightrope => {
target ← SVSelections.CreateCoordSysTarget[coincident, viewerToolData];
SVSelections.PushTarget[target];
};
coordframe => {
target ← SVSelections.CreateCoordSysTarget[coincident, viewerToolData];
SVSelections.PushTarget[target];
};
ENDCASE => ERROR;
ComplementSkitter[]; -- erase the skitter
SVSelections.KillSkitter[viewerToolData.editToolData];
SVViewerUser.Painter[DrawLatestTarget, viewerToolData];
};
SkitterMakesPlane:
PROC [viewerToolData: ViewerToolData] = {
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 ← viewerToolData.scene;
camera: Camera ← viewerToolData.camera;
coincident: Assembly;
planeSel: Selection;
DrawLatestPlane:
PROC [dc: Imager.Context] = {
SVSelections.ComplementReferentDC[dc, planeSel, viewerToolData]; -- erase the Jack if any
SVSelections.ComplementSelectionDC[dc, planeSel, viewerToolData]; -- draw selection instead.
};
coincident ← SkitterMakesAux[viewerToolData];
IF coincident =
NIL
THEN
RETURN;
Will draw the new Jack (if any) into the given viewer.
planeSel ← SVSelections.CreatePlaneSelection[coincident, viewerToolData];
SVSelections.PushPlane[planeSel];
ComplementSkitter[];
SVSelections.KillSkitter[viewerToolData.editToolData];
SVViewerUser.Painter[DrawLatestPlane, viewerToolData];
};
SkitterMakesSourceIndirect:
PROC [viewerToolData: ViewerToolData] = {
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.
skitterAssem: Assembly;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[];
indirect: Assembly;
sourceSel: Selection;
camera: Camera ← viewerToolData.camera;
scene: Scene ← viewerToolData.scene;
found: BOOL;
DrawLatestMovee:
PROC [dc: Imager.Context] = {
SVSelections.ComplementSelectionDC[dc, sourceSel, viewerToolData]; -- draw selection.
};
IF skitterMode # coordframe
THEN {
SVError.Append["Can only select indirect with a coordframe skitter.", TRUE, TRUE];
SVError.Blink[];
RETURN;
};
[skitterAssem,----,----] ← SVSelections.GetSkitterData[];
IF skitterAssem.sittingOn =
NIL
THEN {
SVError.Append[Rope.Concat[skitterAssem.name, " is not sitting on anything."], TRUE, TRUE];
SVError.Blink[];
RETURN;
};
[indirect, ----, found] ← SVEditUser.FindAssemblyFromName[skitterAssem.sittingOn, scene];
IF NOT found THEN RETURN;
sourceSel ← SVSelections.CreateHookMovee[skitterAssem, indirect, viewerToolData];
SVSelections.PushMovee[sourceSel];
ComplementSkitter[];
SVSelections.KillSkitter[viewerToolData.editToolData];
SVViewerUser.Painter[DrawLatestMovee, viewerToolData];
};
SkitterMakesTargetIndirect:
PROC [viewerToolData: ViewerToolData] = {
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.
skitterAssem: Assembly;
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[];
indirect: Assembly;
targetSel: Selection;
camera: Camera ← viewerToolData.camera;
scene: Scene ← viewerToolData.scene;
found: BOOL;
DrawLatestTarget:
PROC [dc: Imager.Context] = {
SVSelections.ComplementSelectionDC[dc, targetSel, viewerToolData]; -- draw selection.
};
IF skitterMode # coordframe
THEN {
SVError.Append["Can only select indirect with a coordframe skitter.", TRUE, TRUE];
SVError.Blink[];
RETURN;
};
[skitterAssem,----,----] ← SVSelections.GetSkitterData[];
IF skitterAssem.sittingOn =
NIL
THEN {
SVError.Append[Rope.Concat[skitterAssem.name, " is not sitting on anything."], TRUE, TRUE];
SVError.Blink[];
RETURN;
};
[indirect, ----, found] ← SVEditUser.FindAssemblyFromName[skitterAssem.sittingOn, scene];
IF NOT found THEN RETURN;
targetSel ← SVSelections.CreateHookTarget[skitterAssem, indirect, viewerToolData];
SVSelections.PushTarget[targetSel];
ComplementSkitter[];
SVSelections.KillSkitter[viewerToolData.editToolData];
SVViewerUser.Painter[DrawLatestTarget, viewerToolData];
};
SkitterMakesSourceIndirectOnly:
PROC [viewerToolData: ViewerToolData] = {
Like SkitterMakesSource, except that we don't make any Jacks. Instead, we make a source selection on the skitterAssembly.
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[];
scene: Scene ← viewerToolData.scene;
camera: Camera ← viewerToolData.camera;
coincident: Assembly;
movee: Selection;
DrawLatestMovee:
PROC [dc: Imager.Context] = {
SVSelections.ComplementReferentDC[dc, movee, viewerToolData]; -- erase the Jack if any
SVSelections.ComplementSelectionDC[dc, movee, viewerToolData]; -- draw selection instead.
};
SELECT skitterMode FROM
surface => {
skitterAssem: Assembly;
[skitterAssem,----,----] ← SVSelections.GetSkitterData[];
movee ← SVSelections.CreateCoordSysMovee[skitterAssem, viewerToolData];
SVSelections.PushMovee[movee];
};
tightrope => {
coincident ← SVSelections.AddFloaterFromSkitter[];
SVViewerUser.ComplementAssembly[viewerToolData, coincident]; -- Draw the floater
movee ← SVSelections.CreateCoordSysMovee[coincident, viewerToolData];
SVSelections.PushMovee[movee];
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[];
movee ← SVSelections.CreateCoordSysMovee[coincident, viewerToolData];
SVSelections.PushMovee[movee];
};
ENDCASE => ERROR;
ComplementSkitter[];
SVSelections.KillSkitter[viewerToolData.editToolData];
SVViewerUser.Painter[DrawLatestMovee, viewerToolData];
};
SkitterMakesTargetIndirectOnly:
PROC [viewerToolData: ViewerToolData] = {
Like SkitterMakesTarget, except that we don't make any Jacks for surface skitters. Instead, we make a target selection on the skitterAssembly.
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[];
scene: Scene ← viewerToolData.scene;
camera: Camera ← viewerToolData.camera;
coincident: Assembly;
targetSel: Selection;
DrawLatestMovee:
PROC [dc: Imager.Context] = {
SVSelections.ComplementReferentDC[dc, targetSel, viewerToolData]; -- erase the Jack if any
SVSelections.ComplementSelectionDC[dc, targetSel, viewerToolData]; -- draw selection instead.
};
SELECT skitterMode FROM
surface => {
skitterAssem: Assembly;
[skitterAssem,----,----] ← SVSelections.GetSkitterData[];
targetSel ← SVSelections.CreateCoordSysTarget[skitterAssem, viewerToolData];
SVSelections.PushTarget[targetSel];
};
tightrope => {
coincident ← SVSelections.AddFloaterFromSkitter[];
SVViewerUser.ComplementAssembly[viewerToolData, coincident]; -- Draw the floater
targetSel ← SVSelections.CreateCoordSysTarget[coincident, viewerToolData];
SVSelections.PushTarget[targetSel];
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[];
targetSel ← SVSelections.CreateCoordSysTarget[coincident, viewerToolData];
SVSelections.PushTarget[targetSel];
};
ENDCASE => ERROR;
ComplementSkitter[];
SVSelections.KillSkitter[viewerToolData.editToolData];
SVViewerUser.Painter[DrawLatestMovee, viewerToolData];
};
SkitterMakesPlaneIndirectOnly:
PROC [viewerToolData: ViewerToolData] = {
Like SkitterMakesPlane, except that we don't make any Jacks for surface skitters. Instead, we make a plane selection on the skitterAssembly.
skitterMode: SkitterMode ← SVSelections.GetModeSkitter[];
scene: Scene ← viewerToolData.scene;
camera: Camera ← viewerToolData.camera;
coincident: Assembly;
planeSel: Selection;
DrawLatestPlane:
PROC [dc: Imager.Context] = {
SVSelections.ComplementReferentDC[dc, planeSel, viewerToolData]; -- erase the Jack if any
SVSelections.ComplementSelectionDC[dc, planeSel, viewerToolData]; -- draw selection instead.
};
SELECT skitterMode FROM
surface => {
skitterAssem: Assembly;
[skitterAssem,----,----] ← SVSelections.GetSkitterData[];
planeSel ← SVSelections.CreatePlaneSelection[skitterAssem, viewerToolData];
SVSelections.PushPlane[planeSel];
};
tightrope => {
coincident ← SVSelections.AddFloaterFromSkitter[];
SVViewerUser.ComplementAssembly[viewerToolData, coincident]; -- Draw the floater
planeSel ← SVSelections.CreatePlaneSelection[coincident, viewerToolData];
SVSelections.PushPlane[planeSel];
};
coordframe => {
[coincident,----,----] ← SVSelections.GetSkitterData[];
planeSel ← SVSelections.CreatePlaneSelection[coincident, viewerToolData];
SVSelections.PushPlane[planeSel];
};
ENDCASE => ERROR;
ComplementSkitter[];
SVSelections.KillSkitter[viewerToolData.editToolData];
SVViewerUser.Painter[DrawLatestPlane, viewerToolData];
};
MoveToTarget:
PROC [viewerToolData: ViewerToolData] = {
Move the distinguished source to the distinguished target.
source: Assembly;
dockCS: CoordSystem;
moveeSel, targetSel: Selection;
relativeMat: Matrix4by4;
editToolData: EditToolData ← viewerToolData.editToolData;
scene: Scene ← viewerToolData.scene;
moveeSel ← SVSelections.TopMovee[];
IF moveeSel = NIL THEN RETURN;
targetSel ← SVSelections.TopTarget[];
IF targetSel = NIL THEN RETURN;
IF moveeSel.viewerToolData # targetSel.viewerToolData
THEN {
SVError.Append["Move from viewer to viewer not yet implemented.", TRUE, TRUE];
SVError.Blink[];
RETURN;
};
dockCS ← targetSel.coincident.coordSys;
[----, relativeMat] ← ParentAndPosition[moveeSel, targetSel, scene];
SELECT moveeSel.referentType
FROM
hook => {
source ← moveeSel.indirect;
SVTransforms.TugTransfLeaveTug[source.coordSys, moveeSel.coincident.coordSys, dockCS, relativeMat];
};
coordSys => {
source ← moveeSel.coincident;
SVTransforms.AbsTransf[source.coordSys, dockCS, relativeMat];
};
ENDCASE => ERROR;
SVSelections.ClearMoveeStack[editToolData];
SVSelections.ClearTargetStack[editToolData];
SVEditUser.SceneNewVersion[viewerToolData];
SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, editToolData, scene];
There may be more than one new scene, but for now we'll just repaint the last one.
};
SourceRotX:
PROC [degrees: REAL] = {
sourceSel: Selection;
scene: Scene;
viewerToolData: ViewerToolData;
editToolData: EditToolData;
jack, indirect: Assembly;
sourceSel ← SVSelections.TopMovee[];
IF sourceSel = NIL THEN RETURN;
viewerToolData ← sourceSel.viewerToolData;
editToolData ← viewerToolData.editToolData;
SELECT sourceSel.referentType FROM
hook => {
jack ← sourceSel.coincident;
indirect ← sourceSel.indirect;
};
coordSys => {
jack ← sourceSel.coincident;
indirect ← sourceSel.coincident;
};
ENDCASE => ERROR;
scene ← viewerToolData.scene;
SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect];
SVTransforms.XRotate[indirect.coordSys, jack.coordSys, degrees, TRUE];
SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect];
};
SourceRotY:
PROC [degrees: REAL] = {
sourceSel: Selection;
scene: Scene;
viewerToolData: ViewerToolData;
editToolData: EditToolData;
jack, indirect: Assembly;
sourceSel ← SVSelections.TopMovee[];
IF sourceSel = NIL THEN RETURN;
viewerToolData ← sourceSel.viewerToolData;
editToolData ← viewerToolData.editToolData;
SELECT sourceSel.referentType FROM
hook => {
jack ← sourceSel.coincident;
indirect ← sourceSel.indirect;
};
coordSys => {
jack ← sourceSel.coincident;
indirect ← sourceSel.coincident;
};
ENDCASE => ERROR;
scene ← viewerToolData.scene;
SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect];
SVTransforms.YRotate[indirect.coordSys, jack.coordSys, degrees, TRUE];
SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect];
};
SourceRotZ:
PROC [degrees: REAL] = {
sourceSel: Selection;
scene: Scene;
viewerToolData: ViewerToolData;
editToolData: EditToolData;
jack, indirect: Assembly;
sourceSel ← SVSelections.TopMovee[];
IF sourceSel = NIL THEN RETURN;
viewerToolData ← sourceSel.viewerToolData;
editToolData ← viewerToolData.editToolData;
SELECT sourceSel.referentType FROM
hook => {
jack ← sourceSel.coincident;
indirect ← sourceSel.indirect;
};
coordSys => {
jack ← sourceSel.coincident;
indirect ← sourceSel.coincident;
};
ENDCASE => ERROR;
scene ← viewerToolData.scene;
SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect];
SVTransforms.ZRotate[indirect.coordSys, jack.coordSys, degrees, TRUE];
SVEditUser.PaintAssemblyAllViewers[SVViewerUser.DrawAssemblyXOR, editToolData, scene, indirect];
};
CopyToAllTargets:
PROC [viewerToolData: ViewerToolData] = {
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: Assembly;
moveeSel: Selection;
editToolData: EditToolData ← viewerToolData.editToolData;
oldScene, newScene: Scene;
dockCS: CoordSystem;
relativeMat: Matrix4by4;
targets: SelectionGenerator;
targetsExist: BOOL;
moveeSel ← SVSelections.TopMovee[];
IF moveeSel = NIL THEN RETURN;
oldScene ← moveeSel.viewerToolData.scene;
SELECT moveeSel.referentType
FROM
hook => moveeOriginal ← moveeSel.indirect;
coordSys => moveeOriginal ← moveeSel.coincident;
ENDCASE => ERROR;
[----, moveeParent] ← DisplayList3d.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 {
SVError.Append["Please make some targets to copy to.", TRUE, TRUE];
SVError.Blink[];
RETURN;
};
FOR targetSel: Selection ← SVSelections.NextSelection[targets], SVSelections.NextSelection[targets]
UNTIL targetSel =
NIL
DO
newScene ← targetSel.viewerToolData.scene;
IF newScene = oldScene
THEN {
parent ← moveeParent;
[----, relativeMat] ← ParentAndPosition[moveeSel, targetSel, newScene];
}
ELSE [
parent,
relativeMat] ← ParentAndPosition[moveeSel, targetSel, newScene];
dockCS ← targetSel.coincident.coordSys;
moveeCopy ← DisplayList3d.CopyAssemblyAndSonsUniqueNames[moveeOriginal, oldScene, newScene, parent];
SVTransforms.Normalize[moveeCopy.coordSys, moveeOriginal.coordSys];
SELECT moveeSel.referentType FROM
hook => SVTransforms.TugTransfLeaveTug[moveeCopy.coordSys, moveeSel.coincident.coordSys, dockCS, relativeMat];
coordSys => SVTransforms.AbsTransf[moveeCopy.coordSys, dockCS, relativeMat];
ENDCASE => ERROR;
ENDLOOP;
SVSelections.ClearTargetStack[editToolData];
SVEditUser.SceneNewVersion[viewerToolData];
SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, editToolData, newScene];
There may be more than one new scene, but for now we'll just repaint the last one.
};
CopyRotate:
PROC [] = {
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: Assembly;
sourceSel, planeSel: Selection;
viewerToolData: ViewerToolData;
planeAssem: Assembly;
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.viewerToolData # planeSel.viewerToolData
THEN {
SVError.Append["Can't copy rotate between viewers.", TRUE, TRUE];
SVError.Blink[];
RETURN;
};
viewerToolData ← sourceSel.viewerToolData;
scene ← viewerToolData.scene;
editToolData ← viewerToolData.editToolData;
sourceCS ← sourceSel.coincident.coordSys;
planeCS ← planeSel.coincident.coordSys;
numberOfCopies ← SVViewerTools.GetNat[viewerToolData.textSection.xyz];
numberOfCopiesReal ← numberOfCopies;
SELECT sourceSel.referentType
FROM
hook => moveeOriginal ← sourceSel.indirect;
coordSys => moveeOriginal ← sourceSel.coincident;
ENDCASE => ERROR;
[----, moveeParent] ← DisplayList3d.FindAssemblyFromName[moveeOriginal.name, scene];
deltaDegrees ← 360/numberOfCopiesReal;
FOR i:
NAT
IN [1..numberOfCopies-1]
DO
realI ← i;
degrees ← i*deltaDegrees;
copy ← DisplayList3d.CopyAssemblyAndSonsUniqueNames[moveeOriginal, scene, scene, moveeParent];
SVTransforms.Normalize[copy.coordSys, moveeOriginal.coordSys];
SELECT toolData.plane FROM
1 => SVTransforms.XRotate[copy.coordSys, planeCS, degrees];
2 => SVTransforms.YRotate[copy.coordSys, planeCS, degrees];
3, 4 => SVTransforms.ZRotate[copy.coordSys, planeCS, degrees];
ENDCASE => ERROR;
ENDLOOP;
SVEditUser.SceneNewVersion[viewerToolData];
SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, editToolData, scene];
There may be more than one new scene, but for now we'll just repaint the last one.
}; -- end of CopyRotate
CopyToAllTargetsTree:
PROC [viewerToolData: ViewerToolData] = {
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: Assembly;
moveeSel: Selection;
editToolData: EditToolData ← viewerToolData.editToolData;
oldScene, newScene: Scene;
dockCS: CoordSystem;
relativeMat: Matrix4by4;
targets: SelectionGenerator;
targetsExist: BOOL;
moveeSel ← SVSelections.TopMovee[];
IF moveeSel = NIL THEN RETURN;
oldScene ← moveeSel.viewerToolData.scene;
SELECT moveeSel.referentType
FROM
hook => moveeOriginal ← moveeSel.indirect;
coordSys => moveeOriginal ← moveeSel.coincident;
ENDCASE => ERROR;
[----, moveeParent] ← DisplayList3d.FindAssemblyFromName[moveeOriginal.name, oldScene];
[targets, targetsExist] ← SVSelections.GetSelectionGenerator[target];
IF
NOT targetsExist
THEN {
SVError.Append["Please make some targets to copy to.", TRUE, TRUE];
SVError.Blink[];
RETURN;
};
FOR targetSel: Selection ← SVSelections.NextSelection[targets], SVSelections.NextSelection[targets]
UNTIL targetSel =
NIL
DO
newScene ← targetSel.viewerToolData.scene;
[
parent,
relativeMat] ← ParentAndPosition[moveeSel, targetSel, newScene];
dockCS ← targetSel.coincident.coordSys;
moveeCopy ← DisplayList3d.CopyAssemblyAndSonsUniqueNames[moveeOriginal, oldScene, newScene, parent];
SVTransforms.Normalize[moveeCopy.coordSys, moveeOriginal.coordSys];
SELECT moveeSel.referentType FROM
hook => SVTransforms.TugTransfLeaveTug[moveeCopy.coordSys, moveeSel.coincident.coordSys, dockCS, relativeMat];
coordSys => SVTransforms.AbsTransf[moveeCopy.coordSys, dockCS, relativeMat];
ENDCASE => ERROR;
ENDLOOP;
SVSelections.ClearTargetStack[editToolData];
SVEditUser.SceneNewVersion[viewerToolData];
SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, 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: Assembly,
relativeMat: Matrix4by4] = {
target: Assembly;
SELECT targetSel.referentType FROM
hook => {
[target, parent] ← DisplayList3d.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] ← DisplayList3d.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 [viewerToolData: ViewerToolData] = {
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: Assembly;
moveeSel: Selection;
editToolData: EditToolData ← viewerToolData.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.viewerToolData.scene;
[min, max, ----] ← SVViewerTools.GetThreeReals[editToolData.transformSection.scaleXYZ];
SELECT moveeSel.referentType
FROM
hook => moveeOriginal ← moveeSel.indirect;
coordSys => moveeOriginal ← moveeSel.coincident;
ENDCASE => ERROR;
[----, moveeParent] ← DisplayList3d.FindAssemblyFromName[moveeOriginal.name, oldScene];
[targets, targetsExist] ← SVSelections.GetSelectionGenerator[target];
IF
NOT targetsExist
THEN {
SVError.Append["Please make some targets to copy to.", TRUE, TRUE];
SVError.Blink[];
RETURN;
};
FOR targetSel: Selection ← SVSelections.NextSelection[targets], SVSelections.NextSelection[targets]
UNTIL targetSel =
NIL
DO
newScene ← targetSel.viewerToolData.scene;
IF newScene = oldScene
THEN {
parent ← moveeParent;
[----, relativeMat] ← ParentAndPosition[moveeSel, targetSel, newScene];
}
ELSE [
parent,
relativeMat] ← ParentAndPosition[moveeSel, targetSel, newScene];
dockCS ← targetSel.coincident.coordSys;
moveeCopy ← DisplayList3d.CopyAssemblyAndSonsUniqueNames[moveeOriginal, oldScene, newScene, parent];
SELECT moveeSel.referentType FROM
hook => SVTransforms.TugTransfLeaveTug[moveeCopy.coordSys, moveeSel.coincident.coordSys, dockCS, relativeMat];
coordSys => SVTransforms.AbsTransf[moveeCopy.coordSys, dockCS, relativeMat];
ENDCASE => ERROR;
randomDegrees ← RandomAngle[];
randomScalar ← RandomScalar[min, max];
SVTransforms.ZRotate[moveeCopy.coordSys, dockCS, randomDegrees];
SVTransforms.ScaleEven[moveeCopy, dockCS, randomScalar];
SVSelections.ClearTargetStack[editToolData];
SVEditUser.SceneNewVersion[viewerToolData];
SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, editToolData, newScene];
There may be more than one new scene, but for now we'll just repaint the last one.
};
ComplementBoundBox: PUBLIC PROC [boundBox: BoundBox, viewerToolData: ViewerToolData] = TRUSTED {
camera: Camera ← viewerToolData.camera;
screen: CoordSystem ← camera.screenCS;
DoComplementBoundBox: SAFE PROC [dc: Imager.Context] = TRUSTED {
SVBoundBox.ComplementBoundBox[dc, boundBox, screen];
};
SVViewerUser.Painter[DoComplementBoundBox, viewerToolData];
};
ExtendCurrent:
PUBLIC
PROC [viewerToolData: ViewerToolData] =
TRUSTED {
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: Assembly;
prim: Primitive;
assemblyName: Rope.ROPE;
success: BOOL;
editToolData ← viewerToolData.editToolData;
scene ← viewerToolData.scene;
[assembly, prim, viewerToolData] ← SVSelections.GetSkitterData[];
IF assembly = NIL THEN RETURN;
assemblyName ← assembly.name;
[assembly, parent, success] ← SVEditUser.FindAssemblyFromName[assemblyName, scene];
IF
NOT success
THEN {
SVError.Append[Rope.Cat["ExtendCurrent: assembly ", assemblyName, " not found."], TRUE, TRUE];
SVError.Blink[];
RETURN;
};
SVSelections.UpdateSkitter[parent, prim, viewerToolData];
};
ParentOfSkitter:
PROC [] =
TRUSTED {
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.
viewerToolData: ViewerToolData;
editToolData: EditToolData;
scene: Scene;
assembly, realAssembly, parent: Assembly;
prim: Primitive;
[realAssembly, prim, viewerToolData] ← SVSelections.GetSkitterData[];
editToolData ← viewerToolData.editToolData;
scene ← viewerToolData.scene;
IF realAssembly = NIL THEN RETURN;
[assembly, parent] ← DisplayList3d.FindAssemblyFromName[realAssembly.name, scene];
IF assembly # realAssembly THEN ERROR;
IF parent#NIL THEN SVSelections.UpdateSkitter[parent, prim, viewerToolData];
};
SetTool:
PUBLIC
PROC =
TRUSTED {
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;
viewerToolData: ViewerToolData;
planeAssem: Assembly;
planeSel: Selection;
scene: Scene;
planeSel ← SVSelections.TopPlane[];
IF planeSel =
NIL
THEN {
SVError.Append["SetTool: Make a plane selection first", TRUE, TRUE];
SVError.Blink[];
RETURN;
};
planeAssem ← planeSel.coincident;
viewerToolData ← planeSel.viewerToolData;
scene ← viewerToolData.scene;
editToolData ← NARROW[viewerToolData.editToolData];
planeAssem.showAs ← tool;
DisplayList3d.AddOrResizeToolToAssembly[planeAssem, scene];
SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, editToolData, scene];
}; -- end of SetTool
ResetTool:
PUBLIC
PROC =
TRUSTED {
The current movee selection assembly is now a non-tool. It will once again appear as its regular shape.
editToolData: EditToolData;
viewerToolData: ViewerToolData;
planeAssem: Assembly;
planeSel: Selection;
scene: Scene;
planeSel ← SVSelections.TopPlane[];
IF planeSel =
NIL
THEN {
SVError.Append["ResetTool: Make a plane selection first", TRUE, TRUE];
SVError.Blink[];
RETURN;
};
planeAssem ← planeSel.coincident;
viewerToolData ← planeSel.viewerToolData;
scene ← viewerToolData.scene;
editToolData ← NARROW[viewerToolData.editToolData];
planeAssem.showAs ← normal;
SVEditUser.SceneNewVersion[viewerToolData];
SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, editToolData, scene];
};
CycleTool:
PUBLIC
PROC =
TRUSTED {
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;
viewerToolData: ViewerToolData;
planeAssem: Assembly;
planeSel: Selection;
scene: Scene;
camera: Camera;
toolData: ToolData;
DrawNewPlane: PROC [dc: Imager.Context] = {
SVSelections.ComplementSelectionDC[dc, planeSel, viewerToolData];
};
planeSel ← SVSelections.TopPlane[];
IF planeSel =
NIL
THEN {
SVError.Append["CycleTool: Make a plane selection first", TRUE, TRUE];
SVError.Blink[];
RETURN;
};
planeAssem ← planeSel.coincident;
viewerToolData ← planeSel.viewerToolData;
camera ← viewerToolData.camera;
scene ← viewerToolData.scene;
editToolData ← NARROW[viewerToolData.editToolData];
IF planeAssem.toolMasterObject =
NIL
OR planeAssem.toolMasterObject.mainBody =
NIL
THEN
DisplayList3d.AddOrResizeToolToAssembly[planeAssem, scene];
toolData ← NARROW[planeAssem.toolMasterObject.mainBody];
SVViewerUser.Painter[DrawNewPlane, viewerToolData];
toolData.plane ← IF toolData.plane = 3 THEN 1 ELSE toolData.plane + 1;
SVViewerUser.Painter[DrawNewPlane, viewerToolData];
Indicate the currently selected plane in the message window.
SELECT toolData.plane FROM
1 => SVError.Append[Rope.Cat["x = 0 plane of ", planeAssem.name, " now selected."], TRUE, TRUE];
2 => SVError.Append[Rope.Cat["y = 0 plane of ", planeAssem.name, " now selected."], TRUE, TRUE];
3 => SVError.Append[Rope.Cat["z = 0 plane of ", planeAssem.name, " now selected."], TRUE, TRUE];
4 => SVError.Append[Rope.Cat["All planes of ", planeAssem.name, " now selected."], TRUE, TRUE];
ENDCASE => ERROR;
IF planeAssem.showAs = tool
OR planeAssem.showAs = both
THEN
SVEditUser.PaintSceneAllViewers[SVViewerUser.EraseAndDrawSceneEtc, editToolData, scene];
};
DropPerpendicular:
PROC =
TRUSTED {
sourceSel, planeSel: Selection;
toolData: ToolData;
planeAssem: Assembly;
scene: Scene;
camera: Camera;
viewerToolData: ViewerToolData;
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;
viewerToolData ← planeSel.viewerToolData;
camera ← viewerToolData.camera;
scene ← viewerToolData.scene;
IF planeAssem.toolMasterObject =
NIL
OR planeAssem.toolMasterObject.mainBody =
NIL
THEN
DisplayList3d.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;
SVViewerInput.ComplementSkitter[]; -- erase any old skitter
selectionMat ← CoordSys.FindInTermsOfWorld[planeSel.coincident.coordSys];
selectionMat ← Matrix3d.LocalTranslate[selectionMat, interceptPlane[1], interceptPlane[2], interceptPlane[3]];
SVSelections.UpdateSkitter[NIL, NIL, viewerToolData];
SVSelections.PositionSkitter[[0,0], selectionMat]; -- update skitterWORLD
SVSelections.SetModeSkitter[tightrope];
SVViewerInput.ComplementSkitter[]; -- draw new skitter
SVViewerInput.SkitterMakes[]; -- sceneAssembly will be the parent of the new jack.
};
END.