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, skitter
WORLD: 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, skitter
WORLD: 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: BOOL ← TRUE;
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: BOOL ← TRUE;
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.