<> <> <> <> <> <> <<>> DIRECTORY Atom, BiScrollers, CedarProcess, GGBasicTypes, GGBoundBox, GGCaret, GGError, GGGravity, GGInterfaceTypes, GGModelTypes, GGObjects, GGRefresh, GGSelect, GGSegmentTypes, GGSequence, GGShapes, GGStatistics, GGTouch, GGTraj, GGUtility, GGVector, Imager, ImagerBackdoor, ImagerOps, ImagerPixelMap, List, Process, Rope, Rosary, SlackProcess, TIPUser, Terminal, Interminal, ViewerClasses, ViewerOps; GGRefreshImpl: CEDAR MONITOR IMPORTS Atom, BiScrollers, CedarProcess, GGBoundBox, GGCaret, GGError, GGGravity, GGObjects, GGSelect, GGSequence, GGShapes, GGStatistics, GGTouch, GGTraj, GGUtility, GGVector, Imager, ImagerBackdoor, List, Process, Rope, SlackProcess, Terminal, Interminal, ViewerOps EXPORTS GGRefresh = BEGIN BitVector: TYPE = GGBasicTypes.BitVector; BoundBox: TYPE = GGModelTypes.BoundBox; BoundBoxGenerator: TYPE = GGObjects.BoundBoxGenerator; CameraData: TYPE = GGModelTypes.CameraData; Caret: TYPE = GGInterfaceTypes.Caret; Color: TYPE = Imager.Color; FeatureData: TYPE = GGGravity.FeatureData; OutlineDescriptor: TYPE = GGModelTypes.OutlineDescriptor; Slice: TYPE = GGModelTypes.Slice; SliceParts: TYPE = GGModelTypes.SliceParts; SliceGenerator: TYPE = GGModelTypes.SliceGenerator; SliceDescriptor: TYPE = GGModelTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = GGModelTypes.SliceDescriptorGenerator; EntityGenerator: TYPE = GGModelTypes.EntityGenerator; GargoyleData: TYPE = GGInterfaceTypes.GargoyleData; 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; << [Artwork node; type 'ArtworkInterpress on' to command tool] >> KillData: TYPE = RECORD [process: UNSAFE PROCESS, gargoyleData: GargoyleData]; NilIt: PRIVATE ENTRY PROC [data: REF KillData] = TRUSTED {data.process _ NIL}; ActionAreaPaint: PUBLIC PROC [screen: Imager.Context, whatHasChanged: ATOM, gargoyleData: GargoyleData] = TRUSTED { IF whatHasChanged=$ViewersPaintEntireScene THEN { -- need a special abort watcher data: REF KillData _ NEW[KillData _ [Process.GetCurrent[], gargoyleData]]; <> [] _ CedarProcess.Fork[Killer, data, [excited, TRUE]]; DoActionAreaPaint[screen, whatHasChanged, gargoyleData ! UNWIND => NilIt[data]]; NilIt[data]; } ELSE DoActionAreaPaint[screen, whatHasChanged, gargoyleData]; -- SlackProcess is watching for aborts }; Killer: PROC [data: REF] RETURNS [results: REF _ NIL] = { KillKeysDown: PROC RETURNS [kill: BOOL _ FALSE] = { tsc: TIPUser.TIPScreenCoords ~ NEW[TIPUser.TIPScreenCoordsRec]; vt: Terminal.Virtual ~ Terminal.Current[]; keyBits: Terminal.KeyBits ~ Terminal.GetKeys[vt: vt]; IF (keyBits[LeftShift]=down OR keyBits[RightShift]=down) AND keyBits[Spare3]=down THEN { mouse: Interminal.MousePosition ~ Interminal.GetMousePosition[]; viewer: ViewerClasses.Viewer; tsc^ _ [ mouseX: mouse.mouseX, mouseY: (IF mouse.color THEN vt.colorHeight ELSE vt.bwHeight) - mouse.mouseY, color: mouse.color ]; viewer _ ViewerOps.MouseInViewer[tsc: tsc].viewer; RETURN[viewer#NIL AND BiScrollers.ViewerIsABiScroller[viewer]] ; }; }; MaybeKill: ENTRY PROC = { IF killData.process # NIL AND KillKeysDown[] THEN { gargoyleData: GargoyleData _ killData.gargoyleData; TRUSTED {Process.Abort[killData.process];}; killData.process _ NIL; SlackProcess.FlushQueue[gargoyleData.slackHandle]; -- you have to do this HERE! gargoyleData.refresh.suppressRefresh _ FALSE; -- in case you killed FastPlayback gargoyleData.aborted _ ALL[TRUE]; -- copies of aborted for all purposes }; }; killData: REF KillData _ NARROW[data]; UNTIL killData.process = NIL DO MaybeKill[]; Process.Pause[ticks: Process.SecondsToTicks[1]]; ENDLOOP; }; DoActionAreaPaint: PROC [screen: Imager.Context, whatHasChanged: ATOM, gargoyleData: GargoyleData] = { <> <> <<>> IF gargoyleData.aborted[refresh] THEN { -- last paint got killed => unknown bitmap cache states gargoyleData.aborted[refresh] _ FALSE; PaintEntireScene[screen, gargoyleData]; } ELSE SELECT whatHasChanged FROM $None => NULL; <> $PaintEntireScene, $ViewersPaintEntireScene => PaintEntireScene[screen, gargoyleData]; $NewAlignmentsDeselected => PaintAllPlanes[screen, gargoyleData]; $NewAlignmentsSelected => PaintAllPlanes[screen, gargoyleData]; $SequencesMadeHot => PaintAllPlanes[screen, gargoyleData]; $SequencesMadeCold => PaintAllPlanes[screen, gargoyleData]; $Everything => PaintEntireScene[screen, gargoyleData]; $SelectionChanged => SelectionOrCaretChanged[screen, gargoyleData]; $FinishedAdding => FinishedAdding[screen, gargoyleData]; $FinishedDragging => FinishedDragging[screen, gargoyleData]; $CaretMoved => SelectionOrCaretChanged[screen, gargoyleData]; -- GGMouseEventImplA $AnchorAdded => PaintAllPlanes[screen, gargoyleData]; -- GGEventImplB $AnchorRemoved => PaintAllPlanes[screen, gargoyleData]; -- GGEventImplB <> $DuringMotion => PaintDragOverlay[screen, gargoyleData, TRUE]; -- GGMouseEventImplA $DuringCaretPos => PaintDragOverlay[screen, gargoyleData, FALSE]; -- GGMouseEventImplA $DuringSelect => DuringSelect[screen, gargoyleData]; $ObjectChangedInPlace => ObjectChangedInPlace[screen, gargoyleData, normal]; $ObjectChangedBoundBoxProvided => ObjectChangedBoundBoxProvided[screen, gargoyleData]; $ObjectAdded => ObjectAdded[screen, gargoyleData]; <> $PaintSpot => PaintSpot[screen, gargoyleData]; $PaintHitLine => PaintHitLine[screen, gargoyleData]; $PaintOddHitLine => PaintOddHitLine[screen, gargoyleData]; $PaintTouchPoints => PaintTouchPoints[screen, gargoyleData]; $PaintAlign => PaintAlign[screen, gargoyleData]; $PaintBoundBoxes => PaintBoundBoxes[screen, gargoyleData]; $PaintTightBoxes => PaintTightBoxes[screen, gargoyleData]; $PaintOutlineBoxes => PaintOutlineBoxes[screen, gargoyleData]; $PaintSelectionBox => PaintSelectionBox[screen, gargoyleData]; $PaintMovingBox => PaintMovingBox[screen, gargoyleData]; ENDCASE => { GGError.Append[gargoyleData.feedback, Rope.Cat["Gargoyle GGRefreshImpl doesn't know how to ", Atom.GetPName[whatHasChanged], "."], oneLiner]; GGError.Blink[gargoyleData.feedback]; }; }; <<>> <> <<>> DrawBackground: PROC [dc: Imager.Context, gargoyleData: GargoyleData] = { BackgroundBitsToDC: PROC = { AdjustContextForDrawBits[dc, gargoyleData]; Imager.SetColor[dc, Imager.black]; ImagerBackdoor.DrawBits[dc, backgroundBitmap.base, backgroundBitmap.wordsPerLine, 0, 0, backgroundBitmap.height, backgroundBitmap.width, 0, backgroundBitmap.height]; }; backgroundBitmap: ImagerBackdoor.Bitmap _ gargoyleData.refresh.backgroundBitmap; IF gargoyleData.refresh.showColors.state = off THEN { IF NOT gargoyleData.refresh.backgndBitmapOK THEN { PaintBackground: PROC = { rect: Imager.Rectangle; rect _ ImagerBackdoor.GetBounds[gargoyleData.refresh.backgroundContext]; Imager.SetColor[gargoyleData.refresh.backgroundContext, Imager.white]; Imager.MaskRectangle[gargoyleData.refresh.backgroundContext, rect]; DrawObjectsFiltered[screen: gargoyleData.refresh.backgroundContext, gargoyleData: gargoyleData, filter: GGBoundBox.BoundBoxFromRectangle[rect], excludeOverlay: FALSE, overObject: NIL] }; Imager.DoSaveAll[gargoyleData.refresh.backgroundContext, PaintBackground]; gargoyleData.refresh.backgndBitmapOK _ TRUE; }; Imager.DoSaveAll[dc, BackgroundBitsToDC]; } ELSE { rect: Imager.Rectangle; rect _ BiScrollers.ViewportBox[gargoyleData.biScroller]; Imager.SetColor[dc, Imager.white]; Imager.MaskRectangle[dc, rect]; DrawObjectsFiltered[screen: dc, gargoyleData: gargoyleData, filter: GGBoundBox.BoundBoxFromRectangle[rect], excludeOverlay: FALSE, overObject: NIL] }; }; <> <> <> <> < {>> <> <> <> <> <<};>> < {>> <> <> <> <> <<};>> < ERROR;>> <> <<};>> <> <> <> <> <> <> < 10 OR quick;>> <> <> <<};>> <> <> < 10 OR quick;>> <> <> <<};>> DrawForeground: PROC [dc: Imager.Context, gargoyleData: GargoyleData] = { ForegroundBitsToDC: PROC = { AdjustContextForDrawBits[dc, gargoyleData]; Imager.SetColor[dc, Imager.black]; Imager.MaskBits[dc, foregroundBitmap.base, foregroundBitmap.wordsPerLine, 0, 0, foregroundBitmap.height, foregroundBitmap.width, 0, foregroundBitmap.height]; }; foregroundBitmap: ImagerBackdoor.Bitmap _ gargoyleData.refresh.foregroundBitmap; IF gargoyleData.refresh.showColors.state = off THEN { <> IF NOT gargoyleData.refresh.foregndBitmapOK THEN { PaintForeground: PROC = { rect: Imager.Rectangle; rect _ ImagerBackdoor.GetBounds[gargoyleData.refresh.foregroundContext]; Imager.SetColor[gargoyleData.refresh.foregroundContext, Imager.white]; Imager.MaskRectangle[gargoyleData.refresh.foregroundContext, rect]; GGGravity.DrawObjectBagRegardless[gargoyleData.refresh.foregroundContext, gargoyleData.hitTest.currentObjectBag, gargoyleData]; }; Imager.DoSaveAll[gargoyleData.refresh.foregroundContext, PaintForeground]; gargoyleData.refresh.foregndBitmapOK _ TRUE; }; Imager.DoSaveAll[dc, ForegroundBitsToDC]; } ELSE { <> IF NOT gargoyleData.refresh.foregndBitmapOK THEN GGGravity.DrawObjectBagRegardless[dc, gargoyleData.hitTest.currentObjectBag, gargoyleData]; }; }; DrawCaretPlane: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { <> <> DrawCaret[screen, gargoyleData.caret, Imager.black]; DrawAnchor[screen, gargoyleData.anchor, Imager.black]; }; NoteNewForeground: PUBLIC PROC [alignObjects: LIST OF FeatureData, gargoyleData: GargoyleData] = { <> PaintForeground: PROC = { GGGravity.DrawFeatureList[gargoyleData.refresh.foregroundContext, alignObjects, gargoyleData]; }; Imager.DoSaveAll[gargoyleData.refresh.foregroundContext, PaintForeground]; gargoyleData.refresh.foregndBitmapOK _ TRUE; }; DrawCPFeedback: PROC [dc: Imager.Context, gargoyleData: GargoyleData, caretIsMoving, dragInProgress: BOOL] = { IF gargoyleData.camera.quality#quality THEN { DrawAttractorFeedback[dc, gargoyleData, dragInProgress, caretIsMoving]; DrawCpsOfSelectedOutlines[dc, gargoyleData.scene, gargoyleData.camera, dragInProgress, caretIsMoving]; DrawCpsOfSelectedSlices[dc, gargoyleData.scene, gargoyleData.camera, dragInProgress, caretIsMoving]; }; }; DrawAttractorFeedback: PROC [dc: Imager.Context, gargoyleData: GargoyleData, dragInProgress, caretIsMoving: BOOL] = { <> attractor: REF ANY; selectedParts: SliceParts; attractor _ GGCaret.GetAttractor[gargoyleData.caret]; IF attractor = NIL THEN RETURN; WITH attractor SELECT FROM sliceD: SliceDescriptor => { selectedD: SliceDescriptor _ GGSelect.FindSelectedSlice[slice: sliceD.slice, scene: gargoyleData.scene, selectClass: normal]; selectedParts _ IF selectedD = NIL THEN NIL ELSE selectedD.parts; sliceD.slice.class.drawAttractorFeedback[sliceD, selectedParts, dragInProgress, dc, gargoyleData.camera]; }; outlineD: OutlineDescriptor => { selectedD: OutlineDescriptor _ GGSelect.FindSelectedOutline[outlineD.slice, gargoyleData.scene, normal]; selectedParts _ IF selectedD = NIL THEN NIL ELSE selectedD.parts; outlineD.slice.class.drawAttractorFeedback[outlineD, selectedParts, dragInProgress, dc, gargoyleData.camera]; }; ENDCASE => ERROR; }; 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]; }; AllSelectedOutlines: PROC [scene: Scene] RETURNS [selectedList: LIST OF Outline _ NIL] = { <> ptr: LIST OF Outline; outDGen: GGModelTypes.OutlineDescriptorGenerator; outDGen _ GGSelect.SelectedOutlines[scene, hot]; [selectedList, ptr] _ GGUtility.StartOutlineList[]; FOR outD: OutlineDescriptor _ GGSelect.NextOutlineDescriptor[outDGen], GGSelect.NextOutlineDescriptor[outDGen] UNTIL outD = NIL DO [selectedList, ptr] _ GGUtility.AddOutline[outD.slice, selectedList, ptr]; ENDLOOP; outDGen _ GGSelect.SelectedOutlines[scene, normal]; FOR outD: OutlineDescriptor _ GGSelect.NextOutlineDescriptor[outDGen], GGSelect.NextOutlineDescriptor[outDGen] UNTIL outD = NIL DO IF NOT GGSelect.IsSelectedInPart[outD.slice, scene, hot] THEN [selectedList, ptr] _ GGUtility.AddOutline[outD.slice, selectedList, ptr]; ENDLOOP; }; 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; }; DrawCpsOfSelectedOutlines: PROC [dc: Imager.Context, scene: Scene, camera: CameraData, dragInProgress, caretIsMoving: BOOL] = { normalD, hotD: OutlineDescriptor; normalParts, hotParts: SliceParts; outline: Outline; IF caretIsMoving OR dragInProgress THEN RETURN; FOR oList: LIST OF Outline _ AllSelectedOutlines[scene], oList.rest UNTIL oList=NIL DO outline _ oList.first; normalD _ GGSelect.FindSelectedOutline[outline, scene, normal]; hotD _ GGSelect.FindSelectedOutline[outline, scene, hot]; normalParts _ IF normalD # NIL THEN normalD.parts ELSE NIL; hotParts _ IF hotD # NIL THEN hotD.parts ELSE NIL; outline.class.drawSelectionFeedback[outline, normalParts, hotParts, dc, camera, dragInProgress, caretIsMoving, FALSE, caretIsMoving]; 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[gargoyleData.caret];>> <> < {};>> < {};>> < attOn _ nothing; >> <<};>> <<>> <> <> <> <> <> <> <> <<[attractor: attractor, on: attOn, jointNum: attJointNum, seg: attSeg, segNum: attSegNum] _ GGCaret.GetAttractor[gargoyleData.caret];>> <<[chair: chair, on: chairOn, jointNum: chairJointNum, segNum: chairSegNum, seg: chairSeg] _ GGCaret.GetChair[gargoyleData.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]; }; <<>> <> <<>> PaintEntireScene: PUBLIC PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { <> GGStatistics.StartInterval[$PaintEntireScene, GGStatistics.GlobalTable[]]; gargoyleData.refresh.foregndBitmapOK _ FALSE; gargoyleData.refresh.backgndBitmapOK _ FALSE; PaintAllPlanes[screen, gargoyleData]; GGStatistics.StopInterval[$PaintEntireScene, GGStatistics.GlobalTable[]]; }; PaintAllPlanes: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { IF gargoyleData.refresh.suppressRefresh THEN RETURN; IF gargoyleData.refresh.showColors.state = off THEN { BackgroundToChunking[gargoyleData]; <> CPFeedbackToChunking[gargoyleData, FALSE, FALSE]; ForegroundToChunking[gargoyleData]; CaretPlaneToChunking[gargoyleData]; ChunkingToScreen[screen, gargoyleData]; } ELSE { DrawBackground[screen, gargoyleData]; <> DrawCPFeedback[screen, gargoyleData, FALSE, FALSE]; DrawForeground[screen, gargoyleData]; DrawCaretPlane[screen, gargoyleData]; }; }; <<>> ObjectChangedInPlace: PROC [screen: Imager.Context, gargoyleData: GargoyleData, selectClass: GGInterfaceTypes.SelectionClass _ normal] = { <> bBox: BoundBox _ GGBoundBox.BoundBoxOfSelected[gargoyleData.scene, selectClass]; RepairBackgroundInBoundBox[gargoyleData, bBox, TRUE, NIL]; PaintAllPlanes[screen, gargoyleData]; }; ObjectChangedBoundBoxProvided: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { <> RepairBackgroundInBoundBox[gargoyleData, gargoyleData.refresh.startBoundBox, TRUE, NIL]; PaintAllPlanes[screen, gargoyleData]; }; ObjectAdded: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { <> RepairBackgroundInBoundBox[gargoyleData, gargoyleData.refresh.startBoundBox, FALSE, gargoyleData.refresh.addedObject]; PaintAllPlanes[screen, gargoyleData]; }; RepairBackgroundInBoundBox: PROC [gargoyleData: GargoyleData, bBox: BoundBox, eraseFirst: BOOL _ FALSE, overObject: REF ANY] = { backgroundContext: Imager.Context _ gargoyleData.refresh.backgroundContext; backgroundBitmap: ImagerBackdoor.Bitmap _ gargoyleData.refresh.backgroundBitmap; IF gargoyleData.refresh.suppressRefresh THEN RETURN; IF gargoyleData.refresh.showColors.state = off THEN { PaintObjectsInBox: PROC = { IF eraseFirst THEN GGBoundBox.EraseWithinBoundBox[backgroundContext, bBox]; DrawObjectsFiltered[screen: backgroundContext, gargoyleData: gargoyleData, filter: bBox, overObject: overObject]; }; Imager.DoSaveAll[backgroundContext, PaintObjectsInBox]; gargoyleData.refresh.backgndBitmapOK _ TRUE; }; }; SelectionOrCaretChanged: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { <> PaintAllPlanes[screen, gargoyleData]; }; <<>> <> <<>> << Selection>> DuringSelect: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { <> chunkingContext: Imager.Context _ gargoyleData.refresh.chunkingContext; chunkingBitmap: ImagerBackdoor.Bitmap _ gargoyleData.refresh.chunkingBitmap; IF gargoyleData.refresh.suppressRefresh THEN RETURN; IF gargoyleData.refresh.showColors.state = off THEN { BackgroundBitsToChunking[gargoyleData]; <> CPFeedbackToChunking[gargoyleData, FALSE, FALSE]; ForegroundToChunking[gargoyleData]; CaretPlaneToChunking[gargoyleData]; ChunkingToScreen[screen: screen, gargoyleData: gargoyleData]; } ELSE {}; -- no feedback in SlowPaint mode }; << Adding and Dragging>> SplitBackgroundAndOverlay: PUBLIC PROC [gargoyleData: GargoyleData, restoreBox: BoundBox] = { <> PaintAllButOverlayed: PROC = { GGBoundBox.EraseWithinBoundBox[backgroundContext, restoreBox]; DrawObjectsFiltered[screen: backgroundContext, gargoyleData: gargoyleData, filter: restoreBox, excludeOverlay: TRUE, overObject: NIL]; }; backgroundContext: Imager.Context _ gargoyleData.refresh.backgroundContext; IF gargoyleData.refresh.suppressRefresh THEN RETURN; Imager.DoSaveAll[gargoyleData.refresh.backgroundContext, PaintAllButOverlayed]; }; -- end StoreBackground PaintDragOverlay: PROC [screen: Imager.Context, gargoyleData: GargoyleData, dragInProgress: BOOL] = { <> chunkingBitmap: ImagerBackdoor.Bitmap _ gargoyleData.refresh.chunkingBitmap; IF gargoyleData.refresh.suppressRefresh THEN RETURN; IF gargoyleData.refresh.showColors.state = off THEN { BackgroundBitsToChunking[gargoyleData]; OverlayToChunking[gargoyleData]; CPFeedbackToChunking[gargoyleData: gargoyleData, duringMotion: TRUE, dragInProgress: dragInProgress]; ForegroundToChunking[gargoyleData]; CaretPlaneToChunking[gargoyleData]; ChunkingToScreen[screen, gargoyleData]; } ELSE { DrawCPFeedback[screen, gargoyleData, TRUE, dragInProgress]; DrawForeground[screen, gargoyleData]; DrawCaretPlane[screen, gargoyleData]; }; }; FinishedAdding: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { <> MergeBackgroundAndOverlay[gargoyleData, gargoyleData.refresh.startBoundBox, FALSE, gargoyleData.refresh.addedObject]; PaintAllPlanes[screen, gargoyleData]; }; FinishedDragging: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { GGBoundBox.EnlargeByBox[gargoyleData.refresh.startBoundBox, GGBoundBox.BoundBoxOfMoving[gargoyleData.scene]]; MergeBackgroundAndOverlay[gargoyleData, gargoyleData.refresh.startBoundBox, TRUE, NIL]; PaintAllPlanes[screen, gargoyleData]; }; MergeBackgroundAndOverlay: PROC [gargoyleData: GargoyleData, bBox: BoundBox, eraseFirst: BOOL _ FALSE, overObject: REF ANY] = { <> backgroundContext: Imager.Context _ gargoyleData.refresh.backgroundContext; backgroundBitmap: ImagerBackdoor.Bitmap _ gargoyleData.refresh.backgroundBitmap; MergeBackgroundAndOverlayAux: PROC = { IF eraseFirst THEN GGBoundBox.EraseWithinBoundBox[backgroundContext, bBox]; DrawObjectsFiltered[screen: backgroundContext, gargoyleData: gargoyleData, filter: bBox, overObject: overObject]; }; IF gargoyleData.refresh.suppressRefresh THEN RETURN; IF gargoyleData.refresh.showColors.state = off THEN { Imager.DoSaveAll[backgroundContext, MergeBackgroundAndOverlayAux]; gargoyleData.refresh.backgndBitmapOK _ TRUE; }; }; <> <<>> BackgroundBitsToChunking: PROC [gargoyleData: GargoyleData] = { <> background: ImagerBackdoor.Bitmap _ gargoyleData.refresh.backgroundBitmap; chunkingContext: Imager.Context _ gargoyleData.refresh.chunkingContext; BackgroundBitsToChunkingAux: PROC [] = { AdjustContextForDrawBits[chunkingContext, gargoyleData]; IF gargoyleData.refresh.showColors.state = off THEN ImagerBackdoor.DrawBits[chunkingContext, background.base, background.wordsPerLine, 0, 0, background.height, background.width, 0, background.height] ELSE DrawPixels[chunkingContext, gargoyleData.refresh.backgroundPixelMap, gargoyleData]; <> }; IF gargoyleData.refresh.suppressRefresh THEN RETURN; Imager.DoSaveAll[chunkingContext, BackgroundBitsToChunkingAux]; }; OverlayToChunking: PROC [gargoyleData: GargoyleData] = { <> OverlayToChunkingAux: PROC [] = { DrawDragOverlay[chunkingContext, gargoyleData]; }; chunkingContext: Imager.Context _ gargoyleData.refresh.chunkingContext; Imager.DoSaveAll[chunkingContext, OverlayToChunkingAux]; }; BackgroundToChunking: PROC [gargoyleData: GargoyleData] = { chunkingContext: Imager.Context _ gargoyleData.refresh.chunkingContext; DrawBackground[chunkingContext, gargoyleData]; }; ForegroundToChunking: PROC [gargoyleData: GargoyleData] = { chunkingContext: Imager.Context _ gargoyleData.refresh.chunkingContext; DrawForeground[chunkingContext, gargoyleData]; }; CPFeedbackToChunking: PROC [gargoyleData: GargoyleData, duringMotion, dragInProgress: BOOL] = { chunkingContext: Imager.Context _ gargoyleData.refresh.chunkingContext; DrawCPFeedback[chunkingContext, gargoyleData, duringMotion, dragInProgress]; }; <> <> <> <<};>> <<>> CaretPlaneToChunking: PROC [gargoyleData: GargoyleData] = { chunkingContext: Imager.Context _ gargoyleData.refresh.chunkingContext; DrawCaretPlane[chunkingContext, gargoyleData]; }; ChunkingToScreen: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { ChunkingToScreenAux: PROC = { AdjustContextForDrawBits[screen, gargoyleData]; ImagerBackdoor.DrawBits[screen, chunkingBitmap.base, chunkingBitmap.wordsPerLine, 0, 0, chunkingBitmap.height, chunkingBitmap.width, 0, chunkingBitmap.height]; }; chunkingBitmap: ImagerBackdoor.Bitmap _ gargoyleData.refresh.chunkingBitmap; Imager.DoSaveAll[screen, ChunkingToScreenAux]; }; <<>> <> <<>> DrawDragOverlay: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { <> DrawDragOverlayAux: PROC = { IF gargoyleData.refresh.orderedOverlayList=NIL THEN gargoyleData.refresh.orderedOverlayList _ OrderOverlayList[gargoyleData]; -- update ordered list FOR oList: LIST OF REF ANY _ gargoyleData.refresh.orderedOverlayList, oList.rest UNTIL oList = NIL DO WITH oList.first SELECT FROM sliceD: SliceDescriptor => { sliceD.slice.class.drawTransform[sliceD.slice, sliceD.parts, screen, gargoyleData.camera, gargoyleData.drag.transform]; }; outlineD: OutlineDescriptor => { outlineD.slice.class.drawTransform[outlineD.slice, outlineD.parts, screen, gargoyleData.camera, gargoyleData.drag.transform]; }; traj: Traj => ERROR; caret: Caret => { caret _ NARROW[oList.first]; DrawCaret[screen, caret, Imager.black]; }; ENDCASE => ERROR; ENDLOOP; IF GGCaret.Exists[gargoyleData.anchor] THEN DrawAnchor[screen, gargoyleData.anchor, Imager.black]; -- a kludge for now, June 25, 1986, Bier }; Imager.DoSaveAll[screen, DrawDragOverlayAux]; }; DrawObjects: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { <> scene: Scene _ gargoyleData.scene; entityGen: EntityGenerator; Imager.SetColor[screen, Imager.black]; entityGen _ GGObjects.TopLevelEntitiesInScene[scene]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO WITH entity SELECT FROM outline: Outline => outline.class.drawParts[outline, NIL, screen, gargoyleData.camera, FALSE]; slice: Slice => slice.class.drawParts[slice, NIL, screen, gargoyleData.camera, FALSE]; ENDCASE => ERROR; ENDLOOP; }; DrawObjectsFiltered: PROC [screen: Imager.Context, gargoyleData: GargoyleData, filter: GGBoundBox.BoundBox, excludeOverlay: BOOL _ FALSE, overObject: REF ANY] = { <> 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 entityGen: EntityGenerator _ GGObjects.TopLevelEntitiesInScene[scene]; thisEntity: REF ANY _ GGObjects.NextEntity[entityGen]; IF overObject # NIL THEN { UNTIL thisEntity = overObject OR thisEntity = NIL DO thisEntity _ GGObjects.NextEntity[entityGen] ENDLOOP; IF thisEntity = NIL THEN RETURN; }; Imager.SetColor[screen, Imager.black]; GGBoundBox.Clip[dc: screen, bBox: filter]; FOR entity: REF ANY _ thisEntity, GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO WITH entity SELECT FROM outline: Outline => { IF excludeOverlay AND outline.onOverlay THEN LOOP; IF NOT OutsideOf[outline.class.getBoundBox[outline, NIL], filter] THEN outline.class.drawParts[outline, NIL, screen, gargoyleData.camera, FALSE]; }; slice: Slice => { IF excludeOverlay AND slice.onOverlay THEN LOOP; IF NOT OutsideOf[slice.class.getBoundBox[slice, NIL], filter] THEN slice.class.drawParts[slice, NIL, screen, gargoyleData.camera, FALSE]; }; ENDCASE => ERROR; ENDLOOP; }; scene: Scene _ gargoyleData.scene; IF filter=NIL OR filter.null THEN RETURN; Imager.DoSaveAll[screen, DrawObjectsFilteredAux]; }; DrawCaret: PROC [screen: Imager.Context, caret: Caret, color: Imager.Color] = { caretPos: Point _ GGCaret.GetPoint[caret]; IF NOT GGCaret.Exists[caret] THEN RETURN; Imager.SetColor[screen, color]; GGShapes.DrawCaret[screen, caretPos]; }; DrawAnchor: PROC [screen: Imager.Context, caret: Caret, color: Imager.Color] = { caretPos: Point _ GGCaret.GetPoint[caret]; IF NOT GGCaret.Exists[caret] THEN RETURN; Imager.SetColor[screen, color]; GGShapes.DrawAnchor[screen, caretPos]; }; DrawPixels: PROC [screen: Imager.Context, pm: ImagerPixelMap.PixelMap, gargoyleData: GargoyleData] = {}; <<>> <> DrawNewAnchor: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { anchorPos: Point _ GGCaret.GetPoint[gargoyleData.anchor]; Imager.SetColor[screen, Imager.black]; GGShapes.DrawAnchor[screen, anchorPos]; }; PaintSpot: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { Imager.SetColor[screen, Imager.black]; GGShapes.DrawSpot[screen, gargoyleData.refresh.spotPoint]; }; PaintHitLine: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { Imager.SetColor[screen, Imager.black]; Imager.SetStrokeEnd[screen, round]; Imager.MaskVector[screen, [gargoyleData.refresh.spotPoint.x, gargoyleData.refresh.spotPoint.y], [gargoyleData.refresh.hitPoint.x, gargoyleData.refresh.hitPoint.y]]; GGShapes.DrawFilledRect[screen, gargoyleData.refresh.spotPoint, 3.0]; }; PaintOddHitLine: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { Imager.SetColor[screen, Imager.black]; Imager.SetStrokeEnd[screen, round]; Imager.MaskVector[screen, [gargoyleData.refresh.spotPoint.x, gargoyleData.refresh.spotPoint.y], [gargoyleData.refresh.hitPoint.x, gargoyleData.refresh.hitPoint.y]]; GGShapes.DrawCP[screen, gargoyleData.refresh.spotPoint]; }; PaintAlign: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { <> GGGravity.DrawObjectBagRegardless[screen, NARROW[gargoyleData.hitTest.currentObjectBag], gargoyleData]; }; PaintTouchPoints: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { GGTouch.DrawAllTouchPoints[screen, gargoyleData]; }; PaintBoundBoxes: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { bBoxGen: BoundBoxGenerator; PaintBoundBoxesAux: PROC = { <> bBoxGen _ GGObjects.BoundBoxesInScene[gargoyleData.scene]; FOR box: BoundBox _ GGObjects.NextBox[bBoxGen], GGObjects.NextBox[bBoxGen] UNTIL box = NIL DO GGBoundBox.DrawBoundBox[screen, box]; ENDLOOP; }; Imager.DoSaveAll[screen, PaintBoundBoxesAux]; }; PaintTightBoxes: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { box: BoundBox; PaintTightBoxesAux: PROC = { <> entityGen: GGModelTypes.EntityGenerator; entityGen _ GGSelect.SelectedStuff[gargoyleData.scene, normal]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO WITH entity SELECT FROM sliceD: SliceDescriptor => { box _ sliceD.slice.class.getTightBox[sliceD.slice, sliceD.parts]; }; outlineD: OutlineDescriptor => { box _ outlineD.slice.class.getTightBox[outlineD.slice, outlineD.parts]; }; ENDCASE => ERROR; GGBoundBox.DrawBoundBox[screen, box]; ENDLOOP; }; Imager.DoSaveAll[screen, PaintTightBoxesAux]; }; PaintOutlineBoxes: PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { PaintBoundBoxesAux: PROC = { <> outSeqGen: GGSelect.OutlineSequenceGenerator; bBox: BoundBox; outSeqGen _ GGSelect.SelectedOutlineSequences[gargoyleData.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[screen, bBox]; }; FOR holeSeq: Sequence _ GGSequence.NextSequence[outSeq.holeSeqs], GGSequence.NextSequence[outSeq.holeSeqs] UNTIL holeSeq = NIL DO bBox _ GGTraj.GetBoundBox[holeSeq.traj]; GGBoundBox.DrawBoundBox[screen, bBox]; ENDLOOP; ENDLOOP; }; Imager.DoSaveAll[screen, PaintBoundBoxesAux]; }; PaintSelectionBox: PUBLIC PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { box: BoundBox _ NIL; PaintSelectionBoxAux: PROC = { <> box _ GGBoundBox.BoundBoxOfSelected[gargoyleData.scene]; IF NOT box.null THEN GGBoundBox.DrawBoundBox[screen, box]; }; Imager.DoSaveAll[screen, PaintSelectionBoxAux]; }; PaintMovingBox: PUBLIC PROC [screen: Imager.Context, gargoyleData: GargoyleData] = { box: BoundBox _ NIL; PaintMovingBoxAux: PROC = { <> box _ GGBoundBox.BoundBoxOfMoving[gargoyleData.scene]; IF NOT box.null THEN GGBoundBox.DrawBoundBox[screen, box]; }; Imager.DoSaveAll[screen, PaintMovingBoxAux]; }; EraseAll: PROC [screen: Imager.Context] = { rect: Imager.Rectangle; rect _ ImagerBackdoor.GetBounds[screen]; Imager.SetColor[screen, Imager.white]; Imager.MaskRectangle[screen, 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 GGVector; 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 _ GGVector.Normalize[GGVector.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 _ GGVector.Normalize[GGVector.Sub[tip, base]]; perp _ [axis.y, -axis.x]; Imager.Clip[dc, ClipPath, FALSE, TRUE]; }; }; DrawArrows: PROC [dc: Imager.Context, traj: Traj, gargoyleData: GargoyleData] = { 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]; }; <> MaskStroke: PROC [dc: Imager.Context, seg: Segment] = { MaskPath: Imager.PathProc = { moveTo[seg.lo]; seg.class.buildPath[seg, lineTo, curveTo, conicTo, arcTo]; }; Imager.MaskStroke[dc, MaskPath, FALSE]; }; DrawJoints: PROC [dc: Imager.Context, traj: Traj, gargoyleData: GargoyleData] = { <> <> <> <> <> <> IF gargoyleData.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, gargoyleData: GargoyleData, selectClass: SelectionClass _ normal] = { jointGen: JointGenerator; <> IF gargoyleData.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, gargoyleData: GargoyleData] = { <> SnapshotBackground[dc, gargoyleData]; DrawDragOverlay[dc, gargoyleData]; }; SnapshotBackground: PROC [dc: Imager.Context, gargoyleData: GargoyleData] = { <> scene: Scene _ gargoyleData.scene; entityGen: EntityGenerator; <> Imager.SetColor[dc, Imager.black]; <> entityGen _ GGObjects.TopLevelEntitiesInScene[gargoyleData.scene]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO WITH entity SELECT FROM outline: Outline => { IF OnOverlay[outline, gargoyleData] THEN LOOP ELSE outline.class.drawParts[outline, NIL, dc, gargoyleData.camera, FALSE]; }; slice: Slice => { IF OnOverlay[slice, gargoyleData] THEN LOOP ELSE slice.class.drawParts[slice, NIL, dc, gargoyleData.camera, FALSE]; }; ENDCASE => ERROR; ENDLOOP; <> IF NOT OnOverlay[gargoyleData.caret, gargoyleData] THEN DrawCaret[dc, gargoyleData.caret, Imager.black]; DrawAnchor[dc, gargoyleData.anchor, Imager.black]; <> GGGravity.DrawObjectBagRegardless[dc, NARROW[gargoyleData.hitTest.currentObjectBag], gargoyleData]; }; InterpressEntireScene: PUBLIC PROC [dc: Imager.Context, gargoyleData: GargoyleData] = { DrawObjects[dc, gargoyleData]; }; <<>> <> <<>> MoveToOverlay: PUBLIC PROC [entity: REF ANY, gargoyleData: GargoyleData] = { WITH entity SELECT FROM caret: Caret => { IF OnOverlay[caret, gargoyleData] THEN ERROR; GGCaret.TellOnOverlay[caret, TRUE]; gargoyleData.refresh.overlayList _ List.Nconc[LIST[caret], gargoyleData.refresh.overlayList]; }; < {>> <> <> <> <> <<}>> <<};>> outlineD: OutlineDescriptor => { IF OnOverlay[outlineD, gargoyleData] THEN ERROR; outlineD.slice.onOverlay _ TRUE; gargoyleData.refresh.overlayList _ List.Nconc[LIST[outlineD], gargoyleData.refresh.overlayList]; }; sliceD: SliceDescriptor => { IF OnOverlay[sliceD, gargoyleData] THEN ERROR; sliceD.slice.onOverlay _ TRUE; gargoyleData.refresh.overlayList _ List.Nconc[LIST[sliceD], gargoyleData.refresh.overlayList]; }; ENDCASE => ERROR; gargoyleData.refresh.orderedOverlayList _ NIL; }; MoveAllSelectedToOverlay: PUBLIC PROC [gargoyleData: GargoyleData, selectClass: SelectionClass] = { entityGen: EntityGenerator _ GGSelect.SelectedStuff[gargoyleData.scene, selectClass]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO MoveToOverlay[entity, gargoyleData]; ENDLOOP; }; MoveToBackground: PUBLIC PROC [entity: REF ANY, gargoyleData: GargoyleData] = { IF NOT OnOverlay[entity, gargoyleData] THEN RETURN; gargoyleData.refresh.overlayList _ List.DRemove[entity, gargoyleData.refresh.overlayList]; WITH entity SELECT FROM sliceD: SliceDescriptor => sliceD.slice.onOverlay _ FALSE; outline: Outline => outline.onOverlay _ FALSE; caret: Caret => GGCaret.TellOnOverlay[caret, FALSE]; ENDCASE => ERROR; gargoyleData.refresh.orderedOverlayList _ NIL; }; MoveOverlayToBackground: PUBLIC PROC [gargoyleData: GargoyleData] = { FOR overlayList: LIST OF REF ANY _ gargoyleData.refresh.overlayList, overlayList.rest UNTIL overlayList = NIL DO WITH overlayList.first SELECT FROM sliceD: SliceDescriptor => sliceD.slice.onOverlay _ FALSE; outlineD: OutlineDescriptor => outlineD.slice.onOverlay _ FALSE; caret: Caret => GGCaret.TellOnOverlay[caret, FALSE]; ENDCASE => ERROR; ENDLOOP; gargoyleData.refresh.overlayList _ NIL; gargoyleData.refresh.orderedOverlayList _ NIL; }; EmptyOverlay: PUBLIC PROC [gargoyleData: GargoyleData] RETURNS [BOOL] = { RETURN[gargoyleData.refresh.overlayList = NIL]; }; OnOverlay: PROC [entity: REF ANY, gargoyleData: GargoyleData] RETURNS [BOOL] = { WITH entity SELECT FROM caret: Caret => RETURN[GGCaret.IsOnOverlay[caret]]; outline: Outline => RETURN[outline.onOverlay]; slice: Slice => RETURN[slice.onOverlay]; sliceD: SliceDescriptor => RETURN[sliceD.slice.onOverlay]; outlineD: OutlineDescriptor => RETURN[outlineD.slice.onOverlay]; ENDCASE => ERROR; }; OrderOverlayList: PROC [gargoyleData: GargoyleData] RETURNS [orderedList: LIST OF REF ANY _ NIL] = { <> FindOverlayedD: PROC [slice: REF ANY] RETURNS [sliceD: REF ANY _ NIL] = { FOR ov: LIST OF REF ANY _ gargoyleData.refresh.overlayList, ov.rest UNTIL ov=NIL DO WITH ov.first SELECT FROM sliceD: SliceDescriptor => IF sliceD.slice=slice THEN RETURN[ov.first]; outlineD: OutlineDescriptor => IF outlineD.slice=slice THEN RETURN[ov.first]; ENDCASE => ERROR; ENDLOOP; RETURN[NIL]; }; sliceD: REF ANY; finger: LIST OF REF ANY; entityGen: EntityGenerator; [orderedList, finger] _ GGUtility.StartList[]; entityGen _ GGObjects.TopLevelEntitiesInScene[gargoyleData.scene]; FOR entity: REF ANY _ GGObjects.NextEntity[entityGen], GGObjects.NextEntity[entityGen] UNTIL entity = NIL DO IF OnOverlay[entity, gargoyleData] THEN { <> <> WITH entity SELECT FROM outline: Outline => { -- scene entity is identical to overlay entity sliceD _ FindOverlayedD[entity]; IF sliceD = NIL THEN sliceD _ outline.class.newParts[outline, NIL, topLevel]; [orderedList, finger] _ GGUtility.AddEntity[sliceD, orderedList, finger]; }; slice: Slice => { sliceD _ FindOverlayedD[entity]; IF sliceD = NIL THEN sliceD _ slice.class.newParts[slice, NIL, topLevel]; [orderedList, finger] _ GGUtility.AddEntity[sliceD, orderedList, finger]; }; caret: Caret => {}; -- fix up later ENDCASE => ERROR; }; ENDLOOP; IF OnOverlay[gargoyleData.caret, gargoyleData] THEN [orderedList, finger] _ GGUtility.AddEntity[gargoyleData.caret, orderedList, finger]; }; <<>> <> AdjustContextForDrawBits: PROC [dc: Imager.Context, gargoyleData: GargoyleData] = { <> viewerToClient: Imager.Transformation _ BiScrollers.GetStyle[].GetTransforms[BiScrollers.QuaBiScroller[gargoyleData.actionArea]].viewerToClient; Imager.ConcatT[dc, viewerToClient]; }; InitStats: PROC [] = { interval: GGStatistics.Interval; interval _ GGStatistics.CreateInterval[$PaintEntireScene]; GGStatistics.AddInterval[interval, GGStatistics.GlobalTable[]]; }; InitStats[]; END. <> <>