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
diff options
context:
space:
mode:
-rw-r--r--release/scripts/modules/bpy_types.py4
-rw-r--r--release/scripts/startup/bl_ui/__init__.py6
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py62
-rw-r--r--release/scripts/startup/bl_ui/properties_mask_common.py23
-rw-r--r--release/scripts/startup/bl_ui/properties_material.py24
-rw-r--r--release/scripts/startup/bl_ui/properties_particle.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_common.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py27
-rw-r--r--release/scripts/startup/bl_ui/properties_render.py22
-rw-r--r--release/scripts/startup/bl_ui/properties_scene.py19
-rw-r--r--release/scripts/startup/bl_ui/properties_texture.py21
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py19
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py6
-rw-r--r--source/blender/blenkernel/BKE_screen.h18
-rw-r--r--source/blender/blenloader/intern/readfile.c9
-rw-r--r--source/blender/blenloader/intern/writefile.c4
-rw-r--r--source/blender/editors/include/UI_interface.h7
-rw-r--r--source/blender/editors/include/UI_interface_icons.h3
-rw-r--r--source/blender/editors/interface/interface_handlers.c87
-rw-r--r--source/blender/editors/interface/interface_icons.c39
-rw-r--r--source/blender/editors/interface/interface_intern.h3
-rw-r--r--source/blender/editors/interface/interface_layout.c5
-rw-r--r--source/blender/editors/interface/interface_templates.c512
-rw-r--r--source/blender/editors/space_node/drawnode.c4
-rw-r--r--source/blender/makesdna/DNA_screen_types.h30
-rw-r--r--source/blender/makesrna/RNA_access.h2
-rw-r--r--source/blender/makesrna/RNA_enum_types.h3
-rw-r--r--source/blender/makesrna/intern/rna_dynamicpaint.c22
-rw-r--r--source/blender/makesrna/intern/rna_ui.c164
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c194
-rw-r--r--source/blender/python/intern/bpy_rna.c5
-rw-r--r--source/blender/windowmanager/WM_api.h7
-rw-r--r--source/blender/windowmanager/intern/wm.c58
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
-rw-r--r--source/blenderplayer/bad_level_call_stubs/stubs.c4
36 files changed, 974 insertions, 457 deletions
diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py
index 11e1115fa4c..1c861aa3be2 100644
--- a/release/scripts/modules/bpy_types.py
+++ b/release/scripts/modules/bpy_types.py
@@ -673,6 +673,10 @@ class Panel(StructRNA, _GenericUI, metaclass=RNAMeta):
__slots__ = ()
+class UIList(StructRNA, _GenericUI, metaclass=RNAMeta):
+ __slots__ = ()
+
+
class Header(StructRNA, _GenericUI, metaclass=RNAMeta):
__slots__ = ()
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index e4be84d5396..aa1a8a9a25b 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -132,3 +132,9 @@ def register():
def unregister():
bpy.utils.unregister_module(__name__)
+
+# Define a default UIList, when a list does not need any custom drawing...
+class UI_UL_list(bpy.types.UIList):
+ pass
+
+bpy.utils.register_class(UI_UL_list)
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 845beb0f862..1643210704e 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -124,7 +124,7 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, Panel):
rows = 2
if group:
rows = 5
- row.template_list(pose, "bone_groups", pose.bone_groups, "active_index", rows=rows)
+ row.template_list("UI_UL_list", "", pose, "bone_groups", pose.bone_groups, "active_index", rows=rows)
col = row.column(align=True)
col.active = (ob.proxy is None)
@@ -184,7 +184,7 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
if poselib:
# list of poses in pose library
row = layout.row()
- row.template_list(poselib, "pose_markers", poselib.pose_markers, "active_index", rows=5)
+ row.template_list("UI_UL_list", "", poselib, "pose_markers", poselib.pose_markers, "active_index", rows=5)
# column of operators for active pose
# - goes beside list
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index e33bed7ec6d..7a7c847f040 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
from rna_prop_ui import PropertyPanel
@@ -54,6 +54,57 @@ class MESH_MT_shape_key_specials(Menu):
layout.operator("object.shape_key_add", icon='ZOOMIN', text="New Shape From Mix").from_mix = True
+class MESH_UL_vgroups(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ if not isinstance(item, bpy.types.VertexGroup):
+ return
+ vgroup = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(vgroup.name, 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'
+ layout.label("", icon_value=icon)
+
+
+class MESH_UL_shape_keys(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ if not isinstance(item, bpy.types.ShapeKey):
+ return
+ obj = active_data
+ key = data
+ key_block = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ split = layout.split(0.66, False)
+ split.label(item.name, icon_value=icon)
+ row = split.row(True)
+ if key_block.mute or (obj.mode == 'EDIT' and not (obj.use_shape_key_edit_mode and obj.type == 'MESH')):
+ row.active = False
+ if not item.relative_key or index > 0:
+ row.prop(key_block, "value", text="", emboss=False)
+ else:
+ row.label("")
+ row.prop(key_block, "mute", text="", emboss=False)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon)
+
+
+class MESH_UL_uvmaps_vcols(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ if not isinstance(item, (bpy.types.MeshTexturePolyLayer, bpy.types.MeshLoopColorLayer)):
+ print(item.__class__)
+ return
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(item.name, icon_value=icon)
+ icon = 'RESTRICT_RENDER_OFF' if item.active_render else 'RESTRICT_RENDER_ON'
+ layout.prop(item, "active_render", text="", icon=icon, emboss=False)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon)
+
+
class MeshButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
@@ -144,7 +195,8 @@ class DATA_PT_vertex_groups(MeshButtonsPanel, Panel):
rows = 5
row = layout.row()
- row.template_list(ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
+ row.template_list("MESH_UL_vgroups", "", ob, "vertex_groups", ob.vertex_groups, "active_index", rows=rows)
+
col = row.column(align=True)
col.operator("object.vertex_group_add", icon='ZOOMIN', text="")
@@ -202,7 +254,7 @@ class DATA_PT_shape_keys(MeshButtonsPanel, Panel):
rows = 2
if kb:
rows = 5
- row.template_list(key, "key_blocks", ob, "active_shape_key_index", rows=rows)
+ row.template_list("MESH_UL_shape_keys", "", key, "key_blocks", ob, "active_shape_key_index", rows=rows)
col = row.column()
@@ -282,7 +334,7 @@ class DATA_PT_uv_texture(MeshButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list(me, "uv_textures", me.uv_textures, "active_index", rows=2)
+ col.template_list("MESH_UL_uvmaps_vcols", "", me, "uv_textures", me.uv_textures, "active_index", rows=2)
col = row.column(align=True)
col.operator("mesh.uv_texture_add", icon='ZOOMIN', text="")
@@ -305,7 +357,7 @@ class DATA_PT_vertex_colors(MeshButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list(me, "vertex_colors", me.vertex_colors, "active_index", rows=2)
+ col.template_list("MESH_UL_uvmaps_vcols", "", me, "vertex_colors", me.vertex_colors, "active_index", rows=2)
col = row.column(align=True)
col.operator("mesh.vertex_color_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py
index 208b0a63075..ea04b79357e 100644
--- a/release/scripts/startup/bl_ui/properties_mask_common.py
+++ b/release/scripts/startup/bl_ui/properties_mask_common.py
@@ -22,7 +22,25 @@
# menus are referenced `as is`
import bpy
-from bpy.types import Menu
+from bpy.types import Menu, UIList
+
+
+class MASK_UL_layers(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ if not isinstance(item, bpy.types.MaskLayer):
+ return
+ mask = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ split = layout.split()
+ split.label(mask.name, icon_value=icon)
+ row = split.row(align=True)
+ row.prop(mask, "alpha", text="", emboss=False)
+ row.prop(mask, "hide", text="", emboss=False)
+ row.prop(mask, "hide_select", text="", emboss=False)
+ row.prop(mask, "hide_render", text="", emboss=False)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon)
class MASK_PT_mask:
@@ -69,8 +87,7 @@ class MASK_PT_layers:
rows = 5 if active_layer else 2
row = layout.row()
- row.template_list(mask, "layers",
- mask, "active_layer_index", rows=rows)
+ row.template_list("MASK_UL_layers", "", mask, "layers", mask, "active_layer_index", rows=rows)
sub = row.column(align=True)
diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py
index 951644db752..df676499cfb 100644
--- a/release/scripts/startup/bl_ui/properties_material.py
+++ b/release/scripts/startup/bl_ui/properties_material.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
from rna_prop_ui import PropertyPanel
@@ -69,6 +69,26 @@ class MATERIAL_MT_specials(Menu):
layout.operator("material.paste", icon='PASTEDOWN')
+class MATERIAL_UL_matslots(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ if not isinstance(item, bpy.types.MaterialSlot):
+ return
+ ob = data
+ slot = item
+ ma = slot.material
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(ma.name if ma else "", icon_value=icon)
+ if ma and not context.scene.render.use_shading_nodes:
+ manode = ma.active_node_material
+ if manode:
+ layout.label("Node %s" % manode.name, icon_value=layout.icon(manode))
+ elif ma.use_nodes:
+ layout.label("Node <none>")
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon)
+
+
class MaterialButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
@@ -104,7 +124,7 @@ class MATERIAL_PT_context_material(MaterialButtonsPanel, Panel):
if ob:
row = layout.row()
- row.template_list(ob, "material_slots", ob, "active_material_index", rows=2)
+ row.template_list("MATERIAL_UL_matslots", "", ob, "material_slots", ob, "active_material_index", rows=2)
col = row.column(align=True)
col.operator("object.material_slot_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py
index 2c2ced5db0c..90dcf594137 100644
--- a/release/scripts/startup/bl_ui/properties_particle.py
+++ b/release/scripts/startup/bl_ui/properties_particle.py
@@ -96,7 +96,7 @@ class PARTICLE_PT_context_particles(ParticleButtonsPanel, Panel):
if ob:
row = layout.row()
- row.template_list(ob, "particle_systems", ob.particle_systems, "active_index", rows=2)
+ row.template_list("UI_UL_list", "", ob, "particle_systems", ob.particle_systems, "active_index", rows=2)
col = row.column(align=True)
col.operator("object.particle_system_add", icon='ZOOMIN', text="")
@@ -636,7 +636,7 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel):
layout.label(text="Fluid interaction:")
row = layout.row()
- row.template_list(psys, "targets", psys, "active_particle_target_index")
+ row.template_list("UI_UL_list", "", psys, "targets", psys, "active_particle_target_index")
col = row.column()
sub = col.row()
@@ -702,7 +702,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
# Currently boids can only use the first state so these are commented out for now.
#row = layout.row()
- #row.template_list(boids, "states", boids, "active_boid_state_index", compact="True")
+ #row.template_list("UI_UL_list", "", boids, "states", boids, "active_boid_state_index", compact="True")
#col = row.row()
#sub = col.row(align=True)
#sub.operator("boid.state_add", icon='ZOOMIN', text="")
@@ -723,7 +723,7 @@ class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel):
row.label(text="")
row = layout.row()
- row.template_list(state, "rules", state, "active_boid_rule_index")
+ row.template_list("UI_UL_list", "", state, "rules", state, "active_boid_rule_index")
col = row.column()
sub = col.row()
@@ -886,7 +886,7 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel):
if part.use_group_count and not part.use_whole_group:
row = layout.row()
- row.template_list(part, "dupli_weights", part, "active_dupliweight_index")
+ row.template_list("UI_UL_list", "", part, "dupli_weights", part, "active_dupliweight_index")
col = row.column()
sub = col.row()
diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py
index 405e877d1e2..b70ff322765 100644
--- a/release/scripts/startup/bl_ui/properties_physics_common.py
+++ b/release/scripts/startup/bl_ui/properties_physics_common.py
@@ -85,7 +85,7 @@ def point_cache_ui(self, context, cache, enabled, cachetype):
layout.context_pointer_set("point_cache", cache)
row = layout.row()
- row.template_list(cache, "point_caches", cache.point_caches, "active_index", rows=2)
+ row.template_list("UI_UL_list", "", cache, "point_caches", cache.point_caches, "active_index", rows=2)
col = row.column(align=True)
col.operator("ptcache.add", icon='ZOOMIN', text="")
col.operator("ptcache.remove", icon='ZOOMOUT', text="")
diff --git a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
index 1df2936b2d4..b102f1b09d0 100644
--- a/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
+++ b/release/scripts/startup/bl_ui/properties_physics_dynamicpaint.py
@@ -18,13 +18,35 @@
# <pep8 compliant>
import bpy
-from bpy.types import Panel
+from bpy.types import Panel, UIList
from bl_ui.properties_physics_common import (point_cache_ui,
effector_weights_ui,
)
+class PHYSICS_UL_dynapaint_surfaces(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ if not isinstance(item, bpy.types.DynamicPaintSurface):
+ return
+ surf = item
+ sticon = layout.enum_item_icon(surf, "surface_type", surf.surface_type)
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ row = layout.row(align=True)
+ row.label(text="", icon_value=icon)
+ row.label(text=surf.name, icon_value=sticon)
+ row = layout.row(align=True)
+ if surf.use_color_preview:
+ row.prop(surf, "show_preview", text="", emboss=False,
+ icon='RESTRICT_VIEW_OFF' if surf.show_preview else 'RESTRICT_VIEW_ON')
+ row.prop(surf, "is_active", text="")
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ row = layout.row(align=True)
+ row.label(text="", icon_value=icon)
+ row.label(text="", icon_value=sticon)
+
+
class PhysicButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
@@ -58,7 +80,8 @@ class PHYSICS_PT_dynamic_paint(PhysicButtonsPanel, Panel):
surface = canvas.canvas_surfaces.active
row = layout.row()
- row.template_list(canvas, "canvas_surfaces", canvas.canvas_surfaces, "active_index", rows=2)
+ row.template_list("PHYSICS_UL_dynapaint_surfaces", "", canvas, "canvas_surfaces",
+ canvas.canvas_surfaces, "active_index", rows=2)
col = row.column(align=True)
col.operator("dpaint.surface_slot_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py
index 3fdcf946180..6f0cf6bc691 100644
--- a/release/scripts/startup/bl_ui/properties_render.py
+++ b/release/scripts/startup/bl_ui/properties_render.py
@@ -19,7 +19,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
class RENDER_MT_presets(Menu):
@@ -43,6 +43,24 @@ class RENDER_MT_framerate_presets(Menu):
draw = Menu.draw_preset
+class RENDER_UL_renderlayers(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ if not isinstance(item, bpy.types.SceneRenderLayer):
+ return
+ layer = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(layer.name, icon_value=icon)
+ layout.prop(layer, "use", text="", index=index)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon)
+
+# else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
+# uiItemL(sub, name, icon);
+# uiBlockSetEmboss(block, UI_EMBOSS);
+# uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
+# }
+
class RenderButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
@@ -84,7 +102,7 @@ class RENDER_PT_layers(RenderButtonsPanel, Panel):
rd = scene.render
row = layout.row()
- row.template_list(rd, "layers", rd.layers, "active_index", rows=2)
+ row.template_list("RENDER_UL_renderlayers", "", rd, "layers", rd.layers, "active_index", rows=2)
col = row.column(align=True)
col.operator("scene.render_layer_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py
index 518b253d0b0..100c7d93c77 100644
--- a/release/scripts/startup/bl_ui/properties_scene.py
+++ b/release/scripts/startup/bl_ui/properties_scene.py
@@ -18,10 +18,23 @@
# <pep8 compliant>
import bpy
-from bpy.types import Panel
+from bpy.types import Panel, UIList
from rna_prop_ui import PropertyPanel
+class SCENE_UL_keying_set_paths(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ if not isinstance(item, bpy.types.KeyingSetPath):
+ return
+ kspath = item
+ icon = layout.enum_item_icon(kspath, "id_type", kspath.id_type)
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(kspath.data_path, icon_value=icon)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon)
+
+
class SceneButtonsPanel():
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
@@ -107,7 +120,7 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list(scene, "keying_sets", scene.keying_sets, "active_index", rows=2)
+ col.template_list("UI_UL_list", "", scene, "keying_sets", scene.keying_sets, "active_index", rows=2)
col = row.column(align=True)
col.operator("anim.keying_set_add", icon='ZOOMIN', text="")
@@ -151,7 +164,7 @@ class SCENE_PT_keying_set_paths(SceneButtonsPanel, Panel):
row = layout.row()
col = row.column()
- col.template_list(ks, "paths", ks.paths, "active_index", rows=2)
+ col.template_list("SCENE_UL_keying_set_paths", "", ks, "paths", ks.paths, "active_index", rows=2)
col = row.column(align=True)
col.operator("anim.keying_set_path_add", icon='ZOOMIN', text="")
diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py
index e623d034b48..33b8e126398 100644
--- a/release/scripts/startup/bl_ui/properties_texture.py
+++ b/release/scripts/startup/bl_ui/properties_texture.py
@@ -18,7 +18,7 @@
# <pep8 compliant>
import bpy
-from bpy.types import Menu, Panel
+from bpy.types import Menu, Panel, UIList
from bpy.types import (Brush,
Lamp,
@@ -55,6 +55,23 @@ class TEXTURE_MT_envmap_specials(Menu):
layout.operator("texture.envmap_clear", icon='FILE_REFRESH')
layout.operator("texture.envmap_clear_all", icon='FILE_REFRESH')
+
+class TEXTURE_UL_texslots(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ if not (item is None or isinstance(item, bpy.types.MaterialTextureSlot)):
+ return
+ ma = data
+ slot = item
+ tex = slot.texture if slot else None
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(tex.name if tex else "", icon_value=icon)
+ if tex:
+ layout.prop(ma, "use_textures", text="", index=index)
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label("", icon_value=icon)
+
+
from bl_ui.properties_material import active_node_mat
@@ -142,7 +159,7 @@ class TEXTURE_PT_context_texture(TextureButtonsPanel, Panel):
if tex_collection:
row = layout.row()
- row.template_list(idblock, "texture_slots", idblock, "active_texture_index", rows=2)
+ row.template_list("TEXTURE_UL_texslots", "", idblock, "texture_slots", idblock, "active_texture_index", rows=2)
col = row.column(align=True)
col.operator("texture.slot_move", text="", icon='TRIA_UP').type = 'UP'
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index cb88226b55a..cf5b94277e7 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -19,7 +19,19 @@
# <pep8-80 compliant>
import bpy
-from bpy.types import Panel, Header, Menu
+from bpy.types import Panel, Header, Menu, UIList
+
+
+class CLIP_UL_tracking_objects(UIList):
+ def draw_item(self, context, layout, data, item, icon, active_data, active_propname, index):
+ if not (item is None or isinstance(item, bpy.types.MovieTrackingObject)):
+ return
+ tobj = item
+ if self.layout_type in {'DEFAULT', 'COMPACT'}:
+ layout.label(tobj.name, icon='CAMERA_DATA' if tobj.is_camera else 'OBJECT_DATA')
+ elif self.layout_type in {'GRID'}:
+ layout.alignment = 'CENTER'
+ layout.label("", icon='CAMERA_DATA' if tobj.is_camera else 'OBJECT_DATA')
class CLIP_HT_header(Header):
@@ -471,8 +483,7 @@ class CLIP_PT_objects(CLIP_PT_clip_view_panel, Panel):
tracking = sc.clip.tracking
row = layout.row()
- row.template_list(tracking, "objects",
- tracking, "active_object_index", rows=3)
+ row.template_list("CLIP_UL_tracking_objects", "", tracking, "objects", tracking, "active_object_index", rows=3)
sub = row.column(align=True)
@@ -728,7 +739,7 @@ class CLIP_PT_stabilization(CLIP_PT_reconstruction_panel, Panel):
layout.active = stab.use_2d_stabilization
row = layout.row()
- row.template_list(stab, "tracks", stab, "active_track_index", rows=3)
+ row.template_list("UI_UL_list", "", stab, "tracks", stab, "active_track_index", rows=3)
sub = row.column(align=True)
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index 09b32cd0c56..fb5e4a56aa1 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -1167,7 +1167,8 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
if pe.type == 'PARTICLES':
if ob.particle_systems:
if len(ob.particle_systems) > 1:
- layout.template_list(ob, "particle_systems", ob.particle_systems, "active_index", rows=2, maxrows=3)
+ layout.template_list("UI_UL_list", "", ob, "particle_systems",
+ ob.particle_systems, "active_index", rows=2, maxrows=3)
ptcache = ob.particle_systems.active.point_cache
else:
@@ -1176,7 +1177,8 @@ class VIEW3D_PT_tools_particlemode(View3DPanel, Panel):
ptcache = md.point_cache
if ptcache and len(ptcache.point_caches) > 1:
- layout.template_list(ptcache, "point_caches", ptcache.point_caches, "active_index", rows=2, maxrows=3)
+ layout.template_list("UI_UL_list", "", ptcache, "point_caches", ptcache.point_caches, "active_index",
+ rows=2, maxrows=3)
if not pe.is_editable:
layout.label(text="Point cache must be baked")
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 8aa08beec57..3c6f886b59a 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -46,6 +46,7 @@ struct bContext;
struct bContextDataResult;
struct bScreen;
struct uiLayout;
+struct uiList;
struct uiMenuItem;
struct wmKeyConfig;
struct wmNotifier;
@@ -181,6 +182,23 @@ typedef struct PanelType {
ExtensionRNA ext;
} PanelType;
+/* uilist types */
+
+/* draw an item in the uiList */
+typedef void (*uiListDrawItemFunc)(struct uiList *, struct bContext *, struct uiLayout *, struct PointerRNA *,
+ struct PointerRNA *, int, struct PointerRNA *, const char *, int);
+
+typedef struct uiListType {
+ struct uiListType *next, *prev;
+
+ char idname[BKE_ST_MAXNAME]; /* unique name */
+
+ uiListDrawItemFunc draw_item;
+
+ /* RNA integration */
+ ExtensionRNA ext;
+} uiListType;
+
/* header types */
typedef struct HeaderType {
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index e27f2464f9b..520e4fd2c39 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -5832,6 +5832,7 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc
static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
{
Panel *pa;
+ uiList *uilst;
link_list(fd, &ar->panels);
@@ -5841,7 +5842,13 @@ static void direct_link_region(FileData *fd, ARegion *ar, int spacetype)
pa->activedata = NULL;
pa->type = NULL;
}
-
+
+ link_list(fd, &ar->uiLists);
+
+ for (uilst = ar->uiLists.first; uilst; uilst = uilst->next) {
+ uilst->type = NULL;
+ }
+
ar->regiondata = newdataadr(fd, ar->regiondata);
if (ar->regiondata) {
if (spacetype == SPACE_VIEW3D) {
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 61b75a49374..1b28504700b 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2395,6 +2395,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
for (sa= sc->areabase.first; sa; sa= sa->next) {
SpaceLink *sl;
Panel *pa;
+ uiList *uilst;
ARegion *ar;
writestruct(wd, DATA, "ScrArea", 1, sa);
@@ -2404,6 +2405,9 @@ static void write_screens(WriteData *wd, ListBase *scrbase)
for (pa= ar->panels.first; pa; pa= pa->next)
writestruct(wd, DATA, "Panel", 1, pa);
+
+ for (uilst = ar->uiLists.first; uilst; uilst = uilst->next)
+ writestruct(wd, DATA, "uiList", 1, uilst);
}
sl= sa->spacedata.first;
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index 9a04138e72e..281d80a9d2b 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -56,6 +56,7 @@ struct PropertyRNA;
struct ReportList;
struct rcti;
struct rctf;
+struct uiList;
struct uiStyle;
struct uiFontStyle;
struct uiWidgetColors;
@@ -779,7 +780,7 @@ uiLayout *uiLayoutRow(uiLayout *layout, int align);
uiLayout *uiLayoutColumn(uiLayout *layout, int align);
uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align);
uiLayout *uiLayoutBox(uiLayout *layout);
-uiLayout *uiLayoutListBox(uiLayout *layout, struct PointerRNA *ptr, struct PropertyRNA *prop,
+uiLayout *uiLayoutListBox(uiLayout *layout, struct uiList *uilst, struct PointerRNA *ptr, struct PropertyRNA *prop,
struct PointerRNA *actptr, struct PropertyRNA *actprop);
uiLayout *uiLayoutAbsolute(uiLayout *layout, int align);
uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align);
@@ -825,7 +826,9 @@ void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *te
void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C);
void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr);
-void uiTemplateList(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, struct PointerRNA *activeptr, const char *activeprop, const char *prop_list, int rows, int maxrows, int type);
+void uiTemplateList(uiLayout *layout, struct bContext *C, const char *listtype_name, const char *list_id,
+ struct PointerRNA *dataptr, const char *propname, struct PointerRNA *active_dataptr,
+ const char *active_propname, int rows, int maxrows, int layout_type);
void uiTemplateNodeLink(uiLayout *layout, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
void uiTemplateNodeView(uiLayout *layout, struct bContext *C, struct bNodeTree *ntree, struct bNode *node, struct bNodeSocket *input);
void uiTemplateTextureUser(uiLayout *layout, struct bContext *C);
diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h
index aa94bdec724..f578d68b852 100644
--- a/source/blender/editors/include/UI_interface_icons.h
+++ b/source/blender/editors/include/UI_interface_icons.h
@@ -32,12 +32,14 @@
#ifndef __UI_INTERFACE_ICONS_H__
#define __UI_INTERFACE_ICONS_H__
+struct bContext;
struct Image;
struct ImBuf;
struct World;
struct Tex;
struct Lamp;
struct Material;
+struct PointerRNA;
typedef struct IconFile {
struct IconFile *next, *prev;
@@ -74,5 +76,6 @@ void UI_icons_free_drawinfo(void *drawinfo);
struct ListBase *UI_iconfile_list(void);
int UI_iconfile_get_index(const char *filename);
+int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big);
#endif /* __UI_INTERFACE_ICONS_H__ */
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index 9988224e0ab..ee6916822f0 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -44,6 +44,7 @@
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
@@ -6094,63 +6095,65 @@ static int ui_handle_list_event(bContext *C, wmEvent *event, ARegion *ar)
int value, min, max;
if (but && (event->val == KM_PRESS)) {
- Panel *pa = but->block->panel;
+ uiList *uilst = but->custom_data;
- if (ELEM(event->type, UPARROWKEY, DOWNARROWKEY) ||
- ((ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
- {
- /* activate up/down the list */
- value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
-
- if (ELEM(event->type, UPARROWKEY, WHEELUPMOUSE))
- value--;
- else
- value++;
-
- CLAMP(value, 0, pa->list_last_len - 1);
-
- if (value < pa->list_scroll)
- pa->list_scroll = value;
- else if (value >= pa->list_scroll + pa->list_size)
- pa->list_scroll = value - pa->list_size + 1;
+ if (uilst) {
+ if (ELEM(event->type, UPARROWKEY, DOWNARROWKEY) ||
+ ((ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->alt)))
+ {
+ /* activate up/down the list */
+ value = RNA_property_int_get(&but->rnapoin, but->rnaprop);
- RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
- value = CLAMPIS(value, min, max);
+ if (ELEM(event->type, UPARROWKEY, WHEELUPMOUSE))
+ value--;
+ else
+ value++;
- RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
- RNA_property_update(C, &but->rnapoin, but->rnaprop);
- ED_region_tag_redraw(ar);
+ CLAMP(value, 0, uilst->list_last_len - 1);
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
- /* silly replacement for proper grip */
- if (pa->list_grip_size == 0)
- pa->list_grip_size = pa->list_size;
+ if (value < uilst->list_scroll)
+ uilst->list_scroll = value;
+ else if (value >= uilst->list_scroll + uilst->list_size)
+ uilst->list_scroll = value - uilst->list_size + 1;
- if (event->type == WHEELUPMOUSE)
- pa->list_grip_size--;
- else
- pa->list_grip_size++;
+ RNA_property_int_range(&but->rnapoin, but->rnaprop, &min, &max);
+ value = CLAMPIS(value, min, max);
- pa->list_grip_size = MAX2(pa->list_grip_size, 1);
+ RNA_property_int_set(&but->rnapoin, but->rnaprop, value);
+ RNA_property_update(C, &but->rnapoin, but->rnaprop);
+ ED_region_tag_redraw(ar);
- ED_region_tag_redraw(ar);
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE) && event->shift) {
+ /* silly replacement for proper grip */
+ if (uilst->list_grip_size == 0)
+ uilst->list_grip_size = uilst->list_size;
- retval = WM_UI_HANDLER_BREAK;
- }
- else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
- if (pa->list_last_len > pa->list_size) {
- /* list template will clamp */
if (event->type == WHEELUPMOUSE)
- pa->list_scroll--;
+ uilst->list_grip_size--;
else
- pa->list_scroll++;
+ uilst->list_grip_size++;
+
+ uilst->list_grip_size = MAX2(uilst->list_grip_size, 1);
ED_region_tag_redraw(ar);
retval = WM_UI_HANDLER_BREAK;
}
+ else if (ELEM(event->type, WHEELUPMOUSE, WHEELDOWNMOUSE)) {
+ if (uilst->list_last_len > uilst->list_size) {
+ /* list template will clamp */
+ if (event->type == WHEELUPMOUSE)
+ uilst->list_scroll--;
+ else
+ uilst->list_scroll++;
+
+ ED_region_tag_redraw(ar);
+
+ retval = WM_UI_HANDLER_BREAK;
+ }
+ }
}
}
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index 2928a5607c0..31d1ad7a955 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -49,6 +49,7 @@
#include "BLI_utildefines.h"
#include "DNA_brush_types.h"
+#include "DNA_dynamicpaint_types.h"
#include "DNA_object_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -1179,6 +1180,44 @@ int ui_id_icon_get(bContext *C, ID *id, int big)
return iconid;
}
+int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, int big)
+{
+ ID *id = NULL;
+
+ if (!ptr->data)
+ return rnaicon;
+
+ /* try ID, material, texture or dynapaint slot */
+ if (RNA_struct_is_ID(ptr->type)) {
+ id = ptr->id.data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_MaterialSlot)) {
+ id = RNA_pointer_get(ptr, "material").data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_TextureSlot)) {
+ id = RNA_pointer_get(ptr, "texture").data;
+ }
+ else if (RNA_struct_is_a(ptr->type, &RNA_DynamicPaintSurface)) {
+ DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
+
+ if (surface->format == MOD_DPAINT_SURFACE_F_PTEX)
+ return ICON_TEXTURE_SHADED;
+ else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX)
+ return ICON_OUTLINER_DATA_MESH;
+ else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ)
+ return ICON_FILE_IMAGE;
+ }
+
+ /* get icon from ID */
+ if (id) {
+ int icon = ui_id_icon_get(C, id, big);
+
+ return icon ? icon : rnaicon;
+ }
+
+ return rnaicon;
+}
+
static void icon_draw_at_size(float x, float y, int icon_id, float aspect, float alpha, enum eIconSizes size, int nocreate)
{
int draw_size = get_draw_size(size);
diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h
index f088b3a54f4..8341307481d 100644
--- a/source/blender/editors/interface/interface_intern.h
+++ b/source/blender/editors/interface/interface_intern.h
@@ -271,6 +271,9 @@ struct uiBut {
/* active button data */
struct uiHandleButtonData *active;
+ /* Custom button data. */
+ void *custom_data;
+
char *editstr;
double *editval;
float *editvec;
diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c
index 2ba4c1355c0..19b44422ac0 100644
--- a/source/blender/editors/interface/interface_layout.c
+++ b/source/blender/editors/interface/interface_layout.c
@@ -2308,11 +2308,14 @@ uiLayout *uiLayoutBox(uiLayout *layout)
return (uiLayout *)ui_layout_box(layout, ROUNDBOX);
}
-uiLayout *uiLayoutListBox(uiLayout *layout, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr, PropertyRNA *actprop)
+uiLayout *uiLayoutListBox(uiLayout *layout, uiList *uilist, PointerRNA *ptr, PropertyRNA *prop, PointerRNA *actptr,
+ PropertyRNA *actprop)
{
uiLayoutItemBx *box = ui_layout_box(layout, LISTBOX);
uiBut *but = box->roundbox;
+ but->custom_data = uilist;
+
but->rnasearchpoin = *ptr;
but->rnasearchprop = prop;
but->rnapoin = *actptr;
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 5145c28a2cd..34f325abe76 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -31,18 +31,16 @@
#include "MEM_guardedalloc.h"
-#include "DNA_anim_types.h"
#include "DNA_dynamicpaint_types.h"
-#include "DNA_key_types.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
-#include "DNA_userdef_types.h"
#include "BLI_utildefines.h"
#include "BLI_string.h"
#include "BLI_ghash.h"
#include "BLI_rect.h"
+#include "BLF_api.h"
#include "BLF_translation.h"
#include "BKE_animsys.h"
@@ -59,6 +57,7 @@
#include "BKE_displist.h"
#include "BKE_sca.h"
#include "BKE_scene.h"
+#include "BKE_screen.h"
#include "ED_screen.h"
#include "ED_object.h"
@@ -71,11 +70,9 @@
#include "WM_types.h"
#include "UI_interface.h"
+#include "UI_interface_icons.h"
#include "interface_intern.h"
-#include "BLF_api.h"
-#include "BLF_translation.h"
-
void UI_template_fix_linking(void)
{
}
@@ -2331,254 +2328,28 @@ void uiTemplateGameStates(uiLayout *layout, PointerRNA *ptr, const char *propnam
/************************* List Template **************************/
-
-static int list_item_icon_get(bContext *C, PointerRNA *itemptr, int rnaicon, int big)
+static void uilist_draw_item_default(struct uiList *uilst, struct bContext *UNUSED(C), struct uiLayout *layout,
+ struct PointerRNA *UNUSED(dataptr), struct PointerRNA *itemptr, int icon,
+ struct PointerRNA *UNUSED(active_dataptr), const char *UNUSED(active_propname),
+ int UNUSED(index))
{
- ID *id = NULL;
- int icon;
-
- if (!itemptr->data)
- return rnaicon;
-
- /* try ID, material or texture slot */
- if (RNA_struct_is_ID(itemptr->type)) {
- id = itemptr->id.data;
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
- id = RNA_pointer_get(itemptr, "material").data;
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_TextureSlot)) {
- id = RNA_pointer_get(itemptr, "texture").data;
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_DynamicPaintSurface)) {
- DynamicPaintSurface *surface = (DynamicPaintSurface *)itemptr->data;
-
- if (surface->format == MOD_DPAINT_SURFACE_F_PTEX) return ICON_TEXTURE_SHADED;
- else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) return ICON_OUTLINER_DATA_MESH;
- else if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return ICON_FILE_IMAGE;
- }
-
- /* get icon from ID */
- if (id) {
- icon = ui_id_icon_get(C, id, big);
-
- if (icon)
- return icon;
- }
-
- return rnaicon;
-}
-
-static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, PointerRNA *itemptr, int i,
- int rnaicon, PointerRNA *activeptr, PropertyRNA *activeprop, const char *prop_list_id)
-{
- uiBlock *block = uiLayoutGetBlock(layout);
- uiBut *but;
- uiLayout *split, *overlap, *sub, *row;
char *namebuf;
const char *name;
- int icon;
-
- overlap = uiLayoutOverlap(layout);
-
- /* list item behind label & other buttons */
- sub = uiLayoutRow(overlap, FALSE);
-
- but = uiDefButR_prop(block, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr, activeprop,
- 0, 0, i, 0, 0, "");
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
-
- sub = uiLayoutRow(overlap, FALSE);
-
- /* retrieve icon and name */
- icon = list_item_icon_get(C, itemptr, rnaicon, 0);
- if (icon == ICON_NONE || icon == ICON_DOT)
- icon = 0;
namebuf = RNA_struct_name_get_alloc(itemptr, NULL, 0, NULL);
name = (namebuf) ? namebuf : "";
- /* hardcoded types */
- if (itemptr->type == &RNA_MeshTexturePolyLayer || itemptr->type == &RNA_MeshLoopColorLayer) {
- uiItemL(sub, name, icon);
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiDefIconButR(block, TOG, 0, ICON_SCENE, 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "active_render",
- 0, 0, 0, 0, 0, NULL);
- uiBlockSetEmboss(block, UI_EMBOSS);
+ /* Simplest one! */
+ switch (uilst->layout_type) {
+ case UILST_LAYOUT_GRID:
+ uiItemL(layout, "", icon);
+ break;
+ case UILST_LAYOUT_DEFAULT:
+ case UILST_LAYOUT_COMPACT:
+ default:
+ uiItemL(layout, name, icon);
+ break;
}
- else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialTextureSlot)) {
- uiItemL(sub, name, icon);
- uiBlockSetEmboss(block, UI_EMBOSS);
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, ptr, "use_textures", i, 0, 0, 0, 0, NULL);
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_SceneRenderLayer)) {
- uiItemL(sub, name, icon);
- uiBlockSetEmboss(block, UI_EMBOSS);
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "use", 0, 0, 0, 0, 0, NULL);
- }
- else if (RNA_struct_is_a(itemptr->type, &RNA_MaterialSlot)) {
- /* provision to draw active node name */
- Material *ma, *manode;
- Scene *scene = CTX_data_scene(C);
- Object *ob = (Object *)ptr->id.data;
- int index = (Material **)itemptr->data - ob->mat;
-
- /* default item with material base name */
- uiItemL(sub, name, icon);
-
- ma = give_current_material(ob, index + 1);
- if (ma && !BKE_scene_use_new_shading_nodes(scene)) {
- manode = give_node_material(ma);
- if (manode) {
- char str[MAX_ID_NAME + 12];
- BLI_snprintf(str, sizeof(str), IFACE_("Node %s"), manode->id.name + 2);
- uiItemL(sub, str, ui_id_icon_get(C, &manode->id, 1));
- }
- else if (ma->use_nodes) {
- uiItemL(sub, IFACE_("Node <none>"), ICON_NONE);
- }
- }
- }
- else if (itemptr->type == &RNA_ShapeKey) {
- Object *ob = (Object *)activeptr->data;
- Key *key = (Key *)itemptr->id.data;
- KeyBlock *kb = (KeyBlock *)itemptr->data;
-
- split = uiLayoutSplit(sub, 0.66f, FALSE);
-
- uiItemL(split, name, icon);
-
- uiBlockSetEmboss(block, UI_EMBOSSN);
- row = uiLayoutRow(split, TRUE);
- if (i == 0 || (key->type != KEY_RELATIVE)) uiItemL(row, "", ICON_NONE);
- else uiItemR(row, itemptr, "value", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "mute", 0, "", ICON_NONE);
-
- if ((kb->flag & KEYBLOCK_MUTE) ||
- (ob->mode == OB_MODE_EDIT && !((ob->shapeflag & OB_SHAPE_EDIT_MODE) && ob->type == OB_MESH)))
- {
- uiLayoutSetActive(row, FALSE);
- }
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
- else if (itemptr->type == &RNA_VertexGroup) {
- bDeformGroup *dg = (bDeformGroup *)itemptr->data;
- uiItemL(sub, name, icon);
- /* RNA does not allow nice lock icons, use lower level buttons */
-#if 0
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "lock_weight", 0, 0, 0, 0, 0, NULL);
-#else
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiDefIconButBitC(block, TOG, DG_LOCK_WEIGHT, 0, (dg->flag & DG_LOCK_WEIGHT) ? ICON_LOCKED : ICON_UNLOCKED,
- 0, 0, UI_UNIT_X, UI_UNIT_Y, &dg->flag, 0, 0, 0, 0,
- TIP_("Maintain relative weights while painting"));
- uiBlockSetEmboss(block, UI_EMBOSS);
-#endif
- }
- else if (itemptr->type == &RNA_KeyingSetPath) {
- KS_Path *ksp = (KS_Path *)itemptr->data;
-
- /* icon needs to be the type of ID which is currently active */
- RNA_enum_icon_from_value(id_type_items, ksp->idtype, &icon);
-
- /* nothing else special to do... */
- uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
- }
- else if (itemptr->type == &RNA_DynamicPaintSurface) {
- char name_final[96];
- const char *enum_name;
- PropertyRNA *prop = RNA_struct_find_property(itemptr, "surface_type");
- DynamicPaintSurface *surface = (DynamicPaintSurface *)itemptr->data;
-
- RNA_property_enum_name(C, itemptr, prop, RNA_property_enum_get(itemptr, prop), &enum_name);
-
- BLI_snprintf(name_final, sizeof(name_final), "%s (%s)", name, enum_name);
- uiItemL(sub, name_final, icon);
- if (dynamicPaint_surfaceHasColorPreview(surface)) {
- uiBlockSetEmboss(block, UI_EMBOSSN);
- uiDefIconButR(block, OPTION, 0,
- (surface->flags & MOD_DPAINT_PREVIEW) ? ICON_RESTRICT_VIEW_OFF : ICON_RESTRICT_VIEW_ON,
- 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "show_preview", 0, 0, 0, 0, 0, NULL);
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
- uiDefButR(block, OPTION, 0, "", 0, 0, UI_UNIT_X, UI_UNIT_Y, itemptr, "is_active", i, 0, 0, 0, 0, NULL);
- }
- else if (itemptr->type == &RNA_MovieTrackingObject) {
- MovieTrackingObject *tracking_object = (MovieTrackingObject *)itemptr->data;
-
- split = uiLayoutSplit(sub, 0.75f, FALSE);
- if (tracking_object->flag & TRACKING_OBJECT_CAMERA) {
- uiItemL(split, name, ICON_CAMERA_DATA);
- }
- else {
- uiItemL(split, name, ICON_OBJECT_DATA);
- }
- }
- else if (itemptr->type == &RNA_MaskLayer) {
- split = uiLayoutRow(sub, FALSE);
-
- uiItemL(split, name, icon);
-
- uiBlockSetEmboss(block, UI_EMBOSSN);
- row = uiLayoutRow(split, TRUE);
- uiItemR(row, itemptr, "alpha", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "hide", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "hide_select", 0, "", ICON_NONE);
- uiItemR(row, itemptr, "hide_render", 0, "", ICON_NONE);
-
- uiBlockSetEmboss(block, UI_EMBOSS);
- }
-
- /* There is a last chance to display custom controls (in addition to the name/label):
- * If the given item property group features a string property named as prop_list,
- * this tries to add controls for all properties of the item listed in that string property.
- * (colon-separated names).
- *
- * This is especially useful for python. E.g., if you list a collection of this property
- * group:
- *
- * class TestPropertyGroup(bpy.types.PropertyGroup):
- * bool = BoolProperty(default=False)
- * integer = IntProperty()
- * string = StringProperty()
- *
- * # A string of all identifiers (colon-separated) which property's controls should be
- * # displayed in a template_list.
- * template_list_controls = StringProperty(default="integer:bool:string", options={"HIDDEN"})
- *
- * ... you'll get a numfield for the integer prop, a check box for the bool prop, and a textfield
- * for the string prop, after the name of each item of the collection.
- */
- else if (prop_list_id) {
- row = uiLayoutRow(sub, TRUE);
- uiItemL(row, name, icon);
-
- /* XXX: Check, as sometimes we get an itemptr looking like
- * {id = {data = 0x0}, type = 0x0, data = 0x0}
- * which would obviously produce a sigsev... */
- if (itemptr->type) {
- /* If the special property is set for the item, and it is a collection... */
- PropertyRNA *prop_list = RNA_struct_find_property(itemptr, prop_list_id);
-
- if (prop_list && RNA_property_type(prop_list) == PROP_STRING) {
- int prop_names_len;
- char *prop_names = RNA_property_string_get_alloc(itemptr, prop_list, NULL, 0, &prop_names_len);
- char *prop_names_end = prop_names + prop_names_len;
- char *id = prop_names;
- char *id_next;
- while (id < prop_names_end) {
- if ((id_next = strchr(id, ':'))) *id_next++ = '\0';
- else id_next = prop_names_end;
- uiItemR(row, itemptr, id, 0, NULL, ICON_NONE);
- id = id_next;
- }
- MEM_freeN(prop_names);
- }
- }
- }
-
- else
- uiItemL(sub, name, icon); /* fails, backdrop LISTROW... */
/* free name */
if (namebuf) {
@@ -2586,177 +2357,166 @@ static void list_item_row(bContext *C, uiLayout *layout, PointerRNA *ptr, Pointe
}
}
-void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname, PointerRNA *activeptr,
- const char *activepropname, const char *prop_list, int rows, int maxrows, int listtype)
+void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id,
+ PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
+ const char *active_propname, int rows, int maxrows, int layout_type)
{
+ uiListType *ult;
+ uiList *uilst = NULL;
+ ARegion *ar;
+ uiListDrawItemFunc draw_item;
+
PropertyRNA *prop = NULL, *activeprop;
PropertyType type, activetype;
StructRNA *ptype;
- uiLayout *box, *row, *col;
- uiBlock *block;
+ uiLayout *box, *row, *col, *sub, *overlap;
+ uiBlock *block, *subblock;
uiBut *but;
- Panel *pa;
- const char *name;
+
+ char uilst_id[UI_MAX_NAME_STR];
char numstr[32];
- int rnaicon = 0, icon = 0, i = 0, activei = 0, len = 0, items, found, min, max;
+ int rnaicon = ICON_NONE, icon = ICON_NONE;
+ int i = 0, activei = 0;
+ int len = 0;
+ int items;
+ int found;
+ int min, max;
/* validate arguments */
block = uiLayoutGetBlock(layout);
- pa = block->panel;
- if (!pa) {
- RNA_warning("Only works inside a panel");
+ if (!active_dataptr->data) {
+ RNA_warning("No active data");
return;
}
- if (!activeptr->data)
- return;
-
- if (ptr->data) {
- prop = RNA_struct_find_property(ptr, propname);
+ if (dataptr->data) {
+ prop = RNA_struct_find_property(dataptr, propname);
if (!prop) {
- RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ RNA_warning("Property not found: %s.%s", RNA_struct_identifier(dataptr->type), propname);
return;
}
}
- activeprop = RNA_struct_find_property(activeptr, activepropname);
+ activeprop = RNA_struct_find_property(active_dataptr, active_propname);
if (!activeprop) {
- RNA_warning("Property not found: %s.%s", RNA_struct_identifier(ptr->type), activepropname);
+ RNA_warning("Property not found: %s.%s", RNA_struct_identifier(active_dataptr->type), active_propname);
return;
}
if (prop) {
type = RNA_property_type(prop);
if (type != PROP_COLLECTION) {
- RNA_warning("uiExpected collection property");
+ RNA_warning("Expected a collection data property");
return;
}
}
activetype = RNA_property_type(activeprop);
if (activetype != PROP_INT) {
- RNA_warning("Expected integer property");
+ RNA_warning("Expected an integer active data property");
return;
}
/* get icon */
- if (ptr->data && prop) {
- ptype = RNA_property_pointer_type(ptr, prop);
+ if (dataptr->data && prop) {
+ ptype = RNA_property_pointer_type(dataptr, prop);
rnaicon = RNA_struct_ui_icon(ptype);
}
/* get active data */
- activei = RNA_property_int_get(activeptr, activeprop);
+ activei = RNA_property_int_get(active_dataptr, activeprop);
- if (listtype == 'i') {
- box = uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
- col = uiLayoutColumn(box, TRUE);
- row = uiLayoutRow(col, FALSE);
+ /* Find the uiList type. */
+ ult = WM_uilisttype_find(listtype_name, FALSE);
- if (ptr->data && prop) {
- /* create list items */
- RNA_PROP_BEGIN (ptr, itemptr, prop)
- {
- /* create button */
- if (!(i % 9))
- row = uiLayoutRow(col, FALSE);
-
- icon = list_item_icon_get(C, &itemptr, rnaicon, 1);
- but = uiDefIconButR_prop(block, LISTROW, 0, icon, 0, 0, UI_UNIT_X * 10, UI_UNIT_Y, activeptr,
- activeprop, 0, 0, i, 0, 0, "");
- uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
-
-
- i++;
- }
- RNA_PROP_END;
- }
+ if (ult == NULL) {
+ RNA_warning("List type %s not found", listtype_name);
+ return;
}
- else if (listtype == 'c') {
- /* compact layout */
-
- row = uiLayoutRow(layout, TRUE);
- if (ptr->data && prop) {
- /* create list items */
- RNA_PROP_BEGIN (ptr, itemptr, prop)
- {
- found = (activei == i);
+ draw_item = ult->draw_item ? ult->draw_item : uilist_draw_item_default;
- if (found) {
- /* create button */
- name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL);
- icon = list_item_icon_get(C, &itemptr, rnaicon, 0);
- uiItemL(row, (name) ? name : "", icon);
+ /* Find or add the uiList to the current Region. */
+ /* We tag the list id with the list type... */
+ BLI_snprintf(uilst_id, sizeof(uilst_id), "%s_%s", ult->idname, list_id ? list_id : "");
- if (name) {
- MEM_freeN((void *)name);
- }
- }
+ ar = CTX_wm_region(C);
+ uilst = BLI_findstring(&ar->uiLists, uilst_id, offsetof(uiList, list_id));
- i++;
- }
- RNA_PROP_END;
- }
+ if (!uilst) {
+ uilst = MEM_callocN(sizeof(uiList), __func__);
+ BLI_strncpy(uilst->list_id, uilst_id, sizeof(uilst->list_id));
+ BLI_addtail(&ar->uiLists, uilst);
+ }
- /* if not found, add in dummy button */
- if (i == 0)
- uiItemL(row, "", ICON_NONE);
+ /* Because we can't actually pass type across save&load... */
+ uilst->type = ult;
+ uilst->layout_type = layout_type;
- /* next/prev button */
- BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
- but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y, activeptr,
- activeprop, 0, 0, 0, 0, 0, "");
- if (i == 0)
- uiButSetFlag(but, UI_BUT_DISABLED);
- }
- else {
+ switch (layout_type) {
+ case UILST_LAYOUT_DEFAULT:
/* default rows */
if (rows == 0)
rows = 5;
if (maxrows == 0)
maxrows = 5;
- if (pa->list_grip_size != 0)
- rows = pa->list_grip_size;
+ if (uilst->list_grip_size != 0)
+ rows = uilst->list_grip_size;
/* layout */
- box = uiLayoutListBox(layout, ptr, prop, activeptr, activeprop);
+ box = uiLayoutListBox(layout, uilst, dataptr, prop, active_dataptr, activeprop);
row = uiLayoutRow(box, FALSE);
col = uiLayoutColumn(row, TRUE);
/* init numbers */
- RNA_property_int_range(activeptr, activeprop, &min, &max);
+ RNA_property_int_range(active_dataptr, activeprop, &min, &max);
if (prop)
- len = RNA_property_collection_length(ptr, prop);
+ len = RNA_property_collection_length(dataptr, prop);
items = CLAMPIS(len, rows, MAX2(rows, maxrows));
/* if list length changes and active is out of view, scroll to it */
- if (pa->list_last_len != len)
- if ((activei < pa->list_scroll || activei >= pa->list_scroll + items))
- pa->list_scroll = activei;
+ if ((uilst->list_last_len != len) &&
+ (activei < uilst->list_scroll || activei >= uilst->list_scroll + items)) {
+ uilst->list_scroll = activei;
+ }
- pa->list_scroll = MIN2(pa->list_scroll, len - items);
- pa->list_scroll = MAX2(pa->list_scroll, 0);
- pa->list_size = items;
- pa->list_last_len = len;
+ uilst->list_scroll = MIN2(uilst->list_scroll, len - items);
+ uilst->list_scroll = MAX2(uilst->list_scroll, 0);
+ uilst->list_size = items;
+ uilst->list_last_len = len;
- if (ptr->data && prop) {
+ if (dataptr->data && prop) {
/* create list items */
- RNA_PROP_BEGIN (ptr, itemptr, prop)
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
{
- if (i >= pa->list_scroll && i < pa->list_scroll + items)
- list_item_row(C, col, ptr, &itemptr, i, rnaicon, activeptr, activeprop, prop_list);
+ if (i >= uilst->list_scroll && i < uilst->list_scroll + items) {
+ subblock = uiLayoutGetBlock(col);
+ overlap = uiLayoutOverlap(col);
+
+ /* list item behind label & other buttons */
+ sub = uiLayoutRow(overlap, FALSE);
+
+ but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, i, 0, 0, "");
+ uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+
+ sub = uiLayoutRow(overlap, FALSE);
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(uilst, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ }
i++;
}
RNA_PROP_END;
}
/* add dummy buttons to fill space */
- while (i < pa->list_scroll + items) {
- if (i >= pa->list_scroll)
+ while (i < uilst->list_scroll + items) {
+ if (i >= uilst->list_scroll)
uiItemL(col, "", ICON_NONE);
i++;
}
@@ -2764,9 +2524,75 @@ void uiTemplateList(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *
/* add scrollbar */
if (len > items) {
col = uiLayoutColumn(row, FALSE);
- uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &pa->list_scroll,
+ uiDefButI(block, SCROLL, 0, "", 0, 0, UI_UNIT_X * 0.75, UI_UNIT_Y * items, &uilst->list_scroll,
0, len - items, items, 0, "");
}
+ break;
+ case UILST_LAYOUT_COMPACT:
+ row = uiLayoutRow(layout, TRUE);
+
+ if (dataptr->data && prop) {
+ /* create list items */
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ found = (activei == i);
+
+ if (found) {
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ if (icon == ICON_DOT)
+ icon = ICON_NONE;
+ draw_item(uilst, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+ }
+
+ i++;
+ }
+ RNA_PROP_END;
+ }
+
+ /* if list is empty, add in dummy button */
+ if (i == 0)
+ uiItemL(row, "", ICON_NONE);
+
+ /* next/prev button */
+ BLI_snprintf(numstr, sizeof(numstr), "%d :", i);
+ but = uiDefIconTextButR_prop(block, NUM, 0, 0, numstr, 0, 0, UI_UNIT_X * 5, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, 0, 0, 0, "");
+ if (i == 0)
+ uiButSetFlag(but, UI_BUT_DISABLED);
+ break;
+ case UILST_LAYOUT_GRID:
+ box = uiLayoutListBox(layout, uilst, dataptr, prop, active_dataptr, activeprop);
+ col = uiLayoutColumn(box, TRUE);
+ row = uiLayoutRow(col, FALSE);
+
+ if (dataptr->data && prop) {
+ /* create list items */
+ RNA_PROP_BEGIN (dataptr, itemptr, prop)
+ {
+ /* create button */
+ if (!(i % 9))
+ row = uiLayoutRow(col, FALSE);
+
+ subblock = uiLayoutGetBlock(row);
+ overlap = uiLayoutOverlap(row);
+
+ /* list item behind label & other buttons */
+ sub = uiLayoutRow(overlap, FALSE);
+
+ but = uiDefButR_prop(subblock, LISTROW, 0, "", 0, 0, UI_UNIT_X * 10, UI_UNIT_Y,
+ active_dataptr, activeprop, 0, 0, i, 0, 0, "");
+ uiButSetFlag(but, UI_BUT_NO_TOOLTIP);
+
+ sub = uiLayoutRow(overlap, FALSE);
+
+ icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE);
+ draw_item(uilst, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i);
+
+ i++;
+ }
+ RNA_PROP_END;
+ }
+ break;
}
}
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 59dd66a0207..b702dc4c0bc 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -2152,12 +2152,12 @@ static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C
active_index = RNA_int_get(ptr, "active_input_index");
/* using different collection properties if multilayer format is enabled */
if (multilayer) {
- uiTemplateList(col, C, ptr, "layer_slots", ptr, "active_input_index", NULL, 0, 0, 0);
+ uiTemplateList(col, C, "UI_UL_list", "", ptr, "layer_slots", ptr, "active_input_index", 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"),
active_index, &active_input_ptr);
}
else {
- uiTemplateList(col, C, ptr, "file_slots", ptr, "active_input_index", NULL, 0, 0, 0);
+ uiTemplateList(col, C, "UI_UL_list", "", ptr, "file_slots", ptr, "active_input_index", 0, 0, 0);
RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
active_index, &active_input_ptr);
}
diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h
index de6ddb4b896..5d8176c8021 100644
--- a/source/blender/makesdna/DNA_screen_types.h
+++ b/source/blender/makesdna/DNA_screen_types.h
@@ -110,12 +110,26 @@ typedef struct Panel { /* the part from uiBlock that needs saved in file */
int sortorder; /* panels are aligned according to increasing sortorder */
struct Panel *paneltab; /* this panel is tabbed in *paneltab */
void *activedata; /* runtime for panel manipulation */
-
- int list_scroll, list_size;
- int list_last_len, list_grip_size;
- char list_search[64];
} Panel;
+typedef struct uiList { /* some list UI data need to be saved in file */
+ struct uiList *next, *prev;
+
+ struct uiListType *type; /* runtime */
+ void *padp;
+
+ char list_id[64]; /* defined as UI_MAX_NAME_STR */
+
+ int layout_type; /* How items are layedout in the list */
+ int padi;
+
+ int list_scroll;
+ int list_size;
+ int list_last_len;
+ int list_grip_size;
+/* char list_search[64]; */
+} uiList;
+
typedef struct ScrArea {
struct ScrArea *next, *prev;
@@ -167,6 +181,7 @@ typedef struct ARegion {
ListBase uiblocks; /* uiBlock */
ListBase panels; /* Panel */
+ ListBase uiLists; /* uiList */
ListBase handlers; /* wmEventHandler */
struct wmTimer *regiontimer; /* blend in/out */
@@ -216,6 +231,13 @@ typedef struct ARegion {
#define PNL_DEFAULT_CLOSED 1
#define PNL_NO_HEADER 2
+/* uilist layout_type */
+enum {
+ UILST_LAYOUT_DEFAULT = 0,
+ UILST_LAYOUT_COMPACT = 1,
+ UILST_LAYOUT_GRID = 2,
+};
+
/* regiontype, first two are the default set */
/* Do NOT change order, append on end. Types are hardcoded needed */
enum {
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 7625605c5fb..bf78c622cbd 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -587,7 +587,7 @@ extern StructRNA RNA_TrackToConstraint;
extern StructRNA RNA_TransformConstraint;
extern StructRNA RNA_TransformSequence;
extern StructRNA RNA_UILayout;
-extern StructRNA RNA_UIListItem;
+extern StructRNA RNA_UIList;
extern StructRNA RNA_UVWarpModifier;
extern StructRNA RNA_UVProjectModifier;
extern StructRNA RNA_UVProjector;
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 9d08cf2d364..49f881ce285 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -133,6 +133,9 @@ extern EnumPropertyItem prop_dynamicpaint_type_items[];
extern EnumPropertyItem clip_editor_mode_items[];
+extern EnumPropertyItem icon_items[];
+extern EnumPropertyItem uilist_layout_type_items[];
+
struct bContext;
struct PointerRNA;
struct PropertyRNA;
diff --git a/source/blender/makesrna/intern/rna_dynamicpaint.c b/source/blender/makesrna/intern/rna_dynamicpaint.c
index 4f9f2009a14..030325494ff 100644
--- a/source/blender/makesrna/intern/rna_dynamicpaint.c
+++ b/source/blender/makesrna/intern/rna_dynamicpaint.c
@@ -32,6 +32,8 @@
#include "rna_internal.h"
+#include "BLI_math_base.h"
+
#include "BKE_modifier.h"
#include "BKE_dynamicpaint.h"
@@ -219,6 +221,14 @@ static int rna_DynamicPaint_is_cache_user_get(PointerRNA *ptr)
return (surface->format != MOD_DPAINT_SURFACE_F_IMAGESEQ) ? 1 : 0;
}
+/* is some 3D view preview available */
+static int rna_DynamicPaint_use_color_preview_get(PointerRNA *ptr)
+{
+ DynamicPaintSurface *surface = (DynamicPaintSurface *)ptr->data;
+
+ return dynamicPaint_surfaceHasColorPreview(surface);
+}
+
/* does output layer exist*/
static int rna_DynamicPaint_is_output_exists(DynamicPaintSurface *surface, Object *ob, int index)
{
@@ -239,6 +249,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
tmp.value = MOD_DPAINT_SURFACE_T_PAINT;
tmp.identifier = "PAINT";
tmp.name = "Paint";
+ tmp.icon = ICON_TPAINT_HLT;
RNA_enum_item_add(&item, &totitem, &tmp);
/* Displace */
@@ -248,6 +259,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
tmp.value = MOD_DPAINT_SURFACE_T_DISPLACE;
tmp.identifier = "DISPLACE";
tmp.name = "Displace";
+ tmp.icon = ICON_MOD_DISPLACE;
RNA_enum_item_add(&item, &totitem, &tmp);
}
@@ -256,6 +268,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
tmp.value = MOD_DPAINT_SURFACE_T_WEIGHT;
tmp.identifier = "WEIGHT";
tmp.name = "Weight";
+ tmp.icon = ICON_MOD_VERTEX_WEIGHT;
RNA_enum_item_add(&item, &totitem, &tmp);
}
@@ -264,6 +277,7 @@ static EnumPropertyItem *rna_DynamicPaint_surface_type_itemf(bContext *C, Pointe
tmp.value = MOD_DPAINT_SURFACE_T_WAVE;
tmp.identifier = "WAVE";
tmp.name = "Waves";
+ tmp.icon = ICON_MOD_WAVE;
RNA_enum_item_add(&item, &totitem, &tmp);
}
@@ -705,6 +719,14 @@ static void rna_def_canvas_surface(BlenderRNA *brna)
RNA_def_property_boolean_funcs(prop, "rna_DynamicPaint_is_cache_user_get", NULL);
RNA_def_property_ui_text(prop, "Use Cache", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+
+ /* whether this surface has preview data for 3D view */
+ RNA_define_verify_sdna(FALSE);
+ prop = RNA_def_property(srna, "use_color_preview", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_funcs(prop, "rna_DynamicPaint_use_color_preview_get", NULL);
+ RNA_def_property_ui_text(prop, "Use Corlor Preview", "Whether this surface has some color preview for 3D view");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE);
+ RNA_define_verify_sdna(TRUE);
}
static void rna_def_dynamic_paint_canvas_settings(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_ui.c b/source/blender/makesrna/intern/rna_ui.c
index de359fd6413..e6e953c412b 100644
--- a/source/blender/makesrna/intern/rna_ui.c
+++ b/source/blender/makesrna/intern/rna_ui.c
@@ -55,6 +55,16 @@ EnumPropertyItem operator_context_items[] = {
{0, NULL, 0, NULL, NULL}
};
+EnumPropertyItem uilist_layout_type_items[] = {
+ {UILST_LAYOUT_DEFAULT, "DEFAULT", 0, "Default Layout",
+ "Use the default, multi-rows layout"},
+ {UILST_LAYOUT_COMPACT, "COMPACT", 0, "Compact Layout",
+ "Use the compact, single-row layout"},
+ {UILST_LAYOUT_GRID, "GRID", 0, "Grid Layout",
+ "Use the grid-based layout"},
+ {0, NULL, 0, NULL, NULL}
+};
+
#ifdef RNA_RUNTIME
#include <assert.h>
@@ -252,6 +262,105 @@ static StructRNA *rna_Panel_refine(PointerRNA *ptr)
return (hdr->type && hdr->type->ext.srna) ? hdr->type->ext.srna : &RNA_Panel;
}
+/* UIList */
+static void uilist_draw_item(uiList *uilst, bContext *C, uiLayout *layout, PointerRNA *dataptr, PointerRNA *itemptr,
+ int icon, PointerRNA *active_dataptr, const char *active_propname, int index)
+{
+ extern FunctionRNA rna_UIList_draw_item_func;
+
+ PointerRNA ultr;
+ ParameterList list;
+ FunctionRNA *func;
+
+ RNA_pointer_create(&CTX_wm_screen(C)->id, uilst->type->ext.srna, uilst, &ultr);
+ func = &rna_UIList_draw_item_func; /* RNA_struct_find_function(&ultr, "draw_item"); */
+
+ RNA_parameter_list_create(&list, &ultr, func);
+ RNA_parameter_set_lookup(&list, "context", &C);
+ RNA_parameter_set_lookup(&list, "layout", &layout);
+ RNA_parameter_set_lookup(&list, "data", dataptr);
+ RNA_parameter_set_lookup(&list, "item", itemptr);
+ RNA_parameter_set_lookup(&list, "icon", &icon);
+ RNA_parameter_set_lookup(&list, "active_data", active_dataptr);
+ RNA_parameter_set_lookup(&list, "active_property", &active_propname);
+ RNA_parameter_set_lookup(&list, "index", &index);
+ uilst->type->ext.call((bContext *)C, &ultr, func, &list);
+
+ RNA_parameter_list_free(&list);
+}
+
+static void rna_UIList_unregister(Main *UNUSED(bmain), StructRNA *type)
+{
+ uiListType *ult = RNA_struct_blender_type_get(type);
+
+ if (!ult)
+ return;
+
+ RNA_struct_free_extension(type, &ult->ext);
+
+ WM_uilisttype_freelink(ult);
+
+ RNA_struct_free(&BLENDER_RNA, type);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+}
+
+static StructRNA *rna_UIList_register(Main *bmain, ReportList *reports, void *data, const char *identifier,
+ StructValidateFunc validate, StructCallbackFunc call, StructFreeFunc free)
+{
+ uiListType *ult, dummyult = {NULL};
+ uiList dummyuilist = {NULL};
+ PointerRNA dummyultr;
+ int have_function[1];
+ size_t over_alloc = 0; /* warning, if this becomes a bess, we better do another alloc */
+
+ /* setup dummy menu & menu type to store static properties in */
+ dummyuilist.type = &dummyult;
+ RNA_pointer_create(NULL, &RNA_UIList, &dummyuilist, &dummyultr);
+
+ /* validate the python class */
+ if (validate(&dummyultr, data, have_function) != 0)
+ return NULL;
+
+ if (strlen(identifier) >= sizeof(dummyult.idname)) {
+ BKE_reportf(reports, RPT_ERROR, "Registering uilist class: '%s' is too long, maximum length is %d",
+ identifier, (int)sizeof(dummyult.idname));
+ return NULL;
+ }
+
+ /* check if we have registered this uilist type before, and remove it */
+ ult = WM_uilisttype_find(dummyult.idname, TRUE);
+ if (ult && ult->ext.srna)
+ rna_UIList_unregister(bmain, ult->ext.srna);
+
+ /* create a new menu type */
+ ult = MEM_callocN(sizeof(uiListType) + over_alloc, "python uilist");
+ memcpy(ult, &dummyult, sizeof(dummyult));
+
+ ult->ext.srna = RNA_def_struct(&BLENDER_RNA, ult->idname, "UIList");
+ ult->ext.data = data;
+ ult->ext.call = call;
+ ult->ext.free = free;
+ RNA_struct_blender_type_set(ult->ext.srna, ult);
+ RNA_def_struct_flag(ult->ext.srna, STRUCT_NO_IDPROPERTIES);
+
+ ult->draw_item = (have_function[0]) ? uilist_draw_item : NULL;
+
+ WM_uilisttype_add(ult);
+
+ /* update while blender is running */
+ WM_main_add_notifier(NC_SCREEN | NA_EDITED, NULL);
+
+ return ult->ext.srna;
+}
+
+static StructRNA *rna_UIList_refine(PointerRNA *ptr)
+{
+ uiList *uilst = (uiList *)ptr->data;
+ return (uilst->type && uilst->type->ext.srna) ? uilst->type->ext.srna : &RNA_UIList;
+}
+
/* Header */
static void header_draw(const bContext *C, Header *hdr)
@@ -495,6 +604,8 @@ static void rna_Menu_bl_description_set(PointerRNA *ptr, const char *value)
else assert(!"setting the bl_description on a non-builtin menu");
}
+/* UILayout */
+
static int rna_UILayout_active_get(PointerRNA *ptr)
{
return uiLayoutGetActive(ptr->data);
@@ -738,6 +849,58 @@ static void rna_def_panel(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Options", "Options for this panel type");
}
+static void rna_def_uilist(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+ PropertyRNA *parm;
+ FunctionRNA *func;
+
+ srna = RNA_def_struct(brna, "UIList", NULL);
+ RNA_def_struct_ui_text(srna, "UIList", "UI list containing the elements of a collection");
+ RNA_def_struct_sdna(srna, "uiList");
+ RNA_def_struct_refine_func(srna, "rna_UIList_refine");
+ RNA_def_struct_register_funcs(srna, "rna_UIList_register", "rna_UIList_unregister", NULL);
+
+ /* draw */
+ func = RNA_def_function(srna, "draw_item", NULL);
+ RNA_def_function_ui_description(func, "Draw an item in the list (NOTE: when you define your own draw_item "
+ "function, you may want to check given 'item' is of the right type...)");
+ RNA_def_function_flag(func, FUNC_REGISTER);
+ parm = RNA_def_pointer(func, "context", "Context", "", "");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "layout", "UILayout", "", "Layout to draw the item");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_NEVER_NULL);
+ parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take Collection property");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+ parm = RNA_def_pointer(func, "item", "AnyType", "", "Item of the collection property");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
+ parm = RNA_def_int(func, "icon", 0, 0, INT_MAX, "", "Icon of the item in the collection", 0, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_pointer(func, "active_data", "AnyType", "",
+ "Data from which to take property for the active element");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+ parm = RNA_def_string(func, "active_property", "", 0, "",
+ "Identifier of property in active_data, for the active element");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_int(func, "index", 0, 0, INT_MAX, "", "Index of the item in the collection", 0, INT_MAX);
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+
+ prop = RNA_def_property(srna, "layout_type", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_items(prop, uilist_layout_type_items);
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+
+ /* registration */
+ prop = RNA_def_property(srna, "bl_idname", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_sdna(prop, NULL, "type->idname");
+ RNA_def_property_flag(prop, PROP_REGISTER | PROP_NEVER_CLAMP);
+ RNA_def_property_ui_text(prop, "ID Name",
+ "If this is set, the uilist gets a custom ID, otherwise it takes the "
+ "name of the class used to define the uilist (for example, if the "
+ "class name is \"OBJECT_UL_vgroups\", and bl_idname is not set by the "
+ "script, then bl_idname = \"OBJECT_UL_vgroups\")");
+}
+
static void rna_def_header(BlenderRNA *brna)
{
StructRNA *srna;
@@ -852,6 +1015,7 @@ void RNA_def_ui(BlenderRNA *brna)
{
rna_def_ui_layout(brna);
rna_def_panel(brna);
+ rna_def_uilist(brna);
rna_def_header(brna);
rna_def_menu(brna);
}
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 548539e3395..366d0dc1fd9 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -33,8 +33,12 @@
#include <stdio.h>
#include "RNA_define.h"
+#include "RNA_enum_types.h"
+
+#include "DNA_screen_types.h"
#include "UI_resources.h"
+#include "UI_interface_icons.h"
#include "rna_internal.h"
@@ -70,12 +74,117 @@ static PointerRNA rna_uiItemO(uiLayout *layout, const char *opname, const char *
return uiItemFullO(layout, opname, name, icon, NULL, uiLayoutGetOperatorContext(layout), flag);
}
+static void rna_uiItemL(uiLayout *layout, const char *name, int icon, int icon_value)
+{
+ if (icon_value && !icon) {
+ icon = icon_value;
+ }
+
+ uiItemL(layout, name, icon);
+}
+
+static int rna_ui_get_rnaptr_icon(bContext *C, PointerRNA *ptr_icon)
+{
+ return UI_rnaptr_icon_get(C, ptr_icon, RNA_struct_ui_icon(ptr_icon->type), FALSE);
+}
+
+static const char *rna_ui_get_enum_name(bContext *C, PointerRNA *ptr, const char *propname, const char *identifier)
+{
+ PropertyRNA *prop = NULL;
+ EnumPropertyItem *items = NULL, *item;
+ int free;
+ const char *name = "";
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop || (RNA_property_type(prop) != PROP_ENUM)) {
+ RNA_warning("Property not found or not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return name;
+ }
+
+ RNA_property_enum_items_gettexted(C, ptr, prop, &items, NULL, &free);
+
+ if (items) {
+ for (item = items; item->identifier; item++) {
+ if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+ name = item->name;
+ break;
+ }
+ }
+ if (free) {
+ MEM_freeN(items);
+ }
+ }
+
+ return name;
+}
+
+static const char *rna_ui_get_enum_description(bContext *C, PointerRNA *ptr, const char *propname,
+ const char *identifier)
+{
+ PropertyRNA *prop = NULL;
+ EnumPropertyItem *items = NULL, *item;
+ int free;
+ const char *desc = "";
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop || (RNA_property_type(prop) != PROP_ENUM)) {
+ RNA_warning("Property not found or not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return desc;
+ }
+
+ RNA_property_enum_items_gettexted(C, ptr, prop, &items, NULL, &free);
+
+ if (items) {
+ for (item = items; item->identifier; item++) {
+ if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+ desc = item->description;
+ break;
+ }
+ }
+ if (free) {
+ MEM_freeN(items);
+ }
+ }
+
+ return desc;
+}
+
+static int rna_ui_get_enum_icon(bContext *C, PointerRNA *ptr, const char *propname, const char *identifier)
+{
+ PropertyRNA *prop = NULL;
+ EnumPropertyItem *items = NULL, *item;
+ int free;
+ int icon = ICON_NONE;
+
+ prop = RNA_struct_find_property(ptr, propname);
+ if (!prop || (RNA_property_type(prop) != PROP_ENUM)) {
+ RNA_warning("Property not found or not an enum: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return icon;
+ }
+
+ RNA_property_enum_items(C, ptr, prop, &items, NULL, &free);
+
+ if (items) {
+ for (item = items; item->identifier; item++) {
+ if (item->identifier[0] && strcmp(item->identifier, identifier) == 0) {
+ icon = item->icon;
+ break;
+ }
+ }
+ if (free) {
+ MEM_freeN(items);
+ }
+ }
+
+ return icon;
+}
+
#else
#define DEF_ICON_BLANK_SKIP
#define DEF_ICON(name) {ICON_##name, (#name), 0, (#name), ""},
#define DEF_VICO(name) {VICO_##name, (#name), 0, (#name), ""},
-static EnumPropertyItem icon_items[] = {
+EnumPropertyItem icon_items[] = {
#include "UI_icons.h"
{0, NULL, 0, NULL, NULL}
};
@@ -92,7 +201,6 @@ static void api_ui_item_common(FunctionRNA *func)
prop = RNA_def_property(func, "icon", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, icon_items);
RNA_def_property_ui_text(prop, "Icon", "Override automatic icon of the item");
-
}
static void api_ui_item_op(FunctionRNA *func)
@@ -130,13 +238,6 @@ void RNA_api_ui_layout(StructRNA *srna)
{'h', "HUE", 0, "Hue", ""},
{0, NULL, 0, NULL, NULL}
};
-
- static EnumPropertyItem list_type_items[] = {
- {0, "DEFAULT", 0, "None", ""},
- {'c', "COMPACT", 0, "Compact", ""},
- {'i', "ICONS", 0, "Icons", ""},
- {0, NULL, 0, NULL, NULL}
- };
/* simple layout specifiers */
func = RNA_def_function(srna, "row", "uiLayoutRow");
@@ -175,6 +276,44 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_float(func, "percentage", 0.0f, 0.0f, 1.0f, "Percentage", "Percentage of width to split at", 0.0f, 1.0f);
RNA_def_boolean(func, "align", 0, "", "Align buttons to each other");
+ /* Icon of a rna pointer */
+ func = RNA_def_function(srna, "icon", "rna_ui_get_rnaptr_icon");
+ parm = RNA_def_int(func, "icon_value", ICON_NONE, 0, INT_MAX, "", "Icon identifier", 0, INT_MAX);
+ RNA_def_function_return(func, parm);
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take the icon");
+ RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
+ RNA_def_function_ui_description(func, "Return the custom icon for this data, "
+ "use it e.g. to get materials or texture icons");
+
+ /* UI name, description and icon of an enum item */
+ func = RNA_def_function(srna, "enum_item_name", "rna_ui_get_enum_name");
+ parm = RNA_def_string(func, "name", "", 0, "", "UI name of the enum item");
+ RNA_def_function_return(func, parm);
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+ parm = RNA_def_string(func, "identifier", "", 0, "", "Identifier of the enum item");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_function_ui_description(func, "Return the UI name for this enum item");
+
+ func = RNA_def_function(srna, "enum_item_description", "rna_ui_get_enum_description");
+ parm = RNA_def_string(func, "description", "", 0, "", "UI description of the enum item");
+ RNA_def_function_return(func, parm);
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+ parm = RNA_def_string(func, "identifier", "", 0, "", "Identifier of the enum item");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_function_ui_description(func, "Return the UI description for this enum item");
+
+ func = RNA_def_function(srna, "enum_item_icon", "rna_ui_get_enum_icon");
+ parm = RNA_def_int(func, "icon_value", ICON_NONE, 0, INT_MAX, "", "Icon identifier", 0, INT_MAX);
+ RNA_def_function_return(func, parm);
+ RNA_def_function_flag(func, FUNC_NO_SELF | FUNC_USE_CONTEXT);
+ api_ui_item_rna_common(func);
+ parm = RNA_def_string(func, "identifier", "", 0, "", "Identifier of the enum item");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ RNA_def_function_ui_description(func, "Return the icon for this enum item");
+
/* items */
func = RNA_def_function(srna, "prop", "rna_uiItemR");
RNA_def_function_ui_description(func, "Item. Exposes an RNA item and places it into the layout");
@@ -274,9 +413,13 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_property_flag(parm, PROP_REQUIRED);
#endif
- func = RNA_def_function(srna, "label", "uiItemL");
- RNA_def_function_ui_description(func, "Item. Display text in the layout");
+ func = RNA_def_function(srna, "label", "rna_uiItemL");
+ RNA_def_function_ui_description(func, "Item. Display text and/or icon in the layout");
api_ui_item_common(func);
+ parm = RNA_def_property(func, "icon_value", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_ui_text(parm, "Icon Value",
+ "Override automatic icon of the item "
+ "(use it e.g. with custom material icons returned by icon()...)");
func = RNA_def_function(srna, "menu", "uiItemM");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
@@ -439,26 +582,29 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_boolean(func, "compact", 0, "", "Use more compact layout");
func = RNA_def_function(srna, "template_list", "uiTemplateList");
- RNA_def_function_ui_description(func, "Item. A list widget to display data, e.g. vertexgroups "
- "(WARNING: only one per panel allowed!).");
+ RNA_def_function_ui_description(func, "Item. A list widget to display data, e.g. vertexgroups.");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
- parm = RNA_def_pointer(func, "data", "AnyType", "", "Data from which to take property");
+ parm = RNA_def_string(func, "listtype_name", "", 0, "", "Identifier of the list type to use");
+ RNA_def_property_flag(parm, PROP_REQUIRED);
+ parm = RNA_def_string(func, "list_id", "", 0, "",
+ "Identifier of this list widget. "
+ "If this is set, the uilist gets a custom ID, otherwise it takes the "
+ "name of the class used to define the uilist (for example, if the "
+ "class name is \"OBJECT_UL_vgroups\", and list_id is not set by the "
+ "script, then bl_idname = \"OBJECT_UL_vgroups\")");
+ parm = RNA_def_pointer(func, "dataptr", "AnyType", "", "Data from which to take the Collection property");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR);
- parm = RNA_def_string(func, "property", "", 0, "", "Identifier of property in data");
+ parm = RNA_def_string(func, "propname", "", 0, "", "Identifier of the Collection property in data");
RNA_def_property_flag(parm, PROP_REQUIRED);
- parm = RNA_def_pointer(func, "active_data", "AnyType", "",
- "Data from which to take property for the active element");
+ parm = RNA_def_pointer(func, "active_dataptr", "AnyType", "",
+ "Data from which to take the integer property, index of the active item");
RNA_def_property_flag(parm, PROP_REQUIRED | PROP_RNAPTR | PROP_NEVER_NULL);
- parm = RNA_def_string(func, "active_property", "", 0, "",
- "Identifier of property in data, for the active element");
+ parm = RNA_def_string(func, "active_propname", "", 0, "",
+ "Identifier of the integer property in active_data, index of the active item");
RNA_def_property_flag(parm, PROP_REQUIRED);
- RNA_def_string(func, "prop_list", "", 0, "",
- "Identifier of a string property in each data member, specifying which "
- "of its properties should have a widget displayed in its row "
- "(format: \"propname1:propname2:propname3:...\")");
RNA_def_int(func, "rows", 5, 0, INT_MAX, "", "Number of rows to display", 0, INT_MAX);
RNA_def_int(func, "maxrows", 5, 0, INT_MAX, "", "Maximum number of rows to display", 0, INT_MAX);
- RNA_def_enum(func, "type", list_type_items, 0, "Type", "Type of list to use");
+ RNA_def_enum(func, "type", uilist_layout_type_items, UILST_LAYOUT_DEFAULT, "Type", "Type of layout to use");
func = RNA_def_function(srna, "template_running_jobs", "uiTemplateRunningJobs");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c
index 2de477c46c3..bc245ecda5c 100644
--- a/source/blender/python/intern/bpy_rna.c
+++ b/source/blender/python/intern/bpy_rna.c
@@ -7373,8 +7373,9 @@ PyDoc_STRVAR(pyrna_register_class_doc,
".. method:: register_class(cls)\n"
"\n"
" Register a subclass of a blender type in (:class:`bpy.types.Panel`,\n"
-" :class:`bpy.types.Menu`, :class:`bpy.types.Header`, :class:`bpy.types.Operator`,\n"
-" :class:`bpy.types.KeyingSetInfo`, :class:`bpy.types.RenderEngine`).\n"
+" :class:`bpy.types.UIList`, :class:`bpy.types.Menu`, :class:`bpy.types.Header`,\n"
+" :class:`bpy.types.Operator`, :class:`bpy.types.KeyingSetInfo`,\n"
+" :class:`bpy.types.RenderEngine`).\n"
"\n"
" If the class has a *register* class method it will be called\n"
" before registration.\n"
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index c418b07401d..eee4b5a3a57 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -265,6 +265,13 @@ char *WM_prop_pystring_assign(struct bContext *C, struct PointerRNA *ptr, struc
void WM_operator_bl_idname(char *to, const char *from);
void WM_operator_py_idname(char *to, const char *from);
+/* *************** uilist types ******************** */
+void WM_uilisttype_init(void);
+struct uiListType *WM_uilisttype_find(const char *idname, int quiet);
+int WM_uilisttype_add(struct uiListType *ult);
+void WM_uilisttype_freelink(struct uiListType *ult);
+void WM_uilisttype_free(void);
+
/* *************** menu types ******************** */
void WM_menutype_init(void);
struct MenuType *WM_menutype_find(const char *idname, int quiet);
diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c
index 8fe387765ce..53e67e91bd2 100644
--- a/source/blender/windowmanager/intern/wm.c
+++ b/source/blender/windowmanager/intern/wm.c
@@ -149,7 +149,63 @@ void WM_operator_stack_clear(wmWindowManager *wm)
WM_main_add_notifier(NC_WM | ND_HISTORY, NULL);
}
-/* ****************************************** */
+
+/* ************ uiListType handling ************** */
+
+static GHash *uilisttypes_hash = NULL;
+
+uiListType *WM_uilisttype_find(const char *idname, int quiet)
+{
+ uiListType *ult;
+
+ if (idname[0]) {
+ ult = BLI_ghash_lookup(uilisttypes_hash, idname);
+ if (ult) {
+ return ult;
+ }
+ }
+
+ if (!quiet) {
+ printf("search for unknown uilisttype %s\n", idname);
+ }
+
+ return NULL;
+}
+
+int WM_uilisttype_add(uiListType *ult)
+{
+ BLI_ghash_insert(uilisttypes_hash, (void *)ult->idname, ult);
+ return 1;
+}
+
+void WM_uilisttype_freelink(uiListType *ult)
+{
+ BLI_ghash_remove(uilisttypes_hash, ult->idname, NULL, (GHashValFreeFP)MEM_freeN);
+}
+
+/* called on initialize WM_init() */
+void WM_uilisttype_init(void)
+{
+ uilisttypes_hash = BLI_ghash_str_new("uilisttypes_hash gh");
+}
+
+void WM_uilisttype_free(void)
+{
+ GHashIterator *iter = BLI_ghashIterator_new(uilisttypes_hash);
+
+ for (; !BLI_ghashIterator_isDone(iter); BLI_ghashIterator_step(iter)) {
+ uiListType *ult = BLI_ghashIterator_getValue(iter);
+ if (ult->ext.free) {
+ ult->ext.free(ult->ext.data);
+ }
+ }
+ BLI_ghashIterator_free(iter);
+
+ BLI_ghash_free(uilisttypes_hash, NULL, (GHashValFreeFP)MEM_freeN);
+ uilisttypes_hash = NULL;
+}
+
+/* ************ MenuType handling ************** */
static GHash *menutypes_hash = NULL;
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index 3cffa143ebc..aae44f51f18 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -137,6 +137,7 @@ void WM_init(bContext *C, int argc, const char **argv)
GHOST_CreateSystemPaths();
wm_operatortype_init();
WM_menutype_init();
+ WM_uilisttype_init();
set_free_windowmanager_cb(wm_close_and_free); /* library.c */
set_blender_test_break_cb(wm_window_testbreak); /* blender.c */
@@ -403,6 +404,7 @@ void WM_exit_ext(bContext *C, const short do_python)
wm_operatortype_free();
wm_dropbox_free();
WM_menutype_free();
+ WM_uilisttype_free();
/* all non-screen and non-space stuff editors did, like editmode */
if (C)
diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c
index 2b29129c0f7..4b8b7460f00 100644
--- a/source/blenderplayer/bad_level_call_stubs/stubs.c
+++ b/source/blenderplayer/bad_level_call_stubs/stubs.c
@@ -414,7 +414,9 @@ void uiTemplateCurveMapping(struct uiLayout *layout, struct CurveMapping *cumap,
void uiTemplateColorRamp(struct uiLayout *layout, struct ColorBand *coba, int expand) {}
void uiTemplateLayers(struct uiLayout *layout, struct PointerRNA *ptr, char *propname) {}
void uiTemplateImageLayers(struct uiLayout *layout, struct bContext *C, struct Image *ima, struct ImageUser *iuser) {}
-ListBase uiTemplateList(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *activeptr, char *activepropname, int rows, int listtype) {struct ListBase b = {0,0}; return b;}
+void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, const char *list_id,
+ PointerRNA *dataptr, const char *propname, PointerRNA *active_dataptr,
+ const char *active_propname, int rows, int maxrows, int layout_type) {}
void uiTemplateRunningJobs(struct uiLayout *layout, struct bContext *C) {}
void uiTemplateOperatorSearch(struct uiLayout *layout) {}
void uiTemplateHeader3D(struct uiLayout *layout, struct bContext *C) {}