diff options
author | Daniel Genrich <daniel.genrich@gmx.net> | 2012-08-15 03:37:19 +0400 |
---|---|---|
committer | Daniel Genrich <daniel.genrich@gmx.net> | 2012-08-15 03:37:19 +0400 |
commit | 43bb431548436b6b1699f795acd107de0f6b86a8 (patch) | |
tree | f1ab16c6380b85d50fdf6bb978e5f117b0d5d118 /release | |
parent | b8905ba0a6731d2aba6f3487be58b338f35df5f7 (diff) | |
parent | b174610a8461348a82454f9050bc0dee7d9ce926 (diff) |
Merge from trunk r49601-r49907
Diffstat (limited to 'release')
19 files changed, 263 insertions, 134 deletions
diff --git a/release/datafiles/.Bfont b/release/datafiles/bfont.pfb Binary files differindex 364194d9ff1..8faffc3902d 100644 --- a/release/datafiles/.Bfont +++ b/release/datafiles/bfont.pfb diff --git a/release/datafiles/clkernelstoh.py b/release/datafiles/clkernelstoh.py deleted file mode 100755 index 9c24c9e2d03..00000000000 --- a/release/datafiles/clkernelstoh.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- - -# ***** BEGIN GPL LICENSE BLOCK ***** -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software Foundation, -# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -# -# The Original Code is Copyright (C) 2012 Blender Foundation. -# All rights reserved. -# -# Contributor(s): Jeroen Bakker -# -# ***** END GPL LICENCE BLOCK ***** - -# <pep8 compliant> - -import sys -import os - -if len(sys.argv) < 2: - sys.stdout.write("Usage: clkernelstoh <cl_file>\n") - sys.exit(1) - -filename = sys.argv[1] - -try: - fpin = open(filename, "r") -except: - sys.stdout.write("Unable to open input %s\n" % sys.argv[1]) - sys.exit(1) - -if filename[0:2] == "." + os.sep: - filename = filename[2:] - -cname = filename + ".h" -sys.stdout.write("Making H file <%s>\n" % cname) - -filename = filename.split("/")[-1].split("\\")[-1] -filename = filename.replace(".", "_") - -try: - fpout = open(cname, "w") -except: - sys.stdout.write("Unable to open output %s\n" % cname) - sys.exit(1) - -fpout.write("/* clkernelstoh output of file <%s> */\n\n" % filename) -fpout.write("const char * clkernelstoh_%s = " % filename) - -lines = fpin.readlines() -for line in lines: - fpout.write("\"") - fpout.write(line.rstrip()) - fpout.write("\\n\" \\\n") -fpout.write("\"\\0\";\n") - -fpin.close() -fpout.close() diff --git a/release/datafiles/preview.blend b/release/datafiles/preview.blend Binary files differindex 807d1b08c4d..7eaa7a63eeb 100644 --- a/release/datafiles/preview.blend +++ b/release/datafiles/preview.blend diff --git a/release/datafiles/prvicons b/release/datafiles/prvicons.png Binary files differindex 364d9678f0b..364d9678f0b 100644 --- a/release/datafiles/prvicons +++ b/release/datafiles/prvicons.png diff --git a/release/datafiles/startup.blend b/release/datafiles/startup.blend Binary files differnew file mode 100644 index 00000000000..6f6c6646e31 --- /dev/null +++ b/release/datafiles/startup.blend diff --git a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py index d668f2badfc..ef4926c4a98 100644 --- a/release/scripts/modules/bl_i18n_utils/spell_check_utils.py +++ b/release/scripts/modules/bl_i18n_utils/spell_check_utils.py @@ -297,6 +297,7 @@ dict_uimsgs = { "gimbal", "grayscale", "icosphere", + "inpaint", "lightmap", "lossless", "lossy", "midtones", diff --git a/release/scripts/presets/interaction/blender.py b/release/scripts/presets/interaction/blender.py index c5454e479a3..0c79a3fc909 100644 --- a/release/scripts/presets/interaction/blender.py +++ b/release/scripts/presets/interaction/blender.py @@ -1,7 +1,8 @@ # Configuration Blender import bpy -bpy.context.user_preferences.view.use_mouse_auto_depth = False +bpy.context.user_preferences.view.use_mouse_depth_cursor = False +bpy.context.user_preferences.view.use_mouse_depth_navigate = False bpy.context.user_preferences.view.use_zoom_to_mouse = False bpy.context.user_preferences.view.use_rotate_around_active = False bpy.context.user_preferences.edit.use_drag_immediately = False diff --git a/release/scripts/startup/bl_operators/__init__.py b/release/scripts/startup/bl_operators/__init__.py index 06b4429d25c..ecbbe34dbb4 100644 --- a/release/scripts/startup/bl_operators/__init__.py +++ b/release/scripts/startup/bl_operators/__init__.py @@ -29,6 +29,7 @@ _modules = ( "console", "image", "mesh", + "node", "object_align", "object", "object_randomize_transform", diff --git a/release/scripts/startup/bl_operators/node.py b/release/scripts/startup/bl_operators/node.py new file mode 100644 index 00000000000..8a6874b43d1 --- /dev/null +++ b/release/scripts/startup/bl_operators/node.py @@ -0,0 +1,169 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8-80 compliant> + +import bpy +from bpy.types import Operator +from bpy.props import EnumProperty + +# XXX These node item lists should actually be generated by a callback at operator execution time (see node_type_items below), +# using the active node tree from the context. Due to a difficult bug in bpy this is not possible (item list memory gets freed too early), +# so for now just copy the static item lists to these global variables. +# +# In the custom_nodes branch, the static per-tree-type node items are replaced by a single independent type list anyway (with a poll function +# to limit node types to the respective trees). So this workaround is only temporary. + +# lazy init +node_type_items_dict = {} + +# Prefixes used to distinguish base node types and node groups +node_type_prefix = 'NODE_' +node_group_prefix = 'GROUP_' + + +# Generate a list of enum items for a given node class +# Copy existing type enum, adding a prefix to distinguish from node groups +# Skip the base node group type, node groups will be added below for all existing group trees +def node_type_items(node_class): + return [(node_type_prefix + item.identifier, item.name, item.description) + for item in node_class.bl_rna.properties['type'].enum_items if item.identifier != 'GROUP'] + + +# Generate items for node group types +# Filter by the given tree_type +# Node group trees don't have a description property yet (could add this as a custom property though) +def node_group_items(tree_type): + return [(node_group_prefix + group.name, group.name, '') + for group in bpy.data.node_groups if group.type == tree_type] + + +# Returns the enum item list for the edited tree in the context +def node_type_items_cb(self, context): + snode = context.space_data + if not snode: + return [] + tree = snode.edit_tree + if not tree: + return [] + + # Lists of basic node types for each + if not node_type_items_dict: + node_type_items_dict.update({ + 'SHADER': node_type_items(bpy.types.ShaderNode), + 'COMPOSITING': node_type_items(bpy.types.CompositorNode), + 'TEXTURE': node_type_items(bpy.types.TextureNode), + }) + + # XXX Does not work correctly, see comment above + #return [(item.identifier, item.name, item.description, item.value) for item in tree.nodes.bl_rna.functions['new'].parameters['type'].enum_items] + + if tree.type in node_type_items_dict: + return node_type_items_dict[tree.type] + node_group_items(tree.type) + else: + return [] + + +class NODE_OT_add_search(Operator): + '''Add a node to the active tree''' + bl_idname = "node.add_search" + bl_label = "Search and Add Node" + bl_options = {'REGISTER', 'UNDO'} + + # XXX this should be called 'node_type' but the operator search property is hardcoded to 'type' by a hack in bpy_operator_wrap.c ... + type = EnumProperty( + name="Node Type", + description="Node type", + items=node_type_items_cb, + ) + + _node_type_items_dict = None + + def create_node(self, context): + space = context.space_data + tree = space.edit_tree + + # Enum item identifier has an additional prefix to distinguish base node types from node groups + item = self.type + if (item.startswith(node_type_prefix)): + # item means base node type + node = tree.nodes.new(type=item[len(node_type_prefix):]) + elif (item.startswith(node_group_prefix)): + # item means node group type + node = tree.nodes.new(type='GROUP', group=bpy.data.node_groups[item[len(node_group_prefix):]]) + else: + return None + + for n in tree.nodes: + if n == node: + node.select = True + tree.nodes.active = node + else: + node.select = False + node.location = space.cursor_location + return node + + @classmethod + def poll(cls, context): + space = context.space_data + # needs active node editor and a tree to add nodes to + return (space.type == 'NODE_EDITOR' and space.edit_tree) + + def execute(self, context): + self.create_node(context) + return {'FINISHED'} + + def invoke(self, context, event): + space = context.space_data + v2d = context.region.view2d + + # convert mouse position to the View2D for later node placement + space.cursor_location = v2d.region_to_view(event.mouse_region_x, event.mouse_region_y) + + context.window_manager.invoke_search_popup(self) + return {'CANCELLED'} + + +class NODE_OT_collapse_hide_unused_toggle(Operator): + '''Toggle collapsed nodes and hide unused sockets''' + bl_idname = "node.collapse_hide_unused_toggle" + bl_label = "Collapse and Hide Unused Sockets" + bl_options = {'REGISTER', 'UNDO'} + + @classmethod + def poll(cls, context): + space = context.space_data + # needs active node editor and a tree + return (space.type == 'NODE_EDITOR' and space.edit_tree) + + def execute(self, context): + space = context.space_data + tree = space.edit_tree + + for node in tree.nodes: + if node.select: + hide = (not node.hide) + + node.hide = hide + # Note: connected sockets are ignored internally + for socket in node.inputs: + socket.hide = hide + for socket in node.outputs: + socket.hide = hide + + return {'FINISHED'} diff --git a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py index 9cb9dfc708c..b4733ac9d87 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -28,7 +28,9 @@ import os def guess_player_path(preset): import sys - if preset == 'BLENDER24': + if preset == 'INTERNAL': + return bpy.app.binary_path + elif preset == 'BLENDER24': player_path = "blender" if sys.platform == "darwin": @@ -110,32 +112,7 @@ class PlayRenderedAnim(Operator): cmd = [player_path] # extra options, fps controls etc. - if preset == 'BLENDER24': - # ----------------------------------------------------------------- - # Check blender is not 2.5x until it supports playback again - try: - process = subprocess.Popen([player_path, '--version'], - stdout=subprocess.PIPE, - ) - except: - # ignore and allow the main execution to catch the problem. - process = None - - if process is not None: - process.wait() - out = process.stdout.read() - process.stdout.close() - out_split = out.strip().split() - if out_split[0] == b'Blender': - if not out_split[1].startswith(b'2.4'): - self.report({'ERROR'}, - "Blender %s doesn't support playback: %r" % - (out_split[1].decode(), player_path)) - return {'CANCELLED'} - del out, out_split - del process - # ----------------------------------------------------------------- - + if preset in {'BLENDER24', 'INTERNAL'}: opts = ["-a", "-f", str(rd.fps), str(rd.fps_base), "-j", str(scene.frame_step), file] cmd.extend(opts) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 7485e532bd4..ae0c4d4161c 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -215,6 +215,8 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): layout.label(text="Face Count" + ": %d" % md.face_count) def DISPLACE(self, layout, ob, md): + has_texture = (md.texture is not None) + split = layout.split() col = split.column() @@ -226,12 +228,18 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col = split.column() col.label(text="Direction:") col.prop(md, "direction", text="") - col.label(text="Texture Coordinates:") - col.prop(md, "texture_coords", text="") + colsub = col.column() + colsub.active = has_texture + colsub.label(text="Texture Coordinates:") + colsub.prop(md, "texture_coords", text="") if md.texture_coords == 'OBJECT': - layout.prop(md, "texture_coords_object", text="Object") + row = layout.row() + row.active = has_texture + row.prop(md, "texture_coords_object", text="Object") elif md.texture_coords == 'UV' and ob.type == 'MESH': - layout.prop_search(md, "uv_layer", ob.data, "uv_textures") + row = layout.row() + row.active = has_texture + row.prop_search(md, "uv_layer", ob.data, "uv_textures") layout.separator() diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py index e40b46fda70..bb25f8fa076 100644 --- a/release/scripts/startup/bl_ui/properties_mask_common.py +++ b/release/scripts/startup/bl_ui/properties_mask_common.py @@ -127,6 +127,8 @@ class MASK_PT_spline(): row.prop(spline, "use_cyclic") row.prop(spline, "use_fill") + col.prop(spline, "use_self_intersection_check") + class MASK_PT_point(): # subclasses must define... @@ -235,6 +237,13 @@ class MASK_PT_tools(): col.operator("mask.parent_set") col.operator("mask.parent_clear") + col = layout.column(align=True) + col.label(text="Animation:") + col.operator("mask.shape_key_clear") + col.operator("mask.shape_key_insert") + col.operator("mask.shape_key_feather_reset") + col.operator("mask.shape_key_rekey") + class MASK_MT_mask(Menu): bl_label = "Mask" diff --git a/release/scripts/startup/bl_ui/properties_object_constraint.py b/release/scripts/startup/bl_ui/properties_object_constraint.py index e4da581ab83..3d671a0d1b7 100644 --- a/release/scripts/startup/bl_ui/properties_object_constraint.py +++ b/release/scripts/startup/bl_ui/properties_object_constraint.py @@ -773,16 +773,26 @@ class ConstraintButtonsPanel(): row.prop(con, "use_active_clip") row.prop(con, "use_3d_position") + col = layout.column() + if not con.use_active_clip: - layout.prop(con, "clip") + col.prop(con, "clip") + + row = col.row() + row.prop(con, "frame_method", expand=True) if clip: - layout.prop_search(con, "object", clip.tracking, "objects", icon='OBJECT_DATA') - layout.prop_search(con, "track", clip.tracking, "tracks", icon='ANIM_DATA') + tracking = clip.tracking - layout.prop(con, "camera") + col.prop_search(con, "object", tracking, "objects", icon='OBJECT_DATA') - row = layout.row() + tracking_object = tracking.objects.get(con.object, tracking.objects[0]) + + col.prop_search(con, "track", tracking_object, "tracks", icon='ANIM_DATA') + + col.prop(con, "camera") + + row = col.row() row.active = not con.use_3d_position row.prop(con, "depth_object") diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index 1ed3638080a..74bb720b618 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -66,6 +66,7 @@ class RENDER_PT_render(RenderButtonsPanel, Panel): row = layout.row() row.operator("render.render", text="Image", icon='RENDER_STILL') row.operator("render.render", text="Animation", icon='RENDER_ANIMATION').animation = True + row.operator("render.play_rendered_anim", text="Play", icon='RENDER_ANIMATION') layout.prop(rd, "display_mode", text="Display") diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index af39ce3437a..5302ad9b471 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -106,6 +106,10 @@ class IMAGE_MT_select(Menu): layout.operator("uv.select_pinned") layout.operator("uv.select_linked") + layout.separator() + + layout.operator("uv.select_split") + class IMAGE_MT_image(Menu): bl_label = "Image" @@ -383,11 +387,17 @@ class IMAGE_HT_header(Header): layout.prop(sima, "mode", text="") + if show_maskedit: + row = layout.row() + row.template_ID(sima, "mask", new="mask.new") + + if show_uvedit or show_maskedit: + layout.prop(sima, "pivot_point", text="", icon_only=True) + # uv editing if show_uvedit: uvedit = sima.uv_editor - layout.prop(uvedit, "pivot_point", text="", icon_only=True) layout.prop(toolsettings, "use_uv_select_sync", text="") if toolsettings.use_uv_select_sync: @@ -408,14 +418,6 @@ class IMAGE_HT_header(Header): mesh = context.edit_object.data layout.prop_search(mesh.uv_textures, "active", mesh, "uv_textures", text="") - if show_maskedit: - row = layout.row() - row.template_ID(sima, "mask", new="mask.new") - - # reused for mask - uvedit = sima.uv_editor - layout.prop(uvedit, "pivot_point", text="", icon_only=True) - if ima: # layers layout.template_image_layers(ima, iuser) @@ -617,6 +619,7 @@ class IMAGE_PT_view_properties(Panel): sima = context.space_data ima = sima.image show_uvedit = sima.show_uvedit + show_maskedit = sima.show_maskedit uvedit = sima.uv_editor split = layout.split() @@ -635,12 +638,12 @@ class IMAGE_PT_view_properties(Panel): col.label(text="Coordinates:") col.prop(uvedit, "show_normalized_coords", text="Normalized") - if show_uvedit: - + if show_uvedit or show_maskedit: col = layout.column() col.label("Cursor Location:") - col.row().prop(uvedit, "cursor_location", text="") + col.row().prop(sima, "cursor_location", text="") + if show_uvedit: col.separator() col.label(text="UVs:") diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index adcf5a9e9df..5b7ecbfb618 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -115,6 +115,7 @@ class NODE_MT_view(Menu): layout.separator() + layout.operator("node.view_selected") layout.operator("node.view_all") if context.space_data.show_backdrop: @@ -181,6 +182,7 @@ class NODE_MT_node(Menu): layout.operator("node.preview_toggle") layout.operator("node.hide_socket_toggle") layout.operator("node.options_toggle") + layout.operator("node.collapse_hide_unused_toggle") layout.separator() diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index d099db1645b..45814205d9c 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -75,6 +75,9 @@ class SEQUENCER_HT_header(Header): row.prop(ed, "overlay_frame", text="") row.prop(ed, "overlay_lock", text="", icon='LOCKED') + row = layout.row() + row.prop(st, "overlay_type", text="") + row = layout.row(align=True) props = row.operator("render.opengl", text="", icon='RENDER_STILL') props.sequencer = True @@ -428,13 +431,19 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel): def draw(self, context): layout = self.layout + sequencer = context.scene.sequence_editor strip = act_strip(context) + if strip.input_count > 0: col = layout.column() col.prop(strip, "input_1") if strip.input_count > 1: col.prop(strip, "input_2") + if strip.is_supports_mask: + col = layout.column() + col.prop_search(strip, "input_mask", sequencer, "sequences") + if strip.type == 'COLOR': layout.prop(strip, "color") @@ -763,20 +772,26 @@ class SEQUENCER_PT_filter(SequencerButtonsPanel, Panel): layout.prop(strip, "use_color_balance") if strip.use_color_balance and strip.color_balance: # TODO - need to add this somehow - row = layout.row() - row.active = strip.use_color_balance - col = row.column() - col.template_color_wheel(strip.color_balance, "lift", value_slider=False, cubic=True) - col.row().prop(strip.color_balance, "lift") - col.prop(strip.color_balance, "invert_lift", text="Inverse") - col = row.column() - col.template_color_wheel(strip.color_balance, "gamma", value_slider=False, lock_luminosity=True, cubic=True) - col.row().prop(strip.color_balance, "gamma") - col.prop(strip.color_balance, "invert_gamma", text="Inverse") - col = row.column() - col.template_color_wheel(strip.color_balance, "gain", value_slider=False, lock_luminosity=True, cubic=True) - col.row().prop(strip.color_balance, "gain") - col.prop(strip.color_balance, "invert_gain", text="Inverse") + col = layout.column() + col.label(text="Lift:") + col.template_color_wheel(strip.color_balance, "lift", value_slider=True, cubic=True) + row = col.row() + row.prop(strip.color_balance, "lift", text="") + row.prop(strip.color_balance, "invert_lift", text="Inverse") + + col = layout.column() + col.label(text="Gamma:") + col.template_color_wheel(strip.color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) + row = col.row() + row.prop(strip.color_balance, "gamma", text="") + row.prop(strip.color_balance, "invert_gamma", text="Inverse") + + col = layout.column() + col.label(text="Gain:") + col.template_color_wheel(strip.color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True) + row = col.row() + row.prop(strip.color_balance, "gain", text="") + row.prop(strip.color_balance, "invert_gain", text="Inverse") class SEQUENCER_PT_proxy(SequencerButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index e443c7804a6..e7dd9fb4751 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -197,7 +197,8 @@ class USERPREF_PT_interface(Panel): col = row.column() col.label(text="View Manipulation:") - col.prop(view, "use_mouse_auto_depth") + col.prop(view, "use_mouse_depth_cursor") + col.prop(view, "use_mouse_depth_navigate") col.prop(view, "use_zoom_to_mouse") col.prop(view, "use_rotate_around_active") col.prop(view, "use_global_pivot") diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 2d9c9467a01..9368d3ab5db 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1183,6 +1183,7 @@ class VIEW3D_MT_hook(Menu): layout.operator_context = 'EXEC_AREA' layout.operator("object.hook_add_newob") layout.operator("object.hook_add_selob") + layout.operator("object.hook_add_selob", text="Hook to Selected Object Bone").use_bone = True if [mod.type == 'HOOK' for mod in context.active_object.modifiers]: layout.separator() |