7
$\begingroup$

Is it possible to run a script every few seconds or so, while letting the interface update in the meantime?

How can I do this?

$\endgroup$
11
$\begingroup$

See the Operator Modal Timer template in the Text Editor:

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

    def modal(self, context, event):
        if event.type == 'ESC':
            return self.cancel(context)

        if event.type == 'TIMER':
            # change theme color, silly!
            color = context.user_preferences.themes[0].view_3d.space.gradients.high_gradient
            color.s = 1.0
            color.h += 0.01

        return {'PASS_THROUGH'}

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

    def cancel(self, context):
        context.window_manager.event_timer_remove(self._timer)
        return {'CANCELLED'}


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()

You can specify the interval for the 'TIMER' event, but note that all active timers will be caught (there is no way to distinguish them).

The timer class also comes with some handy attributes:

if event.type == 'TIMER':
    print (self._timer.time_duration) # elapsed time since the operator call
    print (self._timer.time_delta)    # elapsed time since the last step
    ...

Beware of using threads, they can crash Blender.

| improve this answer | |
$\endgroup$
  • 2
    $\begingroup$ Trippy template XD $\endgroup$ – Greg Zaal Mar 20 '14 at 7:27
2
$\begingroup$

in blender 2.80 you can do this: (for blender 2.7 I don't know)


def timer_call_fnc():
    print('called')
    return 1.0 # call every second

bpy.app.timers .register( timer_call_fnc )
timer_call_fnc() # make first call

# unregister later:
#bpy.app.timers .unregister( timer_call_fnc )

more info: blender 2.80 timer api

note:
"You should never modify Blender DATA at arbitrary points in time in separate threads. "

for addons you might have to make the timer and handler persistent. example:

# blender 2.8 example 
# persistent timer 
#

from bpy.app.handlers import persistent

@persistent   # do not discard, when file changes 
def timer_fired():
   # do stuff
   return 0.5 # seconds 

@persistent
def handler_load_post():
   if not bpy.app.timers  .is_registered( timer_fired ):
       bpy.app.timers .register( timer_fired, first_interval=1.0, persistent=True )

def my_init():
   bpy.app.handlers .load_post .append( handler_load_post )
| improve this answer | |
$\endgroup$

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.