Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorBastien Montagne <montagne29@wanadoo.fr>2013-08-29 17:34:36 +0400
committerBastien Montagne <montagne29@wanadoo.fr>2013-08-29 17:34:36 +0400
commitb7e2cd5948a437cc5c599dec966f9dfc05212aeb (patch)
tree4b11e4695c19074b217a93fbc8353794d3f86ae5 /doc
parent7e73620a980c81ce87f6f5b1621639a31281c9b5 (diff)
UIList: update examples and templates.
Diffstat (limited to 'doc')
-rw-r--r--doc/python_api/examples/bpy.types.UIList.1.py (renamed from doc/python_api/examples/bpy.types.UIList.py)5
-rw-r--r--doc/python_api/examples/bpy.types.UIList.2.py160
2 files changed, 164 insertions, 1 deletions
diff --git a/doc/python_api/examples/bpy.types.UIList.py b/doc/python_api/examples/bpy.types.UIList.1.py
index 0f4ae0703cc..97c9bb40480 100644
--- a/doc/python_api/examples/bpy.types.UIList.py
+++ b/doc/python_api/examples/bpy.types.UIList.1.py
@@ -22,7 +22,10 @@ class MATERIAL_UL_matslots_example(bpy.types.UIList):
# active item of the collection).
# active_propname is the name of the active property (use 'getattr(active_data, active_propname)').
# index is index of the current item in the collection.
- def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ # flt_flag is the result of the filtering process for this item.
+ # Note: as index and flt_flag are optional arguments, you do not have to use/declare them here if you don't
+ # need them.
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
ob = data
slot = item
ma = slot.material
diff --git a/doc/python_api/examples/bpy.types.UIList.2.py b/doc/python_api/examples/bpy.types.UIList.2.py
new file mode 100644
index 00000000000..3ffd099859a
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.UIList.2.py
@@ -0,0 +1,160 @@
+"""
+Advanced UIList Example - Filtering and Reordering
+++++++++++++++++++++++++++++++++++++++++++++++++++
+This script is an extended version of the UIList subclass used to show vertex groups. It is not used 'as is',
+because iterating over all vertices in a 'draw' function is a very bad idea for UI performances! However, it's a good
+example of how to create/use filtering/reordering callbacks.
+"""
+import bpy
+
+
+class MESH_UL_vgroups_slow(UIList):
+ # Constants (flags)
+ # Be careful not to shadow FILTER_ITEM!
+ VGROUP_EMPTY = 1 << 0
+
+ # Custom properties, saved with .blend file.
+ use_filter_empty = bpy.props.BoolProperty(name="Filter Empty", default=False, options=set(),
+ description="Whether to filter empty vertex groups")
+ use_filter_empty_reverse = bpy.props.BoolProperty(name="Reverse Empty", default=False, options=set(),
+ description="Reverse empty filtering")
+ use_filter_name_reverse = bpy.props.BoolProperty(name="Reverse Name", default=False, options=set(),
+ description="Reverse name filtering")
+
+ # This allows us to have mutually exclusive options, which are also all disable-able!
+ def _gen_order_update(name1, name2):
+ def _u(self, ctxt):
+ if (getattr(self, name1)):
+ setattr(self, name2, False)
+ return _u
+ use_order_name = bpy.props.BoolProperty(name="Name", default=False, options=set(),
+ description="Sort groups by their name (case-insensitive)",
+ update=_gen_order_update("use_order_name", "use_order_importance"))
+ use_order_importance = bpy.props.BoolProperty(name="Importance", default=False, options=set(),
+ description="Sort groups by their average weight in the mesh",
+ update=_gen_order_update("use_order_importance", "use_order_name"))
+
+ # Usual draw item function.
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index, flt_flag):
+ # Just in case, we do not use it here!
+ self.use_filter_invert = False
+
+ # assert(isinstance(item, bpy.types.VertexGroup)
+ vgroup = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ # Here we use one feature of new filtering feature: it can pass data to draw_item, through flt_flag
+ # parameter, which contains exactly what filter_items set in its filter list for this item!
+ # In this case, we show empty groups grayed out.
+ if flt_flag & self.VGROUP_EMPTY:
+ col = layout.column()
+ col.enabled = False
+ col.alignment = 'LEFT'
+ col.label(text=vgroup.name, translate=False, icon_value=icon)
+ else:
+ layout.label(text=vgroup.name, translate=False, icon_value=icon)
+ icon = 'LOCKED' if vgroup.lock_weight else 'UNLOCKED'
+ layout.prop(vgroup, "lock_weight", text="", icon=icon, emboss=False)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ if flt_flag & self.VGROUP_EMPTY:
+ layout.enabled = False
+ layout.label(text="", icon_value=icon)
+
+ def draw_filter(self, context, layout):
+ # Nothing much to say here, it's usual UI code...
+ row = layout.row()
+
+ subrow = row.row(align=True)
+ subrow.prop(self, "filter_name", text="")
+ icon = 'ZOOM_OUT' if self.use_filter_name_reverse else 'ZOOM_IN'
+ subrow.prop(self, "use_filter_name_reverse", text="", icon=icon)
+
+ subrow = row.row(align=True)
+ subrow.prop(self, "use_filter_empty", toggle=True)
+ icon = 'ZOOM_OUT' if self.use_filter_empty_reverse else 'ZOOM_IN'
+ subrow.prop(self, "use_filter_empty_reverse", text="", icon=icon)
+
+ row = layout.row(align=True)
+ row.label("Order by:")
+ row.prop(self, "use_order_name", toggle=True)
+ row.prop(self, "use_order_importance", toggle=True)
+ icon = 'TRIA_UP' if self.use_filter_orderby_invert else 'TRIA_DOWN'
+ row.prop(self, "use_filter_orderby_invert", text="", icon=icon)
+
+ def filter_items_empty_vgroups(self, context, vgroups):
+ # This helper function checks vgroups to find out whether they are empty, and what's their average weights.
+ # TODO: This should be RNA helper actually (a vgroup prop like "raw_data: ((vidx, vweight), etc.)").
+ # Too slow for python!
+ obj_data = context.active_object.data
+ ret = {vg.index: [True, 0.0] for vg in vgroups}
+ if hasattr(obj_data, "vertices"): # Mesh data
+ if obj_data.is_editmode:
+ import bmesh
+ bm = bmesh.from_edit_mesh(obj_data)
+ # only ever one deform weight layer
+ dvert_lay = bm.verts.layers.deform.active
+ fact = 1 / len(bm.verts)
+ if dvert_lay:
+ for v in bm.verts:
+ for vg_idx, vg_weight in v[dvert_lay].items():
+ ret[vg_idx][0] = False
+ ret[vg_idx][1] += vg_weight * fact
+ else:
+ fact = 1 / len(obj_data.vertices)
+ for v in obj_data.vertices:
+ for vg in v.groups:
+ ret[vg.group][0] = False
+ ret[vg.group][1] += vg.weight * fact
+ elif hasattr(obj_data, "points"): # Lattice data
+ # XXX no access to lattice editdata?
+ fact = 1 / len(obj_data.points)
+ for v in obj_data.points:
+ for vg in v.groups:
+ ret[vg.group][0] = False
+ ret[vg.group][1] += vg.weight * fact
+ return ret
+
+ def filter_items(self, context, data, propname):
+ # This function gets the collection property (as the usual tuple (data, propname)), and must return two lists:
+ # * The first one is for filtering, it must contain 32bit integers were self.bitflag_filter_item marks the
+ # matching item as filtered (i.e. to be shown), and 31 other bits are free for custom needs. Here we use the
+ # first one to mark VGROUP_EMPTY.
+ # * The second one is for reordering, it must return a list containing the new indices of the items (which
+ # gives us a mapping org_idx -> new_idx).
+ # Please note that the default UI_UL_list defines helper functions for common tasks (see its doc for more info).
+ # If you do not make filtering and/or ordering, return empty list(s) (this will be more efficient than
+ # returning full lists doing nothing!).
+ vgroups = getattr(data, propname)
+ helper_funcs = bpy.types.UI_UL_list
+
+ # Default return values.
+ flt_flags = []
+ flt_neworder = []
+
+ # Pre-compute of vgroups data, CPU-intensive. :/
+ vgroups_empty = self.filter_items_empty_vgroups(context, vgroups)
+
+ # Filtering by name
+ if self.filter_name:
+ flt_flags = helper_funcs.filter_items_by_name(self.filter_name, self.bitflag_filter_item, vgroups, "name",
+ reverse=self.use_filter_name_reverse)
+ if not flt_flags:
+ flt_flags = [self.bitflag_filter_item] * len(vgroups)
+
+ # Filter by emptiness.
+ for idx, vg in enumerate(vgroups):
+ if vgroups_empty[vg.index][0]:
+ flt_flags[idx] |= self.VGROUP_EMPTY
+ if self.use_filter_empty and self.use_filter_empty_reverse:
+ flt_flags[idx] &= ~self.bitflag_filter_item
+ elif self.use_filter_empty and not self.use_filter_empty_reverse:
+ flt_flags[idx] &= ~self.bitflag_filter_item
+
+ # Reorder by name or average weight.
+ if self.use_order_name:
+ flt_neworder = helper_funcs.sort_items_by_name(vgroups, "name")
+ elif self.use_order_importance:
+ _sort = [(idx, vgroups_empty[vg.index][1]) for idx, vg in enumerate(vgroups)]
+ flt_neworder = helper_funcs.sort_items_helper(_sort, lambda e: e[1], True)
+
+ return flt_flags, flt_neworder