diff options
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) {} |