We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Following this thread I'm trying to add a mouse event to a sketch using the toxiclibs library.
I'd like to be able to move a specific particle with the mouse and see the distortion on the springs grid.
Here's what the sketch looks like
Main .Pyde file
add_library('verletphysics')
add_library('toxiclibscore')
from toxi.physics2d import VerletPhysics2D
from toxi.physics2d.behaviors import GravityBehavior
from Particle import particle
from Locker import locker
def setup():
size(600, 600, OPENGL)
smooth(10)
global physics, collection, lockers, n_rowcol
physics = VerletPhysics2D()
physics.addBehavior(GravityBehavior(Vec2D(0, 1)))
collection, springs, lockers = [], [], []
n_rowcol, lngth, strength = 40, 10, .6
#Display particles and add to Physics
[[collection.append(particle(100 + (e * 10), 10 + (f * 10))) for f in range(n_rowcol)] for e in range(n_rowcol)]
[physics.addParticle(e) for e in collection]
#Lock specific particles
[collection[e].lock() for e in (0, n_rowcol - 1, n_rowcol ** 2 - n_rowcol, n_rowcol ** 2 - 1)]
#Display springs
for e in range(0, n_rowcol ** 2 , n_rowcol):
for f in range(n_rowcol - 1):
a = collection[e + f]
b = collection[e + f + 1]
s = VerletSpring2D(a, b, lngth, strength)
physics.addSpring(s)
for e in range(n_rowcol):
for f in range(0, n_rowcol ** 2 - n_rowcol, n_rowcol):
a = collection[e + f]
b = collection[e + f + n_rowcol]
s = VerletSpring2D(a, b, lngth, strength)
physics.addSpring(s)
#Display lockers (red circles to move with mouse)
for e in (0, n_rowcol - 1, n_rowcol ** 2 - n_rowcol, n_rowcol**2 - 1):
lockers.append(locker(collection[e].x(), collection[e].y()))
def draw():
background(0)
#Framerate
[fill(255), text(int(frameRate), 10, 20)]
#Run physics
physics.update()
#Draw lockers (red circles, not lockers really)
for e in lockers:
e.display()
e.mousePressed()
e.mouseDragged()
#Draw particles
[e.display() for e in collection]
#Draw springlines
springlines()
def springlines():
for e in range(0, n_rowcol ** 2, n_rowcol):
for f in range(n_rowcol - 1):
a = collection[e + f]
b = collection[e + f + 1]
stroke(255)
line(a.x(), a.y(), b.x(), b.y())
for e in range(n_rowcol):
for f in range(0, n_rowcol ** 2 - n_rowcol, n_rowcol):
a = collection[e + f]
b = collection[e + f + n_rowcol]
stroke(255)
line(a.x(), a.y(), b.x(), b.y())
Locker.py file
class locker(object):
def __init__(self, x, y):
self.x = x
self.y = y
self.over = False
self.locked = False
def display(self):
if dist(self.x, self.y, mouseX, mouseY) < 20:
self.over = True
fill(0, 0, 255)
else:
self.over = False
fill(255, 20, 20)
noStroke()
ellipse(self.x, self.y, 20, 20)
def mousePressed(self):
if mousePressed and self.over:
self.locked = True
else:
self.locked = False
def mouseDragged(self):
if self.locked:
self.x = mouseX
self.y = mouseY
Particle.py file
from toxi.physics2d import VerletParticle2D
class particle(VerletParticle2D):
over = False
def display(pos):
if dist(pos.x(), pos.y(), mouseX, mouseY) < 4:
pos.over = True
fill(255, 20, 20)
else:
pos.over = False
fill(255)
ellipse(pos.x(), pos.y(), 4, 4)
The problem lies in the last snippet above (Particle.py):
To drag a specific particle when mousePressed, I need to access the x and y coordinates of the ellipse (the particle) and say something like:
def mousePressed():
if pos.over:
pos.x() = mouseX
pos.y() = mouseY
But doing so gives me an error: "can't assign to function call" because x() and y() appear as functions.
How can I access the x and y coordinates and make that mouse event work ?
Answers
B/c they're indeed getter methods. If you wanna set their values, use the set() method. *-:)
__init__()
! #:-Shttps://Forum.Processing.org/two/discussion/26346/class-inheritance-with-toxiclibs-pyhton#Item_18
# def __init__(p, *args): super(Particle, p).__init__(*args)
.I see... so many things I didn't know. :-B
Following your instructions and this tutorial I came up with this:
from toxi.physics2d import VerletParticle2D
But unfortunately it's not working properly, the mouse barely drag anything + the mousePressed function doesn't work (the drag function "kind of" works although I didn't press anything). :-?
Also I have carefully looked at your code but please keep in mind that I don't have your level of coding + you integrated many functions that were not really necessary to understand the problem (confusing at first). It's sometime better to focus only on what really matters to convey your idea rather than implementing "subsidiary" functions even though I totally understand the satisfaction to write comprehensive and "pretty" code.
Callbacks like mousePressed(), mouseDragged(), etc., just like the main 1s setup() & draw(), all of them belong to class PApplet. :-B
Normally, Processing can't find them when they're defined outside the sketch's level scope! :-SS
Anyways, Processing provides the undocumented PApplet::registerMethod() so we can have callbacks defined in our own classes findable by Processing.
However, I've got my doubts that would work under Python Mode. :-/
Therefore, you're better off simply using the regular sketch-scoped callbacks rather than having them inside other classes. :(
ok, I feel like i'm struggling against some invisible force. But I'm not giving up yet.
So, following your suggestion I wrote the mouse event within the main .pyde file but once again (please forgive the beginner that I am) it's messy AND it doesn't work:
def draw()
The particle.py file looks now like this:
I tried many configurations (in the main sketch file, in a distinct function, in the draw(), in a child class...etc) but none worked. I have implemented mouse events before but it doesn't seem to work in this sketch specifically.
You're creating functions inside a loop there! :-&
Callbacks need to go to the sketch-global-level scope. [-(
http://py.Processing.org/reference/mouseDragged.html
http://py.Processing.org/tutorials/interactivity/
I know, I tried but it didn't work. That's why I started "experimenting" weird configurations. lol ~X(
This won't work either so...
This is the best I could figure out and it's still not working:
To get the dragging work I have to call the the mouseDragged() function. But it's still not working. Do you or anyone have any idea what's wrong ?
I guess you should set apart your project here and learn how to drag objects 1st.
Found this random online Java Mode sketch below: :bz
https://OpenProcessing.org/sketch/472169
BtW, you're mixing up global variables w/ class instance variables. :-\"
Working code below ! :
Particle class
What's inside draw()
Additional functions
(Note the springs can be dragged but not the particles)
@solub -- thank you for sharing your solution!
Was draggable springs rather than particles what you wanted, in the end?
@jeremydouglass Thank YOU and GoToLoop for the amazing help you're providing here. I'm sure it's possible to drag particles as well but I ended up only displaying springs so I'm fine with the code as it is.