1

I am dynamically adding a custom property to certain objects in a scene and I want to display that property in a panel. The custom property is a dictionary with keys that point to basic types, I only want to display some of the keys. Below is a simplified version of the workflow - the user selects an object, clicks a button and the property gets added, then I'd like the user to edit some of the data. Unfortunately I can't figure out how to get the panel to display/edit some of the values from the dictionary.

class myDynamicPropertyDict(dict):
    def __init__(self):
        self['userEditable'] = '<user-editable text>'
        self['internalUse'] = '<non-user-editable stuff>'

class MYCOMPANY_OT_AddProperty(bpy.types.Operator): bl_label = "Add Property" bl_idname = "mycompany.addproperty"

def execute(self, context):
    if context.active_object.get(&quot;myProp&quot;) is None:
        context.active_object[&quot;myProp&quot;] = myDynamicPropertyDict()
    return {'FINISHED'}


class MYCOMPANY_PT_TestPanel(bpy.types.Panel): bl_label="Test Panel" bl_space_type = "VIEW_3D" bl_region_type = "UI"

def draw(self, context):
    layout=self.layout
    layout.operator(&quot;mycompany.addproperty&quot;, text = &quot;Add&quot;, icon=&quot;ADD&quot;)
    if context.active_object and (&quot;myProp&quot; in context.active_object):

        ### Attempt #1 ###
        ### Results in this message:
        # TypeError: UILayout.prop(): error with keyword argument &quot;data&quot; -  Function.data expected a AnyType type, not IDPropertyGroup
        #
        # location: &lt;unknown location&gt;:-1
        ### layout.prop( data=context.active_object[&quot;myProp&quot;], property='[&quot;userEditable&quot;]')


        ### Attempt #2 ###
        ### Results in this message:
        # rna_uiItemR: property not found: Object.[&quot;myProp&quot;][&quot;userEditable&quot;]
        ### layout.prop( data=context.active_object, property='[&quot;myProp&quot;][&quot;userEditable&quot;]')


        ### Attempt #3 ###
        ### Renders, but get a mouseover saying &quot;This property is for internal use only and is disabled.&quot;
        ### layout.prop( data=context.active_object, property='[&quot;myProp&quot;]')

        layout.label(text=&quot;Dummy label to see something rendering&quot;)


def register(): bpy.utils.register_class(MYCOMPANY_OT_AddProperty) bpy.utils.register_class(MYCOMPANY_PT_TestPanel)

def unregister(): bpy.utils.unregister_class(MYCOMPANY_PT_TestPanel) bpy.utils.unregister_class(MYCOMPANY_OT_AddProperty)

if name == "main": register() ```

Spurkey
  • 91
  • 3
  • It's trickier than it seems to do what you're trying to do. The builtin layout functions don't allow displaying a dictionary. It only works with proper bpy.props properties. see https://docs.blender.org/api/current/bpy.props.html for examples. Maybe this will help https://blender.stackexchange.com/a/176499/86891. tldr : you'll have to define blender specific properties to store your dictionary and a custom layout system to display it like you want – Gorgious Mar 29 '22 at 19:46
  • Or if the values are simple data types like string or integer, you can store it as a string and use json.loads and json.dumps to store it in a regular string custom prop – Gorgious Mar 29 '22 at 19:50
  • hm ...maybe what I'm doing just isn't The Blender Way™. I'd hoped to be able to add my blob of properties only to the objects that needed them to try and keep things simple but it seems I'll be fighting Blender the entire time. – Spurkey Mar 31 '22 at 00:48

0 Answers0