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. ��T��GGTouchImpl.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šœ<™<K™7K™vK™%—K™�šÏk ˜ KšœÊ˜ÊK˜�—šœ œ˜Kšœ_˜fKšœ ˜—Kš˜K˜�Kšœœ˜!Kšœœ!˜3Kšœœ˜!Kšœœ˜1Kšœ œ˜%Kšœœ˜!Kšœ œ˜'Kšœ œ˜'Kšœœ˜Kšœœ!˜7Kšœœ˜.K˜�Kšœœœ˜%Kšœœ ˜3Kšœœ#˜9Kšœœœ˜#Kšœœ˜1K˜�Kšœœœ˜5šœœ!˜<K˜�—˜�K˜�—Kšœœœœ˜(K˜�šÏnœœœ,œ˜hšœœ˜Kšœœ˜ Kšœ˜K˜—Kšœœ˜;K˜K˜�—šžœœœ4œ˜fšœœ˜Kšœ˜Kšœ˜K˜Kšœ ˜ Kšœœ˜ K˜K˜—Kšœœ˜.˜K˜�——šž œœœEœ˜yšœœ˜Kšœ˜Kšœ˜K˜Kšœœ˜Kšœ ˜ Kšœ˜K˜—Kšœœ˜.˜K˜�——šžœœœ=˜UKšœ!˜!Kšœœœ˜Kšœ%˜%šœMœ œ˜dKšœ˜Kšœœ˜'—Kšœ˜Kšœœ˜KšœP˜PK˜K˜�—K™�K™8šžœœœ!˜@šœœœ4œ œ˜bKšœœ˜ —Kšœ˜K˜K˜�—šžœœœ@˜]K˜Kšœ˜šœœ˜K™9šœœœ'œœ™SKšœœœœ™+—Kšœ™Kšœœ™Kšœ˜K˜—Kšœœ˜Kšœ˜Kšœ˜šœFœœ˜`Kšœ˜%˜ šœœGœ˜SKšÏbÐbkœ˜Kšœ;˜;K˜—K˜—˜šœœEœ˜QKšŸZœ˜[Kšœ;˜;K˜—K˜—Kšœœ˜—Kšœ˜Kšœœœœ˜šœœœÏc%˜EKšœ'˜'Kšœ˜%˜ KšŸ œ˜Kšœ;˜;K˜—˜KšŸZœ˜[Kšœ;˜;K˜—Kšœœ˜KšœO˜OK˜—K˜—K™�K™‚šÐbn œœœ^œ˜€Kšœ˜K˜ K˜Kšœ,˜,šœœBœ˜[Kšœœ#˜1šœœœ˜Kšœ=˜=K˜——Kšœ˜Kšœ,˜,šœOœœ˜dšœœœ.œœ˜ZKšœT˜TKšœH˜H—Kšœ˜—Kšœ˜K˜K˜�—š¢ œœœ[œ˜yKšœ˜K˜ K˜Kšœ)˜)šœœBœ˜[Kšœœ˜-šœœœ˜Kšœ=˜=K˜——Kšœ˜Kšœ)˜)šœOœœ˜dšœœœ.œœ˜ZKšœT˜TKšœH˜H—Kšœ˜—Kšœ˜K˜—K™�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��