> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.snJpROjgJAR/rev.1722
 * 
 * authors: 
 *   Tom Hlina

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 




/* @pjs preload="/static/uploaded_resources/p.3612/color.png"; */

int gGridX  = 40;
int gGridY  = 40; 
int gSize   = 40;
 
int gColorPickerX = 400;
int gColorPickerY = 40;
 
int gFrameManagerX = 400;
int gFrameManagerY = 220;


boolean gPlayMode = false; 
 
int gMaxFrames = 10; 
color gTileColor = color( 255 );
 
PFont gFont = loadFont( "Arial" );
 
Grid myGrid;
GridData[] myAnimation;
ColorPicker myColorPicker;
FrameManager myFrameManager;
 
void setup() 
{ 
  background( 127 );
  size( 700, 600 ); 
  smooth();   
  frameRate( 25 );
  strokeWeight( 2 );
  stroke( 64 );
  rectMode( CORNER );
  textFont( gFont, 24 ); 
 
  myAnimation = new Grid[ gMaxFrames] ;
  for( int i=0; i < gMaxFrames; i++)
  {
    myAnimation[i] = new GridData( gGridX, gGridY, gSize  );
  }
  myGrid = new Grid( gGridX, gGridY, gSize );   
  myColorPicker = new ColorPicker( gColorPickerX, gColorPickerY );
  myFrameManager = new FrameManager( gFrameManagerX, gFrameManagerY ); 
  
 
  myGrid.draw( myAnimation[ myFrameManager.getCurrentFrame() ] );
  myColorPicker.draw();
  myFrameManager.draw();
 
 
} 
 
void draw()
{
  if( gPlayMode )
  { 
    myFrameManager.draw();    
    myGrid.draw( myAnimation[ myFrameManager.getCurrentFrame() ] );
    myFrameManager.nextAnimationFrame();    
  }
  else
  {
    if( myGrid.isMouseIn() || myColorPicker.isMouseIn() || myFrameManager.isMouseIn() )   
    {
        cursor( CROSS );
    }
    else
    {
        cursor( ARROW );    
    }
  }
}
 
 
void mouseClicked() 
{
    
  if( myGrid.isMouseIn() && !gPlayMode )
  {
    myGrid.setTile( myAnimation[ myFrameManager.getCurrentFrame() ], mouseX, mouseY, gTileColor );
  }
 
  if(  myColorPicker.isMouseIn() && !gPlayMode )
  {
    gTileColor = myColorPicker.pick( mouseX, mouseY );
  }
 
  if( myFrameManager.isMouseIn() && !gPlayMode )
  {
    myFrameManager.handleClick();
    myGrid.draw( myAnimation[ myFrameManager.getCurrentFrame() ] );
  }   
}
 
/////////////////////////
 
 
class ColorPicker
{
  private int mX;
  private int mY;
  private int mSizeX;
  private int mSizeY;
  private color mColor;
  private color mBackUp1Color;
  private color mBackUp2Color;
  private PImage mImage;
 
  ColorPicker( int pX, int pY )
  {
    this.mSizeX = 210;
    this.mSizeY = 150;
    this.mColor  = color( 255 );
    this.mBackUp1Color = color( 255 );
    this.mBackUp2Color = color( 255 );
    
    //this.mImage = loadImage("color.png");
    this.mImage = loadImage("/static/uploaded_resources/p.3612/color.png");
 
    this.mX = pX;
    this.mY = pY;
  }
 
  public void draw()
  {
    pushMatrix();
    translate( this.mX, this.mY );
    fill( 0 );
    rect( 0, 0, this.mSizeX, this.mSizeY );
    
    fill( this.mColor );
    rect( 160, 5, 40, 40 );
 
    fill( this.mBackUp1Color );   
    rect( 160, 55, 40, 40 );
 
    fill( this.mBackUp2Color );
    rect( 160, 105, 40, 40 );
 
    image( this.mImage, 0, 0 );
    popMatrix();
  }
 
  public color pick( int pX, int pY )
  {
    if( !( mouseX > ( this.mX + 160 ) && mouseX < ( this.mX + 200 )
      && mouseY > ( this.mY + 5 ) && mouseY < ( this.mY + 45 ) ) )
    {     
      this.mBackUp2Color = this.mBackUp1Color;
      this.mBackUp1Color = this.mColor; 
      this.mColor = get( pX, pY );
      this.draw();
    }      
    return( this.mColor );
  }
 
  public boolean isMouseIn()
  {
    if(
      ( mouseX > this.mX && mouseX < ( this.mX + 150 )
        && mouseY > this.mY && mouseY < ( this.mY + 150 ) )
    ||( mouseX > ( this.mX + 160 ) && mouseX < ( this.mX + 200 )
      && mouseY > ( this.mY + 5 ) && mouseY < ( this.mY + 45 ) )   
    ||( mouseX > ( this.mX + 160 ) && mouseX < ( this.mX + 200 )
      && mouseY > ( this.mY + 55 ) && mouseY < ( this.mY + 95 ) )   
    ||( mouseX > ( this.mX + 160 ) && mouseX < ( this.mX + 200 )
      && mouseY > ( this.mY + 105 ) && mouseY < ( this.mY + 145 ) )   
    )
    {
      return true;
    }
    else
    { 
      return false;
    }
  }
}
 
 
/////////////////////////////
 
 
class FrameManager
{
 
  private int mCurrentFrame;
  private int mMaxFrame;
 
  private int mX;
  private int mY;
  
  FrameManager( int pX, int pY )
  {
    this.mX = pX;
    this.mY = pY;
    this.mCurrentFrame = 0;
    this.mMaxFrames = 0;
  }
 
 
  public void handleClick(){
  
//    println("X: " + ( mouseX - this.mX ) + " Y: " + ( mouseY - this.mY ) );
    
    if( mouseX > ( this.mX + 133 ) && mouseX < ( this.mX + 153 )
     && mouseY > ( this.mY + 18 ) && mouseY < ( this.mY + 35 )
    )
    {
      this.handlePrior(); 
    }
    if( mouseX > ( this.mX + 169 ) && mouseX < ( this.mX + 188 )
     && mouseY > ( this.mY + 18 ) && mouseY < ( this.mY + 35 )
    )
    {
      this.handleNext(); 
    }
    if( mouseX > ( this.mX + 13 ) && mouseX < ( this.mX + 64 )
     && mouseY > ( this.mY + 42 ) && mouseY < ( this.mY + 58 )
    )
    {
      this.handleNew(); 
    }
    if( mouseX > ( this.mX + 78 ) && mouseX < ( this.mX + 151 )
     && mouseY > ( this.mY + 41 ) && mouseY < ( this.mY + 58 )
    )
    {
      this.handleDel(); 
    }
    if( mouseX > ( this.mX + 14 ) && mouseX < ( this.mX + 64 )
     && mouseY > ( this.mY + 64 ) && mouseY < ( this.mY + 82 )
    )
    {
      this.handleView(); 
    }
    if( mouseX > ( this.mX + 80 ) && mouseX < ( this.mX + 136 )
     && mouseY > ( this.mY + 64 ) && mouseY < ( this.mY + 82 )
    )
    {
      this.handleSave(); 
    }
    
    
  }
 
  public boolean isMouseIn()
  {
    if( mouseX > ( this.mX + 133 ) && mouseX < ( this.mX + 153 )
     && mouseY > ( this.mY + 18 ) && mouseY < ( this.mY + 35 )
    )
    {
      return true;
    }
    if( mouseX > ( this.mX + 169 ) && mouseX < ( this.mX + 188 )
     && mouseY > ( this.mY + 18 ) && mouseY < ( this.mY + 35 )
    )
    {
      return true;
    }
    if( mouseX > ( this.mX + 13 ) && mouseX < ( this.mX + 64 )
     && mouseY > ( this.mY + 42 ) && mouseY < ( this.mY + 58 )
    )
    {
      return true;
    }
    if( mouseX > ( this.mX + 78 ) && mouseX < ( this.mX + 151 )
     && mouseY > ( this.mY + 42 ) && mouseY < ( this.mY + 58 )
    )
    {
      return true;
    }
    if( mouseX > ( this.mX + 14 ) && mouseX < ( this.mX + 64 )
     && mouseY > ( this.mY + 64 ) && mouseY < ( this.mY + 82 )
    )
    {
      return true;
    }
    if( mouseX > ( this.mX + 80 ) && mouseX < ( this.mX + 136 )
     && mouseY > ( this.mY + 64 ) && mouseY < ( this.mY + 82 )
    )
    {
      return true;
    }
 
    return false;
  }   
  
  public int getCurrentFrame()
  {
    return this.mCurrentFrame;  
  }
  
  public void draw()
  {
    pushMatrix();
    translate( this.mX, this.mY );
    fill( 0 );
    rect( 0, 0, 210, 140 );
    fill( 127 );
    text( "Tile: " + ( this.mCurrentFrame + 1 ) + "/" + ( this.mMaxFrames + 1 ), 10, 34 );
    text( "[<] [>]", 130, 34);
    text( "[new] [delete]", 10, 58 );
    text( "[view] [save]", 10, 82 );
    
    popMatrix();    
  }
  
  private void handleNext()
  {
    if( ( this.mCurrentFrame + 1 ) <= this.mMaxFrames ) 
      this.mCurrentFrame++;     
    this.draw();    
  }
 
  private void handlePrior()
  {
    if( ( this.mCurrentFrame - 1 ) >= 0 ) 
      this.mCurrentFrame--;     
    this.draw();    
  }
 
  private void handleNew()
  {
   if( ( this.mMaxFrames + 1 ) < gMaxFrames )  
   {
     if( this.mCurrentFrame != this.mMaxFrames )
     {
       for ( int i=( this.mMaxFrames + 1 ); i > this.mCurrentFrame; i-- )
       {
         myAnimation[ i ] = myAnimation [ (i-1) ];
       }
       myGrid.clear(  myAnimation[ (this.mCurrentFrame + 1) ] );   
     }
     this.mCurrentFrame++;
     this.mMaxFrames++;     
     this.draw();
    }  
  }

  private void handleDel()
  {
    if( this.mMaxFrames > 0 )
    {
      if( this.mCurrentFrame == this.mMaxFrames )
      {
        myGrid.clear( myAnimation[ this.mMaxFrames ] );
        this.mCurrentFrame--;
        this.mMaxFrames--;      
      }
      else
      {
        println("mCurrentFrame:" + this.mCurrentFrame);
        for( int i=( this.mCurrentFrame + 1 ); i <= this.mMaxFrames; i++ )
        {
          myAnimation[ ( i-1 ) ] = myAnimation[ i ];
          println("C: " + i + " M: " + this.mMaxFrames);
        }
        myGrid.clear( myAnimation[ this.mMaxFrames ] );       
        this.mMaxFrames--;
      }        
      this.draw();
     }
  }
 
  private void handleView()
  {
    gPlayMode = true;
    frameRate( 1 );
    noCursor();
    this.mCurrentFrame = 0;
    this.draw();  
  } 
    
  private void handleSave()
  {
   println("Save"); 
  }
 
 
  public void nextAnimationFrame()
  {
    if( ( this.mCurrentFrame ) < this.mMaxFrames )
    {
      this.mCurrentFrame++;  
    }
    else
    {
      gPlayMode = false;
      frameRate( 25 );
    }
  }  
}
 
///////////////////////////////////////
 
class Tile
{
 
  private int mSize;
 
  private int   mX;
  private int   mY;
  private color mColor;
 
  Tile( int pX, int pY, int pSize )
  {
    this.mColor = color( 0 );
 
    this.mX = pX;
    this.mY = pY;
    this.mSize = pSize;
  }
 
  public void setColor( color pColor )
  {
    this.mColor = pColor;
  }
  
  public color getColor()
  {
    return this.mColor;
  }

 
  public void draw()
  {
    pushMatrix();
    fill( this.mColor );
    translate( this.mX, this.mY );
    rect( 0, 0, this.mSize, this.mSize );
    popMatrix();
  }
 
}
 
 
class Grid
{

  private int mX;
  private int mY;
  private int mSize;

  Grid( int pX, int pY, int pSize )
  {
    this.mX = pX;
    this.mY = pY;
    this.mSize = pSize;
  }
 
  public void draw( GridData pGridData )
  {
    for ( int i=0; i<8; i++ )
      for ( int j=0; j<8; j++ )
      {
        pushMatrix();
        pGridData.getTile( i, j ).draw();
        popMatrix();
      }
  }
  
  public void setTile( GridData pGridData, int pX, int pY, color pColor )
  {
   int vX = constrain( floor( ( pX - this.mX) / this.mSize ), 0, 7 );
   int vY = constrain( floor( ( pY - this.mY) / this.mSize ), 0, 7 );
   
   pGridData.setColor( vX, vY, pColor );
   pGridData.getTile( vX, vY ).draw();    
  }
  
  public void clear( GridData pGridData )
  {
    for ( int i=0; i<8; i++ )
      for ( int j=0; j<8; j++ )
        pGridData.setColor( i, j, color( 0 ) );
  }
  
  public boolean isMouseIn()
  {
    if( mouseX > this.mX && mouseX < ( this.mX + 8 * this.mSize )
      && mouseY > this.mY && mouseY < ( this.mY + 8 * this.mSize )    
    )
    {
      return true;
    }
    else
    { 
      return false;
    }
  }
}


////////////////////////////////////////
class GridData
{
  private Tile[][] mGrid; 
  
  
  GridData( int pX, int pY, int pSize )
  {   
    mGrid = new Tile[8][8];
    for ( int i=0; i<8; i++ )
      for ( int j=0; j<8; j++ )
        mGrid[i][j] = new Tile( pX + i*pSize, pY + j*pSize, pSize );        
  }

  public void setColor( int pX, int pY, color pColor )
  {
    this.mGrid[ pX ][ pY ].setColor( pColor );
  }  

  public color getColor( int pX, int pY )
  {
    return this.mGrid[ pX ][ pY ].getColor();
  }
  
  public Tile getTile( int pX, int pY)
  {
    return this.mGrid[ pX ][ pY ]; 
  }
}