File: SVMouseEventImplB.mesa
Last edited by Bier on September 24, 1987 0:05:07 am PDT
Copyright © 1984 by Xerox Corporation. All rights reserved.
Contents: Procedures for responding to button clicks made in a solidviewer.
Bloomenthal, June 16, 1987 7:29:53 pm PDT
DIRECTORY
CodeTimer, Feedback, Imager, ImagerBackdoor, ImagerPath, IO, SVMatrix3d, Rope, SV2d, SV3d, SVAlign, SVAssembly, SVBasicTypes, SVCaret, SVDescribe, SVGraphics, SVGravity, SVInterfaceTypes, SVModelTypes, SVMouseEvent, SVRefresh, SVScene, SVSceneTypes, SVSelect, SVState, SVWindow, TIPUser, ViewerClasses;
SVMouseEventImplB:
CEDAR PROGRAM
IMPORTS CodeTimer, SVGraphics, Feedback, Imager, ImagerBackdoor, SVMatrix3d, Rope, SVAlign, SVAssembly, SVCaret, SVDescribe, SVGravity, SVRefresh, SVScene, SVSelect, SVState, SVWindow
EXPORTS SVMouseEvent =
BEGIN
ArtworkToolData: TYPE = SVInterfaceTypes.ArtworkToolData;
BoundBox: TYPE = SVBasicTypes.BoundBox;
Camera: TYPE = SVModelTypes.Camera;
Classification: TYPE = SVSceneTypes.Classification;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
EditToolData: TYPE = SVInterfaceTypes.EditToolData;
ExtendMode: TYPE = SVSceneTypes.ExtendMode;
FeatureData: TYPE = SVInterfaceTypes.FeatureData;
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 = SVSceneTypes.Primitive;
Ray: TYPE = SVSceneTypes.Ray;
Scene: TYPE = SVSceneTypes.Scene;
Selection: TYPE = SVInterfaceTypes.Selection;
SelectionGenerator: TYPE = SVInterfaceTypes.SelectionGenerator;
SelectMode: TYPE = SVSceneTypes.SelectMode;
Skitter: TYPE = SVSceneTypes.Skitter;
SkitterMode: TYPE = SVSceneTypes.SkitterMode;
Slice: TYPE = SVSceneTypes.Slice;
SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor;
ToolData: TYPE = SVSceneTypes.ToolData;
TrigLine: TYPE = SV2d.TrigLine;
Vector3d: TYPE = SV3d.Vector3d;
SVData: TYPE = SVInterfaceTypes.SVData;
MouseProc: TYPE = SVMouseEvent.MouseProc;
StartProc: TYPE = SVMouseEvent.StartProc;
Problem: SIGNAL [msg: Rope.ROPE] = Feedback.Problem;
FrameUpLeft:
PUBLIC StartProc = {
Controlpoint is in camera coordinates.
camera: Camera ← svData.camera;
camera.frame.fullScreen ← FALSE;
camera.frame.downLeft[1] ← cameraPoint[1];
camera.frame.upRight[2] ← cameraPoint[2];
camera.frame.downLeft[2] ← cameraPoint[2] - 50.0; -- Just to give the frame an initial size.
camera.frame.upRight[1] ← cameraPoint[1] + 50.0;
SVWindow.RestoreScreenAndInvariants[$DuringMotion, svData];
};
FrameDownRightMove:
PUBLIC MouseProc = {
Controlpoint is in camera coordinates.
camera: Camera ← svData.camera;
DoDrawFrame:
PROC [dc: Imager.Context] = {
Imager.SetColor[dc, ImagerBackdoor.invert];
SVGraphics.DrawFrame [dc, camera];
};
camera.frame.downLeft[2] ← cameraPoint[2];
camera.frame.upRight[1] ← cameraPoint[1];
Draw the new frame.
SVWindow.RestoreScreenAndInvariants[$DuringMotion, svData];
};
FrameDownRightEnd:
PUBLIC MouseProc = {
camera: Camera ← svData.camera;
fileCamera: FileCamera;
success: BOOL;
FrameDownRightMove[event, svData, cameraPoint];
Once last update with the final position.
Tell the appropriate file camera about the new frame.
[fileCamera, success] ← SVScene.FindFileCameraFromName[camera.viewName, svData.scene];
IF success
THEN {
fileCamera.frame.downLeft ← camera.frame.downLeft;
fileCamera.frame.upRight ← camera.frame.upRight;
fileCamera.frame.fullScreen ← FALSE;
};
};
DeleteFrame:
PUBLIC MouseProc = {
camera: Camera ← svData.camera;
frame: FrameBox ← camera.frame;
DoDrawFrame:
PROC [dc: Imager.Context] = {
Imager.SetColor[dc, ImagerBackdoor.invert];
SVGraphics.DrawFrame [dc, camera];
};
Erase the old frame.
SVWindow.RestoreScreenAndInvariants[$FrameChanged, svData];
frame.fullScreen ← TRUE;
};
SaveSavedState:
PROC [svData: SVData] = {
SVScene.SaveSelections[svData.scene];
SVWindow.SaveCaretPos[gargoyleData];
SVCaret.Copy[from: svData.caret, to: svData.drag.savedCaret];
};
Selection Procs
StartSelectJoint:
PUBLIC StartProc = {
svData.drag.selectState ← joint;
StartSelectAux[svData, cameraPoint];
DuringSelect[NIL, svData, cameraPoint];
};
StartSelectSegment:
PUBLIC StartProc = {
svData.drag.selectState ← segment;
StartSelectAux[svData, cameraPoint];
DuringSelect[NIL, svData, cameraPoint];
};
StartSelectTraj:
PUBLIC StartProc = {
svData.drag.selectState ← traj;
StartSelectAux[svData, cameraPoint];
DuringSelect[NIL, svData, cameraPoint];
};
StartSelectTopLevel:
PUBLIC StartProc = {
svData.drag.selectState ← topLevel;
StartSelectAux[svData, cameraPoint];
DuringSelect[NIL, svData, cameraPoint];
};
StartSelectAux:
PROC [svData: SVData, cameraPoint: Point2d] = {
IF NOT SVRefresh.EmptyOverlay[svData] THEN ERROR;
SaveSavedState[svData];
};
DuringSelect:
PUBLIC MouseProc = {
While a joint, segment, traj, or top level object is being selected, gravity is forced to be StrictDistance. The object bag should consist only of trajectories and slices. The caret is moved to the segment endpoint of the nearest segment or traj as appropriate or tracks the cursor if none are nearby. Feedback is in the form of highlighted joints.
opRope: Rope.ROPE = "Selecting ";
worldPt: Point3d;
normalVec: Vector3d;
feature: FeatureData;
hitData: REF ANY;
scene: Scene ← svData.scene;
selectMode: SelectMode ← SVState.GetSelectMode[svData];
SELECT selectMode
FROM
joint => [worldPt, normalVec, feature, hitData] ← SVGravity.PointsPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE];
segment => [worldPt, normalVec, feature, hitData] ← SVGravity.LinesPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE];
traj, topLevel => [worldPt, normalVec, feature, hitData] ← SVGravity.FacesPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData];
ENDCASE => ERROR;
SetCaretAttractorEndpoint[svData, cameraPoint, worldPt, normalVec, feature, hitData];
SVSelect.DeselectAll[scene, normal];
IF feature#NIL THEN SelectAndDescribeSlicePart[feature, hitData, worldPt, svData, selectMode, opRope] ELSE DescribeOperationOnNothing[svData, opRope];
SVWindow.RestoreScreenAndInvariants[paintAction: $DuringSelect, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE];
}; -- end DuringSelect
SelectAndDescribeSlicePart:
PUBLIC
PROC [feature: FeatureData, hitData:
REF
ANY, hitPoint: Point3d, svData: SVData, mode: SelectMode, opRope: Rope.
ROPE] = {
selectedD: REF ANY ← SelectSlicePart[feature, hitData, hitPoint, svData, mode];
description: Rope.
ROPE ←
WITH selectedD
SELECT
FROM
sliceD: SliceDescriptor => SVAssembly.Describe[sliceD],
ENDCASE => SVDescribe.DescribeFeature[feature, hitData, svData];
Feedback.PutFHerald[svData.feedback, oneLiner, "%g %g", [rope[opRope]], [rope[description]] ];
};
SelectSlicePart:
PUBLIC
PROC [feature: FeatureData, hitData:
REF
ANY, hitPoint: Point3d, svData: SVData, mode: SelectMode]
RETURNS [selectedD:
REF
ANY] = {
Find out which point is being selected and highlight it.
SELECT feature.type
FROM
slice => {
slice: Slice ← NARROW[feature.shape, SliceDescriptor].slice;
selectedSliceD: SliceDescriptor;
selectedSliceD ← SVAssembly.NewParts[slice, hitData, hitPoint, mode];
SVSelect.SelectSlice[selectedSliceD, svData.scene, normal];
selectedD ← selectedSliceD;
};
slopeLine, angleLine, distanceLine, intersectionPoint, sphere, midpoint => ERROR;
ENDCASE => ERROR Problem[msg: "unimplemented result type"];
};
DescribeOperationOnNothing:
PUBLIC
PROC [svData: SVData, opRope: Rope.
ROPE] = {
Feedback.PutFHerald[svData.feedback, oneLiner, "%g %g", [rope[opRope]], [rope["nothing"]] ];
};
SetCaretAttractorEndpoint:
PUBLIC
PROC [svData: SVData, cameraPoint: Point2d, worldPt: Point3d, normal: Vector3d, feature: FeatureData, hitData:
REF
ANY] = {
sliceD: SliceDescriptor;
skitter: Skitter ← svData.editToolData.skitter;
sliceD ← IF feature = NIL THEN NIL ELSE NARROW[feature.shape];
IF feature=NIL THEN SVCaret.SetAttractor[skitter, cameraPoint, worldPt, normal, sliceD]
ELSE {
shape: REF ANY ← feature.shape;
SELECT feature.type
FROM
slice => {
jointPos: Point3d;
jointNormal: Vector3d;
sliceD: SliceDescriptor ← NARROW[shape];
jointD: SliceDescriptor;
[jointD, jointPos, jointNormal] ← SVAssembly.ClosestJointToHitData[sliceD, worldPt, normal, hitData];
SVCaret.SetAttractor[skitter, cameraPoint, jointPos, jointNormal, sliceD];
};
ENDCASE => SVCaret.SetAttractor[skitter, cameraPoint, worldPt, normal, sliceD];
};
};
EndSelect:
PUBLIC MouseProc = {
pointWorld: Point3d;
normalWorld: Vector3d;
feature: FeatureData;
hitData: REF ANY;
scene: Scene ← svData.scene;
featureCycler: SVGravity.FeatureCycler;
selectMode: SelectMode ← SVState.GetSelectMode[svData];
SELECT selectMode
FROM
joint => featureCycler ← SVGravity.PointsPreferredCycler[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE, 1];
segment => featureCycler ← SVGravity.LinesPreferredCycler[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE, 1];
traj, topLevel => {
featureCycler ← SVGravity.FacesPreferredCycler[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData];
};
ENDCASE => ERROR;
[pointWorld, normalWorld, feature, hitData] ← SVGravity.FirstFeature[featureCycler];
SVState.SetSelectionCycler[svData, featureCycler];
SelectFromFeature[svData, cameraPoint, pointWorld, normalWorld, feature, hitData];
}; -- end EndSelect
SelectFromFeature:
PUBLIC
PROC [svData: SVData, cameraPt: Point2d, point
World: Point3d, normal
World: Vector3d, feature: FeatureData, hitData:
REF
ANY] = {
selectMode: SelectMode ← SVState.GetSelectMode[svData];
scene: Scene ← svData.scene;
SetCaretAttractorEndpoint[svData, cameraPt, pointWorld, normalWorld, feature, hitData];
SVWindow.NewCaretPos[svData];
SVSelect.DeselectAll[scene, normal];
SELECT selectMode
FROM
joint => EndSelectAux[svData, cameraPt, feature, hitData, pointWorld, joint, "joint"];
segment => EndSelectAux[svData, cameraPt, feature, hitData, pointWorld, segment, "segment"];
traj => EndSelectAux[svData, cameraPt, feature, hitData, pointWorld, traj, "trajectory"];
topLevel => EndSelectAux[svData, cameraPt, feature, hitData, pointWorld, topLevel, "object"];
ENDCASE => ERROR;
};
EndSelectAux:
PROC [svData: SVData, cameraPoint: Point2d, feature: FeatureData, hitData:
REF
ANY, hitPoint: Point3d, mode: SelectMode, opName: Rope.
ROPE] = {
Prepare for a subsequent Add operation and for Extend.
IF feature =
NIL
THEN {
GGCaret.SitOn[svData.caret, NIL];
Feedback.PutFHerald[svData.feedback, oneLiner, "No near %g found.", [rope[opName]]];
}
ELSE {
Make Selection and Prepare for Extend.
SELECT mode
FROM
joint => SVState.SetExtendMode[svData, joint];
segment => SVState.SetExtendMode[svData, segmentRange];
traj => SVState.SetExtendMode[svData, traj];
topLevel => SVState.SetExtendMode[svData, topLevel];
ENDCASE => ERROR;
SELECT feature.type
FROM
slice => {
sliceD: SliceDescriptor ← NARROW[SelectSlicePart[feature, hitData, hitPoint, svData, mode]];
featureCycler: SVGravity.FeatureCycler ← SVState.GetSelectionCycler[svData];
cycleCount: NAT ← featureCycler.count;
IF mode = traj OR mode = topLevel THEN GGCaret.SitOn[svData.caret, NIL]
ELSE GGCaret.SitOn[svData.caret, sliceD];
IF cycleCount > 1 THEN Feedback.PutFHerald[svData.feedback, oneLiner, Rope.Concat[SVAssembly.Describe[sliceD], " selected (%g more)"], [integer[cycleCount-1]]]
ELSE Feedback.AppendHerald[svData.feedback, Rope.Concat[SVAssembly.Describe[sliceD], " selected"], oneLiner];
SVState.SetSliceToExtend[svData, sliceD];
};
ENDCASE => ERROR Problem[msg: "Unexpected feature type"];
};
SVWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE];
}; -- end EndSelectAux
Extend selection procs.
StartExtend
SelectJoint:
PUBLIC StartProc = {
svData.drag.extendMode ← joint;
RETURN[StartExtendSelection[event, svData, cameraPoint]];
};
StartExtend
SelectSegment:
PUBLIC StartProc = {
svData.drag.extendMode ← segment;
RETURN[StartExtendSelection[event, svData, cameraPoint]];
};
StartExtend
SelectTraj:
PUBLIC StartProc = {
svData.drag.extendMode ← traj;
RETURN[StartExtendSelection[event, svData, cameraPoint]];
};
StartExtend
SelectTopLevel:
PUBLIC StartProc = {
svData.drag.extendMode ← topLevel;
RETURN[StartExtendSelection[event, svData, cameraPoint]];
};
StartExtendSelection:
PUBLIC StartProc = {
IF NOT SVRefresh.EmptyOverlay[svData] THEN ERROR;
SaveSavedState[svData]; -- must do this before any possible aborts occur
svData.drag.currentPoint ← cameraPoint;
svData.drag.transform ← SVMatrix3d.Identity[];
DuringExtendSelection[NIL, svData, cameraPoint];
};
DuringExtendSelection:
PUBLIC MouseProc= {
opRope: Rope.ROPE = "Extending to ";
surfacePtWorld: Point3d;
normalWorld: Vector3d;
feature: FeatureData;
hitData: REF ANY;
scene: Scene ← svData.scene;
extendMode: ExtendMode ← SVState.GetExtendMode[svData];
CodeTimer.StartInt[$DuringExtendSelection, $Solidviews];
SELECT extendMode
FROM
joint => {
[surfacePtWorld, normalWorld, feature, hitData] ← SVGravity.PointsPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE];
};
segment, segmentRange => {
[surfacePtWorld, normalWorld, feature, hitData] ← SVGravity.LinesPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData, TRUE];
};
traj, slice, topLevel => {
[surfacePtWorld, normalWorld, feature, hitData] ← SVGravity.FacesPreferred[cameraPoint, svData.hitTest.t, SVAlign.emptyAlignBag, svData.hitTest.sceneBag, svData];
};
ENDCASE => ERROR;
Put Caret on a joint (if any).
SetCaretAttractorEndpoint[svData, cameraPoint, surfacePtWorld, normalWorld, feature, hitData];
Reselect all.
SVSelect.DeselectAll[scene, normal];
SVScene.RestoreSelections[scene];
IF feature#
NIL
THEN {
SELECT extendMode
FROM
joint, segment, segmentRange, traj, topLevel => DuringExtendSelectionFeedback[feature, hitData, surfacePtWorld, svData];
slice, none => NULL;
ENDCASE => ERROR;
}
ELSE DescribeOperationOnNothing[svData, opRope];
SVWindow.RestoreScreenAndInvariants[paintAction: $DuringSelect, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE];
CodeTimer.StopInt[$DuringExtendSelection, $Solidviews];
}; -- end DuringExtendSelection
DuringExtendSelectionFeedback:
PROC [feature: FeatureData, hitData:
REF
ANY, hitPoint: Point3d, svData: SVData] = {
depending on extend mode, check if feature is in that mode, then select the new feature.
opRope: Rope.ROPE ← "Extending to ";
SELECT svData.drag.extendMode
FROM
joint, segment, traj, topLevel => [] ← SelectAndDescribeSlicePart[feature, hitData, hitPoint, svData, SVState.GetExtendMode[svData], opRope];
segmentRange => {
GOTO RegularSelectMechanism;
EXITS
RegularSelectMechanism => [] ← SelectAndDescribeSlicePart[feature, hitData, hitPoint, svData, segment, opRope];
};
ENDCASE => ERROR; -- should have been weeded about before calling this Proc
};
End
ExtendSelection:
PUBLIC MouseProc = {
SVWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE];
}; -- end EndExtendSelection
InitStats:
PROC [] = {
interval: CodeTimer.Interval;
interval ← CodeTimer.CreateInterval[$DuringExtendSelection];
CodeTimer.AddInt[interval, $Solidviews];
};
END.