1
$\begingroup$

Hi and thanks for any help in advance.

I have two dropdowns. On the change of the first dropdown, I want to repopulate the options of the second dropdown. Here is some demo code, but in my real world use my first dropdown is used to select the "Asset Type" (prop, character etc) and then the second dropdown would be for the actual "Asset Name" (Rock, Chair, Bobby, Sue).

class ADDONAME_OT_TemplateOperator(bpy.types.Operator):
    bl_label = "Template Operator"
    bl_idname = "wm.template_operator"
    
    def changed_dropdown_one(self, context):
        print('Dropdown one changed')

        # My problem is below, dropdown_two.items here error's out
        # I tried using "self" and "context" but I don't understand how to get to 
        dropdown_two.items = [( 
            ('option_3', 'Changed', 'tool tip'),
            ('option_4', 'Them', 'tool tip'),
        )]

    dropdown_one: bpy.props.EnumProperty(
        name="awd",
        description="",
        items=[
            ('option_1', 'First', 'tool tip'),
            ('option_2', 'Second', 'tool tip'),
        ],
        update=changed_dropdown_one
    )
    dropdown_two: bpy.props.EnumProperty(
        name="",
        description="",
        items=[
            ('option_1', 'First', 'tool tip'),
            ('option_2', 'Second', 'tool tip'),
        ]
    )

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_props_dialog(self)
    
    def draw(self, context):
        layout = self.layout
        layout.prop(self, "dropdown_one")
        layout.prop(self, "dropdown_two")
    
    def execute(self, context):
        return {'FINISHED'}    
$\endgroup$
2
  • 1
    $\begingroup$ Hello ! Changing the state of another property in an update is possible but not really supported. It may have side effects that will make Blender crash. It looks really complicated to me, why not use a third enum and change which one is displayed depending on the value of the first enum ? $\endgroup$
    – Gorgious
    Feb 9, 2023 at 16:28
  • $\begingroup$ Hi! Thanks for the reply. Yeah you're right, it doesn't seem like there is a good solution currently. Would need to use some hacks like your idea or the code below. In my case I have dynamic dropdown items, so making a third hidden dropdown won't work for me. But it's an idea for someone else for sure! :) $\endgroup$
    – Frank
    Feb 13, 2023 at 13:59

1 Answer 1

0
$\begingroup$

For brevity, I'm going to refer to dropdown_one and dropdown_two as DD1 and DD2.

The mindtrick here is to stop thinking in terms of "DD1 is changing the items of DD2", and flip it around to "DD2's items depend on the value of DD1". This can be done by passing a function as items, as described in the EnumProperty docs:

# Mapping from dropdown_one value to dropdown_two enum items:
_dd2_items = {
    'option_1': [
        ('option_11', 'A1', 'tool tip'),
        ('option_12', 'A2', 'tool tip'),
    ],
    'option_2': [
        ('option_21', 'B1', 'tool tip'),
        ('option_22', 'B2', 'tool tip'),
    ],
}

class ADDONAME_OT_TemplateOperator(bpy.types.Operator):
    bl_label = "Template Operator"
    bl_idname = "wm.template_operator"

    def _dropdown_two_items(self, _):
        try:
            return _dd2_items[self.dropdown_one]
        except KeyError:
            return [
                ('-', f'no options for {self.dropdown_one}', ''),
            ]

    dropdown_one: bpy.props.EnumProperty(
        name="awd",
        description="",
        items=[
            ('option_1', 'First', 'This will show A1/A2'),
            ('option_2', 'Second', 'This will show B1/B2'),
            ('option_3', 'Third', 'This will have no options'),
        ],
    )
    dropdown_two: bpy.props.EnumProperty(
        name="",
        description="",
        items=_dropdown_two_items,
    )

    def invoke(self, context, event):
        wm = context.window_manager
        return wm.invoke_props_dialog(self)
    
    def draw(self, context):
        layout = self.layout
        layout.prop(self, "dropdown_one")
        layout.prop(self, "dropdown_two")
    
    def execute(self, context):
        return {'FINISHED'}    
$\endgroup$
8
  • $\begingroup$ Hi :) Thanks for the help! So my problem with this is if you put print("something") inside the _dropdown_two_items function, it's going to trigger literally all the time right? You're going to have thousands of something prints. This is extremely bad code because if I had to source a list from a website or something it would be fetching HTTP calls all the time. Am I misunderstanding something maybe or is this just how Blender works? $\endgroup$
    – Frank
    Feb 10, 2023 at 9:29
  • $\begingroup$ "This is extremely bad code" is not a nice thing to say when someone tries to help you out. No, you shouldn't do a HTTP call directly in that function. You never mentioned anything about network connections in your question, so you can't expect to get any answer that takes networking into account, now can you? $\endgroup$
    – dr. Sybren
    Feb 10, 2023 at 13:42
  • 1
    $\begingroup$ You still haven't answered my question about the print statement problem. If you are a Blender dev then accept that this solution is bad and fix it. And if you don't think this solution is bad then you need to check you ego mate. $\endgroup$
    – Frank
    Feb 13, 2023 at 8:45
  • 2
    $\begingroup$ @Frank, kindly be advised that this is not an acceptable way to interact with people trying to help you. Especially with one of the blender devs who took their time to post an answer to your question. Nowhere in there did you specify that you were interacting with a database and you were looking to lower the amount of interactions. Dynamic items callbacks is a feature that exists in pretty much all of the softwares and graphical interface packages out there. You seem to not be aware that you can cache results in a variable once you've retrieved it from your database. $\endgroup$
    – Gorgious
    Feb 13, 2023 at 17:12
  • 1
    $\begingroup$ I would not be surprised if trigerring the callback literally cost nanoseconds of computing time compared to retrieving the items from a member variable. $\endgroup$
    – Gorgious
    Feb 13, 2023 at 17:15

You must log in to answer this question.

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