// ––––––––––––––––––––––––––––––––––––––––––––––––––––––––
// Program to produce the generative illustration 
// for the cover of UNIKO annual report.
// Andreas Pirchner, 2022
// ––––––––––––––––––––––––––––––––––––––––––––––––––––––––

import processing.pdf.*;

// Initialize the increment values for the 3 types of shapes (cubes, lines, and points)
float incCubes = 0.09;
float incLines = 0.05;
float incPoints = 0.015;

// Initialize time and record variables
float time = 0.0;
boolean record;

void setup(){
  // Set the window size and enable smoothing
  size(800,800);
  smooth(8);
  
  // Set the record variable to false
  record = false;
}

void draw(){
  // Check if the record flag is set to true
  if (record) {
    // If it is, start recording the frames of the animation
    beginRecord(PDF, "frame-####.pdf");
  }
  
  // Set the background color to white
  background(255);
  
  // Initialize a counter variable
  int counter = 0;
  
  // Initialize the offset values for the 3 types of shapes
  float xoffCubes = 0.0;
  float xoffLines = 0.0;
  float xoffPoints = 0.0;

  // Loop through the width of the window and create lines
  for(int i = 20; i < width; i+=20){
    // Increment the x offset for lines
    xoffLines += incLines;
    
    // Initialize the y offset for lines
    float yoffLines = 0.0;
    
    // Loop through the height of the window and create lines
    for(int j = 0; j < height; j+=40){
      // Increment the y offset for lines
      yoffLines += incLines;
      
      // Generate noise based on the x and y offset values and the current time
      float noiseLines = noise(xoffLines, yoffLines, time);
      
      // Set the x and y positions for the lines
      int x = i;
      int y = j;
      
      // Push the current matrix onto a stack to allow for translation
      pushMatrix();
      translate(x,y);
      
      // If the noise value is greater than 0.4, create a line
      if (noiseLines>0.4){
         makeLine();
      }
      // Pop the matrix from the stack
      popMatrix();
    }
  }
  
  // Loop through the width of the window and create cubes and points
  for(int i = 20; i < width; i+=10){
    // This loop will repeat for every 10th value of i, starting from 20 until it reaches the value of width
    
    // Increment the x offset values for cubes and points
    xoffCubes += incCubes;
    xoffPoints += incPoints;
    
    // Initialize the y offset values for cubes and points to 0
    float yoffCubes = 0.0; 
    float yoffPoints = 0.0;
      
    // Calculate the noise values for cubes and points using the current x and y offset values and the time value
    float noiseCube = noise(xoffCubes, yoffCubes, time);
    //float noiseLines = noise(xoffLines, yoffLines);
    float noisePoints = noise(xoffPoints, yoffPoints, time);
      
    // Initialize x and y with the current value of i
    int x = i;
    int y = j;

    // If counter is an even number, increase x by 10
    if (counter%2 == 0){
        x+=10; 
    }
    
    // Save the current transformation matrix
    pushMatrix();
    
    // Translate the coordinate system to the current x and y values
    translate(x,y);
       
    // If the noise value for the cubes is greater than 0.5, call the makeCube() function
    if (noiseCube>0.5){
         makeCube();
    }
    
    // If the noise value for the points is greater than 0.4, fill a circle with a red color and no stroke
    if (noisePoints>0.4){
         fill(255,0,0,100);
         noStroke();
         circle(0,0,3);
    }
    
    // /*if (noiseLines>0.4){
    //   makeLine();
    // }*/
  
    // Restore the previous transformation matrix
    popMatrix();
    
    // Increment counter by 1
    counter++;
    }
  }

  
  time = time +0.01;

  if (record) {
    endRecord();
    record = false;
  }
}

void makeCube(){
    // Set the stroke color to red (255,0,0) with 20% opacity
    stroke(255,0,0,20);
    // Set the stroke weight to 1
    strokeWeight(1);
    // Disable the fill color
    noFill();
    // Draw four quadrilaterals to create a cube
    quad(0, 0, 10, 5, 20, 0, 10, -5);
    quad(0, 0, 0, 15, 10, 20, 10, 5);
    quad(10,5, 10, 20, 20, 15, 20,0);
}

// Define the makeLine function
void makeLine(){
    // Set the stroke color to red (255,0,0)
    stroke(255,0,0);
    // Set the stroke weight to 0.5
    strokeWeight(0.5);
    // Disable the fill color
    noFill();
    // Draw a line from (0,-15) to (0,15)
    line(0,-15,0,15);
}

// The keyPressed function
void keyPressed() {
    // If record is false
    if (!record){
        // Set record to true
        record = true;
    }
}