test_template_list.py
# ##### BEGIN GPL LICENSE BLOCK #####
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# ##### END GPL LICENSE BLOCK #####
# Blender2.77a
import bpy
def creat_not_jyuufuku_name(name, name_set, num):
new_name = ""
if '.' in name:
split_name = name.split('.')
if split_name[-1].isdigit():
new_name = ".".join(split_name[0:-1]) + ".{:03d}".format(num)
else:
if split_name[-1] == "":
new_name = name + "{:03d}".format(num)
else:
new_name = ".".join(split_name) + ".{:03d}".format(num)
else:
new_name = name + ".{:03d}".format(num)
if new_name in name_set:
return creat_not_jyuufuku_name(new_name, name_set, num+1)
return new_name
def get_my_string(self):
return self["name"]
def set_my_string(self, value):
self["name"] = value
tl = bpy.context.window_manager.test_ui_list.test_list
if len(tl) > 1:
s = set()
result = [x.name for x in tl if x.name in s or s.add(x.name)]
if len(result):
number = 1
self["name"] = creat_not_jyuufuku_name(value, s, 1)
class MyTestGroup(bpy.types.PropertyGroup):
name = bpy.props.StringProperty(get=get_my_string, set=set_my_string)
int_val = bpy.props.IntProperty()
bpy.utils.register_class(MyTestGroup)
class MyCollectionProperty(bpy.types.PropertyGroup):
active_index = bpy.props.IntProperty()
test_list = bpy.props.CollectionProperty(type=bpy.types.MyTestGroup)
def add(self):
item = self.test_list.add()
item.name = "name"
item.int_val = 10
self.active_index = len(self.test_list)-1
def remove(self):
if len(self.test_list):
self.test_list.remove(self.active_index)
if len(self.test_list)-1 < self.active_index:
self.active_index = len(self.test_list)-1
if self.active_index < 0:
self.active_index = 0
def move(self, index1, index2):
if len(self.test_list) < 2:
return
if 0 <= index1 < len(self.test_list):
if 0 <= index2 < len(self.test_list):
self.test_list.move(index1, index2)
self.active_index = index2
def clear(self):
self.test_list.clear()
class MyUIListAddItemOperator(bpy.types.Operator):
bl_idname = "view3d.my_uilist_add_item"
bl_label = "Add Item"
def execute(self, context):
context.window_manager.test_ui_list.add()
return {'FINISHED'}
class MyUIListRemoveItemOperator(bpy.types.Operator):
bl_idname = "view3d.my_uilist_remove_item"
bl_label = "Remove Item"
def execute(self, context):
context.window_manager.test_ui_list.remove()
return {'FINISHED'}
class MyUIListMoveItemOperator(bpy.types.Operator):
bl_idname = "view3d.my_uilist_move_item"
bl_label = "Move Item"
type = bpy.props.StringProperty(default='UP')
def execute(self, context):
ui_list = context.window_manager.test_ui_list
if self.type == 'UP':
ui_list.move(ui_list.active_index, ui_list.active_index-1)
elif self.type == 'DOWN':
ui_list.move(ui_list.active_index, ui_list.active_index+1)
return {'FINISHED'}
class MyUIListClearItemOperator(bpy.types.Operator):
bl_idname = "view3d.my_uilist_clear_item"
bl_label = "Clear Item"
def execute(self, context):
context.window_manager.test_ui_list.clear()
return {'FINISHED'}
class MY_UL_test_group_list(bpy.types.UIList):
def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
if self.layout_type in {'DEFAULT', 'COMPACT'}:
layout.prop(item, "name", text="", emboss=False, icon_value=icon)
elif self.layout_type == 'GRID':
layout.alignment = 'CENTER'
layout.label(text="", icon_value=icon)
class UIListTestPanel(bpy.types.Panel):
bl_label = "UIList Test Panel"
bl_idname = "VIEW3D_PT_ui_list_test"
bl_space_type = "VIEW_3D"
bl_region_type = "UI"
def draw(self, context):
layout = self.layout
ui_list = context.window_manager.test_ui_list
row = layout.row()
col = row.column()
col.template_list("MY_UL_test_group_list", "", ui_list, "test_list", ui_list, "active_index", rows=1)
col = row.column(align=True)
col.operator("view3d.my_uilist_add_item", icon='ZOOMIN', text="")
col.operator("view3d.my_uilist_remove_item", icon='ZOOMOUT', text="")
col.operator("view3d.my_uilist_move_item", icon='TRIA_UP', text="").type = 'UP'
col.operator("view3d.my_uilist_move_item", icon='TRIA_DOWN', text="").type = 'DOWN'
layout.operator("view3d.my_uilist_clear_item", text="All Clear")
if len(ui_list.test_list):
row = layout.row()
row.prop(ui_list.test_list[ui_list.active_index], "name")
row = layout.row()
row.prop(ui_list.test_list[ui_list.active_index], "int_val")
def register():
bpy.utils.register_class(MyCollectionProperty)
bpy.utils.register_class(MyUIListAddItemOperator)
bpy.utils.register_class(MyUIListRemoveItemOperator)
bpy.utils.register_class(MyUIListMoveItemOperator)
bpy.utils.register_class(MyUIListClearItemOperator)
bpy.utils.register_class(MY_UL_test_group_list)
bpy.utils.register_class(UIListTestPanel)
bpy.types.WindowManager.test_ui_list = bpy.props.PointerProperty(type=MyCollectionProperty)
def unregister():
del bpy.types.WindowManager.test_ui_list
bpy.utils.unregister_class(UIListTestPanel)
bpy.utils.unregister_class(MY_UL_test_group_list)
bpy.utils.unregister_class(MyUIListAddItemOperator)
bpy.utils.unregister_class(MyUIListRemoveItemOperator)
bpy.utils.unregister_class(MyUIListMoveItemOperator)
bpy.utils.unregister_class(MyUIListClearItemOperator)
bpy.utils.unregister_class(MyCollectionProperty)
#bpy.utils.unregister_class(MyTestGroup)
if __name__ == "__main__":
register()
Copy and paste it into a text editor in Blender and execute it.
You can add and delete data from the + and-buttons. Move the selected item with the up and down buttons. You can delete all with the All Clear button.
A separate operator is prepared for adding and deleting data, and placed next to it so that it looks the same as other panels. When actually using it, it is better to put the remove button in a remote place.
You have to avoid duplicate names yourself.
It seems that the contents of the list are displayed at draw_item () of the MY_UL_test_group_list class. You can display it by changing "name" to "int_val".
The place where you can change directly by double-clicking is the same.
I don't think I have much chance to use template_list (), but I needed it a little, so I tried to find out how to use it.
move ()
and clear ()
of Collection Property
as buttons.Recommended Posts