// CSC220F20PixelBrush 10/22/2020 PImage lastScreen = null ; int hue = 0 ; // red on color wheel float scaling = 1.0, rotation = 0.0, sweight = 20 ; boolean xflip = false, yflip = false, isclear = false ; int brushArraySize = 10 ; boolean brushdown = true ; int nextbrush = 0 ; // next brush to add paintbrush [] brushes = new paintbrush [ brushArraySize ]; String currentShape = "point" ; void setup() { fullScreen(P2D); frameRate(30); background(0); colorMode(HSB, 360, 100, 100, 100); stroke(hue, 100, 100, 100); // full saturation, brightness, alpha strokeWeight(sweight); imageMode(CENTER); } void draw() { if (isclear) { background(0); lastScreen = null ; isclear = false ; } push(); translate(width/2, height/2); if (lastScreen != null) { push(); if (scaling != 1.0) { scale(scaling); } if (rotation != 0.0) { rotate(radians(rotation)); } else { rotate(TWO_PI); // kludge, rotate 0 becomes asymmetric on scaling up??? } image(lastScreen, 0, 0, width, height); pop(); } if (brushdown) { for (paintbrush pb : brushes) { if (pb != null) { pb.display(); } } } if (mousePressed) { paintbrush newbrush = new paintbrush(mouseX-width/2, mouseY-height/2, hue, currentShape, sweight, xflip, yflip); brushes[nextbrush] = newbrush ; nextbrush = (nextbrush + 1) % brushes.length ; // wrap back to 0 at top, circular buffer newbrush.display(); //<>// } pop(); lastScreen = copyScreen(); } PImage copyScreen() { PImage result = createImage(width,height,ARGB); // https://processing.org/reference/createImage_.html loadPixels(); // from current display result.loadPixels(); java.lang.System.arraycopy(pixels, 0, result.pixels, 0, pixels.length); updatePixels(); result.updatePixels(); return result ; } String command = "" ; // empty command string, build it up. void keyPressed() { if (key == 'x') { xflip = ! xflip ; command = ""; } else if (key == 'y') { yflip = ! yflip ; command = "" ; // clear the command buffer } else if (key == 'c') { isclear = true ; command = "" ; } else if (key == 'R') { // reset -- get to starting condition isclear = true ; command = "" ; scaling = 1.0; rotation = 0.0; sweight = 20 ; xflip = false; yflip = false; nextbrush = 0 ; // next brush to add brushes = new paintbrush [ brushArraySize ]; } else if (key == 'r' || key == 's' || key == 'h' || key == 'w') { command = "" + key ; // start new command message } else if (((key >= '0' && key <= '9') || key == '-' || key == '.') && command.length() > 0) { // Tack on another digit to N command = command + key ; } else if (key == '\n' && command.length() > 1) { try { float number = java.lang.Float.parseFloat(command.substring(1)); char c = command.charAt(0); command = "" ; // reset if (c == 'r') { rotation = constrain(number, -360, 360); } else if (c == 's') { scaling = number ; } else if (c == 'h') { hue = int(constrain(abs(number), 0, 359)); } else if (c == 'w') { sweight = int(constrain(abs(number), 1, 100)); } else { command = "" ; // reset it } } catch (NumberFormatException nx) { println("ERROR, NumberFormatException: " + nx.getMessage()); command = "" ; // reset } } } // START NEW ON Oct 29, 2020 // paintbrush records xloc, yloc, hue, shape, strokeWeight class paintbrush { int xloc, yloc, hue ; String shapeName ; float strkWeight ; // stroke weight boolean xflip, yflip ; paintbrush(int x, int y, int huey, String shapeID, float sweight, boolean xflip, boolean yflip) { // Parameters in effect when I clicked the mouse. xloc = x ; yloc = y ; hue = huey ; shapeName = shapeID ; strkWeight = sweight ; this.xflip = xflip ; this.yflip = yflip ; } void display() { push(); // Do the usual push() at start, pop at end stroke(hue, 100, 100); strokeWeight(strkWeight); helpdisplay(false, false); //<>// if (xflip) { helpdisplay(true, false); } if (yflip) { helpdisplay(false, true); } if (xflip && yflip) { helpdisplay(true, true); } pop(); } void helpdisplay(boolean xf, boolean yf) { push(); // The first translate has no global (display-relative) xflip or yflip float xscale = 1.0, yscale = 1.0 ; if (xf) { yscale = -1.0 ; } if (yf) { xscale = -1.0 ; } scale(xscale, yscale); translate(xloc, yloc); if (shapeName.equals("point")) { // (shapeName == "point") REQUIRES THEM TO BE THE SAME OBJECT, WHICH THEY MIGHT NOT BE. // (shapeName.equals("point")) COMPARES THEIR CONTENTS, NOT THEIR OBJECT ADDRESS IN MEMORY. point(0, 0); } pop(); } } // END NEW ON Oct 29, 2020