DIRECTORY Atom, BufferedRefresh, CodeTimer, CoordSys, FunctionCache, SVGraphics, DisplayListToTree, Feedback, GList, Imager, ImagerPath, ImagerTransformation, Matrix3d, Preprocess3d, PriorityQueue, Real, Rope, SV2d, SV3d, SVAlign, SVAssembly, SVBasicTypes, SVBoundBox, SVCaret, SVDraw3d, SVFiles, SVImage, SVInterfaceTypes, SVModelTypes, SVRefresh, SVScene, SVSceneTypes, SVSelect, SVSelections, SVState, SVUtility; SVRefreshImpl: CEDAR PROGRAM IMPORTS Atom, BufferedRefresh, CodeTimer, CoordSys, FunctionCache, SVGraphics, DisplayListToTree, Feedback, GList, Imager, ImagerTransformation, Matrix3d, Preprocess3d, PriorityQueue, Rope, SVAlign, SVAssembly, SVBoundBox, SVCaret, SVDraw3d, SVFiles, SVImage, SVScene, SVSelect, SVSelections, SVState, SVUtility EXPORTS SVRefresh = BEGIN ArtworkToolData: TYPE = SVInterfaceTypes.ArtworkToolData; AssemblyGenerator: TYPE = SVScene.AssemblyGenerator; SliceList: TYPE = SVSceneTypes.SliceList; BoundBox: TYPE = SVBasicTypes.BoundBox; Camera: TYPE = SVModelTypes.Camera; Color: TYPE = Imager.Color; CoordSysGenerator: TYPE = SVScene.CoordSysGenerator; CoordSystem: TYPE = SVModelTypes.CoordSystem; CSGTree: TYPE = SVSceneTypes.CSGTree; EditToolData: TYPE = SVInterfaceTypes.EditToolData; FeatureData: TYPE = SVInterfaceTypes.FeatureData; FrameBox: TYPE = SVModelTypes.FrameBox; Matrix4by4: TYPE = SVModelTypes.Matrix4by4; PlanarSurface: TYPE = SVSceneTypes.PlanarSurface; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Rectangle: TYPE = Imager.Rectangle; Sandwich: TYPE = BufferedRefresh.Sandwich; Scene: TYPE = SVSceneTypes.Scene; Selection: TYPE = SVInterfaceTypes.Selection; SelectionClass: TYPE = SVSelect.SelectionClass; SelectionGenerator: TYPE = SVInterfaceTypes.SelectionGenerator; SelectionType: TYPE = SVInterfaceTypes.SelectionType; -- {target, movee, plane}; Shape: TYPE = SVSceneTypes.Shape; Skitter: TYPE = SVSceneTypes.Skitter; Slice: TYPE = SVSceneTypes.Slice; SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = SVSceneTypes.SliceDescriptorGenerator; SliceParts: TYPE = SVSceneTypes.SliceParts; ToolData: TYPE = SVSceneTypes.ToolData; SVData: TYPE = SVInterfaceTypes.SVData; CreateSandwich: PUBLIC PROC [] RETURNS [sandwich: Sandwich] = { sandwich _ BufferedRefresh.CreateSandwich[LIST[ [$Background, TRUE, RefreshBackground], -- back ... [$Overlay, FALSE, RefreshOverlay], [$SelectionPlane, FALSE, RefreshSelectionPlane], [$Foreground, TRUE, RefreshForeground], [$SkitterPlane, FALSE, RefreshSkitterPlane]]]; -- ... to front }; ActionAreaPaint: PUBLIC PROC [screen: Imager.Context, whatHasChanged: ATOM, svData: SVData] = { DoActionAreaPaint[screen, whatHasChanged, svData]; }; DoActionAreaPaint: PROC [screen: Imager.Context, whatHasChanged: ATOM, svData: SVData] = { showColors: BOOL; IF svData.refresh.suppressRefresh THEN RETURN; showColors _ SVState.GetShowColors[svData]; SELECT whatHasChanged FROM $None => NULL; $PaintEntireScene, $ViewersPaintEntireScene => PaintEntireScene[screen, svData, showColors]; $NewAlignmentsDeselected => PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; $NewAlignmentsSelected => PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; $SequencesMadeHot => PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; $SequencesMadeCold => PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; $SelectionChanged => SelectionOrCaretChanged[screen, svData, showColors]; $FinishedDragging => FinishedDragging[screen, svData, showColors]; $SkitterMoved => SelectionOrCaretChanged[screen, svData, showColors]; $AnchorAdded => PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; $AnchorRemoved => PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; $FrameChanged => PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; $DrawPlane => PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; $DuringMotion => PaintDragOverlay[screen, svData, TRUE, showColors]; $DuringSkitterPos => PaintDragOverlay[screen, svData, FALSE, showColors]; $DuringSelect => DuringSelect[screen, svData, showColors]; $ObjectChangedBoundBoxProvided => PaintEntireScene[screen, svData, showColors]; $ObjectAdded => PaintEntireScene[screen, svData, showColors]; $DrawBlackAndWhite => DrawBlackAndWhite[screen, svData]; $DrawColor => DrawColor[screen, svData]; $DrawCoordSystems => DrawCoordSystems[screen, svData]; $DrawBoundBoxes => DrawBoundBoxes[screen, svData]; $DrawBoundSpheres => DrawBoundSpheres[screen, svData]; $DrawRayCastProgress => DrawRayCastProgress[screen, svData]; $DrawCrossHairs => DrawCrossHairs[screen, svData]; $DrawPt => DrawPt[screen, svData]; $DrawPaint => DrawPaint[screen, svData]; $PaintSpot => PaintSpot[screen, svData]; $PaintHitLine => PaintHitLine[screen, svData]; ENDCASE => { Feedback.Append[svData.feedback, Rope.Cat["SVRefreshImpl doesn't know how to ", Atom.GetPName[whatHasChanged], "."], oneLiner]; Feedback.Blink[svData.feedback]; }; }; DrawRayCastProgress: PROC [screen: Imager.Context, svData: SVData] = { camera: Camera _ svData.camera; width: REAL _ 10; box: Imager.Rectangle; lowLeft, upRight: Point2d; currentY, minX, minY, maxX, maxY: REAL; currentY _ svData.refresh.currentY; minX _ svData.refresh.minX; minY _ svData.refresh.minY; maxX _ svData.refresh.maxX; maxY _ svData.refresh.maxY; lowLeft _ CoordSys.CameraToScreen[[minX, minY], camera.screenCS]; upRight _ CoordSys.CameraToScreen[[maxX, currentY], camera.screenCS]; box _ [lowLeft[1], lowLeft[2], upRight[1] - lowLeft[1], upRight[2] - lowLeft[2]]; Imager.SetColor[screen, Imager.black]; Imager.MaskRectangle[screen, box]; }; PaintEntireScene: PROC [screen: Imager.Context, svData: SVData, showColors: BOOL] = { sandwich: BufferedRefresh.Sandwich _ svData.refresh.sandwich; CodeTimer.StartInt[$PaintEntireScene, $Solidviews]; BufferedRefresh.SetLayerOK[sandwich, $Foreground, FALSE]; BufferedRefresh.SetLayerOK[sandwich, $Background, FALSE]; PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; CodeTimer.StopInt[$PaintEntireScene, $Solidviews]; }; PaintAllPlanes: PROC [screen: Imager.Context, svData: SVData, showColors: BOOL, caretIsMoving: BOOL, dragInProgress: BOOL] = { sandwich: BufferedRefresh.Sandwich _ svData.refresh.sandwich; clientToViewer, viewerToClient: Imager.Transformation; ignoreBackingMap: BOOL; IF svData.refresh.suppressRefresh THEN RETURN; svData.refresh.caretIsMoving _ caretIsMoving; svData.refresh.dragInProgress _ dragInProgress; clientToViewer _ viewerToClient _ ImagerTransformation.Scale[1.0]; ignoreBackingMap _ showColors; BufferedRefresh.DrawSandwich[sandwich, screen, clientToViewer, viewerToClient, svData, ignoreBackingMap]; }; RefreshBackground: PROC [dc: Imager.Context, boundRect: Rectangle, clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; camera: Camera _ svData.camera; lo, hi: Point2d; lo _ [boundRect.x, boundRect.y]; -- in screen coords hi _ [boundRect.x + boundRect.w, boundRect.y + boundRect.h]; lo _ CoordSys.ScreenToCamera[lo, camera.screenCS]; hi _ CoordSys.ScreenToCamera[hi, camera.screenCS]; DrawObjectsFiltered[dc, svData, SVBoundBox.BoundBoxFromValues[lo[1], lo[2], hi[1], hi[2]], FALSE, -Real.LargestNumber]; }; RefreshOverlay: PROC [dc: Imager.Context, boundRect: Rectangle, clientData: REF ANY] = { DrawDragOverlayAux: PROC = { IF svData.refresh.orderedOverlayList=NIL THEN svData.refresh.orderedOverlayList _ OrderOverlayList[svData]; -- update ordered list SELECT camera.style FROM wire, normals => { FOR list: LIST OF SliceDescriptor _ svData.refresh.orderedOverlayList, list.rest UNTIL list = NIL DO SVAssembly.DrawTransform[list.first, dc, scene, camera, svData.drag.transform]; ENDLOOP; }; shaded => { predictedBufferSize: NAT _ CountSurfacesInAssembly[scene.assembly]; polygonBuffer: PriorityQueue.Ref _ PriorityQueue.Predict[predictedBufferSize, DeeperPlanarPolygon]; FOR list: LIST OF SliceDescriptor _ svData.refresh.orderedOverlayList, list.rest UNTIL list = NIL DO SVAssembly.AddPolygonsToBufferTransform[polygonBuffer, list.first, scene, camera, svData.drag.transform]; ENDLOOP; SVAssembly.DrawBuffer[dc, polygonBuffer, scene, camera]; }; ENDCASE => ERROR; }; svData: SVData _ NARROW[clientData]; scene: Scene _ svData.scene; camera: Camera _ svData.camera; filter: BoundBox _ SVBoundBox.BoundBoxFromRectangle[boundRect, camera]; IF svData.refresh.suppressRefresh THEN RETURN; Imager.DoSaveAll[dc, DrawDragOverlayAux]; }; RefreshSelectionPlane: PROC [dc: Imager.Context, boundRect: Rectangle, clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; camera: Camera _ svData.camera; scene: Scene _ svData.scene; caretIsMoving: BOOL _ svData.refresh.caretIsMoving; dragInProgress: BOOL _ svData.refresh.dragInProgress; IF svData.refresh.suppressRefresh THEN RETURN; IF svData.camera.quality#quality THEN { DrawAttractorFeedback[dc, svData, dragInProgress, caretIsMoving]; DrawCpsOfSelectedSlices[dc, scene, camera, dragInProgress, caretIsMoving]; }; IF caretIsMoving OR dragInProgress THEN RETURN; Imager.SetColor[dc, Imager.black]; IF svData.showCoordSys THEN DrawCoordSystems[dc, svData]; DrawAnySelectionsDCAux[dc, movee, svData, scene, camera]; DrawAnySelectionsDCAux[dc, target, svData, scene, camera]; DrawAnySelectionsDCAux[dc, plane, svData, scene, camera]; }; RefreshForeground: PROC [dc: Imager.Context, boundRect: Rectangle, clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; IF SVState.GetSuppressRefresh[svData] THEN RETURN; FunctionCache.Flush[svData.refresh.lineCache]; SVAlign.DrawAlignBagRegardless[dc, svData.hitTest.alignBag, svData]; }; RefreshSkitterPlane: PROC [dc: Imager.Context, boundRect: Rectangle, clientData: REF ANY] = { svData: SVData _ NARROW[clientData]; camera: Camera _ svData.camera; Imager.SetColor[dc, Imager.black]; DrawSkitter[dc, svData.editToolData, camera]; DrawAnchor[dc, svData, camera]; }; NoteNewForeground: PUBLIC PROC [alignObjects: LIST OF FeatureData, svData: SVData] = { PaintForeground: PROC = { SVAlign.DrawFeatureList[foregroundContext, alignObjects, svData]; }; foregroundContext: Imager.Context _ BufferedRefresh.GetLayerContext[svData.refresh.sandwich, $Foreground]; Imager.DoSave[foregroundContext, PaintForeground]; BufferedRefresh.SetLayerOK[svData.refresh.sandwich, $Foreground, TRUE]; }; DrawAttractorFeedback: PROC [dc: Imager.Context, svData: SVData, dragInProgress, caretIsMoving: BOOL] = { skitter: Skitter _ svData.editToolData.skitter; scene: Scene _ svData.scene; attractor: SliceDescriptor _ SVCaret.GetAttractor[skitter]; IF attractor#NIL THEN { selectedD: SliceDescriptor _ SVSelect.FindSelectedSlice[attractor.slice, scene, normal]; selectedParts: SliceParts _ IF selectedD = NIL THEN NIL ELSE selectedD.parts; SVAssembly.DrawAttractorFeedback[attractor, selectedParts, dragInProgress, dc, svData.camera]; }; }; DrawCpsOfSelectedSlices: PROC [dc: Imager.Context, scene: Scene, camera: Camera, 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 _ SVSelect.FindSelectedSlice[slice, scene, normal]; hotSliceD _ SVSelect.FindSelectedSlice[slice, scene, hot]; normalParts _ IF normalSliceD # NIL THEN normalSliceD.parts ELSE NIL; hotParts _ IF hotSliceD # NIL THEN hotSliceD.parts ELSE NIL; SVAssembly.DrawSelectionFeedback[slice, normalParts, hotParts, dc, camera, dragInProgress, caretIsMoving, FALSE, caretIsMoving]; ENDLOOP; }; AllSelectedSlices: PROC [scene: Scene] RETURNS [selectedList: LIST OF Slice _ NIL] = { ptr: LIST OF Slice; sGen: SliceDescriptorGenerator _ SVSelect.SelectedSlices[scene, hot]; [selectedList, ptr] _ SVUtility.StartSliceList[]; FOR sd: SliceDescriptor _ SVSelect.NextSliceDescriptor[sGen], SVSelect.NextSliceDescriptor[sGen] UNTIL sd = NIL DO [selectedList, ptr] _ SVUtility.AddSlice[sd.slice, selectedList, ptr]; ENDLOOP; sGen _ SVSelect.SelectedSlices[scene, normal]; FOR sd: SliceDescriptor _ SVSelect.NextSliceDescriptor[sGen], SVSelect.NextSliceDescriptor[sGen] UNTIL sd = NIL DO IF NOT SVSelect.IsSelectedInPart[sd.slice, scene, hot] THEN [selectedList, ptr] _ SVUtility.AddSlice[sd.slice, selectedList, ptr]; ENDLOOP; }; DrawAnySelectionsDCAux: PROC [dc: Imager.Context, selType: SelectionType, svData: SVData, scene: Scene, camera: Camera] = { g: SelectionGenerator; selectionsExist: BOOL; [g, selectionsExist] _ SVSelections.GetSelectionGenerator[selType]; IF NOT selectionsExist THEN RETURN; FOR sel: Selection _ SVSelections.NextSelection[g], SVSelections.NextSelection[g] UNTIL sel = NIL DO IF sel.svData = svData THEN { DrawSelectionDC[dc, sel, svData]; }; ENDLOOP; }; DrawSelectionDC: PROC [dc: Imager.Context, sel: Selection, svData: SVData] = { DrawSelectionDCAux: SAFE PROC = { Imager.SetColor[dc, Imager.black]; SELECT sel.selectionType FROM target => { csCAMERA: Matrix4by4; csCAMERA _ CoordSys.WRTCamera[sel.coincident.coordSys, camera.coordSys]; SVDraw3d.DrawTargetCoordSys[dc, csCAMERA, camera]; }; movee => SVDraw3d.DrawMovee[dc, sel.coincident.coordSys, camera]; plane => { toolData: ToolData; planeAssem: Slice; planeAssem _ sel.coincident; IF planeAssem.toolMasterObject = NIL OR planeAssem.toolMasterObject.mainBody = NIL THEN ERROR; toolData _ NARROW[planeAssem.toolMasterObject.mainBody]; SVDraw3d.DrawPlaneSelection[dc, sel.coincident.coordSys, toolData.plane, camera]; }; ENDCASE => ERROR; }; camera: Camera; IF svData # sel.svData THEN RETURN; camera _ svData.camera; Imager.DoSave[dc, DrawSelectionDCAux]; }; DrawSkitter: PROC [dc: Imager.Context, editToolData: EditToolData, camera: Camera] = { skitterWORLD, skitterCAMERA: Matrix4by4; skitter: Skitter _ editToolData.skitter; IF NOT SVCaret.Exists[skitter] THEN RETURN; skitterWORLD _ SVCaret.GetPosition[skitter]; skitterCAMERA _ Matrix3d.AInTermsOfB[skitterWORLD, CoordSys.WRTWorld[camera.coordSys]]; Imager.SetColor[dc, Imager.black]; SVDraw3d.DrawSkitter[dc, skitterCAMERA, camera]; }; DrawAnchor: PROC [dc: Imager.Context, svData: SVData, camera: Camera] = { anchorWORLD, anchorCAMERA: Matrix4by4; scene: Scene _ svData.scene; IF NOT SVCaret.Exists[scene.anchor] THEN RETURN; anchorWORLD _ SVCaret.GetPosition[scene.anchor]; anchorCAMERA _ Matrix3d.AInTermsOfB[anchorWORLD, CoordSys.WRTWorld[camera.coordSys]]; Imager.SetColor[dc, Imager.black]; SVDraw3d.DrawTargetCoordSys[dc, anchorCAMERA, camera]; }; OutsideOf: PROC [test, bound: SVBoundBox.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 >= }; DeeperPlanarPolygon: PROC [x,y: PriorityQueue.Item, data: REF _ NIL] RETURNS [BOOL] = { xS: PlanarSurface _ NARROW[x]; yS: PlanarSurface _ NARROW[y]; RETURN[xS.depth < yS.depth]; }; DrawObjectsFiltered: PROC [dc: Imager.Context, svData: SVData, filter: BoundBox, excludeOverlay: BOOL _ FALSE, selectedDepth: REAL _ -Real.LargestNumber] = { DrawObjectsFilteredAux: PROC = { -- need to clip to filter, then image g: AssemblyGenerator _ SVScene.PrimAssembliesInScene[scene]; thisSlice: Slice _ SVScene.NextAssembly[g]; Imager.SetColor[dc, Imager.black]; SVBoundBox.Clip[dc: dc, bBox: filter, screen: camera.screenCS]; SELECT camera.style FROM wire, normals => { FOR slice: Slice _ thisSlice, SVScene.NextAssembly[g] UNTIL slice = NIL DO IF excludeOverlay AND slice.onOverlay THEN LOOP; IF NOT SVBoundBox.OutsideOf[SVAssembly.GetBoundBox[slice, NIL, camera], filter] THEN SVAssembly.DrawParts[slice, NIL, dc, scene, camera, FALSE]; ENDLOOP; }; shaded => { predictedBufferSize: NAT _ CountSurfacesInAssembly[scene.assembly]; polygonBuffer: PriorityQueue.Ref _ PriorityQueue.Predict[predictedBufferSize, DeeperPlanarPolygon]; FOR slice: Slice _ thisSlice, SVScene.NextAssembly[g] UNTIL slice = NIL DO IF excludeOverlay AND slice.onOverlay THEN LOOP; IF NOT SVBoundBox.OutsideOf[SVAssembly.GetBoundBox[slice, NIL, camera], filter] THEN SVAssembly.AddPolygonsToBuffer[polygonBuffer, slice, camera]; ENDLOOP; SVAssembly.DrawBuffer[dc, polygonBuffer, scene, camera]; }; ENDCASE => ERROR; }; scene: Scene _ svData.scene; camera: Camera _ svData.camera; IF filter=NIL OR filter.null THEN RETURN; Imager.DoSaveAll[dc, DrawObjectsFilteredAux]; }; CountSurfacesInAssembly: PROC [assembly: Slice] RETURNS [surfCount: NAT] = { WITH assembly.shape SELECT FROM assems: SliceList => surfCount _ CountSurfacesInAssemblyList[assems]; shape: Shape => surfCount _ shape.mo.class.countSurf[shape.mo]; ENDCASE => ERROR; }; CountSurfacesInAssemblyList: PROC [asl: SliceList] RETURNS [surfCount: NAT] = { surfCount _ 0; FOR list: LIST OF Slice _ asl.list, list.rest UNTIL list = NIL DO surfCount _ surfCount + CountSurfacesInAssembly[list.first]; ENDLOOP; }; DrawCPFeedback: PROC [dc: Imager.Context, svData: SVData, caretIsMoving, dragInProgress: BOOL] = { }; SelectionOrCaretChanged: PROC [screen: Imager.Context, svData: SVData, showColors: BOOL] = { PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; }; DepthOfAssembly: PROC [slice: REF ANY] RETURNS [depth: REAL] = { depth _ -Real.LargestNumber; }; ObjectAdded: PROC [screen: Imager.Context, svData: SVData, showColors: BOOL] = { assembly: Slice _ NARROW[svData.refresh.addedObject]; bBox: BoundBox _ NIL; selectedDepth: REAL _ DepthOfAssembly[svData.refresh.addedObject]; RepairBackgroundInBoundBox[svData, bBox, FALSE, selectedDepth, showColors]; PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; }; RepairBackgroundInBoundBox: PROC [svData: SVData, bBox: BoundBox, eraseFirst: BOOL _ FALSE, selectedDepth: REAL, showColors: BOOL] = { backgroundContext: Imager.Context _ BufferedRefresh.GetLayerContext[svData.refresh.sandwich, $Background]; IF NOT showColors THEN { PaintObjectsInBox: PROC = { DrawObjectsFiltered[dc: backgroundContext, svData: svData, filter: bBox, selectedDepth: selectedDepth]; }; Imager.DoSaveAll[backgroundContext, PaintObjectsInBox]; BufferedRefresh.SetLayerOK[svData.refresh.sandwich, $Background, TRUE]; }; }; PaintDragOverlay: PROC [screen: Imager.Context, svData: SVData, dragInProgress: BOOL, showColors: BOOL] = { clientToViewer, viewerToClient: Imager.Transformation; svData.refresh.dragInProgress _ dragInProgress; svData.refresh.caretIsMoving _ TRUE; clientToViewer _ viewerToClient _ ImagerTransformation.Scale[1.0]; BufferedRefresh.DrawSandwich[svData.refresh.sandwich, screen, clientToViewer, viewerToClient, svData, showColors]; }; BackmostSelectedDepth: PROC [scene: Scene] RETURNS [selectedDepth: REAL] = { RETURN[-Real.LargestNumber]; }; FinishedDragging: PROC [screen: Imager.Context, svData: SVData, showColors: BOOL] = { scene: Scene _ svData.scene; camera: Camera _ svData.camera; selectedDepth: REAL _ BackmostSelectedDepth[scene]; SVBoundBox.EnlargeByBox[svData.refresh.startBoundBox, SVBoundBox.BoundBoxOfMoving[scene, camera]]; MergeBackgroundAndOverlay[svData, svData.refresh.startBoundBox, TRUE, selectedDepth, showColors]; PaintAllPlanes[screen, svData, showColors, FALSE, FALSE]; }; MergeBackgroundAndOverlay: PROC [svData: SVData, bBox: BoundBox, eraseFirst: BOOL _ FALSE, selectedDepth: REAL, showColors: BOOL] = { MergeBackgroundAndOverlayAux: PROC = { IF eraseFirst THEN SVBoundBox.EraseWithinBoundBox[backgroundContext, bBox, camera.screenCS]; DrawObjectsFiltered[dc: backgroundContext, svData: svData, filter: bBox, selectedDepth: selectedDepth]; }; camera: Camera _ svData.camera; backgroundContext: Imager.Context _ BufferedRefresh.GetLayerContext[svData.refresh.sandwich, $Background]; IF svData.refresh.suppressRefresh THEN RETURN; IF NOT showColors THEN { Imager.DoSaveAll[backgroundContext, MergeBackgroundAndOverlayAux]; BufferedRefresh.SetLayerOK[svData.refresh.sandwich, $Background, TRUE]; }; }; DuringSelect: PROC [screen: Imager.Context, svData: SVData, showColors: BOOL] = { IF svData.refresh.suppressRefresh THEN RETURN; IF NOT showColors THEN { clientToViewer, viewerToClient: Imager.Transformation; clientToViewer _ viewerToClient _ ImagerTransformation.Scale[1.0]; BufferedRefresh.DrawSandwich[svData.refresh.sandwich, screen, clientToViewer, viewerToClient, svData, showColors]; } ELSE {}; -- no feedback in SlowPaint mode }; SplitBackgroundAndOverlay: PUBLIC PROC [svData: SVData, restoreBox: BoundBox] = { PaintAllButOverlayed: PROC = { SVBoundBox.EraseWithinBoundBox[backgroundContext, restoreBox, camera.screenCS]; DrawObjectsFiltered[dc: backgroundContext, svData: svData, filter: restoreBox, excludeOverlay: TRUE, selectedDepth: -Real.LargestNumber]; }; backgroundContext: Imager.Context; camera: Camera _ svData.camera; IF svData.refresh.suppressRefresh THEN RETURN; backgroundContext _ BufferedRefresh.GetLayerContext[svData.refresh.sandwich, $Background]; Imager.DoSaveAll[backgroundContext, PaintAllButOverlayed]; }; DrawColor: PROC [dc: Imager.Context, svData: SVData] = { scene: Scene _ svData.scene; resolution: REAL; boundBox: BoundBox; minX, minY, maxX, maxY: REAL; camera: Camera _ svData.camera; tree: CSGTree; screenMat: Matrix4by4; aisRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[scene.name], ".ais"]; resolution _ camera.resolution; tree _ DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera]; [minX, minY, maxX, maxY] _ MinAndMaxFromCameraAndTree[camera, tree]; boundBox _ SVBoundBox.BoundBoxFromValues[minX, minY, maxX, maxY]; screenMat _ CoordSys.GetMat[camera.screenCS]; SVImage.DrawAlignedColorImage[dc, aisRope, resolution, [screenMat[1][4], screenMat[2][4]], boundBox, svData.feedback]; }; DrawBlackAndWhite: PROC [dc: Imager.Context, svData: SVData] = { scene: Scene _ svData.scene; camera: Camera _ svData.camera; resolution: REAL; boundBox: BoundBox; minX, minY, maxX, maxY: REAL; tree: CSGTree; screenMat: Matrix4by4; aisRope: Rope.ROPE _ Rope.Concat[SVFiles.FilenameMinusExtension[scene.name], ".ais"]; resolution _ camera.resolution; tree _ DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera]; [minX, minY, maxX, maxY] _ MinAndMaxFromCameraAndTree[camera, tree]; boundBox _ SVBoundBox.BoundBoxFromValues[minX, minY, maxX, maxY]; screenMat _ CoordSys.GetMat[camera.screenCS]; SVImage.DrawAlignedBlackAndWhiteImage[dc, aisRope, resolution, [screenMat[1][4], screenMat[2][4]], boundBox, svData.feedback]; Imager.SetColor[dc, Imager.black]; SVGraphics.DrawFrame [dc, camera]; }; MinAndMaxFromCameraAndTree: PROC [camera: Camera, tree: CSGTree] RETURNS [minX, minY, maxX, maxY: REAL] = { frame: FrameBox _ camera.frame; boundBox: BoundBox; defaultHalfSide: REAL = 100.0; IF frame.fullScreen THEN { [boundBox] _ Preprocess3d.PreprocessForInteraction[tree, camera]; IF boundBox = NIL THEN { minX _ minY _ -defaultHalfSide; maxX _ maxY _ defaultHalfSide; } ELSE { minX _ boundBox.loX; minY _ boundBox.loY; maxX _ boundBox.hiX; maxY _ boundBox.hiY; }; } ELSE { minX _ frame.downLeft[1]; minY _ frame.downLeft[2]; maxX _ frame.upRight[1]; maxY _ frame.upRight[2]; }; }; DrawCoordSystems: PROC [dc: Imager.Context, svData: SVData] = { scene: Scene _ svData.scene; camera: Camera _ svData.camera; g: CoordSysGenerator _ SVScene.GetCoordSysGenerator[scene]; mat: Matrix4by4; FOR cs: CoordSystem _ SVScene.NextCoordSys[g], SVScene.NextCoordSys[g] UNTIL cs = NIL DO mat _ CoordSys.WRTCamera[cs, camera.coordSys]; SVDraw3d.DrawCoordSys[dc, mat, camera]; ENDLOOP; }; DrawBoundBoxes: PROC [dc: Imager.Context, svData: SVData] = { scene: Scene _ svData.scene; camera: Camera _ svData.camera; bBox: BoundBox; g: SVScene.AssemblyGenerator _ SVScene.PrimAssembliesInScene[scene]; FOR slice: Slice _ SVScene.NextAssembly[g], SVScene.NextAssembly[g] UNTIL slice = NIL DO bBox _ SVAssembly.GetBoundBox[slice, NIL, camera]; SVBoundBox.DrawBoundBox[dc, bBox, camera.screenCS]; ENDLOOP; }; DrawBoundSpheres: PROC [dc: Imager.Context, svData: SVData] = { scene: Scene _ svData.scene; camera: Camera _ svData.camera; tree: CSGTree; tree _ DisplayListToTree.AssemblyToTree[scene.assembly, scene, camera]; -- does a TellAboutCameraAndWorld [] _ Preprocess3d.PreprocessForCatScan[tree, camera]; -- computes the bounding spheres SVDraw3d.DrawBoundSpheres[dc, tree, camera]; }; DrawCrossHairs: PROC [dc: Imager.Context, svData: SVData] = { camera: Camera _ svData.camera; SVDraw3d.Draw2dCoordSys[dc, [0,0], camera]; }; DrawPt: PROC [dc: Imager.Context, svData: SVData] = { camera: Camera _ svData.camera; x, y: REAL; [x, y] _ SVUtility.ReadTwoReals[svData.textSection.xyz]; SVDraw3d.DrawX[dc, [x, y], camera]; }; DrawPaint: PROC [dc: Imager.Context, svData: SVData] = { OPEN Matrix3d; camera: Camera _ svData.camera; skitterWORLD, worldCamera: Matrix4by4; path: ImagerPath.Trajectory; editToolData: EditToolData _ svData.editToolData; skitter: Skitter _ editToolData.skitter; artworkToolData: ArtworkToolData _ NARROW[editToolData.artworkTool.data]; paintColor: Color _ artworkToolData.paintColor; skitterWORLD _ SVCaret.GetPosition[skitter]; worldCamera _ CoordSys.FindWorldInTermsOf[camera.coordSys]; SVGraphics.MoveToAbsolute[path, Update[Update[[-2, -2, 0], skitterWORLD], worldCamera], camera]; SVGraphics.LineToAbsolute[path, Update[Update[[-2, 2, 0], skitterWORLD], worldCamera], camera]; SVGraphics.LineToAbsolute[path, Update[Update[[2, 2, 0], skitterWORLD], worldCamera], camera]; SVGraphics.LineToAbsolute[path, Update[Update[[2, -2, 0], skitterWORLD], worldCamera], camera]; Imager.SetColor[dc, paintColor]; SVGraphics.DrawStroke[dc, path, 1, TRUE]; }; PaintSpot: PUBLIC PROC [dc: Imager.Context, svData: SVData] = { spotPoint: Point2d _ svData.refresh.spotPoint; camera: Camera _ svData.camera; SVDraw3d.DrawX[dc, spotPoint, camera]; }; PaintHitLine: PUBLIC PROC [dc: Imager.Context, svData: SVData] = { spotPoint: Point2d _ svData.refresh.spotPoint; -- in Camera hitPoint: Point3d _ svData.refresh.hitPoint; -- in WORLD scene: Scene _ svData.scene; camera: Camera _ svData.camera; hitPoint _ CoordSys.FromCSToCS[hitPoint, scene.coordSysRoot, camera.coordSys]; SVGraphics.SetCPAbsolute[dc, [spotPoint[1], spotPoint[2], 0.0], camera]; SVGraphics.DrawToAbsolute[dc, hitPoint, camera]; }; SnapShot: PUBLIC PROC [dc: Imager.Context, svData: SVData] = { boundRect: Rectangle _ [x: 0.0, y: 0.0, w: 8.5*72.0, h: 11.0*72.0]; -- room for 8.5 by 11 pictures for now SnapshotBackground[dc, svData]; RefreshOverlay[dc, boundRect, svData]; -- fortunately, RefreshOverlay doesn't use boundRect }; SnapshotBackground: PROC [dc: Imager.Context, svData: SVData] = { scene: Scene _ svData.scene; camera: Camera _ svData.camera; sliceGen: AssemblyGenerator; sliceGen _ SVScene.PrimAssembliesInScene[scene]; RefreshBackground[dc, SVState.GetViewport[svData], svData]; DrawAttractorFeedback[dc, svData, svData.refresh.dragInProgress, svData.refresh.caretIsMoving]; FunctionCache.Flush[svData.refresh.lineCache]; -- need to fully refresh foreground SVAlign.DrawAlignBagRegardless[dc, svData.hitTest.alignBag, svData]; DrawSkitter[dc, svData.editToolData, camera]; DrawAnchor[dc, svData, camera]; }; InterpressEntireScene: PUBLIC PROC [dc: Imager.Context, svData: SVData] = { scene: Scene _ svData.scene; camera: Camera _ svData.camera; lo, hi: Point2d; lo _ [0,0]; hi _ [8.5*72.0, 11.0*72.0]; lo _ CoordSys.ScreenToCamera[lo, camera.screenCS]; hi _ CoordSys.ScreenToCamera[hi, camera.screenCS]; DrawObjectsFiltered[dc, svData, SVBoundBox.BoundBoxFromValues[lo[1], lo[2], hi[1], hi[2]] ]; }; OnOverlay: PROC [entity: REF ANY, svData: SVData] RETURNS [BOOL] = { WITH entity SELECT FROM slice: Slice => RETURN[slice.onOverlay]; sliceD: SliceDescriptor => RETURN[sliceD.slice.onOverlay]; ENDCASE => ERROR; }; MoveToOverlay: PUBLIC PROC [entity: REF ANY, svData: SVData] = { WITH entity SELECT FROM sliceD: SliceDescriptor => { IF OnOverlay[sliceD, svData] THEN ERROR; sliceD.slice.onOverlay _ TRUE; svData.refresh.overlayList _ CONS[sliceD, svData.refresh.overlayList]; }; ENDCASE => ERROR; svData.refresh.orderedOverlayList _ NIL; }; MoveToBackground: PUBLIC PROC [entity: REF ANY, svData: SVData] = { IF NOT OnOverlay[entity, svData] THEN RETURN; svData.refresh.overlayList _ NARROW[GList.DRemove[entity, svData.refresh.overlayList]]; WITH entity SELECT FROM sliceD: SliceDescriptor => sliceD.slice.onOverlay _ FALSE; ENDCASE => ERROR; svData.refresh.orderedOverlayList _ NIL; }; MoveAllSelectedToOverlay: PUBLIC PROC [svData: SVData, selectClass: SelectionClass] = { sGen: SliceDescriptorGenerator _ SVSelect.SelectedSlices[svData.scene, selectClass]; FOR sliceD: SliceDescriptor _ SVSelect.NextSliceDescriptor[sGen], SVSelect.NextSliceDescriptor[sGen] UNTIL sliceD = NIL DO MoveToOverlay[sliceD, svData]; ENDLOOP; }; MoveOverlayToBackground: PUBLIC PROC [svData: SVData] = { sliceD: SliceDescriptor; FOR overlayList: LIST OF SliceDescriptor _ svData.refresh.overlayList, overlayList.rest UNTIL overlayList = NIL DO sliceD _ overlayList.first; sliceD.slice.onOverlay _ FALSE; ENDLOOP; svData.refresh.overlayList _ NIL; svData.refresh.orderedOverlayList _ NIL; }; EmptyOverlay: PUBLIC PROC [svData: SVData] RETURNS [BOOL] = { RETURN[svData.refresh.overlayList = NIL]; }; OrderOverlayList: PROC [svData: SVData] RETURNS [orderedList: LIST OF SliceDescriptor _ NIL] = { FindOverlayedD: PROC [slice: REF ANY] RETURNS [sliceD: SliceDescriptor _ NIL] = { FOR ov: LIST OF SliceDescriptor _ svData.refresh.overlayList, ov.rest UNTIL ov=NIL DO sliceD _ ov.first; IF sliceD.slice=slice THEN RETURN[sliceD]; ENDLOOP; RETURN[NIL]; }; sliceD: SliceDescriptor; finger: LIST OF SliceDescriptor; g: SVScene.AssemblyGenerator; scene: Scene _ svData.scene; [orderedList, finger] _ SVUtility.StartSliceDescriptorList[]; g _ SVScene.PrimAssembliesInScene[scene]; FOR slice: Slice _ SVScene.NextAssembly[g], SVScene.NextAssembly[g] UNTIL slice = NIL DO IF OnOverlay[slice, svData] THEN { sliceD _ FindOverlayedD[slice]; IF sliceD = NIL THEN sliceD _ SVAssembly.NewParts[slice, NIL, [0,0,0], topLevel]; [orderedList, finger] _ SVUtility.AddSliceDescriptor[sliceD, orderedList, finger]; }; ENDLOOP; }; InitStats: PROC = { interval: CodeTimer.Interval; interval _ CodeTimer.CreateInterval[$PaintEntireScene]; CodeTimer.AddInt[interval, $Solidviews]; }; InitStats[]; END. SVRefreshImpl.mesa Copyright c 1986 by Xerox Corporation. All rights reserved. Last edited by Bier on February 2, 1987 Contents: All painting actions in Solidviews are called thru this interface. whatHasChanged will be an atom describing some change which has occurred to the viewable scene state, such as $CaretMoved, $OverlayMoved, $ObjectAdded, $SelectionChanged, or $Everything. A pointer to the particular objects to be repainted will be stored in svData for now. We envision a scheme where Dispatch may actually queue up painting jobs and attempt optimizations on the queue. In this case, the objects to be repainted will have to be stored separately from the svData. Dragging $ObjectChangedInPlace => ObjectChangedInPlace[screen, svData, normal]; Debugging and Draw Directly on the Screen $DrawCatScan => DrawCatScan[screen, svData]; Single-Plane Commands This could use some optimizing. Draw Coordinate Frames and Old Fashioned Selections (Solidviews only) Add these new features to the foreground context. Drawing Utilities Draws control points on slices which are the caret attractor. attractor.slice.class.drawAttractorFeedback[ Puts all the selected (hot & normal) slices in a list, and returns them For each selection, If the selected object is a hook or a floater, complement the jack and then draw the selection. If a coordinate system, just draw selection. Paints those objects in the scene within the filter bounding box, and in front of (and including) overObject (in PriorityOrder) into the display context. IF overObject # NIL THEN { UNTIL thisSlice = overObject OR thisSlice = NIL DO thisSlice _ SVScene.NextAssembly[g] ENDLOOP; IF thisSlice = NIL THEN RETURN; }; The selection plane or the skitter plane is obsolete. Since these planes have no backing bitmaps, no repairs are needed. Simply redraw the planes. Fixing Planes An object has been added to the scene. All of the changes are confined to the box svData.refresh.startBoundBox. Repair the background plane and refresh the screen. bBox: BoundBox _ SVBoundBox.BoundBoxOfAssembly[assembly]; IF eraseFirst THEN SVBoundBox.EraseWithinBoundBox[backgroundContext, bBox]; Dynamic This routine is called DuringDrag. Write the overlay shapes, selection feedback, and the foreground shapes onto the chunking bitmap and then dump the chunking bitmap onto the screen. g: SVScene.AssemblyGenerator; sliceD: SliceDescriptor; g _ SVScene.PrimAssembliesInScene[scene]; FOR slice: Slice _ SVScene.NextAssembly[g], SVScene.NextAssembly[g] UNTIL slice = NIL DO sliceD _ SVSelect.FindSelectedSlice[slice, scene, normal]; IF sliceD # NIL THEN RETURN[slice]; ENDLOOP; The background and overlay planes are about to be recombined into the background plane, after dragging. Similar to PaintAllPlanes Debugging Routines (draw directly on the screen) Make sure you have up to date coordSys positions. DrawCatScan: PROC [dc: Imager.Context, svData: SVData] = { catScan: CatScan _ svData.refresh.catScan; camera: Camera _ svData.camera; SVCatScan.DrawSlice3d[dc, catScan, camera]; }; For Interpress Masters Called by SVMouseEvent.IPSnapShot to get a picture of Gargoyle dragging in action. Draw all but the overlay objects into a bitmap. Auxiliary for SnapShot. SVScene.DrawScene[dc, scene, camera]; The Overlay Plane. traverse the scene.entities from back to end front. Κ †˜J˜Icodešœ™Kšœ Οmœ1™—˜J˜——š œžœžœ*žœ˜_Kšœ2˜2J˜J˜—š œžœ*žœ˜ZKšœ‘™‘KšœΝ™ΝK˜Kšœ žœ˜Kšžœ žœžœ˜.Kšœ+˜+šžœž˜K˜Kšœ žœ˜Kšœ]˜]KšœGžœžœ˜UKšœEžœžœ˜SKšœ@žœžœ˜NKšœAžœžœ˜OKšœI˜IKšœB˜BKšœE˜EKšœ;žœžœ˜IKšœ=žœžœ˜KKšœ<žœžœ˜Jšœ9žœžœ˜GKšΟb™—Kšœ2žœ˜DKšœ6žœ ˜IKšœ:˜:KšœF™FKšœO˜Ošœ=˜=Kš‘)™)—Kšœ8˜8Kšœ(˜(Kšœ6˜6Kšœ2˜2Kšœ6˜6Kšœ<˜˜’Kšžœ˜—Kšœ8˜8K˜—Kšžœžœ˜—K˜—Kšœ˜Kšœ˜Kš žœžœžœ žœžœ˜)Kšœ-˜-K˜K˜—š œžœžœ žœ˜Lšžœžœž˜JšœE˜EJšœ?˜?Jšžœžœ˜—Jšœ˜J˜—š œžœžœ žœ˜OJšœ˜š žœžœžœžœžœž˜AJšœ<˜KšœR™RKšœDŸ&˜jKšœ˜Kšœ'Ÿ4˜[K˜K˜—š œžœ)˜AKšœH™HKšœ˜Kšœ˜Kšœ˜Kšœ0˜0Kšœ;˜;Kšœ_˜_Kšœ/Ÿ#˜RKšœD˜DJšœ-˜-Jšœ˜K˜K˜—š œž œ)˜KKšœ˜Jšœ˜J˜J˜ J˜Jšœ2˜2Kšœ2˜2Jšœ%™%Jšœ\˜\K˜K˜—J™J™š   œžœ žœžœžœžœ˜Dšžœžœž˜Kšœžœ˜(Kšœžœ˜:Kšžœžœ˜—K˜K˜—š   œžœžœ žœžœ˜@šžœžœž˜šœ˜Kšžœžœžœ˜(Kšœžœ˜Kšœžœ%˜FK˜—Kšžœžœ˜—Kšœ$žœ˜(J˜J˜—š  œžœžœ žœžœ˜CKšžœžœžœžœ˜-Kšœžœ4˜Wšžœžœž˜Kšœ4žœ˜:Kšžœžœ˜—Kšœ$žœ˜(J˜J˜—š œžœžœ2˜WKšœT˜Tšžœbžœ žœž˜zKšœ˜Kšžœ˜—J˜J˜J˜—š œžœžœ˜9Kšœ˜š žœžœžœ@žœžœž˜rKšœ˜Kšœžœ˜Kšžœ˜—Kšœžœ˜!Kšœ$žœ˜(J˜—š   œžœžœžœžœ˜=Kšžœžœ˜)J˜—š  œžœžœžœžœžœ˜`K™3š  œžœ žœžœžœžœ˜Qš žœžœžœ7žœžœž˜UKšœ˜Kšžœžœžœ ˜*Kšžœ˜—Kšžœžœ˜ K˜—Kšœ˜Kšœžœžœ˜ Kšœ˜Kšœ˜Kšœ=˜=Kšœ)˜)šžœAžœ žœž˜Xšžœžœ˜"Kšœ˜Kšžœ žœžœ%žœ˜QKšœR˜RK˜—Kšžœ˜—K˜K˜—K˜š  œžœ˜K˜K˜7K˜(K˜K˜—K˜ K˜Kšžœ˜K˜J˜—…—uz£