Make drag/drop object only clickable once

Using Windows 11 and PsychoPy version (2023.2.3).

Firstly:
I am trying hard to build my experiment on my own - but with limited knowledge in python/PsychoPy coding I am struggling. Is there some documentation or description of functions I could use to help me? I have accessed the Reference manual API and using docs for psychopy.event (psychopy.event - for keypresses and mouse clicks — PsychoPy v2024.2.4) but I don’t think this is enough. For example, someone on the forum helped me add:

def movePicked(picked, mouse, grabbed):

but I don’t actually know what the functions ‘picked’ and ‘grabbed’ do or how to use them properly if I want to advance the code myself. If anyone can suggest any resources or documentation I might benefit from, that would be really helpful.

Secondly:
In this experiment, participants watch a video stimulus then are asked to replicate the position of 8 objects on a blank canvas. The routine successfully allows the 8 objects (image stimuli) to be dragged and dropped by a mouse click, and successfully exports the position coordinates of the objects. However, I would like the objects to only be movable once - i.e., when participants drag and drop the object, they can’t move it again. Currently, participants are able to drop the object, and pick it up again to move it. As I mentioned, I would like to eventually be able to build this myself, but I don’t have the competence yet. I’m not sure what to do, so any help would be appreciated.

Begin Experiment:

def movePicked(picked, mouse, grabbed):
    # Move piece if we already moving that piece
    if grabbed is not None and mouse.isPressedIn(grabbed):
        grabbed.pos = mouse.getPos()
        return grabbed
    else:
        # Move newly clicked piece
        for piece in picked:
            if mouse.isPressedIn(piece) and grabbed is None:
                return piece

Begin Routine:

pieces = [X_1, X_2, X_3, X_4, O_1, O_2, O_3, O_4]
picked = []
movingPiece = None

opacity = 0
spacepress = False

event.clearEvents()

Each Frame:

for piece in pieces: 
    if mouse.isPressedIn(piece) and movingPiece is None:
        picked.append(piece)
        
movingPiece = movePicked(picked, mouse, movingPiece)

keys = event.getKeys()  # Get the keys pressed in the current frame
if 'space' in keys:  # Check if the space bar is pressed
    opacity = 1.0
    spacepress = True
 
if 'left' in keys:    
    opacity = 0.0
    spacepress = False
    
if 'right' in keys and spacepress:
     continueRoutine = False
    
event.clearEvents()

Thanks,
Aimee

Regarding my first query:
I do understand that ‘picked’ and ‘grabbed’ are terms we created with custom code, but I mean I’m not sure what the limit is in what we can do with these terms we’ve created and how I can advance what we’ve done with them.

Hope that makes sense :slight_smile:

How about pieces.remove(grabbed)?

Hello, for anyone following:

Thanks, but pieces.remove(grabbed) didn’t seem to do anything.

I’ve solved the issue using the following solution:

(Removed code from Begin Experiment)

Begin Routine

pieces = [X_1, X_2, X_3, X_4, O_1, O_2, O_3, O_4] #stimuli components into a list
placed = [] #new list for moved pieces to go into
movingPiece = None #currently clicked piece, move function only works for whatever this is set to

opacity = 0
spacepress = False

event.clearEvents() #clears all events i.e., spacebar, from previous routine

Each Frame

# checking if movable object in list 'pieces' is clicked on and setting it to current 'movingPiece', and remove it from pickable list
for piece in pieces:
    if mouse.isPressedIn(piece) and movingPiece is None:
        movingPiece = piece
        pieces.remove(piece)

# if movingPiece is active it equals mosue position, and checks if mouse is still pressed
if movingPiece is not None:  
    movingPiece.pos = mouse.getPos()
    leftclicked = mouse.getPressed()[0]

# when mouse is not clicked, drop piece
    if not leftclicked:
        finished = True
    else:
        finished = False
        
# if piece is dropped, add to placed list for saving data (finished = flase is restting the code for next click)
    if finished:
        placed.append(movingPiece)
        movingPiece = None
        finished = False
   
keys = event.getKeys() # Get the keys pressed in the current frame
if 'space' in keys:  # Check if the space bar is pressed
    opacity = 1.0
    spacepress = True
 
if 'left' in keys:    
    opacity = 0.0
    spacepress = False
    
if 'right' in keys and spacepress:
     continueRoutine = False
    
event.clearEvents()

End Routine

for piece in placed:
     thisExp.addData(piece.name,piece.pos)

Hope this helps someone else!
Aimee