Catching changes of scene properties

Hi,

I’m looking for a way to track changes that happen on some blender properties, such as bpy.context.scene.render.resolution_x so my script could update other values.

A dirty workaround was to check the value in the draw part of a custom panel, but that’s anyway no more possible since recent API change prevents writing to properties at draw time.

Any clue?
Thanks in advance,
yoyoz

Seems to me that drivers is an ideal way to do this.

I’d like to give a try to this but I don’t know how to attach the driver to an existing property from the script itself. I’ve seen a post in this forum showing an elegant way to register a driver name globally, so this part should be ok.

I also hope there’re no side effect such as turning the property in blue or whatever… :wink:

i used to do it the draw() way either. Now i’m going with a modal operator but that’s not less dirty. Uncle Entity made a patch that made notifiers and listeners available to blenders python api. but that is still in the patch tracker waiting to be reviewed by a core dev.

my code looks as follows:


IS_RUNNING = False
class PROPERTIES_OT_maintain_renderman(bpy.types.Operator):
    bl_idname = 'renderman.maintain'
    bl_label ="maintain renderman"
    bl_options = {'REGISTER'}
    
    def modal(self, context, event):
        #print("Blender to Renderman Addon Loaded")
        maintain(context)
        return {'PASS_THROUGH'}
                
    def execute(self, context):
        wm = context.window_manager
        global IS_RUNNING
        if context.area.type == 'PROPERTIES':
            if not IS_RUNNING:
                IS_RUNNING = True
                print("adding modal handler")
                wm.modal_handler_add(self)
        return {'RUNNING_MODAL'}

the operator is started in a draw() function of a custom panel.
that’s a realy ugly way but for now it works. There must be a way to check if the modal operator is running but i don’t know how. I’ve looked at the measure panel but the way how it’s described doesn’t seem to work for me somehow.
Btw: you could also still check your values in a draw panel and then run an operator from there if needed.

It could also fit my need, waiting for real callback or event system…
BTW, how to you call the operator from the draw area? (I’m sorry I can’t figure out the syntax)

bpy.ops.renderman.maintain()

Thanks, it works the way I want!

The only problem I have is blender flooding the logs when exiting:

Aspect ratio fix installed
bpy stats - tot exec: 16000, tot run: 0.2427sec, average run: 0.000015sec, tot usage 1.6630%
Saved session recovery to /tmp/quit.blend
Error Totblock: 456
wmOperatorReportList len: 40 0x497e628
ASPECT_OT_fix len: 168 0x4a76118
wmOperatorPtrRNA len: 24 0x31c42f8
IDProperty group len: 96 0x496a5f8
wmOperatorReportList len: 40 0x4987dd8
ASPECT_OT_fix len: 168 0x4a62a18
wmOperatorPtrRNA len: 24 0x31c4bf8
IDProperty group len: 96 0x4969f38
wmOperatorReportList len: 40 0x4a45288
… for many pages

Here’s the modified code. It just ensures that the aspect ratio is back to 1:1 and it’s called in the draw part of my first panel. I’m only annoyed with the messages in the log…

IS_RUNNING = False
class PROPERTIES_aspect_fix(bpy.types.Operator):
    bl_idname = 'aspect.fix'
    bl_label ="Keeps 1:1 pixels"
    bl_options = {'REGISTER'}
    
    def modal(self, context, event):
        #self.maintain(context)
        rd = bpy.context.scene.render
        if rd.pixel_aspect_x != 1:
            rd.pixel_aspect_x =1
            log ('Reset pixel to square')
        if rd.pixel_aspect_y != 1:
            rd.pixel_aspect_y = 1
            log ('Reset pixel to square')
        return {'PASS_THROUGH'}
                
    def execute(self, context):
        wm = context.window_manager
        global IS_RUNNING
        if context.area.type == 'PROPERTIES':
            if not IS_RUNNING:
                IS_RUNNING = True
                print("Aspect ratio fix installed")
                wm.modal_handler_add(self)
        return {'RUNNING_MODAL'}

Do you Guys have a clue about how I could get rid of the nasty logs? It seems to me Blender is stacking errors and I fear some unstability if using it for a long time…
Thanks,
Yoyoz

I managed doing it this way, but this is broken this morning with latest builds…

I’m getting the following now:

File "/home/lionel/.blender/2.56/scripts/addons/octanerender/ui_texture.py", line 178, in draw
    bpy.ops.octane.fixtexture()
  File "/usr/share/blender/2.56/scripts/modules/bpy/ops.py", line 179, in __call__
    ret = op_call(self.idname_py(), None, kw)
SystemError: Calling operator "bpy.ops.octane.fixtexture" error, can't modify blend data in this state (drawing/rendering)