<> <> <> DIRECTORY GGAlign, GGCaret, GGError, GGGravity, GGInterfaceTypes, GGModelTypes, GGObjects, GGSelect, GGVector; GGAlignImpl: CEDAR PROGRAM IMPORTS GGCaret, GGGravity, GGObjects, GGSelect, GGVector EXPORTS GGAlign = BEGIN Angle: TYPE = GGModelTypes.Angle; Edge: TYPE = GGModelTypes.Edge; EntityGenerator: TYPE = GGObjects.EntityGenerator; FeatureData: TYPE = REF FeatureDataObj; FeatureDataObj: TYPE = GGGravity.FeatureDataObj; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; Joint: TYPE = GGModelTypes.Joint; JointGenerator: TYPE = GGObjects.JointGenerator; Line: TYPE = GGModelTypes.Line; ObjectBag: TYPE = GGGravity.ObjectBag; Outline: TYPE = GGModelTypes.Outline; Point: TYPE = GGModelTypes.Point; Scene: TYPE = GGModelTypes.Scene; ScalarButtonClient: TYPE = GGInterfaceTypes.ScalarButtonClient; SegAndIndex: TYPE = GGObjects.SegAndIndex; SegmentGenerator: TYPE = GGObjects.SegmentGenerator; SelectionClass: TYPE = GGInterfaceTypes.SelectionClass; Sequence: TYPE = GGModelTypes.Sequence; SymmetryGroup: TYPE = GGGravity.SymmetryGroup; Traj: TYPE = GGModelTypes.Traj; TrajGenerator: TYPE = GGObjects.TrajGenerator; Vector: TYPE = GGModelTypes.Vector; <> <> <> <<>> Triggers: TYPE = {joint, segment, symmetryGroup, coordFrame}; <> <> <> <> <<>> JointFireRule: PRIVATE PROC [point: Point, jointNum: NAT, traj: Traj, objectBag: ObjectBag, gargoyleData: GargoyleData] = { firstButton: ScalarButtonClient; <> firstButton _ gargoyleData.hitTest.slopeButtons; FOR thisButton: ScalarButtonClient _ firstButton, thisButton.next UNTIL thisButton = NIL DO IF thisButton.on THEN GGGravity.JointAddSlopeLine[ degrees: thisButton.value, direction: GGVector.VectorFromAngle[thisButton.value], point: point, jointNum: jointNum, traj: traj, objectBag: objectBag]; ENDLOOP; <> firstButton _ gargoyleData.hitTest.radiusButtons; FOR thisButton: ScalarButtonClient _ firstButton, thisButton.next UNTIL thisButton = NIL DO IF thisButton.on THEN GGGravity.JointAddCircle[ radius: thisButton.value, point: point, jointNum: jointNum, traj: traj, objectBag: objectBag]; ENDLOOP; <> }; SegmentFireRule: PRIVATE PROC [segNum: NAT, traj: Traj, objectBag: ObjectBag, gargoyleData: GargoyleData] = { firstButton: ScalarButtonClient; <> firstButton _ gargoyleData.hitTest.distanceButtons; FOR thisButton: ScalarButtonClient _ firstButton, thisButton.next UNTIL thisButton = NIL DO IF thisButton.on THEN GGGravity.SegmentAddDistanceLines[ distance: thisButton.value, segNum: segNum, traj: traj, objectBag: objectBag]; ENDLOOP; }; SymmetryFireRule: PRIVATE PROC [group: SymmetryGroup, entity: REF ANY, objectBag: ObjectBag, gargoyleData: GargoyleData] = { <> }; CoordinateFrameFireRule: PRIVATE PROC [objectBag: ObjectBag, gargoyleData: GargoyleData] = { <> }; <> <<>> TrajectoryFireRule: PRIVATE PROC [hotTraj: Traj, objectBag: ObjectBag, gargoyleData: GargoyleData] = { jointGen: JointGenerator; segGen: SegmentGenerator; point: Point; <> jointGen _ GGObjects.JointsInTraj[hotTraj]; FOR i: INT _ GGObjects.NextJoint[jointGen], GGObjects.NextJoint[jointGen] UNTIL i = -1 DO point _ GGObjects.FetchJointPos[hotTraj, i]; JointFireRule[point, i, hotTraj, objectBag, gargoyleData]; ENDLOOP; <> segGen _ GGObjects.SegmentsInTraj[hotTraj]; FOR next: SegAndIndex _ GGObjects.NextSegmentAndIndex[segGen], GGObjects.NextSegmentAndIndex[segGen] UNTIL next.seg = NIL DO SegmentFireRule[next.index, hotTraj, objectBag, gargoyleData]; ENDLOOP; }; SequenceFireRule: PRIVATE PROC [hotSeq: Sequence, objectBag: ObjectBag, gargoyleData: GargoyleData] = { jointGen: JointGenerator; segGen: SegmentGenerator; point: Point; <> jointGen _ GGObjects.JointsInSequence[hotSeq]; FOR i: INT _ GGObjects.NextJoint[jointGen], GGObjects.NextJoint[jointGen] UNTIL i = -1 DO point _ GGObjects.FetchJointPos[hotSeq.traj, i]; JointFireRule[point, i, hotSeq.traj, objectBag, gargoyleData]; ENDLOOP; <> segGen _ GGObjects.SegmentsInSequence[hotSeq]; FOR next: SegAndIndex _ GGObjects.NextSegmentAndIndex[segGen], GGObjects.NextSegmentAndIndex[segGen] UNTIL next.seg = NIL DO SegmentFireRule[next.index, hotSeq.traj, objectBag, gargoyleData]; ENDLOOP; }; <<>> <> FilterSequenceExceptClass: PRIVATE PROC [seq: Sequence, gargoyleData: GargoyleData, objectBag: ObjectBag, exceptClass: SelectionClass] = { jointGen: JointGenerator; segGen: SegmentGenerator; joint: Joint; <> jointGen _ GGObjects.JointsInSequence[seq]; FOR i: INT _ GGObjects.NextJoint[jointGen], GGObjects.NextJoint[jointGen] UNTIL i = -1 DO joint _ GGObjects.FetchJoint[seq.traj, i]; IF GGSelect.IsSelected[joint, gargoyleData, exceptClass] THEN LOOP; JointFireRule[joint.point, i, seq.traj, objectBag, gargoyleData]; ENDLOOP; <> segGen _ GGObjects.SegmentsInSequence[seq]; FOR next: SegAndIndex _ GGObjects.NextSegmentAndIndex[segGen], GGObjects.NextSegmentAndIndex[segGen] UNTIL next.seg = NIL DO IF GGSelect.IsSelected[next.seg, gargoyleData, exceptClass] THEN LOOP; joint _ GGObjects.FetchJoint[seq.traj, next.index]; IF GGSelect.IsSelected[joint, gargoyleData, exceptClass] THEN LOOP; joint _ GGObjects.FetchJoint[seq.traj, GGObjects.FollowingJoint[seq.traj, next.index]]; IF GGSelect.IsSelected[joint, gargoyleData, exceptClass] THEN LOOP; SegmentFireRule[next.index, seq.traj, objectBag, gargoyleData]; ENDLOOP; }; FilterSelectedTriggers: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag, selectClass: SelectionClass] = { <> selectGen: EntityGenerator; trajGen: TrajGenerator; <> selectGen _ GGSelect.SelectedEntities[gargoyleData, selectClass]; FOR entity: REF ANY _ GGObjects.NextEntity[selectGen], GGObjects.NextEntity[selectGen] UNTIL entity = NIL DO WITH entity SELECT FROM hotOutline: Outline => { trajGen _ GGObjects.TrajsInOutline[hotOutline]; FOR hotTraj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL hotTraj = NIL DO TrajectoryFireRule[hotTraj, objectBag, gargoyleData]; ENDLOOP; }; hotSeq: Sequence => SequenceFireRule[hotSeq, objectBag, gargoyleData]; ENDCASE => ERROR; ENDLOOP; <> }; FilterSelectedTriggersExcept: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag, selectClass: SelectionClass, exceptTraj: Traj] = { <> selectGen: EntityGenerator; trajGen: TrajGenerator; <> selectGen _ GGSelect.SelectedEntities[gargoyleData, selectClass]; FOR entity: REF ANY _ GGObjects.NextEntity[selectGen], GGObjects.NextEntity[selectGen] UNTIL entity = NIL DO WITH entity SELECT FROM hotOutline: Outline => { trajGen _ GGObjects.TrajsInOutline[hotOutline]; FOR hotTraj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL hotTraj = NIL DO IF hotTraj = exceptTraj THEN LOOP; TrajectoryFireRule[hotTraj, objectBag, gargoyleData]; ENDLOOP; }; hotSeq: Sequence => { IF hotSeq.traj = exceptTraj THEN LOOP; SequenceFireRule[hotSeq, objectBag, gargoyleData]; }; ENDCASE => ERROR; ENDLOOP; <> }; FilterSelectedTriggersExceptClass: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag, selectClass, except: SelectionClass] = { <> selectGen: EntityGenerator; trajGen: TrajGenerator; <> selectGen _ GGSelect.SelectedEntities[gargoyleData, selectClass]; FOR entity: REF ANY _ GGObjects.NextEntity[selectGen], GGObjects.NextEntity[selectGen] UNTIL entity = NIL DO WITH entity SELECT FROM selOutline: Outline => { IF GGSelect.IsSelected[selOutline, gargoyleData, except] THEN LOOP; trajGen _ GGObjects.TrajsInOutline[selOutline]; FOR selTraj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL selTraj = NIL DO TrajectoryFireRule[selTraj, objectBag, gargoyleData]; ENDLOOP; }; selSeq: Sequence => FilterSequenceExceptClass[selSeq, gargoyleData, objectBag, except]; ENDCASE => ERROR; ENDLOOP; <> }; FilterUnSelectedPiecesNotHot: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag, selectClass: SelectionClass] = { selectedGen: EntityGenerator; union, diff, seq, whole: Sequence; selectedGen _ GGSelect.SelectedEntities[gargoyleData, selectClass]; FOR selected: REF ANY _ GGObjects.NextEntity[selectedGen], GGObjects.NextEntity[selectedGen] UNTIL selected = NIL DO IF NOT ISTYPE[selected, Sequence] THEN LOOP; seq _ NARROW[selected]; IF GGSelect.IsSelectedInPart[seq, gargoyleData, hot] THEN LOOP; <> whole _ GGObjects.CreateCompleteSequence[seq.traj]; [union, diff] _ GGObjects.CombineSequences[whole, seq]; IF NOT GGObjects.IsEmptySequence[diff] THEN SequenceFireRule[diff, objectBag, gargoyleData]; ENDLOOP; }; <<>> <> SensitiveTrajectories: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag] = { trajGen: TrajGenerator; trajGen _ GGObjects.TrajsInScene[gargoyleData.scene]; FOR traj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL traj = NIL DO GGGravity.AddTrajectory[traj, objectBag]; ENDLOOP; }; SensitiveSelectedTrajectories: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag, selectClass: SelectionClass] = { trajGen: TrajGenerator; trajGen _ GGObjects.TrajsInScene[gargoyleData.scene]; FOR traj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL traj = NIL DO IF GGSelect.IsSelectedInPart[traj, gargoyleData, selectClass] THEN GGGravity.AddTrajectory[traj, objectBag]; ENDLOOP; }; SensitiveTrajectoriesExcept: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag, exceptTraj: Traj] = { <> trajGen: TrajGenerator; trajGen _ GGObjects.TrajsInScene[gargoyleData.scene]; FOR traj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL traj = NIL DO IF traj = exceptTraj THEN LOOP; GGGravity.AddTrajectory[traj, objectBag]; ENDLOOP; }; SensitiveTrajectoriesNotSelected: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag] = { <> trajGen: TrajGenerator; trajGen _ GGObjects.TrajsInScene[gargoyleData.scene]; FOR traj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL traj = NIL DO IF GGSelect.IsSelectedInPart[traj, gargoyleData, normal] THEN LOOP; GGGravity.AddTrajectory[traj, objectBag]; ENDLOOP; }; SensitiveUnSelectedPieces: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag, selectClass: SelectionClass] = { selectedGen: EntityGenerator; diff, seq, whole: Sequence; selectedGen _ GGSelect.SelectedEntities[gargoyleData, selectClass]; FOR selected: REF ANY _ GGObjects.NextEntity[selectedGen], GGObjects.NextEntity[selectedGen] UNTIL selected = NIL DO IF NOT ISTYPE[selected, Sequence] THEN LOOP; seq _ NARROW[selected]; IF GGSelect.IsSelectedInPart[seq, gargoyleData, hot] THEN LOOP; <> whole _ GGObjects.CreateCompleteSequence[seq.traj]; [----, diff] _ GGObjects.CombineSequences[whole, seq]; IF NOT GGObjects.IsEmptySequence[diff] THEN GGGravity.AddSequence[diff, objectBag]; ENDLOOP; }; <> <<>> SelectPointMode: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag] = { <> <<1) All hot vertices, segments, symmetry groups.>> <> <<1) All.>> <> FilterSelectedTriggers[gargoyleData, objectBag, hot]; <> SensitiveTrajectories[gargoyleData, objectBag]; }; AddMode: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag] = { <> <<1) All hot vertices, segments, symmetry groups, except the caret trajectory.>> <<2) All parts of the caret trajectory, except the segment being added.>> <> <<1) All trajectories except the caret trajectory.>> <<2) All parts of the caret trajectory, except the segment being added.>> caretTraj: Traj; caretSeq: Sequence; jointNum: NAT; <> [caretTraj, ----, ----, jointNum, ----] _ GGCaret.GetChair[gargoyleData.caret]; FilterSelectedTriggersExcept[gargoyleData, objectBag, hot, caretTraj]; IF caretTraj # NIL THEN { IF jointNum = 0 THEN caretSeq _ GGObjects.CreateSimpleSequence[caretTraj, 1, GGObjects.HiJoint[caretTraj]] ELSE IF jointNum = GGObjects.HiJoint[caretTraj] THEN caretSeq _ GGObjects.CreateSimpleSequence[caretTraj, 0, GGObjects.HiJoint[caretTraj] - 1] ELSE ERROR; SequenceFireRule[caretSeq, objectBag, gargoyleData]; }; <> SensitiveTrajectoriesExcept[gargoyleData, objectBag, caretTraj]; IF caretTraj # NIL THEN GGGravity.AddSequence[caretSeq, objectBag]; }; DragMode: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag] = { <> <<1) All hot vertices, segments, symmetry groups (except those being dragged).>> <<2) All unselected pieces of selected trajectories.>> <> <<1) All unselected trajectories.>> <<2) All unselected pieces of selected trajectories.>> <> FilterSelectedTriggersExceptClass[gargoyleData, objectBag, hot, normal]; <> FilterUnSelectedPiecesNotHot[gargoyleData, objectBag, normal]; <> <> SensitiveTrajectoriesNotSelected[gargoyleData, objectBag]; SensitiveUnSelectedPieces[gargoyleData, objectBag, normal]; }; DragStartUpMode: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag] = { <> <<1) All selected vertices, segments, and symmetry groups.>> <<2) All hot vertices, segments, symmetry groups.>> <> <<1) All selected vertices, segments.>> <<2) All hot vertices, segments. >> <> <> FilterSelectedTriggers[gargoyleData, objectBag, normal]; <> FilterSelectedTriggers[gargoyleData, objectBag, hot]; <> <> SensitiveSelectedTrajectories[gargoyleData, objectBag, normal]; SensitiveSelectedTrajectories[gargoyleData, objectBag, hot]; }; SelectTrajectoryMode: PRIVATE PROC [gargoyleData: GargoyleData, objectBag: ObjectBag] = { <> <> <<1) All vertices and segments.>> SensitiveTrajectories[gargoyleData, objectBag]; }; <> <<>> AddItemsForAction: PUBLIC PROC [gargoyleData: GargoyleData, objectBag: ObjectBag, action: ATOM] = { SELECT action FROM $SelectPoint => SelectPointMode[gargoyleData, objectBag]; $Add => AddMode[gargoyleData, objectBag]; $Drag => DragMode[gargoyleData, objectBag]; $DragStartUp => DragStartUpMode[gargoyleData, objectBag]; $SelectTrajectory => SelectTrajectoryMode[gargoyleData, objectBag]; ENDCASE => ERROR; }; <<>> END.