diff options
Diffstat (limited to 'release/scripts')
16 files changed, 379 insertions, 107 deletions
diff --git a/release/scripts/modules/bpy_extras/__init__.py b/release/scripts/modules/bpy_extras/__init__.py index 1af9048ebfd..15a8d00cddc 100644 --- a/release/scripts/modules/bpy_extras/__init__.py +++ b/release/scripts/modules/bpy_extras/__init__.py @@ -16,4 +16,5 @@ __all__ = ( "mesh_utils", "node_utils", "view3d_utils", + "id_map_utils", ) diff --git a/release/scripts/modules/bpy_extras/id_map_utils.py b/release/scripts/modules/bpy_extras/id_map_utils.py new file mode 100644 index 00000000000..cf39f2185c6 --- /dev/null +++ b/release/scripts/modules/bpy_extras/id_map_utils.py @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: GPL-2.0-or-later + +# <pep8 compliant> + +from typing import Dict, Set +import bpy +from bpy.types import ID + + +__all__ = ( + "get_id_reference_map", + "get_all_referenced_ids", +) + + +def get_id_reference_map() -> Dict[ID, Set[ID]]: + """Return a dictionary of direct datablock references for every datablock in the blend file.""" + inv_map = {} + for key, values in bpy.data.user_map().items(): + for value in values: + if value == key: + # So an object is not considered to be referencing itself. + continue + inv_map.setdefault(value, set()).add(key) + return inv_map + + +def recursive_get_referenced_ids( + ref_map: Dict[ID, Set[ID]], id: ID, referenced_ids: Set, visited: Set +): + """Recursively populate referenced_ids with IDs referenced by id.""" + if id in visited: + # Avoid infinite recursion from circular references. + return + visited.add(id) + for ref in ref_map.get(id, []): + referenced_ids.add(ref) + recursive_get_referenced_ids( + ref_map=ref_map, id=ref, referenced_ids=referenced_ids, visited=visited + ) + + +def get_all_referenced_ids(id: ID, ref_map: Dict[ID, Set[ID]]) -> Set[ID]: + """Return a set of IDs directly or indirectly referenced by id.""" + referenced_ids = set() + recursive_get_referenced_ids( + ref_map=ref_map, id=id, referenced_ids=referenced_ids, visited=set() + ) + return referenced_ids diff --git a/release/scripts/modules/bpy_types.py b/release/scripts/modules/bpy_types.py index b3f0c055769..4c6e2508859 100644 --- a/release/scripts/modules/bpy_types.py +++ b/release/scripts/modules/bpy_types.py @@ -1145,3 +1145,11 @@ class TextureNode(NodeInternal): @classmethod def poll(cls, ntree): return ntree.bl_idname == 'TextureNodeTree' + + +class GeometryNode(NodeInternal): + __slots__ = () + + @classmethod + def poll(cls, ntree): + return ntree.bl_idname == 'GeometryNodeTree' diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py index 64e0917da65..3e0d3dadcf1 100644 --- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py +++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py @@ -1300,6 +1300,8 @@ def km_uv_editor(params): {"properties": [("data_path", 'tool_settings.use_snap_uv')]}), ("wm.context_menu_enum", {"type": 'TAB', "value": 'PRESS', "shift": True, "ctrl": True}, {"properties": [("data_path", 'tool_settings.snap_uv_element')]}), + ("wm.context_toggle", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "ctrl": True}, + {"properties": [("data_path", 'space_data.show_gizmo')]}), *_template_items_context_menu("IMAGE_MT_uvs_context_menu", params.context_menu_event), ]) @@ -1967,6 +1969,8 @@ def km_image(params): ), ("image.render_border", {"type": 'B', "value": 'PRESS', "ctrl": True}, None), ("image.clear_render_border", {"type": 'B', "value": 'PRESS', "ctrl": True, "alt": True}, None), + ("wm.context_toggle", {"type": 'ACCENT_GRAVE', "value": 'PRESS', "ctrl": True}, + {"properties": [("data_path", 'space_data.show_gizmo')]}), *_template_items_context_menu("IMAGE_MT_mask_context_menu", params.context_menu_event), ]) @@ -3960,6 +3964,8 @@ def km_grease_pencil_stroke_sculpt_mode(params): ("gpencil.active_frames_delete_all", {"type": 'DEL', "value": 'PRESS', "shift": True}, None), # Active layer op_menu("GPENCIL_MT_layer_active", {"type": 'Y', "value": 'PRESS'}), + # Active material + op_menu("GPENCIL_MT_material_active", {"type": 'U', "value": 'PRESS'}), # Merge Layer ("gpencil.layer_merge", {"type": 'M', "value": 'PRESS', "shift": True, "ctrl": True}, None), # Keyframe menu diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index d6e21053e3b..a421428c067 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -203,7 +203,7 @@ class DATA_PT_geometry_curve_start_end(CurveButtonsPanelCurve, Panel): @classmethod def poll(cls, context): # Text objects don't support these properties - return (type(context.curve) in {Curve}) + return (type(context.curve) == Curve) def draw(self, context): layout = self.layout 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 481753d5e79..189210d8540 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -41,17 +41,7 @@ class AnnotationDrawingToolsPanel: row.prop_enum(tool_settings, "annotation_stroke_placement_view2d", 'IMAGE', text="Image") -class GreasePencilSculptOptionsPanel: - bl_label = "Sculpt Strokes" - - @classmethod - def poll(cls, context): - tool_settings = context.scene.tool_settings - settings = tool_settings.gpencil_sculpt_paint - brush = settings.brush - tool = brush.gpencil_sculpt_tool - - return bool(tool in {'SMOOTH', 'RANDOMIZE'}) +class GreasePencilSculptAdvancedPanel: def draw(self, context): layout = self.layout @@ -59,17 +49,21 @@ class GreasePencilSculptOptionsPanel: layout.use_property_decorate = False tool_settings = context.scene.tool_settings - settings = tool_settings.gpencil_sculpt_paint - brush = settings.brush - gp_settings = brush.gpencil_settings + brush = context.tool_settings.gpencil_sculpt_paint.brush tool = brush.gpencil_sculpt_tool + gp_settings = brush.gpencil_settings - if tool in {'SMOOTH', 'RANDOMIZE'}: - layout.prop(gp_settings, "use_edit_position", text="Affect Position") - layout.prop(gp_settings, "use_edit_strength", text="Affect Strength") - layout.prop(gp_settings, "use_edit_thickness", text="Affect Thickness") + col = layout.column(heading="Auto-Masking", align=True) + col.prop(gp_settings, "use_automasking_stroke", text="Stroke") + col.prop(gp_settings, "use_automasking_layer", text="Layer") + col.prop(gp_settings, "use_automasking_material", text="Material") - layout.prop(gp_settings, "use_edit_uv", text="Affect UV") + if tool in {'SMOOTH', 'RANDOMIZE'}: + col = layout.column(heading="Affect", align=True) + col.prop(gp_settings, "use_edit_position", text="Position") + col.prop(gp_settings, "use_edit_strength", text="Strength") + col.prop(gp_settings, "use_edit_thickness", text="Thickness") + col.prop(gp_settings, "use_edit_uv", text="UV") # GP Object Tool Settings diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 9a116aa1717..b8136f26e90 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -405,7 +405,13 @@ class FalloffPanel(BrushPanel): if not super().poll(context): return False settings = cls.paint_settings(context) - return (settings and settings.brush and settings.brush.curve) + if not (settings and settings.brush and settings.brush.curve): + return False + if cls.get_brush_mode(context) == 'SCULPT_CURVES': + brush = settings.brush + if brush.curves_sculpt_tool in {'ADD', 'DELETE'}: + return False + return True def draw(self, context): layout = self.layout @@ -432,7 +438,13 @@ class FalloffPanel(BrushPanel): row.operator("brush.curve_preset", icon='LINCURVE', text="").shape = 'LINE' row.operator("brush.curve_preset", icon='NOCURVE', text="").shape = 'MAX' - if mode in {'SCULPT', 'PAINT_VERTEX', 'PAINT_WEIGHT', 'SCULPT_CURVES'} and brush.sculpt_tool != 'POSE': + show_fallof_shape = False + if mode in {'SCULPT', 'PAINT_VERTEX', 'PAINT_WEIGHT'} and brush.sculpt_tool != 'POSE': + show_fallof_shape = True + if not show_fallof_shape and mode == 'SCULPT_CURVES' and context.space_data.type == 'PROPERTIES': + show_fallof_shape = True + + if show_fallof_shape: col.separator() row = col.row(align=True) row.use_property_split = True @@ -769,6 +781,27 @@ def brush_settings(layout, context, brush, popover=False): elif brush.color_type == 'GRADIENT': layout.row().prop(brush, "gradient_fill_mode", expand=True) + elif mode == 'SCULPT_CURVES': + if brush.curves_sculpt_tool == 'ADD': + layout.prop(brush.curves_sculpt_settings, "add_amount") + layout.prop(brush.curves_sculpt_settings, "curve_length") + col = layout.column(heading="Interpolate", align=True) + col.prop(brush.curves_sculpt_settings, "interpolate_length", text="Length") + col.prop(brush.curves_sculpt_settings, "interpolate_shape", text="Shape") + col.prop(brush.curves_sculpt_settings, "interpolate_point_count", text="Point Count") + + col = layout.column() + col.active = not brush.curves_sculpt_settings.interpolate_length + col.prop(brush.curves_sculpt_settings, "curve_length") + + col = layout.column() + col.active = not brush.curves_sculpt_settings.interpolate_point_count + col.prop(brush.curves_sculpt_settings, "points_per_curve") + use_frontface = True + elif brush.curves_sculpt_tool == 'GROW_SHRINK': + layout.prop(brush.curves_sculpt_settings, "scale_uniform") + layout.prop(brush.curves_sculpt_settings, "minimum_length") + def brush_shared_settings(layout, context, brush, popover=False): """ Draw simple brush settings that are shared between different paint modes. """ @@ -827,6 +860,7 @@ def brush_shared_settings(layout, context, brush, popover=False): if mode == 'SCULPT_CURVES': size = True strength = True + direction = brush.curves_sculpt_tool == 'GROW_SHRINK' ### Draw settings. ### ups = context.scene.tool_settings.unified_paint_settings @@ -925,16 +959,6 @@ def brush_settings_advanced(layout, context, brush, popover=False): col.prop(brush, "use_original_plane", text="Plane") layout.separator() - elif mode == 'SCULPT_CURVES': - if brush.curves_sculpt_tool == 'ADD': - layout.prop(brush.curves_sculpt_settings, "add_amount") - layout.prop(brush.curves_sculpt_settings, "curve_length") - layout.prop(brush.curves_sculpt_settings, "interpolate_length") - layout.prop(brush.curves_sculpt_settings, "interpolate_shape") - elif brush.curves_sculpt_tool == 'GROW_SHRINK': - layout.prop(brush.curves_sculpt_settings, "scale_uniform") - layout.prop(brush.curves_sculpt_settings, "minimum_length") - # 3D and 2D Texture Paint. elif mode in {'PAINT_TEXTURE', 'PAINT_2D'}: capabilities = brush.image_paint_capabilities diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index 0b7a728fa95..3d6ad2ece9b 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -54,8 +54,10 @@ class PARTICLE_MT_context_menu(Menu): bl_label = "Particle Specials" COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_EEVEE', 'BLENDER_WORKBENCH'} - def draw(self, _context): + def draw(self, context): layout = self.layout + psys = context.particle_system + experimental = context.preferences.experimental props = layout.operator( "particle.copy_particle_systems", @@ -72,6 +74,11 @@ class PARTICLE_MT_context_menu(Menu): props.use_active = False props.remove_target_particles = True + if experimental.use_new_curves_type and psys.settings.type == 'HAIR': + layout.operator( + "curves.convert_from_particle_system", + text="Convert to Curves") + layout.separator() layout.operator( diff --git a/release/scripts/startup/bl_ui/properties_physics_field.py b/release/scripts/startup/bl_ui/properties_physics_field.py index c1b213766df..2e7e68f02ef 100644 --- a/release/scripts/startup/bl_ui/properties_physics_field.py +++ b/release/scripts/startup/bl_ui/properties_physics_field.py @@ -77,7 +77,6 @@ class PHYSICS_PT_field_settings(PhysicButtonsPanel, Panel): elif field.type == 'GUIDE': col = flow.column() - col.prop(field, "guide_minimum") col.prop(field, "guide_free") col.prop(field, "falloff_power") col.prop(field, "use_guide_path_add") @@ -88,11 +87,20 @@ class PHYSICS_PT_field_settings(PhysicButtonsPanel, Panel): col = flow.column() col.prop(field, "guide_clump_amount", text="Clumping Amount") col.prop(field, "guide_clump_shape") - col.prop(field, "use_max_distance") - sub = col.column() + col.separator() + + col.prop(field, "guide_minimum", text="Min Distance") + + col = layout.column(align=False, heading="Max Distance") + col.use_property_decorate = False + row = col.row(align=True) + sub = row.row(align=True) + sub.prop(field, "use_max_distance", text="") + sub = sub.row(align=True) sub.active = field.use_max_distance - sub.prop(field, "distance_max") + sub.prop(field, "distance_max", text="") + row.prop_decorator(field, "distance_max") elif field.type == 'TEXTURE': col = flow.column() diff --git a/release/scripts/startup/bl_ui/properties_texture.py b/release/scripts/startup/bl_ui/properties_texture.py index 5ceaf8fc644..1f9362f02b5 100644 --- a/release/scripts/startup/bl_ui/properties_texture.py +++ b/release/scripts/startup/bl_ui/properties_texture.py @@ -840,7 +840,6 @@ class TEXTURE_PT_colors_ramp(TextureButtonsPanel, TextureColorsPoll, Panel): if is_active: layout.template_color_ramp(tex, "color_ramp", expand=True) else: - layout.alignment = 'RIGHT' layout.label(text="Enable the Color Ramp first") diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 1dd50c979e2..d61055c9024 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -806,6 +806,13 @@ class IMAGE_HT_header(Header): layout.separator_spacer() + # Gizmo toggle & popover. + row = layout.row(align=True) + row.prop(sima, "show_gizmo", icon='GIZMO', text="") + sub = row.row(align=True) + sub.active = sima.show_gizmo + sub.popover(panel="IMAGE_PT_gizmo_display", text="") + # Overlay toggle & popover row = layout.row(align=True) row.prop(overlay, "show_overlays", icon='OVERLAY', text="") @@ -1453,6 +1460,26 @@ class IMAGE_PT_uv_cursor(Panel): col.prop(sima, "cursor_location", text="Location") +class IMAGE_PT_gizmo_display(Panel): + bl_space_type = 'IMAGE_EDITOR' + bl_region_type = 'HEADER' + bl_label = "Gizmos" + bl_ui_units_x = 8 + + def draw(self, context): + layout = self.layout + + view = context.space_data + + col = layout.column() + col.label(text="Viewport Gizmos") + col.separator() + + col.active = view.show_gizmo + colsub = col.column() + colsub.prop(view, "show_gizmo_navigate", text="Navigate") + + class IMAGE_PT_overlay(Panel): bl_space_type = 'IMAGE_EDITOR' bl_region_type = 'HEADER' @@ -1680,6 +1707,7 @@ classes = ( IMAGE_PT_scope_sample, IMAGE_PT_uv_cursor, IMAGE_PT_annotation, + IMAGE_PT_gizmo_display, IMAGE_PT_overlay, IMAGE_PT_overlay_guides, IMAGE_PT_overlay_uv_edit, diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 7c7bb456473..94bad5459c9 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -611,7 +611,16 @@ class SEQUENCER_MT_change(Menu): strip = context.active_sequence_strip layout.operator_context = 'INVOKE_REGION_WIN' + if strip and strip.type == 'SCENE': + bpy_data_scenes_len = len(bpy.data.scenes) + if bpy_data_scenes_len > 10: + layout.operator_context = 'INVOKE_DEFAULT' + layout.operator("sequencer.change_scene", text="Change Scene...") + elif bpy_data_scenes_len > 1: + layout.operator_menu_enum("sequencer.change_scene", "scene", text="Change Scene") + del bpy_data_scenes_len + layout.operator_context = 'INVOKE_DEFAULT' layout.operator_menu_enum("sequencer.change_effect_input", "swap") layout.operator_menu_enum("sequencer.change_effect_type", "type") prop = layout.operator("sequencer.change_path", text="Path/Files") @@ -667,15 +676,7 @@ class SEQUENCER_MT_add(Menu): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' - bpy_data_scenes_len = len(bpy.data.scenes) - if bpy_data_scenes_len > 10: - layout.operator_context = 'INVOKE_DEFAULT' - layout.operator("sequencer.scene_strip_add", text="Scene...", icon='SCENE_DATA') - elif bpy_data_scenes_len > 1: - layout.operator_menu_enum("sequencer.scene_strip_add", "scene", text="Scene", icon='SCENE_DATA') - else: - layout.menu("SEQUENCER_MT_add_empty", text="Scene", icon='SCENE_DATA') - del bpy_data_scenes_len + layout.menu("SEQUENCER_MT_add_scene", text="Scene", icon='SCENE_DATA') bpy_data_movieclips_len = len(bpy.data.movieclips) if bpy_data_movieclips_len > 10: @@ -725,6 +726,34 @@ class SEQUENCER_MT_add(Menu): col.enabled = selected_sequences_len(context) >= 1 +class SEQUENCER_MT_add_scene(Menu): + bl_label = "Scene" + bl_translation_context = i18n_contexts.operator_default + + def draw(self, context): + + layout = self.layout + layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator("sequencer.scene_strip_add_new", text="New Scene", icon="ADD").type = 'NEW' + + bpy_data_scenes_len = len(bpy.data.scenes) + if bpy_data_scenes_len > 10: + layout.separator() + layout.operator_context = 'INVOKE_DEFAULT' + layout.operator("sequencer.scene_strip_add", text="Scene...", icon='SCENE_DATA') + elif bpy_data_scenes_len > 1: + layout.separator() + scene = context.scene + for sc_item in bpy.data.scenes: + if sc_item == scene: + continue + + layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator("sequencer.scene_strip_add", text=sc_item.name).scene = sc_item.name + + del bpy_data_scenes_len + + class SEQUENCER_MT_add_empty(Menu): bl_label = "Empty" @@ -917,6 +946,9 @@ class SEQUENCER_MT_strip(Menu): strip = context.active_sequence_strip + if strip and strip.type == 'SCENE': + layout.operator("sequencer.delete", text="Delete Strip & Data").delete_data = True + if has_sequencer: if strip: strip_type = strip.type @@ -1035,6 +1067,10 @@ class SEQUENCER_MT_context_menu(Menu): props.keep_open = False layout.operator("sequencer.delete", text="Delete") + strip = context.active_sequence_strip + if strip and strip.type == 'SCENE': + layout.operator("sequencer.delete", text="Delete Strip & Data").delete_data = True + layout.separator() layout.operator("sequencer.slip", text="Slip Strip Contents") @@ -2600,6 +2636,7 @@ classes = ( SEQUENCER_MT_marker, SEQUENCER_MT_navigation, SEQUENCER_MT_add, + SEQUENCER_MT_add_scene, SEQUENCER_MT_add_effect, SEQUENCER_MT_add_transitions, SEQUENCER_MT_add_empty, diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index af56b966f17..d4d1e6ace76 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -2274,6 +2274,7 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel): self._draw_items( context, ( ({"property": "use_new_curves_type"}, "T68981"), + ({"property": "use_new_curves_tools"}, "T68981"), ({"property": "use_new_point_cloud_type"}, "T75717"), ({"property": "use_full_frame_compositor"}, "T88150"), ({"property": "enable_eevee_next"}, "T93220"), diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index a8624030564..995b2afebf0 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -109,8 +109,8 @@ class VIEW3D_HT_tool_header(Header): if is_valid_context: brush = context.tool_settings.gpencil_sculpt_paint.brush tool = brush.gpencil_sculpt_tool - if tool in {'SMOOTH', 'RANDOMIZE'}: - layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_options") + if tool != 'CLONE': + layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_brush_popover") layout.popover("VIEW3D_PT_tools_grease_pencil_sculpt_appearance") elif tool_mode == 'WEIGHT_GPENCIL': if is_valid_context: @@ -151,6 +151,11 @@ class VIEW3D_HT_tool_header(Header): row.popover(panel="VIEW3D_PT_sculpt_symmetry_for_topbar", text="") elif mode_string == 'PAINT_VERTEX': row.popover(panel="VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar", text="") + elif mode_string == 'SCULPT_CURVES': + _row, sub = row_for_mirror() + sub.prop(context.object.data, "use_mirror_x", text="X", toggle=True) + sub.prop(context.object.data, "use_mirror_y", text="Y", toggle=True) + sub.prop(context.object.data, "use_mirror_z", text="Z", toggle=True) # Expand panels from the side-bar as popovers. popover_kw = {"space_type": 'VIEW_3D', "region_type": 'UI', "category": "Tool"} @@ -241,7 +246,7 @@ class _draw_tool_settings_context_mode: unified_name="use_unified_size", text="Radius", slider=True, - header=True + header=True, ) # strength, use_strength_pressure @@ -254,7 +259,7 @@ class _draw_tool_settings_context_mode: pressure_name=pressure_name, unified_name="use_unified_strength", text="Strength", - header=True + header=True, ) # direction @@ -315,7 +320,7 @@ class _draw_tool_settings_context_mode: "weight", unified_name="use_unified_weight", slider=True, - header=True + header=True, ) UnifiedPaintPanel.prop_unified( @@ -327,7 +332,7 @@ class _draw_tool_settings_context_mode: unified_name="use_unified_size", slider=True, text="Radius", - header=True + header=True, ) UnifiedPaintPanel.prop_unified( layout, @@ -336,7 +341,7 @@ class _draw_tool_settings_context_mode: "strength", pressure_name="use_pressure_strength", unified_name="use_unified_strength", - header=True + header=True, ) return True @@ -479,7 +484,6 @@ class _draw_tool_settings_context_mode: tool_settings = context.tool_settings paint = tool_settings.curves_sculpt - layout.template_ID_preview(paint, "brush", rows=3, cols=8, hide_buttons=True) brush = paint.brush if brush is None: @@ -491,9 +495,10 @@ class _draw_tool_settings_context_mode: brush, "size", unified_name="use_unified_size", + pressure_name="use_pressure_size", text="Radius", slider=True, - header=True + header=True, ) if brush.curves_sculpt_tool not in {'ADD', 'DELETE'}: @@ -503,31 +508,29 @@ class _draw_tool_settings_context_mode: brush, "strength", unified_name="use_unified_strength", - header=True + pressure_name="use_pressure_strength", + header=True, ) if brush.curves_sculpt_tool == 'COMB': layout.prop(brush, "falloff_shape", expand=True) - layout.prop(brush, "curve_preset") + layout.popover("VIEW3D_PT_tools_brush_falloff") if brush.curves_sculpt_tool == 'ADD': - layout.prop(brush, "use_frontface") layout.prop(brush, "falloff_shape", expand=True) layout.prop(brush.curves_sculpt_settings, "add_amount") - layout.prop(brush.curves_sculpt_settings, "curve_length") - layout.prop(brush.curves_sculpt_settings, "interpolate_length") - layout.prop(brush.curves_sculpt_settings, "interpolate_shape") + layout.popover("VIEW3D_PT_curves_sculpt_add_shape", text="Curve Shape") + layout.prop(brush, "use_frontface", text="Front Faces Only") if brush.curves_sculpt_tool == 'GROW_SHRINK': layout.prop(brush, "direction", expand=True, text="") layout.prop(brush, "falloff_shape", expand=True) - layout.prop(brush.curves_sculpt_settings, "scale_uniform") - layout.prop(brush.curves_sculpt_settings, "minimum_length") - layout.prop(brush, "curve_preset") + layout.popover("VIEW3D_PT_curves_sculpt_grow_shrink_scaling", text="Scaling") + layout.popover("VIEW3D_PT_tools_brush_falloff") if brush.curves_sculpt_tool == 'SNAKE_HOOK': layout.prop(brush, "falloff_shape", expand=True) - layout.prop(brush, "curve_preset") + layout.popover("VIEW3D_PT_tools_brush_falloff") if brush.curves_sculpt_tool == 'DELETE': layout.prop(brush, "falloff_shape", expand=True) @@ -2035,7 +2038,7 @@ class VIEW3D_MT_curve_add(Menu): bl_idname = "VIEW3D_MT_curve_add" bl_label = "Curve" - def draw(self, _context): + def draw(self, context): layout = self.layout layout.operator_context = 'INVOKE_REGION_WIN' @@ -2049,18 +2052,14 @@ class VIEW3D_MT_curve_add(Menu): layout.operator("curve.primitive_nurbs_circle_add", text="Nurbs Circle", icon='CURVE_NCIRCLE') layout.operator("curve.primitive_nurbs_path_add", text="Path", icon='CURVE_PATH') + experimental = context.preferences.experimental + if experimental.use_new_curves_type: + layout.separator() -class VIEW3D_MT_curves_add(Menu): - bl_idname = "VIEW3D_MT_curves_add" - bl_label = "Curves" - - def draw(self, _context): - layout = self.layout - - layout.operator_context = 'INVOKE_REGION_WIN' + layout.operator("object.curves_empty_hair_add", text="Empty Hair", icon='CURVES_DATA') - layout.operator("object.curves_empty_hair_add", text="Empty Hair", icon='CURVES_DATA') - layout.operator("object.curves_random_add", text="Random", icon='CURVES_DATA') + if experimental.use_new_curves_tools: + layout.operator("object.curves_random_add", text="Random", icon='CURVES_DATA') class VIEW3D_MT_surface_add(Menu): @@ -2215,8 +2214,6 @@ class VIEW3D_MT_add(Menu): # layout.operator_menu_enum("object.curve_add", "type", text="Curve", icon='OUTLINER_OB_CURVE') layout.menu("VIEW3D_MT_curve_add", icon='OUTLINER_OB_CURVE') - if context.preferences.experimental.use_new_curves_type: - layout.menu("VIEW3D_MT_curves_add", icon='OUTLINER_OB_CURVES') # layout.operator_menu_enum("object.surface_add", "type", text="Surface", icon='OUTLINER_OB_SURFACE') layout.menu("VIEW3D_MT_surface_add", icon='OUTLINER_OB_SURFACE') layout.menu("VIEW3D_MT_metaball_add", text="Metaball", icon='OUTLINER_OB_META') @@ -2345,6 +2342,7 @@ class VIEW3D_MT_object(Menu): layout.separator() layout.operator("object.shade_smooth") + layout.operator("object.shade_smooth", text="Shade Auto Smooth").use_auto_smooth = True layout.operator("object.shade_flat") layout.separator() @@ -2587,7 +2585,8 @@ class VIEW3D_MT_object_context_menu(Menu): # Shared among some object types. if obj is not None: if obj.type in {'MESH', 'CURVE', 'SURFACE'}: - layout.operator("object.shade_smooth", text="Shade Smooth") + layout.operator("object.shade_smooth") + layout.operator("object.shade_smooth", text="Shade Auto Smooth").use_auto_smooth = True layout.operator("object.shade_flat", text="Shade Flat") layout.separator() @@ -3147,7 +3146,9 @@ class VIEW3D_MT_sculpt_curves(Menu): def draw(self, _context): layout = self.layout - layout.operator("curves.snap_curves_to_surface") + layout.operator("curves.snap_curves_to_surface", text="Snap to Deformed Surface").attach_mode = 'DEFORM' + layout.operator("curves.snap_curves_to_surface", text="Snap to Nearest Surface").attach_mode = 'NEAREST' + layout.separator() layout.operator("curves.convert_to_particle_system", text="Convert to Particle System") @@ -7612,6 +7613,55 @@ class TOPBAR_PT_gpencil_vertexcolor(GreasePencilVertexcolorPanel, Panel): return ob and ob.type == 'GPENCIL' +class VIEW3D_PT_curves_sculpt_add_shape(Panel): + # Only for popover, these are dummy values. + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_label = "Curves Sculpt Add Curve Options" + + def draw(self, context): + layout = self.layout + + layout.use_property_split = True + layout.use_property_decorate = False # No animation. + + settings = UnifiedPaintPanel.paint_settings(context) + brush = settings.brush + + col = layout.column(heading="Interpolate", align=True) + col.prop(brush.curves_sculpt_settings, "interpolate_length", text="Length") + col.prop(brush.curves_sculpt_settings, "interpolate_shape", text="Shape") + col.prop(brush.curves_sculpt_settings, "interpolate_point_count", text="Point Count") + + col = layout.column() + col.active = not brush.curves_sculpt_settings.interpolate_length + col.prop(brush.curves_sculpt_settings, "curve_length", text="Length") + + col = layout.column() + col.active = not brush.curves_sculpt_settings.interpolate_point_count + col.prop(brush.curves_sculpt_settings, "points_per_curve", text="Points") + + +class VIEW3D_PT_curves_sculpt_grow_shrink_scaling(Panel): + # Only for popover, these are dummy values. + bl_space_type = 'VIEW_3D' + bl_region_type = 'WINDOW' + bl_label = "Curves Grow/Shrink Scaling" + bl_ui_units_x = 12 + + def draw(self, context): + layout = self.layout + + layout.use_property_split = True + layout.use_property_decorate = False # No animation. + + settings = UnifiedPaintPanel.paint_settings(context) + brush = settings.brush + + layout.prop(brush.curves_sculpt_settings, "scale_uniform") + layout.prop(brush.curves_sculpt_settings, "minimum_length") + + classes = ( VIEW3D_HT_header, VIEW3D_HT_tool_header, @@ -7654,7 +7704,6 @@ classes = ( VIEW3D_MT_angle_control, VIEW3D_MT_mesh_add, VIEW3D_MT_curve_add, - VIEW3D_MT_curves_add, VIEW3D_MT_surface_add, VIEW3D_MT_edit_metaball_context_menu, VIEW3D_MT_metaball_add, @@ -7844,6 +7893,8 @@ classes = ( TOPBAR_PT_gpencil_materials, TOPBAR_PT_gpencil_vertexcolor, TOPBAR_PT_annotation_layers, + VIEW3D_PT_curves_sculpt_add_shape, + VIEW3D_PT_curves_sculpt_grow_shrink_scaling, ) diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 570d7c12e30..3e1754fd908 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -3,7 +3,7 @@ # <pep8 compliant> from bpy.types import Menu, Panel, UIList from bl_ui.properties_grease_pencil_common import ( - GreasePencilSculptOptionsPanel, + GreasePencilSculptAdvancedPanel, GreasePencilDisplayPanel, GreasePencilBrushFalloff, ) @@ -391,6 +391,11 @@ class VIEW3D_PT_tools_brush_settings_advanced(Panel, View3DPaintBrushPanel): bl_options = {'DEFAULT_CLOSED'} bl_ui_units_x = 14 + @classmethod + def poll(cls, context): + mode = cls.get_brush_mode(context) + return mode is not None and mode != 'SCULPT_CURVES' + def draw(self, context): layout = self.layout @@ -1049,6 +1054,36 @@ class VIEW3D_PT_sculpt_symmetry_for_topbar(Panel): draw = VIEW3D_PT_sculpt_symmetry.draw +class VIEW3D_PT_curves_sculpt_symmetry(Panel, View3DPaintPanel): + bl_context = ".curves_sculpt" # dot on purpose (access from topbar) + bl_label = "Symmetry" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + return context.object and context.object.type == 'CURVES' + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + + curves = context.object.data + + row = layout.row(align=True, heading="Mirror") + row.prop(curves, "use_mirror_x", text="X", toggle=True) + row.prop(curves, "use_mirror_y", text="Y", toggle=True) + row.prop(curves, "use_mirror_z", text="Z", toggle=True) + + +class VIEW3D_PT_curves_sculpt_symmetry_for_topbar(Panel): + bl_space_type = 'TOPBAR' + bl_region_type = 'HEADER' + bl_label = "Symmetry" + + draw = VIEW3D_PT_curves_sculpt_symmetry.draw + + # ********** default tools for weight-paint **************** @@ -1907,6 +1942,41 @@ class VIEW3D_PT_tools_grease_pencil_brush_sculpt_falloff(GreasePencilBrushFallof return (settings and settings.brush and settings.brush.curve) +class VIEW3D_PT_tools_grease_pencil_sculpt_brush_advanced(GreasePencilSculptAdvancedPanel, View3DPanel, Panel): + bl_context = ".greasepencil_sculpt" + bl_label = "Advanced" + bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_sculpt_settings' + bl_category = "Tool" + bl_options = {'DEFAULT_CLOSED'} + + @classmethod + def poll(cls, context): + brush = context.tool_settings.gpencil_sculpt_paint.brush + if brush is None: + return False + + tool = brush.gpencil_sculpt_tool + return tool != 'CLONE' + + +class VIEW3D_PT_tools_grease_pencil_sculpt_brush_popover(GreasePencilSculptAdvancedPanel, View3DPanel, Panel): + bl_context = ".greasepencil_sculpt" + bl_label = "Brush" + bl_category = "Tool" + + @classmethod + def poll(cls, context): + if context.region.type != 'TOOL_HEADER': + return False + + brush = context.tool_settings.gpencil_sculpt_paint.brush + if brush is None: + return False + + tool = brush.gpencil_sculpt_tool + return tool != 'CLONE' + + # Grease Pencil weight painting tools class GreasePencilWeightPanel: bl_context = ".greasepencil_weight" @@ -2240,13 +2310,6 @@ class VIEW3D_PT_tools_grease_pencil_brush_mix_palette(View3DPanel, Panel): col.template_palette(settings, "palette", color=True) -class VIEW3D_PT_tools_grease_pencil_sculpt_options(GreasePencilSculptOptionsPanel, Panel, View3DPanel): - bl_context = ".greasepencil_sculpt" - bl_parent_id = 'VIEW3D_PT_tools_grease_pencil_sculpt_settings' - bl_category = "Tool" - bl_label = "Sculpt Strokes" - - # Grease Pencil Brush Appearance (one for each mode) class VIEW3D_PT_tools_grease_pencil_paint_appearance(GreasePencilDisplayPanel, Panel, View3DPanel): bl_context = ".greasepencil_paint" @@ -2323,6 +2386,9 @@ classes = ( VIEW3D_PT_sculpt_options, VIEW3D_PT_sculpt_options_gravity, + VIEW3D_PT_curves_sculpt_symmetry, + VIEW3D_PT_curves_sculpt_symmetry_for_topbar, + VIEW3D_PT_tools_weightpaint_symmetry, VIEW3D_PT_tools_weightpaint_symmetry_for_topbar, VIEW3D_PT_tools_weightpaint_options, @@ -2357,7 +2423,8 @@ classes = ( VIEW3D_PT_tools_grease_pencil_paint_appearance, VIEW3D_PT_tools_grease_pencil_sculpt_select, VIEW3D_PT_tools_grease_pencil_sculpt_settings, - VIEW3D_PT_tools_grease_pencil_sculpt_options, + VIEW3D_PT_tools_grease_pencil_sculpt_brush_advanced, + VIEW3D_PT_tools_grease_pencil_sculpt_brush_popover, VIEW3D_PT_tools_grease_pencil_sculpt_appearance, VIEW3D_PT_tools_grease_pencil_weight_paint_select, VIEW3D_PT_tools_grease_pencil_weight_paint_settings, diff --git a/release/scripts/startup/nodeitems_builtins.py b/release/scripts/startup/nodeitems_builtins.py index f9bd4342b6e..f5282123ce8 100644 --- a/release/scripts/startup/nodeitems_builtins.py +++ b/release/scripts/startup/nodeitems_builtins.py @@ -419,12 +419,10 @@ shader_node_categories = [ NodeItem("ShaderNodeRGBToBW"), NodeItem("ShaderNodeShaderToRGB", poll=object_eevee_shader_nodes_poll), NodeItem("ShaderNodeVectorMath"), - NodeItem("ShaderNodeSeparateRGB"), - NodeItem("ShaderNodeCombineRGB"), + NodeItem("ShaderNodeSeparateColor"), + NodeItem("ShaderNodeCombineColor"), NodeItem("ShaderNodeSeparateXYZ"), NodeItem("ShaderNodeCombineXYZ"), - NodeItem("ShaderNodeSeparateHSV"), - NodeItem("ShaderNodeCombineHSV"), NodeItem("ShaderNodeWavelength"), NodeItem("ShaderNodeBlackbody"), ]), @@ -483,14 +481,8 @@ compositor_node_categories = [ NodeItem("CompositorNodePremulKey"), NodeItem("CompositorNodeIDMask"), NodeItem("CompositorNodeRGBToBW"), - NodeItem("CompositorNodeSepRGBA"), - NodeItem("CompositorNodeCombRGBA"), - NodeItem("CompositorNodeSepHSVA"), - NodeItem("CompositorNodeCombHSVA"), - NodeItem("CompositorNodeSepYUVA"), - NodeItem("CompositorNodeCombYUVA"), - NodeItem("CompositorNodeSepYCCA"), - NodeItem("CompositorNodeCombYCCA"), + NodeItem("CompositorNodeSeparateColor"), + NodeItem("CompositorNodeCombineColor"), NodeItem("CompositorNodeSeparateXYZ"), NodeItem("CompositorNodeCombineXYZ"), NodeItem("CompositorNodeSwitchView"), @@ -576,8 +568,8 @@ texture_node_categories = [ NodeItem("TextureNodeCurveRGB"), NodeItem("TextureNodeInvert"), NodeItem("TextureNodeHueSaturation"), - NodeItem("TextureNodeCompose"), - NodeItem("TextureNodeDecompose"), + NodeItem("TextureNodeCombineColor"), + NodeItem("TextureNodeSeparateColor"), ]), TextureNodeCategory("TEX_PATTERN", "Pattern", items=[ NodeItem("TextureNodeChecker"), @@ -629,8 +621,8 @@ geometry_node_categories = [ NodeItem("ShaderNodeMixRGB"), NodeItem("ShaderNodeRGBCurve"), NodeItem("ShaderNodeValToRGB"), - NodeItem("ShaderNodeSeparateRGB"), - NodeItem("ShaderNodeCombineRGB"), + NodeItem("FunctionNodeSeparateColor"), + NodeItem("FunctionNodeCombineColor"), ]), GeometryNodeCategory("GEO_CURVE", "Curve", items=curve_node_items), GeometryNodeCategory("GEO_PRIMITIVES_CURVE", "Curve Primitives", items=[ |