Frame Review vs. Frame Change (a threaded approach in Blender 2.5)

Hi All,

I have been running into some problems with the driver based frame change event system. It seems to be problematic when rendering. I have been looking into another way to simulate a frame change event and have come up with a threaded sampling concept that seems to solve this rendering problem.

https://vimeo.com/21276947

Feel free to download the BLEND file. Press play to see CameraPlus threaded version in action.

I have only tested this system on Windows XP64 using Blender 2.5 32bit and 64bit builds. So any feedback as to the reliabilty of this concept on other OS’ would be great.

A related video:
http://python.mirocommunity.org/video/1501/pycon-2010-demystifying-non-bl

Attachments

25_cameraplus_threading_model_1b.blend (672 KB)

This looks like it can do what I’ve been attempting to do for months! Would I be correct to say that this script can run something in the background of Blender while the user uses Blender, without requiring the mouse to moving constantly (as is the case with a modal operator)?

Yes, the initial thread is launched and then the launching thread exits, returning control back to Blender. So the thread is running simultaneous along with Blender. Be aware, however, there can be synchronizations errors when you attempt to read or write to bpy.data. But as I mention in the short video, correct try/catch protection on the code that makes the connection to BPY can go a long way to making this work. Also, using this technique there is no CONTEXT so all those features are not available.

Ok I never needed context anyway, if this thread hangs, will Blender also hang? (i.e. as produced by a socketobject.recv(buffer).

I don’t think it will hang Blender. The initial Blender event that launched the thread has already happened and returned control to Blender. It is python that has launched the thread.

Give it a try. I crashed Blender 2.5 quite a bit writing this code so don’t be surprised if you experience a crash too.

It doesn’t hang, I’ve had my socket hang, but Blender keeps running. Can I please please please use this for my socket thing? It’s brillant you can have credit and everything too! (god I’m like a child with a new toy )

That is why I posted it. Anyone can use the code. Enjoy!

Hi Atom,

thank you a lot for sharing your code.

I needed some text to change over time (controlled via frames) and I tried your script. I substituted your lines for changing the camera with a text updater. Unfortunately, Blender kept stopping working for some seconds then restarting then holding again and so on. It might well be because I was running it on a laptop … anyway, getting right to the point, I tried a different solution an what I found out is that for me it was much more effective and less CPU consuming to base it on the embedded operator modal timer (in text templates). By changing the silly (by definition) color changer with a frame check and my piece of code, it worked out quite well. Haven’t found any problem so far. Only thing is that when it renders it uses a frame behind, but by applying a + 1 to the frame reader it is easily solved. I suspect that if I were playing with frames while it is rendering it might give some errors, but apparently Blender doesn’t allow you to do so. You need to rewind in this case as well.

Hope this is interesting to you all.

@loscotec: Nice to know, I had not played around with that example yet.

But how to I get it to run when I want to render my animation?
Here is my modification to move the cube.


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

        if event.type == 'TIMER':
            ob = bpy.data.objects["Cube"]
            if ob != None:
                x = ob.location[0]
                x = x + 1
                ob.location[0] = x

        return {'PASS_THROUGH'}

    def execute(self, context):
        context.window_manager.modal_handler_add(self)
        self._timer = context.window_manager.event_timer_add(0.1, context.window)
        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()