Sounds to me like you want a CollectionProperty plus presets?
Here’s a complex example:
import bpy
from bpy.props import *
sire_items = (
('s', "Scale", ""),
('i', "Inset", ""),
('r', "Rotate", ""),
('e', "Extrude", "")
)
sire_items_dict = {}
for identifier, label, description in sire_items:
sire_items_dict[identifier] = label
sire_step_presets_dict = {
'BASIC_1': ("Basic 1", "Base preset",
(
{
'name': 'Scale',
'val': 1.67,
},
{
'name': 'Rotate',
'val': -0.5,
'rot': 'ccw',
}
)
),
'BASIC_2': ("Basic 2", "Another preset",
(
{
'name': 'Inset',
'val': 22.2,
'other': 'out',
},
{
'name': 'Rotate',
'val': 4.4,
}
)
)
}
sire_step_presets = [(identifier, label, description) for identifier, (label, description, settings) in sire_step_presets_dict.items()]
class SireStep(bpy.types.PropertyGroup):
name = StringProperty()
trans = EnumProperty(items=sire_items) # default 's' required?
val = FloatProperty(min=0.001, soft_max=1000, default=1.0, precision=3)
rot = EnumProperty(items=(
('cw', 'CW', ''),
('ccw', 'CCW', '')),
name="Rotation" # name required if enum expanded, or labels will be missing
)
other = EnumProperty(items=(
('in', 'In', ''),
('out', 'Out', '')),
name="Other"
)
class Sire(bpy.types.PropertyGroup):
type_add = EnumProperty(
items=sire_items,
name = "some name",
default = 's'
)
steps = CollectionProperty(type=SireStep, name="Sire Step")
index = IntProperty() # min/max/default?
class SIRE_UL_steplist(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
# draw_item must handle the three layout types... Usually 'DEFAULT' and 'COMPACT' can share the same code.
if self.layout_type in {'DEFAULT', 'COMPACT'}:
row = layout.row(align=True)
row.label(item.name)
row.prop(item, "val", text="")
sub = row.row(align=True)
sub.scale_x = 0.4
if item.name == sire_items_dict['r']:
sub.prop(item, "rot", expand=True)
else:
sub.prop(item, "other", expand=True) # if not expanded, use text=""
# 'GRID' layout type should be as compact as possible (typically a single icon!).
elif self.layout_type in {'GRID'}:
layout.alignment = 'CENTER'
layout.label("", icon_value=icon)
# ------ operator 0 ------ add item to collection
class VIEW3D_OT_sire_step_add(bpy.types.Operator):
bl_idname = 'view3d.sire_step_add'
bl_label = 'Add'
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
@classmethod
def poll(cls, context):
return (context.active_object and
context.active_object.type == 'MESH' and
context.mode == 'EDIT_MESH')
def execute(self, context):
steps = context.scene.sire.steps
step = steps.add()
step.name = sire_items_dict[context.scene.sire.type_add]
context.scene.sire.index = len(steps) - 1
return {'FINISHED'}
# ------ operator 1 ------ remove item from collection
class VIEW3D_OT_sire_step_remove(bpy.types.Operator):
bl_idname = 'view3d.sire_step_remove'
bl_label = 'Remove'
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
@classmethod
def poll(cls, context):
return (context.active_object and
context.active_object.type == 'MESH' and
context.mode == 'EDIT_MESH' and
len(context.scene.sire.steps) > 0)
def execute(self, context):
idx = context.scene.sire.index
move_idx = len(context.scene.sire.steps) - 1 == idx
context.scene.sire.steps.remove(idx)
if move_idx:
context.scene.sire.index -= 1
return {'FINISHED'}
# ------ operator 2 ------ move item up
class VIEW3D_OT_sire_step_moveup(bpy.types.Operator):
bl_idname = 'view3d.sire_step_moveup'
bl_label = 'Move up'
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
@classmethod
def poll(cls, context):
return (context.active_object and
context.active_object.type == 'MESH' and
context.mode == 'EDIT_MESH' and
len(context.scene.sire.steps) > 0 and
context.scene.sire.index > 0)
def draw(self, context):
layout = self.layout
def execute(self, context):
idx = context.scene.sire.index
context.scene.sire.steps.move(idx, idx-1)
context.scene.sire.index -= 1
return {'FINISHED'}
# ------ operator 3 ------ move item down
class VIEW3D_OT_sire_step_movedown(bpy.types.Operator):
bl_idname = 'view3d.sire_step_movedown'
bl_label = 'Move down'
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
@classmethod
def poll(cls, context):
return (context.active_object and
context.active_object.type == 'MESH' and
context.mode == 'EDIT_MESH' and
len(context.scene.sire.steps) > 0 and
context.scene.sire.index < len(context.scene.sire.steps) - 1)
def execute(self, context):
idx = context.scene.sire.index
context.scene.sire.steps.move(idx, idx+1)
context.scene.sire.index += 1
return {'FINISHED'}
class VIEW3D_OT_sire_step_clear(bpy.types.Operator):
bl_idname = 'view3d.sire_step_clear'
bl_label = 'Clear all'
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
def execute(self, context):
context.scene.sire.steps.clear()
return {'FINISHED'}
class VIEW3D_OT_sire_step_preset(bpy.types.Operator):
bl_idname = 'view3d.sire_step_preset'
bl_label = 'Add Preset Steps'
bl_options = {'REGISTER', 'UNDO', 'INTERNAL'}
preset = bpy.props.EnumProperty(items=sire_step_presets)
def execute(self, context):
steps = context.scene.sire.steps
label, description, settings = sire_step_presets_dict[self.preset]
for elem in settings:
item = steps.add()
for k, v in elem.items():
setattr(item, k, v)
context.scene.sire.index = len(steps) - 1
return {'FINISHED'}
class VIEW3D_MT_sire_specials(bpy.types.Menu):
bl_label = "Specials"
bl_idname = "VIEW3D_MT_sire_specials"
def draw(self, context):
layout = self.layout
layout.operator("view3d.sire_step_clear", icon="X")
layout.separator()
layout.operator_enum("view3d.sire_step_preset", "preset")
class VIEW3D_PT_sire_steplist(bpy.types.Panel):
"""Tooltip"""
bl_label = "SIRE"
bl_idname = "VIEW3D_PT_sire_steplist"
bl_space_type = 'VIEW_3D'
bl_region_type = 'TOOLS'
bl_context = "mesh_edit"
def draw(self, context):
layout = self.layout
layout.prop(context.scene.sire, "type_add", expand=True)
row = layout.row()
row.template_list("SIRE_UL_steplist", "", context.scene.sire, "steps", context.scene.sire, "index", rows=4, maxrows=10)
col = row.column(align=True)
col.operator("view3d.sire_step_add", text="", icon="ZOOMIN")
col.operator("view3d.sire_step_remove", text="", icon="ZOOMOUT")
col.menu("VIEW3D_MT_sire_specials", text="", icon="DOWNARROW_HLT")
col.separator()
col.operator('view3d.sire_step_moveup', text='', icon='TRIA_UP')
col.operator('view3d.sire_step_movedown', text='', icon='TRIA_DOWN')
def register():
bpy.utils.register_module(__name__)
bpy.types.Scene.sire = PointerProperty(type=Sire)
def unregister():
bpy.utils.unregister_module(__name__)
del bpy.types.Scene.sire
if __name__ == "__main__":
register()
Shows up in T toolshelf if a mesh object is selected and in editmode. Use the specials menu to add from presets (dark arrow down).
If you have two lists:
list_1 = [‘health’, ‘health’, ‘health’]
list_2 = [‘100’, ‘25’, ‘75’]
Then use zip():
for l1, l2 in zip(list_1, list_2):
print("%s = %s" % (l1, l2))