Blender Internal, Update node for GLSL Viewport / Handler + Driver

Download Demo File of Issue: [ATTACH]422854[/ATTACH]

I am running into a weird issue that I have solved in the past but can’t seem to figure out now.

I have a material node keyframed in Blender Internal, and unfortunately blender does not show the transition in the GLSL textured viewport. So I have written a small script that will reinforce the value of a MixRGB factor to itself.

When I click on “Run Script” everything works fine and my material is updated. However assigning the function to a driver or even handler does need yield expected result, which is updating that MixRGB factor on every frame change.

import bpy


def refreshNow(val):
    mat = bpy.data.materials['Skin_Gloss']
    nodes = mat.node_tree.nodes
    nodes["Mix"].inputs[0].default_value = nodes["Mix"].inputs[0].default_value
    return val


refreshNow(0)


bpy.app.driver_namespace['refresh'] = refreshNow


def my_handler():
    refreshNow(0)


def register():
    bpy.app.handlers.frame_change_post.append(my_handler)



Below is my driver setup. As you can see the debug info shows my current frame, which is 115. Meaning that refreshNow is actually called and has returned.


Here is my material setup, pay attention to the MixRGB being keyframed from 0 to 1, from frame 0 to 50:


Like I said, the script works fine when I click on “Run Script”, and the driver shows that the function has returned. What could possibly be the issue?

Thank you in advance.

Edit:I have attached a blend file demonstrating the issue;

[ATTACH]422854[/ATTACH]

I have attached a blend file demonstrating the issue;

DriverGLSLIssue.blend (554 KB)

I managed to fix the issue by using a Modal Timer rather than utilizing handlers or drivers. Only problem is that I have to click on “Run Script” every time I want to play the animation and see the transition in viewport :frowning:

Below is the code for anyone who might need it in future. This is simply the Modal Timer template, I just replaced the default functionality of changing theme color to reinforcing the MixRGB node’s factor input to itself. I have also removed the functionality of cancelling the event.

Is it possible to attache this script to the “Play” function, so every time I click on “Play” or press Alt-A it start and when I stop the playback the script stops running as well?


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 in {'RIGHTMOUSE', 'ESC'}:
            self.cancel(context)
            return {'CANCELLED'}


        if event.type == 'TIMER':
            mat = bpy.data.materials['Material']
            nodes = mat.node_tree.nodes
            mix = nodes["Mix"].inputs[0]
            mix.default_value = mix.default_value


        return {'PASS_THROUGH'}


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

hello @joemoehobo
Don’t use driver
Just use frame_change_pre


import bpy

def frame_change_callback(scene):
            mat = bpy.data.materials['Material']
            nodes = mat.node_tree.nodes
            mix = nodes["Mix"].inputs[0]
            mix.default_value = mix.default_value
    
bpy.app.handlers.frame_change_pre.append(frame_change_callback)