<> <> <> <> DIRECTORY AIS, CastRays, CoordSys, CSG, CSGGraphics, DisplayList3d, DisplayListToTree, Graphics, GraphicsColor, InputFocus, IO, Matrix3d, Preprocess3d, Real, SV2d, SV3d, SVArtworkUser, SVError, SVInterfaceTypes, SVLines2d, SVMatrix2d, SVModelTypes, SVRayTypes, SVSceneTypes, SVSelections, SVVector3d, SVViewerInput, SVViewerUser, TIPUser, ViewerClasses; SVViewerInputImplB: PROGRAM IMPORTS AIS, CastRays, CoordSys, CSG, CSGGraphics, DisplayList3d, DisplayListToTree, Graphics, GraphicsColor, InputFocus, --IO, --Matrix3d, Preprocess3d, Real, SVArtworkUser, SVError, SVLines2d, SVMatrix2d, SVSelections, SVViewerInput, SVViewerUser, SVVector3d EXPORTS SVViewerInput = BEGIN Artwork: TYPE = SVModelTypes.Artwork; ArtworkToolData: TYPE = SVInterfaceTypes.ArtworkToolData; Assembly: TYPE = SVSceneTypes.Assembly; AssemblyList: TYPE = SVSceneTypes.AssemblyList; BoundBox: TYPE = SVModelTypes.BoundBox; Camera: TYPE = SVModelTypes.Camera; Classification: TYPE = SVRayTypes.Classification; Color: TYPE = GraphicsColor.Color; CoordSystem: TYPE = SVModelTypes.CoordSystem; EditToolData: TYPE = SVInterfaceTypes.EditToolData; FileCamera: TYPE = SVSceneTypes.FileCamera; FrameBox: TYPE = SVModelTypes.FrameBox; MasterObject: TYPE = SVSceneTypes.MasterObject; Matrix4by4: TYPE = SV3d.Matrix4by4; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Primitive: TYPE = SVRayTypes.Primitive; Ray: TYPE = SVRayTypes.Ray; Scene: TYPE = SVSceneTypes.Scene; SearchDepth: TYPE = SVInterfaceTypes.SearchDepth; Selection: TYPE = SVInterfaceTypes.Selection; SelectionGenerator: TYPE = SVInterfaceTypes.SelectionGenerator; Shape: TYPE = SVSceneTypes.Shape; SkitterMode: TYPE = SVInterfaceTypes.SkitterMode; ToolData: TYPE = SVSceneTypes.ToolData; TrigLine: TYPE = SV2d.TrigLine; Vector: TYPE = SV3d.Vector; ViewerToolData: TYPE = SVInterfaceTypes.ViewerToolData; SurfacePointAndNormalAtSearchDepth: PROC [class: Classification, rayWorld: Ray, searchDepth: SearchDepth, root: Assembly] RETURNS [surfacePtWorld: Point3d, normalWorld: Vector] = { SELECT searchDepth FROM first => [surfacePtWorld, normalWorld] _ CastRays.NthSurfacePointAndNormal[class, rayWorld, 1]; lastOfFirst => [surfacePtWorld, normalWorld] _ CastRays.LastOfFirstPointAndNormal[class, rayWorld]; last => IF class.count = 0 THEN ERROR ELSE [surfacePtWorld, normalWorld] _ CastRays.NthSurfacePointAndNormal[class, rayWorld, class.count]; lastOfLevel1 => [surfacePtWorld, normalWorld] _ CastRays.LastTopLevelPointAndNormal[class, rayWorld, root]; ENDCASE => ERROR; }; AssemblyAndPrimitiveAtSearchDepth: PROC [class: Classification, searchDepth: SearchDepth, root: Assembly] RETURNS [assembly: Assembly, primitive: Primitive] = { SELECT searchDepth FROM first => [assembly, primitive] _ CastRays.NthAssemblyAndPrimitive[class, 1]; lastOfFirst => [assembly, primitive] _ CastRays.NthAssemblyAndPrimitive[class, 1]; last => [assembly, primitive] _ CastRays.NthAssemblyAndPrimitive[class, class.count]; lastOfLevel1 => [assembly, primitive] _ CastRays.LastTopLevelAssemAndPrim[class, root]; ENDCASE => ERROR; }; StartTightRope: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED { <> planeSel: Selection; planeAssem: Assembly; scene: Scene _ viewerToolData.scene; planeSel _ SVSelections.TopPlane[]; SVSelections.SetModeSkitter[tightrope]; IF planeSel = NIL THEN { SVError.Append["Please make a plane selection to specify tightrope.", TRUE, TRUE]; SVError.Blink[]; RETURN; }; planeAssem _ planeSel.coincident; IF planeAssem.toolMasterObject = NIL OR planeAssem.toolMasterObject.mainBody = NIL THEN DisplayList3d.AddOrResizeToolToAssembly[planeAssem, scene]; DuringTightRope[viewerToolData, cameraPoint]; }; TightRopeAux: PRIVATE PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d, target: Assembly] RETURNS [skitterWORLD: Matrix4by4] = { <> skitterTarget: Matrix4by4; newOriginCamera, newOriginTarget: Point3d; plane: NAT; toolData: ToolData; cameraDir: Vector; camera1, camera2: Point3d; screen1, screen2, q: Point2d; ropeShadow, normalLine: TrigLine; parallel: BOOL; camera: Camera _ viewerToolData.camera; targetCS: CoordSystem _ target.coordSys; worldCS: CoordSystem _ viewerToolData.scene.coordSysRoot; cameraCS: CoordSystem _ camera.coordSys; <> <> <> <<};>> camera1 _ Matrix3d.OriginOfMatrix[targetCS.wrtCamera]; toolData _ NARROW[target.toolMasterObject.mainBody]; plane _ toolData.plane; plane _ IF plane > 3 THEN 3 ELSE plane; SELECT plane FROM 1 => cameraDir _ Matrix3d.XAxisOfMatrix[targetCS.wrtCamera]; 2 => cameraDir _ Matrix3d.YAxisOfMatrix[targetCS.wrtCamera]; 3 => cameraDir _ Matrix3d.ZAxisOfMatrix[targetCS.wrtCamera]; ENDCASE => ERROR; camera2 _ SVVector3d.Add[camera1, cameraDir]; screen1 _ CSGGraphics.DoProjection[camera1, camera]; screen2 _ CSGGraphics.DoProjection[camera2, camera]; ropeShadow _ SVLines2d.TrigLineFromPoints[screen1, screen2]; normalLine _ SVLines2d.TrigLineNormalToTrigLineThruPoint[ropeShadow, cameraPoint]; [q, parallel] _ SVLines2d.TrigLineMeetsTrigLine[ropeShadow, normalLine]; IF parallel THEN ERROR; <> <> <> <> <> <> <> <> <> <<(p1 + t*d1)f = (f - p3 - t*d3)*q1.>> <> <> <> <<(p1 + t*d1) = q1.>> <> <> BEGIN p: Point3d; d: Vector; t: REAL; p _ camera1; d _ cameraDir; SELECT camera.projection FROM orthogonal => { IF ABS[d[1]] > ABS[d[2]] THEN t _ (q[1]-p[1])/d[1] ELSE t _ (q[2]-p[2])/d[2]; newOriginCamera[1] _ p[1] + t*d[1]; newOriginCamera[2] _ p[2] + t*d[2]; newOriginCamera[3] _ p[3] + t*d[3]; }; perspective => { denom1, denom2: REAL; f: REAL _ camera.focalLength; denom1 _ (d[1]*f + d[3]*q[1]); denom2 _ (d[2]*f + d[3]*q[2]); IF ABS[denom1] > ABS[denom2] THEN t _ ((f-p[3])*q[1] - (p[1]*f))/denom1 ELSE t _ ((f-p[3])*q[2] - (p[2]*f))/denom2; newOriginCamera[1] _ p[1] + t*d[1]; newOriginCamera[2] _ p[2] + t*d[2]; newOriginCamera[3] _ p[3] + t*d[3]; }; ENDCASE => ERROR; END; newOriginTarget _ CoordSys.FromCSToCS[newOriginCamera, cameraCS, targetCS]; <> skitterTarget _ Matrix3d.MakeTranslateMat[newOriginTarget[1], newOriginTarget[2], newOriginTarget[3]]; skitterWORLD _ CoordSys.FromCSToCSMat[skitterTarget, targetCS, worldCS]; }; DuringTightRope: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED { <> planeAssem: Assembly; planeSel: Selection; skitterWORLD: Matrix4by4; camera: Camera _ viewerToolData.camera; planeSel _ SVSelections.TopPlane[]; IF planeSel = NIL THEN RETURN; planeAssem _ planeSel.coincident; skitterWORLD _ TightRopeAux[viewerToolData, cameraPoint, planeAssem]; SVViewerInput.ComplementSkitter[]; -- erase any old skitter SVSelections.UpdateSkitter[NIL, NIL, viewerToolData]; SVSelections.PositionSkitter[cameraPoint, skitterWORLD]; SVViewerInput.ComplementSkitter[]; -- draw new skitter }; EndTightRope: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED { DuringTightRope[viewerToolData, cameraPoint]; }; StartWallWalk: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED { planeSel: Selection; planeAssem: Assembly; scene: Scene _ viewerToolData.scene; planeSel _ SVSelections.TopPlane[]; SVSelections.SetModeSkitter[tightrope]; IF planeSel = NIL THEN { SVError.Append["Please make a plane selection to specify walk wall.", TRUE, TRUE]; SVError.Blink[]; RETURN; }; planeAssem _ planeSel.coincident; IF planeAssem.toolMasterObject = NIL OR planeAssem.toolMasterObject.mainBody = NIL THEN DisplayList3d.AddOrResizeToolToAssembly[planeAssem, scene]; DuringWallWalk[viewerToolData, cameraPoint]; }; DuringWallWalk: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED { <> planeAssem: Assembly; planeSel: Selection; targetWORLD, skitterWORLD: Matrix4by4; hitPointWORLD: Point3d; camera: Camera _ viewerToolData.camera; scene: Scene _ viewerToolData.scene; worldCS: CoordSystem _ scene.coordSysRoot; toolData: ToolData; parallel: BOOL; planeSel _ SVSelections.TopPlane[]; IF planeSel = NIL THEN RETURN; planeAssem _ planeSel.coincident; toolData _ NARROW[planeAssem.toolMasterObject.mainBody]; IF toolData = NIL THEN { SVError.Append["Wall walk plane is not defined.", TRUE, TRUE]; SVError.Blink[]; RETURN; }; <> [hitPointWORLD, parallel] _ RayMeetsTopPlane[cameraPoint, planeAssem, 0, toolData.plane, camera]; IF parallel THEN { SVError.Append["DuringWallWalk: plane is parallel to ray.", TRUE, TRUE]; SVError.Blink[]; RETURN; }; targetWORLD _ planeAssem.coordSys.wrtWorld; skitterWORLD _ Matrix3d.Translate[targetWORLD, hitPointWORLD[1], hitPointWORLD[2], hitPointWORLD[3]]; SVViewerInput.ComplementSkitter[]; -- erase any old skitter SVSelections.UpdateSkitter[NIL, NIL, viewerToolData]; SVSelections.PositionSkitter[cameraPoint, skitterWORLD]; SVViewerInput.ComplementSkitter[]; -- draw new skitter }; EndWallWalk: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED { DuringWallWalk[viewerToolData, cameraPoint]; }; Sign: PRIVATE PROC [r: REAL] RETURNS [INT] = { IF r = 0.0 THEN RETURN[2]; IF r < 0.0 THEN RETURN[-1] ELSE RETURN[1]; }; AntiParallel: PRIVATE PROC [v1, v2: Vector] RETURNS [BOOL] = { RETURN[Sign[v1[1]] = -Sign[v2[1]] OR Sign[v1[2]] = -Sign[v2[2]] OR Sign[v1[3]] = -Sign[v2[3]] ]; }; MakeAlignedMat: PRIVATE PROC [worldNormal: Vector, surfacePtInWorld: Point3d, cs: CoordSystem] RETURNS [mat: Matrix4by4] = TRUSTED { <> yAxisOfCS: Vector _ Matrix3d.YAxisOfMatrix[cs.wrtWorld]; xAxis: Vector; IF SVVector3d.Parallel[yAxisOfCS, worldNormal] THEN { xAxis _ Matrix3d.XAxisOfMatrix[cs.wrtWorld]; IF AntiParallel[yAxisOfCS, worldNormal] THEN xAxis _ SVVector3d.Negate[xAxis]; <> } ELSE xAxis _ SVVector3d.CrossProduct[yAxisOfCS, worldNormal]; mat _ Matrix3d.MakeMatFromZandXAxis[worldNormal, xAxis, surfacePtInWorld]; }; RayMeetsTopPlane: PRIVATE PROC [cameraPoint: Point2d, target: Assembly, depth: REAL, plane: NAT, camera: Camera] RETURNS [planePtWorld: Point3d, parallel: BOOL] = TRUSTED { <> newRay: Ray; newRay _ CSG.GetRayFromPool[]; CSG.StuffWorldRayFromCamera[newRay, cameraPoint, camera]; [planePtWorld, parallel] _ CastRays.RayMeetsPlaneOfCoordSystem[target.coordSys, newRay, plane, depth]; CSG.ReturnRayToPool[newRay]; }; StartSkitter: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d, searchDepth: SearchDepth] = TRUSTED { <> selectionMat: Matrix4by4; surfacePtWorld: Point3d; normalWorld: Vector; assembly: Assembly; primitive: Primitive; class: Classification; rayWorld: Ray; scene: Scene _ viewerToolData.scene; camera: Camera _ viewerToolData.camera; IF viewerToolData.treeOutOfDate THEN { viewerToolData.tree _ DisplayListToTree.AssemblyToTree[viewerToolData.scene.assembly, scene, viewerToolData.camera]; [] _ Preprocess3d.PreprocessForInteraction[viewerToolData.tree, viewerToolData.camera]; viewerToolData.treeOutOfDate _ FALSE; }; [class, rayWorld] _ CastRays.SingleRay2[cameraPoint, viewerToolData.tree, viewerToolData.camera]; [assembly, primitive] _ AssemblyAndPrimitiveAtSearchDepth[class, searchDepth, scene.assembly]; IF class.count > 0 THEN [surfacePtWorld, normalWorld] _ SurfacePointAndNormalAtSearchDepth[class, rayWorld, searchDepth, scene.assembly]; CSG.ReturnRayToPool[rayWorld]; CastRays.ReturnClassToPool[class]; SVViewerInput.ComplementSkitter[]; -- erase any old skitter IF assembly # NIL THEN { selectionMat _ MakeAlignedMat[normalWorld, surfacePtWorld, assembly.coordSys]; SVSelections.UpdateSkitter[assembly, primitive, viewerToolData]; SVSelections.PositionSkitter[cameraPoint, selectionMat]; }; SVSelections.SetModeSkitter[surface]; SVViewerInput.ComplementSkitter[]; -- draw new skitter SVViewerUser.Selected[NIL, viewerToolData, red, FALSE, FALSE]; InputFocus.SetInputFocus[viewerToolData.viewerPicture]; }; -- end of StartSkitter DuringSkitter: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d, searchDepth: SearchDepth] = TRUSTED { <> surfacePtWorld: Point3d; normalWorld: Vector; assembly: Assembly; primitive: Primitive; selectionMat: Matrix4by4; camera: Camera _ viewerToolData.camera; scene: Scene _ viewerToolData.scene; class: Classification; rayWorld: Ray; [class, rayWorld] _ CastRays.SingleRay2[cameraPoint, viewerToolData.tree, camera]; [assembly, primitive] _ AssemblyAndPrimitiveAtSearchDepth[class, searchDepth, scene.assembly]; IF class.count > 0 THEN [surfacePtWorld, normalWorld] _ SurfacePointAndNormalAtSearchDepth[class, rayWorld, searchDepth, scene.assembly]; CSG.ReturnRayToPool[rayWorld]; CastRays.ReturnClassToPool[class]; SVViewerInput.ComplementSkitter[]; -- erase any old skitter IF assembly # NIL THEN { editToolData: EditToolData _ viewerToolData.editToolData; selectionMat _ MakeAlignedMat[normalWorld, surfacePtWorld, assembly.coordSys]; SVSelections.UpdateSkitter[assembly, primitive, viewerToolData]; SVSelections.PositionSkitter[cameraPoint, selectionMat]; } ELSE SVSelections.UpdateSkitter[NIL, NIL, viewerToolData]; SVViewerInput.ComplementSkitter[]; -- draw new skitter }; -- end DuringSkitter EndSkitter: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d, searchDepth: SearchDepth] = TRUSTED { DuringSkitter[viewerToolData, cameraPoint, searchDepth]; -- set the skitter to the final point. }; ExtendSkitter: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d, searchDepth: SearchDepth] = TRUSTED { <> oldAssembly, assem, commonAncestor: Assembly; oldPrimitive, prim: Primitive; oldViewerToolData, vtd: ViewerToolData; scene: Scene; scene _ viewerToolData.scene; [oldAssembly, oldPrimitive, oldViewerToolData] _ SVSelections.GetSkitterData[]; DuringSkitter[viewerToolData, cameraPoint, searchDepth]; [assem, prim, vtd] _ SVSelections.GetSkitterData[]; IF vtd # oldViewerToolData THEN { SVError.Append["Can't extend across viewers.", TRUE, TRUE]; SVError.Blink[]; RETURN; }; IF assem = NIL THEN SVSelections.UpdateSkitter[oldAssembly, oldPrimitive, vtd] ELSE { commonAncestor _ DisplayListToTree.CommonAncestor[assem, oldAssembly, scene.assembly]; SVSelections.UpdateSkitter[commonAncestor, prim, vtd]; }; }; ExtendCoordSkitter: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED { <> oldAssembly, assem, commonAncestor: Assembly; oldPrimitive, prim: Primitive; oldViewerToolData, vtd: ViewerToolData; scene: Scene; scene _ viewerToolData.scene; [oldAssembly, oldPrimitive, oldViewerToolData] _ SVSelections.GetSkitterData[]; DuringCoordSkitter[viewerToolData, cameraPoint]; [assem, prim, vtd] _ SVSelections.GetSkitterData[]; IF vtd # oldViewerToolData THEN { SVError.Append["Can't extend across viewers.", TRUE, TRUE]; SVError.Blink[]; RETURN; }; IF assem = NIL THEN SVSelections.UpdateSkitter[oldAssembly, oldPrimitive, vtd] ELSE { commonAncestor _ DisplayListToTree.CommonAncestor[assem, oldAssembly, scene.assembly]; SVSelections.UpdateSkitter[commonAncestor, prim, vtd]; }; }; NearestAssemblyToRay: PRIVATE PROC [cameraRay: Ray, root: Assembly] RETURNS [nearest: Assembly, dSquared: REAL] = { sonD: REAL; sonA: Assembly; origin: Point3d; WITH root.shape SELECT FROM shape: Shape => { -- A primitive. Just compute distance. nearest _ root; origin _ Matrix3d.OriginOfMatrix[root.coordSys.wrtCamera]; dSquared _ RayToPoint[cameraRay, origin]; }; alist: AssemblyList => { -- Take the minimum of myself and my subtrees, giving preference to the subtrees nearest _ root; origin _ Matrix3d.OriginOfMatrix[root.coordSys.wrtCamera]; dSquared _ RayToPoint[cameraRay, origin]; FOR sons: LIST OF Assembly _ alist.list, sons.rest UNTIL sons = NIL DO [sonA, sonD] _ NearestAssemblyToRay[cameraRay, sons.first]; IF sonD <= dSquared THEN { nearest _ sonA; dSquared _ sonD; }; ENDLOOP; }; ENDCASE => ERROR; }; RayToPoint: PUBLIC PROC [cameraRay: Ray, cameraPt: Point3d] RETURNS [dSquared: REAL] = TRUSTED { <> magRaySquared, dotProd, dotProdSquared, rCosThetaSquared, rSquared: REAL; screenToPoint: Vector; basePt: Point3d; direction: Vector; [basePt, direction] _ CSG.GetCameraRay[cameraRay]; magRaySquared _ SVVector3d.MagnitudeSquared[direction]; screenToPoint _ SVVector3d.Sub[cameraPt, basePt]; rSquared _ SVVector3d.MagnitudeSquared[screenToPoint]; dotProd _ SVVector3d.DotProduct[direction, screenToPoint]; dotProdSquared _ dotProd*dotProd; rCosThetaSquared _ dotProdSquared/magRaySquared; dSquared _ rSquared - rCosThetaSquared; -- Pythagorean Theorem }; StartCoordSkitter: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = { SVViewerUser.Selected[NIL, viewerToolData, red, FALSE, FALSE]; InputFocus.SetInputFocus[viewerToolData.viewerPicture]; DuringCoordSkitter[viewerToolData, cameraPoint]; }; DuringCoordSkitter: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = { <> cameraRay: Ray _ CSG.GetRayFromPool[]; camera: Camera _ viewerToolData.camera; scene: Scene _ viewerToolData.scene; nearest: Assembly; CSG.StuffCameraRay[cameraRay, cameraPoint, camera]; [nearest, ----] _ NearestAssemblyToRay[cameraRay, scene.assembly]; CSG.ReturnRayToPool[cameraRay]; SVViewerInput.ComplementSkitter[]; -- erase any old skitter SVSelections.UpdateSkitter[nearest, NIL, viewerToolData]; SVSelections.PositionSkitter[cameraPoint, nearest.coordSys.wrtWorld]; SVSelections.SetModeSkitter[coordframe]; SVViewerInput.ComplementSkitter[]; -- draw new skitter }; EndCoordSkitter: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = {}; Paint: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = { <> editToolData: EditToolData _ viewerToolData.editToolData; artworkToolData: ArtworkToolData _ NARROW[editToolData.artworkTool.data]; camera: Camera _ viewerToolData.camera; artwork: Artwork _ artworkToolData.artwork; assembly: Assembly; skitterWORLD, assemWORLD, skitterassem, worldCamera: Matrix4by4; imagePoint: Point2d; skitterPoint, surfPtassem: Point3d; normal: Vector; paintColor: Color _ artworkToolData.paintColor; path: Graphics.Path _ Graphics.NewPath[4]; DoDrawBrush: PROC [dc: Graphics.Context] = { Graphics.SetColor[dc, artworkToolData.paintColor]; CSGGraphics.DrawStroke[dc, path, 1, TRUE]; }; DuringSkitter[viewerToolData, cameraPoint, first]; [assembly, ----, viewerToolData] _ SVSelections.GetSkitterData[]; [----, skitterWORLD] _ SVSelections.GetPositionSkitter[]; assemWORLD _ assembly.coordSys.wrtWorld; skitterassem _ Matrix3d.WorldToLocal[assemWORLD, skitterWORLD]; normal _ Matrix3d.ZAxisOfMatrix[skitterassem]; <> FOR i: INT IN [-2..2] DO FOR j: INT IN [-2..2] DO skitterPoint _ [i, j, 0.0]; surfPtassem _ Matrix3d.Update[skitterassem, skitterPoint]; imagePoint _ SVArtworkUser.GetImagePointFromSurfacePoint[artwork, surfPtassem, normal]; <> SetImageColorAtPoint[artwork, imagePoint, paintColor]; ENDLOOP; ENDLOOP; worldCamera _ CoordSys.FindWorldInTermsOf[camera.coordSys]; CSGGraphics.MoveToAbsolute[path, Matrix3d.Update[worldCamera, Matrix3d.Update[skitterWORLD, [-2, -2, 0]]], camera]; CSGGraphics.LineToAbsolute[path, Matrix3d.Update[worldCamera, Matrix3d.Update[skitterWORLD, [-2, 2, 0]]], camera]; CSGGraphics.LineToAbsolute[path, Matrix3d.Update[worldCamera, Matrix3d.Update[skitterWORLD, [2, 2, 0]]], camera]; CSGGraphics.LineToAbsolute[path, Matrix3d.Update[worldCamera, Matrix3d.Update[skitterWORLD, [2, -2, 0]]], camera]; SVViewerUser.Painter[DoDrawBrush, viewerToolData]; }; SetImageColorAtPoint: PROC [artwork: Artwork, imagePoint: Point2d, paintColor: Color] = { <> <> <> artworkPoint: Point2d; IF artwork.source = NIL THEN RETURN; BEGIN uAIS, vAIS: REAL; -- u and v in AIS dots at this ais file's resolution uInch, vInch: REAL; -- u and v in inches artworkPoint _ SVMatrix2d.Update[artwork.artWRTPad.padWRTLocal, imagePoint]; -- in screen dots uInch _ artworkPoint[1]/72.0; vInch _ artworkPoint[2]/72.0; uAIS _ uInch*artwork.resolution; vAIS _ vInch*artwork.resolution; IF artwork.isColorFile THEN { redValue, greenValue, blueValue: CARDINAL; realRedValue, realGreenValue, realBlueValue: REAL; [realRedValue, realGreenValue, realBlueValue] _ GraphicsColor.ColorToRGB[paintColor]; <> IF uInch <= - artwork.halfWidth OR uInch >= artwork.halfWidth OR vInch <= -artwork.halfHeight OR vInch >= artwork.halfHeight THEN RETURN; redValue _ Real.Fix[realRedValue*255.0]; AIS.WriteSample[artwork.redWindow, redValue, Real.FixC[-vAIS + artwork.halfHeightDots], Real.FixC[uAIS + artwork.halfWidthDots]]; greenValue _ Real.Fix[realGreenValue*255.0]; AIS.WriteSample[artwork.greenWindow, greenValue, Real.FixC[-vAIS + artwork.halfHeightDots], Real.FixC[uAIS + artwork.halfWidthDots]]; blueValue _ Real.Fix[realBlueValue*255.0]; AIS.WriteSample[artwork.blueWindow, blueValue, Real.FixC[-vAIS + artwork.halfHeightDots], Real.FixC[uAIS + artwork.halfWidthDots]]; } ELSE {-- artwork is a black and white file blackValue: CARDINAL; realBlackValue: REAL; realBlackValue _ GraphicsColor.ColorToIntensity[paintColor]; IF uInch <= - artwork.halfWidth OR uInch >= artwork.halfWidth OR vInch <= -artwork.halfHeight OR vInch >= artwork.halfHeight THEN RETURN; blackValue _ Real.Fix[realBlackValue*255.0]; AIS.WriteSample[artwork.blackWindow, blackValue, Real.FixC[-vAIS + artwork.halfHeightDots], Real.FixC[uAIS + artwork.halfWidthDots]]; }; END; }; -- end of SetImageColorAtPoint FrameUpLeft: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED { <> camera: Camera _ viewerToolData.camera; oldMode: Graphics.PaintMode; DoDrawFrame: SAFE PROC [dc: Graphics.Context] = TRUSTED { Graphics.SetColor[dc, GraphicsColor.black]; oldMode _ Graphics.SetPaintMode[dc, invert]; CSGGraphics.DrawFrame [dc, camera]; [] _ Graphics.SetPaintMode[dc, oldMode]; }; SVViewerUser.Painter[DoDrawFrame, viewerToolData]; -- erase old frame camera.frame.fullScreen _ FALSE; camera.frame.downLeft[1] _ cameraPoint[1]; camera.frame.upRight[2] _ cameraPoint[2]; camera.frame.downLeft[2] _ cameraPoint[2] - 50.0; -- Just to give the frame an initial size. camera.frame.upRight[1] _ cameraPoint[1] + 50.0; SVViewerUser.Painter[DoDrawFrame, viewerToolData]; }; FrameDownRightMove: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED { <> camera: Camera _ viewerToolData.camera; oldMode: Graphics.PaintMode; DoDrawFrame: SAFE PROC [dc: Graphics.Context] = TRUSTED { Graphics.SetColor[dc, GraphicsColor.black]; oldMode _ Graphics.SetPaintMode[dc, invert]; CSGGraphics.DrawFrame [dc, camera]; [] _ Graphics.SetPaintMode[dc, oldMode]; }; <> SVViewerUser.Painter[DoDrawFrame, viewerToolData]; camera.frame.downLeft[2] _ cameraPoint[2]; camera.frame.upRight[1] _ cameraPoint[1]; <> SVViewerUser.Painter[DoDrawFrame, viewerToolData]; }; FrameDownRightEnd: PUBLIC PROC [viewerToolData: ViewerToolData, cameraPoint: Point2d] = TRUSTED { camera: Camera _ viewerToolData.camera; fileCamera: FileCamera; success: BOOL; FrameDownRightMove[viewerToolData, cameraPoint]; <> <> [fileCamera, success] _ DisplayList3d.FindFileCameraFromName[camera.viewName, viewerToolData.scene]; IF success THEN { fileCamera.frame.downLeft _ camera.frame.downLeft; fileCamera.frame.upRight _ camera.frame.upRight; fileCamera.frame.fullScreen _ FALSE; }; }; DeleteFrame: PUBLIC PROC [viewerToolData: ViewerToolData] = TRUSTED { camera: Camera _ viewerToolData.camera; frame: FrameBox _ camera.frame; oldMode: Graphics.PaintMode; DoDrawFrame: SAFE PROC [dc: Graphics.Context] = TRUSTED { Graphics.SetColor[dc, GraphicsColor.black]; oldMode _ Graphics.SetPaintMode[dc, invert]; CSGGraphics.DrawFrame [dc, camera]; [] _ Graphics.SetPaintMode[dc, oldMode]; }; <> SVViewerUser.Painter[DoDrawFrame, viewerToolData]; frame.fullScreen _ TRUE; }; END.