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?
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:
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()