diff options
author | Bastien Montagne <montagne29@wanadoo.fr> | 2018-06-09 16:36:37 +0300 |
---|---|---|
committer | Bastien Montagne <montagne29@wanadoo.fr> | 2018-06-09 16:36:37 +0300 |
commit | 2b83d81f68e18f60955c72cd61b3cdc62670c69a (patch) | |
tree | 971e8e8391a852733a8d2bf4e617633bec84912c /release/scripts | |
parent | d3fe0338752de05916bb3e3e15bb3c5ef4d18dc5 (diff) | |
parent | 70f8eaf1b769c402ec61d86f25237d6b64186861 (diff) |
Merge branch 'blender2.8' into ui_layout_gridflow
Diffstat (limited to 'release/scripts')
41 files changed, 1741 insertions, 788 deletions
diff --git a/release/scripts/addons b/release/scripts/addons -Subproject 4b91309b122bcdcddd1854b1137407b2c4f55c7 +Subproject ebd058d7a6438d137522063bb3286c8acc325ca diff --git a/release/scripts/addons_contrib b/release/scripts/addons_contrib -Subproject cd57934bd04c174fc3402888d01a74e6e6653b2 +Subproject 474702157831f1a58bb50f5240ab8b1b02b6ba3 diff --git a/release/scripts/startup/bl_operators/image.py b/release/scripts/startup/bl_operators/image.py index 6a538f0ae33..c2ca271de66 100644 --- a/release/scripts/startup/bl_operators/image.py +++ b/release/scripts/startup/bl_operators/image.py @@ -249,4 +249,4 @@ classes = ( ProjectApply, ProjectEdit, SaveDirty, -)
\ No newline at end of file +) diff --git a/release/scripts/startup/bl_operators/mask.py b/release/scripts/startup/bl_operators/mask.py index 78a4bd9af27..3ce1abad9b8 100644 --- a/release/scripts/startup/bl_operators/mask.py +++ b/release/scripts/startup/bl_operators/mask.py @@ -35,4 +35,4 @@ class MASK_MT_add(Menu): classes = ( MASK_MT_add, -)
\ No newline at end of file +) 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 f4d6c7065a9..e32c1ac0f81 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -184,4 +184,4 @@ class PlayRenderedAnim(Operator): classes = ( PlayRenderedAnim, -)
\ No newline at end of file +) diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py index 7209b6b478f..337492bc8a7 100644 --- a/release/scripts/startup/bl_operators/sequencer.py +++ b/release/scripts/startup/bl_operators/sequencer.py @@ -140,4 +140,4 @@ classes = ( SequencerCrossfadeSounds, SequencerCutMulticam, SequencerDeinterlaceSelectedMovies, -)
\ No newline at end of file +) diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index ee101bb3cc6..b0a5e19d269 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -19,13 +19,17 @@ # <pep8 compliant> import bpy -from bpy.types import Operator +from bpy.types import ( + Operator, + OperatorFileListElement +) from bpy.props import ( BoolProperty, EnumProperty, FloatProperty, IntProperty, StringProperty, + CollectionProperty, ) from bpy.app.translations import pgettext_tip as tip_ @@ -2394,12 +2398,126 @@ class WM_OT_toolbar(Operator): def draw_menu(popover, context): layout = popover.layout - cls.draw_cls(layout, context, detect_layout=False) + cls.draw_cls(layout, context, detect_layout=False, scale_y=1.0) wm.popover(draw_menu, keymap=keymap) return {'FINISHED'} +# Studio Light operations +class WM_OT_studiolight_install(Operator): + """Install a user defined studio light""" + bl_idname = "wm.studiolight_install" + bl_label = "Install Custom Studio Light" + + files = CollectionProperty( + name="File Path", + type=OperatorFileListElement, + ) + directory = StringProperty( + subtype='DIR_PATH', + ) + filter_folder = BoolProperty( + name="Filter folders", + default=True, + options={'HIDDEN'}, + ) + filter_glob = StringProperty( + default="*.png;*.jpg;*.hdr;*.exr", + options={'HIDDEN'}, + ) + orientation = EnumProperty( + items=( + ("MATCAP", "MatCap", ""), + ("WORLD", "World", ""), + ("CAMERA", "Camera", ""), + ) + ) + + def execute(self, context): + import traceback + import shutil + import pathlib + userpref = context.user_preferences + + filepaths = [pathlib.Path(self.directory, e.name) for e in self.files] + path_studiolights = bpy.utils.user_resource('DATAFILES') + + if not path_studiolights: + self.report({'ERROR'}, "Failed to get Studio Light path") + return {'CANCELLED'} + + path_studiolights = pathlib.Path(path_studiolights, "studiolights", self.orientation.lower()) + if not path_studiolights.exists(): + try: + path_studiolights.mkdir(parents=True, exist_ok=True) + except: + traceback.print_exc() + + for filepath in filepaths: + shutil.copy(str(filepath), str(path_studiolights)) + userpref.studio_lights_refresh() + + # print message + msg = ( + tip_("StudioLight Installed %r into %r") % + (", ".join(str(x.name) for x in self.files), str(path_studiolights)) + ) + print(msg) + self.report({'INFO'}, msg) + return {'FINISHED'} + + def invoke(self, context, event): + wm = context.window_manager + wm.fileselect_add(self) + return {'RUNNING_MODAL'} + + +class WM_OT_studiolight_uninstall(Operator): + bl_idname = 'wm.studiolight_uninstall' + bl_label = "Uninstall Studio Light" + index = bpy.props.IntProperty() + + def execute(self, context): + import pathlib + userpref = context.user_preferences + for studio_light in userpref.studio_lights: + if studio_light.index == self.index: + path = pathlib.Path(studio_light.path) + if path.exists(): + path.unlink() + userpref.studio_lights_refresh() + return {'FINISHED'} + return {'CANCELLED'} + + +class WM_OT_studiolight_expand(Operator): + bl_idname = "wm.studiolight_expand" + bl_label = "Expand Studio Light" + index = bpy.props.IntProperty() + + def execute(self, context): + userpref = context.user_preferences + for studio_light in userpref.studio_lights: + if studio_light.index == self.index: + studio_light.show_expanded = not studio_light.show_expanded + break + + return {'FINISHED'} + + +class WM_OT_studiolight_userpref_show(Operator): + """Show light user preferences""" + bl_idname = "wm.studiolight_userpref_show" + bl_label = "" + bl_options = {'INTERNAL'} + + def execute(self, context): + context.user_preferences.active_section = 'LIGHTS' + bpy.ops.screen.userpref_show('INVOKE_DEFAULT') + return {'FINISHED'} + + classes = ( BRUSH_OT_active_index_set, WM_OT_addon_disable, @@ -2454,6 +2572,10 @@ classes = ( WM_OT_owner_disable, WM_OT_owner_enable, WM_OT_url_open, + WM_OT_studiolight_expand, + WM_OT_studiolight_install, + WM_OT_studiolight_uninstall, + WM_OT_studiolight_userpref_show, WM_OT_tool_set_by_name, WM_OT_toolbar, ) diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py index dd99195f12a..da9054fb681 100644 --- a/release/scripts/startup/bl_ui/__init__.py +++ b/release/scripts/startup/bl_ui/__init__.py @@ -88,7 +88,7 @@ _modules = [ "space_userpref", "space_view3d", "space_view3d_toolbar", - ] +] import bpy @@ -167,6 +167,8 @@ def unregister(): # Define a default UIList, when a list does not need any custom drawing... # Keep in sync with its #defined name in UI_interface.h + + class UI_UL_list(bpy.types.UIList): # These are common filtering or ordering operations (same as the default C ones!). @staticmethod diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py index 9782d5a072c..901e15c181a 100644 --- a/release/scripts/startup/bl_ui/properties_animviz.py +++ b/release/scripts/startup/bl_ui/properties_animviz.py @@ -37,27 +37,26 @@ class MotionPathButtonsPanel: mps = avs.motion_path # Display Range - layout.row().prop(mps, "type", expand=True) + layout.use_property_split = True + layout.row().prop(mps, "type") - split = layout.split() + col = layout.column() - col = split.column() - col.label(text="Display Range:") sub = col.column(align=True) if mps.type == 'CURRENT_FRAME': - sub.prop(mps, "frame_before", text="Before") + sub.prop(mps, "frame_before", text="Frame Range Before") sub.prop(mps, "frame_after", text="After") elif mps.type == 'RANGE': - sub.prop(mps, "frame_start", text="Start") + sub.prop(mps, "frame_start", text="Frame Range Start") sub.prop(mps, "frame_end", text="End") sub.prop(mps, "frame_step", text="Step") - col = split.column() + col = layout.column(align=True) if bones: col.label(text="Cache for Bone:") else: - col.label(text="Cache:") + col.label(text="Cache") if mpath: sub = col.column(align=True) @@ -81,17 +80,15 @@ class MotionPathButtonsPanel: sub.operator("object.paths_calculate", text="Calculate...", icon='OBJECT_DATA') # Display Settings - split = layout.split() - col = split.column() - col.label(text="Show:") + layout.label(text="Display") + + col = layout.column() col.prop(mps, "show_frame_numbers", text="Frame Numbers") if mpath is not None: col.prop(mpath, "lines", text="Lines") col.prop(mpath, "line_thickness", text="Thickness") - col = split.column() - col.label("") col.prop(mps, "show_keyframe_highlight", text="Keyframes") sub = col.column() sub.enabled = mps.show_keyframe_highlight @@ -101,11 +98,11 @@ class MotionPathButtonsPanel: # Customize path if mpath is not None: - row = layout.row(align=True) - row.prop(mpath, "use_custom_color", text="", toggle=True, icon='COLOR') - sub = row.row(align=True) + + col.prop(mpath, "use_custom_color", text="Custom Color") + sub = col.column() sub.enabled = mpath.use_custom_color - sub.prop(mpath, "color", text="") + sub.prop(mpath, "color") # FIXME: this panel still needs to be ported so that it will work correctly with animviz diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py index 9b61101778f..b7880e605b3 100644 --- a/release/scripts/startup/bl_ui/properties_constraint.py +++ b/release/scripts/startup/bl_ui/properties_constraint.py @@ -941,6 +941,7 @@ class BONE_PT_constraints(ConstraintButtonsPanel, Panel): for con in context.pose_bone.constraints: self.draw_constraint(context, con) + classes = ( OBJECT_PT_constraints, BONE_PT_constraints, diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index 79a18d743a1..47c53d6ffb5 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -180,9 +180,20 @@ class DATA_PT_geometry_curve(CurveButtonsPanelCurve, Panel): sub.active = curve.taper_object is not None sub.prop(curve, "use_map_taper") - col.separator() - layout.label(text="Bevel") +class DATA_PT_geometry_curve_bevel(CurveButtonsPanelCurve, Panel): + bl_label = "Bevel" + bl_parent_id = "DATA_PT_geometry_curve" + + @classmethod + def poll(cls, context): + return (type(context.curve) in {Curve, TextCurve}) + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + curve = context.curve col = layout.column() sub = col.column() @@ -338,8 +349,18 @@ class DATA_PT_font(CurveButtonsPanelText, Panel): row.prop(char, "use_underline", toggle=True) row.prop(char, "use_small_caps", toggle=True) + +class DATA_PT_font_transform(CurveButtonsPanelText, Panel): + bl_label = "Transform" + bl_parent_id = "DATA_PT_font" + + def draw(self, context): + layout = self.layout + + text = context.curve + char = context.curve.edit_format + layout.use_property_split = True - # layout.prop(text, "font") col = layout.column() @@ -370,12 +391,31 @@ class DATA_PT_paragraph(CurveButtonsPanelText, Panel): text = context.curve - layout.label(text="Alignment") + +class DATA_PT_paragraph_alignment(CurveButtonsPanelText, Panel): + bl_parent_id = "DATA_PT_paragraph" + bl_label = "Alignment" + + def draw(self, context): + layout = self.layout + layout.use_property_split = False + + text = context.curve + layout.row().prop(text, "align_x", expand=True) layout.row().prop(text, "align_y", expand=True) + +class DATA_PT_paragraph_spacing(CurveButtonsPanelText, Panel): + bl_parent_id = "DATA_PT_paragraph" + bl_label = "Spacing" + + def draw(self, context): + layout = self.layout layout.use_property_split = True + text = context.curve + col = layout.column(align=True) col.prop(text, "space_character", text="Character Spacing") col.prop(text, "space_word", text="Word Spacing") @@ -429,10 +469,14 @@ classes = ( DATA_PT_shape_curve, DATA_PT_curve_texture_space, DATA_PT_geometry_curve, + DATA_PT_geometry_curve_bevel, DATA_PT_pathanim, DATA_PT_active_spline, DATA_PT_font, + DATA_PT_font_transform, DATA_PT_paragraph, + DATA_PT_paragraph_alignment, + DATA_PT_paragraph_spacing, DATA_PT_text_boxes, DATA_PT_custom_props_curve, ) diff --git a/release/scripts/startup/bl_ui/properties_data_lamp.py b/release/scripts/startup/bl_ui/properties_data_lamp.py index d47160de8a0..2727c84e820 100644 --- a/release/scripts/startup/bl_ui/properties_data_lamp.py +++ b/release/scripts/startup/bl_ui/properties_data_lamp.py @@ -181,23 +181,59 @@ class DATA_PT_EEVEE_shadow(DataButtonsPanel, Panel): col.prop(lamp, "shadow_buffer_exp", text="Exponent") col.prop(lamp, "shadow_buffer_bleed_bias", text="Bleed Bias") - col.separator() - if lamp.type == 'SUN': - col.label("Cascaded Shadow Map") +class DATA_PT_EEVEE_shadow_cascaded_shadow_map(DataButtonsPanel, Panel): + bl_label = "Cascaded Shadow Map" + bl_parent_id = "DATA_PT_EEVEE_shadow" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + lamp = context.lamp + engine = context.engine + + return (lamp and lamp.type == 'SUN') and (engine in cls.COMPAT_ENGINES) + + def draw(self, context): + layout = self.layout + lamp = context.lamp + layout.use_property_split = True + + col = layout.column() + + col.prop(lamp, "shadow_cascade_count", text="Count") + col.prop(lamp, "shadow_cascade_fade", text="Fade") - col.prop(lamp, "shadow_cascade_count", text="Count") - col.prop(lamp, "shadow_cascade_fade", text="Fade") + col.prop(lamp, "shadow_cascade_max_distance", text="Max Distance") + col.prop(lamp, "shadow_cascade_exponent", text="Distribution") - col.prop(lamp, "shadow_cascade_max_distance", text="Max Distance") - col.prop(lamp, "shadow_cascade_exponent", text="Distribution") - layout.separator() +class DATA_PT_EEVEE_shadow_contact(DataButtonsPanel, Panel): + bl_label = "Contact Shadows" + bl_parent_id = "DATA_PT_EEVEE_shadow" + COMPAT_ENGINES = {'BLENDER_EEVEE'} - layout.prop(lamp, "use_contact_shadow") + @classmethod + def poll(cls, context): + lamp = context.lamp + engine = context.engine + return (lamp and lamp.type in {'POINT', 'SUN', 'SPOT', 'AREA'}) and (engine in cls.COMPAT_ENGINES) + + def draw_header(self, context): + lamp = context.lamp + + layout = self.layout + layout.active = lamp.use_shadow + layout.prop(lamp, "use_contact_shadow", text="") + + def draw(self, context): + layout = self.layout + lamp = context.lamp + layout.use_property_split = True col = layout.column() - col.active = lamp.use_contact_shadow + col.active = lamp.use_shadow and lamp.use_contact_shadow col.prop(lamp, "contact_shadow_distance", text="Distance") col.prop(lamp, "contact_shadow_soft_size", text="Softness") @@ -268,6 +304,7 @@ class DATA_PT_spot(DataButtonsPanel, Panel): class DATA_PT_spot(DataButtonsPanel, Panel): bl_label = "Spot Shape" + bl_parent_id = "DATA_PT_EEVEE_lamp" COMPAT_ENGINES = {'BLENDER_EEVEE'} @classmethod @@ -321,6 +358,8 @@ classes = ( DATA_PT_lamp, DATA_PT_EEVEE_lamp, DATA_PT_EEVEE_shadow, + DATA_PT_EEVEE_shadow_contact, + DATA_PT_EEVEE_shadow_cascaded_shadow_map, DATA_PT_area, DATA_PT_spot, DATA_PT_falloff_curve, diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py index a9c9d512335..12ecbeb3e6b 100644 --- a/release/scripts/startup/bl_ui/properties_freestyle.py +++ b/release/scripts/startup/bl_ui/properties_freestyle.py @@ -629,7 +629,7 @@ class VIEWLAYER_PT_freestyle_linestyle(ViewLayerFreestyleEditorButtonsPanel, Pan row = layout.row(align=True) row.prop(linestyle, "panel", expand=True) if linestyle.panel == 'STROKES': - ## Chaining + # Chaining layout.prop(linestyle, "use_chaining", text="Chaining:") split = layout.split(align=True) split.active = linestyle.use_chaining @@ -643,7 +643,7 @@ class VIEWLAYER_PT_freestyle_linestyle(ViewLayerFreestyleEditorButtonsPanel, Pan col = split.column() col.prop(linestyle, "use_same_object") - ## Splitting + # Splitting layout.label(text="Splitting:") split = layout.split(align=True) # First column @@ -679,7 +679,7 @@ class VIEWLAYER_PT_freestyle_linestyle(ViewLayerFreestyleEditorButtonsPanel, Pan sub.prop(linestyle, "split_dash3", text="D3") sub.prop(linestyle, "split_gap3", text="G3") - ## Sorting + # Sorting layout.prop(linestyle, "use_sorting", text="Sorting:") col = layout.column() col.active = linestyle.use_sorting @@ -693,7 +693,7 @@ class VIEWLAYER_PT_freestyle_linestyle(ViewLayerFreestyleEditorButtonsPanel, Pan row = col.row(align=True) row.prop(linestyle, "sort_order", expand=True) - ## Selection + # Selection layout.label(text="Selection:") split = layout.split(align=True) # First column @@ -716,12 +716,12 @@ class VIEWLAYER_PT_freestyle_linestyle(ViewLayerFreestyleEditorButtonsPanel, Pan sub.active = linestyle.use_chain_count sub.prop(linestyle, "chain_count") - ## Caps + # Caps layout.label(text="Caps:") row = layout.row(align=True) row.prop(linestyle, "caps", expand=True) - ## Dashed lines + # Dashed lines layout.prop(linestyle, "use_dashed_line", text="Dashed Line:") row = layout.row(align=True) row.active = linestyle.use_dashed_line @@ -786,9 +786,10 @@ class VIEWLAYER_PT_freestyle_linestyle(ViewLayerFreestyleEditorButtonsPanel, Pan row = layout.row() props = row.operator( - "wm.properties_context_change", - text="Go to Linestyle Textures Properties", - icon='TEXTURE') + "wm.properties_context_change", + text="Go to Linestyle Textures Properties", + icon='TEXTURE', + ) props.context = 'TEXTURE' elif linestyle.panel == 'MISC': diff --git a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py index decbbff5d60..a2ccfb4f1b8 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -242,7 +242,6 @@ class GreasePencilStrokeEditPanel: if is_3d_view: layout.separator() - layout.separator() col = layout.column(align=True) col.operator("gpencil.stroke_subdivide", text="Subdivide") @@ -1100,11 +1099,11 @@ class GreasePencilPaletteColorPanel: row = layout.row() sub = row.row(align=True) - sub.label(text="Isolate:") # based on active color only + sub.label(text="Isolate:") # based on active color only sub.operator("gpencil.palettecolor_isolate", icon='LOCKED', text="").affect_visibility = False sub.operator("gpencil.palettecolor_isolate", icon='RESTRICT_VIEW_OFF', text="").affect_visibility = True sub = row.row(align=True) - sub.label(text="Lock:") # based on other stuff... + sub.label(text="Lock:") # based on other stuff... sub.operator("gpencil.stroke_lock_color", icon='BORDER_RECT', text="") sub.operator("gpencil.palette_lock_layer", icon='COLOR', text="") diff --git a/release/scripts/startup/bl_ui/properties_mask_common.py b/release/scripts/startup/bl_ui/properties_mask_common.py index a7a67130f2f..450ca80bbc2 100644 --- a/release/scripts/startup/bl_ui/properties_mask_common.py +++ b/release/scripts/startup/bl_ui/properties_mask_common.py @@ -43,8 +43,8 @@ class MASK_UL_layers(UIList): class MASK_PT_mask: # subclasses must define... - #~ bl_space_type = 'CLIP_EDITOR' - #~ bl_region_type = 'UI' + # ~ bl_space_type = 'CLIP_EDITOR' + # ~ bl_region_type = 'UI' bl_label = "Mask Settings" bl_options = {'DEFAULT_CLOSED'} @@ -66,8 +66,8 @@ class MASK_PT_mask: class MASK_PT_layers: # subclasses must define... - #~ bl_space_type = 'CLIP_EDITOR' - #~ bl_region_type = 'UI' + # ~ bl_space_type = 'CLIP_EDITOR' + # ~ bl_region_type = 'UI' bl_label = "Mask Layers" @classmethod @@ -114,8 +114,8 @@ class MASK_PT_layers: class MASK_PT_spline: # subclasses must define... - #~ bl_space_type = 'CLIP_EDITOR' - #~ bl_region_type = 'UI' + # ~ bl_space_type = 'CLIP_EDITOR' + # ~ bl_region_type = 'UI' bl_label = "Active Spline" @classmethod @@ -148,8 +148,8 @@ class MASK_PT_spline: class MASK_PT_point: # subclasses must define... - #~ bl_space_type = 'CLIP_EDITOR' - #~ bl_region_type = 'UI' + # ~ bl_space_type = 'CLIP_EDITOR' + # ~ bl_region_type = 'UI' bl_label = "Active Point" @classmethod @@ -203,8 +203,8 @@ class MASK_PT_point: class MASK_PT_display: # subclasses must define... - #~ bl_space_type = 'CLIP_EDITOR' - #~ bl_region_type = 'UI' + # ~ bl_space_type = 'CLIP_EDITOR' + # ~ bl_region_type = 'UI' bl_label = "Mask Display" bl_options = {'DEFAULT_CLOSED'} @@ -229,8 +229,8 @@ class MASK_PT_display: class MASK_PT_transforms: # subclasses must define... - #~ bl_space_type = 'CLIP_EDITOR' - #~ bl_region_type = 'TOOLS' + # ~ bl_space_type = 'CLIP_EDITOR' + # ~ bl_region_type = 'TOOLS' bl_label = "Transforms" bl_category = "Mask" bl_options = {'DEFAULT_CLOSED'} @@ -253,8 +253,8 @@ class MASK_PT_transforms: class MASK_PT_tools: # subclasses must define... - #~ bl_space_type = 'CLIP_EDITOR' - #~ bl_region_type = 'TOOLS' + # ~ bl_space_type = 'CLIP_EDITOR' + # ~ bl_region_type = 'TOOLS' bl_label = "Mask Tools" bl_category = "Mask" @@ -291,8 +291,8 @@ class MASK_PT_tools: class MASK_PT_add: # subclasses must define... - #~ bl_space_type = 'CLIP_EDITOR' - #~ bl_region_type = 'TOOLS' + # ~ bl_space_type = 'CLIP_EDITOR' + # ~ bl_region_type = 'TOOLS' bl_label = "Add" bl_category = "Mask" diff --git a/release/scripts/startup/bl_ui/properties_material.py b/release/scripts/startup/bl_ui/properties_material.py index 369772f7258..75cdd2d68c6 100644 --- a/release/scripts/startup/bl_ui/properties_material.py +++ b/release/scripts/startup/bl_ui/properties_material.py @@ -23,6 +23,7 @@ from rna_prop_ui import PropertyPanel from bpy.app.translations import pgettext_iface as iface_ from bpy_extras.node_utils import find_node_input, find_output_node + class MATERIAL_MT_specials(Menu): bl_label = "Material Specials" @@ -172,6 +173,7 @@ class EEVEE_MATERIAL_PT_surface(MaterialButtonsPanel, Panel): if mat.use_nodes: panel_node_draw(layout, mat.node_tree, ('OUTPUT_EEVEE_MATERIAL', 'OUTPUT_MATERIAL')) else: + layout.use_property_split = True layout.prop(mat, "diffuse_color", text="Base Color") layout.prop(mat, "metallic") layout.prop(mat, "specular_intensity", text="Specular") @@ -190,6 +192,7 @@ class EEVEE_MATERIAL_PT_options(MaterialButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True mat = context.material diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index 6486fbf0d63..9bcb1099a79 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -86,6 +86,7 @@ class OBJECT_PT_transform(ObjectButtonsPanel, Panel): class OBJECT_PT_delta_transform(ObjectButtonsPanel, Panel): bl_label = "Delta Transform" + bl_parent_id = "OBJECT_PT_transform" bl_options = {'DEFAULT_CLOSED'} def draw(self, context): diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index bc8bc523e12..f1e5102f061 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -126,7 +126,7 @@ def brush_texpaint_common(panel, context, layout, brush, settings, projpaint=Fal col.prop(brush, "gradient_stroke_mode", text="Mode") if brush.gradient_stroke_mode in {'SPACING_REPEAT', 'SPACING_CLAMP'}: col.prop(brush, "grad_spacing") - else: # if brush.image_tool == 'FILL': + else: # if brush.image_tool == 'FILL': col.prop(brush, "gradient_fill_mode") else: row = col.row(align=True) diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index f470a81dca1..00eb13dd222 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -255,56 +255,70 @@ class PARTICLE_PT_emission(ParticleButtonsPanel, Panel): psys = context.particle_system part = particle_get_settings(context) + layout.use_property_split = True + layout.enabled = particle_panel_enabled(context, psys) and (psys is None or not psys.has_multiple_caches) - row = layout.row() - row.active = part.emit_from == 'VERT' or part.distribution != 'GRID' - row.prop(part, "count") + col = layout.column() + col.active = part.emit_from == 'VERT' or part.distribution != 'GRID' + col.prop(part, "count") if part.type == 'HAIR': - row.prop(part, "hair_length") + col.prop(part, "hair_length") if not part.use_advanced_hair: row = layout.row() - row.prop(part, "use_modifier_stack") + col.prop(part, "use_modifier_stack") return if part.type != 'HAIR': - split = layout.split() - col = split.column(align=True) - col.prop(part, "frame_start") - col.prop(part, "frame_end") + col = layout.column() + + sub = col.column(align=True) + sub.prop(part, "frame_start", text="Frame Start") + sub.prop(part, "frame_end", text="End") - col = split.column(align=True) col.prop(part, "lifetime") - col.prop(part, "lifetime_random", slider=True) + col.prop(part, "lifetime_random", slider=True, text="Lifetime Randomness") - layout.label(text="Emit From:") - layout.row().prop(part, "emit_from", expand=True) - row = layout.row() +class PARTICLE_PT_emission_source(ParticleButtonsPanel, Panel): + bl_label = "Source" + bl_parent_id = "PARTICLE_PT_emission" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + def draw(self, context): + layout = self.layout + + part = particle_get_settings(context) + + layout.use_property_split = True + + col = layout.column() + col.prop(part, "emit_from") + col.prop(part, "use_modifier_stack") + if part.emit_from == 'FACE' or part.emit_from == 'VOLUME': + col.prop(part, "distribution") + if part.emit_from == 'VERT': - row.prop(part, "use_emit_random") + col.prop(part, "use_emit_random", text="Random Order") elif part.distribution == 'GRID': - row.prop(part, "invert_grid") - row.prop(part, "hexagonal_grid") + col.label(text="Grid") + col.prop(part, "invert_grid") + col.prop(part, "hexagonal_grid") else: - row.prop(part, "use_emit_random") - row.prop(part, "use_even_distribution") + col.prop(part, "use_emit_random") + col.prop(part, "use_even_distribution") if part.emit_from == 'FACE' or part.emit_from == 'VOLUME': - layout.row().prop(part, "distribution", expand=True) - row = layout.row() if part.distribution == 'JIT': - row.prop(part, "userjit", text="Particles/Face") - row.prop(part, "jitter_factor", text="Jittering Amount", slider=True) + col.prop(part, "userjit", text="Particles/Face") + col.prop(part, "jitter_factor", text="Jittering Amount", slider=True) elif part.distribution == 'GRID': - row.prop(part, "grid_resolution") - row.prop(part, "grid_random", text="Random", slider=True) - - row = layout.row() - row.prop(part, "use_modifier_stack") + col.prop(part, "grid_resolution") + col.prop(part, "grid_random", text="Random", slider=True) class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel): @@ -332,6 +346,7 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel): psys = context.particle_system if not psys.cloth: + layout.label(text="Hair dynamics disabled") return cloth_md = psys.cloth @@ -345,44 +360,20 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel): row.operator("particle.hair_dynamics_preset_add", text="", icon='ZOOMIN') row.operator("particle.hair_dynamics_preset_add", text="", icon='ZOOMOUT').remove_active = True - split = layout.column() - - col = split.column() - col.label(text="Structure") - col.prop(cloth, "mass") - sub = col.column(align=True) - subsub = sub.row(align=True) - subsub.prop(cloth, "bending_stiffness", text="Stiffness") - subsub.prop(psys.settings, "bending_random", text="Random") - sub.prop(cloth, "bending_damping", text="Damping") - # XXX has no noticeable effect with stiff hair structure springs - #col.prop(cloth, "spring_damping", text="Damping") - - split.separator() - - col = split.column() - col.label(text="Volume") - col.prop(cloth, "air_damping", text="Air Drag") - col.prop(cloth, "internal_friction", slider=True) - sub = col.column(align=True) - sub.prop(cloth, "density_target", text="Density Target") - sub.prop(cloth, "density_strength", slider=True, text="Strength") - col.prop(cloth, "voxel_cell_size") + layout.use_property_split = True - split.separator() + layout.separator() - col = split.column() - col.label(text="Pinning") - col.prop(cloth, "pin_stiffness", text="Goal Strength") + col = layout.column() + col.prop(cloth, "quality", text="Quality Steps", slider=True) + col.prop(psys.settings, "show_hair_grid", text="Display Hair Grid") - split.separator() + layout.separator() - col = split.column() - col.label(text="Quality:") - col.prop(cloth, "quality", text="Steps", slider=True) + col = layout.column() + col.prop(cloth, "pin_stiffness", text="Pin Goal Strength") - row = col.row() - row.prop(psys.settings, "show_hair_grid", text="HairGrid") + layout.separator() if result: box = layout.box() @@ -405,6 +396,71 @@ class PARTICLE_PT_hair_dynamics(ParticleButtonsPanel, Panel): box.label("Error: %.5f .. %.5f (avg. %.5f)" % (result.min_error, result.max_error, result.avg_error)) +class PARTICLE_PT_hair_dynamics_structure(ParticleButtonsPanel, Panel): + bl_label = "Structure" + bl_parent_id = "PARTICLE_PT_hair_dynamics" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + return context.particle_system.cloth is not None + + def draw(self, context): + layout = self.layout + + psys = context.particle_system + cloth_md = psys.cloth + cloth = cloth_md.settings + result = cloth_md.solver_result + + layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False + + layout.use_property_split = True + + col = layout.column() + col.prop(cloth, "mass") + sub = col.column(align=True) + sub.prop(cloth, "bending_stiffness", text="Stiffness") + sub.prop(psys.settings, "bending_random", text="Random") + col.prop(cloth, "bending_damping", text="Damping") + # XXX has no noticeable effect with stiff hair structure springs + #col.prop(cloth, "spring_damping", text="Damping") + + +class PARTICLE_PT_hair_dynamics_volume(ParticleButtonsPanel, Panel): + bl_label = "Volume" + bl_parent_id = "PARTICLE_PT_hair_dynamics" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + return context.particle_system.cloth is not None + + def draw(self, context): + layout = self.layout + + psys = context.particle_system + cloth_md = psys.cloth + cloth = cloth_md.settings + result = cloth_md.solver_result + + layout.enabled = psys.use_hair_dynamics and psys.point_cache.is_baked is False + + layout.use_property_split = True + + col = layout.column() + col.prop(cloth, "air_damping", text="Air Drag") + col.prop(cloth, "internal_friction", slider=True) + col.prop(cloth, "voxel_cell_size") + + col.separator() + + col.prop(cloth, "density_target", text="Density Target") + col.prop(cloth, "density_strength", slider=True, text="Density Strength") + + class PARTICLE_PT_cache(ParticleButtonsPanel, Panel): bl_label = "Cache" bl_options = {'DEFAULT_CLOSED'} @@ -459,31 +515,29 @@ class PARTICLE_PT_velocity(ParticleButtonsPanel, Panel): part = particle_get_settings(context) layout.enabled = particle_panel_enabled(context, psys) + layout.use_property_split = True - split = layout.split() - - col = split.column() - col.label(text="Emitter Geometry:") + col = layout.column() col.prop(part, "normal_factor") sub = col.column(align=True) - sub.prop(part, "tangent_factor") - sub.prop(part, "tangent_phase", slider=True) + sub.prop(part, "tangent_factor", text="Tangent") + sub.prop(part, "tangent_phase", slider=True, text="Tangent Phase") - col = split.column() - col.label(text="Emitter Object:") - col.prop(part, "object_align_factor", text="") + col.separator() + + col.prop(part, "object_align_factor") + + col.separator() - layout.label(text="Other:") - row = layout.row() if part.emit_from == 'PARTICLE': - row.prop(part, "particle_factor") + col.prop(part, "particle_factor") else: - row.prop(part, "object_factor", slider=True) - row.prop(part, "factor_random") + col.prop(part, "object_factor", slider=True) + col.prop(part, "factor_random", text="Randomize") - #if part.type=='REACTOR': - # sub.prop(part, "reactor_factor") - # sub.prop(part, "reaction_shape", slider=True) + # if part.type=='REACTOR': + # sub.prop(part, "reactor_factor") + # sub.prop(part, "reaction_shape", slider=True) class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel): @@ -522,32 +576,46 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel): part = context.space_data.pin_id layout.enabled = particle_panel_enabled(context, psys) and part.use_rotations + layout.use_property_split = True - layout.label(text="Initial Orientation:") + col = layout.column() - split = layout.split() + col.prop(part, "rotation_mode") + col.prop(part, "rotation_factor_random", slider=True, text="Randomize") - col = split.column(align=True) - col.prop(part, "rotation_mode", text="") - col.prop(part, "rotation_factor_random", slider=True, text="Random") + col.separator() - col = split.column(align=True) col.prop(part, "phase_factor", slider=True) - col.prop(part, "phase_factor_random", text="Random", slider=True) + col.prop(part, "phase_factor_random", text="Randomize Phase ", slider=True) if part.type != 'HAIR': - layout.label(text="Angular Velocity:") + col.prop(part, "use_dynamic_rotation") - split = layout.split() - col = split.column(align=True) - col.prop(part, "angular_velocity_mode", text="") - sub = col.column(align=True) - sub.active = part.angular_velocity_mode != 'NONE' - sub.prop(part, "angular_velocity_factor", text="") +class PARTICLE_PT_rotation_angular_velocity(ParticleButtonsPanel, Panel): + bl_label = "Angular Velocity" + bl_parent_id = "PARTICLE_PT_rotation" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} - col = split.column() - col.prop(part, "use_dynamic_rotation") + def draw(self, context): + layout = self.layout + + psys = context.particle_system + if psys: + part = psys.settings + else: + part = context.space_data.pin_id + + layout.enabled = particle_panel_enabled(context, psys) and part.use_rotations + layout.use_property_split = True + + col = layout.column() + + col.prop(part, "angular_velocity_mode", text="Axis") + sub = col.column(align=True) + sub.active = part.angular_velocity_mode != 'NONE' + sub.prop(part, "angular_velocity_factor", text="Amount") class PARTICLE_PT_physics(ParticleButtonsPanel, Panel): @@ -568,127 +636,87 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True psys = context.particle_system part = particle_get_settings(context) layout.enabled = particle_panel_enabled(context, psys) - layout.row().prop(part, "physics_type", expand=True) + layout.prop(part, "physics_type") - row = layout.row() + col = layout.column() if part.physics_type != 'NO': - col = row.column(align=True) + col = col.column() col.prop(part, "mass") col.prop(part, "use_multiply_size_mass", text="Multiply mass with size") - if part.physics_type in {'NEWTON', 'FLUID'}: - split = layout.split() + if part.physics_type == 'FLUID': + fluid = part.fluid - col = split.column() - col.label(text="Forces:") - col.prop(part, "brownian_factor") - col.prop(part, "drag_factor", slider=True) - col.prop(part, "damping", slider=True) + col.label(text="Fluid") + col.prop(fluid, "solver") + col.prop(fluid, "stiffness", text="Stiffness") + col.prop(fluid, "linear_viscosity", text="Viscosity") + col.prop(fluid, "buoyancy", text="Buoyancy", slider=True) - col = split.column() - col.label(text="Integration:") - col.prop(part, "integrator", text="") - col.prop(part, "timestep") - sub = col.row() - sub.prop(part, "subframes") - supports_courant = part.physics_type == 'FLUID' - subsub = sub.row() - subsub.enabled = supports_courant - subsub.prop(part, "use_adaptive_subframes", text="") - if supports_courant and part.use_adaptive_subframes: - col.prop(part, "courant_target", text="Threshold") + col.label(text="Advanced") - row = layout.row() - row.prop(part, "use_size_deflect") - row.prop(part, "use_die_on_collision") + if fluid.solver == 'DDR': + sub = col.column() + sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion) + sub.prop(fluid, "factor_repulsion") - layout.prop(part, "collision_group") + sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity) + sub.prop(fluid, "factor_stiff_viscosity") - if part.physics_type == 'FLUID': - fluid = part.fluid - - split = layout.split() - sub = split.row() - sub.prop(fluid, "solver", expand=True) - - split = layout.split() - - col = split.column() - col.label(text="Fluid Properties:") - col.prop(fluid, "stiffness", text="Stiffness") - col.prop(fluid, "linear_viscosity", text="Viscosity") - col.prop(fluid, "buoyancy", text="Buoyancy", slider=True) - - col = split.column() - col.label(text="Advanced:") - - if fluid.solver == 'DDR': - sub = col.row() - sub.prop(fluid, "repulsion", slider=fluid.factor_repulsion) - sub.prop(fluid, "factor_repulsion", text="") - - sub = col.row() - sub.prop(fluid, "stiff_viscosity", slider=fluid.factor_stiff_viscosity) - sub.prop(fluid, "factor_stiff_viscosity", text="") - - sub = col.row() - sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius) - sub.prop(fluid, "factor_radius", text="") - - sub = col.row() - sub.prop(fluid, "rest_density", slider=fluid.use_factor_density) - sub.prop(fluid, "use_factor_density", text="") - - if fluid.solver == 'CLASSICAL': - # With the classical solver, it is possible to calculate the - # spacing between particles when the fluid is at rest. This - # makes it easier to set stable initial conditions. - particle_volume = part.mass / fluid.rest_density - spacing = pow(particle_volume, 1.0 / 3.0) - sub = col.row() - sub.label(text="Spacing: %g" % spacing) - - elif fluid.solver == 'DDR': - split = layout.split() - - col = split.column() - col.label(text="Springs:") - col.prop(fluid, "spring_force", text="Force") - col.prop(fluid, "use_viscoelastic_springs") - sub = col.column(align=True) - sub.active = fluid.use_viscoelastic_springs - sub.prop(fluid, "yield_ratio", slider=True) - sub.prop(fluid, "plasticity", slider=True) - - col = split.column() - col.label(text="Advanced:") - sub = col.row() - sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length) - sub.prop(fluid, "factor_rest_length", text="") - col.label(text="") - sub = col.column() - sub.active = fluid.use_viscoelastic_springs - sub.prop(fluid, "use_initial_rest_length") - sub.prop(fluid, "spring_frames", text="Frames") + sub = col.column() + sub.prop(fluid, "fluid_radius", slider=fluid.factor_radius) + sub.prop(fluid, "factor_radius") + + sub.prop(fluid, "rest_density", slider=fluid.use_factor_density) + sub.prop(fluid, "use_factor_density") + + if fluid.solver == 'CLASSICAL': + # With the classical solver, it is possible to calculate the + # spacing between particles when the fluid is at rest. This + # makes it easier to set stable initial conditions. + particle_volume = part.mass / fluid.rest_density + spacing = pow(particle_volume, 1.0 / 3.0) + + sub.label(text="Spacing: %g" % spacing) + + elif fluid.solver == 'DDR': + + col.label(text="Springs") + col.prop(fluid, "spring_force", text="Force") + col.prop(fluid, "use_viscoelastic_springs") + + sub = col.column() + sub.active = fluid.use_viscoelastic_springs + sub.prop(fluid, "yield_ratio", slider=True) + sub.prop(fluid, "plasticity", slider=True) + + col.label(text="Advanced") + sub = col.column() + sub.prop(fluid, "rest_length", slider=fluid.factor_rest_length) + sub.prop(fluid, "factor_rest_length", text="") + + sub = col.column() + sub.active = fluid.use_viscoelastic_springs + sub.prop(fluid, "use_initial_rest_length") + sub.prop(fluid, "spring_frames", text="Frames") elif part.physics_type == 'KEYED': - split = layout.split() - sub = split.column() - row = layout.row() - col = row.column() - col.active = not psys.use_keyed_timing - col.prop(part, "keyed_loops", text="Loops") + sub = col.column() + sub.active = not psys.use_keyed_timing + sub.prop(part, "keyed_loops", text="Loops") if psys: - row.prop(psys, "use_keyed_timing", text="Use Timing") + col.prop(psys, "use_keyed_timing", text="Use Timing") + + col.label(text="Keys") - layout.label(text="Keys:") elif part.physics_type == 'BOIDS': boids = part.boids @@ -786,6 +814,93 @@ class PARTICLE_PT_physics(ParticleButtonsPanel, Panel): sub.prop(key, "system", text="System") +class PARTICLE_PT_physics_deflection(ParticleButtonsPanel, Panel): + bl_label = "Deflection" + bl_parent_id = "PARTICLE_PT_physics" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.physics_type in {'NEWTON', 'FLUID'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + part = particle_get_settings(context) + + layout.enabled = particle_panel_enabled(context, psys) + + col = layout.column() + col.prop(part, "use_size_deflect") + col.prop(part, "use_die_on_collision") + + col.prop(part, "collision_group") + + +class PARTICLE_PT_physics_forces(ParticleButtonsPanel, Panel): + bl_label = "Forces" + bl_parent_id = "PARTICLE_PT_physics" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.physics_type == 'NEWTON' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + part = particle_get_settings(context) + + layout.enabled = particle_panel_enabled(context, psys) + + col = layout.column() + + col.prop(part, "brownian_factor") + col.prop(part, "drag_factor", slider=True) + col.prop(part, "damping", slider=True) + + +class PARTICLE_PT_physics_integration(ParticleButtonsPanel, Panel): + bl_label = "Integration" + bl_options = {'DEFAULT_CLOSED'} + bl_parent_id = "PARTICLE_PT_physics" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.physics_type == 'NEWTON' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + part = particle_get_settings(context) + + layout.enabled = particle_panel_enabled(context, psys) + + col = layout.column() + + col.prop(part, "integrator") + col.prop(part, "timestep") + sub = col.row() + sub.prop(part, "subframes") + supports_courant = part.physics_type == 'FLUID' + subsub = sub.row() + subsub.enabled = supports_courant + subsub.prop(part, "use_adaptive_subframes", text="") + if supports_courant and part.use_adaptive_subframes: + col.prop(part, "courant_target", text="Threshold") + + class PARTICLE_PT_boidbrain(ParticleButtonsPanel, Panel): bl_label = "Boid Brain" COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} @@ -811,7 +926,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("UI_UL_list", "particle_boids", boids, "states", + # row.template_list("UI_UL_list", "particle_boids", boids, "states", # boids, "active_boid_state_index", compact="True") #col = row.row() #sub = col.row(align=True) @@ -904,175 +1019,387 @@ class PARTICLE_PT_render(ParticleButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True psys = context.particle_system part = particle_get_settings(context) + layout.prop(part, "render_type", text="Render As") + + if part.type == 'EMITTER' or \ + (part.render_type in {'OBJECT', 'COLLECTION'} and part.type == 'HAIR'): + if part.render_type not in {'NONE'}: + + col = layout.column(align=True) + col.prop(part, "particle_size", text="Scale") + col.prop(part, "size_random", slider=True, text="Scale Randomness") + if psys: - row = layout.row() - if part.render_type in {'OBJECT', 'GROUP'}: - row.enabled = False - row.prop(part, "material_slot", text="") - row.prop(psys, "parent") + col = layout.column() + if part.render_type not in {'OBJECT', 'COLLECTION', 'NONE'}: + # col.enabled = False + col.prop(part, "material_slot", text="Material") + col.prop(psys, "parent", text="Coordinate System") - split = layout.split() - col = split.column() - col.prop(part, "use_parent_particles") +class PARTICLE_PT_render_extra(ParticleButtonsPanel, Panel): + bl_label = "Extra" + bl_parent_id = "PARTICLE_PT_render" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} - col = split.column() - col.prop(part, "show_unborn") - col.prop(part, "use_dead") + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type != 'NONE' - layout.row().prop(part, "render_type", expand=True) + def draw(self, context): + layout = self.layout + layout.use_property_split = True - split = layout.split() + psys = context.particle_system + ob = context.object + part = particle_get_settings(context) - col = split.column() + col = layout.column() - if part.render_type == 'LINE': - col.prop(part, "line_length_tail") - col.prop(part, "line_length_head") + col = layout.column() + col.prop(part, "use_parent_particles", text="Parent Particles") + col.prop(part, "show_unborn", text="Unborn") + col.prop(part, "use_dead", text="Dead") - split.prop(part, "use_velocity_length") - elif part.render_type == 'PATH': - col.prop(part, "use_strand_primitive") - sub = col.column() - sub.active = (part.use_strand_primitive is False) - sub.prop(part, "use_render_adaptive") - sub = col.column() - sub.active = part.use_render_adaptive or part.use_strand_primitive is True - sub.prop(part, "adaptive_angle") - sub = col.column() - sub.active = (part.use_render_adaptive is True and part.use_strand_primitive is False) - sub.prop(part, "adaptive_pixel") - col.prop(part, "use_hair_bspline") - col.prop(part, "render_step", text="Steps") - col = split.column() - col.label(text="Timing:") - col.prop(part, "use_absolute_path_time") +class PARTICLE_PT_render_line(ParticleButtonsPanel, Panel): + bl_label = "Line" + bl_parent_id = "PARTICLE_PT_render" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} - if part.type == 'HAIR' or psys.point_cache.is_baked: - col.prop(part, "path_start", text="Start", slider=not part.use_absolute_path_time) - else: - col.prop(part, "trail_count") + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type == 'LINE' - col.prop(part, "path_end", text="End", slider=not part.use_absolute_path_time) - col.prop(part, "length_random", text="Random", slider=True) + def draw(self, context): + layout = self.layout + layout.use_property_split = True - elif part.render_type == 'OBJECT': - col.prop(part, "dupli_object") - sub = col.row() - sub.prop(part, "use_global_dupli") - sub.prop(part, "use_rotation_dupli") - sub.prop(part, "use_scale_dupli") - elif part.render_type == 'GROUP': - col.prop(part, "dupli_group") - split = layout.split() + psys = context.particle_system + ob = context.object + part = particle_get_settings(context) - col = split.column() - col.prop(part, "use_whole_group") - sub = col.column() - sub.active = (part.use_whole_group is False) - sub.prop(part, "use_group_pick_random") - sub.prop(part, "use_group_count") + col = layout.column() - col = split.column() - sub = col.column() - sub.active = (part.use_whole_group is False) - sub.prop(part, "use_global_dupli") - sub.prop(part, "use_rotation_dupli") - sub.prop(part, "use_scale_dupli") + col.separator() + sub = col.column(align=True) + sub.prop(part, "line_length_tail", text="Length Tail") + sub.prop(part, "line_length_head", text="Head") + col.prop(part, "use_velocity_length", text="Velocity Length") - if part.use_group_count and not part.use_whole_group: - row = layout.row() - row.template_list("UI_UL_list", "particle_dupli_weights", part, "dupli_weights", - part, "active_dupliweight_index") - col = row.column() - sub = col.row() - subsub = sub.column(align=True) - subsub.operator("particle.dupliob_copy", icon='ZOOMIN', text="") - subsub.operator("particle.dupliob_remove", icon='ZOOMOUT', text="") - subsub.operator("particle.dupliob_move_up", icon='TRIA_UP', text="") - subsub.operator("particle.dupliob_move_down", icon='TRIA_DOWN', text="") +class PARTICLE_PT_render_path(ParticleButtonsPanel, Panel): + bl_label = "Path" + bl_parent_id = "PARTICLE_PT_render" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} - weight = part.active_dupliweight - if weight: - row = layout.row() - row.prop(weight, "count") + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type == 'PATH' - elif part.render_type == 'BILLBOARD': - ob = context.object + def draw(self, context): + layout = self.layout + layout.use_property_split = True - col.label(text="Align:") + psys = context.particle_system + ob = context.object + part = particle_get_settings(context) - row = layout.row() - row.prop(part, "billboard_align", expand=True) - row.prop(part, "lock_billboard", text="Lock") - row = layout.row() - row.prop(part, "billboard_object") + col = layout.column() - row = layout.row() - col = row.column(align=True) - col.label(text="Tilt:") - col.prop(part, "billboard_tilt", text="Angle", slider=True) - col.prop(part, "billboard_tilt_random", text="Random", slider=True) - col = row.column() - col.prop(part, "billboard_offset") + col.prop(part, "use_strand_primitive") + sub = col.column() + sub.active = (part.use_strand_primitive is False) + sub.prop(part, "use_render_adaptive") + sub = col.column() + sub.active = part.use_render_adaptive or part.use_strand_primitive is True + sub.prop(part, "adaptive_angle") + sub = col.column() + sub.active = (part.use_render_adaptive is True and part.use_strand_primitive is False) + sub.prop(part, "adaptive_pixel") + col.prop(part, "use_hair_bspline") + col.prop(part, "render_step", text="Steps") + + +class PARTICLE_PT_render_path_timing(ParticleButtonsPanel, Panel): + bl_label = "Timing" + bl_parent_id = "PARTICLE_PT_render" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} - row = layout.row() - col = row.column() - col.prop(part, "billboard_size", text="Scale") - if part.billboard_align == 'VEL': - col = row.column(align=True) - col.label("Velocity Scale:") - col.prop(part, "billboard_velocity_head", text="Head") - col.prop(part, "billboard_velocity_tail", text="Tail") + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type == 'PATH' - if psys: - col = layout.column() - col.prop_search(psys, "billboard_normal_uv", ob.data, "uv_layers") - col.prop_search(psys, "billboard_time_index_uv", ob.data, "uv_layers") + def draw(self, context): + layout = self.layout + layout.use_property_split = True - split = layout.split(percentage=0.33) - split.label(text="Split UVs:") - split.prop(part, "billboard_uv_split", text="Number of splits") + psys = context.particle_system + ob = context.object + part = particle_get_settings(context) - if psys: - col = layout.column() - col.active = part.billboard_uv_split > 1 - col.prop_search(psys, "billboard_split_uv", ob.data, "uv_layers") + col = layout.column() - row = col.row() - row.label(text="Animate:") - row.prop(part, "billboard_animation", text="") - row.label(text="Offset:") - row.prop(part, "billboard_offset_split", text="") + col.prop(part, "use_absolute_path_time") - if part.render_type == 'HALO' or part.render_type == 'LINE' or part.render_type == 'BILLBOARD': - row = layout.row() - col = row.column() + if part.type == 'HAIR' or psys.point_cache.is_baked: + col.prop(part, "path_start", text="Start", slider=not part.use_absolute_path_time) + else: col.prop(part, "trail_count") - if part.trail_count > 1: - col.prop(part, "use_absolute_path_time", text="Length in Frames") - col = row.column() - col.prop(part, "path_end", text="Length", slider=not part.use_absolute_path_time) - col.prop(part, "length_random", text="Random", slider=True) - else: - col = row.column() - col.label(text="") - if part.type == 'EMITTER' or \ - (part.render_type in {'OBJECT', 'GROUP'} and part.type == 'HAIR'): - row = layout.row(align=True) - row.prop(part, "particle_size") - row.prop(part, "size_random", slider=True) + col.prop(part, "path_end", text="End", slider=not part.use_absolute_path_time) + col.prop(part, "length_random", text="Random", slider=True) + + +class PARTICLE_PT_render_object(ParticleButtonsPanel, Panel): + bl_label = "Object" + bl_parent_id = "PARTICLE_PT_render" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type == 'OBJECT' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + ob = context.object + part = particle_get_settings(context) + + col = layout.column() + + col.prop(part, "dupli_object", text="Instance Object") + sub = col.column() + sub.prop(part, "use_global_dupli", text="Global Coordinates") + sub.prop(part, "use_rotation_dupli", text="Object Rotation") + sub.prop(part, "use_scale_dupli", text="Object Scale") + + +class PARTICLE_PT_render_collection(ParticleButtonsPanel, Panel): + bl_label = "Collection" + bl_parent_id = "PARTICLE_PT_render" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type == 'COLLECTION' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + ob = context.object + part = particle_get_settings(context) + + col = layout.column() + + col.prop(part, "dupli_group") + + col.prop(part, "use_whole_group") + sub = col.column() + sub.active = (part.use_whole_group is False) + sub.prop(part, "use_group_pick_random") + sub.prop(part, "use_global_dupli", text="Global Coordinates") + sub.prop(part, "use_rotation_dupli", text="Object Rotation") + sub.prop(part, "use_scale_dupli", text="Object Scale") + + +class PARTICLE_PT_render_collection_use_count(ParticleButtonsPanel, Panel): + bl_label = "Use Count" + bl_parent_id = "PARTICLE_PT_render_collection" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type == 'COLLECTION' + + def draw_header(self, context): + layout = self.layout + part = particle_get_settings(context) + + layout.active = not part.use_whole_group + + layout.prop(part, "use_group_count", text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + ob = context.object + part = particle_get_settings(context) + + col = layout.column() + + layout.active = part.use_group_count and not part.use_whole_group + + row = layout.row() + row.template_list("UI_UL_list", "particle_dupli_weights", part, "dupli_weights", + part, "active_dupliweight_index") + + col = row.column() + sub = col.row() + subsub = sub.column(align=True) + subsub.operator("particle.dupliob_copy", icon='ZOOMIN', text="") + subsub.operator("particle.dupliob_remove", icon='ZOOMOUT', text="") + subsub.operator("particle.dupliob_move_up", icon='TRIA_UP', text="") + subsub.operator("particle.dupliob_move_down", icon='TRIA_DOWN', text="") + + weight = part.active_dupliweight + if weight: + row = layout.row() + row.prop(weight, "count") + + +class PARTICLE_PT_render_billboards_alignment(ParticleButtonsPanel, Panel): + bl_label = "Billboard Alignment" + bl_parent_id = "PARTICLE_PT_render" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type == 'BILLBOARD' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + ob = context.object + part = particle_get_settings(context) + + col = layout.column() + + col.prop(part, "billboard_align", text="Align To") + col.prop(part, "lock_billboard", text="Lock Axis") + col.prop(part, "billboard_object") + + +class PARTICLE_PT_render_billboards_tilt(ParticleButtonsPanel, Panel): + bl_label = "Billboard Tilt" + bl_parent_id = "PARTICLE_PT_render" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type == 'BILLBOARD' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + ob = context.object + part = particle_get_settings(context) + + col = layout.column() + + sub = col.column(align=True) + sub.prop(part, "billboard_tilt", text="Angle", slider=True) + sub.prop(part, "billboard_tilt_random", text="Random", slider=True) + + sub = col.column(align=True) + sub.prop(part, "billboard_offset") + col.prop(part, "billboard_size", text="Scale") + if part.billboard_align == 'VEL': + col = col.column(align=True) + col.prop(part, "billboard_velocity_head", text="Velocity ScaleHead") + col.prop(part, "billboard_velocity_tail", text="Tail") + + +class PARTICLE_PT_render_billboards_uv(ParticleButtonsPanel, Panel): + bl_label = "Billboard UVs" + bl_parent_id = "PARTICLE_PT_render" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type == 'BILLBOARD' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + ob = context.object + part = particle_get_settings(context) + + col = layout.column() + + if psys: + col.prop_search(psys, "billboard_normal_uv", ob.data, "uv_layers") + col.prop_search(psys, "billboard_time_index_uv", ob.data, "uv_layers") + + col.prop(part, "billboard_uv_split", text="Split UVs") + + if psys: + sub = col.column() + sub.active = part.billboard_uv_split > 1 + sub.prop_search(psys, "billboard_split_uv", ob.data, "uv_layers") + + sub.prop(part, "billboard_animation") + sub.prop(part, "billboard_offset_split") + + +class PARTICLE_PT_render_trails(ParticleButtonsPanel, Panel): + bl_label = "Trails" + bl_parent_id = "PARTICLE_PT_render" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.render_type in {'HALO', 'LINE', 'BILLBOARD'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + psys = context.particle_system + part = particle_get_settings(context) + + col = layout.column() + + col.prop(part, "trail_count") + + sub = col.column() + sub.active = (part.trail_count > 1) + sub.prop(part, "use_absolute_path_time", text="Length in Frames") + sub.prop(part, "path_end", text="Length", slider=not part.use_absolute_path_time) + sub.prop(part, "length_random", text="Random Length", slider=True) class PARTICLE_PT_draw(ParticleButtonsPanel, Panel): - bl_label = "Display" + bl_label = "Viewport Display" bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} @@ -1086,53 +1413,52 @@ class PARTICLE_PT_draw(ParticleButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True psys = context.particle_system part = particle_get_settings(context) - row = layout.row() - row.prop(part, "draw_method", expand=True) - row.prop(part, "show_guide_hairs") + layout.prop(part, "draw_method", text="Display As") if part.draw_method == 'NONE' or (part.render_type == 'NONE' and part.draw_method == 'RENDER'): return path = (part.render_type == 'PATH' and part.draw_method == 'RENDER') or part.draw_method == 'PATH' - row = layout.row() - row.prop(part, "draw_percentage", slider=True) + layout.separator() + + col = layout.column() + col.prop(part, "draw_color", text="Color") + if part.draw_color in {'VELOCITY', 'ACCELERATION'}: + col.prop(part, "color_maximum", text="Fade Distance") + + col = layout.column() + + if path: + col.prop(part, "draw_step", text="Strand Steps") + col.prop(part, "draw_percentage", slider=True, text="Amount") if part.draw_method != 'RENDER' or part.render_type == 'HALO': - row.prop(part, "draw_size") - else: - row.label(text="") + col.prop(part, "draw_size", text="Size") if part.draw_percentage != 100 and psys is not None: if part.type == 'HAIR': if psys.use_hair_dynamics and psys.point_cache.is_baked is False: - layout.row().label(text="Display percentage makes dynamics inaccurate without baking!") + layout.row().label(text="Display percentage makes dynamics inaccurate without baking") else: phystype = part.physics_type if phystype != 'NO' and phystype != 'KEYED' and psys.point_cache.is_baked is False: - layout.row().label(text="Display percentage makes dynamics inaccurate without baking!") + layout.row().label(text="Display percentage makes dynamics inaccurate without baking") + else: + layout.row().label(text="") - row = layout.row() - col = row.column() + col = layout.column() + col.prop(part, "show_guide_hairs", text="Guide Hairs") col.prop(part, "show_size") col.prop(part, "show_velocity") col.prop(part, "show_number") if part.physics_type == 'BOIDS': col.prop(part, "show_health") - col = row.column(align=True) - col.label(text="Color:") - col.prop(part, "draw_color", text="") - sub = col.row(align=True) - sub.active = (part.draw_color in {'VELOCITY', 'ACCELERATION'}) - sub.prop(part, "color_maximum", text="Max") - - if path: - col.prop(part, "draw_step") - class PARTICLE_PT_children(ParticleButtonsPanel, Panel): bl_label = "Children" @@ -1151,37 +1477,91 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel): layout.row().prop(part, "child_type", expand=True) + layout.use_property_split = True + if part.child_type == 'NONE': return - row = layout.row() + col = layout.column() - col = row.column(align=True) - col.prop(part, "child_nbr", text="Display") - col.prop(part, "rendered_child_count", text="Render") + sub = col.column(align=True) + sub.prop(part, "child_nbr", text="Display Amount") + sub.prop(part, "rendered_child_count", text="Render Amount") + + col.separator() + + col.prop(part, "child_length", slider=True) + col.prop(part, "child_length_threshold", slider=True) + if psys: + col.prop(psys, "child_seed", text="Seed") + + col.separator() if part.child_type == 'INTERPOLATED': - col = row.column() - if psys: - col.prop(psys, "child_seed", text="Seed") col.prop(part, "virtual_parents", slider=True) col.prop(part, "create_long_hair_children") else: - col = row.column(align=True) - col.prop(part, "child_size", text="Size") - col.prop(part, "child_size_random", text="Random") + col.separator() + sub = col.column(align=True) + sub.prop(part, "child_size", text="Size") + sub.prop(part, "child_size_random", text="Randomize Size", slider=True) + + if part.child_type == 'SIMPLE': + col.separator() + col.prop(part, "child_radius", text="Radius") + col.prop(part, "child_roundness", text="Roundness", slider=True) + elif part.virtual_parents > 0.0: + sub = col.column(align=True) + sub.label(text="Parting not available with virtual parents") - split = layout.split() - col = split.column() - col.label(text="Effects:") +class PARTICLE_PT_children_parting(ParticleButtonsPanel, Panel): + bl_label = "Parting" + bl_parent_id = "PARTICLE_PT_children" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} - sub = col.column(align=True) - if part.child_type == 'SIMPLE': - sub.prop(part, "twist") - sub.prop(part, "use_twist_curve") - if part.use_twist_curve: - sub.template_curve_mapping(part, "twist_curve") + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.child_type == 'INTERPOLATED' + + def draw(self, context): + layout = self.layout + + psys = context.particle_system + part = particle_get_settings(context) + + layout.use_property_split = True + + col = layout.column() + col.prop(part, "child_parting_factor", text="Parting", slider=True) + col.prop(part, "child_parting_min", text="Min") + col.prop(part, "child_parting_max", text="Max") + + +class PARTICLE_PT_children_clumping(ParticleButtonsPanel, Panel): + bl_label = "Clumping" + bl_parent_id = "PARTICLE_PT_children" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.child_type != 'NONE' + + def draw(self, context): + layout = self.layout + + psys = context.particle_system + part = particle_get_settings(context) + + layout.use_property_split = True + + col = layout.column() + + sub = col.column() sub.prop(part, "use_clump_curve") if part.use_clump_curve: @@ -1195,28 +1575,33 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel): subsub.enabled = part.use_clump_noise subsub.prop(part, "clump_noise_size") - sub = col.column(align=True) - sub.prop(part, "child_length", slider=True) - sub.prop(part, "child_length_threshold", slider=True) - if part.child_type == 'SIMPLE': - sub = col.column(align=True) - sub.prop(part, "child_radius", text="Radius") - sub.prop(part, "child_roundness", text="Roundness", slider=True) - if psys: - sub.prop(psys, "child_seed", text="Seed") - elif part.virtual_parents > 0.0: - sub = col.column(align=True) - sub.label(text="Parting not") - sub.label(text="available with") - sub.label(text="virtual parents") - else: - sub = col.column(align=True) - sub.prop(part, "child_parting_factor", text="Parting", slider=True) - sub.prop(part, "child_parting_min", text="Min") - sub.prop(part, "child_parting_max", text="Max") + sub.prop(part, "twist") + sub.prop(part, "use_twist_curve") + if part.use_twist_curve: + sub.template_curve_mapping(part, "twist_curve") - col = split.column() + +class PARTICLE_PT_children_roughness(ParticleButtonsPanel, Panel): + bl_label = "Roughness" + bl_parent_id = "PARTICLE_PT_children" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.child_type != 'NONE' + + def draw(self, context): + layout = self.layout + + psys = context.particle_system + part = particle_get_settings(context) + + layout.use_property_split = True + + col = layout.column() col.prop(part, "use_roughness_curve") if part.use_roughness_curve: @@ -1225,8 +1610,6 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel): sub.prop(part, "roughness_1", text="Roughness") sub.prop(part, "roughness_1_size", text="Size") else: - col.label(text="Roughness:") - sub = col.column(align=True) sub.prop(part, "roughness_1", text="Uniform") sub.prop(part, "roughness_1_size", text="Size") @@ -1240,31 +1623,55 @@ class PARTICLE_PT_children(ParticleButtonsPanel, Panel): sub.prop(part, "roughness_2_size", text="Size") sub.prop(part, "roughness_2_threshold", slider=True) - layout.row().label(text="Kink:") - layout.row().prop(part, "kink", expand=True) - split = layout.split() - split.active = part.kink != 'NO' +class PARTICLE_PT_children_kink(ParticleButtonsPanel, Panel): + bl_label = "Kink" + bl_parent_id = "PARTICLE_PT_children" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + @classmethod + def poll(cls, context): + part = particle_get_settings(context) + return part.child_type != 'NONE' + + def draw(self, context): + layout = self.layout + + psys = context.particle_system + part = particle_get_settings(context) + + layout.use_property_split = True + + col = layout.column() + + col.prop(part, "kink", text="Kink Type") + col = layout.column() + col.active = part.kink != 'NO' if part.kink == 'SPIRAL': - col = split.column() - sub = col.column(align=True) - sub.prop(part, "kink_amplitude", text="Radius") - sub.prop(part, "kink_amplitude_random", text="Random", slider=True) - sub = col.column(align=True) + + sub = col.column() + sub.prop(part, "kink_amplitude", text="Amplitude") + sub.prop(part, "kink_amplitude_random", text="Randomize Amplitude", slider=True) + + col.separator() + + sub = col.column() sub.prop(part, "kink_axis") - sub.prop(part, "kink_axis_random", text="Random", slider=True) - col = split.column(align=True) + sub.prop(part, "kink_axis_random", text="Randomize Axis", slider=True) + + col.separator() + col.prop(part, "kink_frequency", text="Frequency") col.prop(part, "kink_shape", text="Shape", slider=True) col.prop(part, "kink_extra_steps", text="Steps") - else: - col = split.column() + + elif part.kink in {'CURL', 'RADIAL', 'WAVE', 'BRAID', 'WAVE'}: sub = col.column(align=True) sub.prop(part, "kink_amplitude") sub.prop(part, "kink_amplitude_clump", text="Clump", slider=True) col.prop(part, "kink_flat", slider=True) - col = split.column(align=True) col.prop(part, "kink_frequency") col.prop(part, "kink_shape", slider=True) @@ -1337,6 +1744,7 @@ class PARTICLE_PT_vertexgroups(ParticleButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True ob = context.object psys = context.particle_system @@ -1441,21 +1849,20 @@ class PARTICLE_PT_hair_shape(ParticleButtonsPanel, Panel): def draw(self, context): layout = self.layout + layout.use_property_split = True psys = context.particle_system part = psys.settings - row = layout.row() - row.prop(part, "shape", text="Shape") + layout.prop(part, "shape", text="Strand Shape") - layout.label(text="Thickness:") - row = layout.row() - row.prop(part, "root_radius", text="Root") - row.prop(part, "tip_radius", text="Tip") + col = layout.column(align=True) + col.prop(part, "root_radius", text="Radius Root") + col.prop(part, "tip_radius", text="Tip") - row = layout.row() - row.prop(part, "radius_scale", text="Scaling") - row.prop(part, "use_close_tip") + col = layout.column() + col.prop(part, "radius_scale", text="Radius Scaling") + col.prop(part, "use_close_tip") class PARTICLE_PT_custom_props(ParticleButtonsPanel, PropertyPanel, Panel): @@ -1470,15 +1877,36 @@ classes = ( PARTICLE_UL_particle_systems, PARTICLE_PT_context_particles, PARTICLE_PT_emission, + PARTICLE_PT_emission_source, PARTICLE_PT_hair_dynamics, + PARTICLE_PT_hair_dynamics_structure, + PARTICLE_PT_hair_dynamics_volume, PARTICLE_PT_cache, PARTICLE_PT_velocity, PARTICLE_PT_rotation, + PARTICLE_PT_rotation_angular_velocity, PARTICLE_PT_physics, + PARTICLE_PT_physics_forces, + PARTICLE_PT_physics_deflection, + PARTICLE_PT_physics_integration, PARTICLE_PT_boidbrain, PARTICLE_PT_render, + PARTICLE_PT_render_line, + PARTICLE_PT_render_path, + PARTICLE_PT_render_path_timing, + PARTICLE_PT_render_object, + PARTICLE_PT_render_collection, + PARTICLE_PT_render_collection_use_count, + PARTICLE_PT_render_billboards_tilt, + PARTICLE_PT_render_billboards_uv, + PARTICLE_PT_render_trails, + PARTICLE_PT_render_extra, PARTICLE_PT_draw, PARTICLE_PT_children, + PARTICLE_PT_children_parting, + PARTICLE_PT_children_clumping, + PARTICLE_PT_children_roughness, + PARTICLE_PT_children_kink, PARTICLE_PT_hair_shape, PARTICLE_PT_field_weights, PARTICLE_PT_force_fields, diff --git a/release/scripts/startup/bl_ui/properties_physics_cloth.py b/release/scripts/startup/bl_ui/properties_physics_cloth.py index e0d0327324b..f450bc61635 100644 --- a/release/scripts/startup/bl_ui/properties_physics_cloth.py +++ b/release/scripts/startup/bl_ui/properties_physics_cloth.py @@ -257,6 +257,7 @@ class PHYSICS_PT_cloth_field_weights(PhysicButtonsPanel, Panel): cloth = context.cloth.settings effector_weights_ui(self, context, cloth.effector_weights, 'CLOTH') + classes = ( CLOTH_MT_presets, PHYSICS_PT_cloth, diff --git a/release/scripts/startup/bl_ui/properties_physics_common.py b/release/scripts/startup/bl_ui/properties_physics_common.py index 3615f8be48c..05c72bf47ee 100644 --- a/release/scripts/startup/bl_ui/properties_physics_common.py +++ b/release/scripts/startup/bl_ui/properties_physics_common.py @@ -274,7 +274,7 @@ def basic_force_field_settings_ui(self, context, field): elif field.type == 'HARMONIC': col.prop(field, "use_multiple_springs") if field.type == 'FORCE': - col.prop(field, "use_gravity_falloff", text="Gravitation") + col.prop(field, "use_gravity_falloff", text="Gravitation") split = layout.split() diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py index 817b0ab76ed..3cb9026fd02 100644 --- a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py +++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py @@ -117,7 +117,7 @@ class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel): rbo = ob.rigid_body #col = layout.column(align=1) - #col.label(text="Activation:") + # col.label(text="Activation:") # XXX: settings such as activate on collison/etc. split = layout.split() diff --git a/release/scripts/startup/bl_ui/properties_render.py b/release/scripts/startup/bl_ui/properties_render.py index f1f5ec425e4..7cb0ce55be3 100644 --- a/release/scripts/startup/bl_ui/properties_render.py +++ b/release/scripts/startup/bl_ui/properties_render.py @@ -152,7 +152,7 @@ class RENDER_PT_dimensions(RenderButtonsPanel, Panel): sub.prop(rd, "use_crop_to_border", text="Crop") col = layout.column(align=True) - col.prop(scene, "frame_start", text="Frame Range Start") + col.prop(scene, "frame_start", text="Frame Start") col.prop(scene, "frame_end", text="End") col.prop(scene, "frame_step", text="Step") @@ -161,8 +161,21 @@ class RENDER_PT_dimensions(RenderButtonsPanel, Panel): col.label(text="Frame Rate") self.draw_framerate(col, rd) + +class RENDER_PT_frame_remapping(RenderButtonsPanel, Panel): + bl_label = "Time Remapping" + bl_parent_id = "RENDER_PT_dimensions" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'} + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + rd = context.scene.render + col = layout.column(align=True) - col.prop(rd, "frame_map_old", text="Time Remapping Old") + col.prop(rd, "frame_map_old", text="Old") col.prop(rd, "frame_map_new", text="New") @@ -222,11 +235,25 @@ class RENDER_PT_stamp(RenderButtonsPanel, Panel): sub.active = rd.use_stamp_note sub.prop(rd, "stamp_note_text", text="") - layout.use_property_split = True - layout.separator() +class RENDER_PT_stamp_burn(RenderButtonsPanel, Panel): + bl_label = "Burn Into Image" + bl_parent_id = "RENDER_PT_stamp" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'} + + def draw_header(self, context): + rd = context.scene.render + + self.layout.prop(rd, "use_stamp", text="") + + def draw(self, context): + layout = self.layout + + rd = context.scene.render + + layout.use_property_split = True - layout.prop(rd, "use_stamp", text="Burn Into Image") col = layout.column() col.active = rd.use_stamp col.prop(rd, "stamp_font_size", text="Font Size") @@ -750,6 +777,7 @@ class RENDER_PT_hair(RenderButtonsPanel, Panel): row = layout.row() row.prop(rd, "hair_type", expand=True) + layout.use_property_split = True layout.prop(rd, "hair_subdiv") @@ -759,10 +787,12 @@ classes = ( RENDER_MT_framerate_presets, RENDER_PT_context, RENDER_PT_dimensions, + RENDER_PT_frame_remapping, RENDER_PT_post_processing, RENDER_PT_output, RENDER_PT_encoding, RENDER_PT_stamp, + RENDER_PT_stamp_burn, RENDER_UL_renderviews, RENDER_PT_stereoscopy, RENDER_PT_hair, diff --git a/release/scripts/startup/bl_ui/properties_scene.py b/release/scripts/startup/bl_ui/properties_scene.py index 731a4586e42..4c5b1a86235 100644 --- a/release/scripts/startup/bl_ui/properties_scene.py +++ b/release/scripts/startup/bl_ui/properties_scene.py @@ -160,6 +160,7 @@ class SceneKeyingSetsPanel: class SCENE_PT_keying_sets(SceneButtonsPanel, SceneKeyingSetsPanel, Panel): bl_label = "Keying Sets" + bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} def draw(self, context): @@ -193,7 +194,7 @@ class SCENE_PT_keying_sets(SceneButtonsPanel, SceneKeyingSetsPanel, Panel): class SCENE_PT_keying_set_paths(SceneButtonsPanel, SceneKeyingSetsPanel, Panel): bl_label = "Active Keying Set" - bl_options = {'DEFAULT_CLOSED'} + bl_parent_id = "SCENE_PT_keying_sets" COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} @classmethod @@ -258,18 +259,44 @@ class SCENE_PT_color_management(SceneButtonsPanel, Panel): layout.use_property_split = True scene = context.scene + view = scene.view_settings col = layout.column() col.prop(scene.display_settings, "display_device") + col.prop(scene.sequencer_colorspace_settings, "name", text="Sequencer Color Space") col.separator() col = layout.column() - col.template_colormanaged_view_settings(scene, "view_settings") + col.prop(view, "view_transform") + col.prop(view, "exposure") + col.prop(view, "gamma") + col.prop(view, "look") - col.separator() - col = layout.column() - col.prop(scene.sequencer_colorspace_settings, "name", text="Sequencer Color Space") + +class SCENE_PT_color_management_curves(SceneButtonsPanel, Panel): + bl_label = "Use Curves" + bl_parent_id = "SCENE_PT_color_management" + bl_options = {'DEFAULT_CLOSED'} + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} + + def draw_header(self, context): + + scene = context.scene + view = scene.view_settings + + self.layout.prop(view, "use_curve_mapping", text="") + + def draw(self, context): + layout = self.layout + + scene = context.scene + view = scene.view_settings + + layout.use_property_split = False + layout.enabled = view.use_curve_mapping + + layout.template_curve_mapping(view, "curve_mapping", levels=True) class SCENE_PT_audio(SceneButtonsPanel, Panel): @@ -306,6 +333,7 @@ class SCENE_PT_audio(SceneButtonsPanel, Panel): class SCENE_PT_physics(SceneButtonsPanel, Panel): bl_label = "Gravity" + bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'} def draw_header(self, context): @@ -368,7 +396,8 @@ class SCENE_PT_rigid_body_world(SceneButtonsPanel, Panel): class SCENE_PT_rigid_body_cache(SceneButtonsPanel, Panel): - bl_label = "Rigid Body Cache" + bl_label = "Cache" + bl_parent_id = "SCENE_PT_rigid_body_world" bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'} @@ -385,7 +414,8 @@ class SCENE_PT_rigid_body_cache(SceneButtonsPanel, Panel): class SCENE_PT_rigid_body_field_weights(SceneButtonsPanel, Panel): - bl_label = "Rigid Body Field Weights" + bl_label = "Field Weights" + bl_parent_id = "SCENE_PT_rigid_body_world" bl_options = {'DEFAULT_CLOSED'} COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE'} @@ -446,6 +476,24 @@ class SCENE_PT_viewport_display(SceneButtonsPanel, Panel): col.prop(scene.display, "shadow_shift") +class SCENE_PT_viewport_display_ssao(SceneButtonsPanel, Panel): + bl_label = "Screen Space Ambient Occlusion" + bl_parent_id = "SCENE_PT_viewport_display" + + @classmethod + def poll(cls, context): + return True + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + scene = context.scene + col = layout.column() + col.prop(scene.display, "matcap_ssao_samples") + col.prop(scene.display, "matcap_ssao_distance") + col.prop(scene.display, "matcap_ssao_attenuation") + + class SCENE_PT_custom_props(SceneButtonsPanel, PropertyPanel, Panel): COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_CLAY', 'BLENDER_EEVEE'} _context_path = "scene" @@ -460,7 +508,9 @@ classes = ( SCENE_PT_keying_sets, SCENE_PT_keying_set_paths, SCENE_PT_color_management, + SCENE_PT_color_management_curves, SCENE_PT_viewport_display, + SCENE_PT_viewport_display_ssao, SCENE_PT_audio, SCENE_PT_physics, SCENE_PT_rigid_body_world, diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py index b7dc8ec9d4e..55a087a8310 100644 --- a/release/scripts/startup/bl_ui/properties_texture.py +++ b/release/scripts/startup/bl_ui/properties_texture.py @@ -59,6 +59,7 @@ class TEXTURE_UL_texslots(UIList): layout.alignment = 'CENTER' layout.label(text="", icon_value=icon) + def context_tex_datablock(context): idblock = context.brush if idblock: @@ -106,6 +107,7 @@ class TEXTURE_PT_preview(TextureButtonsPanel, Panel): if isinstance(idblock, Brush): layout.prop(tex, "use_preview_alpha") + class TEXTURE_PT_context(TextureButtonsPanel, Panel): bl_label = "" bl_context = "texture" diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py index 3c8552c3407..013fac3c099 100644 --- a/release/scripts/startup/bl_ui/properties_view_layer.py +++ b/release/scripts/startup/bl_ui/properties_view_layer.py @@ -43,7 +43,7 @@ class VIEWLAYER_PT_layer(ViewLayerButtonsPanel, Panel): rd = scene.render layer = bpy.context.view_layer - layout.prop(layer, "use", text="Use for Rendering"); + layout.prop(layer, "use", text="Use for Rendering") layout.prop(rd, "use_single_layer", text="Render Single Layer") diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index a3dc401b484..40009090231 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -1018,9 +1018,11 @@ class CLIP_PT_proxy(CLIP_PT_clip_view_panel, Panel): if clip.use_proxy_custom_directory: col.prop(clip.proxy, "directory") - col.operator("clip.rebuild_proxy", - text="Build Proxy / Timecode" if clip.source == 'MOVIE' - else "Build Proxy") + col.operator( + "clip.rebuild_proxy", + text="Build Proxy / Timecode" if clip.source == 'MOVIE' + else "Build Proxy" + ) if clip.source == 'MOVIE': col2 = col.column() @@ -1189,6 +1191,7 @@ class CLIP_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel): class CLIP_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel): bl_space_type = 'CLIP_EDITOR' + class CLIP_MT_view(Menu): bl_label = "View" diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index f3841de3ba4..0dbb3f53332 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -118,7 +118,7 @@ class DOPESHEET_HT_header(Header): row = layout.row(align=True) row.template_header() - + # XXX: perhaps our mode menu can be retired eventually when we get editor submodes in the main menu? layout.prop(st, "mode", text="") @@ -425,11 +425,11 @@ class DOPESHEET_MT_gpencil_channel(Menu): layout.operator("anim.channels_editable_toggle") # XXX: to be enabled when these are ready for use! - #layout.separator() - #layout.operator("anim.channels_expand") - #layout.operator("anim.channels_collapse") + # layout.separator() + # layout.operator("anim.channels_expand") + # layout.operator("anim.channels_collapse") - #layout.separator() + # layout.separator() #layout.operator_menu_enum("anim.channels_move", "direction", text="Move...") @@ -450,9 +450,9 @@ class DOPESHEET_MT_gpencil_frame(Menu): layout.separator() layout.operator("action.keyframe_type") - #layout.separator() - #layout.operator("action.copy") - #layout.operator("action.paste") + # layout.separator() + # layout.operator("action.copy") + # layout.operator("action.paste") class DOPESHEET_MT_delete(Menu): @@ -469,6 +469,66 @@ class DOPESHEET_MT_delete(Menu): layout.operator("action.clean", text="Clean Channels").channels = True +class DOPESHEET_MT_specials(Menu): + bl_label = "Dope Sheet Context Menu" + + def draw(self, context): + layout = self.layout + + layout.operator("action.copy", text="Copy") + layout.operator("action.paste", text="Paste") + layout.operator("action.paste", text="Paste Flipped").flipped = True + + layout.separator() + + layout.operator_menu_enum("action.handle_type", "type", text="Handle Type") + layout.operator_menu_enum("action.interpolation_type", "type", text="Interpolation Mode") + layout.operator_menu_enum("action.easing_type", "type", text="Easing Type") + + layout.separator() + + layout.operator("action.keyframe_insert").type = 'SEL' + layout.operator("action.duplicate_move") + layout.operator("action.delete") + + layout.separator() + + layout.operator_menu_enum("action.mirror", "type", text="Mirror") + layout.operator_menu_enum("action.snap", "type", text="Snap") + + +class DOPESHEET_MT_channel_specials(Menu): + bl_label = "Dope Sheet Channel Context Menu" + + def draw(self, context): + layout = self.layout + + layout.operator("anim.channels_setting_enable", text="Mute Channels").type = 'MUTE' + layout.operator("anim.channels_setting_disable", text="Unmute Channels").type = 'MUTE' + layout.separator() + layout.operator("anim.channels_setting_enable", text="Protect Channels").type = 'PROTECT' + layout.operator("anim.channels_setting_disable", text="Unprotect Channels").type = 'PROTECT' + + layout.separator() + layout.operator("anim.channels_group") + layout.operator("anim.channels_ungroup") + + layout.separator() + layout.operator("anim.channels_editable_toggle") + layout.operator_menu_enum("action.extrapolation_type", "type", text="Extrapolation Mode") + + layout.separator() + layout.operator("anim.channels_expand") + layout.operator("anim.channels_collapse") + + layout.separator() + layout.operator_menu_enum("anim.channels_move", "direction", text="Move...") + + layout.separator() + + layout.operator("anim.channels_delete") + + classes = ( DOPESHEET_HT_header, DOPESHEET_HT_editor_buttons, @@ -482,6 +542,8 @@ classes = ( DOPESHEET_MT_gpencil_channel, DOPESHEET_MT_gpencil_frame, DOPESHEET_MT_delete, + DOPESHEET_MT_specials, + DOPESHEET_MT_channel_specials, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py index 7e927bb6385..6e809c4e86a 100644 --- a/release/scripts/startup/bl_ui/space_graph.py +++ b/release/scripts/startup/bl_ui/space_graph.py @@ -299,6 +299,76 @@ class GRAPH_MT_delete(Menu): layout.operator("graph.clean").channels = False layout.operator("graph.clean", text="Clean Channels").channels = True + +class GRAPH_MT_specials(Menu): + bl_label = "F-Curve Context Menu" + + def draw(self, context): + layout = self.layout + + layout.operator("graph.copy", text="Copy") + layout.operator("graph.paste", text="Paste") + layout.operator("graph.paste", text="Paste Flipped").flipped = True + + layout.separator() + + layout.operator_menu_enum("graph.handle_type", "type", text="Handle Type") + layout.operator_menu_enum("graph.interpolation_type", "type", text="Interpolation Mode") + layout.operator_menu_enum("graph.easing_type", "type", text="Easing Type") + + layout.separator() + + layout.operator("graph.keyframe_insert").type = 'SEL' + layout.operator("graph.duplicate_move") + layout.operator("graph.delete") + + layout.separator() + + layout.operator_menu_enum("graph.mirror", "type", text="Mirror") + layout.operator_menu_enum("graph.snap", "type", text="Snap") + + +class GRAPH_MT_channel_specials(Menu): + bl_label = "F-Curve Channel Context Menu" + + def draw(self, context): + layout = self.layout + st = context.space_data + + layout.separator() + layout.operator("anim.channels_setting_enable", text="Mute Channels").type = 'MUTE' + layout.operator("anim.channels_setting_disable", text="Unmute Channels").type = 'MUTE' + layout.separator() + layout.operator("anim.channels_setting_enable", text="Protect Channels").type = 'PROTECT' + layout.operator("anim.channels_setting_disable", text="Unprotect Channels").type = 'PROTECT' + + layout.separator() + layout.operator("anim.channels_group") + layout.operator("anim.channels_ungroup") + + layout.separator() + layout.operator("anim.channels_editable_toggle") + layout.operator_menu_enum("graph.extrapolation_type", "type", text="Extrapolation Mode") + + layout.separator() + layout.operator("graph.hide", text="Hide Selected Curves").unselected = False + layout.operator("graph.hide", text="Hide Unselected Curves").unselected = True + layout.operator("graph.reveal") + + layout.separator() + layout.operator("anim.channels_expand") + layout.operator("anim.channels_collapse") + + layout.separator() + layout.operator_menu_enum("anim.channels_move", "direction", text="Move...") + + layout.separator() + + layout.operator("anim.channels_delete") + if st.mode == 'DRIVERS': + layout.operator("graph.driver_delete_invalid") + + classes = ( GRAPH_HT_header, GRAPH_MT_editor_menus, @@ -309,6 +379,8 @@ classes = ( GRAPH_MT_key, GRAPH_MT_key_transform, GRAPH_MT_delete, + GRAPH_MT_specials, + GRAPH_MT_channel_specials, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index b1ff1618d09..4b533d2f045 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -422,6 +422,43 @@ class IMAGE_MT_uvs_select_mode(Menu): props.data_path = "tool_settings.uv_select_mode" +class IMAGE_MT_specials(Menu): + bl_label = "UV Context Menu" + + def draw(self, context): + layout = self.layout + + sima = context.space_data + + # UV Edit Mode + if sima.show_uvedit: + layout.operator("uv.unwrap") + layout.operator("uv.follow_active_quads") + + layout.separator() + + layout.operator("uv.pin").clear = False + layout.operator("uv.pin", text="Unpin").clear = True + + layout.separator() + + layout.operator("uv.weld") + layout.operator("uv.stitch") + + layout.separator() + + layout.operator_enum("uv.align", "axis") # W, 2/3/4 + + layout.separator() + + layout.operator("transform.mirror", text="Mirror X").constraint_axis[0] = True + layout.operator("transform.mirror", text="Mirror Y").constraint_axis[1] = True + + layout.separator() + + layout.menu("IMAGE_MT_uvs_snap") + + class IMAGE_HT_header(Header): bl_space_type = 'IMAGE_EDITOR' @@ -584,6 +621,7 @@ class IMAGE_PT_tools_mask(MASK_PT_tools, Panel): bl_region_type = 'TOOLS' bl_category = 'Mask' + class IMAGE_PT_tools_mask_add(MASK_PT_add, Panel): bl_space_type = 'IMAGE_EDITOR' bl_region_type = 'TOOLS' @@ -1127,8 +1165,6 @@ class IMAGE_PT_uv_sculpt(Panel, ImagePaintPanel): col.prop(uvsculpt, "show_brush") - - class IMAGE_PT_options_uvs(Panel, UVToolsPanel): bl_label = "UV Options" bl_category = "Options" @@ -1308,6 +1344,7 @@ classes = ( IMAGE_MT_uvs_mirror, IMAGE_MT_uvs_weldalign, IMAGE_MT_uvs_select_mode, + IMAGE_MT_specials, IMAGE_HT_header, MASK_MT_editor_menus, IMAGE_PT_mask, diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 0963613af5c..bf3fa64a852 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -290,6 +290,41 @@ class NODE_MT_node_color_specials(Menu): layout.operator("node.node_copy_color", icon='COPY_ID') +class NODE_MT_specials(Menu): + bl_label = "Node Context Menu" + + def draw(self, context): + layout = self.layout + + layout.operator_context = 'INVOKE_DEFAULT' + layout.operator("node.duplicate_move") + layout.operator("node.delete") + layout.operator_context = 'EXEC_DEFAULT' + + layout.operator("node.delete_reconnect") + + layout.separator() + + layout.operator("node.link_make").replace = False + layout.operator("node.link_make", text="Make and Replace Links").replace = True + layout.operator("node.links_detach") + + layout.separator() + + layout.operator("node.group_make", text="Group") + layout.operator("node.group_ungroup", text="Ungroup") + layout.operator("node.group_edit").exit = False + + layout.separator() + + layout.operator("node.hide_toggle") + layout.operator("node.mute_toggle") + layout.operator("node.preview_toggle") + layout.operator("node.hide_socket_toggle") + layout.operator("node.options_toggle") + layout.operator("node.collapse_hide_unused_toggle") + + class NODE_PT_active_node_generic(Panel): bl_space_type = 'NODE_EDITOR' bl_region_type = 'UI' @@ -507,11 +542,15 @@ class NODE_PT_tools_grease_pencil_sculpt(GreasePencilStrokeSculptPanel, Panel): bl_region_type = 'TOOLS' # Grease Pencil drawing brushes + + class NODE_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel): bl_space_type = 'NODE_EDITOR' bl_region_type = 'TOOLS' # Grease Pencil drawing curves + + class NODE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel): bl_space_type = 'NODE_EDITOR' bl_region_type = 'TOOLS' @@ -522,6 +561,7 @@ class NODE_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Pane def node_draw_tree_view(layout, context): pass + classes = ( NODE_HT_header, NODE_MT_editor_menus, @@ -531,6 +571,7 @@ classes = ( NODE_MT_node, NODE_MT_node_color_presets, NODE_MT_node_color_specials, + NODE_MT_specials, NODE_PT_active_node_generic, NODE_PT_active_node_color, NODE_PT_active_node_properties, diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index 8b8526cf9f2..12cff72b61a 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -179,7 +179,7 @@ class OUTLINER_MT_collection(Menu): layout.operator("outliner.collection_instance", text="Instance to Scene") if space.display_mode != 'VIEW_LAYER': layout.operator("outliner.collection_link", text="Link to Scene") - layout.operator("outliner.id_operation", text="Unlink").type='UNLINK' + layout.operator("outliner.id_operation", text="Unlink").type = 'UNLINK' if space.display_mode == 'VIEW_LAYER': layout.separator() @@ -206,20 +206,20 @@ class OUTLINER_MT_object(Menu): space = context.space_data - layout.operator("outliner.object_operation", text="Delete").type='DELETE' + layout.operator("outliner.object_operation", text="Delete").type = 'DELETE' if space.display_mode == 'VIEW_LAYER' and not space.use_filter_collection: - layout.operator("outliner.object_operation", text="Delete Hierarchy").type='DELETE_HIERARCHY' + layout.operator("outliner.object_operation", text="Delete Hierarchy").type = 'DELETE_HIERARCHY' layout.separator() - layout.operator("outliner.object_operation", text="Select").type='SELECT' - layout.operator("outliner.object_operation", text="Select Hierarchy").type='SELECT_HIERARCHY' - layout.operator("outliner.object_operation", text="Deselect").type='DESELECT' + layout.operator("outliner.object_operation", text="Select").type = 'SELECT' + layout.operator("outliner.object_operation", text="Select Hierarchy").type = 'SELECT_HIERARCHY' + layout.operator("outliner.object_operation", text="Deselect").type = 'DESELECT' layout.separator() if not (space.display_mode == 'VIEW_LAYER' and not space.use_filter_collection): - layout.operator("outliner.id_operation", text="Unlink").type='UNLINK' + layout.operator("outliner.id_operation", text="Unlink").type = 'UNLINK' layout.separator() layout.operator_menu_enum("outliner.id_operation", 'type', text="ID Data") diff --git a/release/scripts/startup/bl_ui/space_properties.py b/release/scripts/startup/bl_ui/space_properties.py index cd7137e0254..2d1725b2087 100644 --- a/release/scripts/startup/bl_ui/space_properties.py +++ b/release/scripts/startup/bl_ui/space_properties.py @@ -32,8 +32,7 @@ class PROPERTIES_HT_header(Header): row = layout.row() row.template_header() - if view.mode == 'DATA_PROPERTIES': - row.prop(view, "context", expand=True, icon_only=True) + row.prop(view, "context", expand=True, icon_only=True) classes = ( diff --git a/release/scripts/startup/bl_ui/space_statusbar.py b/release/scripts/startup/bl_ui/space_statusbar.py index 983b474d18b..3a6fc4925d8 100644 --- a/release/scripts/startup/bl_ui/space_statusbar.py +++ b/release/scripts/startup/bl_ui/space_statusbar.py @@ -73,7 +73,6 @@ class STATUSBAR_HT_header(Header): return - classes = ( STATUSBAR_HT_header, ) diff --git a/release/scripts/startup/bl_ui/space_time.py b/release/scripts/startup/bl_ui/space_time.py index 48ac85f0d0e..7c584b3177b 100644 --- a/release/scripts/startup/bl_ui/space_time.py +++ b/release/scripts/startup/bl_ui/space_time.py @@ -117,6 +117,7 @@ class TIME_MT_editor_menus(Menu): panel_type="TIME_PT_keyframing_settings", text="Keying") + class TIME_MT_marker(Menu): bl_label = "Marker" @@ -217,6 +218,7 @@ def marker_menu_generic(layout): ################################### + class TimelinePanelButtons: bl_space_type = 'DOPESHEET_EDITOR' bl_region_type = 'UI' @@ -292,7 +294,7 @@ class TIME_PT_keyframing_settings(TimelinePanelButtons, Panel): col = layout.column(align=True) col.label("New Keyframe Type:") col.prop(toolsettings, "keyframe_type", text="") - + col = layout.column(align=True) col.label("Auto Keyframing:") row = col.row() diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py index cb6d3851d02..2b9d4207272 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py @@ -339,9 +339,7 @@ class ToolSelectPanelHelper: # - None: Signal to finish (complete any final operations, e.g. add padding). @staticmethod - def _layout_generator_single_column(layout): - scale_y = 2.0 - + def _layout_generator_single_column(layout, scale_y): col = layout.column(align=True) col.scale_y = scale_y is_sep = False @@ -355,9 +353,8 @@ class ToolSelectPanelHelper: is_sep = yield col @staticmethod - def _layout_generator_multi_columns(layout, column_count): - scale_y = 2.0 - scale_x = 2.2 + def _layout_generator_multi_columns(layout, column_count, scale_y): + scale_x = scale_y * 1.1 column_last = column_count - 1 col = layout.column(align=True) @@ -394,7 +391,7 @@ class ToolSelectPanelHelper: column_index += 1 @staticmethod - def _layout_generator_detect_from_region(layout, region): + def _layout_generator_detect_from_region(layout, region, scale_y): """ Choose an appropriate layout for the toolbar. """ @@ -421,15 +418,14 @@ class ToolSelectPanelHelper: column_count = 1 if column_count == 1: - ui_gen = ToolSelectPanelHelper._layout_generator_single_column(layout) + ui_gen = ToolSelectPanelHelper._layout_generator_single_column(layout, scale_y=scale_y) else: - ui_gen = ToolSelectPanelHelper._layout_generator_multi_columns(layout, column_count=column_count) + ui_gen = ToolSelectPanelHelper._layout_generator_multi_columns(layout, column_count=column_count, scale_y=scale_y) return ui_gen, show_text - @classmethod - def draw_cls(cls, layout, context, detect_layout=True): + def draw_cls(cls, layout, context, detect_layout=True, scale_y=2.0): # Use a classmethod so it can be called outside of a panel context. # XXX, this UI isn't very nice. @@ -445,9 +441,9 @@ class ToolSelectPanelHelper: ) if detect_layout: - ui_gen, show_text = cls._layout_generator_detect_from_region(layout, context.region) + ui_gen, show_text = cls._layout_generator_detect_from_region(layout, context.region, scale_y) else: - ui_gen = ToolSelectPanelHelper._layout_generator_single_column(layout) + ui_gen = ToolSelectPanelHelper._layout_generator_single_column(layout, scale_y) show_text = True # Start iteration @@ -676,6 +672,7 @@ def keymap_from_context(context, space_type): wm.keyconfigs.update() return keymap + classes = ( WM_MT_toolsystem_submenu, ) diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 42fac9e03a4..da86c1c03bc 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -91,7 +91,7 @@ class _defs_view3d_generic: ("transform.translate", dict(release_confirm=True, cursor_transform=True), dict(type='EVT_TWEAK_A', value='ANY'), - ), + ), ), ) @@ -292,7 +292,6 @@ class _defs_edit_armature: class _defs_edit_mesh: - @ToolDef.from_fn def cube_add(): return dict( diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index 243b36bdeb7..c231d05ecdb 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -141,7 +141,7 @@ class TOPBAR_HT_lower_bar(Header): elif mode == 'POSE': pass elif mode == 'PARTICLE': - pass + layout.popover_group(space_type='PROPERTIES', region_type='WINDOW', context=".paint_common", category="") def draw_right(self, context): layout = self.layout @@ -610,6 +610,11 @@ class INFO_MT_edit(Menu): layout.separator() + layout.operator("screen.repeat_last") + layout.operator("screen.repeat_history") + + layout.separator() + layout.operator("screen.userpref_show", text="User Preferences...", icon='PREFERENCES') diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 1e090884fd1..a480fa433e1 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -22,6 +22,7 @@ from bpy.types import ( Header, Menu, Panel, + Operator, ) from bpy.app.translations import pgettext_iface as iface_ from bpy.app.translations import contexts as i18n_contexts @@ -71,6 +72,10 @@ class USERPREF_HT_header(Header): layout.operator("wm.addon_install", icon='FILESEL') layout.operator("wm.addon_refresh", icon='FILE_REFRESH') layout.menu("USERPREF_MT_addons_online_resources") + elif userpref.active_section == 'LIGHTS': + layout.operator('wm.studiolight_install', text="Install MatCap").orientation='MATCAP' + layout.operator('wm.studiolight_install', text="Install World HDRI").orientation='WORLD' + layout.operator('wm.studiolight_install', text="Install Camera HDRI").orientation='CAMERA' elif userpref.active_section == 'THEMES': layout.operator("ui.reset_default_theme") layout.operator("wm.theme_install") @@ -141,7 +146,6 @@ class USERPREF_MT_app_templates(Menu): layout.operator_context = 'INVOKE_DEFAULT' props = layout.operator("wm.app_template_install") - def draw(self, context): self.draw_ex(context, use_splash=False, use_default=True, use_install=True) @@ -282,14 +286,14 @@ class USERPREF_PT_interface(Panel): row.separator() col = row.column() - #Toolbox doesn't exist yet - #col.label(text="Toolbox:") + # Toolbox doesn't exist yet + # col.label(text="Toolbox:") #col.prop(view, "show_column_layout") #col.label(text="Open Toolbox Delay:") #col.prop(view, "open_left_mouse_delay", text="Hold LMB") #col.prop(view, "open_right_mouse_delay", text="Hold RMB") col.prop(view, "show_manipulator") - ## Currently not working + # Currently not working # col.prop(view, "show_manipulator_shaded") sub = col.column() sub.active = view.show_manipulator @@ -328,7 +332,6 @@ class USERPREF_PT_interface(Panel): col.prop(view, "show_view3d_cursor") - class USERPREF_PT_edit(Panel): bl_space_type = 'USER_PREFERENCES' bl_label = "Edit" @@ -412,7 +415,7 @@ class USERPREF_PT_edit(Panel): sub = col.column() - #~ sub.active = edit.use_keyframe_insert_auto # incorrect, time-line can enable + # ~ sub.active = edit.use_keyframe_insert_auto # incorrect, time-line can enable sub.prop(edit, "use_keyframe_insert_available", text="Only Insert Available") col.separator() @@ -1217,7 +1220,7 @@ class USERPREF_PT_input(Panel): #sub.prop(inputs, "use_mouse_mmb_paste") - #col.separator() + # col.separator() sub = col.column() sub.prop(inputs, "invert_zoom_wheel", text="Invert Wheel Zoom Direction") @@ -1332,7 +1335,7 @@ class USERPREF_PT_addons(Panel): 'OFFICIAL': 'FILE_BLEND', 'COMMUNITY': 'POSE_DATA', 'TESTING': 'MOD_EXPLODE', - } + } @classmethod def poll(cls, context): @@ -1410,7 +1413,6 @@ class USERPREF_PT_addons(Panel): sub_col.label(" " + addon_file) sub_col.label(" " + addon_path) - if addon_utils.error_encoding: self.draw_error( col, @@ -1435,11 +1437,11 @@ class USERPREF_PT_addons(Panel): # check if addon should be visible with current filters if ((filter == "All") or - (filter == info["category"]) or - (filter == "Enabled" and is_enabled) or - (filter == "Disabled" and not is_enabled) or - (filter == "User" and (mod.__file__.startswith((scripts_addons_folder, userpref_addons_folder)))) - ): + (filter == info["category"]) or + (filter == "Enabled" and is_enabled) or + (filter == "Disabled" and not is_enabled) or + (filter == "User" and (mod.__file__.startswith((scripts_addons_folder, userpref_addons_folder)))) + ): if search and search not in info["name"].lower(): if info["author"]: if search not in info["author"].lower(): @@ -1573,6 +1575,60 @@ class USERPREF_PT_addons(Panel): row.label(text=module_name, translate=False) +class StudioLightPanelMixin(): + bl_space_type = 'USER_PREFERENCES' + bl_region_type = 'WINDOW' + + @classmethod + def poll(cls, context): + userpref = context.user_preferences + return (userpref.active_section == 'LIGHTS') + + def _get_lights(self, userpref): + return [light for light in userpref.studio_lights if light.is_user_defined and light.orientation == self.sl_orientation] + + def draw_header(self, context): + layout = self.layout + row = layout.row() + userpref = context.user_preferences + lights = self._get_lights(userpref) + row.label("({})".format(len(lights))) + + def draw(self, context): + layout = self.layout + userpref = context.user_preferences + lights = self._get_lights(userpref) + if lights: + flow = layout.column_flow(4) + for studio_light in lights: + self.draw_studio_light(flow, studio_light) + else: + layout.label("No custom {} configured".format(self.bl_label)) + + def draw_studio_light(self, layout, studio_light): + box = layout.box() + row = box.row() + + row.template_icon_view(studio_light, "icon_id") + op = row.operator('wm.studiolight_uninstall', text="", icon='ZOOMOUT') + op.index = studio_light.index + + +class USERPREF_PT_studiolight_matcaps(Panel, StudioLightPanelMixin): + bl_label = "MatCaps" + sl_orientation = 'MATCAP' + + +class USERPREF_PT_studiolight_world(Panel, StudioLightPanelMixin): + bl_label = "World HDRI" + sl_orientation = 'WORLD' + + +class USERPREF_PT_studiolight_camera(Panel, StudioLightPanelMixin): + bl_label = "Camera HDRI" + sl_orientation = 'CAMERA' + + classes = ( USERPREF_HT_header, USERPREF_PT_tabs, @@ -1593,6 +1649,9 @@ classes = ( USERPREF_PT_input, USERPREF_MT_addons_online_resources, USERPREF_PT_addons, + USERPREF_PT_studiolight_matcaps, + USERPREF_PT_studiolight_world, + USERPREF_PT_studiolight_camera, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 4f3396c9ed8..3a8fb3ce2f0 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -1483,7 +1483,7 @@ class VIEW3D_MT_object_clear(Menu): class VIEW3D_MT_object_specials(Menu): - bl_label = "Context Menu" + bl_label = "Object Context Menu" @classmethod def poll(cls, context): @@ -2113,7 +2113,7 @@ class VIEW3D_MT_particle(Menu): class VIEW3D_MT_particle_specials(Menu): - bl_label = "Context Menu" + bl_label = "Particle Context Menu" def draw(self, context): layout = self.layout @@ -2363,7 +2363,7 @@ class VIEW3D_MT_pose_apply(Menu): class VIEW3D_MT_pose_specials(Menu): - bl_label = "Context Menu" + bl_label = "Pose Context Menu" def draw(self, context): layout = self.layout @@ -2496,7 +2496,7 @@ class VIEW3D_MT_edit_mesh(Menu): class VIEW3D_MT_edit_mesh_specials(Menu): - bl_label = "Context Menu" + bl_label = "Mesh Context Menu" def draw(self, context): layout = self.layout @@ -3030,7 +3030,7 @@ class VIEW3D_MT_edit_curve_clean(Menu): class VIEW3D_MT_edit_curve_specials(Menu): - bl_label = "Context Menu" + bl_label = "Curve Context Menu" def draw(self, context): layout = self.layout @@ -3244,7 +3244,7 @@ class VIEW3D_MT_edit_armature(Menu): class VIEW3D_MT_armature_specials(Menu): - bl_label = "Context Menu" + bl_label = "Armature Context Menu" def draw(self, context): layout = self.layout @@ -3394,6 +3394,28 @@ class VIEW3D_MT_edit_gpencil_interpolate(Menu): layout.operator("gpencil.interpolate_sequence", text="Sequence") +class VIEW3D_PIE_object_mode(Menu): + bl_label = "Mode" + + def draw(self, context): + layout = self.layout + + pie = layout.menu_pie() + pie.operator_enum("OBJECT_OT_mode_set", "mode") + + +class VIEW3D_PIE_view(Menu): + bl_label = "View" + bl_idname = "VIEW3D_PIE_view" + + def draw(self, context): + layout = self.layout + + pie = layout.menu_pie() + pie.operator_enum("VIEW3D_OT_viewnumpad", "type") + pie.operator("view3d.view_selected", text="View Selected", icon='ZOOM_SELECTED') + + # ********** Panel ********** @@ -3476,31 +3498,6 @@ class VIEW3D_PT_view3d_cursor(Panel): layout.column().prop(view, "cursor_location", text="Location") -class VIEW3D_PT_view3d_name(Panel): - bl_space_type = 'VIEW_3D' - bl_region_type = 'UI' - bl_label = "Item" - - @classmethod - def poll(cls, context): - return (context.space_data and context.active_object) - - def draw(self, context): - layout = self.layout - - ob = context.active_object - row = layout.row() - row.label(text="", icon='OBJECT_DATA') - row.prop(ob, "name", text="") - - if ob.type == 'ARMATURE' and ob.mode in {'EDIT', 'POSE'}: - bone = context.active_bone - if bone: - row = layout.row() - row.label(text="", icon='BONE_DATA') - row.prop(bone, "name", text="") - - class VIEW3D_PT_shading(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'HEADER' @@ -3517,48 +3514,72 @@ class VIEW3D_PT_shading(Panel): shading = view.shading col = layout.column() - - if shading.type == 'SOLID': - col.row().prop(shading, "color_type", expand=True) - - if shading.color_type == 'SINGLE': - col.row().prop(shading, "single_color", text="") - + col.row().label("Lighting") if shading.type in ('SOLID', 'TEXTURED'): col.row().prop(shading, "light", expand=True) if shading.light == 'STUDIO': - col.row().template_icon_view(shading, "studio_light") + row = col.row() + row.template_icon_view(shading, "studio_light") + row.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='ZOOMIN') if shading.studio_light_orientation == 'WORLD': col.row().prop(shading, "studiolight_rot_z") - row = col.row() - row.prop(shading, "show_specular_highlight") + elif shading.light == 'MATCAP': + row = col.row() + row.template_icon_view(shading, "matcap") + sub = row.column() + sub.operator('VIEW3D_OT_toggle_matcap_flip', emboss=False, text="", icon='ARROW_LEFTRIGHT') + sub.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='ZOOMIN') + if shading.type == 'SOLID': col.separator() + col.row().label("Color") + col.row().prop(shading, "color_type", expand=True) - row = col.row() - row.prop(shading, "show_xray") - sub = row.row() - sub.active = shading.show_xray - sub.prop(shading, "xray_alpha", text="") - - row = col.row() - row.active = not shading.show_xray - row.prop(shading, "show_shadows") - sub = row.row() - sub.active = shading.show_shadows and not shading.show_xray - sub.prop(shading, "shadow_intensity", text="") + if shading.color_type == 'SINGLE': + col.row().prop(shading, "single_color", text="") - row = col.row() - row.prop(shading, "show_object_outline") - sub = row.row() - sub.active = shading.show_object_outline - sub.prop(shading, "object_outline_color", text="") + if shading.type in ('SOLID', 'TEXTURED'): + col.separator() - col.prop(view, "show_world") + if not shading.light == 'MATCAP': + row = col.row() + row.prop(shading, "show_specular_highlight") + + if shading.type in ('SOLID', 'TEXTURED'): + row = col.split(0.4) + row.prop(shading, "show_xray") + sub = row.row() + sub.active = shading.show_xray + sub.prop(shading, "xray_alpha", text="") + + row = col.split(0.4) + row.active = not shading.show_xray + row.prop(shading, "show_shadows") + sub = row.row() + sub.active = shading.show_shadows and not shading.show_xray + sub.prop(shading, "shadow_intensity", text="") + + row = col.split(0.4) + row.active = not shading.show_xray + row.prop(shading, "show_cavity") + sub = row.column(align=True) + sub.active = not shading.show_xray and shading.show_cavity + sub.prop(shading, "cavity_ridge_factor") + sub.prop(shading, "cavity_valley_factor") + + row = col.split(0.4) + row.prop(shading, "show_object_outline") + sub = row.row() + sub.active = shading.show_object_outline + sub.prop(shading, "object_outline_color", text="") + + col.prop(view, "show_world") elif shading.type in ('MATERIAL'): - col.row().template_icon_view(shading, "studio_light") + row = col.row() + row.template_icon_view(shading, "studio_light") + op = row.operator('wm.studiolight_userpref_show', emboss=False, text="", icon='ZOOMIN') if shading.studio_light_orientation == 'WORLD': col.row().prop(shading, "studiolight_rot_z") col.row().prop(shading, "studiolight_background") @@ -3580,7 +3601,6 @@ class VIEW3D_PT_overlay(Panel): view = context.space_data shading = view.shading overlay = view.overlay - scene = context.scene toolsettings = context.tool_settings display_all = overlay.show_overlays @@ -3596,7 +3616,13 @@ class VIEW3D_PT_overlay(Panel): col.prop(overlay, "show_relationship_lines") col.prop(overlay, "show_motion_paths") col.prop(overlay, "show_face_orientation") - col.prop(overlay, "show_wireframes") + + row = col.row() + row.prop(overlay, "show_wireframes") + sub = row.row() + sub.active = overlay.show_wireframes + sub.prop(overlay, "wireframe_threshold", text="") + col.prop(overlay, "show_backface_culling") if shading.type == "MATERIAL": @@ -3616,12 +3642,27 @@ class VIEW3D_PT_overlay(Panel): sub.active = bool(overlay.show_floor or view.region_quadviews or not view.region_3d.is_perspective) subsub = sub.column(align=True) subsub.active = overlay.show_floor - sub.prop(overlay, "grid_scale", text="Scale") - sub.prop(overlay, "grid_subdivisions", text="Subdivisions") + subsub.prop(overlay, "grid_scale", text="Scale") + subsub.prop(overlay, "grid_subdivisions", text="Subdivisions") + + col.prop(view, "show_reconstruction", text="Motion Tracking") + sub = col.column(align=True) + + sub.active = view.show_reconstruction + sub.prop(view, "show_camera_path", text="Camera Path") + sub.prop(view, "show_bundle_names", text="3D Marker Names") + sub.label(text="Track Type and Size:") + row = sub.row(align=True) + row.prop(view, "tracks_draw_type", text="") + row.prop(view, "tracks_draw_size", text="") + col.separator() if context.mode == 'EDIT_MESH': + data = context.active_object.data + statvis = context.tool_settings.statvis + with_freestyle = bpy.app.build_options.freestyle col.separator() - col.label(text="Edit Mode:") + col.label(text="Edit Mesh:") col.prop(overlay, "show_occlude_wire") @@ -3640,6 +3681,72 @@ class VIEW3D_PT_overlay(Panel): sub.active = overlay.show_vertex_normals or overlay.show_face_normals or overlay.show_split_normals sub.prop(overlay, "normals_length", text="Size") + split = col.split() + + sub = split.column() + sub.prop(data, "show_faces", text="Faces") + sub.prop(data, "show_edges", text="Edges") + sub.prop(data, "show_edge_crease", text="Creases") + + if with_freestyle: + sub.prop(data, "show_edge_seams", text="Seams") + + sub = split.column() + if not with_freestyle: + sub.prop(data, "show_edge_seams", text="Seams") + sub.prop(data, "show_edge_sharp", text="Sharp", text_ctxt=i18n_contexts.plural) + col.prop(data, "show_edge_bevel_weight", text="Bevel") + if with_freestyle: + sub.prop(data, "show_freestyle_edge_marks", text="Edge Marks") + sub.prop(data, "show_freestyle_face_marks", text="Face Marks") + + col.separator() + split = col.split() + sub = split.column() + sub.label(text="Edge Info:") + sub.prop(data, "show_extra_edge_length", text="Length") + sub.prop(data, "show_extra_edge_angle", text="Angle") + sub = split.column() + sub.label(text="Face Info:") + sub.prop(data, "show_extra_face_area", text="Area") + sub.prop(data, "show_extra_face_angle", text="Angle") + if bpy.app.debug: + sub.prop(data, "show_extra_indices", text="Indices") + + col.prop(data, "show_statvis", text="Mesh Analysis") + sub = col.column() + sub.active = data.show_statvis + sub.prop(statvis, "type") + statvis_type = statvis.type + if statvis_type == 'OVERHANG': + row = sub.row(align=True) + row.prop(statvis, "overhang_min", text="") + row.prop(statvis, "overhang_max", text="") + layout.row().prop(statvis, "overhang_axis", expand=True) + elif statvis_type == 'THICKNESS': + row = sub.row(align=True) + row.prop(statvis, "thickness_min", text="") + row.prop(statvis, "thickness_max", text="") + layout.prop(statvis, "thickness_samples") + elif statvis_type == 'INTERSECT': + pass + elif statvis_type == 'DISTORT': + row = sub.row(align=True) + row.prop(statvis, "distort_min", text="") + row.prop(statvis, "distort_max", text="") + elif statvis_type == 'SHARP': + row = sub.row(align=True) + row.prop(statvis, "sharp_min", text="") + row.prop(statvis, "sharp_max", text="") + + elif context.mode == 'EDIT_CURVE': + data = context.active_object.data + col.separator() + col.label(text="Edit Curve:") + row = col.row() + row.prop(data, "show_handles", text="Handles") + row.prop(data, "show_normal_face", text="Normals") + elif context.mode == 'POSE': col.separator() col.label(text="Pose Mode:") @@ -3647,7 +3754,11 @@ class VIEW3D_PT_overlay(Panel): col = layout.column() col.active = display_all col.prop(overlay, "show_transparent_bones") - col.prop(overlay, "show_bone_selection") + row = col.split(0.65) + row.prop(overlay, "show_bone_selection") + sub = row.column() + sub.active = display_all and overlay.show_bone_selection + sub.prop(overlay, "bone_selection_alpha", text="") elif context.mode == 'EDIT_ARMATURE': col.separator() @@ -3734,157 +3845,6 @@ class VIEW3D_PT_view3d_stereo(Panel): split.prop(view, "stereo_3d_volume_alpha", text="Alpha") -class VIEW3D_PT_view3d_motion_tracking(Panel): - bl_space_type = 'VIEW_3D' - bl_region_type = 'UI' - bl_label = "Motion Tracking" - bl_options = {'DEFAULT_CLOSED'} - - @classmethod - def poll(cls, context): - view = context.space_data - return (view) - - def draw_header(self, context): - view = context.space_data - - self.layout.prop(view, "show_reconstruction", text="") - - def draw(self, context): - layout = self.layout - - view = context.space_data - - col = layout.column() - col.active = view.show_reconstruction - col.prop(view, "show_camera_path", text="Camera Path") - col.prop(view, "show_bundle_names", text="3D Marker Names") - col.label(text="Track Type and Size:") - row = col.row(align=True) - row.prop(view, "tracks_draw_type", text="") - row.prop(view, "tracks_draw_size", text="") - - -class VIEW3D_PT_view3d_meshdisplay(Panel): - bl_space_type = 'VIEW_3D' - bl_region_type = 'UI' - bl_label = "Mesh Display" - - @classmethod - def poll(cls, context): - # The active object check is needed because of local-mode - return (context.active_object and (context.mode == 'EDIT_MESH')) - - def draw(self, context): - layout = self.layout - with_freestyle = bpy.app.build_options.freestyle - - mesh = context.active_object.data - scene = context.scene - - split = layout.split() - - col = split.column() - col.label(text="Overlays:") - col.prop(mesh, "show_faces", text="Faces") - col.prop(mesh, "show_edges", text="Edges") - col.prop(mesh, "show_edge_crease", text="Creases") - if with_freestyle: - col.prop(mesh, "show_edge_seams", text="Seams") - - col = split.column() - col.label() - if not with_freestyle: - col.prop(mesh, "show_edge_seams", text="Seams") - col.prop(mesh, "show_edge_sharp", text="Sharp", text_ctxt=i18n_contexts.plural) - col.prop(mesh, "show_edge_bevel_weight", text="Bevel") - if with_freestyle: - col.prop(mesh, "show_freestyle_edge_marks", text="Edge Marks") - col.prop(mesh, "show_freestyle_face_marks", text="Face Marks") - - col = layout.column() - - col.separator() - split = layout.split() - col = split.column() - col.label(text="Edge Info:") - col.prop(mesh, "show_extra_edge_length", text="Length") - col.prop(mesh, "show_extra_edge_angle", text="Angle") - col = split.column() - col.label(text="Face Info:") - col.prop(mesh, "show_extra_face_area", text="Area") - col.prop(mesh, "show_extra_face_angle", text="Angle") - if bpy.app.debug: - layout.prop(mesh, "show_extra_indices", text="Indices") - - -class VIEW3D_PT_view3d_meshstatvis(Panel): - bl_space_type = 'VIEW_3D' - bl_region_type = 'UI' - bl_label = "Mesh Analysis" - - @classmethod - def poll(cls, context): - # The active object check is needed because of local-mode - return (context.active_object and (context.mode == 'EDIT_MESH')) - - def draw_header(self, context): - mesh = context.active_object.data - - self.layout.prop(mesh, "show_statvis", text="") - - def draw(self, context): - layout = self.layout - - mesh = context.active_object.data - statvis = context.tool_settings.statvis - layout.active = mesh.show_statvis - - layout.prop(statvis, "type") - statvis_type = statvis.type - if statvis_type == 'OVERHANG': - row = layout.row(align=True) - row.prop(statvis, "overhang_min", text="") - row.prop(statvis, "overhang_max", text="") - layout.row().prop(statvis, "overhang_axis", expand=True) - elif statvis_type == 'THICKNESS': - row = layout.row(align=True) - row.prop(statvis, "thickness_min", text="") - row.prop(statvis, "thickness_max", text="") - layout.prop(statvis, "thickness_samples") - elif statvis_type == 'INTERSECT': - pass - elif statvis_type == 'DISTORT': - row = layout.row(align=True) - row.prop(statvis, "distort_min", text="") - row.prop(statvis, "distort_max", text="") - elif statvis_type == 'SHARP': - row = layout.row(align=True) - row.prop(statvis, "sharp_min", text="") - row.prop(statvis, "sharp_max", text="") - - -class VIEW3D_PT_view3d_curvedisplay(Panel): - bl_space_type = 'VIEW_3D' - bl_region_type = 'UI' - bl_label = "Curve Display" - - @classmethod - def poll(cls, context): - editmesh = context.mode == 'EDIT_CURVE' - return (editmesh) - - def draw(self, context): - layout = self.layout - - curve = context.active_object.data - - col = layout.column() - row = col.row() - row.prop(curve, "show_handles", text="Handles") - row.prop(curve, "show_normal_face", text="Normals") - - class VIEW3D_PT_transform_orientations(Panel): bl_space_type = 'VIEW_3D' bl_region_type = 'UI' @@ -4079,17 +4039,14 @@ classes = ( VIEW3D_MT_edit_armature_delete, VIEW3D_MT_edit_gpencil_transform, VIEW3D_MT_edit_gpencil_interpolate, + VIEW3D_PIE_object_mode, + VIEW3D_PIE_view, VIEW3D_PT_grease_pencil, VIEW3D_PT_grease_pencil_palettecolor, VIEW3D_PT_view3d_properties, VIEW3D_PT_view3d_cursor, - VIEW3D_PT_view3d_name, VIEW3D_PT_quad_view, VIEW3D_PT_view3d_stereo, - VIEW3D_PT_view3d_motion_tracking, - VIEW3D_PT_view3d_meshdisplay, - VIEW3D_PT_view3d_meshstatvis, - VIEW3D_PT_view3d_curvedisplay, VIEW3D_PT_shading, VIEW3D_PT_overlay, VIEW3D_PT_transform_orientations, diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index f6dc64c7df7..cb9ddd470ce 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -70,7 +70,7 @@ def draw_vpaint_symmetry(layout, vpaint): class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel): bl_category = "Options" - bl_context = ".mesh_edit" # dot on purpose (access from topbar) + bl_context = ".mesh_edit" # dot on purpose (access from topbar) bl_label = "Mesh Options" @classmethod @@ -101,9 +101,10 @@ class VIEW3D_PT_tools_meshedit_options(View3DPanel, Panel): # ********** default tools for editmode_curve **************** + class VIEW3D_PT_tools_curveedit_options_stroke(View3DPanel, Panel): bl_category = "Options" - bl_context = ".curve_edit" # dot on purpose (access from topbar) + bl_context = ".curve_edit" # dot on purpose (access from topbar) bl_label = "Curve Stroke" def draw(self, context): @@ -155,8 +156,6 @@ class VIEW3D_PT_tools_curveedit_options_stroke(View3DPanel, Panel): colsub.prop(cps, "surface_plane", expand=True) - - # ********** default tools for editmode_armature **************** @@ -175,7 +174,7 @@ class VIEW3D_PT_tools_armatureedit_options(View3DPanel, Panel): class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel): bl_category = "Options" - bl_context = ".posemode" # dot on purpose (access from topbar) + bl_context = ".posemode" # dot on purpose (access from topbar) bl_label = "Pose Options" def draw(self, context): @@ -194,7 +193,7 @@ class View3DPaintPanel(UnifiedPaintPanel): class VIEW3D_PT_imapaint_tools_missing(Panel, View3DPaintPanel): bl_category = "Tools" - bl_context = ".imagepaint" # dot on purpose (access from topbar) + bl_context = ".imagepaint" # dot on purpose (access from topbar) bl_label = "Missing Data" @classmethod @@ -528,7 +527,7 @@ class VIEW3D_MT_tools_projectpaint_uvlayer(Menu): class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel): - bl_context = ".imagepaint" # dot on purpose (access from topbar) + bl_context = ".imagepaint" # dot on purpose (access from topbar) bl_label = "Slots" bl_category = "Slots" @@ -589,7 +588,7 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel): class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel): - bl_context = ".imagepaint" # dot on purpose (access from topbar) + bl_context = ".imagepaint" # dot on purpose (access from topbar) bl_label = "Mask" bl_category = "Slots" @@ -723,7 +722,7 @@ class VIEW3D_PT_tools_brush_texture(Panel, View3DPaintPanel): class VIEW3D_PT_tools_mask_texture(Panel, View3DPaintPanel): bl_category = "Tools" - bl_context = ".imagepaint" # dot on purpose (access from topbar) + bl_context = ".imagepaint" # dot on purpose (access from topbar) bl_label = "Texture Mask" bl_options = {'DEFAULT_CLOSED'} @@ -886,11 +885,11 @@ class VIEW3D_PT_sculpt_dyntopo(Panel, View3DPaintPanel): def draw_header(self, context): layout = self.layout layout.operator( - "sculpt.dynamic_topology_toggle", - icon='CHECKBOX_HLT' if context.sculpt_object.use_dynamic_topology_sculpting else 'CHECKBOX_DEHLT', - text="", - emboss=False, - ) + "sculpt.dynamic_topology_toggle", + icon='CHECKBOX_HLT' if context.sculpt_object.use_dynamic_topology_sculpting else 'CHECKBOX_DEHLT', + text="", + emboss=False, + ) def draw(self, context): layout = self.layout @@ -1124,7 +1123,7 @@ class VIEW3D_PT_tools_vertexpaint_symmetry(Panel, View3DPaintPanel): class VIEW3D_PT_tools_imagepaint_external(Panel, View3DPaintPanel): bl_category = "Tools" - bl_context = ".imagepaint" # dot on purpose (access from topbar) + bl_context = ".imagepaint" # dot on purpose (access from topbar) bl_label = "External" bl_options = {'DEFAULT_CLOSED'} @@ -1146,7 +1145,7 @@ class VIEW3D_PT_tools_imagepaint_external(Panel, View3DPaintPanel): class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel): bl_category = "Tools" - bl_context = ".imagepaint" # dot on purpose (access from topbar) + bl_context = ".imagepaint" # dot on purpose (access from topbar) bl_label = "Symmetry" bl_options = {'DEFAULT_CLOSED'} @@ -1165,7 +1164,7 @@ class VIEW3D_PT_tools_imagepaint_symmetry(Panel, View3DPaintPanel): class VIEW3D_PT_tools_projectpaint(View3DPaintPanel, Panel): bl_category = "Options" - bl_context = ".imagepaint" # dot on purpose (access from topbar) + bl_context = ".imagepaint" # dot on purpose (access from topbar) bl_label = "Project Paint" @classmethod @@ -1323,6 +1322,8 @@ class VIEW3D_PT_tools_grease_pencil_brush(GreasePencilBrushPanel, Panel): bl_space_type = 'VIEW_3D' # Grease Pencil drawingcurves + + class VIEW3D_PT_tools_grease_pencil_brushcurves(GreasePencilBrushCurvesPanel, Panel): bl_space_type = 'VIEW_3D' |