<> <> <> <> <> <> <<>> DIRECTORY Atom, BiScrollers, BufferedRefresh, CodeTimer, Feedback, FunctionCache, GGBasicTypes, GGBoundBox, GGCaret, GGGravity, GGInterfaceTypes, GGModelTypes, GGScene, GGRefresh, GGSegmentTypes, GGSelect, GGSequence, GGShapes, GGTraj, GGUtility, Imager, ImagerBackdoor, ImagerTransformation, Rope, Rosary, SlackProcess, TIPUser, Vectors2d, ViewerAbort, ViewerClasses; GGRefreshImpl: CEDAR MONITOR IMPORTS Atom, BiScrollers, BufferedRefresh, CodeTimer, Feedback, FunctionCache, GGBoundBox, GGCaret, GGGravity, GGScene, GGSelect, GGSequence, GGShapes, GGTraj, GGUtility, Imager, ImagerBackdoor, Rope, SlackProcess, Vectors2d, ViewerAbort EXPORTS GGRefresh = BEGIN BitVector: TYPE = GGBasicTypes.BitVector; BoundBox: TYPE = GGModelTypes.BoundBox; BoundBoxGenerator: TYPE = GGScene.BoundBoxGenerator; CameraData: TYPE = GGModelTypes.CameraData; Caret: TYPE = GGInterfaceTypes.Caret; Color: TYPE = Imager.Color; FeatureData: TYPE = GGGravity.FeatureData; OutlineDescriptor: TYPE = GGModelTypes.OutlineDescriptor; Rectangle: TYPE = Imager.Rectangle; Sandwich: TYPE = BufferedRefresh.Sandwich; Slice: TYPE = GGModelTypes.Slice; SliceParts: TYPE = GGModelTypes.SliceParts; SliceGenerator: TYPE = GGModelTypes.SliceGenerator; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = GGModelTypes.SliceDescriptorGenerator; EntityGenerator: TYPE = GGModelTypes.EntityGenerator; GGData: TYPE = GGInterfaceTypes.GGData; Joint: TYPE = GGModelTypes.Joint; JointGenerator: TYPE = GGModelTypes.JointGenerator; Outline: TYPE = GGModelTypes.Outline; Point: TYPE = GGBasicTypes.Point; Scene: TYPE = GGModelTypes.Scene; Segment: TYPE = GGSegmentTypes.Segment; SegAndIndex: TYPE = GGSequence.SegAndIndex; SegmentGenerator: TYPE = GGModelTypes.SegmentGenerator; Sequence: TYPE = GGModelTypes.Sequence; SelectionClass: TYPE = GGInterfaceTypes.SelectionClass; SequenceGenerator: TYPE = GGModelTypes.SequenceGenerator; Traj: TYPE = GGModelTypes.Traj; Vector: TYPE = GGBasicTypes.Vector; Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = CODE; ActionAreaPaint: PUBLIC PROC [screen: Imager.Context, whatHasChanged: ATOM, ggData: GGData] = TRUSTED { PaintWithAbort: PROC = TRUSTED { DoActionAreaPaint[screen, whatHasChanged, ggData ! UNWIND => { Feedback.Append[ggData.feedback, "Refresh Aborted", oneLiner]; SlackProcess.FlushQueue[ggData.slackHandle]; -- you have to do this HERE! ggData.refresh.suppressRefresh _ FALSE; -- in case you killed FastPlayback ggData.aborted _ ALL[TRUE]; -- copies of aborted for all purposes }; ]; }; IF whatHasChanged=$ViewersPaintEntireScene THEN ViewerAbort.CallWithAbortEnabled[ggData.actionArea, PaintWithAbort] ELSE DoActionAreaPaint[screen, whatHasChanged, ggData]; -- SlackProcess is watching for aborts }; DoActionAreaPaint: PROC [screen: Imager.Context, whatHasChanged: ATOM, ggData: GGData] = { <> <> <<>> showColors: BOOL _ ggData.refresh.showColors.state = on; IF ggData.aborted[refresh] THEN { -- last paint got killed => unknown bitmap cache states ggData.aborted[refresh] _ FALSE; PaintEntireScene[screen, ggData, showColors]; } ELSE SELECT whatHasChanged FROM $None => NULL; <> $PaintEntireScene, $ViewersPaintEntireScene => PaintEntireScene[screen, ggData, showColors]; $ViewersPaintAllPlanes => PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; $NewAlignmentsDeselected => PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; $NewAlignmentsSelected => PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; $SequencesMadeHot => PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; $SequencesMadeCold => PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; $Everything => PaintEntireScene[screen, ggData, showColors]; $SelectionChanged => PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; $FinishedAdding => FinishedAdding[screen, ggData, showColors]; $FinishedDragging => FinishedDragging[screen, ggData, showColors]; $CaretMoved => PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; -- GGMouseEventImplA $AnchorAdded => PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; -- GGEventImplB $AnchorRemoved => PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; -- GGEventImplB <> $DuringMotion => PaintDragOverlay[screen, ggData, TRUE, showColors]; -- GGMouseEventImplA $DuringCaretPos => PaintDragOverlay[screen, ggData, FALSE, showColors]; -- GGMouseEventImplA $DuringSelect => DuringSelect[screen, ggData, showColors]; $ObjectChangedInPlace => ObjectChangedInPlace[screen, ggData, normal, showColors]; $ObjectChangedBoundBoxProvided => ObjectChangedBoundBoxProvided[screen, ggData, showColors]; $ObjectAdded => ObjectAdded[screen, ggData, showColors]; <> $PaintSpot => PaintSpot[screen, ggData]; $PaintHitLine => PaintHitLine[screen, ggData]; $PaintOddHitLine => PaintOddHitLine[screen, ggData]; $PaintAlign => PaintAlign[screen, ggData]; $PaintBoundBoxes => PaintBoundBoxes[screen, ggData]; $PaintTightBoxes => PaintTightBoxes[screen, ggData]; $PaintOutlineBoxes => PaintOutlineBoxes[screen, ggData]; $PaintSelectionBox => PaintSelectionBox[screen, ggData]; $DrawBackgroundBox, $DrawOverlayBox, $DrawRubberBox, $DrawDragBox => DrawMovingBox[screen, ggData, whatHasChanged]; ENDCASE => { Feedback.Append[ggData.feedback, Rope.Cat["Gargoyle GGRefreshImpl doesn't know how to ", Atom.GetPName[whatHasChanged], "."], oneLiner]; Feedback.Blink[ggData.feedback]; }; }; << [Artwork node; type 'ArtworkInterpress on' to command tool] >> CreateSandwich: PUBLIC PROC [] RETURNS [sandwich: Sandwich] = { sandwich _ BufferedRefresh.CreateSandwich[LIST[ [$Background, TRUE, RefreshBackground], -- back ... [$Overlay, FALSE, RefreshOverlay], [$CPFeedback, FALSE, RefreshCPFeedback], [$Foreground, TRUE, RefreshForeground], [$CaretPlane, FALSE, RefreshCaretPlane]]]; -- ... to front }; PaintEntireScene: PUBLIC PROC [screen: Imager.Context, ggData: GGData, showColors: BOOL] = { sandwich: Sandwich _ ggData.refresh.sandwich; CodeTimer.StartInt[$PaintEntireScene, $Gargoyle]; BufferedRefresh.SetLayerOK[sandwich, $Foreground, FALSE]; BufferedRefresh.SetLayerOK[sandwich, $Background, FALSE]; PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; CodeTimer.StopInt[$PaintEntireScene, $Gargoyle]; }; PaintAllPlanes: PROC [screen: Imager.Context, ggData: GGData, showColors: BOOL, caretIsMoving: BOOL, dragInProgress: BOOL] = { sandwich: Sandwich _ ggData.refresh.sandwich; clientToViewer, viewerToClient: Imager.Transformation; ignoreBackingMap: BOOL; IF ggData.refresh.suppressRefresh THEN RETURN; ggData.refresh.caretIsMoving _ caretIsMoving; ggData.refresh.dragInProgress _ dragInProgress; [clientToViewer, viewerToClient] _ BiScrollers.GetStyle[].GetTransforms[BiScrollers.QuaBiScroller[ggData.actionArea]]; <> ignoreBackingMap _ showColors; BufferedRefresh.DrawSandwich[sandwich, screen, clientToViewer, viewerToClient, ggData, ignoreBackingMap]; }; <<>> <> <<>> RefreshBackground: PROC [dc: Imager.Context, boundRect: Rectangle, clientData: REF ANY] = { ggData: GGData _ NARROW[clientData]; IF ggData.refresh.suppressRefresh THEN RETURN; DrawObjectsFiltered[dc: dc, ggData: ggData, filter: GGBoundBox.BoundBoxFromRectangle[boundRect], excludeOverlay: FALSE, overObject: NIL]; }; RefreshOverlay: PROC [dc: Imager.Context, boundRect: Rectangle, clientData: REF ANY] = { <> ggData: GGData _ NARROW[clientData]; DrawDragOverlayAux: PROC = { IF ggData.refresh.orderedOverlayList=NIL THEN ggData.refresh.orderedOverlayList _ OrderOverlayList[ggData]; -- update ordered list FOR oList: LIST OF SliceDescriptor _ ggData.refresh.orderedOverlayList, oList.rest UNTIL oList = NIL DO oList.first.slice.class.drawTransform[oList.first, dc, ggData.camera, ggData.drag.transform]; ENDLOOP; }; IF ggData.refresh.suppressRefresh THEN RETURN; Imager.DoSaveAll[dc, DrawDragOverlayAux]; }; RefreshCPFeedback: PROC [dc: Imager.Context, boundRect: Rectangle, clientData: REF ANY] = { ggData: GGData _ NARROW[clientData]; caretIsMoving: BOOL _ ggData.refresh.caretIsMoving; dragInProgress: BOOL _ ggData.refresh.dragInProgress; IF ggData.refresh.suppressRefresh THEN RETURN; IF ggData.camera.quality#quality THEN { DrawAttractorFeedback[dc, ggData, dragInProgress, caretIsMoving]; <> DrawCpsOfSelectedSlices[dc, ggData.scene, ggData.camera, dragInProgress, caretIsMoving]; }; }; RefreshForeground: PROC [dc: Imager.Context, boundRect: Rectangle, clientData: REF ANY] = { ggData: GGData _ NARROW[clientData]; IF ggData.refresh.suppressRefresh THEN RETURN; FunctionCache.Flush[ggData.refresh.lineCache]; GGGravity.DrawAlignBagRegardless[dc, ggData.hitTest.alignBag, ggData]; }; RefreshCaretPlane: PROC [dc: Imager.Context, boundRect: Rectangle, clientData: REF ANY] = { <> ggData: GGData _ NARROW[clientData]; IF ggData.refresh.suppressRefresh THEN RETURN; DrawCaret[dc, ggData.caret, Imager.black]; DrawAnchor[dc, ggData.anchor, Imager.black]; }; NoteNewForeground: PUBLIC PROC [alignObjects: LIST OF FeatureData, ggData: GGData] = { <> PaintForeground: PROC = { GGGravity.DrawFeatureList[foregroundContext, alignObjects, ggData]; }; foregroundContext: Imager.Context _ BufferedRefresh.GetLayerContext[ggData.refresh.sandwich, $Foreground]; Imager.DoSaveAll[foregroundContext, PaintForeground]; BufferedRefresh.SetLayerOK[ggData.refresh.sandwich, $Foreground, TRUE]; }; UpdateForegroundForMotion: PUBLIC PROC [ggData: GGData] = { <> PaintForeground: PROC = { GGGravity.DrawAlignBagRegardless[foregroundContext, ggData.hitTest.alignBag, ggData]; }; foregroundContext: Imager.Context _ BufferedRefresh.GetLayerContext[ggData.refresh.sandwich, $Foreground]; Imager.DoSaveAll[foregroundContext, PaintForeground]; BufferedRefresh.SetLayerOK[ggData.refresh.sandwich, $Foreground, TRUE]; }; <> DrawAttractorFeedback: PROC [dc: Imager.Context, ggData: GGData, dragInProgress, caretIsMoving: BOOL] = { <> attractor: SliceDescriptor _ GGCaret.GetAttractor[ggData.caret]; IF attractor#NIL THEN { selectedD: SliceDescriptor _ GGSelect.FindSelectedSlice[attractor.slice, ggData.scene, normal]; selectedParts: SliceParts _ IF selectedD = NIL THEN NIL ELSE selectedD.parts; attractor.slice.class.drawAttractorFeedback[attractor, selectedParts, dragInProgress, dc, ggData.camera]; }; }; MemberTraj: PROC [ref: Traj, list: LIST OF Traj] RETURNS [BOOL] = { FOR tl: LIST OF Traj _ list, tl.rest UNTIL tl = NIL DO IF tl.first = ref THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; <> <> <> <> <> <<[selectedList, ptr] _ GGUtility.StartOutlineList[];>> <> <<[selectedList, ptr] _ GGUtility.AddOutline[outD.slice, selectedList, ptr];>> <> <> <> <> <> <<};>> <<>> AllSelectedSlices: PROC [scene: Scene] RETURNS [selectedList: LIST OF Slice _ NIL] = { <> ptr: LIST OF Slice; sGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[scene, hot]; [selectedList, ptr] _ GGUtility.StartSliceList[]; FOR sd: SliceDescriptor _ GGSelect.NextSliceDescriptor[sGen], GGSelect.NextSliceDescriptor[sGen] UNTIL sd = NIL DO [selectedList, ptr] _ GGUtility.AddSlice[sd.slice, selectedList, ptr]; ENDLOOP; sGen _ GGSelect.SelectedSlices[scene, normal]; FOR sd: SliceDescriptor _ GGSelect.NextSliceDescriptor[sGen], GGSelect.NextSliceDescriptor[sGen] UNTIL sd = NIL DO IF NOT GGSelect.IsSelectedInPart[sd.slice, scene, hot] THEN [selectedList, ptr] _ GGUtility.AddSlice[sd.slice, selectedList, ptr]; ENDLOOP; }; <> <> <> <> <> <> <> <> <> <> <> <> <> <<};>> <<>> DrawCpsOfSelectedSlices: PROC [dc: Imager.Context, scene: Scene, camera: CameraData, dragInProgress, caretIsMoving: BOOL] = { normalSliceD, hotSliceD: SliceDescriptor; normalParts, hotParts: SliceParts; slice: Slice; IF caretIsMoving OR dragInProgress THEN RETURN; FOR sList: LIST OF Slice _ AllSelectedSlices[scene], sList.rest UNTIL sList=NIL DO slice _ sList.first; normalSliceD _ GGSelect.FindSelectedSlice[slice, scene, normal]; hotSliceD _ GGSelect.FindSelectedSlice[slice, scene, hot]; normalParts _ IF normalSliceD # NIL THEN normalSliceD.parts ELSE NIL; hotParts _ IF hotSliceD # NIL THEN hotSliceD.parts ELSE NIL; slice.class.drawSelectionFeedback[slice, normalParts, hotParts, dc, camera, dragInProgress, caretIsMoving, FALSE, caretIsMoving]; ENDLOOP; }; <> <> <<[attractor: attractor, on: attOn, jointNum: attJointNum, seg: attSeg] _ GGCaret.GetAttractor[ggData.caret];>> <> < {};>> < {};>> < attOn _ nothing; >> <<};>> <<>> <> <> <> <> <> <> <> <<[attractor: attractor, on: attOn, jointNum: attJointNum, seg: attSeg, segNum: attSegNum] _ GGCaret.GetAttractor[ggData.caret];>> <<[chair: chair, on: chairOn, jointNum: chairJointNum, segNum: chairSegNum, seg: chairSeg] _ GGCaret.GetChair[ggData.caret];>> <> < {>> <> <> <> <> <> <> <> <> <<};>> <<}>> <> <> <> <> <> <> <<};>> <<}>> <> <> <<};>> < { -- if slices are the same (don't user parts) then chair=attractor>> <> < IF aSliceD.slice=chairSliceD.slice THEN attOn _ nothing;>> <> <<};>> < attOn _ nothing; >> <<};>> <<>> MemberSlice: PROC [ref: SliceDescriptor, list: LIST OF SliceDescriptor] RETURNS [BOOL] = { FOR tl: LIST OF SliceDescriptor _ list, tl.rest UNTIL tl = NIL DO IF tl.first = ref THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; }; <<>> <> <<>> ObjectChangedInPlace: PROC [screen: Imager.Context, ggData: GGData, selectClass: GGInterfaceTypes.SelectionClass _ normal, showColors: BOOL] = { <> bBox: BoundBox _ GGBoundBox.BoundBoxOfSelected[ggData.scene, selectClass]; RepairBackgroundInBoundBox[ggData, bBox, TRUE, NIL]; PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; }; ObjectChangedBoundBoxProvided: PROC [screen: Imager.Context, ggData: GGData, showColors: BOOL] = { <> RepairBackgroundInBoundBox[ggData, ggData.refresh.startBoundBox, TRUE, NIL]; PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; }; ObjectAdded: PROC [screen: Imager.Context, ggData: GGData, showColors: BOOL] = { <> RepairBackgroundInBoundBox[ggData, ggData.refresh.startBoundBox, FALSE, ggData.refresh.addedObject]; PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; }; RepairBackgroundInBoundBox: PROC [ggData: GGData, bBox: BoundBox, eraseFirst: BOOL _ FALSE, overObject: Slice] = { backgroundContext: Imager.Context _ BufferedRefresh.GetLayerContext[ggData.refresh.sandwich, $Background]; IF ggData.refresh.suppressRefresh THEN RETURN; IF ggData.refresh.showColors.state = off THEN { PaintObjectsInBox: PROC = { IF eraseFirst THEN GGBoundBox.EraseWithinBoundBox[backgroundContext, bBox]; DrawObjectsFiltered[dc: backgroundContext, ggData: ggData, filter: bBox, overObject: overObject]; }; Imager.DoSaveAll[backgroundContext, PaintObjectsInBox]; BufferedRefresh.SetLayerOK[ggData.refresh.sandwich, $Background, TRUE]; }; }; <> <<>> DuringSelect: PROC [screen: Imager.Context, ggData: GGData, showColors: BOOL] = { IF ggData.refresh.suppressRefresh THEN RETURN; IF NOT showColors THEN { clientToViewer, viewerToClient: Imager.Transformation; [clientToViewer, viewerToClient] _ BiScrollers.GetStyle[].GetTransforms[BiScrollers.QuaBiScroller[ggData.actionArea]]; BufferedRefresh.DrawSandwich[ggData.refresh.sandwich, screen, clientToViewer, viewerToClient, ggData, showColors]; } ELSE {}; -- no feedback in SlowPaint mode }; SplitBackgroundAndOverlay: PUBLIC PROC [ggData: GGData, restoreBox: BoundBox] = { <> PaintAllButOverlayed: PROC = { GGBoundBox.EraseWithinBoundBox[backgroundContext, restoreBox]; DrawObjectsFiltered[dc: backgroundContext, ggData: ggData, filter: restoreBox, excludeOverlay: TRUE, overObject: NIL]; }; backgroundContext: Imager.Context; IF ggData.refresh.suppressRefresh THEN RETURN; backgroundContext _ BufferedRefresh.GetLayerContext[ggData.refresh.sandwich, $Background]; Imager.DoSaveAll[backgroundContext, PaintAllButOverlayed]; }; -- end StoreBackground PaintDragOverlay: PROC [screen: Imager.Context, ggData: GGData, dragInProgress: BOOL, showColors: BOOL] = { <> clientToViewer, viewerToClient: Imager.Transformation; ggData.refresh.dragInProgress _ dragInProgress; ggData.refresh.caretIsMoving _ TRUE; [clientToViewer, viewerToClient] _ BiScrollers.GetStyle[].GetTransforms[BiScrollers.QuaBiScroller[ggData.actionArea]]; BufferedRefresh.DrawSandwich[ggData.refresh.sandwich, screen, clientToViewer, viewerToClient, ggData, showColors]; }; FinishedAdding: PROC [screen: Imager.Context, ggData: GGData, showColors: BOOL] = { <> MergeBackgroundAndOverlay[ggData, ggData.refresh.startBoundBox, FALSE, ggData.refresh.addedObject, showColors]; PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; }; BackmostSelectedSlice: PROC [scene: Scene] RETURNS [backmost: Slice] = { sliceGen: SliceGenerator _ GGScene.TopLevelEntitiesInScene[scene]; FOR slice: Slice _ GGScene.NextSlice[sliceGen], GGScene.NextSlice[sliceGen] UNTIL slice = NIL DO sliceD: SliceDescriptor _ GGSelect.FindSelectedSlice[slice, scene, normal]; IF sliceD#NIL THEN RETURN[sliceD.slice]; ENDLOOP; RETURN[NIL]; }; FinishedDragging: PROC [screen: Imager.Context, ggData: GGData, showColors: BOOL] = { overObject: Slice _ BackmostSelectedSlice[ggData.scene]; GGBoundBox.EnlargeByBox[ggData.refresh.startBoundBox, GGBoundBox.BoundBoxOfMoving[ggData.scene]]; MergeBackgroundAndOverlay[ggData, ggData.refresh.startBoundBox, FALSE, overObject, showColors]; PaintAllPlanes[screen, ggData, showColors, FALSE, FALSE]; }; MergeBackgroundAndOverlay: PROC [ggData: GGData, bBox: BoundBox, eraseFirst: BOOL _ FALSE, overObject: Slice, showColors: BOOL] = { <> backgroundContext: Imager.Context _ BufferedRefresh.GetLayerContext[ggData.refresh.sandwich, $Background]; MergeBackgroundAndOverlayAux: PROC = { IF eraseFirst THEN GGBoundBox.EraseWithinBoundBox[backgroundContext, bBox]; DrawObjectsFiltered[dc: backgroundContext, ggData: ggData, filter: bBox, overObject: overObject]; }; IF ggData.refresh.suppressRefresh THEN RETURN; IF NOT showColors THEN { Imager.DoSaveAll[backgroundContext, MergeBackgroundAndOverlayAux]; BufferedRefresh.SetLayerOK[ggData.refresh.sandwich, $Background, TRUE]; }; }; <> <<>> DrawObjects: PROC [screen: Imager.Context, ggData: GGData] = { <> scene: Scene _ ggData.scene; camera: CameraData _ ggData.camera; sliceGen: SliceGenerator _ GGScene.TopLevelSlicesInScene[ggData.scene]; Imager.SetColor[screen, Imager.black]; FOR slice: Slice _ GGScene.NextSlice[sliceGen], GGScene.NextSlice[sliceGen] UNTIL slice = NIL DO slice.class.drawParts[slice, NIL, screen, camera, FALSE]; ENDLOOP; }; DrawObjectsFiltered: PROC [dc: Imager.Context, ggData: GGData, filter: GGBoundBox.BoundBox, excludeOverlay: BOOL _ FALSE, overObject: Slice] = { <> OutsideOf: PROC [test, bound: GGBoundBox.BoundBox] RETURNS [BOOL] = { RETURN[ test.hiX < bound.loX OR test.loX > bound.hiX OR test.hiY < bound.loY OR test.loY > bound.hiY ]; -- these tests may have to be <= or >= }; DrawObjectsFilteredAux: PROC = { -- need to clip to filter, then image sliceGen: SliceGenerator _ GGScene.TopLevelEntitiesInScene[scene]; thisSlice: Slice _ GGScene.NextSlice[sliceGen]; IF overObject # NIL THEN { UNTIL thisSlice = overObject OR thisSlice = NIL DO thisSlice _ GGScene.NextSlice[sliceGen]; ENDLOOP; IF thisSlice = NIL THEN RETURN; }; Imager.SetColor[dc, Imager.black]; GGBoundBox.Clip[dc: dc, bBox: filter]; FOR slice: Slice _ thisSlice, GGScene.NextSlice[sliceGen] UNTIL slice = NIL DO IF excludeOverlay AND slice.onOverlay THEN LOOP; IF NOT OutsideOf[slice.class.getBoundBox[slice, NIL], filter] THEN slice.class.drawParts[slice, NIL, dc, camera, FALSE]; ENDLOOP; }; scene: Scene _ ggData.scene; camera: CameraData _ ggData.camera; IF filter=NIL OR filter.null THEN RETURN; Imager.DoSaveAll[dc, DrawObjectsFilteredAux]; }; DrawCaret: PROC [dc: Imager.Context, caret: Caret, color: Imager.Color] = { caretPos: Point _ GGCaret.GetPoint[caret]; IF NOT GGCaret.Exists[caret] THEN RETURN; Imager.SetColor[dc, color]; GGShapes.DrawCaret[dc, caretPos]; }; DrawAnchor: PROC [dc: Imager.Context, caret: Caret, color: Imager.Color] = { caretPos: Point _ GGCaret.GetPoint[caret]; IF NOT GGCaret.Exists[caret] THEN RETURN; Imager.SetColor[dc, color]; GGShapes.DrawAnchor[dc, caretPos]; }; <<>> <> DrawNewAnchor: PROC [dc: Imager.Context, ggData: GGData] = { anchorPos: Point _ GGCaret.GetPoint[ggData.anchor]; Imager.SetColor[dc, Imager.black]; GGShapes.DrawAnchor[dc, anchorPos]; }; PaintSpot: PROC [dc: Imager.Context, ggData: GGData] = { IF ggData.refresh.suppressRefresh THEN RETURN; Imager.SetColor[dc, Imager.black]; GGShapes.DrawSpot[dc, ggData.refresh.spotPoint]; }; PaintHitLine: PROC [dc: Imager.Context, ggData: GGData] = { IF ggData.refresh.suppressRefresh THEN RETURN; Imager.SetColor[dc, Imager.black]; Imager.SetStrokeEnd[dc, round]; Imager.MaskVector[dc, [ggData.refresh.spotPoint.x, ggData.refresh.spotPoint.y], [ggData.refresh.hitPoint.x, ggData.refresh.hitPoint.y]]; GGShapes.DrawFilledRect[dc, ggData.refresh.spotPoint, 3.0]; }; PaintOddHitLine: PROC [dc: Imager.Context, ggData: GGData] = { IF ggData.refresh.suppressRefresh THEN RETURN; Imager.SetColor[dc, Imager.black]; Imager.SetStrokeEnd[dc, round]; Imager.MaskVector[dc, [ggData.refresh.spotPoint.x, ggData.refresh.spotPoint.y], [ggData.refresh.hitPoint.x, ggData.refresh.hitPoint.y]]; GGShapes.DrawCP[dc, ggData.refresh.spotPoint]; }; PaintAlign: PROC [dc: Imager.Context, ggData: GGData] = { <> IF ggData.refresh.suppressRefresh THEN RETURN; GGGravity.DrawAlignBagRegardless[dc, NARROW[ggData.hitTest.alignBag], ggData]; }; PaintBoundBoxes: PROC [dc: Imager.Context, ggData: GGData] = { bBoxGen: BoundBoxGenerator; PaintBoundBoxesAux: PROC = { <> bBoxGen _ GGScene.BoundBoxesInScene[ggData.scene]; FOR box: BoundBox _ GGScene.NextBox[bBoxGen], GGScene.NextBox[bBoxGen] UNTIL box = NIL DO GGBoundBox.DrawBoundBox[dc, box]; ENDLOOP; }; IF ggData.refresh.suppressRefresh THEN RETURN; Imager.DoSaveAll[dc, PaintBoundBoxesAux]; }; PaintTightBoxes: PROC [dc: Imager.Context, ggData: GGData] = { box: BoundBox; PaintTightBoxesAux: PROC = { <> sliceDescGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[ggData.scene, normal]; FOR sliceD: SliceDescriptor _ GGSelect.NextSliceDescriptor[sliceDescGen], GGSelect.NextSliceDescriptor[sliceDescGen] UNTIL sliceD = NIL DO box _ sliceD.slice.class.getTightBox[sliceD.slice, sliceD.parts]; GGBoundBox.DrawBoundBox[dc, box]; ENDLOOP; }; IF ggData.refresh.suppressRefresh THEN RETURN; Imager.DoSaveAll[dc, PaintTightBoxesAux]; }; PaintOutlineBoxes: PROC [dc: Imager.Context, ggData: GGData] = { PaintBoundBoxesAux: PROC = { <> outSeqGen: GGSelect.OutlineSequenceGenerator; bBox: BoundBox; outSeqGen _ GGSelect.SelectedOutlineSequences[ggData.scene, normal]; FOR outSeq: GGSelect.OutlineSequence _ GGSelect.NextOutlineSequences[outSeqGen], GGSelect.NextOutlineSequences[outSeqGen] UNTIL outSeq = NIL DO IF outSeq.fenceSeq # NIL THEN { bBox _ GGTraj.GetBoundBox[outSeq.fenceSeq.traj]; GGBoundBox.DrawBoundBox[dc, bBox]; }; FOR holeSeq: Sequence _ GGSequence.NextSequence[outSeq.holeSeqs], GGSequence.NextSequence[outSeq.holeSeqs] UNTIL holeSeq = NIL DO bBox _ GGTraj.GetBoundBox[holeSeq.traj]; GGBoundBox.DrawBoundBox[dc, bBox]; ENDLOOP; ENDLOOP; }; IF ggData.refresh.suppressRefresh THEN RETURN; Imager.DoSaveAll[dc, PaintBoundBoxesAux]; }; PaintSelectionBox: PUBLIC PROC [dc: Imager.Context, ggData: GGData] = { box: BoundBox _ NIL; PaintSelectionBoxAux: PROC = { <> box _ GGBoundBox.BoundBoxOfSelected[ggData.scene]; IF NOT box.null THEN GGBoundBox.DrawBoundBox[dc, box]; }; IF ggData.refresh.suppressRefresh THEN RETURN; Imager.DoSaveAll[dc, PaintSelectionBoxAux]; }; <> <> <<$DrawBackgroundBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].background,>> <<$DrawOverlayBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].overlay,>> <<$DrawRubberBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].rubber,>> <<$DrawDragBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].drag,>> < ERROR;>> <<};>> <<>> GetSliceParts: PROC [sliceD: SliceDescriptor, atom: ATOM] RETURNS [parts: SliceDescriptor] = { parts _ SELECT atom FROM $DrawBackgroundBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].background, $DrawOverlayBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].overlay, $DrawRubberBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].rubber, $DrawDragBox => sliceD.slice.class.movingParts[sliceD.slice, sliceD.parts].drag, ENDCASE => ERROR; }; DrawMovingBox: PUBLIC PROC [dc: Imager.Context, ggData: GGData, atom: ATOM] = { <> <> <> <> <> <> <> <<};>> SliceEnlargeBox: PROC [sliceD: SliceDescriptor] = { thisBox: BoundBox; theseParts: SliceDescriptor; theseParts _ GetSliceParts[sliceD, atom]; IF theseParts.parts = NIL THEN thisBox _ GGBoundBox.NullBoundBox[] ELSE thisBox _ sliceD.slice.class.getBoundBox[sliceD.slice, theseParts.parts]; GGBoundBox.EnlargeByBox[bBox: box, by: thisBox]; }; box: BoundBox _ GGBoundBox.NullBoundBox[]; IF ggData.refresh.suppressRefresh THEN RETURN; <> GGSelect.DoForEachSelectedSlice[ggData.scene, normal, SliceEnlargeBox]; IF NOT box.null THEN GGBoundBox.DrawBoundBox[dc, box]; }; EraseAll: PROC [dc: Imager.Context] = { rect: Imager.Rectangle; rect _ ImagerBackdoor.GetBounds[dc]; Imager.SetColor[dc, Imager.white]; Imager.MaskRectangle[dc, rect]; }; <<>> <> EndFourPoints: PROC [traj: Traj] RETURNS [firstPoint, secondPoint, secondToLastPoint, lastPoint: Point, firstWidth, lastWidth: REAL] = { seg: Segment; cpCount: NAT; seg _ GGTraj.FetchSegment[traj, 0]; firstWidth _ seg.strokeWidth; firstPoint _ seg.lo; cpCount _ seg.class.controlPointCount[seg]; IF cpCount > 0 THEN { secondPoint _ seg.class.controlPointGet[seg, 0]; } ELSE { secondPoint _ seg.hi; }; seg _ GGTraj.FetchSegment[traj, GGTraj.HiSegment[traj]]; lastWidth _ seg.strokeWidth; lastPoint _ seg.hi; cpCount _ seg.class.controlPointCount[seg]; IF cpCount > 0 THEN { secondToLastPoint _ seg.class.controlPointGet[seg, cpCount-1]; } ELSE { secondToLastPoint _ seg.lo; }; }; ExcludeArrows: PROC [dc: Imager.Context, traj: Traj] = { OPEN Vectors2d; ClipPath: Imager.PathProc = { moveTo[Add[Add[tip, Scale[perp, -halfWidth]], Scale[axis, thisWidth/2.0]]]; lineTo[Add[Add[tip, Scale[perp, halfWidth]], Scale[axis, thisWidth/2.0]]]; lineTo[Sub[tip, Add[Scale[axis, height], Scale[perp, halfWidth]]]]; lineTo[Sub[tip, Add[Scale[axis, height], Scale[perp, -halfWidth]]]]; lineTo[Add[tip, Scale[perp, -halfWidth]]]; }; firstPoint, secondPoint, secondToLastPoint, lastPoint, tip, base: Point; firstWidth, lastWidth, thisWidth, height, halfWidth: REAL; axis, perp: Vector; IF NOT traj.loArrow AND NOT traj.hiArrow THEN RETURN; [firstPoint, secondPoint, secondToLastPoint, lastPoint, firstWidth, lastWidth] _ EndFourPoints[traj]; IF traj.loArrow THEN { thisWidth _ firstWidth; [height, halfWidth] _ GGShapes.ArrowSize[thisWidth]; tip _ firstPoint; base _ secondPoint; axis _ Vectors2d.Normalize[Vectors2d.Sub[tip, base]]; perp _ [axis.y, -axis.x]; Imager.Clip[dc, ClipPath, FALSE, TRUE]; }; IF traj.hiArrow THEN { thisWidth _ lastWidth; [height, halfWidth] _ GGShapes.ArrowSize[thisWidth]; tip _ lastPoint; base _ secondToLastPoint; axis _ Vectors2d.Normalize[Vectors2d.Sub[tip, base]]; perp _ [axis.y, -axis.x]; Imager.Clip[dc, ClipPath, FALSE, TRUE]; }; }; DrawArrows: PROC [dc: Imager.Context, traj: Traj, ggData: GGData] = { firstPoint, secondPoint, secondToLastPoint, lastPoint: Point; firstWidth, lastWidth: REAL; IF NOT traj.loArrow AND NOT traj.hiArrow THEN RETURN; [firstPoint, secondPoint, secondToLastPoint, lastPoint, firstWidth, lastWidth] _ EndFourPoints[traj]; IF traj.loArrow THEN GGShapes.DrawArrow[dc, firstPoint, secondPoint, firstWidth]; IF traj.hiArrow THEN GGShapes.DrawArrow[dc, lastPoint, secondToLastPoint, lastWidth]; }; <> DrawJoints: PROC [dc: Imager.Context, traj: Traj, ggData: GGData] = { <> <> <> <> <> <> IF ggData.camera.quality = quality OR traj.parent.onOverlay THEN RETURN; IF NOT traj.visibleJoints THEN RETURN; <> Imager.SetColor[dc, Imager.black]; FOR i: INT IN [0..GGTraj.HiJoint[traj]] DO GGShapes.DrawJoint[dc, GGTraj.FetchJointPos[traj, i]]; ENDLOOP; }; DrawJointsInSequenceFeedback: PROC [dc: Imager.Context, seq: Sequence, ggData: GGData, selectClass: SelectionClass _ normal] = { jointGen: JointGenerator; <> IF ggData.camera.quality = quality THEN RETURN; Imager.SetColor[dc, Imager.black]; jointGen _ GGSequence.JointsInSequence[seq]; FOR i: INT _ GGSequence.NextJoint[jointGen], GGSequence.NextJoint[jointGen] UNTIL i = -1 DO GGShapes.DrawSelectedJoint[dc, GGTraj.FetchJointPos[seq.traj, i], selectClass]; ENDLOOP; }; <<>> <> SnapShot: PUBLIC PROC [dc: Imager.Context, ggData: GGData] = { <> <> boundRect: Rectangle _ [x: 0.0, y: 0.0, w: 8.5*72.0, h: 11.0*72.0]; -- kludge SnapshotBackground[dc, ggData]; RefreshOverlay[dc, boundRect, ggData]; -- fortunately, RefreshOverlay doesn't user boundRect }; SnapshotBackground: PROC [dc: Imager.Context, ggData: GGData] = { <> scene: Scene _ ggData.scene; camera: CameraData _ ggData.camera; sliceGen: SliceGenerator; <> Imager.SetColor[dc, Imager.black]; <> sliceGen _ GGScene.TopLevelEntitiesInScene[ggData.scene]; FOR slice: Slice _ GGScene.NextSlice[sliceGen], GGScene.NextSlice[sliceGen] UNTIL slice = NIL DO <> IF slice.onOverlay THEN LOOP ELSE slice.class.drawParts[slice, NIL, dc, camera, FALSE]; ENDLOOP; <> <> DrawCaret[dc, ggData.caret, Imager.black]; DrawAnchor[dc, ggData.anchor, Imager.black]; <> GGGravity.DrawAlignBagRegardless[dc, NARROW[ggData.hitTest.alignBag], ggData]; }; InterpressEntireScene: PUBLIC PROC [dc: Imager.Context, ggData: GGData] = { DrawObjects[dc, ggData]; }; <<>> <> <<>> MoveToOverlay: PUBLIC PROC [sliceD: SliceDescriptor, ggData: GGData] = { IF OnOverlay[sliceD, ggData] THEN ERROR; sliceD.slice.onOverlay _ TRUE; ggData.refresh.overlayList _ GGUtility.AppendSliceDescriptorList[LIST[sliceD], ggData.refresh.overlayList]; ggData.refresh.orderedOverlayList _ NIL; }; MoveAllSelectedToOverlay: PUBLIC PROC [ggData: GGData, selectClass: SelectionClass] = { sliceDescGen: SliceDescriptorGenerator _ GGSelect.SelectedSlices[ggData.scene, selectClass]; FOR sliceD: SliceDescriptor _ GGSelect.NextSliceDescriptor[sliceDescGen], GGSelect.NextSliceDescriptor[sliceDescGen] UNTIL sliceD=NIL DO MoveToOverlay[sliceD, ggData]; ENDLOOP; }; MoveToBackground: PUBLIC PROC [sliceD: SliceDescriptor, ggData: GGData] = { IF NOT OnOverlay[sliceD, ggData] THEN RETURN; ggData.refresh.overlayList _ GGUtility.DeleteSliceDescriptorFromList[sliceD, ggData.refresh.overlayList]; sliceD.slice.onOverlay _ FALSE; ggData.refresh.orderedOverlayList _ NIL; }; MoveOverlayToBackground: PUBLIC PROC [ggData: GGData] = { FOR overlayList: LIST OF SliceDescriptor _ ggData.refresh.overlayList, overlayList.rest UNTIL overlayList = NIL DO overlayList.first.slice.onOverlay _ FALSE; ENDLOOP; ggData.refresh.overlayList _ NIL; ggData.refresh.orderedOverlayList _ NIL; }; EmptyOverlay: PUBLIC PROC [ggData: GGData] RETURNS [BOOL] = { RETURN[ggData.refresh.overlayList = NIL]; }; OnOverlay: PROC [sliceD: SliceDescriptor, ggData: GGData] RETURNS [BOOL] = { RETURN[sliceD.slice.onOverlay]; }; OrderOverlayList: PROC [ggData: GGData] RETURNS [orderedList: LIST OF SliceDescriptor] = { <> FindOverlayedD: PROC [slice: Slice] RETURNS [sliceD: SliceDescriptor] = { FOR ov: LIST OF SliceDescriptor _ ggData.refresh.overlayList, ov.rest UNTIL ov=NIL DO IF ov.first.slice=slice THEN RETURN[ov.first]; ENDLOOP; RETURN[NIL]; }; sliceD: SliceDescriptor; sliceGen: SliceGenerator; finger: LIST OF SliceDescriptor; [orderedList, finger] _ GGUtility.StartSliceDescriptorList[]; sliceGen _ GGScene.TopLevelSlicesInScene[ggData.scene]; FOR slice: Slice _ GGScene.NextSlice[sliceGen], GGScene.NextSlice[sliceGen] UNTIL slice = NIL DO IF slice.onOverlay THEN { sliceD _ FindOverlayedD[slice]; IF sliceD = NIL THEN sliceD _ slice.class.newParts[slice, NIL, topLevel]; [orderedList, finger] _ GGUtility.AddSliceDescriptor[sliceD, orderedList, finger]; }; ENDLOOP; <> }; <<>> <> AdjustContextForDrawBits: PROC [dc: Imager.Context, ggData: GGData] = { <> viewerToClient: Imager.Transformation _ BiScrollers.GetStyle[].GetTransforms[BiScrollers.QuaBiScroller[ggData.actionArea]].viewerToClient; Imager.ConcatT[dc, viewerToClient]; }; InitStats: PROC [] = { interval: CodeTimer.Interval; interval _ CodeTimer.CreateInterval[$PaintEntireScene]; CodeTimer.AddInt[interval, $Gargoyle]; }; InitStats[]; END. <> <>