7
$\begingroup$

This time I have a question about Properties in Blender. I want the operator window of my add-on to have one BoolProperty per action defined in bpy.data.actions and I want them to have the names from bpy.data.actions.keys(). I googled a bit and tried some stuff, but it wont work, theres allways something wrong, so is this even possible and can someone give me some hints on how to do it?

class ExportTSA(bpy.types.Operator, ExportHelper):

    actionprop0 = BoolProperty(name=bpy.data.actions.keys()[0],description="Exporet this action",default=True)
    actionprop1 = BoolProperty(name=bpy.data.actions.keys()[1],description="Exporet this action",default=True)
    actionprop2 = BoolProperty(name=bpy.data.actions.keys()[2],description="Exporet this action",default=True)
    actionprop3 = BoolProperty(name=bpy.data.actions.keys()[3],description="Exporet this action",default=True)

    def draw(self, context):
        layout = self.layout

        row = layout.row()
        row.prop(self,"actionprop0")
        row = layout.row()
        row.prop(self,"actionprop1")
        row = layout.row()
        row.prop(self,"actionprop2")
        row = layout.row()
        row.prop(self,"actionprop3")

Heres a simplified version of my class, to demonstrate the idea. Instead of making hardcoded props like actionprop0, actionprop1... I want it to be dynamic in a way that it creates an automatic list, assigns the correct names, registers each one and draws them. I also found that you get into trouble when using bpy.data.actions where I used it, after I googled it it turns out that blender seems to be not fully initialized at that point so that causes errors, which might lead to additional problems.

$\endgroup$

2 Answers 2

2
$\begingroup$

I don't think dynamic property creation is possible. I've tried it before, and Blender always complains:

rna_uiItemR: property not found: [property_name]

An alternative way would be to put the property in bpy.types.Action instead, so every actions already have the property. Then it's only a matter of displaying it.

import bpy

class EX_dynamic_property(bpy.types.Panel):
    bl_idname = 'EX_dynamic_property'
    bl_label = 'Dynamic Property'
    bl_space_type = 'VIEW_3D'
    bl_region_type = 'TOOLS'

    def draw(self, context):
        layout = self.layout
        for action in bpy.data.actions:
            layout.prop(action, 'EX_export_this', text=action.name)
        layout.operator('view3d.print_action_export_status')

class OT_dynamic_property(bpy.types.Operator):
    bl_idname = 'view3d.print_action_export_status'
    bl_label = 'Print'
    bl_options = {'REGISTER'}

    def execute(self, context):
        print('*' * 5)
        for action in bpy.data.actions:
            print("%s:\t%s" % (action.name, action.EX_export_this))
        return {'FINISHED'}

def register():
    bpy.utils.register_module(__name__)
    bpy.types.Action.EX_export_this = bpy.props.BoolProperty(default=False)

if __name__ == "__main__":
    register()

It's easy, and there's not a lot we need to do. Upon execution, the code above will list the property:

Screenshot

$\endgroup$
5
  • $\begingroup$ Thanks alot, it´s not perfect but it works fine so i´ll just go with it $\endgroup$
    – Luis W
    Jul 12, 2013 at 11:00
  • $\begingroup$ I've try to change the 'dynamic property' : for action in bpy.data.actions: With : for action in bpy.data.scenes: But it doesn't work. Does your solution only work with action or it also work with other bpy.data? (I want to create a dynamic check box panel with the Scene.) $\endgroup$
    – lucblender
    Nov 18, 2013 at 9:33
  • $\begingroup$ @lucblender: Scene is a subclass of ID, so it should work. That iteration accesses Action class' boolean EX_export_this property, which is added on script registration. Within register() function, you need to substitute bpy.types.Action with bpy.types.Scene. $\endgroup$
    – Adhi
    Nov 18, 2013 at 11:20
  • $\begingroup$ Sorry for asking question again but is it possible to create a dynamic property panel with string, int, etc... property and not boolean? Edit: I've found it's in registration bpy.types.Scene.RenderTrue = bpy.props.StringProperty(default='Text') $\endgroup$
    – lucblender
    Dec 16, 2013 at 15:18
  • $\begingroup$ @lucblender Yes, as long as the data type is supported by bpy.props. $\endgroup$
    – Adhi
    Dec 16, 2013 at 20:36
9
$\begingroup$

In addition to what Adhi suggested, you can use CollectionProperty in your operator to store key value pairs (where keys are name of the action and values are boolean values). For this to work you must...

  • create a subclass of PropertyGroup that will hold single key-value pair.
  • populate this collection from Operator.invoke method (you might already have it)

So the code goes like this:

import bpy
from bpy_extras.io_utils import ExportHelper
from bpy.props import *

class ActionSelProperty(bpy.types.PropertyGroup):
    name = StringProperty(name="Action Name")
    export = BoolProperty(name="Export", description="Exporet this action", default=True)

class ExportTSA(bpy.types.Operator, ExportHelper):
    bl_idname = "test.export_tsa_op"
    bl_label = "Export TSA"

    actionprop = CollectionProperty(name="Actions", type=ActionSelProperty, description="Select actions to exporet")
    filename_ext = "*.*" # Only needed if subclassing `ExportHelper`

    def invoke(self, context, event):
        for aname in bpy.data.actions.keys():
            self.actionprop.add().name = aname
        wm = context.window_manager
        wm.fileselect_add(self)
        return {'RUNNING_MODAL'}

    def draw(self, context):
        layout = self.layout

        for aindx in range(len(self.actionprop)):
            row = layout.row()
            row.prop(self.actionprop[aindx], "export", text=self.actionprop[aindx].name)

    def execute(self, context):
        for aprop in self.actionprop:
            print("%s:\t%s" % (aprop.name, aprop.export))
        return {'FINISHED'}

def register():
    bpy.utils.register_module(__name__)

if __name__ == "__main__":
    register()

In this case, name is a key and export is a boolean value.

PS: Invoke by searching Export TSA. Screenshots:

enter image description here enter image description here

This may not be perfect, but you can investigate more! :)

HTH

$\endgroup$
2
  • $\begingroup$ I tried your implementation and it works, but adhi´s seemed a little bit simpler but thanks anyways, i appreciate the help $\endgroup$
    – Luis W
    Jul 12, 2013 at 11:01
  • $\begingroup$ Love your answer, this is definitely the right way to do it, though I must admit, adhi's answer is very interesting. $\endgroup$
    – Tcll
    Sep 23, 2016 at 20:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .