DIRECTORY GGBasicTypes, GGDescribe, GGError, GGInterfaceTypes, GGModelTypes, GGObjects, GGOutline, GGSegmentTypes, GGSelect, GGShapes, GGSequence, GGTouch, GGTransform, Imager, ImagerTransformation, Rope, Rosary; GGTouchImpl: CEDAR PROGRAM IMPORTS GGDescribe, GGError, GGObjects, GGOutline, GGSelect, GGSequence, GGShapes, GGTransform, Rosary EXPORTS GGTouch = BEGIN Slice: TYPE = GGModelTypes.Slice; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; Joint: TYPE = GGModelTypes.Joint; JointGenerator: TYPE = GGSequence.JointGenerator; Outline: TYPE = GGModelTypes.Outline; Point: TYPE = GGBasicTypes.Point; Segment: TYPE = GGSegmentTypes.Segment; Sequence: TYPE = GGModelTypes.Sequence; Traj: TYPE = GGModelTypes.Traj; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; TrajGenerator: TYPE = GGObjects.TrajGenerator; TouchGroup: TYPE = REF TouchGroupObj; TouchGroupObj: TYPE = GGSegmentTypes.TouchGroupObj; TouchingPartType: TYPE = GGSegmentTypes.TouchingPartType; TouchItem: TYPE = REF TouchItemObj; TouchItemObj: TYPE = GGSegmentTypes.TouchItemObj; TouchItemGenerator: TYPE = REF TouchItemGeneratorObj; TouchItemGeneratorObj: TYPE = GGTouch.TouchItemGeneratorObj; NotYetImplemented: PUBLIC SIGNAL = CODE; CreateTouchGroup: PUBLIC PROC [gargoyleData: GargoyleData, point: Point] RETURNS [empty: TouchGroup] = { empty _ NEW[TouchGroupObj _ [ list: NIL, point: point ]]; gargoyleData.touching _ CONS[empty, gargoyleData.touching]; }; AddJoint: PUBLIC PROC [traj: Traj, joint: Joint, touchGroup: TouchGroup] RETURNS [item: TouchItem] = { item _ NEW[TouchItemObj _ [ group: touchGroup, traj: traj, touchingPartType: joint, joint: joint, seg: NIL, segPoint: [0.0,0.0] ]]; touchGroup.list _ CONS[item, touchGroup.list]; }; AddSegment: PUBLIC PROC [traj: Traj, seg: Segment, segPoint: Point, touchGroup: TouchGroup] RETURNS [item: TouchItem] = { item _ NEW[TouchItemObj _ [ group: touchGroup, traj: traj, touchingPartType: segment, joint: NIL, seg: seg, segPoint: segPoint ]]; touchGroup.list _ CONS[item, touchGroup.list]; }; MergeGroups: PUBLIC PROC [group1, group2: TouchGroup, gargoyleData: GargoyleData] = { touchItemGen: TouchItemGenerator; IF group1 = group2 THEN RETURN; touchItemGen _ AllTouchItems[group1]; FOR item1: TouchItem _ NextTouchItem[touchItemGen], NextTouchItem[touchItemGen] UNTIL item1 = NIL DO item1.group _ group2; group2.list _ CONS[item1, group2.list]; ENDLOOP; group1.list _ NIL; gargoyleData.touching _ DeleteTouchGroupFromList[group1, gargoyleData.touching]; }; InitializeTouching: PUBLIC PROC [gargoyleData: GargoyleData] = { FOR groupList: LIST OF TouchGroup _ gargoyleData.touching, groupList.rest UNTIL groupList = NIL DO groupList.first.updated _ FALSE; ENDLOOP; }; UpdateTouchGroup: PUBLIC PROC [item: TouchItem, point: Point, gargoyleData: GargoyleData] = { group: TouchGroup _ item.group; itemGen: TouchItemGenerator; IF group.updated THEN { RETURN; }; group.updated _ TRUE; group.point _ point; itemGen _ AllTouchItems[group]; FOR thisItem: TouchItem _ NextTouchItem[itemGen], NextTouchItem[itemGen] UNTIL thisItem = NIL DO SELECT thisItem.touchingPartType FROM joint => { IF NOT GGSelect.IsSelectedInFull[thisItem.joint, gargoyleData.scene, normal] THEN { thisItem.joint.touchItem _ NIL; group.list _ DeleteTouchItemFromList[thisItem, group.list]; }; }; segment => { IF NOT GGSelect.IsSelectedInFull[thisItem.seg, gargoyleData.scene, normal] THEN { thisItem.seg.touchItemList _ DeleteTouchItemFromList[thisItem, thisItem.seg.touchItemList]; group.list _ DeleteTouchItemFromList[thisItem, group.list]; }; }; ENDCASE => ERROR; ENDLOOP; IF group.list = NIL THEN ERROR; IF group.list.rest = NIL THEN { -- only one item left. Delete group. thisItem: TouchItem _ group.list.first; SELECT thisItem.touchingPartType FROM joint => { thisItem.joint.touchItem _ NIL; group.list _ DeleteTouchItemFromList[thisItem, group.list]; }; segment => { thisItem.seg.touchItemList _ DeleteTouchItemFromList[thisItem, thisItem.seg.touchItemList]; group.list _ DeleteTouchItemFromList[thisItem, group.list]; }; ENDCASE => ERROR; gargoyleData.touching _ DeleteTouchGroupFromList[group, gargoyleData.touching]; }; }; SequenceMoved: PUBLIC PROC [seq: Sequence, gargoyleData: GargoyleData, transform: ImagerTransformation.Transformation _ NIL] = { jointGen: JointGenerator; joint: Joint; segGen: SegmentGenerator; jointGen _ GGSequence.JointsInSequence[seq]; FOR i: INT _ GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL i = -1 DO joint _ NARROW[Rosary.Fetch[seq.traj.joints, i]]; IF joint.touchItem # NIL THEN { UpdateTouchGroup[joint.touchItem, joint.point, gargoyleData]; }; ENDLOOP; segGen _ GGSequence.SegmentsInSequence[seq]; FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO FOR itemList: LIST OF TouchItem _ seg.touchItemList, itemList.rest UNTIL itemList = NIL DO itemList.first.segPoint _ GGTransform.Transform[transform, itemList.first.segPoint]; UpdateTouchGroup[itemList.first, itemList.first.segPoint, gargoyleData]; ENDLOOP; ENDLOOP; }; TrajMoved: PUBLIC PROC [traj: Traj, gargoyleData: GargoyleData, transform: ImagerTransformation.Transformation _ NIL] = { jointGen: JointGenerator; joint: Joint; segGen: SegmentGenerator; jointGen _ GGSequence.JointsInTraj[traj]; FOR i: INT _ GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL i = -1 DO joint _ NARROW[Rosary.Fetch[traj.joints, i]]; IF joint.touchItem # NIL THEN { UpdateTouchGroup[joint.touchItem, joint.point, gargoyleData]; }; ENDLOOP; segGen _ GGSequence.SegmentsInTraj[traj]; FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO FOR itemList: LIST OF TouchItem _ seg.touchItemList, itemList.rest UNTIL itemList = NIL DO itemList.first.segPoint _ GGTransform.Transform[transform, itemList.first.segPoint]; UpdateTouchGroup[itemList.first, itemList.first.segPoint, gargoyleData]; ENDLOOP; ENDLOOP; }; DeleteTouchItem: PUBLIC PROC [touchItem: TouchItem, gargoyleData: GargoyleData] = { lastItem: TouchItem; group: TouchGroup _ touchItem.group; touchItem.joint _ NIL; touchItem.seg _ NIL; group.list _ DeleteTouchItemFromList[touchItem, group.list]; IF group.list.rest = NIL THEN { lastItem _ group.list.first; IF lastItem.touchingPartType = joint THEN { lastItem.joint.touchItem _ NIL; lastItem.joint _ NIL; } ELSE { lastItem.seg.touchItemList _ DeleteTouchItemFromList[lastItem, lastItem.seg.touchItemList]; lastItem.seg _ NIL; }; group.list _ NIL; gargoyleData.touching _ DeleteTouchGroupFromList[group, gargoyleData.touching]; }; }; SequenceDeleted: PUBLIC PROC [seq: Sequence, gargoyleData: GargoyleData] = { jointGen: JointGenerator; joint: Joint; segGen: SegmentGenerator; jointGen _ GGSequence.JointsInSequence[seq]; FOR i: INT _ GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL i = -1 DO joint _ NARROW[Rosary.Fetch[seq.traj.joints, i]]; IF joint.touchItem # NIL THEN { DeleteTouchItem[joint.touchItem, gargoyleData]; joint.touchItem _ NIL; }; ENDLOOP; segGen _ GGSequence.SegmentsInSequence[seq]; FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO FOR itemList: LIST OF TouchItem _ seg.touchItemList, itemList.rest UNTIL itemList = NIL DO DeleteTouchItem[itemList.first, gargoyleData]; ENDLOOP; seg.touchItemList _ NIL; ENDLOOP; }; TrajDeleted: PUBLIC PROC [traj: Traj, gargoyleData: GargoyleData] = { jointGen: JointGenerator; joint: Joint; segGen: SegmentGenerator; jointGen _ GGSequence.JointsInTraj[traj]; FOR i: INT _ GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL i = -1 DO joint _ NARROW[Rosary.Fetch[traj.joints, i]]; IF joint.touchItem # NIL THEN { DeleteTouchItem[joint.touchItem, gargoyleData]; joint.touchItem _ NIL; }; ENDLOOP; segGen _ GGSequence.SegmentsInTraj[traj]; FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg = NIL DO FOR itemList: LIST OF TouchItem _ seg.touchItemList, itemList.rest UNTIL itemList = NIL DO DeleteTouchItem[itemList.first, gargoyleData]; ENDLOOP; seg.touchItemList _ NIL; ENDLOOP; }; OutlineDeleted: PUBLIC PROC [outline: Outline, gargoyleData: GargoyleData] = { trajGen: TrajGenerator; trajGen _ GGOutline.TrajsInOutline[outline]; FOR traj: Traj _ GGObjects.NextTraj[trajGen], GGObjects.NextTraj[trajGen] UNTIL traj = NIL DO TrajDeleted[traj, gargoyleData]; ENDLOOP; }; SliceDeleted: PUBLIC PROC [slice: Slice, gargoyleData: GargoyleData] = { ERROR NotYetImplemented; }; TouchGroupOfItem: PUBLIC PROC [item: TouchItem] RETURNS [touchGroup: TouchGroup] = { touchGroup _ item.group; }; AllTouchItems: PUBLIC PROC [touchGroup: TouchGroup] RETURNS [touchItemGen: TouchItemGenerator] = { touchItemGen _ NEW[TouchItemGeneratorObj _ [ list: touchGroup.list ]]; }; NextTouchItem: PUBLIC PROC [touchItemGen: TouchItemGenerator] RETURNS [item: TouchItem] = { IF touchItemGen.list = NIL THEN RETURN[NIL]; item _ touchItemGen.list.first; touchItemGen.list _ touchItemGen.list.rest; }; DrawAllTouchPoints: PUBLIC PROC [dc: Imager.Context, gargoyleData: GargoyleData] = { FOR groupList: LIST OF TouchGroup _ gargoyleData.touching, groupList.rest UNTIL groupList = NIL DO GGShapes.DrawPlus[dc, groupList.first.point]; ENDLOOP; }; DescribeAllTouchPoints: PUBLIC PROC [gargoyleData: GargoyleData] = { text: Rope.ROPE; FOR groupList: LIST OF TouchGroup _ gargoyleData.touching, groupList.rest UNTIL groupList = NIL DO text _ GGDescribe.DescribeTouchGroup[groupList.first]; GGError.AppendTypescript[gargoyleData.feedback, text, oneLiner]; ENDLOOP; }; FindTouchItemAndNeighbors: PROC [entity: TouchItem, entityList: LIST OF TouchItem] RETURNS [beforeEnt, ent, afterEnt: LIST OF TouchItem] = { lastE: LIST OF TouchItem _ NIL; eList: LIST OF TouchItem _ entityList; IF eList = NIL THEN ERROR EntityNotFound; UNTIL eList = NIL DO IF eList.first = entity THEN { beforeEnt _ lastE; ent _ eList; afterEnt _ eList.rest; RETURN}; lastE _ eList; eList _ eList.rest; ENDLOOP; SIGNAL EntityNotFound; }; DeleteTouchItemFromList: PUBLIC PROC [entity: TouchItem, entityList: LIST OF TouchItem] RETURNS [smallerList: LIST OF TouchItem] = { beforeEnt, ent, afterEnt: LIST OF TouchItem; notFound: BOOL _ FALSE; [beforeEnt, ent, afterEnt] _ FindTouchItemAndNeighbors[entity, entityList]; IF notFound THEN RETURN[entityList]; IF beforeEnt = NIL THEN smallerList _ afterEnt ELSE { beforeEnt.rest _ afterEnt; smallerList _ entityList; }; }; -- end of DeleteTouchItemFromList FindTouchGroupAndNeighbors: PROC [entity: TouchGroup, entityList: LIST OF TouchGroup] RETURNS [beforeEnt, ent, afterEnt: LIST OF TouchGroup] = { lastE: LIST OF TouchGroup _ NIL; eList: LIST OF TouchGroup _ entityList; IF eList = NIL THEN ERROR EntityNotFound; UNTIL eList = NIL DO IF eList.first = entity THEN { beforeEnt _ lastE; ent _ eList; afterEnt _ eList.rest; RETURN}; lastE _ eList; eList _ eList.rest; ENDLOOP; SIGNAL EntityNotFound; }; EntityNotFound: PUBLIC SIGNAL = CODE; DeleteTouchGroupFromList: PUBLIC PROC [entity: TouchGroup, entityList: LIST OF TouchGroup] RETURNS [smallerList: LIST OF TouchGroup] = { beforeEnt, ent, afterEnt: LIST OF TouchGroup; notFound: BOOL _ FALSE; [beforeEnt, ent, afterEnt] _ FindTouchGroupAndNeighbors[entity, entityList]; IF notFound THEN RETURN[entityList]; IF beforeEnt = NIL THEN smallerList _ afterEnt ELSE { beforeEnt.rest _ afterEnt; smallerList _ entityList; }; }; -- end of DeleteTouchGroupFromList END. TGGTouchImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by Bier on December 28, 1986 3:08:57 pm PST Contents: Implements a data structures which remembers which trajectory is touching which other trajectory and where. Pier, October 20, 1986 5:16:08 pm PDT Updating when something has moved -- the basic routines. The group has been updated, already. Ignore this update. FOR itemList: LIST OF TouchItem _ group.list, itemList.rest UNTIL itemList = NIL DO IF itemList.first = item THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; Updating when something has moved -- convenience routines (which repeatedly call the basic routines for many joints and segments). Updating when something has been deleted -- the basic routine. Remove the touch item from the group's list. If the group has only one remaining object, remove the group from the global list. Updating when something has been deleted -- convenience routines (which repeatedly call the basic routines for many joints and segments). Browsing. Drawing. List Processing Utilities (will polymorphism never come?) Κ T˜code™Kšœ<™šžœœœ7˜SK™€Kšœ˜Kšœ$˜$Kšœœ˜Kšœœ˜Kšœ<˜<šœœœ˜Kšœ˜šœ#œ˜+Kšœœ˜Kšœœ˜K˜—šœ˜Kšœ[˜[Kšœœ˜K˜—Kšœ œ˜KšœO˜OK˜—K˜—K˜Kšœ)‘`™‰šžœœœ0˜LKšœ˜K˜ K˜Kšœ,˜,šœœBœ˜[Kšœœ#˜1šœœœ˜Kšœ/˜/Kšœœ˜K˜——Kšœ˜Kšœ,˜,šœOœœ˜dš œ œœ.œ œ˜ZKšœ.˜.—Kšœ˜Kšœœ˜—Kšœ˜Kšœ˜—šž œœœ-˜EKšœ˜K˜ K˜Kšœ)˜)šœœBœ˜[Kšœœ˜-šœœœ˜Kšœ/˜/Kšœœ˜K˜——Kšœ˜Kšœ)˜)šœOœœ˜dš œ œœ.œ œ˜ZKšœ.˜.—Kšœ˜Kšœœ˜—Kšœ˜Kšœ˜—šžœœœ3˜NK˜Kšœ,˜,šœGœœ˜]Kšœ ˜ —Kšœ˜K˜K˜—šž œœœ/˜HKšœ˜K˜K˜—K™ šžœœœœ˜TKšœ˜K˜—šž œœœœ'˜bšœœ˜,Kšœ˜K˜—K˜K˜—šž œœœ$œ˜[Kš œœœœœ˜,Kšœ˜Kšœ+˜+K˜K˜—K˜K˜K™šžœœœ5˜Tš œ œœ4œ œ˜bKšœ-˜-—Kšœ˜K˜K˜—šžœœœ!˜DKšœ œ˜š œ œœ4œ œ˜bKšœ6˜6Kšœ@˜@—Kšœ˜K˜K˜—K™K™9K˜šžœœ!œœ œœœ˜ŒKšœœœ œ˜Kšœœœ˜&Kšœ œœœ˜)šœ œ˜Kšœœ˜Kšœ7œ˜?Kšœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜K˜—šžœœœ!œœ œœœ˜„Kšœœœ ˜,Kšœ œœ˜KšœK˜KKšœ œœ ˜$Kšœ œœ˜.šœ˜Kšœ˜Kšœ˜K˜—Kšœ‘!˜$K˜—šžœœ"œœ œœœ˜Kšœœœœ˜ Kšœœœ˜'Kšœ œœœ˜)šœ œ˜Kšœœ˜Kšœ7œ˜?Kšœ˜Kšœ˜—Kšœ˜Kšœ˜Kšœ˜—šœœœœ˜%K˜—šžœœœ"œœ œœœ˜ˆKšœœœ ˜-Kšœ œœ˜KšœL˜LKšœ œœ ˜$Kšœ œœ˜.šœ˜Kšœ˜Kšœ˜K˜—Kšœ‘"˜%—K˜Kšœ˜K˜K˜K˜—…—,¨>P