here is a array of class of rectangles
( with too many features you not need to use )
where a mouse click switch ONE LED ON / OFF ( mouse left/right button )
and a key [c] clears all.
you might need to make a add function like
key [s] send:
read array of class variable selected to your byte array for send to arduino…
// https://discourse.processing.org/t/scalable-grid-with-rectangles/7256
// https://discourse.processing.org/t/better-grid-performance/7314
// https://discourse.processing.org/t/gryd-system-graphic-design/10457
// https://discourse.processing.org/t/change-rectangles-seperately-in-for-loop/10908/2
// https://discourse.processing.org/t/creating-a-grid-of-toggle-buttons/12162
// use backup memory array for resize/reinit grid but remember selected rects
int x = 30, y = x, w = 50, h = w, off= 5, grid = 8, many = grid*grid;
float rang = 0, strokew=1.0;
boolean auto = false;//false;//true;
boolean shownum = false; // key [n]
boolean showFPS = true;
boolean togfill = false;
// color setup:
color bg = color(200, 200, 0);
color stk = color(0, 0, 200);
color fillsel = color(0, 200, 0);
color fillnsel= color(200, 0, 200);
Myrect[] myrects = new Myrect[many];
Mybackup[] myselects = new Mybackup[many]; // temporary memory
void setup() {
size(800, 520);
noSmooth();
set_grid(true); // init
String help = "";
help += "use: mouse LEFT to select, mouse RIGHT to deselect\n";
help += "key UP DOWN RIGHT LEFT for position\n";
help += "key [+] [-] for grid size\n";
help += "key [n] toggle shownumber\n";
help += "key [f] toggle fill\n";
help += "key [c] clear selected\n";
help += "____MouseWheel Plus Plus ____\n";
help += "use key [x] [y] [w] [h] [o] for position and size\n";
help += "use key [r] rotate / key [s] stroke width\n";
help += "and turn mouse wheel";
println(help);
}
void draw() {
background(bg);
fill(0);
if (showFPS ) text(nf(frameRate, 1, 1), 10, 10);
for (int i = 0; i < many; i++) myrects[i].drawit(); // draw each rect ( and check on mouse over + click )
}
class Mybackup {
boolean selected=false;
}
class Myrect {
int x, y, id;//, w, h, off, rang; from global
boolean selected=false;
Myrect (int x, int y, int id) {
this.x = x;
this.y = y;
this.id = id;
}
void drawit() {
if ( strokew > 0.2 ) { strokeWeight(strokew); stroke(stk); }
else noStroke();
if ( selected ) fill(fillsel);
else fill(fillnsel);
if ( togfill ) noFill();
push();
translate(x,y);
rotate(rang);
rect(-(w-off)/2,-(h-off)/2, (w-off), (h-off));
fill(0); // black text
if (shownum) text(id, -w/8, +h/8);
pop();
sel();
}
boolean over() {
return( x-(w-off)/2 < mouseX && mouseX < x+(w-off)/2 && y-(h-off)/2 < mouseY && mouseY < y+(h-off)/2 );
}
void sel() {
if ( over() ) {
if ( selected && mousePressed && mouseButton == RIGHT) selected=false;
if ( !selected && mousePressed && mouseButton == LEFT) selected=true;
}
}
}
void set_wh() {
// use x,y,grid as master and auto adjust rectangles (w,h) to window:
println(" width= "+width+", height= "+height+", grid= "+grid);
w = ( width - 2 * x ) / grid-off;
println(" w= "+w+", x= "+x+", ( grid * w + 2 * x )= "+(grid*w+2*x));
h = ( height - 2 * y ) / grid-off;
println(" h= "+h+", y= "+y+", ( grid * h + 2 * y )= "+(grid*h+2*y));
}
void set_grid(boolean init) {
if ( auto ) set_wh();
if ( init ) for (int i = 0; i < many; i++) myselects[i]=new Mybackup(); // init backup memory
else for (int i = 0; i < many; i++) myselects[i].selected = myrects[i].selected; // backup
for (int i = 0; i < many; i++) myrects[i]=new Myrect(x+(i%grid)*w, y+(floor(i/grid))*h, i); // resize
if ( !init ) for (int i = 0; i < many; i++) myrects[i].selected = myselects[i].selected; // restore
}
void clear_selected() {
for (int i = 0; i < many; i++) myrects[i].selected = false;
println("clear selected after key [c]");
}
void keyPressed() {
if ( keyCode == UP ) y--;
else if ( keyCode == DOWN ) y++;
else if ( keyCode == LEFT ) x--;
else if ( keyCode == RIGHT ) x++;
else if ( key == '+' ) { w++; h++; }
else if ( key == '-' ) { w--; h--; }
//h=w; // quadrat only
auto = false; // confirm
set_grid(false); // resize
if ( key == 'n' ) shownum = !shownum;
if ( key == 'f' ) togfill = !togfill;
if ( key == 'c' ) clear_selected();
}
void mouseWheel(MouseEvent event) {
float e = event.getCount(); //println(e);
if ( keyPressed && key == 'x' ) {
x += e ;
println(" key x: x "+x);
}
if ( keyPressed && key == 'y' ) {
y += e;
println(" key y: y "+y);
}
if ( keyPressed && key == 'w' ) {
w += e;
w=constrain(w,0,width);
println(" key w: w "+w);
}
if ( keyPressed && key == 'h' ) {
h += e;
h=constrain(h,0,height);
println(" key h: h "+h);
}
if ( keyPressed && key == 'o' ) {
off += e;
off=constrain(off,0,w);
println(" key o: off "+off);
}
if ( keyPressed && key == 'r' ) {
rang += e*0.03;
println(" key r: rang "+int(degrees(rang)));
}
if ( keyPressed && key == 's' ) {
strokew += e*0.1;
strokew = constrain(strokew,0,w/2);
println(" key s: strokew "+nf(strokew,1,1));
}
}
with p5.js i have this old sketch
https://editor.p5js.org/kll/sketches/QUnp7YbGv