<<>> <> <> <> DIRECTORY Commander, Controls, Draw2d, G3dBasic, G3dControl, G3dDraw, G3dMatrix, G3dPatch, G3dTool, G3dView, Real, ViewerOps; G3dPatchCmdImpl: CEDAR PROGRAM IMPORTS Controls, Draw2d, G3dControl, G3dDraw, G3dMatrix, G3dPatch, G3dTool, G3dView, Real, ViewerOps ~ BEGIN IntegerPair: TYPE ~ RECORD [i, j: INTEGER]; Data: TYPE ~ REF DataRep; DataRep: TYPE ~ RECORD [ camera: G3dControl.CameraControl ¬ NIL, outer: Controls.Viewer ¬ NIL, outerData: Controls.OuterData ¬ NIL, graphics: Controls.Viewer ¬ NIL, view: G3dMatrix.Matrix ¬ NIL, hold: G3dControl.Hold ¬ NIL, res: Controls.Control ¬ NIL, selected: IntegerPair ¬ [-1, -1], patch: G3dPatch.Patch ¬ NIL ]; PatchCmd: Commander.CommandProc ~ { t13: REAL ¬ 1.0/3.0; d: Data ~ NEW[DataRep]; cp: G3dPatch.ControlPoints ¬ NEW[G3dPatch.ControlPointsRep]; cp[0] ¬ [[-1.0, -1.0, 0.0], [-1.0/3.0, -1.0, 0.5], [1.0/3.0, -1.0, 0.5], [1.0, -1.0, 0.0]]; cp[1] ¬ [[-1.0, -t13, 0.0], [-1.0/3.0, -t13, 0.5], [1.0/3.0, -t13, 0.5], [1.0, -t13, 0.0]]; cp[2] ¬ [[-1.0, t13, 0.0], [-1.0/3.0, t13, 0.5], [1.0/3.0, t13, 0.5], [1.0, t13, 0.0]]; cp[3] ¬ [[-1.0, 1.0, 0.0], [-1.0/3.0, 1.0, 0.5], [1.0/3.0, 1.0, 0.5], [1.0, 1.0, 0.0]]; d.patch ¬ G3dPatch.FromBezier[cp]; d.camera ¬ G3dControl.InitCameraControl[proc: CameraControl, fieldOfView: 0, clientData: d]; d.hold ¬ G3dControl.InitHold[ControlPointMove, d]; d.res ¬ Controls.NewControl[name: "Res", min: 3, max: 20, init: 5, precision: 0, proc: Res]; d.outerData ¬ Controls.OuterViewer[ name: "Test Patch", controls: LIST[ d.camera.fieldOfView, d.camera.scale, d.camera.proxy.xRot, d.camera.proxy.yRot, d.camera.proxy.zRot, d.hold.x, d.hold.y, d.hold.z, d.res], typescriptHeight: 18, graphicsHeight: 400, mouseProc: Mouser, drawProc: Drawer, clientData: d ]; d.outer ¬ d.outerData.parent; d.graphics ¬ d.outerData.graphics; }; CameraControl: Controls.ControlProc ~ { IF control.mouse.button = right AND control.mouse.state # up THEN Repaint[NARROW[clientData]]; }; Drawer: Controls.DrawProc ~ { d: Data ~ NARROW[clientData]; Action: PROC ~ { res: NAT ¬ Real.Round[d.res.value]; vp: G3dMatrix.Viewport ¬ G3dView.GetViewport[viewer]; cp: G3dPatch.ControlPoints ¬ d.patch.controlPoints; d.view ¬ G3dControl.InitContext[context, d.camera, viewer,, d.view]; IF d.selected # [-1, -1] THEN G3dDraw.Mark[context, cp[d.selected.i][d.selected.j], d.view, vp,, asterisk]; G3dDraw.Patch[context, d.view, vp, d.patch, res, res]; FOR i: NAT IN [0..4) DO FOR j: NAT IN [0..3) DO G3dDraw.Segment[context, cp[i][j], cp[i][j+1], d.view, vp, dotted]; G3dDraw.Segment[context, cp[j][i], cp[j+1][i], d.view, vp, dotted]; ENDLOOP; ENDLOOP; }; Draw2d.DoWithBuffer[context, Action]; }; Mouser: Controls.MouseProc ~ { d: Data ~ NARROW[clientData]; minSq: REAL ¬ 1000000.0; FOR i: NAT IN [0..4) DO FOR j: NAT IN [0..4) DO p: G3dBasic.Pair ¬ G3dMatrix.TransformD[d.patch.controlPoints[i][j], d.view]; dx: REAL ¬ mouse.pos.x-p.x; dy: REAL ¬ mouse.pos.y-p.y; sq: REAL ¬ dx*dx+dy*dy; IF sq < minSq THEN {minSq ¬ sq; d.selected ¬ [i, j]}; ENDLOOP; ENDLOOP; G3dControl.SetHold[d.hold, d.patch.controlPoints[d.selected.i][d.selected.j]]; Repaint[d]; }; Res: Controls.ControlProc ~ {Repaint[NARROW[control.clientData]]}; ControlPointMove: Controls.ControlProc ~ { d: Data ~ NARROW[control.clientData]; d.patch.controlPoints[d.selected.i][d.selected.j] ¬ [d.hold.x.value, d.hold.y.value, d.hold.z.value]; d.patch ¬ G3dPatch.FromBezier[d.patch.controlPoints, d.patch]; Repaint[d]; }; Repaint: PROC [d: Data] ~ {ViewerOps.PaintViewer[d.graphics, client, FALSE, d]}; G3dTool.Register["Patch", PatchCmd, "play with patches"]; END.