Drag Example
Here is the sequence of mouse events involved in dragging something:
1) Determine that the mouse button has been depressed (a mousedown event).
2) Continually watch for the mouse to move, and use scene.mouse.pos to update positions. These are mousemove events.
3) Conclude the drag when the mouse button has been released (a mouseup event).
The way you detect these mouse events is by writing functions that are bound to the mouse events using scene.bind, and Web VPython will execute these functions when these mouse events occur.
Here is a complete routine for repeatedly creating and dragging a sphere, so that you can arrange many spheres on the screen. While being dragged the sphere is red, but its color changes to cyan when the mouse button is released.
scene.range = 5
box()
drag = False
s = None # declare s to be used below
def down():
global drag, s
s = sphere(pos=scene.mouse.pos,
color=color.red,
size=0.2*vec(1,1,1))
drag = True
def move():
global drag, s
if drag: # mouse button is down
s.pos = scene.mouse.pos
def up():
global drag, s
s.color = color.cyan
drag = False
scene.bind("mousedown", down)
scene.bind("mousemove", move)
scene.bind("mouseup", up)
It is also possible to use "anonymous" (unnamed) functions, an extended feature of the RapydScript-NG Python-to-JavaScript compiler, as shown here (this will NOT work with installed Python):
scene.range = 5
box()
drag = False
s = None # declare s to be used below
scene.bind("mousedown", def ():
global drag, s
s = sphere(pos=scene.mouse.pos,
color=color.red,
size=0.2*vec(1,1,1))
drag = True
)
scene.bind("mousemove", def ():
global drag, s
if drag: # mouse button is down
s.pos = scene.mouse.pos
)
scene.bind("mouseup", def ():
global drag, s
s.color = color.cyan
drag = False
)
Other mouse events: You can also watch for mouseenter (the mouse is moved from the outside of the canvas to the inside), mouseleave (the mouse leaves the canvas), and click.
Multiple event types: You can bind a function to more than one type of event. Here is a function bound to both mousedown and mouseup events, either of which will cause a sphere to be created:
scene.bind("mousedown mouseup", def ():
sphere(pos=scene.mouse.pos)
)
Unbinding: After binding a function to a mouse event, you can unbind the function, in which case Web VPython will no longer send events to your function. In the program shown above, if you place scene.unbind("mousedown") in the mouseup event, you will be able to drag just one sphere.
Just one: If you use scene.one instead of scene.bind, the binding occurs for just one event and then is automatically unbound. In the program shown above, if you specify scene.one for the mousedown event, you will be able to drag just one sphere.
Custom events: You can set up your own custom events using scene.trigger. In the following sample program, first you see a box, then the while loop halts waiting for the custom "ball" event to occur. When you click, the function t is executed, and in this function a sphere is created and a new type of event, "ball", is triggered by scene.trigger, with the optional argument b, representing the new sphere. With this triggering of a "ball" event, function f receives the triggered arguments in ev and sets the sphere's color to blue. The triggering of a "ball" event also breaks through the scene.waitfor in the while loop that was waiting for a "ball" event. The process in the loop then repeats.
def t():
b = sphere(pos=scene.mouse.pos, radius=0.2)
scene.trigger("ball", b)
scene.bind("click", t)
def f(ev):
# ev.type is "ball"; ev.event is newball
ev.event.color = color.blue
scene.bind("ball", f)
cube = box(pos=vec(-2,0,0))
while True:
s = scene.waitfor("ball")
print(s.type, s.event.pos) # "ball" and the new sphere's pos
cube.rotate(angle=0.1, axis=vec(0,0,1))