Bool property toggle the state of another bool property?

I’ve created a menu which displays three bool properties. These properties are settings later used for an operator which exists as a button for users to click on. When one of these three properties is clicked I need it to toggle the other two off before the user ever clicks on the operator. Here’s what the properties look like set up in a property group.

class myProperties(bpy.types.PropertyGroup):
    wm = bpy.types.WindowManager
    
    wm.mySetting1 = bpy.props.BoolProperty()
    wm.mySetting2 = bpy.props.BoolProperty()
    wm.mySetting3 = bpy.props.BoolProperty()

First I tried creating an update function for the properties to use so that when you chose one setting it would automatically turn the other two.



def settingsSwitch(self, context):
    wm = bpy.context.window_manager
    
    if wm.mySetting1:
        wm.mySetting2 = False
        wm.mySetting3 = False

    if wm.mySetting2:
        wm.mySetting1 = False
        wm.mySetting3 = False

    if wm.mySetting3:
        wm.mySetting1 = False
        wm.mySetting2 = False

class myProperties(bpy.types.PropertyGroup):
    wm = bpy.types.WindowManager
    
    wm.mySetting1 = bpy.props.BoolProperty(update = settingsSwitch)
    wm.mySetting2 = bpy.props.BoolProperty(update = settingsSwitch)
    wm.mySetting3 = bpy.props.BoolProperty(update = settingsSwitch)

But this caused Blender to crash every time. Then I investigated BoolVectorProperty thinking I could use it to toggle between the three states but I can’t get the BoolVectorProperty to show up in a menu? And even when I use attr: “toggle” on the BoolVectorProperty it does not seem to automatically change the other two states to False when one is changed to True via the console (since I can’t even get the BoolVectorProperty to display in the user interface).

What’s the easiest way to display three bools in a menu which when you click on one, it automatically switches the other two off? If anyone is confused by my ramblings, please let me know I’ll try to explain better if you think you can help. THANKS!

Why are you creating a wm variable in the update when you are given self?

Have you tried self.mySettings2 = False instead?

Indeed I was creating an unnecessary step for myself Atom. Thank you, as this will help shorten my code across the board. However it’s still causing Blender to crash but I’m not sure why.

For clarity’s sake, I mean it’s causing Blender to crash when I click on a setting in the menu when I have my bool properties set to update a function where in that function turns the other bool property settings on or off. I wonder if it’s because they’re all displayed in the same menu and the menu just isn’t designed to re-draw the check marks of the different settings?

Why don’t you use an EnumProperty?

An Enum would work, you have 9 possible options…right?

@Atom, I’m not sure what you mean by nine. At any given time I only want one of the three settings available for use with the operator they are made for. So if MySetting1 is true all others must be false, if MySetting2 is true then all others must be false etc… Sorry if I misunderstood what you meant.

@Atom and CoDEmanX, using an Enum property sounds good. I’m not sure how to use an Enum property though. Looking at the API the only difference I see is the “items” bit which I’m not sure how I’d use. How would I make the Enum property and how would I access it in the UI. For instance, here is how I’m accessing the bool properties in the UI:

row.prop(wm, “MySetting1”, text = ‘Setting One’)
row.prop(wm, “MySetting2”, text = ‘Setting Two’)
row.prop(wm, “MySetting3”, text = ‘Setting Three’)

Thank you both for your help.

Here’s an example:

import bpy


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Hello World Panel"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"
    
    def draw_header(self, context):
        self.layout.label(context.object.my_enum, icon='TRIA_RIGHT')

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

        ob = context.object

        col = layout.column()
        col.label("As dropdown:")
        col.prop(ob, "my_enum")
        
        col.separator()
        col.label("Expanded, in column:")
        col.prop(ob, "my_enum", expand=True)
        
        layout.label("Expanded, in row:")
        row = layout.row()
        row.prop(ob, "my_enum", expand=True)


def register():
    bpy.utils.register_module(__name__)
    
    bpy.types.Object.my_enum = bpy.props.EnumProperty(
        items=(
            ('ONE', "One", ""),
            ('TWO', "Two", ""),
            ('THREE', "Three", "")
        ),
        default='TWO'
    )


def unregister():
    bpy.utils.unregister_module(__name__)
    del bpy.types.Object.my_enum


if __name__ == "__main__":
    register()


The crash is because you modify the property inside of the update= function, which causes another call to the update= function and so on until blender crashes.
There isn’t any recursion protection for the update function for bpy.props

Also use an enum as already pointed out above.

@Linusy Ahh, that makes sense.

@CoDEmanX Thanks! Good to have another tool like this at my disposal, appreciate the really good example.

why all those ‘hello world’ piece of… thing, never work ???
:face_with_symbols_over_mouth:

my bad !!!

it works ! even if not what i want. The menu was hidden under other menus…
sorry :face_with_thermometer:

EDIT: it appears this piece of code works only in properties window and won’t work in ‘IMAGE_EDITOR’ window as UI…
i have no damn idea why :((