File: SVEventImplA.mesa
Author: Eric Bier in October 1982
Copyright © 1984 by Xerox Corporation. All rights reserved.
Last edited by Bier on July 12, 1987 11:39:13 pm PDT
Contents: Code to respond to button presses made in an SVViewer
DIRECTORY
AtomButtons, AtomButtonsTypes, Basics, BasicTime, CodeTimer, Containers, CoordSys, DisplayListToTree, Feedback, FileNames, FS, Imager, IO, Menus, Random, Real, Rope, SlackProcess, SV2d, SV3d, SVAlign, SVAssembly, SVBasicTypes, SVCaret, SVCastRays, SVDrawMonitor, SVEditUser, SVEvent, SVFiles, SVGravity, SVInterfaceTypes, SVModelTypes, SVMouseEvent, SVRefresh, SVScene, SVSceneTypes, SVSelect, SVSelections, SVSessionLog, SVState, SVUserInput, SVUtility, SVViewersOnScene, SVViewerTool, SVWindow, TFO3d, ViewerClasses, ViewerOps, ViewerTools;
SVEventImplA:
CEDAR
PROGRAM
IMPORTS AtomButtons, BasicTime, CodeTimer, CoordSys, DisplayListToTree, Feedback, FileNames, FS, IO, Random, Rope, SlackProcess, SVAlign, SVAssembly, SVCaret, SVCastRays, SVEditUser, SVEvent, SVFiles, SVGravity, SVMouseEvent, SVRefresh, SVScene, SVSelect, SVSelections, SVSessionLog, SVState, SVUserInput, SVUtility, SVViewersOnScene, SVWindow, TFO3d, ViewerOps, ViewerTools
EXPORTS SVEvent =
BEGIN
AlignBag: TYPE = SVInterfaceTypes.AlignBag;
BoundBox: TYPE = SVBasicTypes.BoundBox;
Camera: TYPE = SVModelTypes.Camera;
Color: TYPE = Imager.Color;
CoordSysGenerator: TYPE = SVScene.CoordSysGenerator;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
CSGTree: TYPE = SVSceneTypes.CSGTree;
DisplayContextProc: TYPE = SVInterfaceTypes.DCProc;
DrawStyle: TYPE = SVModelTypes.DrawStyle;
EditToolData: TYPE = SVInterfaceTypes.EditToolData;
FeatureData: TYPE = SVInterfaceTypes.FeatureData;
FeedbackData: TYPE = AtomButtonsTypes.FeedbackData;
FileCamera: TYPE = SVSceneTypes.FileCamera;
GravityType: TYPE = SVInterfaceTypes.GravityType;
MasterObject: TYPE = SVSceneTypes.MasterObject;
Matrix4by4: TYPE = SV3d.Matrix4by4;
MouseButton: TYPE = Menus.MouseButton;
Point2d: TYPE = SV2d.Point2d;
Point3d: TYPE = SV3d.Point3d;
Primitive: TYPE = SVSceneTypes.Primitive;
Scene: TYPE = SVSceneTypes.Scene;
Slice: TYPE = SVSceneTypes.Slice;
SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor;
SliceDescriptorGenerator: TYPE = SVSceneTypes.SliceDescriptorGenerator;
SortedButtonHandle: TYPE = AtomButtonsTypes.SortedButtonHandle;
TriggerBag: TYPE = SVInterfaceTypes.TriggerBag;
TwoState: TYPE = AtomButtons.TwoState;
Vector2d: TYPE = SV2d.Vector2d;
Vector3d: TYPE = SV3d.Vector3d;
Viewer: TYPE = ViewerClasses.Viewer;
SVData: TYPE = SVInterfaceTypes.SVData;
Gravity Line Operations
GravityChoiceChange:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
forward: BOOL ← event.rest.first = $FlipForward;
SVState.CycleGravityType[svData, forward];
};
GravityExtentChange:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
extent: REAL ← SVState.GetGravityExtent[svData]; -- in inches
success: BOOL ← TRUE;
SELECT event.rest.first
FROM
$ValueUp => {
IF extent < 256.0 THEN extent ← extent*2.0
ELSE {
Feedback.PutF[svData.feedback, oneLiner, "Can't extend gravity further than 256 inches."];
Feedback.Blink[svData.feedback];
success ← FALSE;
};
};
$ValueDown => extent ← extent/2.0;
ENDCASE => extent ← SVEditUser.GetDefaultGravityExtent[];
IF success
THEN {
SVState.SetGravityExtent[svData, extent];
};
};
ToggleGravity:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVState.ToggleGravity[svData];
};
ToggleMidpoints:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVState.ToggleMidpoints[svData];
};
Alignment Lines
InitializeAlignments:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
AllAlignmentsOff[NIL, svData];
SVState.SetShowAlignments[svData, TRUE];
SVState.SetGravity[svData, TRUE];
SVState.SetGravityType[svData, pointsPreferred];
SVEvent.InchScaleUnit[NIL, svData];
SVState.SetHeuristics[svData, TRUE];
};
AllAlignmentsOff:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SlopeLinePrompt[event, svData];
SlopePlanePrompt[event, svData];
SVState.SetMidpoints[svData, FALSE];
};
StandardSlopes:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
AtomButtons.BuildScalarButtons[svData.hitTest.slopeHandle, svData, SVUserInput.EventNotify,
NIL,
LIST[
["", 999.9, LIST[$NoOp, NEW[REAL ← 999.9]], FALSE], -- dummy first button
["150", 150.0, LIST[LIST[$ChooseSlope, NEW[REAL ← 150.0]]], FALSE],
["135", 135.0, LIST[LIST[$ChooseSlope, NEW[REAL ← 135.0]]], FALSE],
["120", 120.0, LIST[LIST[$ChooseSlope, NEW[REAL ← 120.0]]], FALSE],
["90", 90.0, LIST[LIST[$ChooseSlope, NEW[REAL ← 90.0]]], FALSE],
["60", 60.0, LIST[LIST[$ChooseSlope, NEW[REAL ← 60.0]]], FALSE],
["45", 45.0, LIST[LIST[$ChooseSlope, NEW[REAL ← 45.0]]], FALSE],
["30", 30.0, LIST[LIST[$ChooseSlope, NEW[REAL ← 30.0]]], FALSE],
["0", 0.0, LIST[LIST[$ChooseSlope, NEW[REAL ← 0.0]]], TRUE]
]];
};
StandardAzimuths:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
AtomButtons.BuildScalarButtons[svData.hitTest.azimuthHandle, svData, SVUserInput.EventNotify,
NIL,
LIST[
["", 999.9, LIST[$NoOp, NEW[REAL ← 999.9]], FALSE], -- dummy first button
["150", 150.0, LIST[LIST[$ChooseAzimuth, NEW[REAL ← 150.0]]], FALSE],
["135", 135.0, LIST[LIST[$ChooseAzimuth, NEW[REAL ← 135.0]]], FALSE],
["120", 120.0, LIST[LIST[$ChooseAzimuth, NEW[REAL ← 120.0]]], FALSE],
["90", 90.0, LIST[LIST[$ChooseAzimuth, NEW[REAL ← 90.0]]], FALSE],
["60", 60.0, LIST[LIST[$ChooseAzimuth, NEW[REAL ← 60.0]]], FALSE],
["45", 45.0, LIST[LIST[$ChooseAzimuth, NEW[REAL ← 45.0]]], FALSE],
["30", 30.0, LIST[LIST[$ChooseAzimuth, NEW[REAL ← 30.0]]], FALSE],
["0", 0.0, LIST[LIST[$ChooseAzimuth, NEW[REAL ← 0.0]]], TRUE]
]];
};
StandardSlopeLines:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
AtomButtons.BuildSortedButtons[svData.hitTest.slopeLineHandle, svData, SVUserInput.EventNotify,
NIL,
LIST[
["(0 0)",NEW[Vector2d←[0,0]], LIST[LIST[$ToggleSlopeLine,NEW[Vector2d←[0,0]]]],TRUE],
["(0 90)",NEW[Vector2d←[0,90]],LIST[LIST[$ToggleSlopeLine,NEW[Vector2d←[0,90]]]],FALSE],
["(90 0)",NEW[Vector2d←[90,0]], LIST[LIST[$ToggleSlopeLine,NEW[Vector2d←[90,0]]]],FALSE]
]];
IF event.first = $StandardSlopeLines
THEN
SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsDeselected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
StandardSlopePlanes:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
AtomButtons.BuildSortedButtons[svData.hitTest.slopePlaneHandle, svData, SVUserInput.EventNotify,
NIL,
LIST[
["(0 0)",NEW[Vector2d←[0,0]],LIST[LIST[$ToggleSlopePlane,NEW[Vector2d←[0,0]]]],FALSE],
["(0 90)",NEW[Vector2d←[0,90]],LIST[LIST[$ToggleSlopePlane,NEW[Vector2d←[0,90]]]],FALSE],
["(90 0)",NEW[Vector2d←[90,0]],LIST[LIST[$ToggleSlopePlane,NEW[Vector2d←[90,0]]]],TRUE]
]];
IF event.first = $StandardSlopePlanes
THEN
SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsDeselected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
Azimuth Line
AzimuthPrompt:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
};
GetAzimuth:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
};
AddAzimuth:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
adds azimuth from azimuth viewer in measure line
If azimuthViewValue was set internally, viewer and value will be consistent.
If AzimuthValue viewer was set by typein, viewer and value will be inconsistent.
azimuth: REAL;
success, alreadyThere: BOOL;
[azimuth, success] ← SVState.GetAzimuthValue[svData];
IF NOT success THEN RETURN;
alreadyThere ← SVState.AddAzimuth[svData, azimuth];
IF
NOT alreadyThere
THEN {
-- a new button was added
SVWindow.RestoreScreenAndInvariants[paintAction: $None, svData: svData, remake: none, backgndOK: TRUE, edited: TRUE, okToClearFeedback: TRUE];
};
};
DeleteAzimuth:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVState.DeleteAzimuth[svData];
SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsDeselected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
ChooseAzimuth:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
azimuth: REAL ← NARROW[event.rest.first, REF REAL]^;
AtomButtons.SetAllScalarStates[svData, svData.hitTest.azimuthHandle, FALSE];
AtomButtons.SetScalarState[svData, svData.hitTest.azimuthHandle, azimuth, TRUE];
};
Slope Line
SlopePrompt:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Since slopes are mutually exclusive, there is no reason to turn them all off. We could set the slope to 0 or do nothing at all.
};
GetSlope:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
};
AddSlope:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
adds slope from angle viewer in measure line
If slopeViewValue was set internally, viewer and value will be consistent.
If SlopeValue viewer was set by typein, viewer and value will be inconsistent.
slope: REAL;
success, alreadyThere: BOOL;
[slope, success] ← SVState.GetSlopeValue[svData];
IF NOT success THEN RETURN;
alreadyThere ← SVState.AddSlope[svData, slope];
IF
NOT alreadyThere
THEN {
-- a new button was added
SVWindow.RestoreScreenAndInvariants[paintAction: $None, svData: svData, remake: none, backgndOK: TRUE, edited: TRUE, okToClearFeedback: TRUE];
};
};
DeleteSlope:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVState.DeleteSlope[svData];
SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsDeselected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
ChooseSlope:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
slope: REAL ← NARROW[event.rest.first, REF REAL]^;
AtomButtons.SetAllScalarStates[svData, svData.hitTest.slopeHandle, FALSE];
AtomButtons.SetScalarState[svData, svData.hitTest.slopeHandle, slope, TRUE];
};
Slope Line Line
SlopeLinePrompt:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
AtomButtons.SetAllScalarStates[svData, svData.hitTest.slopeLineHandle, FALSE];
IF event.first = $SlopeLinePrompt THEN SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsDeselected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
GetSlopeLine:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
};
AddSlopeLine:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
AddAzimuth[event, svData];
AddSlope[event, svData];
NewSlopeLine[event, svData];
};
NewSlopeLine:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
azimuth, slope: REAL;
alreadyThere: BOOL;
azimuth ← SVState.GetSelectedAzimuth[svData];
slope ← SVState.GetSelectedSlope[svData];
alreadyThere ← SVState.AddSlopeLine[svData, azimuth, slope];
SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsSelected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
DeleteSlopeLine:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVState.DeleteSlopeLines[svData];
SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsDeselected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
ToggleSlopeLine:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
restoreNow: BOOL ← event.first = $ToggleSlopeLine;
ToggleAlignmentAux[event, svData, svData.hitTest.slopeLineHandle, restoreNow];
};
ToggleAlignmentAux:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData, handle: SortedButtonHandle, restoreNow:
BOOL] = {
FindAzimuthSlope:
PROC [state:
BOOL, name: Rope.
ROPE, value:
REF
ANY, clientData:
REF
ANY]
RETURNS [newState:
BOOL, newName: Rope.
ROPE ←
NIL, newValue:
REF
ANY, done:
BOOL ←
FALSE] = {
azimuthSlope: Vector2d ← NARROW[value, REF Vector2d]^;
IF ABS[azimuthSlope[1]-azimuth] < epsilon AND ABS[azimuthSlope[2]-slope] < epsilon
THEN {totalNewState ← newState ← NOT state; done ← TRUE}
ELSE newState ← state;
newName ← name;
newValue ← value;
};
epsilon: REAL = 0.001;
totalNewState: BOOL;
azimuth, slope: REAL;
azimuthSlope: Vector2d;
azimuthSlope ← NARROW[event.rest.first, REF Vector2d]^;
azimuth ← azimuthSlope[1];
slope ← azimuthSlope[2];
AtomButtons.WriteSortedButtons[handle, FindAzimuthSlope, svData];
IF restoreNow
AND totalNewState
THEN
SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsSelected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE]
ELSE SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsDeselected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
Slope Plane Line
SlopePlanePrompt:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
AtomButtons.SetAllScalarStates[svData, svData.hitTest.slopePlaneHandle, FALSE];
IF event.first = $SlopePlanePrompt THEN SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsDeselected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
GetSlopePlane:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
};
AddSlopePlane:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
AddAzimuth[event, svData];
AddSlope[event, svData];
NewSlopePlane[event, svData];
};
NewSlopePlane:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
azimuth, slope: REAL;
alreadyThere: BOOL;
azimuth ← SVState.GetSelectedAzimuth[svData];
slope ← SVState.GetSelectedSlope[svData];
alreadyThere ← SVState.AddSlopePlane[svData, azimuth, slope];
SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsSelected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
DeleteSlopePlane:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVState.DeleteSlopePlanes[svData];
SVWindow.RestoreScreenAndInvariants[paintAction: $NewAlignmentsDeselected, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
ToggleSlopePlane:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
restoreNow: BOOL ← event.first = $ToggleSlopePlane;
ToggleAlignmentAux[event, svData, svData.hitTest.slopePlaneHandle, restoreNow];
};
MISCELLANEOUS
Painter:
PUBLIC
PROC [proc: DisplayContextProc, svData: SVData ←
NIL] = {
}; -- end of Painter
UpdateHeader:
PUBLIC
PROC [pictureFile: Rope.
ROPE, svData: SVData] = {
headerRope: Rope.ROPE;
aisName: Rope.ROPE;
viewName: Rope.ROPE ← svData.camera.viewName;
IF pictureFile = NIL THEN pictureFile ← svData.scene.name;
headerRope ← Rope.Cat[viewName, " View of Solid Scene: ", pictureFile];
aisName ← Rope.Concat[SVFiles.FilenameMinusExtension[pictureFile], ".ais"];
svData.outer.name ← headerRope;
ViewerOps.PaintViewer[svData.outer, caption, FALSE, NIL];
};
NewVersion:
PUBLIC
PROC [viewer: Viewer] = {
svData: SVData ← NARROW[viewer.data];
scene: Scene ← svData.scene;
scene.dirty ← TRUE;
svData.scene.tree.outOfDate ← TRUE;
svData.outer.newVersion ← TRUE;
UpdateHeader[scene.name, svData];
};
SceneOldVersion:
PUBLIC
PROC [svData: SVData] = {
Tell EditTool that scene is no longer dirty. EditTool will call back all affected viewers using OldVersion (see below).
scene: Scene ← svData.scene;
SVViewersOnScene.SceneOldVersion[svData, scene];
};
OldVersion:
PUBLIC
PROC [viewer: Viewer] = {
svData: SVData ← NARROW[viewer.data];
scene: Scene ← svData.scene;
scene.dirty ← FALSE;
svData.scene.tree.outOfDate ← TRUE; -- OldVersion may result from loading a new scene, or creating an empty scene. In either case, the ray tracing tree is out of date. Set flag just in case.
svData.outer.newVersion ← FALSE;
UpdateHeader[scene.name, svData];
};
DRAW SOMETHING IN A SOLID VIEWER (Fetches a display context first)
EraseAndDrawScene:
PUBLIC
PROC [svData: SVData] = {
SVWindow.RestoreScreenAndInvariants[$PaintEntireScene, svData];
};
MENU PROCS
DrawSceneButton:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVWindow.RestoreScreenAndInvariants[$PaintEntireScene, svData];
};
Clear:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Creates a new empty scene for the viewer to view.
editToolData: EditToolData ← svData.editToolData;
oldScene: Scene ← svData.scene;
newScene: Scene;
oldScreenCS: CoordSystem;
fileCamera: FileCamera;
cameraName: Rope.ROPE;
drawStyle: DrawStyle;
oldScreenCS ← svData.camera.screenCS;
newScene ← svData.scene ← SVScene.CreateScene["NoName.pic"];
SVSelections.KillSkitterAndSelections[editToolData];
UpdateHeader[newScene.name, svData];
SVEvent.Selected[event, svData];
IF newScene.cameraOrder = NIL THEN fileCamera ← newScene.cameras.first
ELSE {
success: BOOL;
cameraName ← newScene.cameraOrder.first;
[fileCamera, success] ← SVScene.FindFileCameraFromName[cameraName, newScene];
IF
NOT success
THEN {
fileCamera ← newScene.cameras.first;
Feedback.Append[svData.feedback, Rope.Cat["Camera ", cameraName, " not found"], oneLiner];
Feedback.Blink[svData.feedback];
};
};
drawStyle ← SVEvent.CurrentStyle[svData];
svData.camera ← SVScene.CreateCamera[newScene.coordSysRoot, CoordSys.CopyCoordSysFromAnyTree[oldScreenCS, "SCREEN", NIL, NIL], drawStyle];
SVScene.StuffCameraFromFileCamera[svData.camera, fileCamera, svData.camera.style, newScene];
SVViewersOnScene.NotifyOfEmpty[svData: svData, from: oldScene, to: svData.scene];
SceneOldVersion[svData];
This must be done after NotifyOfEmpty since SVViewersOnScene expects to register to the newly created NoName scene before it resets the [New Version] headers.
SVWindow.RestoreScreenAndInvariants[$PaintEntireScene, svData];
};
Restore:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
editToolData: EditToolData ← svData.editToolData;
success: BOOL;
wdir: Rope.ROPE;
scene: Scene ← svData.scene;
wdir ← editToolData.originalWorkingDirectory;
[scene, success] ← SVViewersOnScene.LoadScene[svData, scene.name, wdir];
Reload this scene from its backing file.
IF success
THEN {
svData.scene ← scene;
SVSelections.KillSkitterAndSelections[editToolData];
SceneOldVersion[svData];
UpdateHeader[scene.name, svData];
EraseAndDrawScene[svData];
SVEvent.Selected[event, svData];
};
}; -- end of Reset
Save:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
success: BOOL;
sceneName: Rope.ROPE;
scene: Scene ← svData.scene;
sceneName ← FileNames.StripVersionNumber[scene.name];
success ← SVViewersOnScene.SaveScene[svData, sceneName];
IF success
THEN {
SVEvent.Selected[event, svData];
SceneOldVersion[svData];
UpdateHeader[scene.name, svData];
};
}; -- end of Save
GetMergeAux:
PROC [fullName: Rope.
ROPE, wdir: Rope.
ROPE, versionSpecified:
BOOL ←
FALSE, event:
ATOM, opName: Rope.
ROPE, svData: SVData] = {
success: BOOL;
scene: Scene;
oldScreenCS: CoordSystem ← svData.camera.screenCS;
TIMING VARIABLES
startTime: BasicTime.GMT;
endTime: BasicTime.GMT;
totalTime: INT;
timeRope: Rope.ROPE;
drawStyle: DrawStyle;
fileCamera: FileCamera;
cameraName: Rope.ROPE;
startTime ← BasicTime.Now[];
[scene, success] ← SVViewersOnScene.LoadScene[svData, fullName, wdir];
IF NOT success THEN RETURN;
endTime ← BasicTime.Now[];
totalTime ← BasicTime.Period[startTime, endTime];
timeRope ← IO.PutFR[" Done in time (%r)", [integer[totalTime]]];
Feedback.Append[svData.feedback, timeRope, oneLiner];
Choose a Tripod
IF scene.cameraOrder = NIL THEN fileCamera ← scene.cameras.first
ELSE {
cameraName ← scene.cameraOrder.first;
[fileCamera, success] ← SVScene.FindFileCameraFromName[cameraName, scene];
IF
NOT success
THEN {
fileCamera ← scene.cameras.first;
Feedback.Append[svData.feedback, Rope.Cat["Camera ", cameraName, " not found"], oneLiner];
Feedback.Blink[svData.feedback];
};
};
drawStyle ← SVEvent.CurrentStyle[svData];
svData.camera ← SVScene.CreateCamera[scene.coordSysRoot, CoordSys.CopyCoordSysFromAnyTree[oldScreenCS, "SCREEN", NIL, NIL], drawStyle];
SVScene.StuffCameraFromFileCamera[svData.camera, fileCamera, svData.camera.style, scene];
Finish Up
svData.scene ← scene;
UpdateHeader[fullName, svData];
SceneOldVersion[svData];
SVEvent.Selected[NIL, svData];
SVWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, svData: svData, remake: triggerBag, backgndOK: FALSE, edited: event=$Merge, okToClearFeedback: FALSE];
};
Get:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
editToolData: EditToolData ← NARROW[svData.editToolData];
picName: Rope.ROPE ← NARROW[event.rest.first];
success: BOOL;
fullName: Rope.ROPE;
wdir: Rope.ROPE;
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;
ClearAux[event, svData];
GetMergeAux[fullName, wdir, FALSE, $Get, "Get", svData];
}; -- end of Get
ClearAux:
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
svData.refresh.overlayList ← NIL;
SVSelect.DeselectAllAllClasses[svData.scene];
svData.scene ← SVScene.CreateScene["NoName.pic"];
svData.editToolData.skitter ← SVCaret.Create[];
svData.scene.anchor ← SVCaret.Create[];
svData.aborted ← ALL[FALSE];
};
Store:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
editToolData: EditToolData ← NARROW[svData.editToolData];
wdir: Rope.ROPE;
success: BOOL;
picName: Rope.ROPE ← NARROW[event.rest.first];
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;
success ← SVViewersOnScene.StoreScene[svData, scene, fullName];
IF success
THEN {
UpdateHeader[fullName, svData];
SVEvent.Selected[event, svData];
SceneOldVersion[svData];
UpdateHeader[scene.name, svData];
aisName ← Rope.Concat[SVFiles.FilenameMinusExtension[fullName], ".ais"];
};
}; -- end of Store
Split:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Create a new viewer onto this scene. Update the ring of links joining all viewers onto this scene,
scene: Scene ← svData.scene;
SVViewersOnScene.Split[svData, scene];
};
Script Menu
in SVEventImplA.OpenScript
OpenScript:
PUBLIC Menus.ClickProc = {
svData: SVData ← NARROW[clientData];
name: Rope.ROPE ← ViewerTools.GetSelectionContents[];
SVSessionLog.OpenScript[name, svData];
IF svData.debug.logStream#NIL THEN [] ← SlackProcess.EnableSessionLogging[svData.slackHandle];
};
AppendToScript:
PUBLIC Menus.ClickProc = {
svData: SVData ← NARROW[clientData];
name: Rope.ROPE ← ViewerTools.GetSelectionContents[];
SVSessionLog.AppendScript[name, svData];
IF svData.debug.logStream#NIL THEN [] ← SlackProcess.EnableSessionLogging[svData.slackHandle];
};
CloseScript:
PUBLIC Menus.ClickProc = {
svData: SVData ← NARROW[clientData];
[] ← SlackProcess.DisableSessionLogging[svData.slackHandle];
SVSessionLog.CloseScript[svData];
};
PlaybackScript:
PUBLIC Menus.ClickProc = {
svData: SVData ← NARROW[clientData];
name: Rope.ROPE ← ViewerTools.GetSelectionContents[];
SVSessionLog.PlaybackFromFile[name, svData];
};
FastPlayScript:
PUBLIC Menus.ClickProc = {
svData: SVData ← NARROW[clientData];
name: Rope.ROPE ← ViewerTools.GetSelectionContents[];
SVUserInput.EventNotify[svData, LIST[$DisableRefresh]];
SVSessionLog.PlaybackFromFile[name, svData];
SVUserInput.EventNotify[svData, LIST[$EnableRefresh]];
SVUserInput.EventNotify[svData, LIST[$Refresh, $DoNotClearFeedback]];
};
RayCast:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
editToolData: EditToolData ← NARROW[svData.editToolData];
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
feedback: FeedbackData ← svData.feedback;
tree: CSGTree;
startTime: BasicTime.GMT;
afterTreeTime: BasicTime.GMT;
endTime: BasicTime.GMT;
totalTime: INT;
msgRope, wdir: Rope.ROPE;
aisFileRope: Rope.ROPE;
success: BOOL;
maxRed, maxGreen, maxBlue, maxBlack: NAT;
aisFileRope ← Rope.Concat[SVFiles.FilenameMinusExtension[scene.name], ".ais"];
wdir ← editToolData.originalWorkingDirectory;
success ← TRUE;
[aisFileRope,,] ←
FS.ExpandName[aisFileRope, wdir
!
FS.Error =>
IF error.group = user
THEN {
Feedback.Append[svData.feedback, Rope.Concat["RayCast: ", error.explanation], oneLiner];
success ← FALSE;
CONTINUE;
}
];
IF NOT success THEN RETURN;
startTime ← BasicTime.Now[];
tree ← DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera];
afterTreeTime ← BasicTime.Now[];
totalTime ← BasicTime.Period[from: startTime, to: afterTreeTime];
Feedback.PutF[svData.feedback, oneLiner, "Building tree took (%r)",[integer[totalTime]]];
IF mouseButton = red OR mouseButton = blue THEN {
[success, maxRed, maxGreen, maxBlue, maxBlack] ← SVCastRays.DrawTree[tree, scene.lightSources, camera, aisFileRope, mouseButton = blue, SVEvent.RayCastProgress, svData, feedback];
[success, maxRed, maxGreen, maxBlue, maxBlack] ← SVCastRays.DrawTree[tree, scene.lightSources, camera, aisFileRope, TRUE, SVEvent.RayCastProgress, svData, feedback];
}
ELSE { -- yellow bug
cameraPoint: Point2d;
[cameraPoint, ----] ← SVSelections.GetPositionSkitter[];
[success, maxRed, maxGreen, maxBlue, maxBlack] ← SVCastRays.DrawTreeWithStartLine[cameraPoint[2], tree, scene.lightSources, camera, aisFileRope, mouseButton = blue, SVEvent.RayCastProgress, svData, feedback];
};
IF
NOT success
THEN {
Feedback.PutF[feedback, end, "...Raycast aborted."];
RETURN;
};
endTime ← BasicTime.Now[];
totalTime ← BasicTime.Period[from: afterTreeTime, to: endTime];
Feedback.PutF[svData.feedback, begin, " Raycast took (%r).",[integer[totalTime]]];
msgRope ←
IO.PutFR[" Max values were: red: (%g) green: (%g) blue: (%g) black: (%g)\n",
[integer[maxRed]], [integer[maxGreen]], [integer[maxBlue]], [integer[maxBlack]]];
Feedback.AppendTypescript[svData.feedback, msgRope, end];
SVEvent.DrawBlackAndWhite[event, svData];
}; -- end of RayCast
StopRays:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
camera: Camera ← svData.camera;
camera.abort ← TRUE;
};
ARay:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
scene: Scene ← svData.scene;
camera: Camera ← svData.camera;
outHandle: IO.STREAM ← Feedback.GetTypescriptStream[$Solidviews];
Get x and y from appropriate slots. Interpret this as camera coordinates and draw a cross.
x, y: REAL;
tree: CSGTree ← DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera];
color: Color;
[x, y] ← SVUtility.ReadTwoReals[svData.textSection.xyz];
color ← SVCastRays.SingleRay[[x, y], tree, scene.lightSources, camera, svData.feedback, TRUE];
Feedback.PutFTypescript[svData.feedback, begin, "[%g,%g]: ",[real[x]], [real[y]]];
TFO3d.FileoutColor[outHandle, color];
Feedback.PutFTypescript[svData.feedback, end, "\n"];
}; -- end of ARay
Select Menu
CycleSelection:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
scene: Scene ← svData.scene;
pointWorld: Point3d;
normalWorld: Vector3d;
feature: FeatureData;
hitData: REF ANY;
featureCycler: SVGravity.FeatureCycler ← SVState.GetSelectionCycler[svData];
direction: ATOM ← NARROW[event.rest.first];
SELECT direction
FROM
$Forward => [pointWorld, normalWorld, feature, hitData] ← SVGravity.NextFeature[featureCycler];
$Backward => [pointWorld, normalWorld, feature, hitData] ← SVGravity.PreviousFeature[featureCycler];
ENDCASE => ERROR;
SVMouseEvent.SelectFromFeature[svData, featureCycler.cameraPt, pointWorld, normalWorld, feature, hitData];
};
Hot Spots Menu
MakeHot:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
sliceDescGen: SliceDescriptorGenerator ← SVSelect.SelectedSlices[svData.scene, normal];
Make slices hot.
FOR sliceD: SliceDescriptor ← SVSelect.NextSliceDescriptor[sliceDescGen], SVSelect.NextSliceDescriptor[sliceDescGen]
UNTIL sliceD=
NIL
DO
SVSelect.SelectSlice[sliceD, svData.scene, hot];
ENDLOOP;
Fix the trigger bags, object bags, and Foreground plane (for efficiency).
sliceDescGen ← SVSelect.SelectedSlices[svData.scene, hot];
FOR sliceD: SliceDescriptor ← SVSelect.NextSliceDescriptor[sliceDescGen], SVSelect.NextSliceDescriptor[sliceDescGen]
UNTIL sliceD=
NIL
DO
sliceFeature: FeatureData ← SVAlign.AddHotSlice[sliceD, svData.hitTest.triggerBag]; -- fix triggerBag
alignObjects: LIST OF FeatureData ← SVAlign.IncrementalFilters[sliceFeature, svData.hitTest, NOT SVState.GetShowAlignments[svData], svData.hitTest.alignBag];
SVRefresh.NoteNewForeground[alignObjects, svData]; -- fix foreground plane
ENDLOOP;
Repaint
SVWindow.RestoreScreenAndInvariants[paintAction: $SequencesMadeHot, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
MakeCold:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
sliceDescGen: SliceDescriptorGenerator ← SVSelect.SelectedSlices[svData.scene, normal];
FOR sliceD: SliceDescriptor ← SVSelect.NextSliceDescriptor[sliceDescGen], SVSelect.NextSliceDescriptor[sliceDescGen]
UNTIL sliceD=
NIL
DO
SVSelect.DeselectSlice[sliceD.slice, sliceD.parts, svData.scene, hot];
ENDLOOP;
SVWindow.RestoreScreenAndInvariants[paintAction: $SequencesMadeCold, svData: svData, remake: triggerBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
MakeAllHot:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
triggerBag: TriggerBag ← svData.hitTest.triggerBag;
alignBag: AlignBag ← svData.hitTest.alignBag;
sliceDescGen: SliceDescriptorGenerator;
sliceGen: SVScene.AssemblyGenerator ← SVScene.PrimAssembliesInScene[svData.scene];
FOR slice: Slice ← SVScene.NextAssembly[sliceGen], SVScene.NextAssembly[sliceGen]
UNTIL slice =
NIL
DO
sliceD: SliceDescriptor ← SVAssembly.NewParts[slice, NIL, [0,0,0], topLevel];
SVSelect.SelectSlice[sliceD, svData.scene, hot];
ENDLOOP;
Update the hot and current trigger bags.
sliceDescGen ← SVSelect.SelectedSlices[svData.scene, hot]; -- expects only outline types !!
FOR sliceD: SliceDescriptor ← SVSelect.NextSliceDescriptor[sliceDescGen], SVSelect.NextSliceDescriptor[sliceDescGen]
UNTIL sliceD=
NIL
DO
feature: FeatureData ← SVAlign.AddHotSlice[sliceD, triggerBag];
alignObjects: LIST OF FeatureData;
alignObjects ← SVAlign.IncrementalFilters[feature, svData.hitTest, NOT SVState.GetShowAlignments[svData], alignBag];
SVRefresh.NoteNewForeground[alignObjects, svData];
ENDLOOP;
SVWindow.RestoreScreenAndInvariants[paintAction: $SequencesMadeHot, svData: svData, remake: triggerBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
MakeAllCold:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
sliceDescGen: SliceDescriptorGenerator ← SVSelect.SelectedSlices[svData.scene, hot];
FOR sliceD: SliceDescriptor ← SVSelect.NextSliceDescriptor[sliceDescGen], SVSelect.NextSliceDescriptor[sliceDescGen]
UNTIL sliceD=
NIL
DO
SVSelect.DeselectSlice[sliceD.slice, sliceD.parts, svData.scene, hot];
ENDLOOP;
SVWindow.RestoreScreenAndInvariants[paintAction: $SequencesMadeCold, svData: svData, remake: triggerBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
DropAnchor:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
editToolData: EditToolData ← svData.editToolData;
SVCaret.Copy[from: editToolData.skitter, to: svData.scene.anchor];
[] ← SVAlign.CreateAnchorTrigger[SVState.GetAnchor[svData], svData.hitTest.triggerBag]; -- anchor can trigger
SVWindow.RestoreScreenAndInvariants[paintAction: $AnchorAdded, svData: svData, remake: alignBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
LiftAnchor:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
IF SVCaret.Exists[svData.scene.anchor]
THEN {
SVCaret.Kill[svData.scene.anchor];
SVAlign.RemoveAnchorTrigger[svData.hitTest.triggerBag]; -- don't trigger
SVAlign.RemoveAnchorTrigger[svData.hitTest.sceneBag]; -- don't be gravity active
SVWindow.RestoreScreenAndInvariants[paintAction: $AnchorRemoved, svData: svData, remake: triggerBag, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE];
};
};
StandardAlignments:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
};
Other Style Buttons
ToggleShowColors:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
stateInfo: TwoState ← svData.refresh.showColors;
AtomButtons.SwitchBinaryState[stateInfo];
SVWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireViewer, svData: svData, remake: none, backgndOK: FALSE, edited: FALSE, okToClearFeedback: TRUE];
};
DrawCoordSystems:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVWindow.RestoreScreenAndInvariants[$DrawCoordSystems, svData];
};
DrawBoundBoxes:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
viewer is Container
SVWindow.RestoreScreenAndInvariants[$DrawBoundBoxes, svData];
}; -- end of DrawBoundBoxes
DrawBoundSpheres:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
SVWindow.RestoreScreenAndInvariants[$DrawBoundSpheres, svData];
}; -- end of DrawBoundSpheres
DrawPt:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
camera: Camera ← svData.camera;
get x and y from appropriate slots. Interpret this as camera coordinates and draw a cross.
SVWindow.RestoreScreenAndInvariants[$DrawPt, svData];
};
CrossHairs:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
viewer is the crossHairs button
SVWindow.RestoreScreenAndInvariants[$DrawCrossHairs, svData];
}; -- end of CrossHairs
TestGravity:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
Within the bounds of the viewer, randomly choose mouse positions. See if that mouse position is in range of any object. If so, draw a dot at that point. Repeat until 100 points have been drawn.
xRandomStream, yRandomStream: Random.RandomStream;
testPoint: Point2d;
pointCount: INT ← NARROW[event.rest.first, REF INT]^;
x, y: INT;
totalCount, hitCount, diffCount: NAT ← 0;
surfacePtWORLD: Point3d;
camera: Camera ← svData.camera;
scene: Scene ← svData.scene;
screenCS: CoordSystem ← camera.screenCS;
feature: FeatureData;
gravityType: GravityType ← SVState.GetGravityType[svData];
xRandomStream ← Random.Create[svData.actionArea.cw];
yRandomStream ← Random.Create[svData.actionArea.ch];
UNTIL totalCount >= pointCount
DO
x ← Random.NextInt[xRandomStream];
y ← Random.NextInt[yRandomStream];
testPoint ← [x, y];
testPoint ← CoordSys.ScreenToCamera[testPoint, screenCS];
svData.refresh.spotPoint ← testPoint;
[surfacePtWORLD, ----, feature] ← SVGravity.RayMap[testPoint, svData.hitTest.t, NIL, svData.hitTest.sceneBag, svData];
totalCount ← totalCount + 1;
IF feature =
NIL
THEN {
SVWindow.RestoreScreenAndInvariants[paintAction: $PaintSpot, svData: svData];
}
ELSE {
hitCount ← hitCount + 1;
svData.refresh.hitPoint ← surfacePtWORLD;
SVWindow.RestoreScreenAndInvariants[paintAction: $PaintHitLine, svData: svData];
};
ENDLOOP;
Feedback.PutF[svData.feedback, oneLiner, "Tested %g total points. %g hits.", [integer[totalCount]], [integer[hitCount]]];
}; -- end TestGravity
ResetStatistics:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
CodeTimer.ResetTable[CodeTimer.GetTable[$Solidviews]];
};
PrintStatistics:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
f: IO.STREAM ← Feedback.GetTypescriptStream[$Solidviews];
CodeTimer.PrintTable[f, CodeTimer.GetTable[$Solidviews]];
};
RaiseSIGNAL:
PUBLIC
PROC [event:
LIST
OF
REF
ANY, svData: SVData] = {
scene: SVSceneTypes.Scene ← svData.scene;
firstSlice, secondSlice: SVSceneTypes.Slice;
sliceGen: SVScene.AssemblyGenerator;
sliceGen ← SVScene.PrimAssembliesInScene[scene];
firstSlice ← SVScene.NextAssembly[sliceGen];
secondSlice ← SVScene.NextAssembly[sliceGen];
SIGNAL Feedback.Problem[msg: "Client requested SIGNAL"];
};
END.