DIRECTORY BasicTime, CubicSplines, FS, GGAlign, GGButtons, GGCaret, GGDescribe, GGDrawProcess, GGError, GGEvent, GGGraphicsButton, GGGravity, GGInterfaceTypes, GGModelTypes, GGObjects, GGRefresh, GGSegment, GGSelect, GGTouch, GGVector, GGViewerOps, GGWindow, Imager, ImagerColor, ImagerInterpress, IO, Random, Real, Rope, Rosary, TiogaButtons, ViewerClasses, ViewerIO, ViewerOps, ViewerTools; GGEventImpl: CEDAR PROGRAM IMPORTS BasicTime, FS, GGAlign, GGButtons, GGCaret, GGDescribe, GGDrawProcess, GGError, GGGraphicsButton, GGGravity, GGObjects, GGRefresh, GGSegment, GGSelect, GGTouch, GGVector, GGViewerOps, GGWindow, Imager, ImagerColor, ImagerInterpress, IO, Random, Real, Rope, Rosary, TiogaButtons, ViewerIO, ViewerOps, ViewerTools EXPORTS GGEvent = BEGIN Cluster: TYPE = GGModelTypes.Cluster; EntityGenerator: TYPE = GGModelTypes.EntityGenerator; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; Outline: TYPE = GGModelTypes.Outline; Point: TYPE = GGModelTypes.Point; ScalarButtonClient: TYPE = GGInterfaceTypes.ScalarButtonClient; Segment: TYPE = GGModelTypes.Segment; Sequence: TYPE = GGModelTypes.Sequence; Traj: TYPE = GGModelTypes.Traj; TrajGenerator: TYPE = GGModelTypes.TrajGenerator; TwoState: TYPE = GGInterfaceTypes.TwoState; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; SequenceGenerator: TYPE = GGModelTypes.SequenceGenerator; Vector: TYPE = GGModelTypes.Vector; Viewer: TYPE = ViewerClasses.Viewer; Clear: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Reset: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Get: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Store: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Split: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Interpress: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { ipRef: ImagerInterpress.Ref; wdir, ipName, fullName: Rope.ROPE; success: BOOL; pixelsPerMeter: REAL _ 0.0254 / 72.0; startTime: BasicTime.GMT; endTime: BasicTime.GMT; totalTime: INT; msgRope: Rope.ROPE; DoMakeInterpress: PROC [dc: Imager.Context] = { Imager.ScaleT[dc, pixelsPerMeter]; GGRefresh.InterpressEntireScene[dc, gargoyleData]; }; ipName _ ViewerTools.GetSelectionContents[]; IF Rope.Length[ipName] = 0 THEN RETURN; wdir _ gargoyleData.originalWorkingDirectory; success _ TRUE; [fullName,,] _ FS.ExpandName[ipName, wdir ! FS.Error => IF error.group = user THEN { success _ FALSE; CONTINUE; } ]; IF NOT success THEN RETURN; ipRef _ ImagerInterpress.Create[fullName]; msgRope _ IO.PutFR["Writing to interpress file: %g . . . ", [rope[fullName]]]; GGError.Append[msgRope, begin]; startTime _ BasicTime.Now[]; ImagerInterpress.DoPage[ipRef, DoMakeInterpress, 1.0]; ImagerInterpress.Close[ipRef]; endTime _ BasicTime.Now[]; totalTime _ BasicTime.Period[startTime, endTime]; msgRope _ IO.PutFR[" Done in time (%r)", [integer[totalTime]]]; GGError.Append[msgRope, end]; }; Delete: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { parentOutline: Outline; entityGen: EntityGenerator; entityGen _ GGSelect.SelectedEntities[gargoyleData, normal]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO GGSelect.DeselectEntity[entity, gargoyleData, normal]; GGSelect.DeselectEntity[entity, gargoyleData, copy]; GGSelect.DeselectEntity[entity, gargoyleData, hot]; GGSelect.DeselectEntity[entity, gargoyleData, active]; WITH entity SELECT FROM cluster: Cluster => ERROR NotYetImplemented; outline: Outline => { GGObjects.DeleteOutline[gargoyleData.scene, outline]; GGTouch.OutlineDeleted[outline, gargoyleData]; }; seq: Sequence => { parentOutline _ GGObjects.OutlineOfTraj[seq.traj]; IF GGObjects.HasHoles[parentOutline] THEN { SELECT seq.traj.role FROM hole => ERROR NotYetImplemented; open => ERROR; -- impossible since the outline has holes fence => { GGError.Append["You can't delete the fence trajectory of an outline with holes.", oneLiner]; LOOP; }; ENDCASE => ERROR; } ELSE { IF seq.all THEN { -- the whole trajectory is selected GGObjects.DeleteOutline[gargoyleData.scene, parentOutline]; GGTouch.OutlineDeleted[parentOutline, gargoyleData]; } ELSE { -- part of a trajectory is selected. Remove the parts in a sensible fashion. This may require breaking up the trajectory into pieces. Remove all of the pieces from touching lists. ERROR NotYetImplemented; }; }; }; ENDCASE => ERROR; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; SelectAll: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGSelect.DeselectAll[gargoyleData, normal]; GGSelect.SelectAll[gargoyleData, normal]; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; NotYetImplemented: PUBLIC SIGNAL = CODE; SetStraight: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segmentGen: SegmentGenerator; traj: Traj; newSeg: Segment; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO segmentGen _ GGObjects.SegmentsInSequence[seq]; traj _ seq.traj; FOR next: GGObjects.SegAndIndex _ GGObjects.NextSegmentAndIndex[segmentGen], GGObjects.NextSegmentAndIndex[segmentGen] UNTIL next.seg = NIL DO newSeg _ GGSegment.MakeLine[next.seg.lo, next.seg.hi]; AddSegment[traj, newSeg, next]; ENDLOOP; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; SetArc: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segmentGen: SegmentGenerator; traj: Traj; newSeg: Segment; p0, p1, p2: Point; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO segmentGen _ GGObjects.SegmentsInSequence[seq]; traj _ seq.traj; FOR next: GGObjects.SegAndIndex _ GGObjects.NextSegmentAndIndex[segmentGen], GGObjects.NextSegmentAndIndex[segmentGen] UNTIL next.seg = NIL DO p0 _ next.seg.lo; p2 _ next.seg.hi; p1 _ GetPt[p0, GGVector.Sub[p2,p0], GGVector.Distance[p0,p1]]; newSeg _ GGSegment.MakeArc[p0, p1, p2]; AddSegment[traj, newSeg, next]; ENDLOOP; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; SetConic: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segmentGen: SegmentGenerator; traj: Traj; newSeg: Segment; p0, p1, p2: Point; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO segmentGen _ GGObjects.SegmentsInSequence[seq]; traj _ seq.traj; FOR next: GGObjects.SegAndIndex _ GGObjects.NextSegmentAndIndex[segmentGen], GGObjects.NextSegmentAndIndex[segmentGen] UNTIL next.seg = NIL DO p0 _ next.seg.lo; p2 _ next.seg.hi; p1 _ GetPt[p0, GGVector.Sub[p2,p0], GGVector.Distance[p0,p1]]; newSeg _ GGSegment.MakeConic[p0, p1, p2, 0.7]; AddSegment[traj, newSeg, next]; ENDLOOP; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; random: Random.RandomStream _ Random.Create[10000,0]; NewV: PROC RETURNS[REAL] = {RETURN[Random.NextInt[random]/10000.0]}; GetPt: PROC[p0, dir: Point, maxL: REAL] RETURNS [pt: Point] = { scale1: REAL _ NewV[]*maxL; angle: REAL _ 180*NewV[]-90; --range -90..90 pt _ GGVector.Add[GGVector.Scale[GGVector.VectorPlusAngle[dir,angle], scale1], p0]; }; GetPtSequence: PROC[p0,p1: Point, n: NAT] RETURNS [CubicSplines.KnotSequence] ={ points: CubicSplines.KnotSequence _ NEW[CubicSplines.KnotSequenceRec[n+2]]; dir: Point _ GGVector.Sub[p1,p0]; inc: REAL _ GGVector.Distance[p0,p1]/(n-2); maxL: REAL _ inc; points[0] _ p0; FOR i: NAT IN [1..points.length-1) DO points[i] _ GetPt[p0, dir, maxL]; maxL _ maxL+inc; ENDLOOP; points[points.length-1] _ p1; RETURN[points]; }; AddSegment: PROC[traj: Traj, newSeg: Segment, next: GGObjects.SegAndIndex] = { traj.segments _ Rosary.Cat[ Rosary.Substr[traj.segments, 0, next.index], Rosary.FromItem[newSeg], Rosary.Substr[traj.segments, next.index+1, GGObjects.HiSegment[traj]-next.index] ]; }; SetBezier: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segmentGen: SegmentGenerator; traj: Traj; newSeg: Segment; p0, p1, p2, p3: Point; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO segmentGen _ GGObjects.SegmentsInSequence[seq]; traj _ seq.traj; FOR next: GGObjects.SegAndIndex _ GGObjects.NextSegmentAndIndex[segmentGen], GGObjects.NextSegmentAndIndex[segmentGen] UNTIL next.seg = NIL DO length: REAL _ GGVector.Distance[next.seg.lo, next.seg.hi]; dir: Point _ GGVector.Sub[p3,p0]; p0 _ next.seg.lo; p1 _ GetPt[p0, dir,length*0.7]; p2 _ GetPt[p0, dir,length]; p3 _ next.seg.hi; newSeg _ GGSegment.MakeBezier[p0, p1, p2, p3]; AddSegment[traj, newSeg, next]; ENDLOOP; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; SetSpline: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segmentGen: SegmentGenerator; traj: Traj; newSeg: Segment; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR seq: Sequence _ GGObjects.NextSequence[seqGen], GGObjects.NextSequence[seqGen] UNTIL seq = NIL DO segmentGen _ GGObjects.SegmentsInSequence[seq]; traj _ seq.traj; FOR next: GGObjects.SegAndIndex _ GGObjects.NextSegmentAndIndex[segmentGen], GGObjects.NextSegmentAndIndex[segmentGen] UNTIL next.seg = NIL DO length: REAL _ GGVector.Distance[next.seg.lo, next.seg.hi]; type: CubicSplines.SplineType _ naturalAL; nKnots: INT _ Real.RoundLI[10*NewV[]]; cps: CubicSplines.KnotSequence _ GetPtSequence[next.seg.lo, next.seg.hi, nKnots]; newSeg _ GGSegment.MakeCubicSpline[cps, type]; AddSegment[traj, newSeg, next]; ENDLOOP; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; Close: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { traj: Traj; firstPoint, lastPoint: Point; seg: Segment; [traj,----,----,----,----] _ GGCaret.GetChair[gargoyleData.caret]; IF traj = NIL THEN { GGError.Append["There is no caret trajectory to close.", oneLiner]; GGError.Blink[]; RETURN; }; GGError.Append["The caret trajectory will be closed.", oneLiner]; firstPoint _ GGObjects.FetchJointPos[traj, 0]; lastPoint _ GGObjects.LastJointPos[traj]; seg _ GGSegment.MakeLine[lastPoint, firstPoint]; GGObjects.CloseWithSegment[traj, seg, lo]; GGObjects.SetFillColor[GGObjects.OutlineOfTraj[traj], Imager.MakeGray[0.5]]; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; TestGravity: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { xRandomStream, yRandomStream: Random.RandomStream; testPoint: Point; x, y: INT; totalCount: NAT _ 0; s: IO.STREAM; resultPoint: Point; feature: REF ANY; countRope: Rope.ROPE; environ: GGGravity.ObjectBag; xRandomStream _ Random.Create[gargoyleData.actionArea.cw]; yRandomStream _ Random.Create[gargoyleData.actionArea.ch]; environ _ GGGravity.CreateObjectBag[]; GGAlign.AddItemsForAction[gargoyleData, environ, $SelectPoint]; IF environ = NIL THEN { GGError.Append["Add some trajectories to test gravity.", oneLiner]; GGError.Blink[]; RETURN; }; gargoyleData.hitTest.environ _ environ; GGWindow.Painter[$PaintAlign, gargoyleData]; gargoyleData.hitTest.hitCount _ 0; UNTIL totalCount > 1000 DO IF gargoyleData.aborted THEN { gargoyleData.aborted _ FALSE; EXIT; }; x _ Random.NextInt[xRandomStream]; y _ Random.NextInt[yRandomStream]; testPoint _ [x, y]; testPoint _ GGWindow.ScreenToWorld[testPoint, gargoyleData.camera]; gargoyleData.refresh.spotPoint _ testPoint; [resultPoint, feature] _ GGGravity.Map[testPoint, gargoyleData.hitTest.tolerance, environ, gargoyleData]; IF feature # NIL THEN { gargoyleData.refresh.hitPoint _ resultPoint; GGWindow.Painter[$PaintHitLine, gargoyleData]; gargoyleData.hitTest.hitCount _ gargoyleData.hitTest.hitCount + 1; } ELSE { GGWindow.Painter[$PaintSpot, gargoyleData]; }; totalCount _ totalCount + 1; ENDLOOP; s _ IO.ROS[]; s.PutF["Tested %g total points. %g were hits", [integer[totalCount]], [integer[gargoyleData.hitTest.hitCount]]]; countRope _ IO.RopeFromROS[s]; GGError.Append[countRope, oneLiner]; }; DrawTouchPoints: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGWindow.Painter[$PaintTouchPoints, gargoyleData]; }; DescribeTouchPoints: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGTouch.DescribeAllTouchPoints[gargoyleData]; }; DrawBoundBoxes: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGWindow.Painter[$PaintBoundBoxes, gargoyleData]; }; DrawSelectionBox: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGWindow.Painter[$PaintSelectionBox, gargoyleData]; }; Typescript: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { newViewer: Viewer; inHandle, outHandle: IO.STREAM; [inHandle, outHandle, newViewer] _ MakeNewViewerAndHandle[]; GGError.SetErrorStream[outHandle]; gargoyleData.debug.typescript _ newViewer; }; MakeNewViewerAndHandle: PRIVATE PROC [] RETURNS [in, out: IO.STREAM, newViewer: Viewer] = { newViewer _ ViewerOps.CreateViewer[ flavor: $TypeScript, info: [ name: "Gargoyle Script", menu: NIL, data: NIL, iconic: TRUE, column: right, scrollable: TRUE, icon: unInit ], paint: FALSE]; ViewerOps.SetOpenHeight[newViewer, 120]; ViewerOps.OpenIcon[icon: newViewer, closeOthers: FALSE, bottom: TRUE, paint: TRUE]; [in, out] _ ViewerIO.CreateViewerStreams["gargoyle script", newViewer, NIL, TRUE]; }; SlackLog: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGDrawProcess.OutputLog[]; }; DescribeCaretObject: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { chair: Traj; description, msgRope: Rope.ROPE; isJoint: BOOL; jointNum: NAT; seg: Segment; [chair, isJoint, ----, jointNum, seg] _ GGCaret.GetChair[gargoyleData.caret]; IF isJoint THEN { description _ GGDescribe.DescribeJoint[chair, jointNum]; } ELSE { segNum: INT; segNum _ GGObjects.IndexOfSegment[seg, chair]; IF segNum = -1 THEN description _ Rope.Concat["Nonexistent segment of ", GGDescribe.DescribeTraj[chair]] ELSE description _ GGDescribe.DescribeSegment[chair, segNum]; }; msgRope _ IO.PutFR["Caret is on %g.", [rope[description]]]; GGError.Append[msgRope, oneLiner]; }; LineWidth: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { strokeWidth: REAL; msgRope: Rope.ROPE; sequenceGen: SequenceGenerator; widthRef: REF INT _ NARROW[event.rest.first]; width: NAT _ widthRef^; strokeWidth _ width; msgRope _ IO.PutFR["Selected objects will have line width %g.", [real[strokeWidth]]]; GGError.Append[msgRope, oneLiner]; sequenceGen _ GGSelect.SelectedSequences[gargoyleData, normal]; FOR sequence: Sequence _ GGObjects.NextSequence[sequenceGen], GGObjects.NextSequence[sequenceGen] UNTIL sequence = NIL DO GGObjects.SetStrokeWidth[sequence, strokeWidth]; ENDLOOP; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; AreaColorBlack: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { outline: Outline; entityGen: EntityGenerator; entityGen _ GGSelect.SelectedEntities[gargoyleData, normal]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO WITH entity SELECT FROM seq: Sequence => outline _ GGObjects.OutlineOfTraj[seq.traj]; traj: Traj => outline _ GGObjects.OutlineOfTraj[traj]; o: Outline => outline _ o; cluster: Cluster => ERROR NotYetImplemented; ENDCASE => ERROR; GGObjects.SetFillColor[outline, Imager.black]; ENDLOOP; }; AreaColorWhite: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { outline: Outline; entityGen: EntityGenerator; entityGen _ GGSelect.SelectedEntities[gargoyleData, normal]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO WITH entity SELECT FROM seq: Sequence => outline _ GGObjects.OutlineOfTraj[seq.traj]; traj: Traj => outline _ GGObjects.OutlineOfTraj[traj]; o: Outline => outline _ o; cluster: Cluster => ERROR NotYetImplemented; ENDCASE => ERROR; GGObjects.SetFillColor[outline, Imager.white]; ENDLOOP; }; AreaColorGray: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { outline: Outline; entityGen: EntityGenerator; entityGen _ GGSelect.SelectedEntities[gargoyleData, normal]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO WITH entity SELECT FROM seq: Sequence => outline _ GGObjects.OutlineOfTraj[seq.traj]; traj: Traj => outline _ GGObjects.OutlineOfTraj[traj]; o: Outline => outline _ o; cluster: Cluster => ERROR NotYetImplemented; ENDCASE => ERROR; GGObjects.SetFillColor[outline, ImagerColor.ColorFromGray[0.5]]; ENDLOOP; }; MakeHot: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { entityGen: EntityGenerator; entityGen _ GGSelect.SelectedEntities[gargoyleData, normal]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO GGSelect.SelectEntity[entity, gargoyleData, hot]; ENDLOOP; }; MakeCold: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { entityGen: EntityGenerator; entityGen _ GGSelect.SelectedEntities[gargoyleData, normal]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO GGSelect.DeselectEntity[entity, gargoyleData, hot]; ENDLOOP; }; DropAnchor: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGCaret.Copy[gargoyleData.anchor, gargoyleData.caret]; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; KillAnchor: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGCaret.Kill[gargoyleData.anchor]; GGWindow.Painter[$PaintEntireScene, gargoyleData]; }; GravityChoiceChange: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { info: GGInterfaceTypes.EnumTypeRef _ gargoyleData.hitTest.gravityTypeMenu; name: Rope.ROPE; IF event.rest.first = $FlipForward THEN GGButtons.TimeToFlipThru[LIST[$FlipForward, info]] ELSE GGButtons.TimeToFlipThru[LIST[$FlipBackward, info]]; name _ info.flipLabel.name; SELECT TRUE FROM Rope.Equal[name, "StrictDistance", TRUE] => gargoyleData.hitTest.gravityType _ strictDistance; Rope.Equal[name, "PointsPreferred", TRUE] => gargoyleData.hitTest.gravityType _ innerCircle; Rope.Equal[name, "Sectors", TRUE] => gargoyleData.hitTest.gravityType _ sectors; Rope.Equal[name, "None", TRUE] => gargoyleData.hitTest.gravityType _ none; ENDCASE => ERROR; }; GravityExtentChange: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { value: REAL; msgRope: Rope.ROPE; graphicsState: GGGraphicsButton.GraphicsState _ gargoyleData.hitTest.gravityExtentButton; value _ GGGraphicsButton.GetValue[graphicsState]; SELECT event.rest.first FROM $ValueUp => { value _ value*2.0; msgRope _ IO.PutFR["Gravity extent is now %g screen dots.", [real[value]] ]; GGError.Append[msgRope, oneLiner]; GGGraphicsButton.SetButtonValueAndPaint[graphicsState, value]; }; $ValueDown => { value _ value/2.0; msgRope _ IO.PutFR["Gravity extent is now %g screen dots.", [real[value]] ]; GGError.Append[msgRope, oneLiner]; GGGraphicsButton.SetButtonValueAndPaint[graphicsState, value]; }; $InitialValue => {}; ENDCASE => ERROR; gargoyleData.hitTest.tolerance _ value; gargoyleData.hitTest.criticalR _ value; gargoyleData.hitTest.innerR _ value; }; ToggleAlwaysOn: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { stateInfo: TwoState _ gargoyleData.hitTest.linesAlwaysOn; GGButtons.SwitchState[stateInfo]; }; ToggleDoubleBuffer: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { stateInfo: TwoState _ gargoyleData.refresh.doubleBuffer; GGButtons.SwitchState[stateInfo]; }; SlopePrompt: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { viewer: Viewer _ gargoyleData.hitTest.slopeText; ViewerTools.SetSelection[viewer]; }; AddSlope: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { slope: REAL; thisButton: ScalarButtonClient; tiogaButton: TiogaButtons.TiogaButton; slope _ GGViewerOps.GetReal[gargoyleData.hitTest.slopeText, 90.0]; thisButton _ gargoyleData.hitTest.slopeButtons; UNTIL thisButton.next = NIL DO thisButton _ thisButton.next ENDLOOP; tiogaButton _ thisButton.button; [] _ GGButtons.AddScalarButton[tiogaButton, slope, LIST[$ToggleSlope, NEW[REAL _ slope]], FALSE, gargoyleData]; }; GetSlope: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segGen: SegmentGenerator; seq, next: Sequence; direction: Vector; degrees: REAL; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; seq _ GGObjects.NextSequence[seqGen]; next _ GGObjects.NextSequence[seqGen]; IF next # NIL THEN { GGError.Append["Select a single sequence for a GetSlope.", oneLiner]; GGError.Blink[]; }; segGen _ GGObjects.SegmentsInSequence[seq]; FOR seg: Segment _ GGObjects.NextSegment[segGen], GGObjects.NextSegment[segGen] UNTIL seg = NIL DO direction _ GGVector.VectorFromPoints[seg.lo, seg.hi]; degrees _ GGVector.AngleFromVector[direction]; IF degrees < 0.0 THEN degrees _ degrees + 180.0; BEGIN thisButton: ScalarButtonClient; tiogaButton: TiogaButtons.TiogaButton; thisButton _ gargoyleData.hitTest.slopeButtons; UNTIL thisButton.next = NIL DO thisButton _ thisButton.next ENDLOOP; tiogaButton _ thisButton.button; [] _ GGButtons.AddScalarButton[tiogaButton, degrees, LIST[$ToggleSlope, NEW[REAL _ degrees]], FALSE, gargoyleData]; END ENDLOOP; }; ToggleSlope: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { slope: REAL; firstButton, pushedButton: ScalarButtonClient; tiogaButton: TiogaButtons.TiogaButton; WITH event.rest.first SELECT FROM int: REF INT => slope _ int^; real: REF REAL => slope _ real^; ENDCASE => ERROR; firstButton _ gargoyleData.hitTest.slopeButtons; FOR thisButton: ScalarButtonClient _ firstButton, thisButton.next UNTIL thisButton = NIL DO IF thisButton.value = slope THEN { pushedButton _ thisButton; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; tiogaButton _ pushedButton.button; IF pushedButton.on THEN { pushedButton.on _ FALSE; TiogaButtons.ChangeButtonLooks[tiogaButton, "", "b"]; } ELSE { pushedButton.on _ TRUE; TiogaButtons.ChangeButtonLooks[tiogaButton, "b", ""]; }; }; DeleteSlope: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; RadiusPrompt: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { viewer: Viewer _ gargoyleData.hitTest.radiusText; ViewerTools.SetSelection[viewer]; }; AddRadius: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { radius: REAL; thisButton: ScalarButtonClient; tiogaButton: TiogaButtons.TiogaButton; radius _ GGViewerOps.GetReal[gargoyleData.hitTest.radiusText, 72.0]; thisButton _ gargoyleData.hitTest.radiusButtons; UNTIL thisButton.next = NIL DO thisButton _ thisButton.next ENDLOOP; tiogaButton _ thisButton.button; [] _ GGButtons.AddScalarButton[tiogaButton, radius, LIST[$ToggleRadius, NEW[REAL _ radius]], FALSE, gargoyleData]; }; GetRadius: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { seqGen: SequenceGenerator; segGen: SegmentGenerator; seq, next: Sequence; radius: REAL; seqGen _ GGSelect.SelectedSequences[gargoyleData, normal]; seq _ GGObjects.NextSequence[seqGen]; next _ GGObjects.NextSequence[seqGen]; IF next # NIL THEN { GGError.Append["Select a single sequence for a GetRadius.", oneLiner]; GGError.Blink[]; }; segGen _ GGObjects.SegmentsInSequence[seq]; FOR seg: Segment _ GGObjects.NextSegment[segGen], GGObjects.NextSegment[segGen] UNTIL seg = NIL DO radius _ GGVector.Distance[seg.lo, seg.hi]; BEGIN thisButton: ScalarButtonClient; tiogaButton: TiogaButtons.TiogaButton; thisButton _ gargoyleData.hitTest.radiusButtons; UNTIL thisButton.next = NIL DO thisButton _ thisButton.next ENDLOOP; tiogaButton _ thisButton.button; [] _ GGButtons.AddScalarButton[tiogaButton, radius, LIST[$ToggleRadius, NEW[REAL _ radius]], FALSE, gargoyleData]; END ENDLOOP; }; ToggleRadius: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { radius: REAL; firstButton, pushedButton: ScalarButtonClient; tiogaButton: TiogaButtons.TiogaButton; WITH event.rest.first SELECT FROM int: REF INT => radius _ int^; real: REF REAL => radius _ real^; ENDCASE => ERROR; firstButton _ gargoyleData.hitTest.radiusButtons; FOR thisButton: ScalarButtonClient _ firstButton, thisButton.next UNTIL thisButton = NIL DO IF thisButton.value = radius THEN { pushedButton _ thisButton; EXIT; }; REPEAT FINISHED => ERROR; ENDLOOP; tiogaButton _ pushedButton.button; IF pushedButton.on THEN { pushedButton.on _ FALSE; TiogaButtons.ChangeButtonLooks[tiogaButton, "", "b"]; } ELSE { pushedButton.on _ TRUE; TiogaButtons.ChangeButtonLooks[tiogaButton, "b", ""]; }; }; DeleteRadius: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = {}; Erase: PUBLIC PROC [event: LIST OF REF ANY, gargoyleData: GargoyleData] = { GGWindow.Painter[$EraseAll, gargoyleData]; }; END. ��¦��GGEventImpl.mesa Last edited by Bier on August 19, 1985 4:19:09 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. Stone, August 9, 1985 2:38:57 pm PDT File Operations TIMING VARIABLES The Painting Call START TIMING Master Menu Hierarchy Menu Curve Menu Choose a random p1: Choose a random p near the line p0, p2: Choose a random p1 and p2: Choose a random number of knots and positions: Edit Curve Menu Debug Menu 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. Style Operations Alignment Operations Doesn't properly handle end conditions. Assumes that some buttons already exist. Doesn't properly handle end conditions. Assumes that some buttons already exist. Miscellaneous �ÊÛ��˜�Ihead1™J™5™€Icode™$—J™�šÏk ˜ Jšœþ˜þJ˜�—šœ œ˜Jšœ¸˜¿Jšœ ˜—Jš˜J˜�Jšœ œ˜%Jšœœ ˜5Jšœœ!˜3Jšœ œ˜%Jšœœ˜!Jšœœ'˜?Jšœ œ˜%Jšœ œ˜'Jšœœ˜Jšœœ˜1Jšœ œ˜+Jšœœ!˜7Jšœœ"˜9Jšœœ˜#J˜$J˜�J™�J™J™�JšÏnœœœ œœœœ#˜MJšžœœœ œœœœ#˜MJšžœœœ œœœœ#˜KJšžœœœ œœœœ#˜MJšžœœœ œœœœ#˜MšÐbn œœœ œœœœ!˜PIprocšœ˜Mšœœ˜"Mšœ œ˜M˜%Jšœ™Jšœœ˜Jšœœ˜Jšœœ˜Jšœœ˜M™šžœœ˜/M˜"Mšœ2˜2M˜M˜�—Mšœ,˜,Jšœœœ˜'JšÏbœ)˜-Jšœ œ˜šœ œœ˜)šœœ œœ˜*Jšœ œ˜Jšœ˜ J˜—Jšœ˜—Jšœœ œœ˜Jšœ*˜*Jšœ œB˜NJšœ˜Jšœ™Jš ˜Jšœ6˜6Jšœ˜Jš ˜Jšœ1˜1Jšœ œ3˜?Jšœ˜M˜J˜�J˜�—J™�J™J˜�J™šžœœœ œœœœ!˜LM˜Mšœ˜Mšœ<˜<šœ œœDœ œ˜lMšœ6˜6Mšœ4˜4Mšœ3˜3Mšœ6˜6Mšœœ˜Mšœœ˜,šœ˜Mšœ5˜5Mšœ.˜.M˜—šœ˜Mšœ2˜2šœ#œ˜+Mšœ˜Mšœœ˜ MšœœÏc)˜8šœ ˜ Mšœ\˜\Mšœ˜M˜—Mšœœ˜Mšœ˜—šœ˜šœ œ¡#˜5Mšœ;˜;Mšœ4˜4M˜—šœ¡¶˜½Mšœ˜M˜—M˜—M˜—Mšœœ˜—Mšœ˜Jšœ2˜2J˜J˜�—šž œœ œœœœ!˜OMšœ+˜+Mšœ)˜)Jšœ2˜2M˜J˜�—Jšœœœœ˜(J™�J™ šžœœ œœœœ!˜QJ˜J˜J˜J˜Jšœ:˜:šœPœœ˜eJšœ/˜/Jšœ˜šœtœœ˜ŽJšœžœ˜6J˜—Jšœ˜—Jšœ˜Jšœ2˜2Jšœ˜—šžœœœ œœœœ!˜LJ˜J˜J˜J˜J˜Jšœ:˜:šœPœœ˜eJšœ/˜/Jšœ˜Jšœtœœ˜Ž™J˜J˜Jšœ>˜>Jšœžœ ˜'J˜—Jšœ˜—Jšœ˜Jšœ2˜2J˜—šžœœ œœœœ!˜NJ˜J˜J˜J˜J˜Jšœ:˜:šœPœœ˜eJšœ/˜/Jšœ˜šœtœœ˜ŽJ˜J˜Jšœ>˜>Jšœž œ˜.J˜—Jšœ˜—Jšœ˜Jšœ2˜2Jšœ˜—J˜�J˜5Jš žœœœœœ"˜DJ˜�šžœœœœ˜?J™'Jšœœ˜Jšœœ¡˜,J˜SJ˜—J˜�J˜�šž œœœœ˜PJšœ$œ$˜KJšœ!˜!Jšœœ"˜+Jšœœ˜J˜šœœœ˜%Jšœ!˜!J˜Jšœ˜—Jšœ˜Jšœ ˜J˜J˜�—šž œœ>˜NJšœµ˜µJ˜J˜�—šŸ œœ œœœœ!˜OJ˜J˜J˜J˜J˜Jšœ:˜:šœPœœ˜eJšœ/˜/Jšœ˜Jšœtœœ˜Ž™Jšœœ/˜;Jšœ!˜!J˜Jšœ˜Jšœ˜J˜Jšœž œ˜.J˜—Jšœ˜—Jšœ˜Jšœ2˜2J˜—šž œœ œœœœ!˜OJ˜J˜J˜J˜Jšœ:˜:šœPœœ˜eJšœ/˜/Jšœ˜Jšœtœœ˜Ž™.Jšœœ/˜;J˜*Jšœœ˜&JšœQ˜QJšœžœ˜.J˜—Jšœ˜—Jšœ˜Jšœ2˜2Jšœ˜—J™�J™šžœœœ œœœœ!˜KMšœ˜Mšœ˜M˜ MšœB˜Bšœœœ˜MšœC˜CMšœ˜Mšœ˜M˜—MšœA˜AMšœ.˜.Mšœ)˜)Mšœ0˜0Mšœ*˜*MšœL˜LJšœ2˜2M˜J˜�—J˜�J™�J™ šžœœœ œœœœ!˜QM™ÄMšœ2˜2Mšœ˜Mšœœ˜ Mšœœ˜Mšœœœ˜ Jšœ˜Jšœ œœ˜Mšœœ˜Mšœ˜Mšœ:˜:Mšœ:˜:Mšœ&˜&Mšœ?˜?šœœœ˜MšœC˜CM˜Mšœ˜M˜—Mšœ'˜'Mšœ,˜,Mšœ"˜"šœ˜šœœ˜Mšœœ˜Mšœ˜M˜—Mšœ"˜"Mšœ"˜"M˜MšœC˜CMšœ+˜+Mšœi˜išœœœ˜Mšœ,˜,Mšœ.˜.MšœB˜BM˜—šœ˜Mšœ+˜+M˜—M˜—Mšœ˜Mšœœœ˜ Mšœq˜qMšœœ˜Mšœ$˜$M˜M˜�—šžœœœ œœœœ!˜UJšœ2˜2J˜—šžœœœ œœœœ!˜YJšœ-˜-J˜—šžœœœ œœœœ!˜TJšœ1˜1J˜—šžœœœ œœœœ!˜VJšœ3˜3J˜—šž œœœ œœœœ!˜PJšœ˜Jšœœœ˜Jšœ<˜<Jšœ"˜"Jšœ*˜*Jšœ˜—šžœœœœœœ˜[˜#J˜Jšœ'œœ œœœ˜„—Jšœ(˜(Jšœ1œ œ œ˜SJšœGœœ˜RJšœ˜J˜�—šžœœ œœœœ!˜NJšœ˜J˜J˜�—šžœœœ œœœœ!˜YJ˜Jšœœ˜ Jšœ œ˜Jšœ œ˜J˜ Jšœ¡œ8˜Mšœ œ˜Jšœ8˜8J˜—šœ˜Jšœœ˜Jšœ.˜.Jšœ œU˜hJšœ9˜=J˜—Jšœ œ/˜;Jšœ"˜"J˜—J™�J™J™�šž œœœ œœœœ!˜OMšœ œ˜Mšœœ˜M˜Mšœ œœœ˜-Mšœœ ˜Mšœ˜Mšœ œI˜UMšœ"˜"Mšœ?˜?šœ_œœ˜yMšœ0˜0—Mšœ˜Jšœ2˜2J˜J˜�—M™�šžœœœ œœœœ!˜TM˜Mšœ˜Mšœ<˜<šœ œœDœ œ˜lMšœœ˜M˜=M˜6M˜Mšœœ˜,Mšœœ˜Mšœ.˜.—Mšœ˜M˜J˜�—šžœœ œœœœ!˜TM˜Mšœ˜Mšœ<˜<šœ œœDœ œ˜lMšœœ˜M˜=M˜6M˜Mšœœ˜,Mšœœ˜Mšœ.˜.—Mšœ˜M˜—šž œœ œœœœ!˜SM˜Mšœ˜Mšœ<˜<šœ œœDœ œ˜lMšœœ˜M˜=M˜6M˜Mšœœ˜,Mšœœ˜Mšœ@˜@—Mšœ˜M˜—M™�M™M™�šžœœœ œœœœ!˜MMšœ˜Mšœ<˜<šœ œœDœ œ˜lMšœ1˜1—Mšœ˜M˜—šžœœ œœœœ!˜NMšœ˜Mšœ<˜<šœ œœDœ œ˜lMšœ3˜3—Mšœ˜M˜M˜�—šž œœ œœœœ!˜PJšœ6˜6Jšœ2˜2J˜J˜�—šž œœ œœœœ!˜PJšœ"˜"Jšœ2˜2J˜—J™�šžœœœ œœœœ!˜YMšœJ˜JMšœœ˜šœ!˜'Mšœœ˜2—šœ˜Mšœœ˜4—Mšœ˜Mšœœ˜Mšœ#œ7˜^Mšœ$œ4˜\Mšœœ0˜PMšœœ-˜JMšœœ˜M˜M˜�—šžœœœ œœœœ!˜YMšœœ˜Mšœœ˜MšœY˜YMšœ1˜1Mšœ˜šœ œ˜ Mšœ˜Mšœ œ@˜LM˜"Mšœ>˜>M˜—šœ˜Mšœ˜Mšœ œ@˜LM˜"Mšœ>˜>M˜—M˜Mš œœ˜Mšœ'˜'Mšœ'˜'Mšœ$˜$M˜M˜�—šžœœ œœœœ!˜TMšœ9˜9Mšœ!˜!M˜—šžœœœ œœœœ!˜XMšœ8˜8Mšœ!˜!M˜—M˜�šžœœ œœœœ!˜QMšœ0˜0Mšœ!˜!Mšœ˜M˜�—šžœœ œœœœ!˜NM™QMšœœ˜Mšœ˜Mšœ&˜&MšœB˜BMšœ/˜/Mšœœœœ˜DMšœ ˜ Mš œ3œœœœ˜oM˜M˜�—šžœœœ œœœœ!˜NMšœ˜Mšœ˜Mšœ˜M˜Mšœ œ˜Mšœ:˜:Mšœ%˜%Mšœ&˜&šœœœ˜M˜EM˜M˜—Mšœ+˜+šœMœœ˜bM˜6Mšœ.˜.Mšœœ˜0š˜Mšœ˜Mšœ&˜&Mšœ/˜/Mšœœœœ˜DMšœ ˜ Mš œ5œœœœ˜s—Mš˜—Mšœ˜˜M˜�—M˜�—šžœœœ œœœœ!˜QMšœœ˜Mšœ.˜.Mšœ&˜&Mšœœ˜!Mšœœœ˜Mšœœœ˜ Mšœœ˜Mšœ0˜0šœ?œœ˜[šœœ˜"Mšœ˜Mšœ˜M˜——š˜Mšœœ˜—Mšœ˜Mšœ"˜"šœœ˜Mšœœ˜Mšœ5˜5M˜—šœ˜Mšœœ˜Mšœ5˜5M˜—M˜M˜�—Mšžœœ œœœœ#˜SM˜�šžœœ œœœœ!˜RMšœ1˜1Mšœ!˜!M˜M˜�—šž œœœ œœœœ!˜OM™QMšœœ˜ Mšœ˜Mšœ&˜&MšœD˜DMšœ0˜0Mšœœœœ˜DMšœ ˜ Mš œ4œœœ œ˜rM˜—šž œœ œœœœ!˜OMšœ˜Mšœ˜Mšœ˜Mšœœ˜ Mšœ:˜:Mšœ%˜%Mšœ&˜&šœœœ˜M˜FM˜M˜—Mšœ+˜+šœMœœ˜bMšœ+˜+š˜Mšœ˜Mšœ&˜&Mšœ0˜0Mšœœœœ˜DMšœ ˜ Mš œ4œœœ œ˜r—Mš˜—Mšœ˜Mšœ˜—šžœœœ œœœœ!˜RMšœœ˜ Mšœ.˜.Mšœ&˜&Mšœœ˜!Mšœœœ˜Mšœœœ˜!Mšœœ˜Mšœ1˜1šœ?œœ˜[šœœ˜#Mšœ˜Mšœ˜M˜——š˜Mšœœ˜—Mšœ˜Mšœ"˜"šœœ˜Mšœœ˜Mšœ5˜5M˜—šœ˜Mšœœ˜Mšœ5˜5M˜—M˜M˜�M˜�—Mšžœœœ œœœœ#˜T˜�M˜�—J™ J™�šžœœœ œœœœ!˜KJšœ*˜*Jšœ˜M˜�—J˜�Jšœ˜J˜�—�…—����b����