File: SVSelectionsImpl.mesa
Last edited by: Eric Bier on August 18, 1985 0:47:07 am PDT
Copyright © 1984 by Xerox Corporation. All rights reserved.
Created on July 11, 1984 11:27:40 am PDT
Contents: Definitions for several kinds of selection objects in Solidviews including Movees and Targets.
DIRECTORY
CoordSys,
DisplayList3d,
Imager,
ImagerBackdoor,
Matrix3d,
Rope,
SV2d,
SV3d,
SVDraw3d,
SVEditUser,
SVError,
SVInterfaceTypes,
SVModelTypes,
SVRayTypes,
SVSceneTypes,
SVSelections,
SVViewerUser;
SVSelectionsImpl: CEDAR PROGRAM
IMPORTS CoordSys, DisplayList3d, Imager, ImagerBackdoor, Matrix3d, Rope, SVDraw3d, SVEditUser, SVError, SVViewerUser
EXPORTS SVSelections =
BEGIN
Assembly: TYPE = SVSceneTypes.Assembly;
Camera: TYPE = SVModelTypes.Camera;
CoordSystem: TYPE = SVModelTypes.CoordSystem;
EditToolData: TYPE = SVInterfaceTypes.EditToolData;
MasterObject: TYPE = SVSceneTypes.MasterObject;
Matrix4by4: TYPE = SV3d.Matrix4by4;
Point2d: TYPE = SV2d.Point2d;
Primitive: TYPE = SVRayTypes.Primitive;
Scene: TYPE = SVSceneTypes.Scene;
ToolData: TYPE = SVSceneTypes.ToolData;
ViewerToolData: TYPE = SVInterfaceTypes.ViewerToolData;
globalSkitter: Skitter;
globalTargetList: LIST OF Selection ← NIL;
globalMoveeList: LIST OF Selection ← NIL;
globalPlaneList: LIST OF Selection ← NIL;
A Skitter is an interactive selection on an object surface. It has no lasting effect unless it is turned into a Movee or Target. There is only one live skitter at a time in the whole world. Skitters only move by interactive pointing. The assembly which is under a live skitter becomes the Star assembly for purposes of shape editing and artwork editing. Skitters have no coordinate system. Just a single matrix to remind them where in WORLD they are. They are viewpoint dependent.
Skitter: TYPE = REF SkitterObj;
SkitterObj: TYPE = SVInterfaceTypes.SkitterObj;
SkitterMode: TYPE = SVInterfaceTypes.SkitterMode; -- {surface, extend, coordframe}
A single skitter is created at initialization time. The user can update with the following routines:
UpdateSkitter: PUBLIC PROC [assembly: Assembly, primitive: Primitive, viewerToolData: ViewerToolData] = {
globalSkitter.assembly ← assembly;
globalSkitter.primitive ← primitive;
globalSkitter.viewerToolData ← viewerToolData;
IF assembly # NIL THEN {
SVEditUser.SetCurrentAssemblyName[assembly, viewerToolData.editToolData];
globalSkitter.alive ← TRUE;
}
ELSE globalSkitter.alive ← FALSE;
};
SetModeSkitter: PUBLIC PROC [mode: SkitterMode] = {
globalSkitter.mode ← mode;
};
PositionSkitter: PUBLIC PROC [cameraPoint: Point2d, skitterWORLD: Matrix4by4] = {
globalSkitter.alive ← TRUE;
globalSkitter.cameraPoint ← cameraPoint;
globalSkitter.skitterWORLD ← skitterWORLD;
};
ComplementSkitter: PUBLIC PROC [dc: Imager.Context, camera: Camera] = TRUSTED {
skitterCAMERA: Matrix4by4;
ComplementSkitterAux: SAFE PROC = TRUSTED {
Imager.SetColor[dc, ImagerBackdoor.invert];
skitterCAMERA ← Matrix3d.WorldToLocal[CoordSys.FindInTermsOfWorld[camera.coordSys], globalSkitter.skitterWORLD];
SVDraw3d.DrawCoordSys[dc, skitterCAMERA, camera];
};
IF NOT globalSkitter.alive THEN RETURN;
Imager.DoSave[dc, ComplementSkitterAux];
};
DrawSkitter: PUBLIC PROC [dc: Imager.Context, camera: Camera] = TRUSTED {
skitterCAMERA: Matrix4by4;
skitterCAMERA ← Matrix3d.WorldToLocal[CoordSys.FindInTermsOfWorld[camera.coordSys], globalSkitter.skitterWORLD];
SVDraw3d.DrawCoordSys[dc, skitterCAMERA, camera];
};
KillSkitter: PUBLIC PROC [editToolData: EditToolData] = {
Remove all pointers to objects. Complement the skitter one last time and cease drawing it.
globalSkitter.alive ← FALSE;
globalSkitter.assembly ← NIL;
globalSkitter.primitive ← NIL;
globalSkitter.viewerToolData ← NIL;
SVEditUser.SetCurrentAssemblyName[NIL, editToolData];
};
IsAliveSkitter: PUBLIC PROC [] RETURNS [BOOL] = {
RETURN[globalSkitter.alive];
};
GetSkitterData: PUBLIC PROC [] RETURNS [assembly: Assembly, primitive: Primitive, viewerToolData: ViewerToolData] = {
IF globalSkitter.alive THEN {
assembly ← globalSkitter.assembly;
primitive ← globalSkitter.primitive;
viewerToolData ← globalSkitter.viewerToolData;
}
ELSE {
assembly ← NIL;
primitive ← NIL;
viewerToolData ← NIL;
SVError.Append["Please make a skitter selection first.", TRUE, TRUE];
SVError.Blink[];
};
};
GetModeSkitter: PUBLIC PROC [] RETURNS [mode: SkitterMode] = {
IF globalSkitter.alive THEN mode ← globalSkitter.mode
ELSE {
mode ← coordframe;
SVError.Append["Get Mode Skitter: There is no skitter.", TRUE, TRUE];
SVError.Blink[];
};
};
GetPositionSkitter: PUBLIC PROC [] RETURNS [cameraPoint: Point2d, skitterWORLD: Matrix4by4] = TRUSTED {
IF globalSkitter.alive THEN {
cameraPoint ← globalSkitter.cameraPoint;
skitterWORLD ← globalSkitter.skitterWORLD;
}
ELSE {
cameraPoint ← [0,0];
skitterWORLD ← Matrix3d.Identity[];
SVError.Append["Get Position Skitter: There is no skitter.", TRUE, TRUE];
SVError.Blink[];
};
};
Hooks, and Floaters are special primitive assemblies which refer to a special "null" master object. For convenience, we provide procedures here to wire up these objects to a scene. For now, both are created as Solidviews Jack objects (Jack is a class, just as sphere is. Jacks look like three perpendicular line segments).
AddHookFromSkitter: PUBLIC PROC [] RETURNS [assembly: Assembly] = TRUSTED {
We add the hook jack under assembly in the coordinate system tree, so it will follow assembly around. We also tell the new assembly that it is sitting on the skitter assembly.
editToolData: EditToolData ← globalSkitter.viewerToolData.editToolData;
viewerToolData: ViewerToolData ← globalSkitter.viewerToolData;
scene: Scene ← viewerToolData.scene;
addSucceeds: BOOLTRUE;
currentCS: CoordSystem ← globalSkitter.assembly.coordSys;
jackName: Rope.ROPE;
hooksuper: Matrix4by4;
hookCS: CoordSystem;
jackName ← CoordSys.UniqueNameWithSuffix[globalSkitter.assembly.name, "Hook", scene.coordSysRoot];
hooksuper ← Matrix3d.WorldToLocal[CoordSys.FindInTermsOfWorld[currentCS], globalSkitter.skitterWORLD];
hookCS ← CoordSys.CreateCoordSysInTree[jackName, hooksuper, currentCS, scene.coordSysRoot];
[assembly, ----] ←
DisplayList3d.CreatePrimitiveAtExistingCoordSys[jackName, "jack", [50, 50, 50], scene, hookCS
! DisplayList3d.NameAlreadyPresent => {
SVError.Append[Rope.Cat["Jack name ", jackName, " is not unique. Contact implementor."], TRUE, TRUE];
SVError.Blink[];
addSucceeds ← FALSE; CONTINUE};
DisplayList3d.AttemptToAddSubassemblyToPrimitive => ERROR;
];
IF NOT addSucceeds THEN RETURN;
assembly.sittingOn ← globalSkitter.assembly.name;
DisplayList3d.ConnectAssemblyToParent[assembly, scene.assembly];
SVEditUser.SceneNewVersion[globalSkitter.viewerToolData]; -- Commented out for now
to permit so that viewerToolData.treeOutOfDate doesn't get set to TRUE when a Jack is
created.
};
AddFloaterFromSkitter: PUBLIC PROC [] RETURNS [assembly: Assembly] = TRUSTED {
We add the floater under the sceneAssembly since it is not associated directly with any other object in the scene.
editToolData: EditToolData ← globalSkitter.viewerToolData.editToolData;
viewerToolData: ViewerToolData ← globalSkitter.viewerToolData;
scene: Scene ← viewerToolData.scene;
addSucceeds: BOOLTRUE;
jackName: Rope.ROPE;
sceneAssemblyCS: CoordSystem ← scene.assembly.coordSys;
floatersuper: Matrix4by4;
floaterCS: CoordSystem;
jackName ← CoordSys.UniqueNameFrom["Floater", scene.coordSysRoot];
floatersuper ← Matrix3d.WorldToLocal[CoordSys.FindInTermsOfWorld[sceneAssemblyCS], globalSkitter.skitterWORLD];
floaterCS ← CoordSys.CreateCoordSysInTree[jackName, floatersuper, sceneAssemblyCS, scene.coordSysRoot];
[assembly, ----] ←
DisplayList3d.CreatePrimitiveAtExistingCoordSys[jackName, "jack", [50, 50, 50], scene, floaterCS
! DisplayList3d.NameAlreadyPresent => {
SVError.Append[Rope.Cat["Jack name ", jackName, " is not unique. Contact implementor."], TRUE, TRUE];
SVError.Blink[];
addSucceeds ← FALSE; CONTINUE};
DisplayList3d.AttemptToAddSubassemblyToPrimitive => ERROR;
];
IF NOT addSucceeds THEN RETURN;
DisplayList3d.ConnectAssemblyToParent[assembly, scene.assembly];
SVEditUser.SceneNewVersion[globalSkitter.viewerToolData]; -- Commented out for now
to permit so that viewerToolData.treeOutOfDate doesn't get set to TRUE when a Jack is
created.
};
Movees and Targets are persistent Selections. They refer to one of the following:
1) A Floater's coordSys
2) A Hook coordSys
3) An Object's coordSys.
Movees allow the referent to participate in operations including:
1) A hook movee selects an object to be tugged and a tugboat at the same time.
2) A floater, hook, or object selection allows the selected coordSys to be moved. A hook might be moved around on a surface or might become a floater. An object moves along with its children. A floater moves in space.
3) The origin of an in-scene ray is specified.
4) The origin of a floater calculation is specified.
Targets allow secondary objects to be specified.
1) Any target can be a center of rotation, a base frame for translation.
2) All selectable objects are also assemblies in the scene tree. All assemblies have an associated distinguished plane. Hence a target can suggest a plane to be used for dragging.
3) The direction point of an in-scene ray is specified.
4) The end point of a floater calculation is specified.
Selections do not move interactively as skitters do. They are not really objects at all. Think of them as pointers to coordinate frames which are currently active. If the referent coordinate frame moves, so does the image of the selection.
Selection: TYPE = REF SelectionObj;
SelectionObj: TYPE = SVInterfaceTypes.SelectionObj;
ReferentType: TYPE = SVInterfaceTypes.ReferentType; -- {hook, floater, coordSys};
SelectionType: TYPE = SVInterfaceTypes.SelectionType; -- {target, movee, plane};
The system maintains the following lists and distinguished objects:
1) The global skitter.
2) A stack of all movee selections.
3) A stack of all target selections.
CreateHookMovee: PUBLIC PROC [jack: Assembly, indirect: Assembly, viewerToolData: ViewerToolData] RETURNS [movee: Selection] = {
movee ← NEW[SelectionObj ← [jack, indirect, viewerToolData, hook, movee]];
};
CreateCoordSysMovee: PUBLIC PROC [coincident: Assembly, viewerToolData: ViewerToolData] RETURNS [movee: Selection] = {
movee ← NEW[SelectionObj ← [coincident, NIL, viewerToolData, coordSys, movee]];
};
CreateHookTarget: PUBLIC PROC [jack: Assembly, indirect: Assembly, viewerToolData: ViewerToolData] RETURNS [target: Selection] = {
target ← NEW[SelectionObj ← [jack, indirect, viewerToolData, hook, target]];
};
CreateCoordSysTarget: PUBLIC PROC [coincident: Assembly, viewerToolData: ViewerToolData] RETURNS [target: Selection] = {
target ← NEW[SelectionObj ← [coincident, NIL, viewerToolData, coordSys, target]];
};
CreatePlaneSelection: PUBLIC PROC [coincident: Assembly, viewerToolData: ViewerToolData] RETURNS [planeSel: Selection] = TRUSTED {
planeSel ← NEW[SelectionObj ← [coincident, NIL, viewerToolData, coordSys, plane]];
DisplayList3d.AddOrResizeToolToAssembly[coincident, viewerToolData.scene];
};
SelectionGenerator: TYPE = SVInterfaceTypes.SelectionGenerator;
SelectionGeneratorObj: TYPE = SVInterfaceTypes.SelectionGeneratorObj;
GetSelectionGenerator: PUBLIC PROC [selectType: SelectionType] RETURNS [g: SelectionGenerator, selectionsExist: BOOL] = {
SELECT selectType FROM
movee => {
g ← NEW[SelectionGeneratorObj ← [currentPtr: globalMoveeList]];
selectionsExist ← (NOT globalMoveeList = NIL);
};
target => {
g ← NEW[SelectionGeneratorObj ← [currentPtr: globalTargetList]];
selectionsExist ← (NOT globalTargetList = NIL);
};
plane => {
g ← NEW[SelectionGeneratorObj ← [currentPtr: globalPlaneList]];
selectionsExist ← (NOT globalPlaneList = NIL);
};
ENDCASE => ERROR;
};
ComplainIfNot: PUBLIC PROC [selectionsExist: BOOL] = {
IF NOT selectionsExist THEN {
SVError.Append["There are no source selections.", TRUE, TRUE];
SVError.Blink[];
};
};
NextSelection: PUBLIC PROC [g: SelectionGenerator] RETURNS [sel: Selection] = {
IF g.currentPtr = NIL THEN RETURN[NIL];
sel ← g.currentPtr.first;
g.currentPtr ← g.currentPtr.rest;
};
NextSelectionCoincident: PUBLIC PROC [g: SelectionGenerator] RETURNS [coin: Assembly] = {
IF g.currentPtr = NIL THEN RETURN[NIL];
coin ← g.currentPtr.first.coincident;
g.currentPtr ← g.currentPtr.rest;
};
PushMovee: PUBLIC PROC [moveeSel: Selection] = {
globalMoveeList ← CONS[moveeSel, globalMoveeList];
SVEditUser.SetSourceName[moveeSel.coincident, moveeSel.viewerToolData.editToolData];
};
PopMovee: PUBLIC PROC [] RETURNS [moveeSel: Selection] = {
newTop: Selection;
IF globalMoveeList = NIL THEN {
moveeSel ← NIL;
SVError.Append["There are no source selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE {
moveeSel ← globalMoveeList.first;
globalMoveeList ← globalMoveeList.rest;
newTop ← IF globalMoveeList = NIL THEN NIL ELSE globalMoveeList.first;
IF newTop # NIL THEN SVEditUser.SetSourceName[newTop.coincident, newTop.viewerToolData.editToolData]
ELSE SVEditUser.SetSourceName[NIL, moveeSel.viewerToolData.editToolData];
};
};
NextMovee: PUBLIC PROC [] RETURNS [moveeSel: Selection] = {
Like PopMovee, but doesn't complain if stack is empty.
newTop: Selection;
IF globalMoveeList = NIL THEN moveeSel ← NIL
ELSE {
moveeSel ← globalMoveeList.first;
globalMoveeList ← globalMoveeList.rest;
newTop ← IF globalMoveeList = NIL THEN NIL ELSE globalMoveeList.first;
IF newTop # NIL THEN SVEditUser.SetSourceName[newTop.coincident, newTop.viewerToolData.editToolData]
ELSE SVEditUser.SetSourceName[NIL, moveeSel.viewerToolData.editToolData];
};
};
PopMoveeCoincident: PUBLIC PROC [] RETURNS [movee: Assembly] = {
newTop: Selection;
moveeSel: Selection;
IF globalMoveeList = NIL THEN {
movee ← NIL;
SVError.Append["There are no source selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE {
moveeSel ← globalMoveeList.first;
movee ← moveeSel.coincident;
globalMoveeList ← globalMoveeList.rest;
newTop ← IF globalMoveeList = NIL THEN NIL ELSE globalMoveeList.first;
IF newTop # NIL THEN SVEditUser.SetSourceName[newTop.coincident, newTop.viewerToolData.editToolData]
ELSE SVEditUser.SetSourceName[NIL, moveeSel.viewerToolData.editToolData];
};
};
NextMoveeCoincident: PUBLIC PROC [] RETURNS [movee: Assembly] = {
Like PopMoveeCoincident, but doesn't complain if stack is empty.
newTop: Selection;
moveeSel: Selection;
IF globalMoveeList = NIL THEN movee ← NIL
ELSE {
moveeSel ← globalMoveeList.first;
movee ← moveeSel.coincident;
globalMoveeList ← globalMoveeList.rest;
newTop ← IF globalMoveeList = NIL THEN NIL ELSE globalMoveeList.first;
IF newTop # NIL THEN SVEditUser.SetSourceName[newTop.coincident, newTop.viewerToolData.editToolData]
ELSE SVEditUser.SetSourceName[NIL, moveeSel.viewerToolData.editToolData];
};
};
TopMovee: PUBLIC PROC [] RETURNS [moveeSel: Selection] = {
IF globalMoveeList = NIL THEN moveeSel ← NIL
ELSE moveeSel ← globalMoveeList.first;
};
TopMoveeC: PUBLIC PROC [] RETURNS [moveeSel: Selection] = {
Returns NIL AND complains if there are none.
IF globalTargetList = NIL THEN {
moveeSel ← NIL;
SVError.Append["There are no source selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE moveeSel ← globalTargetList.first;
};
TopMoveeCoincident: PUBLIC PROC [] RETURNS [movee: Assembly] = {
IF globalMoveeList = NIL THEN movee ← NIL
ELSE movee ← globalMoveeList.first.coincident;
};
ClearMoveeStack: PUBLIC PROC [editToolData: EditToolData] = {
Should be done before deleting any movee selected object. Must also be done after each command which uses a movee to allow the user to make new selections.
ComplementAllSelections[movee];
globalMoveeList ← NIL;
SVEditUser.SetSourceName[NIL, editToolData];
};
PushTarget: PUBLIC PROC [targetSel: Selection] = {
globalTargetList ← CONS[targetSel, globalTargetList];
SVEditUser.SetTargetName[targetSel.coincident, targetSel.viewerToolData.editToolData];
};
PopTarget: PUBLIC PROC [] RETURNS [targetSel: Selection] = {
newTop: Selection;
IF globalTargetList = NIL THEN {
targetSel ← NIL;
SVError.Append["There are no target selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE {
targetSel ← globalTargetList.first;
globalTargetList ← globalTargetList.rest;
newTop ← IF globalTargetList = NIL THEN NIL ELSE globalTargetList.first;
IF newTop # NIL THEN SVEditUser.SetTargetName[newTop.coincident, newTop.viewerToolData.editToolData]
ELSE SVEditUser.SetTargetName[NIL, targetSel.viewerToolData.editToolData];
};
};
NextTarget: PUBLIC PROC [] RETURNS [targetSel: Selection] = {
Just like PopTarget but doesn't complain if there aren't any.
newTop: Selection;
IF globalTargetList = NIL THEN targetSel ← NIL
ELSE {
targetSel ← globalTargetList.first;
globalTargetList ← globalTargetList.rest;
newTop ← IF globalTargetList = NIL THEN NIL ELSE globalTargetList.first;
IF newTop # NIL THEN SVEditUser.SetTargetName[newTop.coincident, newTop.viewerToolData.editToolData]
ELSE SVEditUser.SetTargetName[NIL, targetSel.viewerToolData.editToolData];
};
};
PopTargetCoincident: PUBLIC PROC [] RETURNS [target: Assembly] = {
targetSel, newTop: Selection;
IF globalTargetList = NIL THEN {
target ← NIL;
SVError.Append["There are no target selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE {
targetSel ← globalTargetList.first;
target ← targetSel.coincident;
globalTargetList ← globalTargetList.rest;
newTop ← IF globalTargetList = NIL THEN NIL ELSE globalTargetList.first;
IF newTop # NIL THEN SVEditUser.SetTargetName[newTop.coincident, newTop.viewerToolData.editToolData]
ELSE SVEditUser.SetTargetName[NIL, targetSel.viewerToolData.editToolData];
};
};
NextTargetCoincident: PUBLIC PROC [] RETURNS [target: Assembly] = {
Like PopTargetCoincident but doesn't complain if stack is empty.
targetSel, newTop: Selection;
IF globalTargetList = NIL THEN target ← NIL
ELSE {
targetSel ← globalTargetList.first;
target ← targetSel.coincident;
globalTargetList ← globalTargetList.rest;
newTop ← IF globalTargetList = NIL THEN NIL ELSE globalTargetList.first;
IF newTop # NIL THEN SVEditUser.SetTargetName[newTop.coincident, newTop.viewerToolData.editToolData]
ELSE SVEditUser.SetTargetName[NIL, targetSel.viewerToolData.editToolData];
};
};
TopTarget: PUBLIC PROC [] RETURNS [targetSel: Selection] = {
IF globalTargetList = NIL THEN targetSel ← NIL
ELSE targetSel ← globalTargetList.first;
};
TopTargetC: PUBLIC PROC [] RETURNS [targetSel: Selection] = {
IF globalTargetList = NIL THEN {
targetSel ← NIL;
SVError.Append["There are no target selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE targetSel ← globalTargetList.first;
};
TopTargetCoincident: PUBLIC PROC [] RETURNS [target: Assembly] = {
IF globalTargetList = NIL THEN {
target ← NIL;
SVError.Append["There are no target selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE target ← globalTargetList.first.coincident;
};
TopTargetCoinCoordSys: PUBLIC PROC [] RETURNS [targetCS: CoordSystem] = {
IF globalTargetList = NIL THEN targetCS ← NIL
ELSE targetCS ← globalTargetList.first.coincident.coordSys;
};
TopTargetCoinCoordSysC: PUBLIC PROC [] RETURNS [targetCS: CoordSystem] = {
IF globalTargetList = NIL THEN {
targetCS ← NIL;
SVError.Append["There are no target selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE targetCS ← globalTargetList.first.coincident.coordSys;
};
ClearTargetStack: PUBLIC PROC [editToolData: EditToolData] = {
Should be done before deleting any target-selected object. Must also be done after each command which uses a target to allow the user to make new selections.
ComplementAllSelections[target];
globalTargetList ← NIL;
SVEditUser.SetTargetName[NIL, editToolData];
};
PushPlane: PUBLIC PROC [planeSel: Selection] = {
globalPlaneList ← CONS[planeSel, globalPlaneList];
SVEditUser.SetPlaneName[planeSel.coincident, planeSel.viewerToolData.editToolData];
};
PopPlane: PUBLIC PROC [] RETURNS [planeSel: Selection] = {
newTop: Selection;
IF globalPlaneList = NIL THEN {
planeSel ← NIL;
SVError.Append["There are no plane selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE {
planeSel ← globalPlaneList.first;
globalPlaneList ← globalPlaneList.rest;
newTop ← IF globalPlaneList = NIL THEN NIL ELSE globalPlaneList.first;
IF newTop # NIL THEN SVEditUser.SetPlaneName[newTop.coincident, newTop.viewerToolData.editToolData]
ELSE SVEditUser.SetPlaneName[NIL, planeSel.viewerToolData.editToolData];
};
};
TopPlane: PUBLIC PROC [] RETURNS [planeSel: Selection] = {
IF globalPlaneList = NIL THEN planeSel ← NIL
ELSE planeSel ← globalPlaneList.first;
};
TopPlaneC: PUBLIC PROC [] RETURNS [planeSel: Selection] = {
IF globalPlaneList = NIL THEN {
planeSel ← NIL;
SVError.Append["There are no plane selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE planeSel ← globalPlaneList.first;
};
TopPlaneCoincident: PUBLIC PROC [] RETURNS [planeAssem: Assembly] = {
IF globalPlaneList = NIL THEN {
planeAssem ← NIL;
SVError.Append["There are no plane selections.", TRUE, TRUE];
SVError.Blink[];
}
ELSE planeAssem ← globalPlaneList.first.coincident;
};
PlaneStackEmpty: PUBLIC PROC [] RETURNS [BOOL] = {
RETURN[globalPlaneList = NIL];
};
ClearPlaneStack: PUBLIC PROC [editToolData: EditToolData] = {
ComplementAllSelections[plane];
globalPlaneList ← NIL;
SVEditUser.SetPlaneName[NIL, editToolData];
};
ComplementAnySelectionsOnDC: PUBLIC PROC [dc: Imager.Context, assembly: Assembly, scene: Scene] = TRUSTED {
g: SelectionGenerator;
selectionsExist: BOOL;
camera: Camera;
viewerToolData: ViewerToolData;
FOR type: SelectionType IN [target..plane] DO
[g, selectionsExist] ← GetSelectionGenerator[type];
IF NOT selectionsExist THEN LOOP;
FOR sel: Selection ← NextSelection[g], NextSelection[g] UNTIL sel = NIL DO
IF (sel.referentType = hook AND sel.indirect = assembly) OR sel.coincident = assembly THEN {
viewerToolData ← sel.viewerToolData;
camera ← viewerToolData.camera;
SELECT sel.selectionType FROM
target => {
csCAMERA: Matrix4by4;
csCAMERA ← CoordSys.FindInTermsOfCamera[sel.coincident.coordSys, camera.coordSys];
SVDraw3d.DrawTargetCoordSys[dc, csCAMERA, camera];
};
movee => SVDraw3d.DrawMovee[dc, sel.coincident.coordSys, camera];
plane => {
toolData: ToolData;
planeAssem: Assembly;
planeAssem ← sel.coincident;
IF planeAssem.toolMasterObject = NIL OR planeAssem.toolMasterObject.mainBody = NIL THEN ERROR;
toolData ← NARROW[planeAssem.toolMasterObject.mainBody];
SVDraw3d.DrawPlaneSelection[dc, sel.coincident.coordSys, toolData.plane, camera];
};
ENDCASE => ERROR;
};
ENDLOOP;
ENDLOOP;
};
ComplementSelection: PUBLIC PROC [viewerToolData: ViewerToolData, sel: Selection] = {
DoComplementSelection: PROC [dc: Imager.Context] = {
ComplementSelectionDC[dc, sel, viewerToolData];
};
SVViewerUser.Painter[DoComplementSelection, sel.viewerToolData];
};
ComplementSelectionDC: PUBLIC PROC [dc: Imager.Context, sel: Selection, viewerToolData: ViewerToolData] = TRUSTED {
camera: Camera;
ComplementSelectionDCAux: SAFE PROC = TRUSTED {
Imager.SetColor[dc, ImagerBackdoor.invert];
SELECT sel.selectionType FROM
target => {
csCAMERA: Matrix4by4;
csCAMERA ← CoordSys.FindInTermsOfCamera[sel.coincident.coordSys, camera.coordSys];
SVDraw3d.DrawTargetCoordSys[dc, csCAMERA, camera];
};
movee => SVDraw3d.DrawMovee[dc, sel.coincident.coordSys, camera];
plane => {
toolData: ToolData;
planeAssem: Assembly;
planeAssem ← sel.coincident;
IF planeAssem.toolMasterObject = NIL OR planeAssem.toolMasterObject.mainBody = NIL THEN ERROR;
toolData ← NARROW[planeAssem.toolMasterObject.mainBody];
SVDraw3d.DrawPlaneSelection[dc, sel.coincident.coordSys, toolData.plane, camera];
};
ENDCASE => ERROR;
};
IF viewerToolData # sel.viewerToolData THEN RETURN;
camera ← viewerToolData.camera;
Imager.DoSave[dc, ComplementSelectionDCAux];
};
ComplementAnySelectionsDC: PUBLIC PROC [dc: Imager.Context, viewerToolData: ViewerToolData] = {
Draw the skitter into dc, if the skitter is in the viewer associated with viewerToolData. Draw and movee and target selections for that viewer as well. (Called by SVViewerUser.DrawSceneEtc[] after DisplayList3d.DrawScene.)
camera: Camera ← viewerToolData.camera;
scene: Scene ← viewerToolData.scene;
IF globalSkitter.viewerToolData = viewerToolData THEN
ComplementSkitter[dc, viewerToolData.camera];
ComplementAnySelectionsDCAux[dc, movee, viewerToolData, scene, camera];
ComplementAnySelectionsDCAux[dc, target, viewerToolData, scene, camera];
ComplementAnySelectionsDCAux[dc, plane, viewerToolData, scene, camera];
};
ComplementAnySelectionsDCAux: PRIVATE PROC [dc: Imager.Context, selType: SelectionType, viewerToolData: ViewerToolData, scene: Scene, camera: Camera] = {
For each selection, If the selected object is a hook or a floater, complement the jack and then draw the selection. If a coordinate system, just draw selection.
g: SelectionGenerator;
selectionsExist: BOOL;
[g, selectionsExist] ← GetSelectionGenerator[selType];
IF NOT selectionsExist THEN RETURN;
FOR sel: Selection ← NextSelection[g], NextSelection[g] UNTIL sel = NIL DO
IF sel.viewerToolData = viewerToolData THEN {
ComplementReferentDC[dc, sel, viewerToolData]; -- erase the Jack if any.
ComplementSelectionDC[dc, sel, viewerToolData];
};
ENDLOOP;
};
ComplementReferentDC: PUBLIC PROC [dc: Imager.Context, selection: Selection, viewerToolData: ViewerToolData] = TRUSTED {
IF selection.referentType # coordSys AND selection.viewerToolData = viewerToolData THEN {
SVViewerUser.DrawAssemblyXOR[dc, viewerToolData, selection.coincident];
};
};
ComplementAllSelections: PUBLIC PROC [selType: SelectionType] = {
Complements all selections of selType regardless of what viewer they are in.
g: SelectionGenerator;
selectionsExist: BOOL;
scene: Scene;
camera: Camera;
sel: Selection;
DoComplementSelection: PROC [dc: Imager.Context] = {
ComplementReferentDC[dc, sel, sel.viewerToolData]; -- erase the Jack if any.
ComplementSelectionDC[dc, sel, sel.viewerToolData];
};
[g, selectionsExist] ← GetSelectionGenerator[selType];
IF NOT selectionsExist THEN RETURN;
FOR sel ← NextSelection[g], NextSelection[g] UNTIL sel = NIL DO
scene ← sel.viewerToolData.scene;
camera ← sel.viewerToolData.camera;
SVViewerUser.Painter[DoComplementSelection, sel.viewerToolData];
ENDLOOP;
};
KillSkitterAndSelections: PUBLIC PROC [editToolData: EditToolData] = {
viewerToolData: ViewerToolData;
camera: Camera;
DoComplementSkitter: PROC [dc: Imager.Context] = {
ComplementSkitter[dc, camera];
};
ClearTargetStack[editToolData];
ClearMoveeStack[editToolData];
ClearPlaneStack[editToolData];
IF IsAliveSkitter[] THEN {
[----,----,viewerToolData] ← GetSkitterData[];
IF viewerToolData = NIL THEN ERROR;
camera ← viewerToolData.camera;
SVViewerUser.Painter[DoComplementSkitter, viewerToolData];
};
KillSkitter[editToolData];
};
Init: PROC [] = TRUSTED {
globalSkitter ← NEW[SkitterObj ← [FALSE, [0,0], NIL, NIL, Matrix3d.Identity[], NIL, surface]];
};
Init[];
END.