Drag and Drop Boolean Array

Hello there,

I need help with processing.
I want to make a drag&drop example in a array of elements.
Unfortunaly, it still does not work after struggling in processing.

int num = 3;

Drag[] element = new Drag[int(num)];

float[] cx = new float[num];
float[] cy = new float[num];

int boxSize = 75;
boolean overBox;
boolean locked = false;
float xOffset = 0.0; 
float yOffset = 0.0; 

void setup() 
{
  size(640, 360);
  rectMode(CENTER);
  for (int i = 0; i < num; i++) {
    cx[i] = random(width);
    cy[i] = random(height);
  }
}


void draw() 
{ 
  background(0);
  for (int i = 0; i < num; i++) {
    element[i] = new Drag(cx[i], cy[i]); 
    element[i].display();
  }
}


void mousePressed() {
  for (int i = 0; i < num; i++) {
    element[i].mousePressed();
  }
}

void mouseDragged() {
  for (int i = 0; i < num; i++) {
    element[i].mouseDragged();
  }
}

class Drag { 
  float x, y;

  Drag(float _x, float _y) { 
    x = _x;
    y = _y;    
  }

  void display() {
    // Test if the cursor is over the box 
    if (mouseX > x-boxSize && mouseX < x+boxSize && 
      mouseY > y-boxSize && mouseY < y+boxSize) {
      overBox = true;  
      if (!locked) { 
        stroke(255); 
        fill(153);
      }
    } else {
      stroke(153);
      fill(153);
      overBox = false;
    }
    rect(x, y, boxSize, boxSize);
  }
  void mousePressed() {
    for (int i = 0; i < num; i++) {
      if (overBox) { 
        locked = true; 
        fill(255, 255, 255);
      } else {
        locked = false;
      }
    }
  }

  void mouseDragged() {
    for (int i = 0; i < num; i++) {
      if (locked) {
        cx[i] = mouseX; 
        cy[i] = mouseY;
      }
    }
  }

  void mouseReleased() {
    locked = false;
  }
}

There is a tutorial on the website in the tutorials section- named objects

Please read it

Belongs into setup only!!

belongs into draw()


Also in the class please no for-loops in your case. A class represents only ONE item

And a big welcome to the forum!

Great to have you here!

Thank you for your feedback.
The problem is that i want to define cx[i] as mouseX coördinates which i can not do in the setup. Is there a other solution to define cx[i] as mouseX which will be updates when i move my mouse.

A check when mouse is in the correct position, then check if mouse is pressed.
if so set a flag to say mousedown && in position.
Finally if !mousePressed reset flag.

I dont normally use void mousePressed() for drag drop events, just having a mouseLogic () function in the class you wish to test is usually enough.

example from my program

if(dposg()&&mousePressed&&!navPos()){
      // fill(255,50);
      // rect(0,0,width,height);
      ddown = true;
    }

if(ddown) doSomething();

if(!mousePressed) ddown = false;

int num = 3;

Drag[] element = new Drag[num];

// the drag process 
boolean drag=false; // if 
int my_i=0;    // which 

// -------------------------------------------------------------

void setup() {
  size(640, 360);
  rectMode(CENTER);

  int boxSize = 75;

  for (int i = 0; i < num; i++) {
    element[i] = new Drag(random(boxSize, width-boxSize), random(boxSize, height-boxSize));
  }
}

void draw() { 
  background(0);

  for (int i = 0; i < num; i++) {
    element[i].display();
  }

  if (drag) {
    element[my_i].mouseDragged();
  }
}

// -------------------------------------------------------------

void mousePressed() {
  // search 
  for (int i = 0; i < num; i++) {
    // init drag 
    if ( element[i].mousePressed() ) {
      drag=true; 
      my_i = i; 
      return;
    }
  }
}

void mouseDragged() {
  //
}

void mouseReleased() {
  element[my_i].mouseReleased();
  drag=false;
}

// =========================================================================================

class Drag { 
  float x, y;

  int boxSize = 75;
  boolean overBox = false;
  boolean locked = false;

  //float xOffset = 0.0; 
  //float yOffset = 0.0; 

  // constr 
  Drag(float _x, float _y) { 
    x = _x;
    y = _y;
  } // constr 

  void display() {
    // Test if the cursor is over the box 
    if (mouseX > x-boxSize && 
      mouseX < x+boxSize && 
      mouseY > y-boxSize && 
      mouseY < y+boxSize) {
      overBox = true;  
      if (locked) { 
        stroke(255); 
        fill(153);
      } else {
        stroke(255); 
        fill(153);
      }
    } else {
      stroke(153);
      fill(153);
      overBox = false;
    }
    rect(x, y, boxSize, boxSize);
  }

  boolean mousePressed() {
    if (overBox) { 
      locked = true; 
      fill(255, 255, 255);
      return true;
    } else {
      locked = false;
      return false;
    }
  }

  void mouseDragged() {
    if (locked) {
      x = mouseX; 
      y = mouseY;
    }
  }

  void mouseReleased() {
    locked = false;
  }
}//class
//

Hello,

i am not really sure about a few things in your code:

  1. why do you need to create new objects in every frame ? ( element[i] = new Drag(cx[i], cy[i]); in draw()) ? Since you do not update cx[i] and cy[i] unless using some mouse action occurs, re-creating them every frame does not do much most of the time.
    With more than 3 objects it will probably reduce your frame rate noticeably.

The “typical” way would be to declare the array (as you do) an then to instantiate your objects in setup once. Lateron the only information that will change will be the x and y coordinates.

  1. i do not think that you need to create separate float arrays for cx and cy.
    That could (should) go into your constructor, since you only use random values in the beginning.
class Drag { 
  float x, y;
//-------------------------
  Drag() { 
    x = random(width);
    y = random(height);    
  }
...
}
  1. I also notice that you have split up your checks for mouse inside, mouse pressed and mouse released between letting your object do the check and “sending” info for pressed and dragged events “into” your object. understandably you have to cycle through each object again…

inside your display() method you could use the mousePressed variable.

The first advantage will be that you do not have different places where you need to loop through all your objects. If your class has its own states for “inside”, “pressed” and “dragged”, you can easily create combinations and ask for different things, like:

if (isInside) -> allow drag to happen only when the mouse is inside
if (isInside && mousePressed) -> update x and y

a similar discussion happened not to long ago: How can I mask graphics to a resizable rectangle?
it gets a little more complicated there to check wether its a click (mouse released after a short time a release or a release and stuff.

the point I want to get at is, that, if you successfully manage to give your class the ability to check on its states itself, you only have to run the needed method once inside draw().

usually its a good idea to have two or more separate methods, like update() and render(). you will usually want to render stuff every frame while changes to the variables (like x,y) may not always depend on a frame to frame basis. another example would be to separate checking wether the mouse is inside from the rest, since the mouse being inside is a prerequisite to grabbing and releasing it)

so a “fake” code could look like this:

before setup: declare your array -> Drag [] element
inside setup: create the number of objects you want :

element = new Drag(3);  
for (int i; i <3; i ++) {
element[i] = new Drag();
}

your class looks a little like:

class Drag {
boolean isInside;
//-------------------------------
Drag() {
//set your random x,y
}
//-------------------------------
void update () {
  checkInside ();
  if (isInside) { // so you only look if the mouse is Pressed or dragged when isInside = true
    checkDrag() {
    // here you look if the mouse is being pressed or has been released and update stuff
    }
  }
}
//-------------------------------
void checkInside () {
// check if the mouse is Inside
  }
void checkDrag() {
  }
//-------------------------------
void render () {
//render stuff
  }
}

and draw does:

void draw () {
for (int i; i <3; i ++) {
  //update each object
  // render each object
  }
}

finally there is a little “mistake” in you current methods:
in your own mousePressed() and mouseDragged() methods in your class, you do not need to cycle through all objects, e.g. in the outside mouseDragged() method you say:

  for (int i = 0; i < num; i++) {
    element[i].mouseDragged();
  }

so (with num = 3) each object sets all 3 entries in float[] cx and float[] cy 3 times.
one solution would be to give each object an index variable, another to pass that number to the method inside:

void mouseDragged() {
  for (int i = 0; i < num; i++) {
    element[i].mouseDragged(i); // <- note the i
  }
}

void mouseDragged(int index) {
        cx[index] = mouseX; 
        cy[index] = mouseY;
  }

so you only set the correct values once.

but… as said before, I think you’ll be happier without needing to store variables that are important for you objects outside the class anyway…

2 Likes