1
$\begingroup$

Is it possible to do this within a bpy API - a set of boolean properties where multiple can be selected, with their own icons, right next to each other like below (from the outliner filter):

Row of adjacent toggles with individual icons

Whenever I try row(align=True) or grid_flow(align=True) with multiple boolean properties, there's still a padding/margin between them:

multiple boolean properties with space between them

Is there a way to do this with individual booleans or boolean vector properties?

Here's a sample of the code (the variables are BoolProperty type):

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

    layout.use_property_split = True

    row = layout.row(align=True)
    row.prop(scene, 'v_name',
             icon='RESTRICT_SELECT_OFF', icon_only=True)
    row.prop(scene, 'v_name2',
             icon='HIDE_OFF', icon_only=True)
$\endgroup$
2
$\begingroup$

Just pass align=True when calling the encapsulating layout element like UILayout.row(align=True), UILayout.column(align=True), or UILayout.grid_flow(align=True) to get rid of the padding:

    ...
    layout = self.layout
    row = layout.row(align=True)
    row.prop(mytool, "my_bool", icon='CAMERA_DATA', text="")
    row.prop(mytool, "my_bool", icon='CONSOLE', text="")
    row.prop(mytool, "my_bool", icon='ARMATURE_DATA', text="")
    ...

Demo based on the template from How to create a custom UI?

bl_info = {
    "name": "Add-on Template",
    "author": "p2or, brockmann",
    "version": (0, 0, 3),
    "blender": (2, 80, 0),
    "location": "3D View > Tools",
    "category": "Development"
}


import bpy

from bpy.props import BoolProperty, PointerProperty
from bpy.types import Panel, PropertyGroup

# ------------------------------------------------------------------------
#    Scene Properties
# ------------------------------------------------------------------------

class MyProperties(PropertyGroup):

    my_bool: BoolProperty(
        name="Enable or Disable",
        description="A bool property",
        default = False
        )

# ------------------------------------------------------------------------
#    Panel in Object Mode
# ------------------------------------------------------------------------

class OBJECT_PT_CustomPanel(Panel):
    bl_label = "My Panel"
    bl_idname = "OBJECT_PT_custom_panel"
    bl_space_type = "VIEW_3D"   
    bl_region_type = "UI"
    bl_category = "Tools"
    bl_context = "objectmode"   


    @classmethod
    def poll(self,context):
        return context.object is not None

    def draw(self, context):
        layout = self.layout
        scene = context.scene
        mytool = scene.my_tool
        
        # layout.use_property_split = True
        # layout.use_property_decorate = False

        row = layout.row(align=True)
        row.prop(mytool, "my_bool", icon='CAMERA_DATA', text="")
        row.prop(mytool, "my_bool", icon='CONSOLE', text="")
        row.prop(mytool, "my_bool", icon='ARMATURE_DATA', text="")
        row.prop(mytool, "my_bool", icon='OUTLINER_OB_LIGHT', text="")
        row.prop(mytool, "my_bool", icon='BOLD', text="")
        
        grid = layout.grid_flow(columns=5, align=True)
        grid.prop(mytool, "my_bool", icon='CAMERA_DATA', text="")
        grid.prop(mytool, "my_bool", icon='CONSOLE', text="")
        grid.prop(mytool, "my_bool", icon='ARMATURE_DATA', text="")
        grid.prop(mytool, "my_bool", icon='BOLD', text="")
        
        col = layout.column(align=True)
        col.prop(mytool, "my_bool", icon='CAMERA_DATA', text="")
        col.prop(mytool, "my_bool", icon='CONSOLE', text="")
        col.prop(mytool, "my_bool", icon='ARMATURE_DATA', text="")
        col.prop(mytool, "my_bool", icon='OUTLINER_OB_LIGHT', text="")
        col.prop(mytool, "my_bool", icon='BOLD', text="")
        
# ------------------------------------------------------------------------
#    Registration
# ------------------------------------------------------------------------

classes = (
    MyProperties,
    OBJECT_PT_CustomPanel
)

def register():
    from bpy.utils import register_class
    for cls in classes:
        register_class(cls)

    bpy.types.Scene.my_tool = PointerProperty(type=MyProperties)

def unregister():
    from bpy.utils import unregister_class
    for cls in reversed(classes):
        unregister_class(cls)
    del bpy.types.Scene.my_tool


if __name__ == "__main__":
    register()

Note: If you'd like to use UILayout.use_property_split, make sure you set layout.use_property_decorate to False, otherwise the panel will look like:

$\endgroup$
1
  • $\begingroup$ I had "align=True" in my case. Updated post with code sample. $\endgroup$ Sep 27 '21 at 15:18
1
$\begingroup$

Although align=True is usually the issue, I figured out it was UILayout.use_property_split in this case. I set it to "False" for the row itself and it worked as expected.

Edit: UILayout.use_property_decorate specifically adds the space for the keyframe button - I explicitly prevented these props from being animateable, so the decoration didn't show up. But the space was still made. So disabling this property also works.

$\endgroup$
5
  • 2
    $\begingroup$ You can also enable UILayout.use_property_split but disable UILayout.use_property_decorate. If I set use_property_split to true (in code above) I get these dots in between the elements: i.stack.imgur.com/ZyDKD.png (I think the screenshot in your question would look way different... Doesn't it?). Glad you have found the bug - however, impossible to guess based on your question IMHO. $\endgroup$
    – brockmann
    Sep 27 '21 at 15:33
  • $\begingroup$ @brockmann thank you for that - that also works. I had set my props to not be animateable, but it spaces them anyway even if they aren't visually decorated. I'll add that as well. $\endgroup$ Sep 27 '21 at 15:44
  • 1
    $\begingroup$ No problem. Can not confirm, no spaces here, looks like the same as without split enabled. Added as option to the demo so you can test it. $\endgroup$
    – brockmann
    Sep 27 '21 at 15:48
  • 2
    $\begingroup$ IMO since the default is False docs.blender.org/api/current/… the issue was that you set it to True, making question a bit like "There's something wrong with my dog, ... trick question it's a cat" Please always add all relevant code to questions in future. $\endgroup$
    – batFINGER
    Sep 27 '21 at 15:52
  • 1
    $\begingroup$ @batFINGER will do. I know that's my bad in not sharing enough information :/ $\endgroup$ Sep 27 '21 at 16:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.