<> <> <> <> <> <> <<>> DIRECTORY GGBasicTypes, GGBoundBox, GGCaret, GGModelTypes, GGObjects, GGOutline, GGInterfaceTypes, GGSceneType, GGSegmentTypes, GGSelect, GGSequence, GGTraj, GGUtility, List; GGSelectImpl: CEDAR PROGRAM IMPORTS GGBoundBox, GGCaret, GGObjects, GGOutline, GGSequence, GGTraj, GGUtility, List EXPORTS GGModelTypes, GGSelect = BEGIN BoundBox: TYPE = GGBasicTypes.BoundBox; Caret: TYPE = GGInterfaceTypes.Caret; EntityGenerator: TYPE = REF EntityGeneratorObj; EntityGeneratorObj: TYPE = GGModelTypes.EntityGeneratorObj; Joint: TYPE = GGModelTypes.Joint; JointGenerator: TYPE = GGModelTypes.JointGenerator; Outline: TYPE = GGModelTypes.Outline; OutlineDescriptor: TYPE = REF OutlineDescriptorObj; OutlineDescriptorObj: TYPE = GGModelTypes.OutlineDescriptorObj; SceneRef: TYPE = REF SceneObj; SceneObj: PUBLIC TYPE = GGSceneType.SceneObj; SegAndIndex: TYPE = GGSequence.SegAndIndex; Segment: TYPE = GGSegmentTypes.Segment; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; SelectionClass: TYPE = GGInterfaceTypes.SelectionClass; Sequence: TYPE = REF SequenceObj; SequenceGenerator: TYPE = REF SequenceGeneratorObj; SequenceGeneratorObj: TYPE = GGModelTypes.SequenceGeneratorObj; SequenceObj: TYPE = GGModelTypes.SequenceObj; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = GGModelTypes.SliceDescriptorGenerator; SliceDescriptorGeneratorObj: TYPE = GGModelTypes.SliceDescriptorGeneratorObj; SliceDescriptorObj: TYPE = GGModelTypes.SliceDescriptorObj; SliceGenerator: TYPE = REF SliceGeneratorObj; SliceGeneratorObj: TYPE = GGModelTypes.SliceGeneratorObj; SliceParts: TYPE = GGModelTypes.SliceParts; Traj: TYPE = GGModelTypes.Traj; TrajEnd: TYPE = GGModelTypes.TrajEnd; TrajGenerator: TYPE = REF TrajGeneratorObj; TrajGeneratorObj: TYPE = GGModelTypes.TrajGeneratorObj; NotYetImplemented: PUBLIC SIGNAL = CODE; OutlineSequenceGenerator: TYPE = REF OutlineSequenceGeneratorObj; OutlineSequenceGeneratorObj: TYPE = GGSelect.OutlineSequenceGeneratorObj; OutlineSequence: TYPE = REF OutlineSequenceObj; OutlineSequenceObj: TYPE = GGSelect.OutlineSequenceObj; <> <> <> <> <> <<1) If an OutlineDescriptor 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.>> <> <<2) Only one sequence per trajectory may appear on the selected list.>> <> <<3) A non-gargoyle 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-Gargoyle slice is on the selected list, the "selectedInFull" field of that slice will be true.>> <> <<>> <> <> < {>> <> <<};>> < {>> <> <<};>> < { -- this case needed for ReselectTraj>> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> < ERROR;>> <<};>> <<>> <> <<>> ChangeDonkeyTail: PROC [sliceD: SliceDescriptor, selectClass: SelectionClass] = { SELECT selectClass FROM normal => sliceD.slice.normalSelectedParts _ sliceD.parts; hot => sliceD.slice.hotSelectedParts _ sliceD.parts; active => sliceD.slice.activeSelectedParts _ sliceD.parts; ENDCASE; }; ChangeDonkeyTailOutline: PROC [sliceD: OutlineDescriptor, selectClass: SelectionClass] = { SELECT selectClass FROM normal => sliceD.slice.normalSelectedParts _ sliceD.parts; hot => sliceD.slice.hotSelectedParts _ sliceD.parts; active => sliceD.slice.activeSelectedParts _ sliceD.parts; ENDCASE; }; NoDonkeyTail: PROC [slice: Slice, selectClass: SelectionClass] = { SELECT selectClass FROM normal => slice.normalSelectedParts _ NIL; hot => slice.hotSelectedParts _ NIL; active => slice.activeSelectedParts _ NIL; ENDCASE; }; NoDonkeyTailOutline: PROC [slice: Outline, selectClass: SelectionClass] = { SELECT selectClass FROM normal => slice.normalSelectedParts _ NIL; hot => slice.hotSelectedParts _ NIL; active => slice.activeSelectedParts _ NIL; ENDCASE; }; SelectAll: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] = { entityGen: EntityGenerator; entityGen _ GGObjects.TopLevelEntitiesInScene[scene]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO WITH entity SELECT FROM slice: Slice => { SelectEntireSlice[slice, scene, selectClass]; }; outline: Outline => { SelectEntireOutline[outline, scene, selectClass]; }; ENDCASE => ERROR; ENDLOOP; }; SelectSlice: PUBLIC PROC [slice: Slice, parts: SliceParts, scene: SceneRef, selectClass: SelectionClass] = { oldSliceD, sliceD: SliceDescriptor; IF slice.class.emptyParts[slice, parts] THEN RETURN; oldSliceD _ FindSelectedSlice[slice, scene, selectClass]; IF oldSliceD#NIL THEN { parts _ slice.class.unionParts[slice, oldSliceD.parts, parts]; DeselectSlice[slice, oldSliceD.parts, scene, selectClass]; -- throw away old selection }; IF selectClass = normal THEN parts _ slice.class.augmentParts[slice, parts, selectClass]; sliceD _ NEW[SliceDescriptorObj _ [slice, parts] ]; AppendSelection[scene, sliceD, selectClass]; ChangeDonkeyTail[sliceD, selectClass]; <> }; -- end SelectSlice SelectOutline: PUBLIC PROC [outline: Outline, parts: SliceParts, scene: SceneRef, selectClass: SelectionClass] = { oldD, newD: OutlineDescriptor; IF outline.class.emptyParts[outline, parts] THEN RETURN; oldD _ FindSelectedOutline[outline, scene, selectClass]; IF oldD # NIL THEN { parts _ outline.class.unionParts[outline, oldD.parts, parts]; DeselectOutline[outline, oldD.parts, scene, selectClass]; -- throw away old selection }; IF selectClass = normal THEN parts _ outline.class.augmentParts[outline, parts, selectClass]; newD _ NEW[OutlineDescriptorObj _ [outline, parts] ]; AppendSelection[scene, newD, selectClass]; ChangeDonkeyTailOutline[newD, selectClass]; <> }; -- end SelectOutline SelectEntireOutline: PUBLIC PROC [outline: Outline, scene: SceneRef, selectClass: SelectionClass] = { allParts: SliceParts _ outline.class.newParts[outline, NIL, slice]; SelectOutline[outline, allParts, scene, selectClass]; }; SelectEntireSlice: PUBLIC PROC [slice: Slice, scene: SceneRef, selectClass: SelectionClass] = { allParts: SliceParts _ slice.class.newParts[slice, NIL, slice]; SelectSlice[slice, allParts, scene, selectClass]; }; <<>> SelectSequence: PUBLIC PROC [seq: Sequence, scene: SceneRef, selectClass: SelectionClass] = { outline: Outline _ GGOutline.OutlineOfTraj[seq.traj]; parts: SliceParts; IF GGSequence.IsEmpty[seq] THEN RETURN; parts _ GGOutline.PartsFromSequence[outline, seq]; SelectOutline[outline, parts, scene, selectClass]; }; SelectTraj: PUBLIC PROC [traj: Traj, scene: SceneRef, selectClass: SelectionClass] = { <> wholeSeq: Sequence; wholeSeq _ GGSequence.CreateComplete[traj]; SelectSequence[wholeSeq, scene, selectClass]; }; <<>> DuplicateSelections: PROC [scene: SceneRef, fromClass: SelectionClass, toClass: SelectionClass] = { sliceDescGen: GGSelect.SliceDescriptorGenerator; seqGen: SequenceGenerator; sliceDescGen _ SelectedSlices[scene, fromClass]; FOR sliceD: SliceDescriptor _ NextSliceDescriptor[sliceDescGen], NextSliceDescriptor[sliceDescGen] UNTIL sliceD = NIL DO SelectSlice[sliceD.slice, sliceD.parts, scene, toClass]; ENDLOOP; seqGen _ SelectedSequences[scene, fromClass]; FOR seq: Sequence _ GGSequence.NextSequence[seqGen], GGSequence.NextSequence[seqGen] UNTIL seq = NIL DO SelectSequence[seq, scene, toClass]; ENDLOOP; }; DeselectAll: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] = { <> FOR selected: LIST OF REF ANY _ ListSelected[scene, selectClass], selected.rest UNTIL selected = NIL DO <> WITH selected.first SELECT FROM sliceD: SliceDescriptor => NoDonkeyTail[sliceD.slice, selectClass]; outlineD: OutlineDescriptor => NoDonkeyTailOutline[outlineD.slice, selectClass]; ENDCASE => ERROR; ENDLOOP; SetSelectedList[scene, NIL, selectClass]; }; DeselectEntity: PUBLIC PROC [entity: REF ANY, scene: SceneRef, selectClass: SelectionClass] = { WITH entity SELECT FROM seq: Sequence => DeselectSequence[seq, scene, selectClass]; traj: Traj => DeselectTraj[traj, scene, selectClass]; outline: Outline => DeselectEntireOutline[outline, scene, selectClass]; outlineD: OutlineDescriptor => DeselectOutline[outlineD.slice, outlineD.parts, scene, selectClass]; slice: Slice => DeselectEntireSlice[slice, scene, selectClass]; sliceD: SliceDescriptor => DeselectSlice[sliceD.slice, sliceD.parts, scene, selectClass]; ENDCASE => ERROR; }; DeselectEntityAllClasses: PUBLIC PROC [entity: REF ANY, scene: SceneRef] = { DeselectEntity[entity, scene, normal]; DeselectEntity[entity, scene, active]; DeselectEntity[entity, scene, hot]; }; DeselectAllAllClasses: PUBLIC PROC [scene: SceneRef] = { DeselectAll[scene, normal]; DeselectAll[scene, active]; DeselectAll[scene, hot]; }; DeselectEntireSlice: PUBLIC PROC [slice: Slice, scene: SceneRef, selectClass: SelectionClass] = { <> selSliceD: SliceDescriptor _ FindSelectedSlice[slice, scene, selectClass]; IF selSliceD#NIL THEN { IF selSliceD.slice.class.type = $Outline THEN ERROR NotYetImplemented; DeleteSelection[scene, selSliceD, selectClass]; NoDonkeyTail[selSliceD.slice, selectClass]; <> }; }; DeselectSlice: PUBLIC PROC [slice: Slice, parts: SliceParts, scene: SceneRef, selectClass: SelectionClass] = { oldD, newD: SliceDescriptor; newParts: SliceParts; oldD _ FindSelectedSlice[slice, scene, selectClass]; IF oldD # NIL THEN { newParts _ slice.class.differenceParts[slice, oldD.parts, parts]; DeleteSelection[scene, oldD, selectClass]; NoDonkeyTail[oldD.slice, selectClass]; <> IF NOT slice.class.emptyParts[slice, newParts] THEN { IF selectClass = normal THEN newParts _ slice.class.augmentParts[slice, newParts, selectClass]; newD _ NEW[SliceDescriptorObj _ [slice, newParts] ]; AppendSelection[scene, newD, selectClass]; ChangeDonkeyTail[newD, selectClass]; <> }; }; }; DeselectOutline: PUBLIC PROC [outline: Outline, parts: SliceParts, scene: SceneRef, selectClass: SelectionClass] = { <> oldD, newD: OutlineDescriptor; newParts: SliceParts; oldD _ FindSelectedOutline[outline, scene, selectClass]; IF oldD # NIL THEN { newParts _ outline.class.differenceParts[outline, oldD.parts, parts]; DeleteSelection[scene, oldD, selectClass]; NoDonkeyTailOutline[oldD.slice, selectClass]; IF NOT outline.class.emptyParts[outline, newParts] THEN { IF selectClass = normal THEN newParts _ outline.class.augmentParts[outline, newParts, selectClass]; newD _ NEW[OutlineDescriptorObj _ [outline, newParts] ]; AppendSelection[scene, newD, selectClass]; ChangeDonkeyTailOutline[newD, selectClass]; }; }; }; DeselectSequence: PUBLIC PROC [seq: Sequence, scene: SceneRef, selectClass: SelectionClass] = { outline: Outline _ GGOutline.OutlineOfTraj[seq.traj]; seqParts: SliceParts _ GGOutline.PartsFromSequence[outline, seq]; DeselectOutline[outline, seqParts, scene, selectClass]; }; DeselectEntireOutline: PUBLIC PROC [outline: Outline, scene: SceneRef, selectClass: SelectionClass] = { <> outlineD: OutlineDescriptor _ FindSelectedOutline[outline, scene, selectClass]; IF outlineD # NIL THEN { DeleteSelection[scene, outlineD, selectClass]; NoDonkeyTailOutline[outlineD.slice, selectClass]; }; }; DeselectTraj: PUBLIC PROC [traj: Traj, scene: SceneRef, selectClass: SelectionClass] = { outline: Outline _ GGOutline.OutlineOfTraj[traj]; outlineD: OutlineDescriptor _ FindSelectedOutline[outline, scene, selectClass]; IF outlineD # NIL THEN { GGOutline.RemoveTraj[outlineD, traj]; -- bashes the descriptor in place IF outline.class.emptyParts[outlineD.slice, outlineD.parts] THEN { DeleteSelection[scene, outlineD, selectClass]; NoDonkeyTailOutline[outlineD.slice, selectClass]; }; }; }; <<>> <> <<>> ReselectTraj: PUBLIC PROC [traj: Traj, trajEnd: TrajEnd, scene: SceneRef, extend: BOOL] = { selSeq, newSeq: Sequence; selSeq _ FindSelectedSequence[traj, scene, normal]; <> IF selSeq # NIL THEN { newSeq _ GGSequence.Augment[selSeq, trajEnd, extend]; DeselectTraj[selSeq.traj, scene, normal]; SelectSequence[newSeq, scene, normal]; }; <> selSeq _ FindSelectedSequence[traj, scene, hot]; IF selSeq # NIL THEN { newSeq _ GGSequence.Augment[selSeq, trajEnd, extend]; DeselectTraj[selSeq.traj, scene, hot]; SelectSequence[newSeq, scene, hot]; }; <> selSeq _ FindSelectedSequence[traj, scene, active]; IF selSeq # NIL THEN { ERROR; -- I don't think ReselectTraj should be used for active }; }; <> <<>> DeleteSelection: PROC [scene: SceneRef, entity: REF ANY, selectClass: SelectionClass] = { <> SetSelectedList[scene, List.DRemove[entity, ListSelected[scene, selectClass]], selectClass]; }; ListSelected: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [selectedList: LIST OF REF ANY] = { SELECT selectClass FROM normal => selectedList _ scene.selected.normal; hot => selectedList _ scene.selected.hot; active => selectedList _ scene.selected.active; ENDCASE => ERROR; }; ListSelectedSequences: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [selectedList: LIST OF Sequence] = { <> seq: Sequence; selectedList _ NIL; FOR entityList: LIST OF REF ANY _ ListSelected[scene, selectClass], entityList.rest UNTIL entityList = NIL DO IF ISTYPE[entityList.first, Sequence] THEN { seq _ NARROW[entityList.first]; selectedList _ CONS[seq, selectedList]; }; ENDLOOP; }; <> <<>> SetSliceField: PROC [slice: Slice, selected: BOOL, selectClass: SelectionClass] = { SELECT selectClass FROM normal => slice.selectedInFull.normal _ selected; hot => slice.selectedInFull.hot _ selected; active => slice.selectedInFull.active _ selected; ENDCASE; }; 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; 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; ENDCASE; }; AppendSelection: PROC [scene: SceneRef, entity: REF ANY, selectClass: SelectionClass] = { <> SELECT selectClass FROM normal => scene.selected.normal _ List.Nconc[scene.selected.normal, LIST[entity]]; hot => scene.selected.hot _ List.Nconc[scene.selected.hot, LIST[entity]]; active => scene.selected.active _ List.Nconc[scene.selected.active, LIST[entity]]; ENDCASE => ERROR; }; SetSelectedList: PROC [scene: SceneRef, value: LIST OF REF ANY, selectClass: SelectionClass] = { SELECT selectClass FROM normal => scene.selected.normal _ value; hot => scene.selected.hot _ value; active => scene.selected.active _ value; ENDCASE => ERROR; }; <> IsSelectedInFull: PUBLIC PROC [entity: REF ANY, scene: SceneRef, selectClass: SelectionClass] RETURNS [BOOL] = { WITH entity SELECT FROM slice: Slice => { IF slice.class.type = $Outline THEN ERROR NotYetImplemented; SELECT selectClass FROM normal => RETURN[slice.selectedInFull.normal]; hot => RETURN[slice.selectedInFull.hot]; active => RETURN[slice.selectedInFull.active]; ENDCASE => ERROR; }; outline: Outline => { trajGen: TrajGenerator; trajGen _ GGOutline.TrajsInOutline[outline]; FOR traj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL traj = NIL DO IF NOT IsSelectedInFull[traj, scene, selectClass] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; }; traj: Traj => { seq: Sequence; seq _ FindSelectedSequence[traj, scene, selectClass]; IF seq = NIL THEN RETURN[FALSE]; RETURN[GGSequence.IsComplete[seq]]; }; ENDCASE => ERROR; }; IsSelectedInPart: PUBLIC PROC [entity: REF ANY, scene: SceneRef, selectClass: SelectionClass] RETURNS [BOOL] = { <> <<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.>> WITH entity SELECT FROM slice: Slice => { sliceD: SliceDescriptor; sliceD _ FindSelectedSlice[slice, scene, selectClass]; RETURN[sliceD # NIL]; }; outline: Outline => { outlineD: OutlineDescriptor; outlineD _ FindSelectedOutline[outline, scene, selectClass]; RETURN[outlineD # NIL] }; traj: Traj => { seq: Sequence; seq _ FindSelectedSequence[traj, scene, selectClass]; RETURN[seq # NIL]; }; seq: Sequence => { selSeq: Sequence; selSeq _ FindSelectedSequence[seq.traj, 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: SceneRef, 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]; ENDCASE => ERROR; }; SelectedStuff: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [selectedGen: EntityGenerator] = { <> selectedGen _ NEW[EntityGeneratorObj _ [ list: ListSelected[scene, selectClass], countValid: FALSE, count: 0 ]]; }; FindSelectedSequence: PUBLIC PROC [traj: Traj, scene: SceneRef, selectClass: SelectionClass] RETURNS [seq: Sequence] = { FOR l: LIST OF REF ANY _ ListSelected[scene, selectClass], l.rest UNTIL l = NIL DO IF ISTYPE[l.first, OutlineDescriptor] THEN { outlineD: OutlineDescriptor _ NARROW[l.first, OutlineDescriptor]; seq _ GGOutline.FindTrajInDescriptor[outlineD, traj]; IF seq # NIL THEN RETURN[seq]; }; ENDLOOP; RETURN[NIL]; }; FindSequenceInList: PUBLIC PROC [traj: Traj, selectedList: LIST OF REF ANY] RETURNS [seq: Sequence] = { FOR l: LIST OF REF ANY _ selectedList, l.rest UNTIL l = NIL DO IF ISTYPE[l.first, OutlineDescriptor] THEN { outlineD: OutlineDescriptor _ NARROW[l.first, OutlineDescriptor]; seq _ GGOutline.FindTrajInDescriptor[outlineD, traj]; IF seq # NIL THEN RETURN[seq]; }; ENDLOOP; RETURN[NIL]; }; SelectedSequences: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [seqGen: SequenceGenerator] = { seq: Sequence; ptr, seqList: LIST OF Sequence; seqGen _ NEW[SequenceGeneratorObj]; [seqGen.list, ptr] _ GGUtility.StartSequenceList[]; FOR entityList: LIST OF REF ANY _ ListSelected[scene, selectClass], entityList.rest UNTIL entityList = NIL DO IF ISTYPE[entityList.first, OutlineDescriptor] THEN { seqList _ GGOutline.SequencesOfOutline[NARROW[entityList.first]]; FOR list: LIST OF Sequence _ seqList, list.rest UNTIL list = NIL DO seq _ NARROW[list.first]; [seqGen.list, ptr] _ GGUtility.AddSequence[seq, seqGen.list, ptr]; ENDLOOP; }; ENDLOOP; }; SelectedOutlines: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [outDGen: GGModelTypes.OutlineDescriptorGenerator] = { sliceD: OutlineDescriptor _ NIL; ptr: LIST OF OutlineDescriptor _ NIL; outDGen _ NEW[GGModelTypes.OutlineDescriptorGeneratorObj]; FOR entityList: LIST OF REF ANY _ ListSelected[scene, selectClass], entityList.rest UNTIL entityList = NIL DO IF ISTYPE[entityList.first, OutlineDescriptor] THEN { sliceD _ NARROW[entityList.first]; [outDGen.list, ptr] _ AddOutlineDescriptor[sliceD, outDGen.list, ptr]; }; ENDLOOP; }; FindSelectedSlice: PUBLIC PROC [slice: Slice, scene: SceneRef, selectClass: SelectionClass] RETURNS [sliceD: SliceDescriptor] = { FOR l: LIST OF REF ANY _ ListSelected[scene, selectClass], l.rest UNTIL l = NIL DO IF ISTYPE[l.first, SliceDescriptor] THEN { sliceD _ NARROW[l.first]; IF sliceD.slice = slice THEN RETURN; }; ENDLOOP; RETURN[NIL]; }; FindSelectedOutline: PUBLIC PROC [outline: Outline, scene: SceneRef, selectClass: SelectionClass] RETURNS [outlineD: OutlineDescriptor] = { FOR l: LIST OF REF ANY _ ListSelected[scene, selectClass], l.rest UNTIL l = NIL DO WITH l.first SELECT FROM sliceD: SliceDescriptor => NULL; outlineD: OutlineDescriptor => { IF outlineD.slice = outline THEN RETURN[outlineD]; }; ENDCASE => ERROR; ENDLOOP; RETURN[NIL]; }; <<>> <> <> < sliceD _ IF slice.normalSelectedParts = NIL THEN NIL ELSE NEW[SliceDescriptorObj _ [slice, slice.normalSelectedParts]];>> < sliceD _ IF slice.hotSelectedParts = NIL THEN NIL ELSE NEW[SliceDescriptorObj _ [slice, slice.hotSelectedParts]];>> < sliceD _ IF slice.activeSelectedParts = NIL THEN NIL ELSE NEW[SliceDescriptorObj _ [slice, slice.activeSelectedParts]];>> < ERROR;>> <<};>> SelectedSlices: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [sliceDescGen: SliceDescriptorGenerator] = { sliceD: SliceDescriptor _ NIL; ptr: LIST OF SliceDescriptor _ NIL; sliceDescGen _ NEW[SliceDescriptorGeneratorObj]; FOR entityList: LIST OF REF ANY _ ListSelected[scene, selectClass], entityList.rest UNTIL entityList = NIL DO IF ISTYPE[entityList.first, SliceDescriptor] THEN { sliceD _ NARROW[entityList.first]; [sliceDescGen.list, ptr] _ AddSliceDescriptor[sliceD, sliceDescGen.list, ptr]; }; ENDLOOP; }; NextSliceDescriptor: PUBLIC PROC [g: SliceDescriptorGenerator] RETURNS [next: SliceDescriptor] = { IF g.list = NIL THEN RETURN[NIL] ELSE { next _ g.list.first; g.list _ g.list.rest; }; }; NextOutlineDescriptor: PUBLIC PROC [g: GGModelTypes.OutlineDescriptorGenerator] RETURNS [next: OutlineDescriptor] = { IF g.list = NIL THEN RETURN[NIL] ELSE { next _ g.list.first; g.list _ g.list.rest; }; }; AddSliceDescriptor: PROC [entity: SliceDescriptor, entityList, ptr: LIST OF SliceDescriptor] RETURNS [newList, newPtr: LIST OF SliceDescriptor] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; AddOutlineDescriptor: PROC [entity: OutlineDescriptor, entityList, ptr: LIST OF OutlineDescriptor] RETURNS [newList, newPtr: LIST OF OutlineDescriptor] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; nilSeqGen: SequenceGenerator _ NEW[SequenceGeneratorObj _ [list: NIL]]; SelectedOutlineSequences: PUBLIC PROC [scene: SceneRef, selectClass: SelectionClass] RETURNS [outSeqGen: OutlineSequenceGenerator] = { <> holeSeqs, ptr: LIST OF Sequence; outSeqPtr: LIST OF OutlineSequence; outlineSeq: OutlineSequence; fenceSeq, seq: Sequence; entityGen: GGModelTypes.EntityGenerator; seqList: LIST OF Sequence; newSeqGen: SequenceGenerator; outSeqGen _ NEW[OutlineSequenceGeneratorObj]; [outSeqGen.list, outSeqPtr] _ StartOutlineSequenceList[]; entityGen _ SelectedStuff[scene, selectClass]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO WITH entity SELECT FROM sliceD: SliceDescriptor => NULL; outlineD: OutlineDescriptor => { fenceSeq _ NIL; [holeSeqs, ptr] _ GGUtility.StartSequenceList[]; seqList _ GGOutline.SequencesOfOutline[outlineD]; seq _ seqList.first; IF seq.traj.role = fence OR seq.traj.role = open THEN { fenceSeq _ seq; seqList _ seqList.rest; }; FOR list: LIST OF Sequence _ seqList, list.rest UNTIL list = NIL DO [holeSeqs, ptr] _ GGUtility.AddSequence[list.first, holeSeqs, ptr]; ENDLOOP; newSeqGen _ IF holeSeqs=NIL THEN nilSeqGen ELSE NEW[SequenceGeneratorObj _ [list: holeSeqs]]; outlineSeq _ NEW[OutlineSequenceObj _ [outline: outlineD.slice, fenceSeq: fenceSeq, holeSeqs: newSeqGen]]; [outSeqGen.list, outSeqPtr] _ AddOutlineSequence[outlineSeq, outSeqGen.list, outSeqPtr]; }; ENDCASE => ERROR; ENDLOOP; }; <<>> <<>> NextOutlineSequences: PUBLIC PROC [outSeqGen: OutlineSequenceGenerator] RETURNS [outSeq: OutlineSequence] = { IF outSeqGen.list = NIL THEN RETURN[NIL]; outSeq _ outSeqGen.list.first; outSeqGen.list _ outSeqGen.list.rest; }; AddOutlineSequence: PUBLIC PROC [entity: OutlineSequence, entityList, ptr: LIST OF OutlineSequence] RETURNS [newList, newPtr: LIST OF OutlineSequence] = { IF ptr = NIL THEN { IF NOT entityList = NIL THEN ERROR; newPtr _ newList _ CONS[entity, NIL]; RETURN; } ELSE { newList _ entityList; ptr.rest _ CONS[entity, NIL]; newPtr _ ptr.rest; }; }; StartOutlineSequenceList: PUBLIC PROC [] RETURNS [entityList, ptr: LIST OF OutlineSequence] = { ptr _ entityList _ NIL; }; <> ForEachOutlineRun: PUBLIC PROC [scene: SceneRef, caret: Caret, selectClass: SelectionClass, runProc: RunProc, segmentsOnly: BOOL _ TRUE, selectNewRuns: BOOL _ FALSE] RETURNS [bBox: BoundBox] = { outSeqGen: OutlineSequenceGenerator; fenceSeq: Sequence; thisBox: BoundBox; bBox _ GGBoundBox.BoundBoxOfSelected[scene, normal]; DuplicateSelections[scene, normal, active]; -- all normal selected objects become active outSeqGen _ SelectedOutlineSequences[scene, active]; IF outSeqGen.list # NIL THEN { GGCaret.NoAttractor[caret: caret]; GGCaret.SitOn[caret, NIL]; }; WHILE outSeqGen.list # NIL DO -- while any active objects remain. FOR outSeq: GGSelect.OutlineSequence _ NextOutlineSequences[outSeqGen], NextOutlineSequences[outSeqGen] UNTIL outSeq = NIL DO fenceSeq _ outSeq.fenceSeq; IF fenceSeq # NIL THEN { thisBox _ GetRunAndReplace[fenceSeq, scene, runProc, segmentsOnly, selectNewRuns]; GGBoundBox.EnlargeByBox[bBox: bBox, by: thisBox]; GOTO SelectionsHaveChanged; }; FOR holeSeq: Sequence _ GGSequence.NextSequence[outSeq.holeSeqs], GGSequence.NextSequence[outSeq.holeSeqs] UNTIL holeSeq = NIL DO thisBox _ GetRunAndReplace[holeSeq, scene, runProc, segmentsOnly, selectNewRuns]; GGBoundBox.EnlargeByBox[bBox: bBox, by: thisBox]; GOTO SelectionsHaveChanged; ENDLOOP; REPEAT SelectionsHaveChanged => { outSeqGen _ SelectedOutlineSequences[scene, active]; }; ENDLOOP; ENDLOOP; }; RunProc: TYPE = GGSelect.RunProc; GetRunAndReplace: PROC [seq: Sequence, scene: SceneRef, runProc: RunProc, segmentsOnly: BOOL, selectNewRuns: BOOL] RETURNS [bBox: BoundBox] = { <> <> oldOutline: Outline; runGen: SequenceGenerator; runCount: NAT; newRun: Traj; newOutlines: LIST OF Outline; run: Sequence; oldOutline _ GGOutline.OutlineOfTraj[seq.traj]; GGOutline.SaveSelectionsInOutline[oldOutline, scene]; IF GGSequence.IsComplete[seq] THEN run _ seq ELSE { [runGen, runCount] _ GGSequence.RunsInSequence[seq]; IF runCount = 0 THEN { DeselectSequence[seq, scene, active]; -- maintain the important invariant bBox _ GGBoundBox.emptyBoundBox; RETURN; -- The sequence has only control points. }; run _ GGSequence.NextSequence[runGen]; IF run = NIL THEN ERROR; }; <> IF run.segCount>0 OR NOT segmentsOnly THEN { newRun _ runProc[run]; IF newRun # NIL THEN { SetSelectionBits[newRun, FALSE, active]; -- don't process run twice IF selectNewRuns THEN SetSelectionBits[newRun, TRUE, normal]; }; [newOutlines: newOutlines] _ ReplaceRun[run, newRun, scene]; bBox _ BoundBoxOfOutlines[newOutlines]; DeselectEntityAllClasses[oldOutline, scene]; FOR list: LIST OF Outline _ newOutlines, list.rest UNTIL list = NIL DO GGOutline.RemakeSelectionsFromOutline[list.first, scene]; ENDLOOP; } ELSE { DeselectSequence[seq, scene, active]; -- maintain the important invariant bBox _ GGBoundBox.emptyBoundBox; }; }; ReplaceRun: PROC [run: Sequence, newRun: Traj, scene: SceneRef] RETURNS [newOutlines: LIST OF Outline, newTraj: Traj _ NIL] = { <> IF newRun = NIL THEN [----, newOutlines] _ GGObjects.DeleteSequence[run, scene] ELSE { newTraj _ GGTraj.SpliceIn[run, newRun]; newOutlines _ LIST[newTraj.parent]; GGObjects.DeleteOutline[scene, GGOutline.OutlineOfTraj[run.traj]]; GGObjects.AddOutline[scene, newTraj.parent, -1]; }; }; SubstituteForSegment: PUBLIC PROC [traj: Traj, segNum: NAT, newRun: Traj, scene: SceneRef] RETURNS [bBox: BoundBox, newTraj: Traj] = { <> newOutlines: LIST OF Outline; replaceSeq: Sequence _ GGSequence.CreateFromSegment[traj, segNum]; GGOutline.SaveSelectionsInOutline[traj.parent, scene]; DeselectTraj[traj, scene, normal]; DeselectTraj[traj, scene, hot]; [newOutlines, newTraj] _ ReplaceRun[replaceSeq, newRun, scene]; FOR list: LIST OF Outline _ newOutlines, list.rest UNTIL list = NIL DO GGOutline.RemakeSelectionsFromOutline[list.first, scene]; ENDLOOP; bBox _ BoundBoxOfOutlines[newOutlines]; }; SetSelectionBits: PUBLIC PROC [traj: Traj, selected: BOOL, selectClass: SelectionClass] = { segGen: GGModelTypes.SegmentGenerator; jointGen: GGModelTypes.JointGenerator; joint: Joint; segGen _ GGSequence.SegmentsInTraj[traj]; FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO SetSegmentField[seg, selected, selectClass]; FOR i: NAT IN [0..seg.class.controlPointCount[seg]-1] DO seg.class.controlPointFieldSet[seg, i, selected, selectClass]; ENDLOOP; ENDLOOP; jointGen _ GGSequence.JointsInTraj[traj]; FOR jointNum: INT _ GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL jointNum = -1 DO joint _ GGTraj.FetchJoint[traj, jointNum]; SetJointField[joint, selected, selectClass]; ENDLOOP; }; BoundBoxOfOutlines: PROC [outlines: LIST OF Outline] RETURNS [bBox: BoundBox] = { bBox _ GGBoundBox.NullBoundBox[]; FOR list: LIST OF Outline _ outlines, list.rest UNTIL list = NIL DO GGBoundBox.EnlargeByBox[bBox: bBox, by: list.first.boundBox]; ENDLOOP; }; END. <<>> <<>> << >>