I’m rebuilding the GUI for a plugin and I’m running across an issue that I can’t seem to figure out. I’m assuming it’s because of my own inexperience (I’m still learning), and I’ve honestly spent a ton of time trying to figure it out myself. But now I’m asking for help, maybe it’s something super simple.
This is how I’m rebuilding the GUI. Reason being, that I added more tools which made the previous layout start to seem cluttered to me. I just wanted to clean it up a little more to make it easier to work with. So I’ve worked it into the image below and I’m quite liking it. The buttons on this menu toggle the visibility of a particular tools options and run button. Each button is a custom Boolean Property.
Now the part where I’m running into issues is that I only want one of the buttons to be in the “On” state (or True) at any time. Clicking a new button would deselect the old button. As it works now, each button (which is a bool prop) can be set to be on. That makes all the tools options just keep stacking below, this gets cluttered very quickly. I only want one tool set to be visible at a time.
So ideally it would work almost exactly like the EnumProperty, which is a single property with multiple items. Problem with EnumProperty is that I don’t think you can add an icon to the Enum button or spread buttons out over multiple rows and columns. It’s important for me to keep the buttons with icons in the layout above, which enum won’t allow (as far as I can tell).
This code below is the menu and should work just copy/paste run (creates panel in toolbar menu. My attempt to make only one button, allowed to be “True”, fails horribly. That is the function “deselect_others(prop_name)”, which checks if a button is true, then sets all others to false. This did not work like and is probably sloppy anyways. That function is commented out so the code actually runs (it’s under each property). So my ultimate question, if it’s possible. How do I make it so this group of buttons can only have 1 selected at a time?
import bpy, selection_utils
from bpy.props import FloatProperty, EnumProperty, IntProperty, BoolProperty, FloatVectorProperty
# Class to define properties
class MyProps(bpy.types.PropertyGroup):
enabled = IntProperty(default=0)
tool_objectTrace = BoolProperty(name="Object Trace", default=False, description="Trace selected mesh object with a curve")
tool_objectsConnect = BoolProperty(name="Objects Connect", default=False, description="Connect objects with a curve controlled by hooks")
tool_particleTrace = BoolProperty(name="Particle Trace", default=False, description="Trace particle path with a curve")
tool_meshFollow = BoolProperty(name="Mesh Follow", default=False, description="Follow selection items on animated mesh object")
tool_particleConnect = BoolProperty(name="Particle Connect", default=False, description="Connect particles with a curves and animated over particle lifetime")
tool_handwrite = BoolProperty(name="Handwriting", default=False, description="Create and Animate curve using the grease pencil")
tool_fcurve = BoolProperty(name="F-Curve Noise", default=False, description="Add F-Curve noise to selected objects")
animation_settings = BoolProperty(name="Animation Settings", default=False, description="Show the settings for the Animations")
# Start Panel
class addMyPanel(bpy.types.Panel):
bl_label = "Menu"
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
bl_context = 'objectmode'
def draw(self, context):
layout = self.layout
mypropslist = bpy.context.window_manager.custom_props
def deselect_others(prop_name): #This is the attempt to deselect the others
mytools = [mypropslist.tool_objectTrace, mypropslist.tool_objectsConnect, mypropslist.tool_meshFollow, mypropslist.tool_handwrite, mypropslist.tool_particleTrace, mypropslist.tool_particleConnect, mypropslist.animation_settings, mypropslist.tool_fcurve]
mytoolsnames = ['tool_objectTrace', 'tool_objectsConnect', 'tool_meshFollow', 'tool_handwrite', 'tool_particleTrace', 'tool_particleConnect', 'animation_settings', 'tool_fcurve']
if mypropslist[prop_name]:
index = mytoolsnames.index(prop_name)
mytoolsnames.pop(index)
for i in mytoolsnames:
mypropslist[i] = False
col = self.layout.column(align=True)
row = col.row()
row.prop(mypropslist, "tool_objectTrace", text="Ojbect Trace", icon="FORCE_MAGNETIC")
# deselect_others("tool_objectTrace") # Deselect all others if true
row.prop(mypropslist, "tool_objectsConnect", text="Object Connect", icon="OUTLINER_OB_EMPTY")
# deselect_others("tool_objectsConnect") # Deselect all others if true
row = col.row()
row.prop(mypropslist, "tool_meshFollow", text="Mesh Follow", icon="DRIVER")
# deselect_others("tool_meshFollow") # Deselect all others if true
row.prop(mypropslist, "tool_handwrite", text="Handwriting", icon='BRUSH_DATA')
# deselect_others("tool_handwrite") # Deselect all others if true
row = col.row()
row.prop(mypropslist, "tool_particleTrace", icon="PARTICLES", text="Particle Trace")
# deselect_others("tool_particleTrace") # Deselect all others if true
row.prop(mypropslist, "tool_particleConnect", icon="MOD_PARTICLES", text="Particle Connect")
# deselect_others("tool_particleConnect") # Deselect all others if true
row = col.row()
row.prop(mypropslist, "animation_settings", icon="META_BALL", text="Grow Animation")
# deselect_others("animation_settings") # Deselect all others if true
row.prop(mypropslist, "tool_fcurve", text="Fcurve Noise", icon='RNDCURVE')
# deselect_others("tool_fcurve") # Deselect all others if true
### Define Classes to register
classes = [MyProps,
addMyPanel
]
def register():
for c in classes:
bpy.utils.register_class(c)
bpy.types.WindowManager.custom_props = bpy.props.PointerProperty(type=MyProps)
def unregister():
for c in classes:
bpy.utils.unregister_class(c)
del bpy.types.WindowManager.custom_props
if __name__ == "__main__":
register()
Any advice would be much appreciated! :o