Drag example

Here is the sequence of mouse events involved in dragging something:

1) m1.press is True when you depress the mouse button (it is 'left' if left button; nonzero is True in Python).


2) m1.drag is True when the mouse coordinates change from what they were at the time of m1.press.
At the time of the drag event, the mouse position is reported to be what it was at the time of the press event, so that the dragging can start at the place where the user first clicked. If the mouse is in motion at the time of the press event, it is quite possible that the next position seen by the computer, at the time of the drag event, could be quite far from the click position. This is why the position of the drag event is reported as though it occurred at the press location.


3) No events occur while dragging; you continually use scene.mouse.pos to update what you're dragging.


4) m1.drop is True when you release the mouse button.

You can program dragging with the mouse simply by continually reading the current value of scene.mouse.pos. Here is a complete routine for dragging a sphere with the left button down. Note the statements for making the cursor invisible during the drag.

scene.range = 10 # fixed size, no autoscaling

ball = sphere(pos=(-5,0,0), radius=1., color=color.cyan)

cube = box(pos=(+5,0,0), size=(2,2,2), color=color.red)

pick = None # no object picked out of the scene yet

while 1:

    if scene.mouse.events:

        m1 = scene.mouse.getevent() # obtain drag or drop event

        if m1.drag and m1.pick == ball: # if clicked on the ball

            drag_pos = m1.pickpos # where on the ball the mouse was

            pick = m1.pick # pick is now True (nonzero)

            scene.cursor.visible = 0 # make cursor invisible

        elif m1.drop: # released the mouse button at end of drag

            pick = None # end dragging (None is False)

            scene.cursor.visible = 1 # cursor visible again

    if pick:

        new_pos = scene.mouse.project(normal=(0,1,0)) # project onto xz plane

        if new_pos != drag_pos: # if the mouse has moved since last position

            pick.pos += new_pos - drag_pos # offset for where the ball was clicked

            drag_pos = new_pos # update drag position

If you do a lot of processing of each mouse movement, or you are leaving a trail behind the moving object, you may need to check whether the "new" mouse position is in fact different from the previous position before processing the "move", as is done in the example above. For example, a trail drawn with a curve object that contains a huge number of points all at the same location may not display properly.

Only some of the VPython objects can be "picked" by clicking them, including sphere, box, and cylinder. Here is a more general routine which lets you drag either the tail or the tip of an arrow:

scene.range = 10 # fixed size, no autoscaling

pointer = arrow(pos=(0,4,0), axis=(3,2,0), color=color.yellow))

tolerance = 0.3 # must click within this distance of tail or tip

drag = None # have not selected tail or tip of arrow

while 1:

    if scene.mouse.events:

        m1 = scene.mouse.getevent() # obtain press or drag or drop event

        if m1.press:

            if mag(pointer.pos-m1.pos) <= tolerance:

                drag = 'tail' # pressed near tail of arrow

            elif mag((pointer.pos+pointer.axis)-m1.pos) <= tolerance:

                drag = 'tip' # pressed near tip of arrow

            drag_pos = m1.pos # save press location

        elif m1.drag and drag: # if drag event and something to drag

            scene.cursor.visible = 0 # make cursor invisible

        elif m1.drop: # released the mouse button at end of drag

            drag = None # end dragging (None is False)

            scene.cursor.visible = 1 # cursor visible again

    if drag:

        new_pos = scene.mouse.pos

        if new_pos != drag_pos: # if the mouse has moved since last position

            displace = new_pos - drag_pos # how much the mouse moved

            drag_pos = new_pos # update drag position

            if drag == 'tail':

                pointer.pos += displace # displace the tail

            else:

                pointer.axis += displace # displace the tip

 

Choose Back, or Go to top of mouse documentation