DIRECTORY --CombinePoly,-- Ascii, Atom, AtomButtonsTypes, BasicTime, CodeTimer, ColorTool, CubicSplines, Feedback, FileNames, FS, GGBasicTypes, GGBoundBox, GGCaret, GGEvent, GGFileIn, GGFileOut, GGGravity, GGInterfaceTypes, GGModelTypes, GGMultiGravity, GGOutline, GGScene, GGSegmentTypes, GGSelect, GGSequence, GGSlice, GGUtility, GGWindow, Icons, Imager, ImagerColor, ImagerColorFns, ImagerColorPrivate, IO, List, NamedColors, PrincOpsUtils, Random, Rope, Rosary, Vectors2d, ViewerClasses, ViewerOps, ViewerTools; GGEventImplD: CEDAR PROGRAM IMPORTS ColorTool, --CombinePoly,-- PrincOpsUtils, Ascii, Atom, BasicTime, CodeTimer, Feedback, FileNames, FS, GGCaret, GGEvent, GGFileIn, GGFileOut, GGGravity, GGMultiGravity, GGOutline, GGScene, GGSelect, GGSequence, GGSlice, GGUtility, GGWindow, Icons, Imager, ImagerColor, ImagerColorFns, ImagerColorPrivate, IO, List, NamedColors, Random, Rope, Vectors2d, ViewerOps, ViewerTools EXPORTS GGEvent = BEGIN BoundBox: TYPE = GGBoundBox.BoundBox; WalkProc: TYPE = GGModelTypes.WalkProc; EntityGenerator: TYPE = GGModelTypes.EntityGenerator; FeatureData: TYPE = GGInterfaceTypes.FeatureData; FeedbackData: TYPE = AtomButtonsTypes.FeedbackData; GGData: TYPE = GGInterfaceTypes.GGData; Joint: TYPE = GGModelTypes.Joint; JointGenerator: TYPE = GGModelTypes.JointGenerator; AlignBag: TYPE = GGGravity.AlignBag; Outline: TYPE = GGModelTypes.Outline; OutlineDescriptor: TYPE = GGModelTypes.OutlineDescriptor; Point: TYPE = GGBasicTypes.Point; Scene: TYPE = GGModelTypes.Scene; SegAndIndex: TYPE = GGSequence.SegAndIndex; Segment: TYPE = GGSegmentTypes.Segment; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; Sequence: TYPE = GGModelTypes.Sequence; SequenceGenerator: TYPE = GGModelTypes.SequenceGenerator; Slice: TYPE = GGModelTypes.Slice; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = GGModelTypes.SliceDescriptorGenerator; SliceGenerator: TYPE = GGModelTypes.SliceGenerator; SliceParts: TYPE = GGModelTypes.SliceParts; Traj: TYPE = GGModelTypes.Traj; TrajGenerator: TYPE = GGModelTypes.TrajGenerator; TriggerBag: TYPE = GGGravity.TriggerBag; Vector: TYPE = GGBasicTypes.Vector; Viewer: TYPE = ViewerClasses.Viewer; PaintActionArea: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; ViewerOps.PaintViewer[ viewer: ggData.actionArea, hint: client, whatChanged: ggData, clearClient: FALSE]; }; NotNewVersion: PROC [ggData: GGData, op: ATOM] = { ggData.outer.newVersion _ FALSE; ggData.outer.icon _ SELECT op FROM $clear => noNameIcon, $clean => cleanIcon, ENDCASE => ERROR; ViewerOps.PaintViewer[ggData.outer, caption]; }; GetGargoyleFileName: PROC [event: LIST OF REF ANY, currentWDir: Rope.ROPE, feedback: FeedbackData, emergency: BOOL _ FALSE] RETURNS [fullName: Rope.ROPE _ NIL, success: BOOL _ TRUE, versionSpecified: BOOL _ FALSE] = { RopeFromRef: PROC [ref: REF ANY] RETURNS [rope: Rope.ROPE] ~ { WITH ref SELECT FROM text: REF TEXT => RETURN[Rope.FromRefText[text] ]; r: Rope.ROPE => RETURN[r]; ENDCASE => ERROR; }; fileName: Rope.ROPE; fileName _ IF event#NIL AND event.first#NIL THEN RopeFromRef[event.first] ELSE ViewerTools.GetSelectionContents[]; [fullName, success, versionSpecified] _ GGUtility.GetGargoyleFileName[fileName, currentWDir, feedback, emergency]; }; Get: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; fullName: Rope.ROPE; success, versionSpecified: BOOL _ FALSE; [fullName, success, versionSpecified] _ GetGargoyleFileName[event.rest, ggData.currentWDir, ggData.feedback]; IF NOT success THEN { Feedback.Append[ggData.feedback, "Could not find requested file", oneLiner]; GOTO Abort; }; ClearAux[event, ggData]; GetMergeAux[fullName, versionSpecified, $Get, "Getting", ggData]; NotNewVersion[ggData, $clean]; EXITS Abort => Feedback.Blink[NARROW[clientData, GGData].feedback]; }; Merge: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; fullName: Rope.ROPE; success, versionSpecified: BOOL _ FALSE; [fullName, success, versionSpecified] _ GetGargoyleFileName[event.rest, ggData.currentWDir, ggData.feedback]; IF NOT success THEN { Feedback.Append[ggData.feedback, "Could not find requested file", oneLiner]; GOTO Abort; }; GetMergeAux[fullName, versionSpecified, $Merge, "Merging", ggData]; EXITS Abort => Feedback.Blink[NARROW[clientData, GGData].feedback]; }; GetMergeAux: PROC [fullName: Rope.ROPE, versionSpecified: BOOL _ FALSE, event: ATOM, opName: Rope.ROPE, ggData: GGData] = { f: IO.STREAM; fsName: Rope.ROPE; startTime: BasicTime.GMT; endTime: BasicTime.GMT; totalTime: INT; msgRope: Rope.ROPE; f _ FS.StreamOpen[fullName, $read ! FS.Error, IO.Error => { msgRope _ IO.PutFR["Could not find: %g", [rope[fullName]]]; Feedback.Append[ggData.feedback, msgRope, oneLiner]; GOTO Abort; };]; msgRope _ IO.PutFR["%g %g . . . ", [rope[opName]], [rope[fullName]]]; Feedback.Append[ggData.feedback, msgRope, begin]; startTime _ BasicTime.Now[]; GGFileIn.FileinSceneAndOptions[f, ggData]; f.Close[]; endTime _ BasicTime.Now[]; totalTime _ BasicTime.Period[startTime, endTime]; msgRope _ IO.PutFR[" Done in time (%r)", [integer[totalTime]]]; Feedback.Append[ggData.feedback, msgRope, end]; IF event=$Get OR ggData.outer.file=NIL THEN { -- update viewer name on Get or on first Merge if no Get preceeded it. fsName _ FS.FileInfo[name: fullName, wDir: ggData.currentWDir].fullFName; ggData.outer.file _ FileNames.StripVersionNumber[fsName]; ggData.outer.label _ FileNames.GetShortName[path: fsName, stripOffVersionNumber: TRUE]; ggData.outer.name _ IF versionSpecified THEN Rope.Concat["Gargoyle: ", fsName] ELSE Rope.Cat["Gargoyle: ", ggData.outer.file, " (!", FileNames.Tail[fsName, '!], ")"]; }; GGEvent.SawTextFinish[ggData, LIST[$SawTextFinish]]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, ggData: ggData, remake: triggerBag, backgndOK: FALSE, edited: event=$Merge, okToClearFeedback: FALSE]; EXITS Abort => Feedback.Blink[ggData.feedback]; }; -- end GetMergeAux Store: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; tKeep: CARDINAL _ 0; f: IO.STREAM; fullName, fsName: Rope.ROPE; success, versionSpecified: BOOL _ FALSE; startTime: BasicTime.GMT; endTime: BasicTime.GMT; totalTime: INT; msgRope, opName: Rope.ROPE; ofile: FS.OpenFile; emergency: BOOL _ event.first=$Emergency; [fullName, success, versionSpecified] _ GetGargoyleFileName[event.rest, ggData.currentWDir, ggData.feedback, emergency]; IF NOT success THEN RETURN; tKeep _ FS.FileInfo[name: fullName ! FS.Error => CONTINUE].keep; ofile _ FS.Create[name: fullName, setPages: FALSE, setKeep: TRUE, keep: MAX[tKeep, 2] ! FS.Error => { msgRope _ IO.PutFR["Could not create: %g", [rope[fullName]]]; IF NOT emergency THEN Feedback.Append[ggData.feedback, msgRope, oneLiner]; GOTO Abort; };]; f _ FS.StreamFromOpenFile[openFile: ofile, accessRights: $write]; opName _ IF event.first = NIL THEN "someSave" ELSE Atom.GetPName[NARROW[event.first]]; msgRope _ IO.PutFR["%g: %g . . . ", [rope[opName]], [rope[fullName]]]; IF NOT emergency THEN Feedback.Append[ggData.feedback, msgRope, begin]; startTime _ BasicTime.Now[]; GGFileOut.FileoutSceneAndOptions[f, ggData, fullName]; f.Close[]; endTime _ BasicTime.Now[]; totalTime _ BasicTime.Period[startTime, endTime]; msgRope _ IO.PutFR[" Done in time (%r)", [integer[totalTime]]]; IF NOT emergency THEN Feedback.Append[ggData.feedback, msgRope, end]; fsName _ FS.FileInfo[name: fullName, wDir: ggData.currentWDir].fullFName; --latest version ggData.outer.file _ FileNames.StripVersionNumber[fsName]; ggData.outer.label _ FileNames.GetShortName[path: fsName, stripOffVersionNumber: TRUE]; ggData.outer.name _ IF versionSpecified THEN Rope.Concat["Gargoyle: ", fsName] ELSE Rope.Cat["Gargoyle: ", ggData.outer.file, " (!", FileNames.Tail[fsName, '!], ")"]; NotNewVersion[ggData, $clean]; GGEvent.SawTextFinish[ggData, NIL]; EXITS Abort => { ggData: GGData _ NARROW[clientData]; IF NOT event.first=$Emergency THEN Feedback.Blink[ggData.feedback]; }; }; Save: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; IF ggData.outer.file#NIL THEN Store[event: LIST[$Save, ggData.outer.file], clientData: clientData] ELSE { Feedback.Append[ggData.feedback, "Can't save an unnamed viewer: try Store", oneLiner]; Feedback.Blink[ggData.feedback]; }; }; Split: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData];}; Reset: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; fileName: Rope.ROPE _ ggData.outer.file; ClearAux[event, ggData]; GetMergeAux[fileName, FALSE, $Get, "Restoring", ggData]; NotNewVersion[ggData, $clean]; }; Clear: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; ClearAux[event, ggData]; ggData.outer.file _ NIL; ggData.outer.label _ "Gargoyle"; ggData.outer.name _ "Gargoyle"; GGEvent.SawTextFinish[ggData, NIL]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, ggData: ggData, remake: triggerBag, backgndOK: FALSE, edited: FALSE, okToClearFeedback: TRUE]; NotNewVersion[ggData, $clear]; }; -- end Clear ClearAux: PROC [event: LIST OF REF ANY, ggData: GGData] = { ggData.refresh.overlayList _ NIL; GGSelect.DeselectAllAllClasses[ggData.scene]; ggData.scene _ GGScene.CreateScene[]; ggData.caret _ NEW[GGInterfaceTypes.CaretObj]; ggData.anchor _ NEW[GGInterfaceTypes.CaretObj]; GGEvent.StandardAlignments[ggData, LIST[$StandardAlignments]]; ggData.aborted _ ALL[FALSE]; }; AddToGroup: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { someAddition: BOOL _ FALSE; seqGen: SequenceGenerator; ggData: GGData _ NARROW[clientData]; name: Rope.ROPE _ IF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first]; IF name=NIL OR Rope.Equal[name, ""] THEN { Feedback.AppendHerald[ggData.feedback, "Select a group name", oneLiner]; RETURN; }; seqGen _ GGSelect.SelectedSequences[ggData.scene, normal]; FOR seq: Sequence _ GGSequence.NextSequence[seqGen], GGSequence.NextSequence[seqGen] UNTIL seq=NIL DO segGen: SegmentGenerator _ GGSequence.SegmentsInSequence[seq]; FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg=NIL DO duplicate: BOOL _ FALSE; FOR prop: LIST OF REF ANY _ seg.props, prop.rest UNTIL prop=NIL DO nextProp: Rope.ROPE _ NARROW[prop.first]; IF Rope.Equal[name, nextProp, FALSE] THEN { duplicate _ TRUE; -- already in this group EXIT; }; ENDLOOP; IF NOT duplicate THEN seg.props _ List.Append[seg.props, LIST[name]]; someAddition _ TRUE; ENDLOOP; ENDLOOP; Feedback.PutF[ggData.feedback, oneLiner, IF someAddition THEN "Added selected segments to group %g" ELSE "No segment selections to add to group %g", [rope[name]] ]; }; SelectGroup: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; name: Rope.ROPE _ IF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first]; trajGen: TrajGenerator _ GGScene.TrajsInScene[ggData.scene]; segGen: SegmentGenerator; seq: Sequence; segsFound: BOOL; GGSelect.DeselectAll[ggData.scene, normal]; -- get rid of old selection FOR traj: Traj _ GGScene.NextTraj[trajGen], GGScene.NextTraj[trajGen] UNTIL traj = NIL DO segGen _ GGSequence.SegmentsInTraj[traj]; segsFound _ FALSE; FOR next: SegAndIndex _ GGSequence.NextSegmentAndIndex[segGen], GGSequence.NextSegmentAndIndex[segGen] UNTIL next.seg=NIL DO FOR prop: LIST OF REF ANY _ next.seg.props, prop.rest UNTIL prop=NIL DO nextProp: Rope.ROPE _ NARROW[prop.first]; IF Rope.Equal[name, nextProp, FALSE] THEN { IF NOT segsFound THEN seq _ GGSequence.CreateEmpty[traj]; segsFound _ TRUE; IF NOT seq.segments[next.index] THEN { seq.segments[next.index] _ TRUE; seq.segCount _ seq.segCount + 1; }; }; ENDLOOP; -- next prop ENDLOOP; -- next segment IF segsFound THEN GGSelect.SelectSequence[seq, ggData.scene, normal]; ENDLOOP; -- next trajectory GGWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE]; IF GGSelect.NoSelections[ggData.scene, normal] THEN Feedback.AppendHerald[ggData.feedback, "No such group", oneLiner ] ELSE Feedback.PutF[ggData.feedback, oneLiner, "Group %g selected", [rope[name]] ]; }; RemoveFromGroup: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { someRemoval: BOOL _ FALSE; newProps: LIST OF REF ANY; seqGen: SequenceGenerator; ggData: GGData _ NARROW[clientData]; name: Rope.ROPE _ IF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first]; IF name=NIL OR Rope.Equal[name, ""] THEN { Feedback.AppendHerald[ggData.feedback, "Select a group name", oneLiner]; RETURN; }; seqGen _ GGSelect.SelectedSequences[ggData.scene, normal]; FOR seq: Sequence _ GGSequence.NextSequence[seqGen], GGSequence.NextSequence[seqGen] UNTIL seq=NIL DO segGen: SegmentGenerator _ GGSequence.SegmentsInSequence[seq]; FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg=NIL DO newProps _ NIL; FOR prop: LIST OF REF ANY _ seg.props, prop.rest UNTIL prop=NIL DO nextProp: Rope.ROPE _ NARROW[prop.first]; IF NOT Rope.Equal[name, nextProp, FALSE] THEN newProps _ List.Append[newProps, LIST[nextProp]] ELSE someRemoval _ TRUE; ENDLOOP; seg.props _ newProps; ENDLOOP; ENDLOOP; Feedback.PutF[ggData.feedback, oneLiner, IF someRemoval THEN "Removed selected segments from group %g" ELSE "No member segments selected to remove from group %g", [rope[name]] ]; }; PrintGroupsOfSelected: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { groupList: LIST OF REF ANY; seqGen: SequenceGenerator; ggData: GGData _ NARROW[clientData]; IF GGSelect.NoSelections[ggData.scene, normal] THEN { Feedback.AppendHerald[ggData.feedback, "No selections => no groups", oneLiner]; RETURN; }; seqGen _ GGSelect.SelectedSequences[ggData.scene, normal]; FOR seq: Sequence _ GGSequence.NextSequence[seqGen], GGSequence.NextSequence[seqGen] UNTIL seq=NIL DO segGen: SegmentGenerator _ GGSequence.SegmentsInSequence[seq]; FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg=NIL DO FOR prop: LIST OF REF ANY _ seg.props, prop.rest UNTIL prop=NIL DO nextProp: Rope.ROPE _ NARROW[prop.first]; duplicate: BOOL _ FALSE; FOR group: LIST OF REF ANY _ groupList, group.rest UNTIL group=NIL DO nextGroup: Rope.ROPE _ NARROW[group.first]; IF Rope.Equal[nextGroup, nextProp, FALSE] THEN { duplicate _ TRUE; -- already on the group list EXIT; }; ENDLOOP; IF NOT duplicate THEN groupList _ List.Append[groupList, LIST[nextProp]]; ENDLOOP; ENDLOOP; ENDLOOP; IF groupList#NIL THEN { Feedback.Append[ggData.feedback, "Groups of Selected: ", begin]; FOR group: LIST OF REF ANY _ groupList, group.rest UNTIL group=NIL DO nextGroup: Rope.ROPE _ NARROW[group.first]; Feedback.PutF[ggData.feedback, middle, "%g ", [rope[nextGroup]] ]; ENDLOOP; Feedback.Append[ggData.feedback, "", end]; } ELSE Feedback.Append[ggData.feedback, "No Groups of Selected", oneLiner]; }; PrintAllGroups: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { groupList: LIST OF REF ANY; ggData: GGData _ NARROW[clientData]; trajGen: TrajGenerator _ GGScene.TrajsInScene[ggData.scene]; FOR traj: Traj _ GGScene.NextTraj[trajGen], GGScene.NextTraj[trajGen] UNTIL traj = NIL DO segGen: SegmentGenerator _ GGSequence.SegmentsInTraj[traj]; FOR seg: Segment _ GGSequence.NextSegment[segGen], GGSequence.NextSegment[segGen] UNTIL seg=NIL DO FOR prop: LIST OF REF ANY _ seg.props, prop.rest UNTIL prop=NIL DO nextProp: Rope.ROPE _ NARROW[prop.first]; duplicate: BOOL _ FALSE; FOR group: LIST OF REF ANY _ groupList, group.rest UNTIL group=NIL DO nextGroup: Rope.ROPE _ NARROW[group.first]; IF Rope.Equal[nextGroup, nextProp, FALSE] THEN { duplicate _ TRUE; -- already on the group list EXIT; }; ENDLOOP; IF NOT duplicate THEN groupList _ List.Append[groupList, LIST[nextProp]]; ENDLOOP; ENDLOOP; ENDLOOP; IF groupList#NIL THEN { Feedback.Append[ggData.feedback, "Groups: ", begin]; FOR group: LIST OF REF ANY _ groupList, group.rest UNTIL group=NIL DO nextGroup: Rope.ROPE _ NARROW[group.first]; Feedback.PutF[ggData.feedback, middle, "%g ", [rope[nextGroup]] ]; ENDLOOP; Feedback.Append[ggData.feedback, "", end]; } ELSE Feedback.Append[ggData.feedback, "No Groups", oneLiner]; }; RGBFromRopeError: SIGNAL = CODE; AreaColorFromColorTool: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; IF ColorToolIsBound[ggData] THEN AreaColorAux[ImagerColor.ColorFromRGB[ColorTool.GetRGBValue[]], ggData]; }; LineColorFromColorTool: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; IF ColorToolIsBound[ggData] THEN LineColorAux[ImagerColor.ColorFromRGB[ColorTool.GetRGBValue[]], ggData]; }; AreaColorFollowColorTool: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; IF ColorToolIsBound[ggData] THEN { color: Imager.Color _ GGUtility.GetSpecialColor[]; -- "animation" color; IF color#NIL THEN { ggData.refresh.areaFollowColorTool _ TRUE; AreaColorAux[color, ggData]; } ELSE Feedback.Append[ggData.feedback, ". . . Can't find ColorTool", oneLiner]; }; }; LineColorFollowColorTool: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; IF ColorToolIsBound[ggData] THEN { color: Imager.Color _ GGUtility.GetSpecialColor[]; -- "animation" color; IF color#NIL THEN { ggData.refresh.lineFollowColorTool _ TRUE; LineColorAux[color, ggData]; } ELSE Feedback.Append[ggData.feedback, ". . . Can't find ColorTool", oneLiner]; }; }; AreaColorToColorTool: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; IF ColorToolIsBound[ggData] THEN { red, green, blue: REAL; color: Imager.Color; sliceDescGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[ggData.scene, normal]; sliceD: SliceDescriptor _ GGSelect.NextSliceDescriptor[sliceDescGen]; color _ sliceD.slice.class.getFillColor[sliceD.slice]; IF color#NIL THEN { [red, green, blue] _ GGUtility.ExtractRGB[color]; ColorTool.SetRGBValue[[red, green, blue], NIL]; } ELSE Feedback.Append[ggData.feedback, ". . . Object has NIL fill color", oneLiner]; }; }; LineColorToColorTool: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; IF ColorToolIsBound[ggData] THEN { red, green, blue: REAL; color: Imager.Color; sliceDescGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[ggData.scene, normal]; sliceD: SliceDescriptor _ GGSelect.NextSliceDescriptor[sliceDescGen]; color _ sliceD.slice.class.getStrokeColor[sliceD.slice, sliceD.parts]; IF color#NIL THEN { [red, green, blue] _ GGUtility.ExtractRGB[color]; ColorTool.SetRGBValue[[red, green, blue], NIL]; } ELSE Feedback.Append[ggData.feedback, ". . . Object has NIL stroke color", oneLiner]; }; }; AreaColorFromSelectedName: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; name: Rope.ROPE _ IF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first]; color: Imager.Color _ ImagerColor.ColorFromRGB[ImagerColorFns.RGBFromHSL[NamedColors.RopeToHSL[name ! NamedColors.UndefinedName => GOTO UndefinedName; NamedColors.BadGrammar => GOTO BadGrammar; ]]]; AreaColorAux[color, ggData]; EXITS UndefinedName => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Undefined Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; BadGrammar => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Bad Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; }; LineColorFromSelectedName: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; name: Rope.ROPE _ IF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first]; color: Imager.Color _ ImagerColor.ColorFromRGB[ImagerColorFns.RGBFromHSL[NamedColors.RopeToHSL[name ! NamedColors.UndefinedName => GOTO UndefinedName; NamedColors.BadGrammar => GOTO BadGrammar; ]]]; LineColorAux[color, ggData]; EXITS UndefinedName => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Undefined Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; BadGrammar => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Bad Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; }; AreaColorFromSelectedRGB: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; name: Rope.ROPE _ IF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first]; color: Imager.Color _ ImagerColor.ColorFromRGB[RGBFromRope[name ! RGBFromRopeError => GOTO SyntaxError]]; AreaColorAux[color, ggData]; EXITS SyntaxError => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "RGB Syntax is R: [0.0..1.0] G: [0.0..1.0] B: [0.0..1.0]", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; }; LineColorFromSelectedRGB: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; name: Rope.ROPE _ IF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first]; color: Imager.Color _ ImagerColor.ColorFromRGB[RGBFromRope[name ! RGBFromRopeError => GOTO SyntaxError]]; LineColorAux[color, ggData]; EXITS SyntaxError => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "RGB Syntax is R: [0.0..1.0] G: [0.0..1.0] B: [0.0..1.0]", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; }; SelectMatchingAreaColor: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; rgb: ImagerColor.RGB; name: Rope.ROPE _ IF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first]; sliceGen: SliceGenerator _ GGScene.TopLevelSlicesInScene[ggData.scene]; noneFlag: BOOL _ Rope.Equal[name, "none", FALSE]; IF NOT noneFlag THEN rgb _ SELECT event.first FROM $SelectMatchingAreaCNS => ImagerColorFns.RGBFromHSL[NamedColors.RopeToHSL[name ! NamedColors.UndefinedName => GOTO UndefinedName; NamedColors.BadGrammar => GOTO BadGrammar; ]], $SelectMatchingAreaRGB => RGBFromRope[name ! RGBFromRopeError => GOTO SyntaxError] ENDCASE => ERROR; GGSelect.DeselectAll[ggData.scene, normal]; FOR slice: Slice _ GGScene.NextSlice[sliceGen], GGScene.NextSlice[sliceGen] UNTIL slice = NIL DO fillColor: Imager.Color _ slice.class.getFillColor[slice]; IF RGBEqualsColor[rgb, fillColor, noneFlag] THEN GGSelect.SelectEntireSlice[slice, ggData.scene, normal]; ENDLOOP; Feedback.PutFHerald[ggData.feedback, oneLiner, "Areas with fill color %g selected", [rope[name]] ]; GGWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; EXITS SyntaxError => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "RGB Syntax is R: [0.0..1.0] G: [0.0..1.0] B: [0.0..1.0]", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; UndefinedName => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Undefined Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; BadGrammar => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Bad Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; }; SelectMatchingLineColor: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; rgb: ImagerColor.RGB; name: Rope.ROPE _ IF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first]; sliceGen: SliceGenerator _ GGScene.SlicesInScene[ggData.scene]; noneFlag: BOOL _ Rope.Equal[name, "none", FALSE]; IF NOT noneFlag THEN rgb _ SELECT event.first FROM $SelectMatchingLineCNS => ImagerColorFns.RGBFromHSL[NamedColors.RopeToHSL[name ! NamedColors.UndefinedName => GOTO UndefinedName; NamedColors.BadGrammar => GOTO BadGrammar; ]], $SelectMatchingLineRGB => RGBFromRope[name ! RGBFromRopeError => GOTO SyntaxError] ENDCASE => ERROR; GGSelect.DeselectAll[ggData.scene, normal]; FOR slice: Slice _ GGScene.NextSlice[sliceGen], GGScene.NextSlice[sliceGen] UNTIL slice = NIL DO -- for every slice in the scene ColorProc: WalkProc = { RETURN [RGBEqualsColor[rgb, seg.color, noneFlag]]; }; sliceD: SliceDescriptor _ GGSlice.WalkSegments[slice, ColorProc]; -- get a descriptor of matching parts GGSelect.SelectSlice[sliceD, ggData.scene, normal]; -- and select it ENDLOOP; Feedback.PutFHerald[ggData.feedback, oneLiner, "Segments with color %g selected", [rope[name]] ]; GGWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; EXITS SyntaxError => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "RGB Syntax is R: [0.0..1.0] G: [0.0..1.0] B: [0.0..1.0]", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; UndefinedName => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Undefined Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; BadGrammar => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Bad Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; }; SetDefaultLineColor: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; sliceD: SliceDescriptor; sliceDescGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[ggData.scene, normal]; IF sliceDescGen=NIL OR (sliceD _ GGSelect.NextSliceDescriptor[sliceDescGen])=NIL OR GGSelect.NextSliceDescriptor[sliceDescGen]#NIL THEN Feedback.AppendHerald[ggData.feedback, "Select exactly one object for setting default line color", oneLiner] ELSE { isProcessBlack: Rope.ROPE; red, green, blue: REAL; color: Imager.ConstantColor _ NARROW[sliceD.slice.class.getStrokeColor[sliceD.slice, sliceD.parts]]; IF color#NIL THEN { [red,green,blue] _ GGUtility.ExtractRGB[color]; IF color = Imager.black THEN isProcessBlack _ " (process black)" ELSE IF ImagerColorPrivate.GrayFromColor[color]=1.0 THEN isProcessBlack _ " (CMY black)" ELSE isProcessBlack _ ""; Feedback.Append[ ggData.feedback, IO.PutFR["Default Stroke Color: R: %1.3f G: %1.3f B: %1.3f CNS: %g%g", [real[red]], [real[green]], [real[blue]], [rope[NamedColors.HSLToRope[ImagerColorFns.HSLFromRGB[[red,green,blue]]]]], [rope[isProcessBlack]] ], oneLiner]; } ELSE Feedback.Append[ggData.feedback, "Default Stroke Color: None", oneLiner]; ggData.defaults.strokeColor _ color; }; }; SetDefaultFillColor: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; sliceD: SliceDescriptor; sliceDescGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[ggData.scene, normal]; IF sliceDescGen=NIL OR (sliceD _ GGSelect.NextSliceDescriptor[sliceDescGen])=NIL OR GGSelect.NextSliceDescriptor[sliceDescGen]#NIL THEN Feedback.AppendHerald[ggData.feedback, "Select exactly one filled object for setting default fill color", oneLiner] ELSE { isProcessBlack: Rope.ROPE; red, green, blue: REAL; color: Imager.ConstantColor; IF sliceD.slice.class.type=$Outline AND GGOutline.FenceOfOutline[sliceD.slice].role=open THEN { Feedback.AppendHerald[ggData.feedback, "Select one FILLED object for setting default fill color", oneLiner]; RETURN; } ELSE color _ NARROW[sliceD.slice.class.getFillColor[sliceD.slice]]; IF color#NIL THEN { [red,green,blue] _ GGUtility.ExtractRGB[color]; IF color = Imager.black THEN isProcessBlack _ " (process black)" ELSE IF ImagerColorPrivate.GrayFromColor[color]=1.0 THEN isProcessBlack _ " (CMY black)" ELSE isProcessBlack _ ""; Feedback.Append[ ggData.feedback, IO.PutFR["Default Fill Color: R: %1.3f G: %1.3f B: %1.3f CNS: %g%g", [real[red]], [real[green]], [real[blue]], [rope[NamedColors.HSLToRope[ImagerColorFns.HSLFromRGB[[red,green,blue]]]]], [rope[isProcessBlack]] ], oneLiner]; } ELSE Feedback.Append[ggData.feedback, "Default Fill Color: None", oneLiner]; ggData.defaults.fillColor _ color; }; }; ShowDefaultLineColor: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; isProcessBlack: Rope.ROPE; red, green, blue: REAL; color: Imager.ConstantColor _ NARROW[ggData.defaults.strokeColor]; IF color#NIL THEN { [red,green,blue] _ GGUtility.ExtractRGB[color]; IF color = Imager.black THEN isProcessBlack _ " (process black)" ELSE IF ImagerColorPrivate.GrayFromColor[color]=1.0 THEN isProcessBlack _ " (CMY black)" ELSE isProcessBlack _ ""; Feedback.Append[ ggData.feedback, IO.PutFR["Default Stroke Color: R: %1.3f G: %1.3f B: %1.3f CNS: %g%g", [real[red]], [real[green]], [real[blue]], [rope[NamedColors.HSLToRope[ImagerColorFns.HSLFromRGB[[red,green,blue]]]]], [rope[isProcessBlack]] ], oneLiner]; } ELSE Feedback.Append[ggData.feedback, "Default Stroke Color: None", oneLiner]; }; ShowDefaultFillColor: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; isProcessBlack: Rope.ROPE; red, green, blue: REAL; color: Imager.ConstantColor _ NARROW[ggData.defaults.fillColor]; IF color#NIL THEN { [red,green,blue] _ GGUtility.ExtractRGB[color]; IF color = Imager.black THEN isProcessBlack _ " (process black)" ELSE IF ImagerColorPrivate.GrayFromColor[color]=1.0 THEN isProcessBlack _ " (CMY black)" ELSE isProcessBlack _ ""; Feedback.Append[ ggData.feedback, IO.PutFR["Default Fill Color: R: %1.3f G: %1.3f B: %1.3f CNS: %g%g", [real[red]], [real[green]], [real[blue]], [rope[NamedColors.HSLToRope[ImagerColorFns.HSLFromRGB[[red,green,blue]]]]], [rope[isProcessBlack]] ], oneLiner]; } ELSE Feedback.Append[ggData.feedback, "Default Fill Color: None", oneLiner]; }; AreaColorBlack: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; AreaColorAux[Imager.black, ggData]; }; LineColorBlack: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; LineColorAux[Imager.black, ggData]; }; PrintAreaColor: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; sliceD: SliceDescriptor; isProcessBlack: Rope.ROPE; sliceDescGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[ggData.scene, normal]; IF sliceDescGen=NIL OR (sliceD _ GGSelect.NextSliceDescriptor[sliceDescGen])=NIL OR GGSelect.NextSliceDescriptor[sliceDescGen]#NIL THEN Feedback.AppendHerald[ggData.feedback, "Select exactly one object for PrintFillColor", oneLiner] ELSE { red, green, blue: REAL; color: Imager.ConstantColor _ NARROW[sliceD.slice.class.getFillColor[sliceD.slice]]; IF color#NIL THEN { [red,green,blue] _ GGUtility.ExtractRGB[color]; IF color = Imager.black THEN isProcessBlack _ " (process black)" ELSE IF ImagerColorPrivate.GrayFromColor[color]=1.0 THEN isProcessBlack _ " (CMY black)" ELSE isProcessBlack _ ""; Feedback.Append[ ggData.feedback, IO.PutFR["R: %1.3f G: %1.3f B: %1.3f CNS: %g%g", [real[red]], [real[green]], [real[blue]], [rope[NamedColors.HSLToRope[ImagerColorFns.HSLFromRGB[[red,green,blue]]]]], [rope[isProcessBlack]] ], oneLiner]; } ELSE Feedback.Append[ggData.feedback, "No Fill Color", oneLiner]; }; }; PrintLineColor: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; sliceD: SliceDescriptor; isProcessBlack: Rope.ROPE; sliceDescGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[ggData.scene, normal]; IF sliceDescGen=NIL OR (sliceD _ GGSelect.NextSliceDescriptor[sliceDescGen])=NIL OR GGSelect.NextSliceDescriptor[sliceDescGen]#NIL THEN Feedback.AppendHerald[ggData.feedback, "Select exactly one object for PrintLineColor", oneLiner] ELSE { red, green, blue: REAL; color: Imager.ConstantColor _ NARROW[sliceD.slice.class.getStrokeColor[sliceD.slice, sliceD.parts]]; IF color#NIL THEN { [red, green, blue] _ GGUtility.ExtractRGB[color]; IF color = Imager.black THEN isProcessBlack _ " (process black)" ELSE IF ImagerColorPrivate.GrayFromColor[color]=1.0 THEN isProcessBlack _ " (CMY black)" ELSE isProcessBlack _ ""; Feedback.Append[ ggData.feedback, IO.PutFR["R: %1.3f G: %1.3f B: %1.3f CNS: %g%g", [real[red]], [real[green]], [real[blue]], [rope[NamedColors.HSLToRope[ImagerColorFns.HSLFromRGB[[red,green,blue]]]]], [rope[isProcessBlack]] ], oneLiner]; } ELSE Feedback.Append[ggData.feedback, "No Stroke Color", oneLiner]; }; }; AreaColorWhite: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; AreaColorAux[Imager.white, ggData]; }; LineColorWhite: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; LineColorAux[Imager.white, ggData]; }; AreaColorGray: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; AreaColorAux[GGOutline.fillColor, ggData]; }; LineColorGray: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; LineColorAux[GGOutline.fillColor, ggData]; }; AreaColorNone: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; AreaColorAux[NIL, ggData]; }; LineColorNone: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; LineColorAux[NIL, ggData]; }; AreaColorAux: PROC [color: Imager.Color, clientData: REF ANY] = { ggData: GGData _ NARROW[clientData]; sliceDescGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[ggData.scene, normal]; FOR sliceD: SliceDescriptor _ GGSelect.NextSliceDescriptor[sliceDescGen], GGSelect.NextSliceDescriptor[sliceDescGen] UNTIL sliceD=NIL DO sliceD.slice.class.setFillColor[sliceD.slice, color]; ENDLOOP; GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectChangedInPlace, ggData: ggData, remake: none, backgndOK: FALSE, edited: TRUE, okToClearFeedback: TRUE]; }; LineColorAux: PROC [color: Imager.Color, clientData: REF ANY] = { ggData: GGData _ NARROW[clientData]; sliceDescGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[ggData.scene, normal]; FOR sliceD: SliceDescriptor _ GGSelect.NextSliceDescriptor[sliceDescGen], GGSelect.NextSliceDescriptor[sliceDescGen] UNTIL sliceD=NIL DO sliceD.slice.class.setStrokeColor[sliceD.slice, sliceD.parts, color]; ENDLOOP; GGWindow.RestoreScreenAndInvariants[paintAction: $ObjectChangedInPlace, ggData: ggData, remake: none, backgndOK: FALSE, edited: TRUE, okToClearFeedback: TRUE]; }; ColorToolIsBound: PROC [ggData: GGData] RETURNS [BOOL _ FALSE] = TRUSTED { IF PrincOpsUtils.IsBound[LOOPHOLE[ColorTool.GetRGBValue]] THEN RETURN[TRUE]; Feedback.AppendHerald[ggData.feedback, "Please start ColorTool and retry this operation", oneLiner]; }; RGBEqualsColor: PROC [rgb: ImagerColor.RGB, color: Imager.Color, noneFlag: BOOL] RETURNS [BOOL] = { epsilon: REAL = 1.0E-2; IF color=NIL THEN RETURN [noneFlag]; -- color is none => RETURN[looking for none] IF noneFlag THEN RETURN [FALSE] -- looking for none, but color is non-NIL ELSE { r, g, b: REAL; [r,g,b] _ GGUtility.ExtractRGB[color]; RETURN[(r=rgb.R AND g=rgb.G AND b=rgb.B) OR (ABS[r-rgb.R] GOTO RGBError; Check: PROC [x: REAL] = { IF x NOT IN [0.0..1.0] THEN SIGNAL RGBFromRopeError; }; rs: IO.STREAM _ IO.RIS[name]; IF Ascii.Upper[rs.GetChar[]]#'R THEN GOTO RGBError; IF rs.GetChar[]#': THEN GOTO RGBError; rgb.R _ rs.GetReal[]; [] _ rs.SkipWhitespace[]; IF Ascii.Upper[rs.GetChar[]]#'G THEN GOTO RGBError; IF rs.GetChar[]#': THEN GOTO RGBError; rgb.G _ rs.GetReal[]; [] _ rs.SkipWhitespace[]; IF Ascii.Upper[rs.GetChar[]]#'B THEN GOTO RGBError; IF rs.GetChar[]#': THEN GOTO RGBError; rgb.B _ rs.GetReal[]; Check[rgb.R]; Check[rgb.G]; Check[rgb.B]; EXITS RGBError => SIGNAL RGBFromRopeError; }; TestMultiGravity: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { }; TestGravity: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; xRandomStream, yRandomStream: Random.RandomStream; desiredCount: INT _ NARROW[event.rest.first, REF INT]^; testPoint: Point; x, y: INT; totalCount, multiHitCount, uniHitCount, diffCount: NAT _ 0; uniPoint, multiPoint: Point; uniFeature, multiFeature: FeatureData; currentObjects: AlignBag; sceneObjects: TriggerBag; IF desiredCount < 0 THEN RETURN; xRandomStream _ Random.Create[ggData.actionArea.cw]; yRandomStream _ Random.Create[ggData.actionArea.ch]; ggData.aborted[gravitytest] _ FALSE; -- in case there was one left over from prior abort UNTIL totalCount >= desiredCount DO IF ggData.aborted[gravitytest] THEN { ggData.aborted[gravitytest] _ FALSE; EXIT; }; x _ Random.NextInt[xRandomStream]; y _ Random.NextInt[yRandomStream]; testPoint _ [x, y]; testPoint _ GGWindow.ViewerToWorld[viewerPoint: testPoint, ggData: ggData]; ggData.refresh.spotPoint _ testPoint; currentObjects _ ggData.hitTest.alignBag; sceneObjects _ ggData.hitTest.sceneBag; [uniPoint, uniFeature] _ GGGravity.UniMap[testPoint, ggData.hitTest.tolerance, currentObjects, sceneObjects, ggData, TRUE]; [multiPoint, multiFeature] _ GGMultiGravity.Map[testPoint, ggData.hitTest.tolerance, currentObjects, sceneObjects, ggData, TRUE]; IF uniFeature = NIL AND multiFeature = NIL THEN { GGWindow.RestoreScreenAndInvariants[paintAction: $PaintSpot, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; totalCount _ totalCount + 1; LOOP; }; IF uniFeature = NIL OR multiFeature = NIL OR uniFeature # multiFeature OR uniFeature.type # multiFeature.type OR uniPoint # multiPoint THEN { ReportResultsAndPaint[testPoint, uniPoint, uniFeature, multiPoint, multiFeature, ggData]; totalCount _ totalCount + 1; diffCount _ diffCount + 1; IF multiFeature # NIL THEN multiHitCount _ multiHitCount + 1; IF uniFeature # NIL THEN uniHitCount _ uniHitCount + 1; } ELSE { multiHitCount _ multiHitCount + 1; uniHitCount _ uniHitCount + 1; totalCount _ totalCount + 1; ggData.refresh.hitPoint _ multiPoint; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintHitLine, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; ENDLOOP; Feedback.PutF[ggData.feedback, oneLiner, "Tested %g total points. %g unihits. %g multihits. %g differences", [integer[totalCount]], [integer[uniHitCount]], [integer[multiHitCount]], [integer[diffCount]]]; }; -- end TestGravity noisyTestGravity: BOOL _ FALSE; ReportResultsAndPaint: PROC [testPoint: Point, uniPoint: Point, uniFeature: FeatureData, multiPoint: Point, multiFeature: FeatureData, ggData: GGData] = { multiMag, uniMag: REAL; IF uniFeature = NIL THEN { multiMag _ Vectors2d.Magnitude[Vectors2d.Sub[multiPoint, testPoint]]; IF noisyTestGravity THEN Feedback.PutFTypescript[ggData.feedback, oneLiner, "No unihit at [%g, %g]. multihit distance: %g", [real[multiPoint.x]], [real[multiPoint.y]], [real[multiMag]]]; ggData.refresh.hitPoint _ multiPoint; } ELSE IF multiFeature = NIL THEN { uniMag _ Vectors2d.Magnitude[Vectors2d.Sub[uniPoint, testPoint]]; IF noisyTestGravity THEN Feedback.PutFTypescript[ggData.feedback, oneLiner, "No multihit at [%g, %g]. unihit distance: %g", [real[uniPoint.x]], [real[uniPoint.y]], [real[uniMag]]]; ggData.refresh.hitPoint _ uniPoint; } ELSE IF uniFeature # multiFeature THEN { multiMag _ Vectors2d.Magnitude[Vectors2d.Sub[multiPoint, testPoint]]; uniMag _ Vectors2d.Magnitude[Vectors2d.Sub[uniPoint, testPoint]]; IF noisyTestGravity THEN Feedback.PutFTypescript[ggData.feedback, oneLiner, "Features differ at [%g, %g] by %g to %g", [real[multiPoint.x]], [real[multiPoint.y]], [real[multiMag]], [real[uniMag]]]; ggData.refresh.hitPoint _ multiPoint; } ELSE IF uniFeature.type # multiFeature.type THEN { IF noisyTestGravity THEN Feedback.PutFTypescript[ggData.feedback, oneLiner, "Feature types differ at [%g, %g]", [real[multiPoint.x]], [real[multiPoint.y]]]; ggData.refresh.hitPoint _ multiPoint; } ELSE IF uniPoint # multiPoint THEN { multiMag _ Vectors2d.Magnitude[Vectors2d.Sub[multiPoint, testPoint]]; uniMag _ Vectors2d.Magnitude[Vectors2d.Sub[uniPoint, testPoint]]; IF noisyTestGravity THEN Feedback.PutFTypescript[ggData.feedback, oneLiner, "Points differ at [%g, %g] by %g to %g", [real[multiPoint.x]], [real[multiPoint.y]], [real[multiMag]], [real[uniMag]]]; ggData.refresh.hitPoint _ uniPoint; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintOddHitLine, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; ggData.refresh.hitPoint _ multiPoint; } ELSE ERROR; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintOddHitLine, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; Statistics: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; f: IO.STREAM _ Feedback.GetTypescriptStream[$Gargoyle]; CodeTimer.PrintTable[f, CodeTimer.GetTable[$Gargoyle]]; }; PrintSelectedStatistic: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; intervalName: Rope.ROPE _ NARROW[event.rest.first]; atom: ATOM _ Atom.MakeAtom[intervalName]; f: IO.STREAM _ Feedback.GetTypescriptStream[$Gargoyle]; CodeTimer.PrintInt[f, atom, $Gargoyle]; }; ResetStatistics: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; CodeTimer.ResetTable[CodeTimer.GetTable[$Gargoyle]]; }; DrawTouchPoints: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintTouchPoints, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE]; }; DrawBoundBoxes: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintBoundBoxes, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE]; }; DrawTightBoxes: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintTightBoxes, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE]; }; DrawOutlineBoxes: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintOutlineBoxes, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE]; }; DrawSelectionBox: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintSelectionBox, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE]; }; DrawMovingBox: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; atom: ATOM _ NARROW[event.first]; GGWindow.RestoreScreenAndInvariants[paintAction: atom, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: TRUE]; }; DescribeCaretObject: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; description: Rope.ROPE _ "no object"; chair: REF ANY; chair _ GGCaret.GetChair[ggData.caret]; IF chair # NIL THEN { WITH chair SELECT FROM outlineD: OutlineDescriptor => { description _ outlineD.slice.class.describe[outlineD]; }; sliceD: SliceDescriptor => { description _ sliceD.slice.class.describe[sliceD]; }; ENDCASE => ERROR; }; Feedback.Append[ggData.feedback, IO.PutFR["Caret is on %g.", [rope[description]]], oneLiner]; }; SlackLog: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; }; Typescript: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { [] _ Feedback.OpenTypescript["Gargoyle Typescript", $Gargoyle, 120]; }; cleanIcon: Icons.IconFlavor _ unInit; -- filled in by Init noNameIcon: Icons.IconFlavor _ unInit; -- filled in by Init Init: PROC = { -- copied from GGWindowImpl noNameIcon _ Icons.NewIconFromFile["Gargoyle.icons", 1]; -- done here so file will come from working directory into which Gargoyle was brought over, e.g. ///Commands/ cleanIcon _ Icons.NewIconFromFile["Gargoyle.icons", 3]; -- done here so file will come from working directory into which Gargoyle was brought over, e.g. ///Commands/ }; Init[]; END. âGGEventImplD.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last edited by Bier on April 20, 1987 6:00:17 pm PDT Contents: Once an event reaches the front of the slack-process queue, it is dispatched to one of the procedures in this module. Pier, May 12, 1987 5:32:05 pm PDT File Operations need to repaint the caption because viewer is no longer edited ASSERT: event is either NIL or event.first=filename ASSERT: event.first=$Get, event.rest=NIL OR filename ASSERT: event.first=$Merge, event.rest=NIL OR filename ASSERT: event=$Merge or $Get TIMING VARIABLES START TIMING here if successfully read a new GG file ASSERT: event.first=$Store or $Save, event.rest=NIL OR filename Save is simply Store invoked with event.first=ggData.outer.file. KAP February 17, 1986 TIMING VARIABLES START TIMING can only reset to the latest version. No version numbers supported for resetting need to repaint the caption because viewer is no longer edited ggData.refresh.suppressRefresh _ FALSE; -- moved to abort processing code Group Operations Area and Line Colors SelectMatchingAreaColor: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; rgb: ImagerColor.RGB; name: Rope.ROPE _ IF event.rest = NIL THEN ViewerTools.GetSelectionContents[] ELSE NARROW[event.rest.first]; entityGen: EntityGenerator _ GGScene.TopLevelEntitiesInScene[ggData.scene]; noneFlag: BOOL _ Rope.Equal[name, "none", FALSE]; IF NOT noneFlag THEN rgb _ SELECT event.first FROM $SelectMatchingAreaCNS => ImagerColorFns.RGBFromHSL[NamedColors.RopeToHSL[name ! NamedColors.UndefinedName => GOTO UndefinedName; NamedColors.BadGrammar => GOTO BadGrammar; ]], $SelectMatchingAreaRGB => RGBFromRope[name ! RGBFromRopeError => GOTO SyntaxError] ENDCASE => ERROR; GGSelect.DeselectAll[ggData.scene, normal]; FOR entity: REF ANY _ GGScene.NextEntity[entityGen], GGScene.NextEntity[entityGen] UNTIL entity = NIL DO WITH entity SELECT FROM outline: Outline => { fillColor: Imager.Color _ outline.class.getFillColor[outline]; IF RGBEqualsColor[rgb, fillColor, noneFlag] THEN GGSelect.SelectEntireOutline[outline, ggData.scene, normal]; }; slice: Slice => { fillColor: Imager.Color _ slice.class.getFillColor[slice]; IF RGBEqualsColor[rgb, fillColor, noneFlag] THEN GGSelect.SelectSlice[slice.class.newParts[slice, NIL, topLevel], ggData.scene, normal]; }; ENDCASE => ERROR; ENDLOOP; Feedback.PutFHerald[ggData.feedback, oneLiner, "Areas with fill color %g selected", [rope[name]] ]; GGWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; EXITS SyntaxError => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "RGB Syntax is R: [0.0..1.0] G: [0.0..1.0] B: [0.0..1.0]", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; UndefinedName => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Undefined Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; BadGrammar => {Feedback.AppendHerald[NARROW[clientData, GGData].feedback, "Bad Color Name", oneLiner]; Feedback.Blink[NARROW[clientData, GGData].feedback];}; }; trajGen: TrajGenerator _ GGScene.TrajsInScene[ggData.scene]; FOR traj: Traj _ GGScene.NextTraj[trajGen], GGScene.NextTraj[trajGen] UNTIL traj = NIL DO segGen: SegmentGenerator _ GGSequence.SegmentsInTraj[traj]; FOR segAndIndex: SegAndIndex _ GGSequence.NextSegmentAndIndex[segGen], GGSequence.NextSegmentAndIndex[segGen] UNTIL segAndIndex.seg = NIL DO IF RGBEqualsColor[rgb, segAndIndex.seg.color, noneFlag] THEN { seq: Sequence _ GGSequence.CreateFromSegment[traj, segAndIndex.index]; GGSelect.SelectSequence[seq, ggData.scene, normal]; }; ENDLOOP; ENDLOOP; WalkProc: TYPE = PROC [seg: Segment] RETURNS [keep: BOOL]; Debug Menu TestMultiGravity: PUBLIC PROC [clientData: REF ANY, event: LIST OF REF ANY] = { ggData: GGData _ NARROW[clientData]; Within the bounds of the viewer, randomly choose mouse positions. See if that mouse position is in range of any object. If so, draw a dot at that point. Repeat until 100 points have been drawn. xRandomStream, yRandomStream: Random.RandomStream; testPoint: Point; x, y: INT; totalCount: NAT _ 0; features: GGMultiGravity.NearFeatures; points: GGMultiGravity.NearPoints; distances: GGMultiGravity.NearDistances; currentObjects: AlignBag; sceneObjects: TriggerBag; count: NAT; xRandomStream _ Random.Create[ggData.actionArea.cw]; yRandomStream _ Random.Create[ggData.actionArea.ch]; GGAlign.SetBagsForAction[ggData, $CaretPos]; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintAlign, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; ggData.hitTest.hitCount _ 0; ggData.aborted[gravitytest] _ FALSE; -- in case there was one left over from prior abort UNTIL totalCount > 1000 DO IF ggData.aborted[gravitytest] THEN { ggData.aborted[gravitytest] _ FALSE; EXIT; }; x _ Random.NextInt[xRandomStream]; y _ Random.NextInt[yRandomStream]; testPoint _ [x, y]; testPoint _ GGWindow.ViewerToWorld[viewerPoint: testPoint, ggData: ggData]; ggData.refresh.spotPoint _ testPoint; currentObjects _ ggData.hitTest.alignBag; sceneObjects _ ggData.hitTest.sceneBag; [features, points, distances, count] _ GGMultiGravity.MultiMap[20, testPoint, ggData.hitTest.tolerance, currentObjects, sceneObjects, ggData, TRUE]; IF count > 0 THEN { FOR i: NAT IN [0..count-1] DO ggData.refresh.hitPoint _ points[i]; IF distances[i] > ggData.hitTest.tolerance THEN GOTO Done; GGWindow.RestoreScreenAndInvariants[paintAction: $PaintHitLine, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; ggData.hitTest.hitCount _ ggData.hitTest.hitCount + 1; REPEAT Done => { IF i = 0 THEN GGWindow.RestoreScreenAndInvariants[paintAction: $PaintSpot, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; ENDLOOP; } ELSE { GGWindow.RestoreScreenAndInvariants[paintAction: $PaintSpot, ggData: ggData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; totalCount _ totalCount + 1; ENDLOOP; Feedback.PutF[ggData.feedback, oneLiner, "Tested %g total points. %g were hits", [integer[totalCount]], [integer[ggData.hitTest.hitCount]]]; }; Within the bounds of the viewer, randomly choose mouse positions. See if that mouse position is in range of any object. If so, draw a dot at that point. Repeat until 100 points have been drawn. GGAlign.SetStaticBags[ggData]; ggData.hitTest.hitCount _ 0; SlackProcess.OutputLog[ggData.slackHandle, Feedback.GetTypescriptStream[$Gargoyle]]; Ê8˜Icodešœ™Kšœ Ïmœ1™™>Kšœžœ˜ šœžœž˜"Kšœ˜Kšœ˜Kšžœžœ˜—Kšœ-˜-Kšœ˜K˜—š Ÿœžœ žœžœžœžœžœ%žœžœžœžœžœ žœžœžœžœ˜ÙKšžœžœ™3š Ÿ œžœžœžœžœ žœ˜>šžœžœž˜Kšœžœžœžœ˜2Kšœžœžœ˜Kšžœžœ˜—K˜—Kšœžœ˜Kš œ žœžœžœ žœžœžœ%˜sKšœr˜rK˜K™—šŸœžœžœžœžœ žœžœžœžœ˜BKšœžœ ˜$Kšžœžœžœ ™4Kšœžœ˜Kšœžœžœ˜(Kšœm˜mšžœžœ žœ˜KšœL˜LKšžœ˜ Kšœ˜—Kšœ˜KšœA˜AKšœ˜šž˜Kšœžœ˜=—Kšœ˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜DKšœžœ ˜$Kšžœ!žœžœ ™6Kšœžœ˜Kšœžœžœ˜(Kšœm˜mšžœžœ žœ˜KšœL˜LKšžœ˜ Kšœ˜—KšœC˜Cšž˜Kšœžœ˜=—Kšœ˜K˜—šŸ œžœžœžœžœ žœžœ˜|Kšžœ™Kšœžœžœ˜ šœ žœ˜KšÐbkÏb¡ ™—Kšœžœ˜Kšœžœ˜Kšœ žœ˜Kšœžœ˜K˜šœžœžœžœ ˜;Kšœ žœ/˜;Kšœ4˜4Kšžœ˜ Kšœ˜—Kšœ žœ9˜EKšœ1˜1Kšžœž™ Kš¢˜Kšœ*˜*Kšœ ˜ Kš¢˜Kšœ1˜1Kšœ žœ3˜?Kšœ/˜/Kšœ žœ™'š žœ žœžœžœ F˜tKšœ žœ>˜IKšœ9˜9KšœQžœ˜WKšœžœžœ#žœS˜¦Kšœ˜—Kšœžœ˜4Kšœsžœ+žœ˜ªšž˜Kšœ)˜)—Kšœ ˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜DKšœžœ ˜$Kšžœ*žœžœ ™?KšœBžœ™WKšœžœ˜Kšœžœžœ˜ Kšœžœ˜Kšœžœžœ˜(Kšžœž ™Kšœžœ˜Kšœžœ˜Kšœ žœ˜Kšœžœ˜Kšœžœ ˜Kšœ žœ˜)Kšœx˜xKšžœžœ žœžœ˜Kšœžœžœ žœ˜@š œžœ"žœ žœžœ žœ ˜eKšœ žœ1˜=Kšžœžœ žœ5˜JKšžœ˜ Kšœ˜—Kšœžœ;˜AKš œ žœžœžœ žœžœ˜VKšœ žœ:˜FKšžœžœ žœ2˜GKšžœž™ Kš¢˜Kšœ6˜6Kšœ ˜ Kš¢˜Kšœ1˜1Kšœ žœ3˜?Kšžœžœ žœ0˜EKšœ žœ? ˜ZKšœ9˜9KšœQžœ˜WKšœžœžœ#žœS˜¦Kšœ˜Kšœžœ˜#šž˜šœ ˜ Kšœžœ ˜$Kšžœžœžœ!˜CKšœ˜——Kšœ˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜CKšœžœ ˜$Kšžœžœžœžœ3˜bšžœ˜KšœV˜VKšœ ˜ K˜—Kšœ˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜DKšœžœ˜&K˜—šŸœžœžœžœžœ žœžœžœžœ˜DKšœžœ ˜$Kšœžœ˜(Kšœ˜Kš¢P™Pšœžœ˜8Kšœ>™>—Kšœ˜Kšœ˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜DKšœžœ ˜$Kšœ˜Kšœžœ˜Kšœ ˜ Kšœ˜Kšœžœ˜#Kšœsžœ žœžœ˜¢Kšœ˜Kšœ  ˜K˜—š Ÿœžœ žœžœžœžœ˜;Kšœžœ˜!Kšœ-˜-Kšœ%˜%Kšœžœ˜.Kšœžœ˜/Kšœ#žœ˜>Kšœ!žœ !™IKšœžœžœ˜Kšœ˜—K˜K™šŸ œžœžœžœžœ žœžœžœžœ˜IKšœžœžœ˜Kšœ˜Kšœžœ ˜$Kš œ žœžœžœžœ$žœžœ˜lšžœžœžœžœ˜*KšœH˜HKšžœ˜K˜—Kšœ:˜:šžœSžœžœž˜fKšœ>˜>šžœOžœžœž˜bKšœ žœžœ˜šžœžœžœžœžœžœžœž˜BKšœžœžœ ˜)šžœžœžœ˜+Kšœ žœ ˜*Kšžœ˜K˜—Kšžœ˜—Kšžœžœ žœ$žœ˜EKšœžœ˜Kšžœ˜—Kšžœ˜—Kšœ)žœžœ'žœ<˜¤šœ˜K˜——šŸ œžœžœžœžœ žœžœžœžœ˜JKšœžœ ˜$Kš œ žœžœžœžœ$žœžœ˜lKšœ<˜˜>šžœOžœžœž˜bKšœ žœ˜šžœžœžœžœžœžœžœž˜BKšœžœžœ ˜)Kšžœžœžœžœ"žœ žœžœ˜wKšžœ˜—Kšœ˜Kšžœ˜—Kšžœ˜—Kšœ)žœ žœ+žœG˜²šœ˜K˜——šŸœžœžœžœžœ žœžœžœžœ˜TKš œ žœžœžœžœ˜Kšœ˜Kšœžœ ˜$šžœ-žœ˜5KšœO˜OKšžœ˜K˜—Kšœ:˜:šžœSžœžœž˜fKšœ>˜>šžœOžœžœž˜bšžœžœžœžœžœžœžœž˜BKšœžœžœ ˜)Kšœ žœžœ˜šžœžœžœžœžœžœžœž˜EKšœžœžœ˜+šžœ!žœžœ˜0Kšœ žœ ˜.Kšžœ˜K˜—Kšžœ˜—K•StartOfExpansion4[l1: LIST OF REF ANY, l2: LIST OF REF ANY _ NIL]šžœžœ žœ$žœ ˜IKšžœ˜—Kšžœ˜—Kšžœ˜—šžœ žœžœ˜Kšœ@˜@šžœžœžœžœžœžœžœž˜EKšœžœžœ˜+KšœB˜BKšžœ˜—Kšœ*˜*Kšœ˜—KšžœE˜IKšœ˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜MKš œ žœžœžœžœ˜Kšœžœ ˜$Kšœ<˜<šžœCžœžœž˜YKšœ;˜;šžœOžœžœž˜bšžœžœžœžœžœžœžœž˜BKšœžœžœ ˜)Kšœ žœžœ˜šžœžœžœžœžœžœžœž˜EKšœžœžœ˜+šžœ!žœžœ˜0Kšœ žœ ˜.Kšžœ˜K˜—Kšžœ˜—K–4[l1: LIST OF REF ANY, l2: LIST OF REF ANY _ NIL]šžœžœ žœ$žœ ˜IKšžœ˜—Kšžœ˜—Kšžœ˜—šžœ žœžœ˜Kšœ4˜4šžœžœžœžœžœžœžœž˜EKšœžœžœ˜+KšœB˜BKšžœ˜—Kšœ*˜*Kšœ˜—Kšžœ9˜=Kšœ˜—K˜K™KšŸœžœžœ˜ šŸœžœžœžœžœ žœžœžœžœ˜UKšœžœ ˜$KšžœžœI˜iK˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜UKšœžœ ˜$KšžœžœI˜iK˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜WKšœžœ ˜$šžœžœ˜"Kšœ3 ˜Hšžœžœžœ˜Kšœ%žœ˜*Kšœ˜Kšœ˜—KšžœJ˜NKšœ˜—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜WKšœžœ ˜$šžœžœ˜"Kšœ3 ˜Hšžœžœžœ˜Kšœ%žœ˜*Kšœ˜Kšœ˜—KšžœJ˜NKšœ˜—K˜K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜SKšœžœ ˜$šžœžœ˜"Kšœžœ˜Kšœ˜K–=[rgb: RGB, calibration: ImagerColor.RGBCalibration _ NIL]šœW˜WKšœE˜EKšœ6˜6šžœžœžœ˜Kšœ1˜1Kšœ*žœ˜/K˜—KšžœO˜SK˜—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜SKšœžœ ˜$šžœžœ˜"Kšœžœ˜Kšœ˜K–=[rgb: RGB, calibration: ImagerColor.RGBCalibration _ NIL]šœW˜WKšœE˜EKšœF˜Fšžœžœžœ˜Kšœ1˜1Kšœ*žœ˜/K˜—KšžœQ˜UK˜—K˜K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜XKšœžœ ˜$Kš œ žœžœžœžœ$žœžœ˜lšœe˜eKšœžœ˜0Kšœžœ ˜*K˜—Kšœ˜šž˜Kšœ(žœQžœ!˜¦Kšœ%žœKžœ!˜—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜XKšœžœ ˜$Kš œ žœžœžœžœ$žœžœ˜lšœe˜eKšœžœ˜0Kšœžœ ˜*K˜—Kšœ˜šž˜Kšœ(žœQžœ!˜¦Kšœ%žœKžœ!˜—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜WKšœžœ ˜$Kš œ žœžœžœžœ$žœžœ˜lKšœVžœ˜iKšœ˜šž˜Kšœ&žœtžœ!˜Ç—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜WKšœžœ ˜$Kš œ žœžœžœžœ$žœžœ˜lKšœVžœ˜iKšœ˜šž˜Kšœ&žœtžœ!˜Ç—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ™VKšœžœ ™$Kšœžœ™Kš œ žœžœžœžœ$žœžœ™lKšœK™KKšœ žœžœ™1š žœžœ žœžœ ž™3šœ™Kšœ6™6Kšœžœ™0Kšœžœ ™*K™—šœ™Kšœ'žœ ™8—Kšžœžœ™—Kšœ+™+š žœ žœžœ@žœ žœž™hšžœžœž™™Kšœ>™>Kšžœ*žœ=™mK™—™Kšœ:™:Kšžœ*žœ2žœ#™ˆK™—Kšžœžœ™—Kšžœ™—K–Û[feedback: ViewerClasses.Viewer, msgType: GGError.MsgType, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šœc™cKšœmžœ žœžœ™œšž™Kšœ&žœtžœ!™ÇKšœ(žœQžœ!™¦Kšœ%žœKžœ!™—K™K™—šŸœžœžœžœžœ žœžœžœžœ˜VKšœžœ ˜$Kšœžœ˜Kš œ žœžœžœžœ$žœžœ˜lKšœG˜GKšœ žœžœ˜1š žœžœ žœžœ ž˜3šœ˜Kšœ6˜6Kšœžœ˜0Kšœžœ ˜*K˜—šœ˜Kšœ'žœ ˜8—Kšžœžœ˜—Kšœ+˜+šžœIžœ žœž˜`Kšœ:˜:Kšžœ*žœ9˜iKšžœ˜—K–Û[feedback: ViewerClasses.Viewer, msgType: GGError.MsgType, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šœc˜cKšœmžœ žœžœ˜œšž˜Kšœ&žœtžœ!˜ÇKšœ(žœQžœ!˜¦Kšœ%žœKžœ!˜—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜VKšœžœ ˜$Kšœžœ˜Kš œ žœžœžœžœ$žœžœ˜lKšœ<™KšœF™FKšœ3™3Kšœ™—Kšžœ™—Kšžœ™—š žœIžœ žœžœ ˜€šŸ œ˜Kš ¢œžœžœžœžœ™:Kšœžœ,˜3K˜—KšœB %˜gK–s[sliceD: GGModelTypes.SliceDescriptor, scene: GGModelTypes.Scene, selectClass: GGSegmentTypes.SelectionClass]šœ4 ˜DKšžœ˜—K–Û[feedback: ViewerClasses.Viewer, msgType: GGError.MsgType, format: ROPE _ NIL, v1: IO.Value _ [null[]], v2: IO.Value _ [null[]], v3: IO.Value _ [null[]], v4: IO.Value _ [null[]], v5: IO.Value _ [null[]]]šœa˜aKšœmžœ žœžœ˜œšž˜Kšœ&žœtžœ!˜ÇKšœ(žœQžœ!˜¦Kšœ%žœKžœ!˜—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜RKšœžœ ˜$Kšœ˜KšœW˜WKšžœžœžœ7žœžœ,žœžœm˜ôšžœ˜Kšœžœ˜Kšœžœ˜Kšœžœ@˜dšžœžœžœ˜Kšœ/˜/Kšžœžœ$˜@Kšžœžœ-žœ ˜XKšžœ˜šœ˜Kšœ˜KšžœÖ˜ØKšœ ˜ —K˜—KšžœJ˜NK˜$K˜—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜RKšœžœ ˜$Kšœ˜KšœW˜WKšžœžœžœ7žœžœ,žœžœt˜ûšžœ˜Kšœžœ˜Kšœžœ˜Kšœ˜šžœ"žœ2žœ˜_Kšœl˜lKšžœ˜Kšœ˜—Kšžœ žœ0˜Cšžœžœžœ˜Kšœ/˜/Kšžœžœ$˜@Kšžœžœ-žœ ˜XKšžœ˜šœ˜Kšœ˜KšžœÔ˜ÖKšœ ˜ —K˜—KšžœH˜LK˜"K˜—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜SKšœžœ ˜$Kšœžœ˜Kšœžœ˜Kšœžœ˜Bšžœžœžœ˜Kšœ/˜/Kšžœžœ$˜@Kšžœžœ-žœ ˜XKšžœ˜šœ˜Kšœ˜KšžœÖ˜ØKšœ ˜ —K˜—KšžœJ˜NK˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜SKšœžœ ˜$Kšœžœ˜Kšœžœ˜Kšœžœ˜@šžœžœžœ˜Kšœ/˜/Kšžœžœ$˜@Kšžœžœ-žœ ˜XKšžœ˜šœ˜Kšœ˜KšžœÔ˜ÖKšœ ˜ —K˜—KšžœH˜LK˜—K˜šŸœžœžœžœžœ žœžœžœžœ˜MKšœžœ ˜$Kšœ#˜#K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜MKšœžœ ˜$Kšœ#˜#K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜MKšœžœ ˜$Kšœ˜Kšœžœ˜KšœW˜WKšžœžœžœ7žœžœ,žœžœa˜èšžœ˜Kšœžœ˜Kšœžœ0˜Tšžœžœžœ˜Kšœ/˜/Kšžœžœ$˜@Kšžœžœ-žœ ˜XKšžœ˜šœ˜Kšœ˜KšžœÀ˜ÂKšœ ˜ —K˜—Kšžœ=˜AK˜—K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜MKšœžœ ˜$Kšœ˜Kšœžœ˜KšœW˜WKšžœžœžœ7žœžœ,žœžœa˜èšžœ˜Kšœžœ˜Kšœžœ@˜dšžœžœžœ˜Kšœ1˜1Kšžœžœ$˜@Kšžœžœ-žœ ˜XKšžœ˜šœ˜Kšœ˜Kšžœ¿˜ÁKšœ ˜ —K˜—Kšžœ?˜CK˜—K˜K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜MKšœžœ ˜$Kšœ#˜#K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜MKšœžœ ˜$Kšœ#˜#K˜K˜—šŸ œžœžœžœžœ žœžœžœžœ˜LKšœžœ ˜$Kšœ*˜*K˜K˜—šŸ œžœžœžœžœ žœžœžœžœ˜LKšœžœ ˜$Kšœ*˜*K˜K˜—šŸ œžœžœžœžœ žœžœžœžœ˜LKšœžœ ˜$Kšœ žœ ˜K˜K˜—šŸ œžœžœžœžœ žœžœžœžœ˜LKšœžœ ˜$Kšœ žœ ˜K˜K˜K˜—šŸ œžœ#žœžœ˜AKšœžœ ˜$KšœW˜Wšžœržœžœž˜ˆKšœ5˜5Kšžœ˜—Kšœqžœ žœžœ˜ŸK˜K˜—šŸ œžœ#žœžœ˜AKšœžœ ˜$KšœW˜Wšžœržœžœž˜ˆKšœE˜EKšžœ˜—Kšœqžœ žœžœ˜ŸK˜K™—š Ÿœžœžœžœžœžœ˜JKš žœžœžœžœžœ˜LKšœd˜dK˜K˜—š Ÿœžœžœ!žœžœžœ˜cKšœ žœ ˜Kš žœžœžœžœ  ,˜QKš žœ žœžœžœ )˜Išžœ˜Kšœ žœ˜Kšœ&˜&Kšžœ žœ žœ žœžœžœžœžœžœ˜xK˜—K˜K˜—š Ÿ œžœ žœžœžœ˜FKšžœžœžœžœ ˜1šŸœžœžœ˜Kš žœžœžœ žœžœ˜4K˜—Kš œžœžœžœžœ˜Kšžœžœžœ ˜3Kšžœžœžœ ˜&K˜/Kšžœžœžœ ˜3Kšžœžœžœ ˜&K˜/Kšžœžœžœ ˜3Kšžœžœžœ ˜&K˜K˜)šž˜Kšœ žœ˜$—K˜—K˜K™ šŸœžœžœžœžœ žœžœžœžœ˜OK˜—šŸœžœžœžœžœ žœžœžœžœ™OKšœžœ ™$K™ÄKšœ2™2Kšœ™Kšœžœ™ Kšœ žœ™Kšœ&™&Kšœ"™"Kšœ(™(K™K™Kšœžœ™ Kšœ4™4Kšœ4™4Kšœ,™,Kšœgžœ žœžœ™–Kšœ™Kšœžœ 3™Yšžœž™šžœžœ™%Kšœžœ™$Kšžœ™K™—Kšœ"™"Kšœ"™"K™KšœK™KKš¢œ ™%Kšœ)™)Kšœ'™'Kšœ6¢œPžœ™”šžœ žœ™šžœžœžœž™Kš¢œ ™$Kšžœ)žœžœ™:Kšœižœ žœžœ™˜Kšœ6™6šž™šœ ™ Kšžœž™ Kšœfžœ žœžœ™•K™——Kšžœ™—K™—šžœ™Kšœfžœ žœžœ™•K™—K™Kšžœ™—Kšœ™K™K™—šŸ œžœžœžœžœ žœžœžœžœ˜JKšœžœ ˜$K™ÄKšœ2˜2Kš œžœžœžœžœ˜7Kšœ˜Kšœžœ˜ Kšœ3žœ˜;Kšœ˜Kšœ&˜&K˜K˜K˜Kšžœžœžœ˜ Kšœ4˜4Kšœ4˜4Kšœ™Kšœ™Kšœžœ 3˜Yšžœž˜#šžœžœ˜%Kšœžœ˜$Kšžœ˜K˜—Kšœ"˜"Kšœ"˜"K˜KšœK˜KKš¢%˜%Kšœ)˜)Kšœ'˜'Kšœ#¢œLžœ˜{K–Ò[testPoint: GGBasicTypes.Point, criticalR: REAL, currentObjects: GGMultiGravity.ObjectBag, activeObjects: GGMultiGravity.TriggerBag, gargoyleData: GGInterfaceTypes.GargoyleData, intersections: BOOL]šœ¢œLžœ˜š žœžœžœžœžœ˜1Kšœfžœ žœžœ˜•K˜Kšžœ˜K˜—šžœžœžœžœžœžœ%žœžœ˜KšœY˜YK˜K˜Kšžœžœžœ#˜=Kšžœžœžœ˜7K˜—šžœ˜Kšœ"˜"Kšœ˜K˜Kšœ%˜%Kšœižœ žœžœ˜˜K˜—Kšžœ˜—KšœÏ˜ÏKšœ ˜K˜—Kšœžœžœ˜šŸœžœ˜šKšœžœ˜šžœžœžœ˜KšœE˜EKšžœžœ£˜»Kšœ%˜%K˜—šžœžœžœžœ˜!KšœA˜AKšžœžœ˜µKšœ#˜#K˜—šžœžœžœ˜(KšœE˜EKšœA˜AKšžœžœ­˜ÅKšœ%˜%K˜—šžœžœ%žœ˜2Kšžœžœ„˜œKšœ%˜%K˜—šžœžœžœ˜$KšœE˜EKšœA˜AKšžœžœ«˜ÃKšœ#˜#Kšœlžœ žœžœ˜›Kšœ%˜%K˜—Kšžœžœ˜ Kšœlžœ žœžœ˜›K˜K˜—šŸ œžœžœžœžœ žœžœžœžœ˜IKšœžœ ˜$Kšœžœžœ+˜7Kšœ7˜7K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜UKšœžœ ˜$Kšœžœžœ˜3Kšœžœ˜)Kšœžœžœ+˜7Kšœ'˜'K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜NKšœžœ ˜$Kšœ4˜4K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜NKšœžœ ˜$Kšœmžœ žœžœ˜›K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜MKšœžœ ˜$Kšœlžœ žœžœ˜šK˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜MKšœžœ ˜$Kšœlžœ žœžœ˜šK˜K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜OKšœžœ ˜$Kšœnžœ žœžœ˜œK˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜OKšœžœ ˜$Kšœnžœ žœžœ˜œK˜K˜—šŸ œžœžœžœžœ žœžœžœžœ˜LKšœžœ ˜$Kšœžœžœ˜!Kšœ`žœ žœžœ˜ŽK˜K™—šŸœžœžœžœžœ žœžœžœžœ˜RKšœžœ ˜$Kšœžœ˜%Kšœžœžœ˜Kšœ'˜'šžœ žœžœ˜šžœžœž˜˜ Kšœ6˜6K˜—˜Kšœ2˜2K˜—Kšžœžœ˜—K˜—Kšœ!žœ:˜]K˜K˜—šŸœžœžœžœžœ žœžœžœžœ˜GKšœžœ ˜$KšœT™TK˜—K˜šŸ œžœžœžœžœ žœžœžœžœ˜IKšœD˜DK˜K˜—Kšœ& ˜:Kšœ' ˜;K˜šŸœžœ ˜*Kšœ9 m˜¦Kšœ8 m˜¥Kšœ˜—K˜Kšœ˜K˜Kšžœ˜—…—®²™