3
$\begingroup$

I would like to achieve the layout of this panel but I'm having some issues. The example is from blender's Bevel Operator. As far as I can tell it's just an Enum Property without the enum_flag since only Vertices or Edges can be selected at a time:

enter image description here

First attempt:

layout = self.layout
row = layout.row()
row.label(text='My Prop');  row.prop(self, 'enum_prop', expand=True)

Looks pretty similar, just gotta align the label to the right.

enter image description here

Second Attempt:

layout = self.layout
row = layout.row()
split = row.split(factor=0.4)

left_col  = split.column(align=True)
right_col = split.column(align=True)
        
left_col.alignment  = 'RIGHT'
right_col.alignment = 'CENTER'

left_col.label(text='My Prop'); right_col.prop(self, 'enum_prop', expand=True)

enter image description here

Well, I managed to align things into columns but my Enum Prop is suddenly vertical. I figured I wasn't giving it enough room with the Split factor but that wasn't the case. How can I achieve the result from the first image?

(Label aligned to the Right + Horizontal Enum Prop)

EXTRA INFO:

If anyone is wondering, here is how I created the property:

enum_items = [  ('ON',  'On',  'Description1'), 
                ('OFF', 'Off', 'Description2')]
                            
enum_prop: EnumProperty(name='My Prop', default='OFF', items=enum_items)
$\endgroup$
4
$\begingroup$

Just set layout.use_property_split property in your draw method to True:

def draw(self, context):
    layout = self.layout
    layout.use_property_split = True
    layout.use_property_decorate = False  # No animation.
    ...

Custom Panel

Example based on the add-on template from: How to create a custom UI?

enter image description here

bl_info = {
    "name": "Add-on Template",
    "description": "",
    "author": "p2or, brockmann",
    "version": (0, 0, 3),
    "blender": (2, 80, 0),
    "location": "3D View > Tools",
    "warning": "", # used for warning icon and text in addons panel
    "wiki_url": "",
    "tracker_url": "",
    "category": "Development"
}


import bpy

from bpy.props import (StringProperty,
                       BoolProperty,
                       IntProperty,
                       FloatProperty,
                       FloatVectorProperty,
                       EnumProperty,
                       PointerProperty,
                       )
from bpy.types import (Panel,
                       Menu,
                       Operator,
                       PropertyGroup,
                       )


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

class MyProperties(PropertyGroup):

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

    my_int: IntProperty(
        name = "Int Value",
        description="A integer property",
        default = 23,
        min = 10,
        max = 100
        )

    my_float: FloatProperty(
        name = "Float Value",
        description = "A float property",
        default = 23.7,
        min = 0.01,
        max = 30.0
        )

    my_float_vector: FloatVectorProperty(
        name = "Float Vector Value",
        description="Something",
        default=(0.0, 0.0, 0.0), 
        min= 0.0, # float
        max = 0.1
    ) 

    my_string: StringProperty(
        name="User Input",
        description=":",
        default="",
        maxlen=1024,
        )

    my_path: StringProperty(
        name = "Directory",
        description="Choose a directory:",
        default="",
        maxlen=1024,
        subtype='DIR_PATH'
        )

    my_enum: EnumProperty(
        name="Dropdown:",
        description="Apply Data to attribute.",
        items=[ ('OP1', "Option 1", ""),
                ('OP2', "Option 2", ""),
               ]
        )

# ------------------------------------------------------------------------
#    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
        layout.use_property_split = True
        layout.use_property_decorate = False  # No animation.

        scene = context.scene
        mytool = scene.my_tool

        layout.prop(mytool, "my_bool")
        layout.prop(mytool, "my_enum", expand=True)
        layout.prop(mytool, "my_int")
        layout.prop(mytool, "my_float")
        layout.prop(mytool, "my_float_vector")
        layout.prop(mytool, "my_string")
        layout.prop(mytool, "my_path")


# ------------------------------------------------------------------------
#    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()

Custom Operator

It's basically the same for the redo panel, you would have to create an extra row though:

enter image description here

import bpy


class SimpleOperator(bpy.types.Operator):
    """Tooltip"""
    bl_idname = "object.simple_operator"
    bl_label = "Simple Object Operator"
    bl_options = {'REGISTER', 'UNDO'}
    
    my_enum: bpy.props.EnumProperty(
        name="Dropdown:",
        description="Apply Data to attribute.",
        items=[ ('OP1', "Option 1", ""),
                ('OP2', "Option 2", "")])
                
    my_float: bpy.props.FloatProperty(
        name = "Float Value",
        description = "A float property",
        default = 23.7,
        min = 0.01,
        max = 30.0)
        
        
    @classmethod
    def poll(cls, context):
        return context.active_object is not None

    def execute(self, context):
        print(self.bl_idname)
        return {'FINISHED'}

    def draw(self, context):
        layout = self.layout
        layout.use_property_split = True
        layout.use_property_decorate = False  # No animation.

        row = layout.row(align=True)
        row.prop(self, "my_enum", expand=True)
        layout.prop(self, "my_float")

    
def register():
    bpy.utils.register_class(SimpleOperator)


def unregister():
    bpy.utils.unregister_class(SimpleOperator)


if __name__ == "__main__":
    register()

    # test call
    #bpy.ops.object.simple_operator()
$\endgroup$
2
  • $\begingroup$ Thanks, it works perfectly. I will study the link you shared more closely. Blender's built-in templates were not as helpful. Thanks again! $\endgroup$ Nov 9 '20 at 15:25
  • $\begingroup$ Glad I could help @ArmoredWolf $\endgroup$
    – brockmann
    Nov 9 '20 at 16:03

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.