<> <> <> <> <> DIRECTORY AIS, Atom, AtomButtonsTypes, CodeTimer, Feedback, GGBoundBox, Imager, ImagerColorPrivate, ImagerPath, InputFocus, Real, RealFns, Rope, SV2d, SV3d, SVAlign, SVArtworkUser, SVAssembly, SVBasicTypes, SVBoundBox, SVCaret, SVCastRays, SVCoordSys, SVDescribe, SVEditUser, SVEvent, SVGraphics, SVGravity, SVInterfaceTypes, SVLines2d, SVMatrix2d, SVMatrix3d, SVModelTypes, SVMouseEvent, SVRay, SVRefresh, SVScene, SVSceneTypes, SVSelect, SVSelections, SVShading, SVState, SVVector3d, SVViewersOnScene, SVWindow; SVMouseEventImplA: CEDAR PROGRAM IMPORTS AIS, Atom, CodeTimer, Feedback, GGBoundBox, Imager, ImagerColorPrivate, InputFocus, Real, RealFns, Rope, SVAlign, SVArtworkUser, SVAssembly, SVBoundBox, SVCaret, SVCastRays, SVCoordSys, SVDescribe, SVEditUser, SVEvent, SVGraphics, SVGravity, SVLines2d, SVMatrix2d, SVMatrix3d, SVMouseEvent, SVRay, SVRefresh, SVScene, SVSelect, SVSelections, SVShading, SVState, SVVector3d, SVViewersOnScene, SVWindow EXPORTS SVMouseEvent = BEGIN Artwork: TYPE = SVModelTypes.Artwork; ArtworkToolData: TYPE = SVInterfaceTypes.ArtworkToolData; BoundBlock: TYPE = SVBasicTypes.BoundBlock; BoundBox: TYPE = SVBasicTypes.BoundBox; Camera: TYPE = SVModelTypes.Camera; Classification: TYPE = SVSceneTypes.Classification; Color: TYPE = Imager.Color; CoordSystem: TYPE = SVModelTypes.CoordSystem; EditToolData: TYPE = SVInterfaceTypes.EditToolData; FeedbackData: TYPE = AtomButtonsTypes.FeedbackData; FeatureData: TYPE = SVInterfaceTypes.FeatureData; GravityType: TYPE = SVInterfaceTypes.GravityType; MasterObject: TYPE = SVSceneTypes.MasterObject; Matrix4by4: TYPE = SV3d.Matrix4by4; Point2d: TYPE = SV2d.Point2d; Point3d: TYPE = SV3d.Point3d; Primitive: TYPE = SVSceneTypes.Primitive; Ray: TYPE = SVSceneTypes.Ray; Scene: TYPE = SVSceneTypes.Scene; SearchDepth: TYPE = SVSceneTypes.SearchDepth; Selection: TYPE = SVInterfaceTypes.Selection; Shape: TYPE = SVSceneTypes.Shape; Skitter: TYPE = SVSceneTypes.Skitter; Slice: TYPE = SVSceneTypes.Slice; SliceDescriptor: TYPE = SVSceneTypes.SliceDescriptor; SliceDescriptorGenerator: TYPE = SVSceneTypes.SliceDescriptorGenerator; SliceList: TYPE = SVSceneTypes.SliceList; ToolData: TYPE = SVSceneTypes.ToolData; TrigLine: TYPE = SV2d.TrigLine; Vector3d: TYPE = SV3d.Vector3d; SVData: TYPE = SVInterfaceTypes.SVData; MouseProc: TYPE = SVMouseEvent.MouseProc; StartProc: TYPE = SVMouseEvent.StartProc; <> Problem: PUBLIC SIGNAL [msg: Rope.ROPE] = Feedback.Problem; InitializeFSM: PUBLIC PROC [svData: SVData] = { svData.state _ $None; svData.mouseMode _ $None; }; EasyAbort: MouseProc = { <> editToolData: EditToolData _ svData.editToolData; scene: Scene _ svData.scene; SVScene.RestoreSelections[scene]; SVCaret.Copy[from: svData.drag.savedCaret, to: editToolData.skitter]; -- restore original skitter FinishAbort[svData]; }; AbortBlock: PROC [event: LIST OF REF ANY, svData: SVData, cameraPoint: Point2d] = { <> FinishAbort[svData]; }; FinishAbort: PROC [svData: SVData] = { SVRefresh.MoveOverlayToBackground[svData]; Feedback.AppendHerald[svData.feedback, ". . . Aborted.", end]; SVWindow.RestoreScreenAndInvariants[paintAction: $PaintEntireScene, svData: svData, remake: triggerBag, backgndOK: FALSE, edited: FALSE, okToClearFeedback: FALSE]; }; ResetMouseMachinery: PUBLIC PROC [svData: SVData] = { svData.mouseMode _ $None; svData.state _ $None; SVRefresh.MoveOverlayToBackground[svData]; }; HandleMouse: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { atom: ATOM; vec: Imager.VEC _ NARROW[event.rest.first, REF Imager.VEC]^; point: Point2d _ [vec.x, vec.y]; SELECT svData.mouseMode FROM $Block => HandleGuarded[StartBlock, DuringDrag, EndBlock, AbortBlock, NIL, event, svData, point]; $SelectWithBlock => HandleUnGuarded[StartSelectWithBlock, DuringDrag, EndSelectWithBlock, AbortBlock, event, svData, point]; $SelectPartsWithBlock => HandleGuarded[StartSelectWithBlock, DuringDrag, EndSelectPartsWithBlock, AbortBlock, NIL, event, svData, point]; $Drag => HandleGuarded[StartDrag, DuringDrag, EndMotion, EasyAbort, NIL, event, svData, point]; $Rotate => HandleGuarded[StartRotate, DuringRotate, EndMotion, EasyAbort, NIL, event, svData, point]; $Scale => HandleGuarded[StartScale, DuringScale, EndMotion, EasyAbort, NIL, event, svData, point]; $CopyAndDrag => HandleGuarded[StartCopyAndDrag, DuringDrag, EndMotion, EasyAbort, NIL, event, svData, point]; $SelectJoint => HandleUnGuarded[SVMouseEvent.StartSelectJoint, SVMouseEvent.DuringSelect, SVMouseEvent.EndSelect, EasyAbort, event, svData, point]; $SelectSegment => HandleUnGuarded[SVMouseEvent.StartSelectSegment, SVMouseEvent.DuringSelect, SVMouseEvent.EndSelect, EasyAbort, event, svData, point]; $SelectTraj => HandleUnGuarded[SVMouseEvent.StartSelectTraj, SVMouseEvent.DuringSelect, SVMouseEvent.EndSelect, EasyAbort, event, svData, point]; $SelectTopLevel => HandleUnGuarded[SVMouseEvent.StartSelectTopLevel, SVMouseEvent.DuringSelect, SVMouseEvent.EndSelect, EasyAbort, event, svData, point]; $ExtendSelection => HandleUnGuarded[SVMouseEvent.StartExtendSelection, SVMouseEvent.DuringExtendSelection, SVMouseEvent.EndExtendSelection, EasyAbort, event, svData, point]; $ExtendSelectJoint => HandleUnGuarded[SVMouseEvent.StartExtendSelectJoint, SVMouseEvent.DuringExtendSelection, SVMouseEvent.EndExtendSelection, EasyAbort, event, svData, point]; $ExtendSelectSegment => HandleUnGuarded[SVMouseEvent.StartExtendSelectSegment, SVMouseEvent.DuringExtendSelection, SVMouseEvent.EndExtendSelection, EasyAbort, event, svData, point]; $ExtendSelectTraj => HandleUnGuarded[SVMouseEvent.StartExtendSelectTraj, SVMouseEvent.DuringExtendSelection, SVMouseEvent.EndExtendSelection, EasyAbort, event, svData, point]; $ExtendSelectTopLevel => HandleUnGuarded[SVMouseEvent.StartExtendSelectTopLevel, SVMouseEvent.DuringExtendSelection, SVMouseEvent.EndExtendSelection, EasyAbort, event, svData, point]; $Frame => HandleUnGuarded[SVMouseEvent.FrameUpLeft, SVMouseEvent.FrameDownRightMove, SVMouseEvent.FrameDownRightEnd, EasyAbort, event, svData, point]; $Skitter => HandleGuarded[StartSkitter, DuringSkitter, EndSkitter, EasyAbort, NIL, event, svData, point]; <<$SingleRay => SVEvent.SingleRay[svData, controlPoint];>> <<$DeleteFrame => SVMouseEvent.DeleteFrame[svData];>> <<>> <<$Paint => SVMouseEvent.Paint[svData, controlPoint];>> <<$OpenAISFile => SVArtworkUser.OpenFile[artworkToolData];>> <<$CloseAISFile => SVArtworkUser.CloseFile[artworkToolData];>> <<>> <<$ExtendSkitter => SVMouseEvent.ExtendSkitter[svData, controlPoint, first];>> <<$ExtendCoordSkitter => SVMouseEvent.ExtendCoordSkitter[svData, controlPoint];>> $None => { atomName: Rope.ROPE; atom _ NARROW[event.first]; atomName _ Atom.GetPName[atom]; IF Rope.Equal[Rope.Substr[atomName, 0, 5], "Start", TRUE] THEN { svData.mouseMode _ Atom.MakeAtom[Rope.Substr[atomName, 5]]; HandleMouse[event, svData]; } ELSE {}; -- ignore other actions }; ENDCASE => SIGNAL Problem[msg: "Unimplemented Mode"]; }; HandleMouseless: PUBLIC PROC [event: LIST OF REF ANY, svData: SVData] = { <> event _ LIST[event.first, NEW[Imager.VEC _ [0.0, 0.0]]]; HandleMouse[event, svData]; }; HandleGuarded: PROC [startProc: StartProc, duringProc, endProc, abortProc: MouseProc, continueProc: StartProc, event: LIST OF REF ANY, svData: SVData, worldPt: Point2d] = { genericAction, atom: ATOM; atomName: Rope.ROPE; atom _ NARROW[event.first]; atomName _ Atom.GetPName[atom]; genericAction _ IF Rope.Equal[Rope.Substr[atomName, 0, 5], "Start", TRUE] THEN $Start ELSE atom; HandleGuardedAux[startProc, duringProc, endProc, abortProc, continueProc, genericAction, event, svData, worldPt]; }; HandleGuardedAux: PROC [startProc: StartProc, duringProc, endProc, abortProc: MouseProc, continueProc: StartProc, genericAction: ATOM, event: LIST OF REF ANY, svData: SVData, worldPt: Point2d] = { SELECT svData.state FROM $None => { SELECT genericAction FROM $Start => { svData.drag.currentPoint _ worldPt; [] _ InputFocus.SetInputFocus[svData.actionArea]; IF startProc[event, svData, worldPt] THEN svData.state _ $Main ELSE {abortProc[event, svData, worldPt]; svData.state _ $Aborted;}; }; ENDCASE; }; $Main => { SELECT genericAction FROM $During => { duringProc[event, svData, worldPt]; svData.drag.currentPoint _ worldPt; }; $Abort => {abortProc[event, svData, worldPt]; svData.state _ $Aborted}; $GuardUp => svData.state _ $GuardUp; $MouseUp => svData.state _ $MouseUp; $Start => { -- the mouse must have gone out of the window while the mouse button was done. Abort the current action and start a new one. abortProc[event, svData, worldPt]; svData.state _ $None; svData.mouseMode _ $None; HandleMouse[event, svData]; }; ENDCASE; }; $GuardUp => { SELECT genericAction FROM $AllUp => { endProc[event, svData, svData.drag.currentPoint]; svData.mouseMode _ $None; svData.state _ $None; }; $Abort => {abortProc[event, svData, worldPt]; svData.state _ $Aborted}; ENDCASE; }; $MouseUp => { SELECT genericAction FROM $AllUp => { endProc[event, svData, svData.drag.currentPoint]; svData.mouseMode _ $None; svData.state _ $None; }; $Abort => {abortProc[event, svData, worldPt]; svData.state _ $Aborted}; $Start => { -- we may be starting another action of this mode or some other mode. IF Restart[event, svData] AND continueProc # NIL THEN { IF continueProc[event, svData, worldPt] THEN { svData.state _ $Main; svData.drag.currentPoint _ worldPt; } ELSE {abortProc[event, svData, worldPt]; svData.state _ $Aborted;}; } ELSE { svData.mouseMode _ $None; endProc[event, svData, svData.drag.currentPoint]; svData.state _ $None; HandleMouse[event, svData]; }; }; ENDCASE; }; $Aborted => { SELECT genericAction FROM $AllUp => {svData.state _ $None; svData.mouseMode _ $None}; ENDCASE; }; ENDCASE => SIGNAL Problem[msg: "Unknown generic state"]; }; HandleUnGuarded: PROC [startProc: StartProc, duringProc, endProc, abortProc: MouseProc, event: LIST OF REF ANY, svData: SVData, worldPt: Point2d] = { genericAction, atom: ATOM; atomName: Rope.ROPE; atom _ NARROW[event.first]; atomName _ Atom.GetPName[atom]; genericAction _ IF Rope.Equal[Rope.Substr[atomName, 0, 5], "Start", TRUE] THEN $Start ELSE atom; HandleUnGuardedAux[startProc, duringProc, endProc, abortProc, genericAction, event, svData, worldPt]; }; HandleUnGuardedAux: PROC [startProc: StartProc, duringProc, endProc, abortProc: MouseProc, genericAction: ATOM, event: LIST OF REF ANY, svData: SVData, worldPt: Point2d] = { SELECT svData.state FROM $None => { SELECT genericAction FROM $Start => { [] _ InputFocus.SetInputFocus[svData.actionArea]; IF startProc[event, svData, worldPt] THEN svData.state _ $Main ELSE {abortProc[event, svData, worldPt]; svData.state _ $Aborted} }; ENDCASE; }; $Main => { SELECT genericAction FROM $During => duringProc[event, svData, worldPt]; $MouseUp, $AllUp => { endProc[event, svData, worldPt]; svData.state _ $None; svData.mouseMode _ $None; }; $Abort => {abortProc[event, svData, worldPt]; svData.state _ $Aborted}; $Start => { -- the mouse must have gone out of the window while the mouse button was done. Abort the current action and start a new one. abortProc[event, svData, worldPt]; svData.state _ $None; svData.mouseMode _ $None; HandleMouse[event, svData]; }; ENDCASE; }; $Aborted => { SELECT genericAction FROM $AllUp => {svData.state _ $None; svData.mouseMode _ $None}; $MouseUp => {svData.state _ $None; svData.mouseMode _ $None}; ENDCASE; }; ENDCASE => SIGNAL Problem[msg: "Unknown generic state"]; }; Restart: PROC [event: LIST OF REF ANY, svData: SVData] RETURNS [BOOL] = { mouseMode: ATOM _ svData.mouseMode; state: ATOM _ NARROW[event.first]; RETURN[ FALSE ]; }; SaveSavedState: PROC [svData: SVData] = { editToolData: EditToolData _ svData.editToolData; SVScene.SaveSelections[svData.scene]; SVWindow.SaveCaretPos[svData]; SVCaret.Copy[from: editToolData.skitter, to: svData.drag.savedCaret]; }; <<>> <> <<>> StartSkitter: PUBLIC StartProc = { CodeTimer.StartInt[$StartSkitter, $Solidviews]; SVEvent.Selected[NIL, svData]; SVSelections.SetModeSkitter[svData, surface]; SaveSavedState[svData]; DuringSkitter[NIL, svData, cameraPoint]; CodeTimer.StopInt[$StartSkitter, $Solidviews]; }; -- end of StartSkitter DragTheSkitter: PROC [svData: SVData, cameraPt: Point2d, action: Rope.ROPE _ ""] RETURNS [skitterWorld: Matrix4by4] = { surfacePtWorld: Point3d; normalWorld: Vector3d; sliceD: SliceDescriptor; feature: FeatureData; camera: Camera _ svData.camera; scene: Scene _ svData.scene; gravityType: GravityType _ SVState.GetGravityType[svData]; searchDepth: SearchDepth _ first; hitData: REF ANY; skitter: Skitter _ svData.editToolData.skitter; [surfacePtWorld, normalWorld, feature, hitData] _ SVGravity.RayMap[cameraPt, svData.hitTest.t, svData.hitTest.alignBag, svData.hitTest.sceneBag, svData, TRUE]; IF feature = NIL THEN SVCaret.SetAttractor[skitter, cameraPt, surfacePtWorld, normalWorld, NIL] ELSE { SELECT feature.type FROM slice => { sliceD _ NARROW[feature.shape]; SVCaret.SetAttractor[skitter, cameraPt, surfacePtWorld, normalWorld, sliceD]; IF sliceD # NIL THEN SVEditUser.SetCurrentAssemblyName[sliceD.slice, svData.editToolData]; }; anchor => { anchor: Skitter _ NARROW[feature.shape]; SVCaret.NoAttractor[skitter]; SVCaret.PositionFromMatrix[skitter, cameraPt, anchor.skitterWorld]; }; ENDCASE => SVCaret.SetAttractor[skitter, cameraPt, surfacePtWorld, normalWorld, feature.shape]; }; skitterWorld _ SVCaret.GetPosition[skitter]; Feedback.PutFHerald[svData.feedback, oneLiner, "%g Skitter on %g at [%g, %g, %g]", [rope[action]], [rope[SVDescribe.DescribeFeature[feature, hitData, svData]]], [real[surfacePtWorld[1]]], [real[surfacePtWorld[2]]], [real[surfacePtWorld[3]]] ]; }; DuringSkitter: MouseProc = { <> editToolData: EditToolData _ svData.editToolData; CodeTimer.StartInt[$DuringSkitter, $Solidviews]; [] _ DragTheSkitter[svData, cameraPoint, "SkitterMotion"]; SVViewersOnScene.PaintSceneAllViewers[paintAction: $DuringSkitterPos, editToolData: editToolData, scene: svData.scene, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; CodeTimer.StopInt[$DuringSkitter, $Solidviews]; }; -- end DuringSkitter EndSkitter: MouseProc = { CodeTimer.StartInt[$EndSkitter, $Solidviews]; [] _ DragTheSkitter[svData, cameraPoint, "SkitterMotion"]; SVWindow.NewCaretPos[svData]; SVWindow.RestoreScreenAndInvariants[paintAction: $SkitterMoved, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; CodeTimer.StopInt[$EndSkitter, $Solidviews]; }; <<>> <> UpdateSceneForCopy: PROC [scene: Scene, feedback: FeedbackData] RETURNS [newSlices: LIST OF Slice, success: BOOL _ TRUE] = { sliceDGen: SliceDescriptorGenerator; newSlice: Slice; <> sliceDGen _ SVSelect.SelectedSlices[scene, normal]; FOR sliceD: SliceDescriptor _ SVSelect.NextSliceDescriptor[sliceDGen], SVSelect.NextSliceDescriptor[sliceDGen] UNTIL sliceD = NIL DO <> newSlice _ SVScene.CopyAssemblyAndSonsUniqueNames[sliceD.slice, scene, scene, scene.assembly, feedback]; SVSelect.DeselectSlice[sliceD.slice, sliceD.parts, scene, normal]; newSlices _ CONS[newSlice, newSlices]; SVSelect.SelectEntireSlice[newSlice, scene, normal]; ENDLOOP; }; StartCopyAndDrag: PUBLIC StartProc = { <> newSlices: LIST OF Slice; scene: Scene _ svData.scene; SaveSavedState[svData]; -- must do this before any possible aborts occur [newSlices, success] _ UpdateSceneForCopy[scene, svData.feedback]; -- adds new shapes and selects them IF NOT success THEN RETURN; SVAlign.UpdateBagsForNewSlices[newSlices, svData]; success _ StartMotion[svData: svData, opName: "copy", cameraPoint: cameraPoint, saveState: FALSE, needAnchor: FALSE, backgroundOK: FALSE]; IF NOT success THEN RETURN[FALSE]; DuringDrag[NIL, svData, cameraPoint]; }; <<>> <> TransformObjectsAfterMove: PROC [scene: Scene, transform: Matrix4by4] = { sGen: SliceDescriptorGenerator; sGen _ SVSelect.SelectedSlices[scene, normal]; FOR sliceD: SliceDescriptor _ SVSelect.NextSliceDescriptor[sGen], SVSelect.NextSliceDescriptor[sGen] UNTIL sliceD = NIL DO SVAssembly.Transform[sliceD, scene, transform]; ENDLOOP; }; StartMotion: PROC [svData: SVData, opName: Rope.ROPE, cameraPoint: Point2d, saveState: BOOL _ TRUE, needAnchor: BOOL _ FALSE, backgroundOK: BOOL _ FALSE] RETURNS [success: BOOL _ TRUE] = { movingBox: BoundBox; repaintNeeded: BOOL; skitter: Skitter _ svData.editToolData.skitter; IF saveState THEN SaveSavedState[svData]; -- do this before aborts can occur BEGIN IF NOT SVRefresh.EmptyOverlay[svData] THEN ERROR; -- nothing on overlay IF SVSelect.NoSelections[svData.scene, normal] THEN GOTO NoSelections; IF needAnchor AND NOT SVCaret.Exists[svData.scene.anchor] THEN GOTO NoAnchor; SVRefresh.MoveAllSelectedToOverlay[svData, normal]; svData.drag.startSkitter _ SVCaret.GetPosition[svData.editToolData.skitter]; svData.drag.startPoint _ SVMatrix3d.OriginOfMatrix[svData.drag.startSkitter]; <> svData.drag.transform _ SVMatrix3d.Identity[]; <> movingBox _ SVBoundBox.BoundBoxOfMoving[svData.scene, svData.camera]; svData.refresh.startBoundBox^ _ movingBox^; IF NOT backgroundOK THEN SVRefresh.SplitBackgroundAndOverlay[svData, movingBox]; repaintNeeded _ SVAlign.StaticToDynamicBags[svData]; IF repaintNeeded THEN SVWindow.RestoreScreenAndInvariants[paintAction: $None, svData: svData, remake: bitMap, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE] ELSE SVWindow.RestoreScreenAndInvariants[paintAction: $None, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; EXITS NoSelections => { <> Feedback.Append[svData.feedback, "Please select a source to drag.", oneLiner]; Feedback.Blink[svData.feedback]; success _ FALSE; }; NoAnchor => { Feedback.PutFHerald[svData.feedback, oneLiner, "Anchor needed to %g", [rope[opName]]]; Feedback.Blink[svData.feedback]; success _ FALSE; }; END; }; StartDrag: StartProc = { <> startSuccess: BOOL _ StartMotion[svData, "Drag", cameraPoint]; IF NOT startSuccess THEN RETURN[FALSE]; DuringDrag[event, svData, cameraPoint]; }; StartRotate: PUBLIC StartProc = { startSuccess: BOOL _ StartMotion[svData, "rotate", cameraPoint, TRUE, TRUE]; IF NOT startSuccess THEN RETURN[FALSE]; DuringRotate[NIL, svData, cameraPoint]; }; StartScale: PUBLIC StartProc = { anchorPoint: Point3d; originalVector: Vector3d; startSuccess: BOOL _ StartMotion[svData, "scale", cameraPoint, TRUE, TRUE]; IF NOT startSuccess THEN RETURN[FALSE]; anchorPoint _ SVMatrix3d.OriginOfMatrix[SVCaret.GetPosition[svData.scene.anchor]]; originalVector _ SVVector3d.Sub[svData.drag.startPoint, anchorPoint]; IF originalVector = [0.0, 0.0, 0.0] THEN { Feedback.AppendHerald[svData.feedback, "Move skitter away from anchor before scaling.", oneLiner]; Feedback.Blink[svData.feedback]; RETURN[FALSE]; }; DuringScale[NIL, svData, cameraPoint]; }; DuringDrag: MouseProc = { camera: Camera _ svData.camera; scene: Scene _ svData.scene; newOrigin, oldOrigin: Point3d; newSkitterWORLD: Matrix4by4; d: Vector3d; newSkitterWORLD _ DragTheSkitter[svData, cameraPoint, "Drag"]; oldOrigin _ SVMatrix3d.OriginOfMatrix[svData.drag.startSkitter]; newOrigin _ SVMatrix3d.OriginOfMatrix[newSkitterWORLD]; d _ SVVector3d.Sub[newOrigin, oldOrigin]; svData.drag.transform _ SVMatrix3d.MakeTranslateMat[d[1], d[2], d[3]]; SVWindow.RestoreScreenAndInvariants[paintAction: $DuringMotion, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; DuringRotate: PUBLIC MouseProc = { originalVector, newVector: Vector3d; mapPoint: Point3d; anchorPoint: Point3d _ SVMatrix3d.OriginOfMatrix[SVCaret.GetPosition[svData.scene.anchor]]; mapPoint _ SVMatrix3d.OriginOfMatrix[DragTheSkitter[svData, cameraPoint, "Scaling"]]; originalVector _ SVVector3d.Sub[svData.drag.startPoint, anchorPoint]; newVector _ SVVector3d.Sub[mapPoint, anchorPoint]; svData.drag.transform _ RotateAboutPoint[anchorPoint, originalVector, newVector]; SVWindow.RestoreScreenAndInvariants[paintAction: $DuringMotion, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; DuringScale: PUBLIC MouseProc = { epsilon: REAL = 1.0e-3; originalVector, newVector: Vector3d; mapPoint: Point3d; ratio: REAL; anchorPoint: Point3d _ SVMatrix3d.OriginOfMatrix[SVCaret.GetPosition[svData.scene.anchor]]; mapPoint _ SVMatrix3d.OriginOfMatrix[DragTheSkitter[svData, cameraPoint, "Scaling"]]; originalVector _ SVVector3d.Sub[svData.drag.startPoint, anchorPoint]; newVector _ SVVector3d.Sub[mapPoint, anchorPoint]; IF RealFns.AlmostZero[newVector[1], -10] AND RealFns.AlmostZero[newVector[2], -10] AND RealFns.AlmostZero[newVector[3], -10] THEN RETURN; -- can't scale to zero ratio _ SVVector3d.Magnitude[newVector]/SVVector3d.Magnitude[originalVector]; svData.drag.transform _ ScaleAboutPoint[anchorPoint, ratio]; SVWindow.RestoreScreenAndInvariants[paintAction: $DuringMotion, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; EndMotion: MouseProc = { editToolData: EditToolData _ NARROW[svData.editToolData]; scene: Scene _ svData.scene; TransformObjectsAfterMove[scene, svData.drag.transform]; SVRefresh.MoveOverlayToBackground[svData]; SVWindow.NewCaretPos[svData]; [] _ SVAlign.DynamicToStaticBags[svData]; SVViewersOnScene.PaintSceneAllViewers[paintAction: $FinishedDragging, editToolData: editToolData, scene: scene, remake: bitMap, backgndOK: FALSE, edited: TRUE, okToClearFeedback: FALSE]; }; <> ScaleAboutPoint: PUBLIC PROC [origin: Point3d, scalar: REAL] RETURNS [m: Matrix4by4] = { m _ SVMatrix3d.MakeTranslateMat[-origin[1], -origin[2], -origin[3]]; m _ SVMatrix3d.Scale[m, scalar, scalar, scalar]; m _ SVMatrix3d.Translate[m, origin[1], origin[2], origin[3]]; }; RotateAboutPoint: PUBLIC PROC [origin: Point3d, originalVector, newVector: Vector3d] RETURNS [m: Matrix4by4] = { degrees: REAL; axis: Vector3d; epsilon: REAL = 1.0E-5; <> degrees _ SVVector3d.AngleCCWBetweenVectors[originalVector, newVector]; axis _ SVVector3d.CrossProduct[originalVector, newVector]; IF SVVector3d.Magnitude[axis] < epsilon THEN { -- the vectors are close to parallel. m _ SVMatrix3d.Identity[]; } ELSE { m _ SVMatrix3d.MakeTranslateMat[-origin[1], -origin[2], -origin[3]]; m _ SVMatrix3d.RotateAxis[m, axis, degrees]; m _ SVMatrix3d.Translate[m, origin[1], origin[2], origin[3]]; }; }; <> AddNewBlockSlice: PROC [from, to: Point3d, svData: SVData] RETURNS [sliceD: SliceDescriptor] = { completeSliceD: SliceDescriptor; scene: Scene _ svData.scene; corner: [0..7]; loX: REAL _ MIN[from[1], to[1]]; loY: REAL _ MIN[from[2], to[2]]; loZ: REAL _ MIN[from[3], to[3]]; hiX: REAL _ MAX[from[1], to[1]]; hiY: REAL _ MAX[from[2], to[2]]; hiZ: REAL _ MAX[from[3], to[3]]; IF to[1]=loX THEN { IF to[2]=loY THEN { IF to[3]=loZ THEN corner _ 5 ELSE corner _ 4} ELSE { IF to[3]=loZ THEN corner _ 1 ELSE corner _ 0} } ELSE { IF to[2]=loY THEN { IF to[3]=loZ THEN corner _ 6 ELSE corner _ 7} ELSE { IF to[3]=loZ THEN corner _ 2 ELSE corner _ 3} }; sliceD _ SVAssembly.MakeBlockSlice[loX, loY, loZ, hiX, hiY, hiZ, corner, SVMatrix3d.Identity[], scene, svData.feedback]; svData.drag.blockInProgress _ sliceD; completeSliceD _ SVAssembly.NewParts[sliceD.slice, NIL, [0,0,0], slice]; <> <> AddSlice[sliceD.slice, scene]; }; AddSlice: PROC [slice: Slice, scene: Scene] = { sceneAssembly: Slice; sceneAssembly _ scene.assembly; [] _ SVAssembly.AddPrimitive[slice, [1,1,1], sceneAssembly, SVMatrix3d.Identity[], scene]; }; StartBlock: PUBLIC StartProc = { sliceD: SliceDescriptor; caretPos: Point3d; editToolData: EditToolData _ svData.editToolData; CodeTimer.StartInt[$StartBlock, $Solidviews]; caretPos _ SVCaret.GetPoint[editToolData.skitter]; SaveSavedState[svData]; -- must do this before any possible aborts occur IF NOT SVRefresh.EmptyOverlay[svData] THEN ERROR; <> svData.drag.startSkitter _ DragTheSkitter[svData, cameraPoint, "StartBlock"]; svData.drag.startPoint _ SVMatrix3d.OriginOfMatrix[svData.drag.startSkitter]; svData.drag.transform _ SVMatrix3d.Identity[]; <> sliceD _ AddNewBlockSlice[caretPos, svData.drag.startPoint, svData]; SVAssembly.SetFillColor[sliceD.slice, NIL, svData.defaults.fillColor]; SVAssembly.SetStrokeColor[sliceD.slice, NIL, svData.defaults.strokeColor]; SVSelect.DeselectAll[svData.scene, normal]; SVSelect.SelectSlice[sliceD, svData.scene, normal]; <> SVRefresh.MoveToOverlay[sliceD, svData]; -- slice on overlay to be rubberbanded SVRefresh.SplitBackgroundAndOverlay[svData, GGBoundBox.emptyBoundBox]; SVWindow.RestoreScreenAndInvariants[paintAction: $None, svData: svData, remake: bitMap, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; DuringDrag[NIL, svData, cameraPoint]; CodeTimer.StopInt[$StartBlock, $Solidviews]; }; EndBlock: PUBLIC MouseProc = { <> sliceD: SliceDescriptor _ NARROW[svData.drag.blockInProgress]; slice: Slice _ sliceD.slice; SVAssembly.Transform[sliceD, svData.scene, svData.drag.transform]; -- update the slice SVRefresh.MoveOverlayToBackground[svData]; svData.refresh.startBoundBox^ _ SVAssembly.GetBoundBox[slice, NIL, svData.camera]^; svData.refresh.addedObject _ slice; SVWindow.RestoreScreenAndInvariants[paintAction: $FinishedAdding, svData: svData, remake: triggerBag, backgndOK: FALSE, edited: TRUE, okToClearFeedback: FALSE]; }; StartSelectWithBlock: PUBLIC StartProc = { sliceD: SliceDescriptor; slice: Slice; caretPos: Point3d; scene: Scene _ svData.scene; editToolData: EditToolData _ svData.editToolData; caretPos _ SVCaret.GetPoint[editToolData.skitter]; SaveSavedState[svData]; -- must do this before any possible aborts occur IF NOT SVRefresh.EmptyOverlay[svData] THEN ERROR; -- nothing on overlay <> svData.drag.startSkitter _ DragTheSkitter[svData, cameraPoint, "StartSelectWithBlock"]; svData.drag.startPoint _ SVMatrix3d.OriginOfMatrix[svData.drag.startSkitter]; svData.drag.transform _ SVMatrix3d.Identity[]; <> sliceD _ AddNewBlockSlice[caretPos, svData.drag.startPoint, svData]; slice _ sliceD.slice; SVAssembly.SetFillColor[slice, NIL, NIL]; SVAssembly.SetStrokeColor[slice, NIL, Imager.black]; SVSelect.DeselectAll[scene, normal]; SVSelect.SelectSlice[sliceD: sliceD, scene: scene, selectClass: normal]; <> SVRefresh.MoveToOverlay[sliceD, svData]; -- slice on overlay to be rubberbanded SVRefresh.SplitBackgroundAndOverlay[svData, GGBoundBox.emptyBoundBox]; SVWindow.RestoreScreenAndInvariants[paintAction: $None, svData: svData, remake: bitMap, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; DuringDrag[NIL, svData, cameraPoint]; }; EndSelectWithBlock: PUBLIC MouseProc = { <> sliceD: SliceDescriptor _ NARROW[svData.drag.blockInProgress]; slice: Slice _ sliceD.slice; block: BoundBlock; SVAssembly.Transform[sliceD, svData.scene, svData.drag.transform]; -- update the slice SVRefresh.MoveOverlayToBackground[svData]; block _ SVAssembly.GetBoundBlock[slice]; SVSelect.DeselectSliceAllClasses[slice, svData.scene]; SVScene.DeleteSlice[svData.scene, slice]; SVScene.SelectInBlock[svData.scene, block, normal]; SVWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; EndSelectPartsWithBlock: PUBLIC MouseProc = { <> sliceD: SliceDescriptor _ NARROW[svData.drag.blockInProgress]; slice: Slice _ sliceD.slice; block: BoundBlock; SVAssembly.Transform[sliceD, svData.scene, svData.drag.transform]; -- update the slice SVRefresh.MoveOverlayToBackground[svData]; block _ SVAssembly.GetBoundBlock[slice]; SVSelect.DeselectSliceAllClasses[slice, svData.scene]; SVScene.DeleteSlice[svData.scene, slice]; SVScene.SelectPartsInBlock[svData.scene, block, normal]; SVWindow.RestoreScreenAndInvariants[paintAction: $SelectionChanged, svData: svData, remake: none, backgndOK: TRUE, edited: FALSE, okToClearFeedback: FALSE]; }; FixupAbortedBox: PROC [svData: SVData] = { <> sliceD: SliceDescriptor _ NARROW[svData.drag.blockInProgress]; slice: Slice _ sliceD.slice; scene: Scene _ svData.scene; repaintBox: BoundBox _ GGBoundBox.NullBoundBox[]; GGBoundBox.EnlargeByBox[repaintBox, SVAssembly.GetBoundBox[slice, NIL, svData.camera]]; -- repaint deleted box slice [] _ SVScene.DeleteSubassemblyFromAssembly[slice, scene.assembly, scene]; svData.refresh.startBoundBox^ _ repaintBox^; SVWindow.RestoreScreenAndInvariants[paintAction: $ObjectChangedBoundBoxProvided, svData: svData, remake: triggerBag, backgndOK: FALSE, edited: FALSE, okToClearFeedback: FALSE]; }; <<>> <> RayToPoint: PUBLIC PROC [cameraRay: Ray, cameraPt: Point3d] RETURNS [dSquared: REAL] = { <> magRaySquared, dotProd, dotProdSquared, rCosThetaSquared, rSquared: REAL; screenToPoint: Vector3d; basePt: Point3d; direction: Vector3d; [basePt, direction] _ SVRay.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 }; NearestAssemblyToRay: PROC [cameraRay: Ray, root: Slice, camera: Camera] RETURNS [nearest: Slice, dSquared: REAL] = { sonD: REAL; sonA: Slice; origin: Point3d; WITH root.shape SELECT FROM shape: Shape => { -- A primitive. Just compute distance. nearest _ root; origin _ SVMatrix3d.OriginOfMatrix[SVCoordSys.WRTCamera[root.coordSys, camera.coordSys]]; dSquared _ RayToPoint[cameraRay, origin]; }; alist: SliceList => { -- Take the minimum of myself and my subtrees, giving preference to the subtrees nearest _ root; origin _ SVMatrix3d.OriginOfMatrix[SVCoordSys.WRTCamera[root.coordSys, camera.coordSys]]; dSquared _ RayToPoint[cameraRay, origin]; FOR sons: LIST OF Slice _ alist.list, sons.rest UNTIL sons = NIL DO [sonA, sonD] _ NearestAssemblyToRay[cameraRay, sons.first, camera]; IF sonD <= dSquared THEN { nearest _ sonA; dSquared _ sonD; }; ENDLOOP; }; ENDCASE => ERROR; }; StartCoordSkitter: StartProc = { SVEvent.Selected[NIL, svData]; DuringCoordSkitter[event, svData, cameraPoint]; }; DuringCoordSkitter: MouseProc = { <> cameraRay: Ray _ SVRay.GetRayFromPool[]; camera: Camera _ svData.camera; scene: Scene _ svData.scene; nearest: Slice; skitter: Skitter _ svData.editToolData.skitter; SVRay.StuffCameraRay[cameraRay, cameraPoint, camera]; [nearest, ----] _ NearestAssemblyToRay[cameraRay, scene.assembly, camera]; SVRay.ReturnRayToPool[cameraRay]; SVCaret.SetAssemblyAndPrimitive[skitter, nearest, NIL]; SVCaret.PositionFromMatrix[svData.editToolData.skitter, cameraPoint, SVCoordSys.WRTWorld[nearest.coordSys]]; SVSelections.SetModeSkitter[svData, coordframe]; SVWindow.RestoreScreenAndInvariants[$SkitterMoved, svData]; }; EndCoordSkitter: MouseProc = {}; StartTightRope: StartProc = { <> planeSel: Selection; planeAssem: Slice; scene: Scene _ svData.scene; planeSel _ SVSelections.TopPlane[]; SVSelections.SetModeSkitter[svData, tightrope]; IF planeSel = NIL THEN { Feedback.Append[svData.feedback, "Please make a plane selection to specify tightrope.", oneLiner]; Feedback.Blink[svData.feedback]; RETURN; }; planeAssem _ planeSel.coincident; IF planeAssem.toolMasterObject = NIL OR planeAssem.toolMasterObject.mainBody = NIL THEN SVScene.AddOrResizeToolToAssembly[planeAssem, scene]; DuringTightRope[event, svData, cameraPoint]; }; TightRopeAux: PRIVATE PROC [svData: SVData, cameraPoint: Point2d, target: Slice] RETURNS [skitterWORLD: Matrix4by4] = { <> skitterTarget: Matrix4by4; newOriginCamera, newOriginTarget: Point3d; plane: NAT; toolData: ToolData; cameraDir: Vector3d; camera1, camera2: Point3d; screen1, screen2, q: Point2d; ropeShadow, normalLine: TrigLine; parallel: BOOL; camera: Camera _ svData.camera; targetCS: CoordSystem _ target.coordSys; targetCamera: Matrix4by4; worldCS: CoordSystem _ svData.scene.coordSysRoot; cameraCS: CoordSystem _ camera.coordSys; <> <> <> <<};>> targetCamera _ SVCoordSys.WRTCamera[targetCS, camera.coordSys]; camera1 _ SVMatrix3d.OriginOfMatrix[targetCamera]; toolData _ NARROW[target.toolMasterObject.mainBody]; plane _ toolData.plane; plane _ IF plane > 3 THEN 3 ELSE plane; SELECT plane FROM 1 => cameraDir _ SVMatrix3d.XAxisOfMatrix[targetCamera]; 2 => cameraDir _ SVMatrix3d.YAxisOfMatrix[targetCamera]; 3 => cameraDir _ SVMatrix3d.ZAxisOfMatrix[targetCamera]; ENDCASE => ERROR; camera2 _ SVVector3d.Add[camera1, cameraDir]; screen1 _ SVGraphics.DoProjection[camera1, camera]; screen2 _ SVGraphics.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: Vector3d; 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 _ SVCoordSys.FromCSToCS[newOriginCamera, cameraCS, targetCS]; <> skitterTarget _ SVMatrix3d.MakeTranslateMat[newOriginTarget[1], newOriginTarget[2], newOriginTarget[3]]; skitterWORLD _ SVCoordSys.FromCSToCSMat[skitterTarget, targetCS, worldCS]; }; DuringTightRope: MouseProc = { <> planeAssem: Slice; planeSel: Selection; skitterWORLD: Matrix4by4; camera: Camera _ svData.camera; skitter: Skitter _ svData.editToolData.skitter; planeSel _ SVSelections.TopPlane[]; IF planeSel = NIL THEN RETURN; planeAssem _ planeSel.coincident; skitterWORLD _ TightRopeAux[svData, cameraPoint, planeAssem]; SVCaret.SetAssemblyAndPrimitive[skitter, NIL, NIL]; SVCaret.PositionFromMatrix[svData.editToolData.skitter, cameraPoint, skitterWORLD]; SVWindow.RestoreScreenAndInvariants[$SkitterMoved, svData]; }; EndTightRope: MouseProc = { DuringTightRope[event, svData, cameraPoint]; }; StartWallWalk: StartProc = { planeSel: Selection; planeAssem: Slice; scene: Scene _ svData.scene; planeSel _ SVSelections.TopPlane[]; SVSelections.SetModeSkitter[svData, tightrope]; IF planeSel = NIL THEN { Feedback.Append[svData.feedback, "Please make a plane selection to specify walk wall.", oneLiner]; Feedback.Blink[svData.feedback]; RETURN; }; planeAssem _ planeSel.coincident; IF planeAssem.toolMasterObject = NIL OR planeAssem.toolMasterObject.mainBody = NIL THEN SVScene.AddOrResizeToolToAssembly[planeAssem, scene]; DuringWallWalk[event, svData, cameraPoint]; }; RayMeetsTopPlane: PROC [cameraPoint: Point2d, target: Slice, depth: REAL, plane: NAT, camera: Camera] RETURNS [planePtWorld: Point3d, parallel: BOOL] = { <> newRay: Ray; newRay _ SVRay.GetRayFromPool[]; SVRay.StuffWorldRayFromCamera[newRay, cameraPoint, camera]; [planePtWorld, parallel] _ SVCastRays.RayMeetsPlaneOfCoordSystem[target.coordSys, newRay, plane, depth]; SVRay.ReturnRayToPool[newRay]; }; DuringWallWalk: MouseProc = { <> planeAssem: Slice; planeSel: Selection; targetWORLD, skitterWORLD: Matrix4by4; hitPointWORLD: Point3d; camera: Camera _ svData.camera; scene: Scene _ svData.scene; worldCS: CoordSystem _ scene.coordSysRoot; toolData: ToolData; parallel: BOOL; skitter: Skitter _ svData.editToolData.skitter; planeSel _ SVSelections.TopPlane[]; IF planeSel = NIL THEN RETURN; planeAssem _ planeSel.coincident; toolData _ NARROW[planeAssem.toolMasterObject.mainBody]; IF toolData = NIL THEN { Feedback.Append[svData.feedback, "Wall walk plane is not defined.", oneLiner]; Feedback.Blink[svData.feedback]; RETURN; }; <> [hitPointWORLD, parallel] _ RayMeetsTopPlane[cameraPoint, planeAssem, 0, toolData.plane, camera]; IF parallel THEN { Feedback.Append[svData.feedback, "DuringWallWalk: plane is parallel to ray.", oneLiner]; Feedback.Blink[svData.feedback]; RETURN; }; targetWORLD _ SVCoordSys.WRTWorld[planeAssem.coordSys]; skitterWORLD _ SVMatrix3d.Translate[targetWORLD, hitPointWORLD[1], hitPointWORLD[2], hitPointWORLD[3]]; SVCaret.SetAssemblyAndPrimitive[skitter, NIL, NIL]; SVCaret.PositionFromMatrix[svData.editToolData.skitter, cameraPoint, skitterWORLD]; SVWindow.RestoreScreenAndInvariants[$SkitterMoved, svData]; }; EndWallWalk: MouseProc = { DuringWallWalk[event, svData, cameraPoint]; }; <> <> <> <> <> <> <> <> <> <<>> <> <<[oldAssembly, oldPrimitive, oldSVData] _ SVSelections.GetSkitterData[editToolData];>> <> <<[assem, prim, vtd] _ SVSelections.GetSkitterData[editToolData];>> <> <> <> <> <<};>> <> <> <> <> <<};>> <<};>> <<>> <> <> <> <> <> <> <> <<>> <> <<[oldAssembly, oldPrimitive, oldSVData] _ SVSelections.GetSkitterData[editToolData];>> <> <<[assem, prim, vtd] _ SVSelections.GetSkitterData[editToolData];>> <> <> <> <> <<};>> <> <> <> <> <<};>> <<};>> <<>> <> Paint: PUBLIC MouseProc = { <> editToolData: EditToolData _ svData.editToolData; artworkToolData: ArtworkToolData _ NARROW[editToolData.artworkTool.data]; camera: Camera _ svData.camera; artwork: Artwork _ artworkToolData.artwork; assembly: Slice; skitterWORLD, assemWORLD, skitterassem: Matrix4by4; imagePoint: Point2d; skitterPoint, surfPtassem: Point3d; normal: Vector3d; paintColor: Color _ artworkToolData.paintColor; DuringSkitter[event, svData, cameraPoint]; [assembly, ----, svData] _ SVSelections.GetSkitterData[editToolData]; skitterWORLD _ SVCaret.GetPosition[editToolData.skitter]; assemWORLD _ SVCoordSys.WRTWorld[assembly.coordSys]; skitterassem _ SVMatrix3d.AInTermsOfB[skitterWORLD, assemWORLD]; normal _ SVMatrix3d.ZAxisOfMatrix[skitterassem]; <> FOR i: INT IN [-2..2] DO FOR j: INT IN [-2..2] DO skitterPoint _ [i, j, 0.0]; surfPtassem _ SVMatrix3d.Update[skitterPoint, skitterassem]; imagePoint _ SVArtworkUser.GetImagePointFromSurfacePoint[artwork, surfPtassem, normal]; <> SetImageColorAtPoint[artwork, imagePoint, paintColor]; ENDLOOP; ENDLOOP; SVWindow.RestoreScreenAndInvariants[$DrawPaint, svData]; }; 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] _ SVShading.ExtractRGB[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.Fix[-vAIS + artwork.halfHeightDots], Real.Fix[uAIS + artwork.halfWidthDots]]; greenValue _ Real.Fix[realGreenValue*255.0]; AIS.WriteSample[artwork.greenWindow, greenValue, Real.Fix[-vAIS + artwork.halfHeightDots], Real.Fix[uAIS + artwork.halfWidthDots]]; blueValue _ Real.Fix[realBlueValue*255.0]; AIS.WriteSample[artwork.blueWindow, blueValue, Real.Fix[-vAIS + artwork.halfHeightDots], Real.Fix[uAIS + artwork.halfWidthDots]]; } ELSE {-- artwork is a black and white file blackValue: CARDINAL; realBlackValue: REAL; realBlackValue _ ImagerColorPrivate.IntensityFromColor[NARROW[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.Fix[-vAIS + artwork.halfHeightDots], Real.Fix[uAIS + artwork.halfWidthDots]]; }; END; }; -- end of SetImageColorAtPoint <> <> <> < 3 THEN depth _ targetPt[3]>> <> <> <<};>> <<>> <> <> <> <> <> <> <> <<[planePtWorld, parallel] _ SVCastRays.RayMeetsPlaneOfCoordSystem[planeA.coordSys, rayWorld, plane, depth];>> <> <> <> <<};>> <<>> <> <> <> <> <> <> <<[planePtWorld, parallel] _ SVCastRays.RayMeetsPlaneOfCoordSystem[camera.coordSys, rayWorld, 3, depth];>> <> <> <> <<};>> <<>> InitStats: PROC = { interval: CodeTimer.Interval; interval _ CodeTimer.CreateInterval[$StartSkitter]; CodeTimer.AddInt[interval, $Solidviews]; interval _ CodeTimer.CreateInterval[$DuringSkitter]; CodeTimer.AddInt[interval, $Solidviews]; interval _ CodeTimer.CreateInterval[$EndSkitter]; CodeTimer.AddInt[interval, $Solidviews]; interval _ CodeTimer.CreateInterval[$StartBlock]; CodeTimer.AddInt[interval, $Solidviews]; }; InitStats[]; END.