1
$\begingroup$

I'm currently trying to modify some drivers so that they are disabled when they're not on a proxied armature. Right now, I'm using the following script to set a custom property, which is used by the drivers:

import bpy
from bpy import context

class UseHeight(bpy.types.PropertyGroup):
    @classmethod
    def register(cls):
        ob = context.object
        if("UseHeight" in ob.keys()):
            ob["UseHeight"] = (ob.proxy != None)

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

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

if __name__ == "__main__":
    register()

However, I have to put this into every script I use, and with how my memory has been impacted by my health problems, I don't want to add yet another thing for me to keep track of. I've attempted to use it as an addon, but it fails to work due to this error:

Exception in module register(): '/home/zauber/.config/blender/2.69/scripts/addons/MaelstromUseHeight.py'
Traceback (most recent call last):
  File "/home/zauber/Desktop/blender-2.69-linux-glibc211-x86_64/2.69/scripts/modules/addon_utils.py", line 311, in enable
    mod.register()
  File "/home/zauber/.config/blender/2.69/scripts/addons/MaelstromUseHeight.py", line 12, in register
    bpy.utils.register_class(UseHeight)
  File "/home/zauber/.config/blender/2.69/scripts/addons/MaelstromUseHeight.py", line 7, in register
    ob = context.object
AttributeError: '_RestrictContext' object has no attribute 'object'

So, what do I need to do to get this working? Or is there a way I can directly check if the object's proxy value is equal to "None" inside the drivers?

$\endgroup$
  • $\begingroup$ You may not access any bpy.context and bpy.data members (with a few exceptions like for keymaps): Restricted Context $\endgroup$ – CoDEmanX Feb 15 '14 at 0:44
  • $\begingroup$ I just spent an hour trying to adapt my code to work around that. My line count has already doubled or tripled, and nothing works at all. I've tried stuffing the needed value into a PropertyGroup, but (a) I can't actually get data recorded to it, and (b) it seems that the drivers can't read from the property groups anyways. $\endgroup$ – Zauber Paracelsus Feb 15 '14 at 2:43
  • $\begingroup$ Okay, got it to pull data from the property group by having it's data put into a panel. However, when I try to change the data by adding the poll function to the panel class, the panel just disappears. No error output on the console. $\endgroup$ – Zauber Paracelsus Feb 15 '14 at 2:46
  • $\begingroup$ A poll() classmethod is supposed to return True or False to indicate whether the class can be used or not. In case of operater classes, it determines if the context is suitable to invoke/execute the operator. In case of panels, if they shall show. def poll(cls, context): return context.mode == 'OBJECT' (only show panel when in object mode) $\endgroup$ – CoDEmanX Feb 15 '14 at 2:51
  • $\begingroup$ Okay, so if it's not something that is meant to be used, what should I be using? I'm assuming that Operator classes are executed on invocation. I'm looking for something that just runs automatically. $\endgroup$ – Zauber Paracelsus Feb 15 '14 at 2:53
2
$\begingroup$

From the advice of CoDEmanX and reading documentation, I figured out what to do last night. I changed it all to use a pair of handler functions. Here is the altered script:

import bpy
from bpy.app.handlers import persistent

bl_info = {
    "name": "Maelstrom Height Handler",
    "category": "Object",
}

'''
Called when the scene is updated, and calls height_general_update if
any objects in the scene have been updated.
'''
@persistent
def height_scene_update(scene):
    if(bpy.data.objects.is_updated):
        height_general_update(scene)

'''
Iterates through each scene object to see if the "height" property
is present, then adds and/or adjusts the "useHeight" property.  Does
nothing if the height is unchanged, to prevent other potential code
from running.  Runs when a scene is loaded or when called by the
above function.
'''
@persistent
def height_general_update(scene):
    didChange = False
    for obj in bpy.data.objects:
        rigChanged = False
        if("height" in obj.keys()):
            val = int(obj.proxy != None)
            if("useHeight" not in obj.keys()):
                obj["useHeight"] = val
                rigChanged = True
            else:
                if(obj["useHeight"] != val):
                    obj["useHeight"] = val
                    rigChanged = True
        if(rigChanged):
            print("Adjusting useHeight flag of", obj.name)
            didChange = True

def register():
    bpy.app.handlers.scene_update_pre.append(height_scene_update)
    bpy.app.handlers.load_post.append(height_general_update)

def unregister():
    for idx, val in enumerate(bpy.app.handlers.scene_update_pre):
        if(val == height_scene_update):
            del bpy.app.handlers.scene_update_pre[idx]
    for idx, val in enumerate(bpy.app.handlers.load_post):
        if(val == height_general_update):
            del bpy.app.handlers.load_post[idx]


if __name__ == "__main__":
    register()
$\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.