DIRECTORY GGBasicTypes, GGBoundBox, GGCoreTypes, GGModelTypes, GGOutline, GGParent, GGScene, GGSceneType, GGSegmentTypes, GGSelect, GGSequence, GGSlice, GGSliceOps, GGTraj, TextNode; GGSelectImpl: CEDAR PROGRAM IMPORTS GGBoundBox, GGOutline, GGParent, GGScene, GGSequence, GGSlice, GGSliceOps, GGTraj EXPORTS GGModelTypes, GGSelect = BEGIN BoundBox: TYPE = GGCoreTypes.BoundBox; Joint: TYPE = GGModelTypes.Joint; JointGenerator: TYPE = GGModelTypes.JointGenerator; OutlineParts: TYPE = GGOutline.OutlineParts; Scene: TYPE = GGModelTypes.Scene; SceneObj: PUBLIC TYPE = GGSceneType.SceneObj; SegAndIndex: TYPE = GGSequence.SegAndIndex; Segment: TYPE = GGSegmentTypes.Segment; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; SelectionClass: TYPE = GGSegmentTypes.SelectionClass; Sequence: TYPE = GGModelTypes.Sequence; SequenceGenerator: TYPE = GGSequence.SequenceGenerator; SequenceGeneratorObj: TYPE = GGSequence.SequenceGeneratorObj; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = GGModelTypes.SliceDescriptorGenerator; SliceDescriptorGeneratorObj: TYPE = GGModelTypes.SliceDescriptorGeneratorObj; SliceDescriptorObj: TYPE = GGModelTypes.SliceDescriptorObj; SliceDescriptorWalkProc: TYPE = GGModelTypes.SliceDescriptorWalkProc; SliceGenerator: TYPE = GGModelTypes.SliceGenerator; SliceGeneratorObj: TYPE = GGModelTypes.SliceGeneratorObj; SliceParts: TYPE = GGModelTypes.SliceParts; SliceWalkProc: TYPE = GGModelTypes.SliceWalkProc; SlicePartsWalkProc: TYPE = GGModelTypes.SlicePartsWalkProc; TrajData: TYPE = GGModelTypes.TrajData; TrajEnd: TYPE = GGModelTypes.TrajEnd; TrajParts: TYPE = GGModelTypes.TrajParts; OutlineSequenceGenerator: TYPE = REF OutlineSequenceGeneratorObj; OutlineSequenceGeneratorObj: TYPE = RECORD [ list: LIST OF OutlineSequence ]; OutlineSequence: TYPE = REF OutlineSequenceObj; OutlineSequenceObj: TYPE = RECORD [ outline: Slice, -- the outline represented by this record fenceParts: TrajParts, -- included parts of the fence trajectory holeParts: LIST OF TrajParts -- included parts of holes ]; NotYetImplemented: PUBLIC SIGNAL = CODE; ChangeDonkeyTail: PROC [sliceD: SliceDescriptor, selectClass: SelectionClass] = { SELECT selectClass FROM normal => sliceD.slice.normalSelectedParts _ sliceD; hot => sliceD.slice.hotSelectedParts _ sliceD; active => sliceD.slice.activeSelectedParts _ sliceD; match => sliceD.slice.matchSelectedParts _ sliceD; ENDCASE; }; NoDonkeyTail: PROC [slice: Slice, selectClass: SelectionClass] = { SELECT selectClass FROM normal => slice.normalSelectedParts _ NIL; hot => slice.hotSelectedParts _ NIL; active => slice.activeSelectedParts _ NIL; match => slice.matchSelectedParts _ NIL; ENDCASE; }; SelectAll: PUBLIC PROC [scene: Scene, selectClass: SelectionClass] = { DoSelectSlice: PROC [slice: Slice] RETURNS [done: BOOL _ FALSE] = { SelectEntireSlice[slice, scene, selectClass]; }; [] _ GGScene.WalkSlices[scene, first, DoSelectSlice]; IF selectClass = normal THEN { IF scene.selected.normal = NIL OR scene.selected.normal.rest # NIL THEN scene.selected.normalLast _ NIL ELSE scene.selected.normalLast _ scene.selected.normal.first; }; }; SelectSliceFromParts: PUBLIC PROC [slice: Slice, parts: SliceParts, scene: Scene, selectClass: SelectionClass] = { sliceD: SliceDescriptor _ GGSlice.DescriptorFromParts[slice, parts]; SelectSlice[sliceD, scene, selectClass]; IF selectClass = normal THEN scene.selected.normalLast _ GGParent.TopLevelDescriptorFromChildDescriptor[sliceD]; }; SelectSlice: PUBLIC PROC [sliceD: SliceDescriptor, scene: Scene, selectClass: SelectionClass] = { oldSliceD, union: SliceDescriptor; IF sliceD=NIL OR sliceD.parts = NIL OR GGSliceOps.IsEmptyParts[sliceD] THEN RETURN; sliceD _ GGParent.TopLevelDescriptorFromChildDescriptor[sliceD]; oldSliceD _ FindSelectedSlice[sliceD.slice, selectClass]; IF oldSliceD#NIL THEN { union _ GGSliceOps.UnionParts[oldSliceD, sliceD]; DeselectSlice[sliceD.slice, oldSliceD.parts, scene, selectClass]; -- throw away old selection } ELSE union _ sliceD; IF selectClass = normal THEN union _ GGSliceOps.AugmentParts[union, selectClass]; AppendSelection[scene, union, selectClass]; ChangeDonkeyTail[union, selectClass]; IF selectClass = normal THEN scene.selected.normalLast _ GGParent.TopLevelDescriptorFromChildDescriptor[sliceD]; }; -- end SelectSlice SelectEntireSlice: PUBLIC PROC [slice: Slice, scene: Scene, selectClass: SelectionClass] = { allParts: SliceDescriptor _ GGSliceOps.NewParts[slice, NIL, slice]; SelectSlice[allParts, scene, selectClass]; }; DuplicateSelections: PUBLIC PROC [scene: Scene, fromClass: SelectionClass, toClass: SelectionClass] = { DoSelectSlice: PROC [sliceD: SliceDescriptor] RETURNS [done: BOOL _ FALSE] = { SelectSlice[sliceD, scene, toClass]; }; IF fromClass=toClass THEN RETURN; [] _ GGScene.WalkSelectedSlices[scene, first, DoSelectSlice, fromClass]; }; DeselectEntity: PUBLIC PROC [entity: REF ANY, scene: Scene, selectClass: SelectionClass] = { WITH entity SELECT FROM slice: Slice => DeselectEntireSlice[slice, scene, selectClass]; sliceD: SliceDescriptor => DeselectSlice[sliceD.slice, sliceD.parts, scene, selectClass]; ENDCASE => ERROR; }; DeselectEntityAllClasses: PUBLIC PROC [entity: REF ANY, scene: Scene] = { DeselectEntity[entity, scene, normal]; DeselectEntity[entity, scene, active]; DeselectEntity[entity, scene, hot]; DeselectEntity[entity, scene, match]; }; DeselectAll: PUBLIC PROC [scene: Scene, selectClass: SelectionClass] = { FOR sliceD: LIST OF SliceDescriptor _ ListSelected[scene, selectClass], sliceD.rest UNTIL sliceD = NIL DO NoDonkeyTail[sliceD.first.slice, selectClass]; ENDLOOP; SetSelectedList[scene, NIL, selectClass]; }; DeselectAllAllClasses: PUBLIC PROC [scene: Scene] = { DeselectAll[scene, normal]; DeselectAll[scene, active]; DeselectAll[scene, hot]; DeselectAll[scene, match]; }; DeselectEntireSlice: PUBLIC PROC [slice: Slice, scene: Scene, selectClass: SelectionClass] = { IF GGScene.IsTopLevel[slice] THEN { sliceD: SliceDescriptor _ FindSelectedSlice[slice, selectClass]; IF sliceD # NIL THEN { DeleteSelection[scene, sliceD, selectClass]; NoDonkeyTail[sliceD.slice, selectClass]; }; IF selectClass = normal THEN IF scene.selected.normalLast # NIL AND scene.selected.normalLast.slice = slice THEN scene.selected.normalLast _ NIL; } ELSE { entireD: SliceDescriptor _ GGSliceOps.NewParts[slice, NIL, slice]; DeselectSlice[entireD.slice, entireD.parts, scene, selectClass]; }; }; DeselectSlice: PUBLIC PROC [slice: Slice, parts: SliceParts, scene: Scene, selectClass: SelectionClass] = { oldD, newD, tempD: SliceDescriptor; tempD _ GGSlice.DescriptorFromParts[slice, parts]; tempD _ GGParent.TopLevelDescriptorFromChildDescriptor[tempD]; oldD _ FindSelectedSlice[tempD.slice, selectClass]; IF oldD#NIL THEN { newD _ GGSliceOps.DifferenceParts[oldD, tempD]; DeleteSelection[scene, oldD, selectClass]; NoDonkeyTail[oldD.slice, selectClass]; IF NOT GGSliceOps.IsEmptyParts[newD] THEN { IF selectClass = normal THEN newD _ GGSliceOps.AugmentParts[newD, selectClass]; AppendSelection[scene, newD, selectClass]; ChangeDonkeyTail[newD, selectClass]; }; IF selectClass = normal THEN { IF scene.selected.normalLast # NIL AND scene.selected.normalLast.slice = slice THEN scene.selected.normalLast _ GGSliceOps.DifferenceParts[scene.selected.normalLast, tempD]; IF scene.selected.normalLast = NIL OR GGSliceOps.IsEmptyParts[scene.selected.normalLast] THEN scene.selected.normalLast _ NIL; }; }; }; DeselectTraj: PROC [traj: Slice, scene: Scene, selectClass: SelectionClass] = { ancestor: Slice _ GGParent.GetTopLevelAncestor[traj]; oldD: SliceDescriptor _ FindSelectedSlice[ancestor, selectClass]; IF oldD#NIL THEN { newD: SliceDescriptor _ GGParent.RemoveTraj[oldD, traj]; DeleteSelection[scene, oldD, selectClass]; NoDonkeyTail[ancestor, selectClass]; IF NOT GGSliceOps.IsEmptyParts[newD] THEN { AppendSelection[scene, newD, selectClass]; ChangeDonkeyTail[newD, selectClass]; }; IF selectClass = normal THEN IF scene.selected.normalLast # NIL AND scene.selected.normalLast.slice = ancestor THEN { scene.selected.normalLast _ GGParent.RemoveTraj[scene.selected.normalLast, traj]; IF scene.selected.normalLast = NIL OR GGSliceOps.IsEmptyParts[scene.selected.normalLast] THEN scene.selected.normalLast _ NIL; }; }; }; SaveSelectionsInSliceAllClasses: PUBLIC PROC [slice: Slice, scene: Scene] = { sliceD: SliceDescriptor; sliceD _ FindSelectedSlice[slice, normal]; GGSliceOps.SaveSelections[slice, IF sliceD = NIL THEN NIL ELSE sliceD.parts, normal]; sliceD _ FindSelectedSlice[slice, hot]; GGSliceOps.SaveSelections[slice, IF sliceD = NIL THEN NIL ELSE sliceD.parts, hot]; sliceD _ FindSelectedSlice[slice, active]; GGSliceOps.SaveSelections[slice, IF sliceD = NIL THEN NIL ELSE sliceD.parts, active]; sliceD _ FindSelectedSlice[slice, match]; GGSliceOps.SaveSelections[slice, IF sliceD = NIL THEN NIL ELSE sliceD.parts, match]; }; RemakeSelections: PROC [slice: Slice, scene: Scene, selectClass: SelectionClass] RETURNS [isTopLevel: BOOL _ FALSE] = { parts: SliceParts _ GGSliceOps.RemakeSelections[slice, selectClass]; IF GGScene.IsTopLevel[slice] THEN { DeselectEntireSlice[slice, scene, selectClass]; -- get rid of old selection SelectSliceFromParts[slice, parts, scene, selectClass]; isTopLevel _ TRUE; }; }; ReselectSliceAllClasses: PUBLIC PROC [slice: Slice, scene: Scene] = { [] _ RemakeSelections[slice, scene, normal]; [] _ RemakeSelections[slice, scene, hot]; [] _ RemakeSelections[slice, scene, active]; [] _ RemakeSelections[slice, scene, match]; }; ReselectTraj: PUBLIC PROC [traj: Slice, trajEnd: TrajEnd, scene: Scene, extend: BOOL] RETURNS [newHot: Sequence] = { newTrajD: SliceDescriptor; selSeq: Sequence; newSeqParts, newHotParts: TrajParts; selSeq _ FindSelectedSequence[traj, scene, normal]; IF selSeq#NIL THEN { newSeqParts _ GGSequence.Augment[selSeq, trajEnd, extend]; DeselectTraj[selSeq.slice, scene, normal]; newTrajD _ GGSlice.DescriptorFromParts[traj, newSeqParts]; SelectSlice[newTrajD, scene, normal]; }; selSeq _ FindSelectedSequence[traj, scene, hot]; IF selSeq#NIL THEN { newHotParts _ newSeqParts _ GGSequence.Augment[selSeq, trajEnd, extend]; DeselectTraj[selSeq.slice, scene, hot]; -- assumes second level Traj newTrajD _ newHot _ GGSlice.DescriptorFromParts[traj, newSeqParts]; SelectSlice[newTrajD, scene, hot]; }; }; DeleteSelection: PROC [scene: Scene, entity: SliceDescriptor, selectClass: SelectionClass] = { SetSelectedList[scene, DRemove[entity, ListSelected[scene, selectClass]], selectClass]; }; ListSelected: PUBLIC PROC [scene: Scene, selectClass: SelectionClass] RETURNS [selectedList: LIST OF SliceDescriptor] = { SELECT selectClass FROM normal => selectedList _ scene.selected.normal; hot => selectedList _ scene.selected.hot; active => selectedList _ scene.selected.active; match => selectedList _ scene.selected.match; ENDCASE => ERROR; }; SetSelected: PUBLIC PROC [scene: Scene, selectClass: SelectionClass, selected: LIST OF SliceDescriptor] = { FOR list: LIST OF SliceDescriptor _ selected, list.rest UNTIL list = NIL DO SelectSlice[list.first, scene, selectClass]; ENDLOOP; }; SetJointField: PROC [joint: Joint, selected: BOOL, selectClass: SelectionClass] = { SELECT selectClass FROM normal => joint.TselectedInFull.normal _ selected; hot => joint.TselectedInFull.hot _ selected; active => joint.TselectedInFull.active _ selected; match => joint.TselectedInFull.match _ selected; ENDCASE; }; SetSegmentField: PROC [seg: Segment, selected: BOOL, selectClass: SelectionClass] = { SELECT selectClass FROM normal => seg.TselectedInFull.normal _ selected; hot => seg.TselectedInFull.hot _ selected; active => seg.TselectedInFull.active _ selected; match => seg.TselectedInFull.match _ selected; ENDCASE; }; AppendSelection: PROC [scene: Scene, entity: SliceDescriptor, selectClass: SelectionClass] = { SELECT selectClass FROM normal => { IF scene.selected.normal = NIL THEN { scene.selected.normal _ LIST[entity]; scene.selected.normalPtr _ scene.selected.normal; scene.selected.normalPtrValid _ TRUE; } ELSE IF scene.selected.normalPtrValid THEN { scene.selected.normalPtr.rest _ LIST[entity]; scene.selected.normalPtr _ scene.selected.normalPtr.rest; } ELSE { scene.selected.normalPtr _ LastSliceDescriptor[scene.selected.normal]; scene.selected.normalPtr.rest _ LIST[entity]; scene.selected.normalPtr _ scene.selected.normalPtr.rest; scene.selected.normalPtrValid _ TRUE; }; }; hot => { IF scene.selected.hot = NIL THEN { scene.selected.hot _ LIST[entity]; scene.selected.hotPtr _ scene.selected.hot; scene.selected.hotPtrValid _ TRUE; } ELSE IF scene.selected.hotPtrValid THEN { scene.selected.hotPtr.rest _ LIST[entity]; scene.selected.hotPtr _ scene.selected.hotPtr.rest; } ELSE { scene.selected.hotPtr _ LastSliceDescriptor[scene.selected.hot]; scene.selected.hotPtr.rest _ LIST[entity]; scene.selected.hotPtr _ scene.selected.hotPtr.rest; scene.selected.hotPtrValid _ TRUE; }; }; active => { IF scene.selected.active = NIL THEN { scene.selected.active _ LIST[entity]; scene.selected.activePtr _ scene.selected.active; scene.selected.activePtrValid _ TRUE; } ELSE IF scene.selected.activePtrValid THEN { scene.selected.activePtr.rest _ LIST[entity]; scene.selected.activePtr _ scene.selected.activePtr.rest; } ELSE { scene.selected.activePtr _ LastSliceDescriptor[scene.selected.active]; scene.selected.activePtr.rest _ LIST[entity]; scene.selected.activePtr _ scene.selected.activePtr.rest; scene.selected.activePtrValid _ TRUE; }; }; match => { IF scene.selected.match = NIL THEN { scene.selected.match _ LIST[entity]; scene.selected.matchPtr _ scene.selected.match; scene.selected.matchPtrValid _ TRUE; } ELSE IF scene.selected.matchPtrValid THEN { scene.selected.matchPtr.rest _ LIST[entity]; scene.selected.matchPtr _ scene.selected.matchPtr.rest; } ELSE { scene.selected.matchPtr _ LastSliceDescriptor[scene.selected.match]; scene.selected.matchPtr.rest _ LIST[entity]; scene.selected.matchPtr _ scene.selected.matchPtr.rest; scene.selected.matchPtrValid _ TRUE; }; }; ENDCASE => ERROR; }; LastSliceDescriptor: PROC [sliceDList: LIST OF SliceDescriptor] RETURNS [last: LIST OF SliceDescriptor] = { FOR last _ sliceDList, last.rest UNTIL last.rest = NIL DO ENDLOOP; }; SetSelectedList: PROC [scene: Scene, value: LIST OF SliceDescriptor, selectClass: SelectionClass] = { SELECT selectClass FROM normal => { scene.selected.normal _ value; scene.selected.normalPtrValid _ FALSE; }; hot => { scene.selected.hot _ value; scene.selected.hotPtrValid _ FALSE; }; active => { scene.selected.active _ value; scene.selected.activePtrValid _ FALSE; }; match => { scene.selected.match _ value; scene.selected.matchPtrValid _ FALSE; }; ENDCASE => ERROR; }; IsSelectedInFull: PUBLIC PROC [slice: Slice, scene: Scene, selectClass: SelectionClass] RETURNS [BOOL] = { donkeyTail: SliceDescriptor _ SELECT selectClass FROM match => slice.matchSelectedParts, active => slice.activeSelectedParts, hot => slice.hotSelectedParts, normal => slice.normalSelectedParts, ENDCASE => ERROR; IF donkeyTail = NIL THEN RETURN[FALSE]; RETURN[GGSliceOps.IsCompleteParts[donkeyTail]]; }; IsSelectedInPart: PUBLIC PROC [entity: REF ANY, scene: Scene, selectClass: SelectionClass] RETURNS [BOOL] = { WITH entity SELECT FROM slice: Slice => { sliceD: SliceDescriptor _ FindSelectedSlice[slice, selectClass]; RETURN[sliceD # NIL]; }; traj: Slice => { seq: Sequence; seq _ FindSelectedSequence[traj, scene, selectClass]; RETURN[seq # NIL]; }; seq: Sequence => { selSeq: Sequence; selSeq _ FindSelectedSequence[seq.slice, scene, selectClass]; IF selSeq = seq THEN RETURN[TRUE]; IF selSeq = NIL THEN RETURN[FALSE]; RETURN[GGSequence.Overlap[seq, selSeq]]; }; ENDCASE => ERROR; }; NoSelections: PUBLIC PROC [scene: Scene, selectClass: SelectionClass] RETURNS [BOOL] = { SELECT selectClass FROM normal => RETURN[scene.selected.normal = NIL]; hot => RETURN[scene.selected.hot = NIL]; active => RETURN[scene.selected.active = NIL]; match => RETURN[scene.selected.match = NIL]; ENDCASE => ERROR; }; FindSelectedSequence: PROC [traj: Slice, scene: Scene, selectClass: SelectionClass] RETURNS [seq: Sequence] = { -- returns SliceDescriptor for a trajectory if selected LookForTraj: PROC [sliceD: SliceDescriptor] RETURNS [done: BOOL _ FALSE] = { IF sliceD.slice=traj THEN { seq _ sliceD; done _ TRUE; }; }; [] _ GGScene.WalkSelectedSlices[scene, leaf, LookForTraj, selectClass, $Traj]; }; FindSelectedSlice: PUBLIC PROC [slice: Slice, selectClass: SelectionClass] RETURNS [sliceD: SliceDescriptor] = { SELECT selectClass FROM normal => sliceD _ slice.normalSelectedParts; hot => sliceD _ slice.hotSelectedParts; active => sliceD _ slice.activeSelectedParts; match => sliceD _ slice.matchSelectedParts; ENDCASE => ERROR; }; GetLastSelection: PUBLIC PROC [scene: Scene] RETURNS [sliceD: SliceDescriptor] = { sliceD _ scene.selected.normalLast; }; SubstituteForSegment: PUBLIC PROC [traj: Slice, segNum: NAT, newRun: Slice, scene: Scene] RETURNS [bBox: BoundBox, newTraj: Slice] = { newOutlines: LIST OF Slice; trajData: TrajData _ NARROW[traj.data]; runParts: TrajParts _ GGSequence.CreateFromSegment[trajData, segNum]; run: SliceDescriptor _ GGSlice.DescriptorFromParts[traj, runParts]; oldOutline: Slice _ GGParent.GetParent[traj]; newOutline: Slice; priority: INT _ GGScene.GetPriority[scene, oldOutline]; GGOutline.SaveSelectionsInOutlineAllClasses[oldOutline]; DeselectTraj[traj, scene, normal]; DeselectTraj[traj, scene, hot]; newTraj _ GGTraj.SpliceIn[run, newRun]; newOutline _ GGParent.GetParent[newTraj]; GGScene.DeleteSlice[scene, oldOutline]; IF newOutline#NIL THEN { GGScene.AddSlice[scene, newOutline, priority]; ReselectSliceAllClasses[newOutline, scene]; }; bBox _ BoundBoxOfOutlines[newOutlines]; }; BoundBoxOfOutlines: PROC [outlines: LIST OF Slice] RETURNS [bBox: BoundBox] = { bBox _ GGBoundBox.NullBoundBox[]; FOR list: LIST OF Slice _ outlines, list.rest UNTIL list = NIL DO GGBoundBox.EnlargeByBox[bBox: bBox, by: GGSliceOps.GetBoundBox[list.first] ]; ENDLOOP; }; DRemove: PROC [ref: SliceDescriptor, list: LIST OF SliceDescriptor] RETURNS[LIST OF SliceDescriptor] = { l, l1: LIST OF SliceDescriptor _ NIL; l _ list; UNTIL l = NIL DO IF l.first=ref THEN { IF l1 = NIL THEN RETURN[l.rest]; -- ref was first object on list l1.rest _ l.rest; RETURN[list]; }; l1 _ l; l _ l.rest; ENDLOOP; RETURN [list]; }; END. ZGGSelectImpl.mesa Contents: Procedures dealing selecting and deselecting objects, including both selection actions and selection feedback. Copyright Σ 1988 by Xerox Corporation. All rights reserved. Pier, November 10, 1988 4:41:22 pm PST Kurlander August 28, 1986 7:54:12 pm PDT Bier, June 22, 1989 9:22:07 pm PDT Implementation Notes (updated July 6, 1987, by Bier) The Selection mechanism maintains two "structures" which must be kept consistent. The first is a list of selected SliceDescriptors: scene.selected. The second is the set of "selectedInFull" fields in each of the selected slices. To efficiently answer IsSelectedInFull queries, "selectedInFull" fields are found in slices, segments, joints, and control points. IsSelectedInFull is expensive for trajectories, and more expensive for outlines. To efficiently answer IsSelectedInPart queries, the selectedInFull field does double duty in segments, joints, control points, and slices. IsSelectedInPart is somewhat expensive for outlines. The following invariants should be maintained: 1) If a SliceDescriptor is on the selected list, all of the selectedInFull fields of its joints, segments, and control points should be TRUE. The selected fields are maintained for efficiency only. The information they represent is always obtainable from the selected list as well. Converse of 1: If no sequence representing a given joint, segment, or control point is on the selected list, then the selectedInFull field of that entity should be FALSE. 2) Only one sequence per trajectory may appear on the selected list. Corollary of 1 and 2: Any given selected flag is caused by a single element of the selected list. GetSelectedSequence will find that element (for joint, segments, and control points). A selected slice is its own cause. 3) A slice may only appear once on the selected list. 4) Iff a sequence representing a trajectory is on the selected list, the "selectedInPart" field of the trajectory will TRUE. 5) Iff a non-Outline slice is on the selected list, the "selectedInFull" field of that slice will be true. These invariants will be maintained with the help of SetComponentSelectedFields. Basic Selecting and Deselecting Clear all flags that indicate the selection of each object. Remove this slice from the selected list, and reset all selected fields. Very much like DeselectSlice, but optimized for the single Traj case. Updating Selections When Sequences Become Obsolete This routine propogates the former selection (say, hotness) to a newly extended traj and extends the selection to its end if extend = TRUE. newOutlineD: SliceDescriptor; normal selections hot selections Ignore active and match selections Utilities Deletes entity from list. If it is not on the list, do nothing. Operations which dispatch on the SelectionClass: For each SliceDescriptor in selected that is not obsolete, re-establish that selection. Remember to call DeselectAll[scene, selectClass] if you wish to replace any existing selections. OPERATIONS THAT ALTER THE SELECTED LISTS Build the selection list in the proper order and keep it that way. Enumerate Selected Objects Returns TRUE if all or part of entity is selected. These are the cases: 1) entity is a slice. Some outline is selected all or in part. 2) entity is an outline. Some trajectory is selected all or in part. 3) entity is a trajectory. Some joint or segment is selected. 4) entity is a sequence. Some joint or segment is selected. Replaces a segment with a new run. If newRun is not NIL, then only one trajectory is modified, and the new trajectory is returned. Also returned is the bbox of modified Outlines. ΚI˜Icodešœ™šΟnœq™yKšœ=™=Kšœ&™&Kšœ%Οk™(K™"—K™šž ˜ Jšœ¬˜¬K˜—š œžœž˜JšžœR˜YKšžœž˜&—˜Kšœ žœ˜&Kšœžœ˜!Kšœžœ˜3Kšœžœ˜,Kšœžœ˜!Kšœ žœžœ˜-Kšœ žœ˜+Kšœ žœ˜'Kšœžœ!˜7Kšœžœ!˜5Kšœ žœ˜'Kšœžœ ˜7Kšœžœ#˜=Kšœžœ˜!Kšœžœ ˜5Kšœžœ)˜GKšœžœ,˜MKšœžœ#˜;Kšœžœ(˜EKšœžœ˜3Kšœžœ"˜9Kšœ žœ˜+Kšœžœ˜1Kšœžœ#˜;Kšœ žœ˜'Kšœ žœ˜%Kšœ žœ˜)K˜Kšœžœžœ˜Ašœžœžœ˜,Kšœžœžœ˜K˜—Kšœžœžœ˜/šœžœžœ˜#KšœΟc)˜:KšœŸ)˜AKšœŸ˜7K˜K˜——K˜Kšœžœžœžœ˜(Iheadšœ4™4Kšœζ™ζKš œUΟbœ œ œ œS™ΤKšœΐ™ΐ™.Kšœˆžœ™›Kšœ₯žœ™«K™EKšœέ™έK™6Kšœxžœ™}Kšœk™k—šœP™PK™—K˜K™K™šœžœ;˜Qšžœ ž˜Kšœ4˜4Kšœ.˜.Kšœ4˜4Kšœ2˜2Kšžœ˜—K˜K˜—š œžœ0˜Bšžœ ž˜Kšœ&žœ˜*Kšœ žœ˜$Kšœ&žœ˜*Kšœ$žœ˜(Kšžœ˜—K˜—K˜š œžœžœ0˜Fš  œžœžœžœžœ˜CKšœ-˜-J˜—Kšœ$Οtœ ‘˜5šžœžœ˜šžœžœžœž˜BKšžœž˜$Kšžœ9˜=—K˜—K˜K˜—šœžœžœQ˜rKšœD˜DKšœ(˜(KšžœžœT˜pK˜K˜—š œžœžœI˜aKšœ"˜"Kšžœžœžœžœžœ!žœžœ˜SKšœ@˜@Kšœ9˜9šžœ žœžœ˜Kšœ1˜1KšœBŸ˜]K˜—Kšžœ˜Kšžœžœ5˜QKšœ+˜+Kšœ%˜%KšžœžœT˜pKšœŸ˜K˜—šœžœžœ>˜\Kšœ7žœ ˜CKšœ*˜*K˜K™—šœžœžœG˜gš  œžœžœžœžœ˜NJšœ$˜$J˜—Kšžœžœžœ˜!Kšœ,‘œ ‘œ ‘˜H˜J˜——š œžœžœ žœžœ0˜\šžœžœž˜Kšœ?˜?KšœY˜YKšžœžœ˜—K˜K˜—š œžœžœ žœžœ˜IKšœ&˜&Kšœ&˜&Kšœ#˜#Kšœ%˜%K˜K˜—š œžœžœ0˜HK™;š žœ žœžœAžœ žœž˜iKšœ.˜.Kšžœ˜—Kšœžœ˜)K˜K˜—šœžœžœ˜5Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜K˜—šœžœžœ>˜^KšœH™Hšžœžœ˜#Kšœ@˜@šžœ žœžœ˜Kšœ,˜,Kšœ(˜(K˜—šžœž˜šžœžœžœ(˜NKšžœžœ˜%——K˜—šžœ˜Kšœ6žœ ˜BKšœ@˜@K˜—K˜K˜—š œžœžœQ˜kKšœ#˜#K•StartOfExpansion?[slice: GGModelTypes.Slice, parts: GGModelTypes.SliceParts]šœ2˜2Kšœ>˜>Kšœ3˜3šžœžœžœ˜Kšœ/˜/Kšœ*˜*Kšœ&˜&šžœžœžœ˜+Kšžœžœ3˜OKšœ*˜*Kšœ$˜$K˜—šžœžœ˜Kšžœžœžœ(˜NKšžœZ˜^šžœžœžœ3˜XKšžœžœ˜%—K˜—K˜—K˜K˜—š œžœ=˜OKšœE™EKšœ5˜5KšœA˜Ašžœžœžœ˜Kšœ8˜8Kšœ*˜*Kšœ$˜$šžœžœžœ˜+Kšœ*˜*Kšœ$˜$K˜—šžœž˜šžœžœžœ+˜Qšžœ˜KšœQ˜Qšžœžœžœ3˜XKšžœžœ˜%—K˜———K˜—K˜—K™™2K™—šœžœžœ!˜MK˜Kšœ"‘œ˜*Kš œ!žœ žœžœžœžœ‘œ˜UKšœ"‘œ˜'Kš œ!žœ žœžœžœžœ‘œ˜RKšœ"‘œ˜*Kš œ!žœ žœžœžœžœ‘œ˜UKšœ"‘œ˜)Kš œ!žœ žœžœžœžœ‘œ˜TKšœ˜K˜—š œžœ;žœžœžœ˜wJ–h[slice: GGModelTypes.Slice, scene: GGModelTypes.Scene, selectClass: GGSegmentTypes.SelectionClass]šœD˜Dšžœžœ˜#Jšœ0Ÿ˜KJšœ7˜7Jšœ žœ˜J˜—K˜K˜—šœžœžœ!˜EKšœ$ œ˜,Jšœ$ œ˜)Jšœ$ œ˜,Jšœ$ œ˜+K˜K˜—š  œžœžœ7žœžœ˜tK™‹Kšœ™Kšœ˜Kšœ˜Kšœ$˜$Kšœ3˜3Kš ™šžœžœžœ˜Kšœ:˜:Kšœ*˜*Kšœ:˜:Kšœ%˜%K˜—Kš ™Kšœ0˜0šžœžœžœ˜KšœH˜HKšœ(Ÿ˜DKšœC˜CKšœ"˜"K˜—Kš "™"K˜—K˜™ K™—šœžœI˜^K™@šœ˜Kšœ2˜2Kšœ ˜ —K˜K˜—šœ0™0K™—š  œžœžœ-žœžœžœ˜yšžœ ž˜Kšœ/˜/Kšœ)˜)Kšœ/˜/Kšœ-˜-Kšžœžœ˜—K˜K˜—š  œžœžœ7žœžœ˜kKšœΉ™Ήš žœžœžœ'žœžœž˜KJšœ,˜,Jšžœ˜—K˜K˜—š œžœžœ#˜Tšžœ ž˜Kšœ2˜2Kšœ,˜,Kšœ2˜2Kšœ0˜0Kšžœ˜—K˜K˜—šœžœžœ#˜Všžœ ž˜Kšœ0˜0Kšœ*˜*Kšœ0˜0Kšœ.˜.Kšžœ˜—K˜K˜—K™(K™šœžœI˜^K™Bšžœ ž˜šœ ˜ šžœžœžœ˜%Kšœžœ ˜%Kšœ1˜1Kšœ žœ˜%K˜—šžœžœžœ˜,Kšœ žœ ˜-Kšœ9˜9K˜—šžœ˜KšœF˜FKšœ žœ ˜-Kšœ9˜9Kšœ žœ˜%K˜—K˜—šœ˜šžœžœžœ˜"Kšœžœ ˜"Kšœ+˜+Kšœžœ˜"K˜—šžœžœžœ˜)Kšœžœ ˜*Kšœ3˜3K˜—šžœ˜Kšœ@˜@Kšœžœ ˜*Kšœ3˜3Kšœžœ˜"K˜—K˜—šœ ˜ šžœžœžœ˜%Kšœžœ ˜%Kšœ1˜1Kšœ žœ˜%K˜—šžœžœžœ˜,Kšœ žœ ˜-Kšœ9˜9K˜—šžœ˜KšœF˜FKšœ žœ ˜-Kšœ9˜9Kšœ žœ˜%K˜—K˜—šœ ˜ šžœžœžœ˜$Kšœžœ ˜$Kšœ/˜/Kšœžœ˜$K˜—šžœžœžœ˜+Kšœžœ ˜,Kšœ7˜7K˜—šžœ˜KšœD˜DKšœžœ ˜,Kšœ7˜7Kšœžœ˜$K˜—K˜—Kšžœžœ˜—K˜K˜—šœžœžœžœžœžœžœ˜kKš žœžœ žœžœžœ˜BK˜K˜—šœžœžœžœ2˜ešžœ ž˜šœ ˜ Kšœ˜Kšœ žœ˜&K˜—šœ˜Kšœ˜Kšœžœ˜#K˜—šœ ˜ Kšœ˜Kšœ žœ˜&K˜—šœ ˜ Kšœ˜Kšœžœ˜%K˜—Kšžœžœ˜—K˜—K˜™K˜—š œžœžœ;žœžœ˜jšœžœ ž˜5Kšœ"˜"Kšœ$˜$Kšœ˜Kšœ$˜$Kšžœžœ˜—Kš žœžœžœžœžœ˜'Kšžœ)˜/K˜K˜—šœžœžœ žœžœ-žœžœ˜mKšœžœ<™HKšœ@™@KšœF™FKšœ?™?Kšœ=™=Kšžœžœž˜šœ˜Kšœ@˜@Kšžœ žœ˜K˜—šœ˜Kšœ˜Kšœ5˜5Kšžœžœ˜K˜—šœ˜Kšœ˜Kšœ=˜=Kšžœžœžœžœ˜"Kš žœ žœžœžœžœ˜#Kšžœ"˜(K˜—Kšžœžœ˜K˜K™—š  œžœžœ-žœžœ˜Xšžœ ž˜Kšœ žœžœ˜.Kšœžœžœ˜(Kšœ žœžœ˜.Kšœ žœžœ˜,Kšžœžœ˜—K˜K˜—šœžœ:žœŸ7˜§š  œžœžœžœžœ˜Lšžœžœ˜Kšœ ˜ Kšœžœ˜ K˜—J˜—Kšœ+‘œ‘˜NK˜K˜—šœžœžœ-žœ˜pšžœ ž˜Kšœ-˜-Kšœ'˜'Kšœ-˜-Kšœ+˜+Kšžœžœ˜—Kšœ˜K˜—šœžœžœžœ˜RKšœ#˜#K˜K˜—š œžœžœžœžœ%˜†Jšœ5žœ|™΄Kšœ žœžœ˜Kšœžœ ˜'KšœE˜EKšœC˜CKšœ-˜-Kšœ˜Kšœ žœ*˜7K˜Jšœ8˜8J˜"J˜Kšœ'˜'Kšœ)˜)Kšœ'˜'šžœ žœžœ˜Kšœ.˜.Jšœ+˜+J˜—J˜'K˜K˜—š œžœ žœžœžœ˜OKšœ!˜!š žœžœžœžœžœž˜AK–<[bBox: GGBasicTypes.BoundBox, by: GGBasicTypes.BoundBox]šœM˜MKšžœ˜—K˜—K˜šœžœžœžœžœžœžœ˜iKšœžœžœžœ˜%K˜ šžœžœž˜šžœ žœ˜Kš žœžœžœžœ Ÿ˜@K˜Kšžœ˜ Kšœ˜—K˜K˜ Kšžœ˜—Kšžœ˜Kšœ˜—K˜Kšžœ˜—…—GΈk[