<> <> <> <> <> <<>> <> <> DIRECTORY Args USING [Arg, ArgsGet, Error, NArgs], BasicTime USING [GMT, Now, Period], Commander USING [CommandProc, Register], FS USING [ComponentPositions, Copy, Delete, Error, ExpandName, FileInfo, Position, SetKeep], Imager USING [Context, Rectangle], ImagerBrick USING [Brick], ImagerInterpress USING [Close, Create, DoPage, Ref], ImagerSample USING [NewSampleMap, Put], Interpress USING [classAppearanceError, classAppearanceWarning, classComment, classMasterError, classMasterWarning, Close, DoPage, LogProc, Master, Open], InterpressCC USING [InitCC, StandardCC], InterpressToPD USING [DoCommand, ParamsFromPrinterType, PDParams, ProgressProc], IO USING [int, PutFR, PutFR1, real, rope], MessageWindow USING [Append, Blink, Clear], NectarinePd, PeachPrint USING [DoPeachPrintCommand, PupAborted], Process USING [CheckForAbort, Detach, priorityBackground, SetPriority], Real USING [InlineRound], Rope USING [Cat, Concat, IsEmpty, Replace, ROPE, Substr], RuntimeError USING [UNCAUGHT], SafeStorage USING [ReclaimCollectibleObjects], <> SimpleMailer USING [SendMessage], TerminalIO USING [TOS, PutF, PutRope], UserCredentials USING [Get], UserProfile USING [Boolean, Token]; NectarinePdImpl: CEDAR PROGRAM IMPORTS Args, BasicTime, Commander, FS, ImagerInterpress, ImagerSample, Interpress, InterpressCC, InterpressToPD, IO, MessageWindow, PeachPrint, Process, Real, Rope, RuntimeError, SafeStorage, SimpleMailer, TerminalIO, UserCredentials, UserProfile EXPORTS NectarinePd ~ BEGIN OPEN Real; communicationsFailure: PUBLIC SIGNAL ~ CODE; pause: SIGNAL ~ CODE; ROPE: TYPE ~ Rope.ROPE; Brick: TYPE ~ ImagerBrick.Brick; brickK: REF Brick _ NEW [Brick]; brickC: REF Brick _ NEW [Brick]; brickM: REF Brick _ NEW [Brick]; brickY: REF Brick _ NEW [Brick]; medium: Imager.Rectangle ~ [x: 0.0, y: 0.0, w: 215.9, h: 279.4]; -- in mm field: PUBLIC Imager.Rectangle _ [x: medium.x + 10.0, y: medium.y + 10.0, w: medium.w - 20.0, h: medium.h - 20.0]; -- in mm mmXin: REAL ~ 25.4; debug: BOOL _ FALSE; <> ForcedDelete: PROC [fileName: ROPE] ~ BEGIN <> TRUSTED BEGIN SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects; SafeStorage.ReclaimCollectibleObjects; Process.Detach [FORK FS.Delete [fileName ! FS.Error => CONTINUE; RuntimeError.UNCAUGHT => CONTINUE]] END END; -- ForcedDelete MergeRegisterMarks: PROC [masterName: ROPE] RETURNS [newName: ROPE] ~ BEGIN <> pos: FS.ComponentPositions; fullName: ROPE; out: ImagerInterpress.Ref; image, marks: Interpress.Master; [fullName, pos] _ FS.ExpandName [masterName]; newName _ fullName.Substr [pos.base.start, pos.base.length].Concat ["-Bis"]; newName _ fullName.Replace [pos.base.start, pos.base.length, newName]; out _ ImagerInterpress.Create [newName]; image _ Interpress.Open [masterName, LogInterpress]; IF DoLineArt[] AND (NOT UseProcessColors[]) THEN marks _ Interpress.Open ["[DATools7.0]MechanicRegisterMarks.Interpress", LogInterpress] ELSE marks _ Interpress.Open ["[DATools7.0]ProcessRegisterMarks.Interpress", LogInterpress]; FOR page: INT IN [1 .. image.pages] DO pageM: INT ~ ((page-1) MOD marks.pages) + 1; DoIt: PROC [context: Imager.Context] ~ BEGIN <> Interpress.DoPage [master: image, page: page, context: context, log: LogInterpress]; Interpress.DoPage [master: marks, page: pageM, context: context, log: LogInterpress] END; -- DoIt ImagerInterpress.DoPage [self: out, action: DoIt] ENDLOOP; image.Close; out.Close; marks.Close; image _ NIL; out_ NIL; marks _ NIL; ForcedDelete [masterName]; TerminalIO.PutF ["\n%g copied to %g with register marks.\n", IO.rope [masterName], IO.rope [newName]] END; -- MergeRegisterMarks LogInterpress: Interpress.LogProc ~ BEGIN <> TerminalIO.PutRope [SELECT class FROM Interpress.classMasterError => "Master Error: ", Interpress.classMasterWarning => "Master Warning: ", Interpress.classAppearanceError => "Appearance Error: ", Interpress.classAppearanceWarning => "Appearance Warning: ", Interpress.classComment => "Comment: ", ENDCASE => IO.PutFR1 ["Class %g error: ", IO.int [class]]]; TerminalIO.PutRope [explanation]; TerminalIO.PutRope [" . . . \n"] END; -- LogInterpress ProgressLog: InterpressToPD.ProgressProc ~ BEGIN <<[begin: BOOL, page: INT]>> IF begin THEN TerminalIO.PutRope [IO.PutFR1 ["[%g", IO.int [page]]] ELSE TerminalIO.PutRope ["] "] END; -- ProgressLog UseProcessColors: PROC RETURNS [BOOL] ~ INLINE BEGIN RETURN [UserProfile.Boolean [key: "Nectarine.ProcessColors", default: TRUE]] END; -- UseProcessColors DoLineArt: PROC RETURNS [BOOL] ~ INLINE BEGIN RETURN [UserProfile.Boolean [key: "Nectarine.LineArt", default: FALSE]] END; -- DoLineArt ImportantMessage: PROC [msg: ROPE] ~ BEGIN <> TerminalIO.PutRope [msg]; TerminalIO.PutRope ["\n"]; MessageWindow.Clear []; MessageWindow.Append [msg]; MessageWindow.Blink [] END; -- ImportantMessage TimeToRope: PROC [from, to: BasicTime.GMT] RETURNS [time: ROPE] ~ BEGIN <> TwoPosInt: PROC [i: INT] RETURNS [ROPE] ~ BEGIN RETURN [SELECT i FROM = 0 => "00", < 10 => Rope.Cat ["0", IO.PutFR1 [value: IO.int [i]]], ENDCASE => IO.PutFR1 [value: IO.int [i]]] END; s: INT _ BasicTime.Period [from, to]; m: INT _ s / 60; h: INT _ m / 60; d: INT ~ h / 24; s _ s MOD 60; m _ m MOD 60; h _ h MOD 24; IF (d > 0) THEN time _ Rope.Cat ["d:h:m:s ", TwoPosInt[d], ":"] ELSE time _ "h:m:s "; time _ time.Cat [TwoPosInt[h], ":"]; RETURN [time.Cat [TwoPosInt[m], ":", TwoPosInt[s]]] END; -- TimeToRope PdPrintProcess: PUBLIC PROC [masterName, peachName: Rope.ROPE, printerKey: ATOM, copies: INT, doNotScale, mergeRegister: BOOL, sizeHint: REF Imager.Rectangle _ NIL, abortFlag: REF BOOL] ~ BEGIN <> <> <> {ENABLE BEGIN PeachPrint.PupAborted => GOTO peachFailure; END; serverName: ROPE; startTime: BasicTime.GMT; deviceParameters: InterpressToPD.PDParams; doGreyBalance: BOOL ~ UserProfile.Boolean ["Nectarine.GreyBalance", FALSE]; doColorCorrection: BOOL ~ UserProfile.Boolean ["Nectarine.ColorCorrection", FALSE]; scale: REAL; TRUSTED {Process.SetPriority [Process.priorityBackground]}; IF doColorCorrection THEN TerminalIO.PutRope ["Will perform color correction\n"]; IF doGreyBalance AND (NOT doColorCorrection) THEN TerminalIO.PutRope ["Will balance greys\n"]; SELECT printerKey FROM $NVersatec => BEGIN <> deviceParameters _ InterpressToPD.ParamsFromPrinterType [$versatec]; IF (sizeHint # NIL) AND (sizeHint.h > sizeHint.w) THEN BEGIN scale _ (mmXin * deviceParameters.pageFSize) / sizeHint.w; IF (scale*sizeHint.h > (mmXin*deviceParameters.pageSSize)) THEN scale _ (mmXin * deviceParameters.pageSSize) / field.h; IF (scale * sizeHint.h > 2000) THEN ImportantMessage [" Your plot will be longer than 2 metres. Printing anyway"] END ELSE scale _ (mmXin * deviceParameters.pageFSize) / field.w; serverName _ UserProfile.Token ["Nectarine.Versatec", "Sleepy"] END; $NColorVersatec, $NPeachExpand => BEGIN <> deviceParameters _ InterpressToPD.ParamsFromPrinterType [$colorVersatec]; IF (sizeHint # NIL) AND (sizeHint.w = 40*mmXin) THEN scale _ 1.0 ELSE BEGIN IF (sizeHint # NIL) AND (sizeHint.h > sizeHint.w) THEN BEGIN scale _ (mmXin * deviceParameters.pageFSize) / sizeHint.w; IF (scale*sizeHint.h > (mmXin*deviceParameters.pageSSize)) THEN scale _ (mmXin * deviceParameters.pageSSize) / field.h; IF (scale * sizeHint.h > 2000) THEN ImportantMessage [" Your plot will be longer than 2 metres. Printing anyway"] END ELSE scale _ (mmXin * deviceParameters.pageFSize) / field.w END; serverName _ IF (printerKey = $NColorVersatec) THEN UserProfile.Token ["Nectarine.ColorVersatec", "Sleepy"] ELSE UserProfile.Token ["Nectarine.PeachExpand", "Kearsarge"]; IF (doGreyBalance OR doColorCorrection) THEN BEGIN <> deviceParameters.colorCorrectionProc _ InterpressCC.StandardCC; deviceParameters.colorCorrectionData _ InterpressCC.InitCC ["Versatec.CCSpec", doColorCorrection] END ELSE BEGIN IF UserProfile.Boolean ["Nectarine.SprayHalftone", TRUE] THEN BEGIN <> deviceParameters.bricks [black] _ brickK; deviceParameters.bricks [cyan] _ brickC; deviceParameters.bricks [magenta] _ brickM; deviceParameters.bricks [yellow] _ brickY END <> ELSE deviceParameters.ppd _ 3.0 END END; $NBw400 => BEGIN <> deviceParameters _ InterpressToPD.ParamsFromPrinterType [$bw400]; scale _ (mmXin * deviceParameters.pageFSize) / field.w; serverName _ UserProfile.Token ["Nectarine.Bw400", "MtFuji"] END; $NColor400 => BEGIN <> deviceParameters _ InterpressToPD.ParamsFromPrinterType [$color400]; IF (doGreyBalance OR doColorCorrection) THEN BEGIN <> deviceParameters.colorCorrectionProc _ InterpressCC.StandardCC; <> deviceParameters.colorCorrectionData _ InterpressCC.InitCC ["Color400.CCSpec", doColorCorrection] END ELSE BEGIN IF UserProfile.Boolean ["Nectarine.SprayHalftone", TRUE] THEN BEGIN <> deviceParameters.bricks [black] _ brickK; deviceParameters.bricks [cyan] _ brickC; deviceParameters.bricks [magenta] _ brickM; deviceParameters.bricks [yellow] _ brickY END <> ELSE deviceParameters.ppd _ 3.0 END; scale _ (mmXin * deviceParameters.pageFSize) / field.w; serverName _ UserProfile.Token ["Nectarine.Color400", "MtFuji"] END; $NPlateMaker => BEGIN <> deviceParameters _ InterpressToPD.ParamsFromPrinterType [$platemaker]; deviceParameters.tonerUniverse _ LIST [black, cyan, magenta, yellow]; IF UserProfile.Boolean ["Nectarine.SprayHalftone", TRUE] AND (NOT DoLineArt[]) THEN TerminalIO.PutRope ["Your user profile requests so-called spray halftoning. However, this is not usable on a process printer.\nWill use conventional halftoning instead.\n"] <> <> <> END; $NRaven300 => ERROR; -- an Interpress printer, not PD $NRaven384 => deviceParameters _ InterpressToPD.ParamsFromPrinterType [$raven384]; ENDCASE => NULL; -- should never happen <> IF doNotScale OR fieldHasBeenSet THEN scale _ 1.0; IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort; startTime _ BasicTime.Now []; SELECT printerKey FROM $NRaven384 => BEGIN InterpressToPD.DoCommand [inputName: masterName, outputName: peachName, params: deviceParameters, logProc: LogInterpress, progressProc: ProgressLog]; TerminalIO.PutRope [Rope.Cat ["PD file for Raven384 created. Stuff the following line in a Command Tool viewer to send it to a 384 dpi Press-printer like Stinger:\nPrint -h Stinger ", peachName, "\n"]] END; $NPlateMaker => BEGIN <> <> <> user: ROPE ~ UserCredentials.Get[].name; prefix: ROPE _ "[]<>Temp>Nectarine>Erie"; public: BOOL; gNameK, gNameC, gNameM, gNameY, suffix, separation, erieSeparations: ROPE; IF mergeRegister THEN masterName _ MergeRegisterMarks [masterName]; IF DoLineArt[] AND (NOT UseProcessColors[]) THEN TerminalIO.PutRope ["\nStarting production of separations for mechanic colors.\n"] ELSE TerminalIO.PutRope ["\nStarting production of separations for process colors.\n"]; erieSeparations _ UserProfile.Token ["Nectarine.PlatemakerSeparations"]; public _ NOT erieSeparations.IsEmpty; deviceParameters.toners _ LIST [black]; suffix _ IF UseProcessColors[] THEN "-Black.PD" ELSE "-GT4Green.PD"; separation _ prefix.Concat [suffix]; InterpressToPD.DoCommand [inputName: masterName, outputName: separation, params: deviceParameters, tx: 8.0 / mmXin, ty: 12.0 / mmXin, logProc: LogInterpress, progressProc: ProgressLog]; IF abortFlag^ THEN GOTO platemakerAbort; IF public THEN BEGIN gNameK _ FS.Copy [from: separation, to: erieSeparations.Cat [user, ">", peachName, suffix]]; IF NOT gNameK.IsEmpty THEN ForcedDelete [separation] END; IF abortFlag^ THEN GOTO platemakerAbort; deviceParameters.toners _ LIST [cyan]; suffix _ IF UseProcessColors[] THEN "-Cyan.PD" ELSE "-C28Blue.PD"; separation _ prefix.Concat [suffix]; InterpressToPD.DoCommand [inputName: masterName, outputName: separation, params: deviceParameters, tx: 8.0 / mmXin, ty: 12.0 / mmXin, logProc: LogInterpress, progressProc: ProgressLog]; IF abortFlag^ THEN GOTO platemakerAbort; IF public THEN BEGIN gNameC _ FS.Copy [from: separation, to: erieSeparations.Cat [user, ">", peachName, suffix]]; IF NOT gNameC.IsEmpty THEN ForcedDelete [separation] END; IF abortFlag^ THEN GOTO platemakerAbort; deviceParameters.toners _ LIST [magenta]; suffix _ IF UseProcessColors[] THEN "-Magenta.PD" ELSE "-RT6Red.PD"; separation _ prefix.Concat [suffix]; InterpressToPD.DoCommand [inputName: masterName, outputName: separation, params: deviceParameters, tx: 8.0 / mmXin, ty: 12.0 / mmXin, logProc: LogInterpress, progressProc: ProgressLog]; IF abortFlag^ THEN GOTO platemakerAbort; IF public THEN BEGIN gNameM _ FS.Copy [from: separation, to: erieSeparations.Cat [user, ">", peachName, suffix]]; IF NOT gNameM.IsEmpty THEN ForcedDelete [separation] END; IF abortFlag^ THEN GOTO platemakerAbort; deviceParameters.toners _ LIST [yellow]; suffix _ IF UseProcessColors[] THEN "-Yellow.PD" ELSE "-M35Slash2Magenta.PD"; separation _ prefix.Concat [suffix]; InterpressToPD.DoCommand [inputName: masterName, outputName: separation, params: deviceParameters, tx: 8.0 / mmXin, ty: 12.0 / mmXin, logProc: LogInterpress, progressProc: ProgressLog]; IF abortFlag^ THEN GOTO platemakerAbort; IF public THEN BEGIN gNameY _ FS.Copy [from: separation, to: erieSeparations.Cat [user, ">", peachName, suffix]]; IF NOT gNameY.IsEmpty THEN ForcedDelete [separation] END; IF abortFlag^ THEN GOTO platemakerAbort; IF debug THEN pause; IF public THEN BEGIN IF (gNameK.IsEmpty OR gNameC.IsEmpty OR gNameM.IsEmpty OR gNameY.IsEmpty) THEN ImportantMessage ["Was not able to store all the required separations."]; IF DoLineArt [] AND (NOT UseProcessColors []) THEN BEGIN gNameK _ gNameK.Cat ["\nC28 blue: ", gNameC, "\nRT6 red: ", gNameM]; gNameK _ gNameK.Cat ["\nM35/2 magenta: ", gNameY]; [] _ SimpleMailer.SendMessage [from: "Nectarine", to: LIST ["Platemaker.PA"], cc: LIST [user, "Wallgren.PARC"], subject: Rope.Concat ["Erie Print Request ", peachName], body: Rope.Cat ["Hi Bridget or Steve,\n\nPlease print for me on film:\n\nGT4 green: ", gNameK, "\n\n\tIMPORTANT: If I tell you to actually do Cromalin proofs, make positives with the Reverse button on. If I need separations to be stripped by Kedie/Orent, I will probably want negatives with the emulsion up.\n\nIf I need a Cromalin proof, please make it using the custom colors mentioned in the file names in the order GT4 green, C28 blue, M35/2 magenta, and RT6 red.\n\nThank you,\n", user]]; END ELSE BEGIN gNameK _ gNameK.Cat ["\nCyan: ", gNameC, "\nMagenta: ", gNameM]; gNameK _ gNameK.Cat ["\nYellow: ", gNameY]; [] _ SimpleMailer.SendMessage [from: "Nectarine", to: LIST ["Platemaker.PA"], cc: LIST [user, "Wallgren.PARC"], subject: Rope.Concat ["Erie Print Request ", peachName], body: Rope.Cat ["Hi Bridget or Steve,\n\nPlease print for me on film:\n\nBlack: ", gNameK, "\n\n\tIMPORTANT: If I tell you to actually do Cromalin proofs, make positives with the Reverse button on. If I need separations to be stripped by Kedie/Orent, I will probably want negatives with the emulsion up.\n\nIf I will tell you to prepare a Cromalin proof, then please use the Cromalin process inks SOP-Cyan, SOP-Magenta, SOP-Yellow, and, SOP-Black. Apply the colors in the order yellow, cyan, magenta, and black.\n\nThank you,\n", user]] END END ELSE TerminalIO.PutF ["\nThe separations are on your disk in %g-{mechanic/process color name}.PD. You have not set the user profile option Nectarine.PlatemakerSeparations, hence I cannot take care of them.\nDebrouillez vous.\n", IO.rope [prefix]] END; ENDCASE => BEGIN tx, ty: REAL; IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort; IF (printerKey = $NColorVersatec) AND (sizeHint # NIL) AND (sizeHint.w = 40*mmXin) THEN {tx _ ty _ 0} ELSE IF (sizeHint # NIL) THEN {tx _ - (sizeHint.x * scale) / mmXin; ty _ - (sizeHint.y * scale) / mmXin} ELSE {tx _ - (field.x * scale) / mmXin; ty _ - (field.y * scale) / mmXin}; InterpressToPD.DoCommand [inputName: masterName, outputName: peachName, params: deviceParameters, sx: scale, sy: scale, tx: tx, ty: ty, logProc: LogInterpress, progressProc: ProgressLog]; <> FS.SetKeep [peachName, 5]; TerminalIO.PutRope [Rope.Cat ["\nDuration of Interpress to PD conversion: ", TimeToRope [startTime, BasicTime.Now[]], "\n"]]; peachName _ FS.FileInfo [name: peachName, remoteCheck: FALSE].fullFName; -- with version number <> IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort; TerminalIO.PutF ["%g being submitted to %g.\n", IO.rope [peachName], IO.rope [serverName]]; PeachPrint.DoPeachPrintCommand [serverName, peachName, TerminalIO.TOS[], TRUE, copies] END; IF (printerKey = $NPeachExpand) THEN BEGIN pos: FS.ComponentPositions ~ FS.ExpandName[peachName].cp; server2Name: ROPE ~ UserProfile.Token ["Nectarine.ExpandedPeach", "Sleepy"]; simpleName: ROPE ~ peachName.Substr [pos.base.start, pos.base.length]; IF abortFlag^ THEN ERROR ABORTED; Process.CheckForAbort; peachName _ Rope.Cat ["[", serverName, "]PD>", simpleName, "-1.PD"]; TerminalIO.PutF ["%g being submitted to %g.\n", IO.rope [peachName], IO.rope [server2Name]]; PeachPrint.DoPeachPrintCommand [server2Name, peachName, TerminalIO.TOS[], TRUE, copies] END; <> EXITS peachFailure => BEGIN ImportantMessage [Rope.Cat ["Communications failure. File saved on ", peachName, " for manual retry."]]; SIGNAL communicationsFailure END; platemakerAbort => BEGIN user: ROPE ~ UserCredentials.Get[].name; [] _ SimpleMailer.SendMessage [from: "Nectarine", to: LIST ["Platemaker.PA"], cc: LIST [user], subject: peachName, body: Rope.Cat ["Hi again,\n\nNever mind, I have changed my mind.\n\nSorry for bothering you,\n", user]]; ERROR ABORTED END} END; -- PdPrintProcess <> fieldDoc: ROPE ~ "explicitly set the field size to perform image ganging. Specify the field in mm\n\t-x lower left corner x\n\t-y lower left corner y\n\t-w width\n\t-h height\nDefaults: x: medium.x + 10.0, y: medium.y + 10.0, w: medium.w - 20.0, h: medium.h - 20.0; where medium = [x: 0.0, y: 0.0, w: 215.9, h: 279.4]"; argError: ROPE; fieldHasBeenSet: BOOL _ FALSE; SetField: Commander.CommandProc ~ BEGIN <> <> x, y, w, h: Args.Arg; field _ [x: medium.x + 10.0, y: medium.y + 10.0, w: medium.w - 20.0, h: medium.h - 20.0]; fieldHasBeenSet _ FALSE; IF (Args.NArgs [cmd] # 0) THEN BEGIN [x, y, w, h] _ Args.ArgsGet [cmd, "-x%r-y%r-w%r-h%r" ! Args.Error => {argError _ reason; GOTO failure}]; fieldHasBeenSet _ TRUE; IF x.ok THEN field.x _ x.real; IF y.ok THEN field.y _ y.real; IF w.ok THEN field.w _ w.real; IF h.ok THEN field.h _ h.real END; msg _ IO.PutFR ["NectarineField -x %g -y %g -w %g -h %g", IO.real [field.x], IO.real [field.y], IO.real [field.w], IO.real [field.h]]; EXITS failure => RETURN [$Failure, argError.Cat ["\n", fieldDoc]] END; -- SetField InitBricks: PROC ~ BEGIN Matrix: TYPE ~ ARRAY [1 .. 4] OF ARRAY [1 .. 4] OF REAL; <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> FillSample16: PROC [s: REF Brick, a: Matrix] ~ BEGIN Set: PROC [i, j: INTEGER, val: REAL] ~ BEGIN ImagerSample.Put [map: s.sampleMap, index: [i, j], value: InlineRound [255*val]]; END; s^ _ [maxSample: 255, sampleMap: ImagerSample.NewSampleMap [box: [max:[4, 4]], bitsPerSample: 8], phase: 0]; FOR i: [1 .. 4] IN [1 .. 4] DO FOR j: [1 .. 4] IN [1 .. 4] DO a[i][j] _ a[i][j] / 17.0 ENDLOOP ENDLOOP; Set [0, 0, a[1][1]]; Set [0, 1, a[1][2]]; Set [0, 2, a[1][3]]; Set [0, 3, a[1][4]]; Set [1, 0, a[2][1]]; Set [1, 1, a[2][2]]; Set [1, 2, a[2][3]]; Set [1, 3, a[2][4]]; Set [2, 0, a[3][1]]; Set [2, 1, a[3][2]]; Set [2, 2, a[3][3]]; Set [2, 3, a[3][4]]; Set [3, 0, a[4][1]]; Set [3, 1, a[4][2]]; Set [3, 2, a[4][3]]; Set [3, 3, a[4][4]] END; -- FillSample16 <> <> <> <> <> <> <> <> FillSample16 [brickC, [[8.0, 6.0, 7.0, 5.0], [1.0, 3.0, 2.0, 4.0], [16.0, 14.0, 15.0, 13.0], [9.0, 11.0, 10.0, 12.0]]]; FillSample16 [brickM, [[8.0, 1.0, 9.0, 16.0], [6.0, 3.0, 11.0, 14.0], [7.0, 2.0, 10.0, 15.0], [5.0, 4.0, 12.0, 13.0]]]; FillSample16 [brickY, [[8.0, 9.0, 11.0, 4.0], [10.0, 7.0, 3.0, 13.0], [12.0, 2.0, 6.0, 15.0], [1.0, 14.0, 16.0, 5.0]]]; FillSample16 [brickK, [[1.0, 13.0, 15.0, 5.0], [11.0, 2.0, 6.0, 16.0], [9.0, 7.0, 3.0, 14.0], [8.0, 10.0, 12.0, 4.0]]] END; -- InitBricks InitBricks []; Commander.Register [key: "NectarineField", proc: SetField, doc: fieldDoc] END. <> <> <> <> <> <> <<>>