0
$\begingroup$

I am trying to create a simple script in python that will allow me to select objects from my scene. What I did, is created a scene, and added 3 objects, a cube, a sphere and a cylinder, and they are named; Cube, Sphere and a Cylinder , respectively. I am trying to create a python script in which I want to select these objects within a time delay. So for example I want to select the Cylinder, then 1 second later I want to select the Cube and then 1 second after that I want to select the Sphere. At the end of my script all 3 objects should be selected. In my script they are all getting selected but they all get selected instantaneously at the end of the program. I used the time module for python to create the time delay of 1 second after I select one object, but it doesn't seem like the time delay does anything, because all 3 objects gets selected simultaneously. Here is my python script and blender project. enter image description here

Firstly, I create an empty list, which i then fill up with the name of all the objects in my scene, in my case its only 3 objects. I then loop through those objects from my list / scene and select them 1 by 1 with a 1 second delay in between. However when the script ends all the objects are selected instantly. And yes, I did unselect everything before running the script.

Does anyone know how I can fix or re write my code, so when I run the script, it will select an object then wait for 1 second and select the other object and then wait 1 more second after that and select the last object.

Of course, I only used only 3 objects in my scene for simplicity reasons, but this script should of course work for any scene and any number of objects.

$\endgroup$
3
$\begingroup$

Modal timer operator

Would suggest not using time.sleep and use a modal timer operator instead.' Example using modal timer operator template.

import bpy

class ModalTimerOperator(bpy.types.Operator):
    """Operator which runs its self from a timer"""
    bl_idname = "wm.modal_timer_operator"
    bl_label = "Modal Timer Operator"

    _timer = None
    ob_index = 0

    def modal(self, context, event):
        scene = context.scene
        if self.ob_index >= len(scene.objects):
            self.cancel(context)
            return {'CANCELLED'}

        if event.type == 'TIMER':
            scene.objects[self.ob_index].select = True
            self.ob_index += 1

        return {'PASS_THROUGH'}

    def execute(self, context):
        wm = context.window_manager
        self._timer = wm.event_timer_add(1, context.window)
        wm.modal_handler_add(self)
        return {'RUNNING_MODAL'}

    def cancel(self, context):
        wm = context.window_manager
        wm.event_timer_remove(self._timer)

def register():
    bpy.utils.register_class(ModalTimerOperator)

def unregister():
    bpy.utils.unregister_class(ModalTimerOperator)

if __name__ == "__main__":
    register()

    # test call
    bpy.ops.wm.modal_timer_operator()
$\endgroup$
  • $\begingroup$ Yes, this is what I am looking for exactly ! I only have one question, how will I be able to use this Modal time operator ? Do I just use this same code at the beginning of my script and then run my script as it is, or do I need to apply some parameters ? $\endgroup$ – Viktor Raspberry Nov 28 '17 at 15:48
  • $\begingroup$ Yes, I got it working, just by running your script ! I am pretty new to python, but could you shed some light on how and why does this modal time operator works ? $\endgroup$ – Viktor Raspberry Nov 28 '17 at 15:55
  • 1
    $\begingroup$ Will get back to it.. need new batteries for keyboard.. took 5 mins to write this comment lol. $\endgroup$ – batFINGER Nov 28 '17 at 15:58
  • $\begingroup$ Yeah, don't worry! $\endgroup$ – Viktor Raspberry Nov 28 '17 at 15:59
0
$\begingroup$

It ought to function as intended. Try printing time between iterations.

test it

$\endgroup$
  • $\begingroup$ Did it work for you ? $\endgroup$ – Viktor Raspberry Nov 28 '17 at 1:57
  • 1
    $\begingroup$ Yeah, it did OK over here. I can't say why it would jump past a delay for you. You've got the most recent version of Blender? $\endgroup$ – Doyousketch2 Nov 28 '17 at 2:21
  • $\begingroup$ I am using 2.78b. $\endgroup$ – Viktor Raspberry Nov 28 '17 at 2:50
  • $\begingroup$ Possibly due to Python output buffering, using multiple threads to go through the loop. stackoverflow.com/questions/21886233/… Maybe import sys then call sys.stdout.flush() after sleep stackoverflow.com/questions/44799353/… $\endgroup$ – Doyousketch2 Nov 28 '17 at 3:24
  • 1
    $\begingroup$ It waits for me. Printing time ticks once a second, as shown in the image above. Seems like a Python bug, but I can't recreate it here. Could be due to processor or OS, couldn't say. You might try asking on stackoverflow, and see if someone over there has a better idea of what's going on. I'd imagine they'll point you to similar pages, but maybe they can explain it better. $\endgroup$ – Doyousketch2 Nov 28 '17 at 5:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.