diff options
Diffstat (limited to 'release/scripts/startup')
29 files changed, 454 insertions, 192 deletions
diff --git a/release/scripts/startup/bl_operators/object.py b/release/scripts/startup/bl_operators/object.py index c42d5970ed9..12d7984b3b2 100644 --- a/release/scripts/startup/bl_operators/object.py +++ b/release/scripts/startup/bl_operators/object.py @@ -743,7 +743,9 @@ class TransformsToDeltas(Operator): def transfer_rotation(self, obj): # TODO: add transforms together... if obj.rotation_mode == 'QUATERNION': - obj.delta_rotation_quaternion += obj.rotation_quaternion + delta = obj.delta_rotation_quaternion.copy() + obj.delta_rotation_quaternion = obj.rotation_quaternion + obj.delta_rotation_quaternion.rotate(delta) if self.reset_values: obj.rotation_quaternion.identity() diff --git a/release/scripts/startup/bl_operators/object_quick_effects.py b/release/scripts/startup/bl_operators/object_quick_effects.py index e49ca0320c7..71153ba8b74 100644 --- a/release/scripts/startup/bl_operators/object_quick_effects.py +++ b/release/scripts/startup/bl_operators/object_quick_effects.py @@ -466,6 +466,13 @@ class QuickLiquid(Operator): self.report({'ERROR'}, "Select at least one mesh object") return {'CANCELLED'} + # set shading type to wireframe so that liquid particles are visible + for area in bpy.context.screen.areas: + if area.type == 'VIEW_3D': + for space in area.spaces: + if space.type == 'VIEW_3D': + space.shading.type = 'WIREFRAME' + for obj in mesh_objects: fake_context["object"] = obj # make each selected object a liquid flow @@ -499,7 +506,6 @@ class QuickLiquid(Operator): # setup liquid domain bpy.ops.object.modifier_add(type='FLUID') obj.modifiers[-1].fluid_type = 'DOMAIN' - obj.modifiers[-1].domain_settings.domain_type = 'LIQUID' # set all domain borders to obstacle obj.modifiers[-1].domain_settings.use_collision_border_front = True obj.modifiers[-1].domain_settings.use_collision_border_back = True @@ -511,8 +517,8 @@ class QuickLiquid(Operator): # set correct cache file format for liquid obj.modifiers[-1].domain_settings.cache_mesh_format = 'BOBJECT' - # allocate and show particle system for FLIP - obj.modifiers[-1].domain_settings.use_flip_particles = True + # change domain type, will also allocate and show particle system for FLIP + obj.modifiers[-1].domain_settings.domain_type = 'LIQUID' # make the domain smooth so it renders nicely bpy.ops.object.shade_smooth() diff --git a/release/scripts/startup/bl_operators/presets.py b/release/scripts/startup/bl_operators/presets.py index c811f542a3a..6a21f7db654 100644 --- a/release/scripts/startup/bl_operators/presets.py +++ b/release/scripts/startup/bl_operators/presets.py @@ -501,7 +501,7 @@ class AddPresetTrackingSettings(AddPresetBase, Operator): "settings.use_default_mask", "settings.use_default_red_channel", "settings.use_default_green_channel", - "settings.use_default_blue_channel" + "settings.use_default_blue_channel", "settings.default_weight" ] 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 756d2ff1eeb..3900fc3f2c2 100644 --- a/release/scripts/startup/bl_operators/screen_play_rendered_anim.py +++ b/release/scripts/startup/bl_operators/screen_play_rendered_anim.py @@ -85,12 +85,13 @@ class PlayRenderedAnim(Operator): fps_final = rd.fps / rd.fps_base preset = prefs.filepaths.animation_player_preset - player_path = prefs.filepaths.animation_player # file_path = bpy.path.abspath(rd.filepath) # UNUSED is_movie = rd.is_movie_format # try and guess a command line if it doesn't exist - if player_path == "": + if preset == 'CUSTOM': + player_path = prefs.filepaths.animation_player + else: player_path = guess_player_path(preset) if is_movie is False and preset in {'FRAMECYCLER', 'RV', 'MPLAYER'}: diff --git a/release/scripts/startup/bl_operators/userpref.py b/release/scripts/startup/bl_operators/userpref.py index 4c5c269955a..4cb6ddd3fa3 100644 --- a/release/scripts/startup/bl_operators/userpref.py +++ b/release/scripts/startup/bl_operators/userpref.py @@ -49,6 +49,44 @@ def module_filesystem_remove(path_base, module_name): else: os.remove(f_full) +# This duplicates shutil.copytree from Python 3.8, with the new dirs_exist_ok +# argument that we need. Once we upgrade to 3.8 we can remove this. +def _preferences_copytree(entries, src, dst): + import shutil + import os + os.makedirs(dst, exist_ok=True) + errors = [] + + for srcentry in entries: + srcname = os.path.join(src, srcentry.name) + dstname = os.path.join(dst, srcentry.name) + srcobj = srcentry + try: + if srcentry.is_symlink(): + linkto = os.readlink(srcname) + os.symlink(linkto, dstname) + shutil.copystat(srcobj, dstname, follow_symlinks=False) + elif srcentry.is_dir(): + preferences_copytree(srcobj, dstname) + else: + shutil.copy2(srcentry, dstname) + except Error as err: + errors.extend(err.args[0]) + except OSError as why: + errors.append((srcname, dstname, str(why))) + try: + shutil.copystat(src, dst) + except OSError as why: + if getattr(why, 'winerror', None) is None: + errors.append((src, dst, str(why))) + if errors: + raise Error(errors) + return dst + +def preferences_copytree(src, dst): + import os + with os.scandir(src) as entries: + return _preferences_copytree(entries=entries, src=src, dst=dst) class PREFERENCES_OT_keyconfig_activate(Operator): bl_idname = "preferences.keyconfig_activate" @@ -110,9 +148,10 @@ class PREFERENCES_OT_copy_prev(Operator): return os.path.isfile(old_userpref) and not os.path.isfile(new_userpref) def execute(self, _context): - import shutil - - shutil.copytree(self._old_path(), self._new_path(), symlinks=True) + # Use this instead once we upgrade to Python 3.8 with dirs_exist_ok. + # import shutil + # shutil.copytree(self._old_path(), self._new_path(), dirs_exist_ok=True) + preferences_copytree(self._old_path(), self._new_path()) # reload preferences and recent-files.txt bpy.ops.wm.read_userpref() diff --git a/release/scripts/startup/bl_operators/vertexpaint_dirt.py b/release/scripts/startup/bl_operators/vertexpaint_dirt.py index 39d792bd557..a249599b5d7 100644 --- a/release/scripts/startup/bl_operators/vertexpaint_dirt.py +++ b/release/scripts/startup/bl_operators/vertexpaint_dirt.py @@ -37,6 +37,20 @@ def applyVertexDirt(me, blur_iterations, blur_strength, clamp_dirt, clamp_clean, from math import acos import array + # We simulate the accumulation of dirt in the creases of geometric surfaces + # by comparing the vertex normal to the average direction of all vertices + # connected to that vertex. We can also simulate surfaces being buffed or + # worn by testing protruding surfaces. + # + # So if the angle between the normal and geometric direction is: + # < 90 - dirt has accumulated in the crease + # > 90 - surface has been worn or buffed + # ~ 90 - surface is flat and is generally unworn and clean + # + # This method is limited by the complexity or lack there of in the geometry. + # + # Original code and method by Keith "Wahooney" Boshoff. + vert_tone = array.array("f", [0.0]) * len(me.vertices) # create lookup table for each vertex's connected vertices (via edges) diff --git a/release/scripts/startup/bl_operators/wm.py b/release/scripts/startup/bl_operators/wm.py index a677d9932b6..335a2a633cd 100644 --- a/release/scripts/startup/bl_operators/wm.py +++ b/release/scripts/startup/bl_operators/wm.py @@ -1804,9 +1804,6 @@ class WM_OT_toolbar_fallback_pie(Operator): return context.space_data is not None def invoke(self, context, event): - if not context.preferences.experimental.use_tool_fallback: - return {'PASS_THROUGH'} - from bl_ui.space_toolsystem_common import ToolSelectPanelHelper space_type = context.space_data.type cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type) diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py index b75d67b5350..3fc54ff6d12 100644 --- a/release/scripts/startup/bl_ui/properties_constraint.py +++ b/release/scripts/startup/bl_ui/properties_constraint.py @@ -492,6 +492,8 @@ class ConstraintButtonsPanel: col.prop(con, "frame_start", text="Start") col.prop(con, "frame_end", text="End") + layout.prop(con, "mix_mode", text="Mix") + def LOCKED_TRACK(self, _context, layout, con): self.target_template(layout, con) diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py index 5d654d33a2d..957b119e9ba 100644 --- a/release/scripts/startup/bl_ui/properties_data_camera.py +++ b/release/scripts/startup/bl_ui/properties_data_camera.py @@ -501,6 +501,7 @@ class DATA_PT_camera_safe_areas_center_cut(CameraButtonsPanel, Panel): col = layout.column() col.prop(safe_data, "title_center", slider=True) + col.prop(safe_data, "action_center", slider=True) class DATA_PT_custom_props_camera(CameraButtonsPanel, PropertyPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index d1975919d7e..b694062dfc5 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -144,7 +144,6 @@ class DATA_PT_curve_texture_space(CurveButtonsPanel, Panel): curve = context.curve col = layout.column() - col.prop(curve, "use_uv_as_generated") col.prop(curve, "use_auto_texspace") col = layout.column() diff --git a/release/scripts/startup/bl_ui/properties_data_empty.py b/release/scripts/startup/bl_ui/properties_data_empty.py index 4ce87b85410..88fdaae0433 100644 --- a/release/scripts/startup/bl_ui/properties_data_empty.py +++ b/release/scripts/startup/bl_ui/properties_data_empty.py @@ -37,7 +37,6 @@ class DATA_PT_empty(DataButtonsPanel, Panel): def draw(self, context): layout = self.layout layout.use_property_split = True - layout.use_property_decorate = False ob = context.object @@ -45,12 +44,6 @@ class DATA_PT_empty(DataButtonsPanel, Panel): layout.prop(ob, "empty_display_size", text="Size") if ob.empty_display_type == 'IMAGE': - layout.prop(ob, "use_empty_image_alpha") - - col = layout.column() - col.active = ob.use_empty_image_alpha - col.prop(ob, "color", text="Transparency", index=3, slider=True) - col = layout.column(align=True) col.prop(ob, "empty_image_offset", text="Offset X", index=0) col.prop(ob, "empty_image_offset", text="Y", index=1) @@ -63,6 +56,30 @@ class DATA_PT_empty(DataButtonsPanel, Panel): col.prop(ob, "show_empty_image_only_axis_aligned") +class DATA_PT_empty_alpha(DataButtonsPanel, Panel): + bl_label = "Transparency" + bl_parent_id = "DATA_PT_empty" + + @classmethod + def poll(cls, context): + ob = context.object + return (ob and ob.type == 'EMPTY' and ob.empty_display_type == 'IMAGE') + + def draw_header(self, context): + ob = context.object + + self.layout.prop(ob, "use_empty_image_alpha", text="") + + def draw(self, context): + layout = self.layout + layout.use_property_split = True + + ob = context.object + + layout.active = ob.use_empty_image_alpha + layout.prop(ob, "color", text="Opacity", index=3, slider=True) + + class DATA_PT_empty_image(DataButtonsPanel, Panel): bl_label = "Image" @@ -81,6 +98,7 @@ class DATA_PT_empty_image(DataButtonsPanel, Panel): classes = ( DATA_PT_empty, + DATA_PT_empty_alpha, DATA_PT_empty_image, ) diff --git a/release/scripts/startup/bl_ui/properties_data_light.py b/release/scripts/startup/bl_ui/properties_data_light.py index 6f730cf3307..cf894b48e1e 100644 --- a/release/scripts/startup/bl_ui/properties_data_light.py +++ b/release/scripts/startup/bl_ui/properties_data_light.py @@ -134,17 +134,15 @@ class DATA_PT_EEVEE_light_distance(DataButtonsPanel, Panel): light = context.light layout = self.layout - layout.active = light.use_shadow layout.prop(light, "use_custom_distance", text="") def draw(self, context): layout = self.layout light = context.light + layout.active = light.use_custom_distance layout.use_property_split = True - col = layout.column() - - col.prop(light, "cutoff_distance", text="Distance") + layout.prop(light, "cutoff_distance", text="Distance") class DATA_PT_EEVEE_shadow(DataButtonsPanel, Panel): @@ -311,7 +309,8 @@ class DATA_PT_falloff_curve(DataButtonsPanel, Panel): def draw(self, context): light = context.light - self.layout.template_curve_mapping(light, "falloff_curve", use_negative_slope=True) + self.layout.template_curve_mapping( + light, "falloff_curve", use_negative_slope=True) class DATA_PT_custom_props_light(DataButtonsPanel, PropertyPanel, Panel): diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index d4b2c39bd5e..197566f16f3 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -293,7 +293,9 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col = split.column() col.label(text="Vertex Group:") - col.prop_search(md, "vertex_group", ob, "vertex_groups", text="") + row = col.row(align=True) + row.prop_search(md, "vertex_group", ob, "vertex_groups", text="") + row.prop(md, "invert_vertex_group", text="", icon='ARROW_LEFTRIGHT') col = split.column() col.label(text="Control Object:") col.prop(md, "object", text="") diff --git a/release/scripts/startup/bl_ui/properties_data_speaker.py b/release/scripts/startup/bl_ui/properties_data_speaker.py index 5de133f184a..10645bdd214 100644 --- a/release/scripts/startup/bl_ui/properties_data_speaker.py +++ b/release/scripts/startup/bl_ui/properties_data_speaker.py @@ -45,12 +45,10 @@ class DATA_PT_context_speaker(DataButtonsPanel, Panel): speaker = context.speaker space = context.space_data - split = layout.split(factor=0.65) - if ob: - split.template_ID(ob, "data") + layout.template_ID(ob, "data") elif speaker: - split.template_ID(space, "pin_id") + layout.template_ID(space, "pin_id") class DATA_PT_speaker(DataButtonsPanel, Panel): 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 45cb10bb3bd..2001f46820f 100644 --- a/release/scripts/startup/bl_ui/properties_grease_pencil_common.py +++ b/release/scripts/startup/bl_ui/properties_grease_pencil_common.py @@ -581,9 +581,9 @@ class AnnotationDataPanel: def poll(cls, context): # Show this panel as long as someone that might own this exists # AND the owner isn't an object (e.g. GP Object) - if context.gpencil_data_owner is None: + if context.annotation_data_owner is None: return False - elif type(context.gpencil_data_owner) is bpy.types.Object: + elif type(context.annotation_data_owner) is bpy.types.Object: return False else: return True @@ -597,14 +597,14 @@ class AnnotationDataPanel: layout.use_property_decorate = False # Grease Pencil owner. - gpd_owner = context.gpencil_data_owner - gpd = context.gpencil_data + gpd_owner = context.annotation_data_owner + gpd = context.annotation_data # Owner selector. if context.space_data.type == 'CLIP_EDITOR': layout.row().prop(context.space_data, "grease_pencil_source", expand=True) - layout.template_ID(gpd_owner, "grease_pencil", new="gpencil.data_add", unlink="gpencil.data_unlink") + layout.template_ID(gpd_owner, "grease_pencil", new="gpencil.annotation_add", unlink="gpencil.data_unlink") # List of layers/notes. if gpd and gpd.layers: @@ -624,17 +624,17 @@ class AnnotationDataPanel: col = row.column() sub = col.column(align=True) - sub.operator("gpencil.layer_add", icon='ADD', text="") - sub.operator("gpencil.layer_remove", icon='REMOVE', text="") + sub.operator("gpencil.layer_annotation_add", icon='ADD', text="") + sub.operator("gpencil.layer_annotation_remove", icon='REMOVE', text="") - gpl = context.active_gpencil_layer + gpl = context.active_annotation_layer if gpl: if len(gpd.layers) > 1: col.separator() sub = col.column(align=True) - sub.operator("gpencil.layer_move", icon='TRIA_UP', text="").type = 'UP' - sub.operator("gpencil.layer_move", icon='TRIA_DOWN', text="").type = 'DOWN' + sub.operator("gpencil.layer_annotation_move", icon='TRIA_UP', text="").type = 'UP' + sub.operator("gpencil.layer_annotation_move", icon='TRIA_DOWN', text="").type = 'DOWN' tool_settings = context.tool_settings if gpd and gpl: @@ -653,7 +653,7 @@ class AnnotationDataPanel: else: lock_label = iface_("Lock Frame") row.prop(gpl, "lock_frame", text=lock_label, icon='UNLOCKED') - row.operator("gpencil.active_frame_delete", text="", icon='X') + row.operator("gpencil.annotation_active_frame_delete", text="", icon='X') class AnnotationOnionSkin: @@ -665,26 +665,26 @@ class AnnotationOnionSkin: def poll(cls, context): # Show this panel as long as someone that might own this exists # AND the owner isn't an object (e.g. GP Object) - if context.gpencil_data_owner is None: + if context.annotation_data_owner is None: return False - elif type(context.gpencil_data_owner) is bpy.types.Object: + elif type(context.annotation_data_owner) is bpy.types.Object: return False else: - gpl = context.active_gpencil_layer + gpl = context.active_annotation_layer if gpl is None: return False return True def draw_header(self, context): - gpl = context.active_gpencil_layer + gpl = context.active_annotation_layer self.layout.prop(gpl, "use_annotation_onion_skinning", text="") def draw(self, context): layout = self.layout layout.use_property_decorate = False - gpl = context.active_gpencil_layer + gpl = context.active_annotation_layer col = layout.column() split = col.split(factor=0.5) split.active = gpl.use_annotation_onion_skinning diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py index 327df079d3b..a9e8cae3c8b 100644 --- a/release/scripts/startup/bl_ui/properties_paint_common.py +++ b/release/scripts/startup/bl_ui/properties_paint_common.py @@ -121,7 +121,7 @@ class UnifiedPaintPanel: if unified_name and not header: # NOTE: We don't draw UnifiedPaintSettings in the header to reduce clutter. D5928#136281 - row.prop(ups, unified_name, text="", icon="WORLD") + row.prop(ups, unified_name, text="", icon="BRUSHES_ALL") return row @@ -438,7 +438,7 @@ 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'}: + if mode in {'SCULPT', 'PAINT_VERTEX', 'PAINT_WEIGHT'} and brush.sculpt_tool != 'POSE': col.separator() row = col.row(align=True) row.use_property_split = True @@ -616,9 +616,12 @@ def brush_settings(layout, context, brush, popover=False): layout.separator() if brush.sculpt_tool == 'POSE': - row = layout.row() - row.prop(brush, "pose_offset") - + layout.separator() + layout.prop(brush, "pose_offset") + layout.prop(brush, "pose_smooth_iterations") + layout.prop(brush, "pose_ik_segments") + layout.separator() + if brush.sculpt_tool == 'SCRAPE': row = layout.row() row.prop(brush, "invert_to_scrape_fill", text="Invert to Fill") diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index 21abf8bb34c..3384032e332 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -582,7 +582,10 @@ class PARTICLE_PT_rotation(ParticleButtonsPanel, Panel): else: part = context.space_data.pin_id - self.layout.prop(part, "use_rotations", text="") + layout = self.layout + layout.prop(part, "use_rotations", text="") + layout.enabled = particle_panel_enabled(context, psys) + def draw(self, context): layout = self.layout @@ -1961,7 +1964,7 @@ class PARTICLE_PT_hair_shape(ParticleButtonsPanel, Panel): layout.prop(part, "shape", text="Strand Shape") col = layout.column(align=True) - col.prop(part, "root_radius", text="Radius Root") + col.prop(part, "root_radius", text="Diameter Root") col.prop(part, "tip_radius", text="Tip") col = layout.column() diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py index 6b0dd7ac36f..28c9895f53b 100644 --- a/release/scripts/startup/bl_ui/properties_physics_fluid.py +++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py @@ -95,6 +95,26 @@ class PhysicButtonsPanel: md = context.fluid return md and (md.fluid_type == 'FLOW') + @staticmethod + def poll_fluid_flow_outflow(context): + if not PhysicButtonsPanel.poll_fluid_flow(context): + return False + + md = context.fluid + flow = md.flow_settings + if (flow.flow_behavior == 'OUTFLOW'): + return True + + @staticmethod + def poll_fluid_flow_liquid(context): + if not PhysicButtonsPanel.poll_fluid_flow(context): + return False + + md = context.fluid + flow = md.flow_settings + if (flow.flow_type == 'LIQUID'): + return True + class PHYSICS_PT_fluid(PhysicButtonsPanel, Panel): bl_label = "Fluid" @@ -313,9 +333,9 @@ class PHYSICS_PT_smoke(PhysicButtonsPanel, Panel): flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False) flow.enabled = not is_baking_any and not has_baked_data - col = flow.column() - col.prop(domain, "alpha") - col.prop(domain, "beta", text="Temperature Diff.") + col = flow.column(align=True) + col.prop(domain, "alpha", text="Buoyancy Density") + col.prop(domain, "beta", text="Heat") col = flow.column() col.prop(domain, "vorticity") @@ -389,14 +409,12 @@ class PHYSICS_PT_fire(PhysicButtonsPanel, Panel): col = flow.column() col.prop(domain, "burning_rate", text="Reaction Speed") - col = flow.column() + col = flow.column(align=True) col.prop(domain, "flame_smoke", text="Flame Smoke") - col = flow.column() - col.prop(domain, "flame_vorticity", text="Flame Vorticity") - col = flow.column() - col.prop(domain, "flame_ignition", text="Temperature Ignition") - col = flow.column() - col.prop(domain, "flame_max_temp", text="Maximum Temperature") + col.prop(domain, "flame_vorticity", text="Vorticity") + col = flow.column(align=True) + col.prop(domain, "flame_max_temp", text="Temperature Maximum") + col.prop(domain, "flame_ignition", text="Minimum") col = flow.column() col.prop(domain, "flame_smoke_color", text="Flame Color") @@ -485,10 +503,10 @@ class PHYSICS_PT_flow_source(PhysicButtonsPanel, Panel): col = grid.column() if flow.flow_source == 'MESH': col.prop(flow, "use_plane_init", text="Is Planar") - col.prop(flow, "surface_distance", text="Surface Thickness") + col.prop(flow, "surface_distance", text="Surface Emission") if flow.flow_type in {'SMOKE', 'BOTH', 'FIRE'}: col = grid.column() - col.prop(flow, "volume_density", text="Volume Density") + col.prop(flow, "volume_density", text="Volume Emission") if flow.flow_source == 'PARTICLES': col.prop(flow, "use_particle_size", text="Set Size") @@ -507,6 +525,9 @@ class PHYSICS_PT_flow_initial_velocity(PhysicButtonsPanel, Panel): if not PhysicButtonsPanel.poll_fluid_flow(context): return False + if PhysicButtonsPanel.poll_fluid_flow_outflow(context): + return False + return (context.engine in cls.COMPAT_ENGINES) def draw_header(self, context): @@ -546,6 +567,12 @@ class PHYSICS_PT_flow_texture(PhysicButtonsPanel, Panel): if not PhysicButtonsPanel.poll_fluid_flow(context): return False + if PhysicButtonsPanel.poll_fluid_flow_outflow(context): + return False + + if PhysicButtonsPanel.poll_fluid_flow_liquid(context): + return False + return (context.engine in cls.COMPAT_ENGINES) def draw_header(self, context): @@ -1088,13 +1115,7 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel): col.separator() split = layout.split() - bake_incomplete = (domain.cache_frame_pause_data < domain.cache_frame_end) - if domain.has_cache_baked_data and not domain.is_cache_baking_data and bake_incomplete: - col = split.column() - col.operator("fluid.bake_all", text="Resume") - col = split.column() - col.operator("fluid.free_all", text="Free") - elif domain.is_cache_baking_data and not domain.has_cache_baked_data: + if domain.is_cache_baking_data and not domain.has_cache_baked_data: split.enabled = False split.operator("fluid.pause_bake", text="Baking All - ESC to pause") elif not domain.has_cache_baked_data and not domain.is_cache_baking_data: diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py index 5a73ff094a2..a09e263fd87 100644 --- a/release/scripts/startup/bl_ui/space_dopesheet.py +++ b/release/scripts/startup/bl_ui/space_dopesheet.py @@ -542,8 +542,8 @@ class DOPESHEET_MT_gpencil_channel(Menu): # 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_menu_enum("anim.channels_move", "direction", text="Move...") class DOPESHEET_MT_gpencil_frame(Menu): diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index 82ed701aa4c..cd65980fc0d 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -92,7 +92,7 @@ class INFO_MT_area(Menu): layout.separator() - layout.operator("screen.area_dupli", icon='DUPLICATE') + layout.operator("screen.area_dupli", icon='WINDOW') layout.separator() diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py index 28b67c93666..4ecc4e7fdd9 100644 --- a/release/scripts/startup/bl_ui/space_nla.py +++ b/release/scripts/startup/bl_ui/space_nla.py @@ -167,6 +167,7 @@ class NLA_MT_edit(Menu): layout.operator("nla.duplicate", text="Linked Duplicate").linked = True layout.operator("nla.split") layout.operator("nla.delete") + layout.operator("nla.tracks_delete") layout.separator() layout.operator("nla.mute_toggle") diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index 097564444d0..af0c23e7892 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -30,6 +30,9 @@ from bpy.app.translations import ( from bl_ui.properties_grease_pencil_common import ( AnnotationDataPanel, ) +from bl_ui.space_toolsystem_common import ( + ToolActivePanelHelper, +) from rna_prop_ui import PropertyPanel @@ -89,6 +92,35 @@ def draw_color_balance(layout, color_balance): split.template_color_picker(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True) +class SEQUENCER_PT_active_tool(ToolActivePanelHelper, Panel): + bl_space_type = 'SEQUENCE_EDITOR' + bl_region_type = 'UI' + bl_category = "Tool" + + +class SEQUENCER_HT_tool_header(Header): + bl_space_type = 'SEQUENCE_EDITOR' + bl_region_type = 'TOOL_HEADER' + + def draw(self, context): + layout = self.layout + + layout.template_header() + + self.draw_tool_settings(context) + + # TODO: options popover. + + def draw_tool_settings(self, context): + layout = self.layout + + # Active Tool + # ----------- + from bl_ui.space_toolsystem_common import ToolSelectPanelHelper + tool = ToolSelectPanelHelper.draw_active_tool_header(context, layout) + tool_mode = context.mode if tool is None else tool.mode + + class SEQUENCER_HT_header(Header): bl_space_type = 'SEQUENCE_EDITOR' @@ -97,7 +129,10 @@ class SEQUENCER_HT_header(Header): st = context.space_data - layout.template_header() + show_region_tool_header = st.show_region_tool_header + + if not show_region_tool_header: + layout.template_header() layout.prop(st, "view_type", text="") @@ -226,8 +261,12 @@ class SEQUENCER_MT_view(Menu): # wm_keymap_item_find_props() (see #32595). layout.operator_context = 'INVOKE_REGION_PREVIEW' layout.prop(st, "show_region_ui") + layout.prop(st, "show_region_toolbar") layout.operator_context = 'INVOKE_DEFAULT' + if is_sequencer_view: + layout.prop(st, "show_region_hud") + if st.view_type == 'SEQUENCER': layout.prop(st, "show_backdrop", text="Preview as Backdrop") @@ -268,6 +307,7 @@ class SEQUENCER_MT_view(Menu): layout.operator_context = 'INVOKE_DEFAULT' layout.prop(st, "show_seconds") + layout.prop(st, "show_locked_time") layout.prop(st, "show_strip_offset") layout.separator() layout.prop(st, "show_markers") @@ -2128,6 +2168,7 @@ class SEQUENCER_PT_custom_props(SequencerButtonsPanel, PropertyPanel, Panel): classes = ( SEQUENCER_MT_change, + SEQUENCER_HT_tool_header, SEQUENCER_HT_header, SEQUENCER_MT_editor_menus, SEQUENCER_MT_range, @@ -2153,7 +2194,7 @@ classes = ( SEQUENCER_MT_strip_input, SEQUENCER_MT_strip_lock_mute, SEQUENCER_MT_context_menu, - + SEQUENCER_PT_active_tool, SEQUENCER_PT_strip, SEQUENCER_PT_effect, diff --git a/release/scripts/startup/bl_ui/space_text.py b/release/scripts/startup/bl_ui/space_text.py index 81ccc9216a1..b7c5dcd5437 100644 --- a/release/scripts/startup/bl_ui/space_text.py +++ b/release/scripts/startup/bl_ui/space_text.py @@ -30,7 +30,7 @@ class TEXT_HT_header(Header): st = context.space_data text = st.text - + is_syntax_highlight_supported = st.is_syntax_highlight_supported() layout.template_header() TEXT_MT_editor_menus.draw_collapsible(context, layout) @@ -43,7 +43,18 @@ class TEXT_HT_header(Header): layout.separator_spacer() row = layout.row(align=True) - row.template_ID(st, "text", new="text.new", unlink="text.unlink", open="text.open") + row.template_ID(st, "text", new="text.new", + unlink="text.unlink", open="text.open") + + if text: + is_osl = text.name.endswith((".osl", ".osl")) + if is_osl: + row.operator("node.shader_script_update", + text="", icon='FILE_REFRESH') + else: + row = layout.row() + row.active = is_syntax_highlight_supported + row.operator("text.run_script", text="", icon='PLAY') layout.separator_spacer() @@ -51,28 +62,10 @@ class TEXT_HT_header(Header): row.prop(st, "show_line_numbers", text="") row.prop(st, "show_word_wrap", text="") - is_syntax_highlight_supported = st.is_syntax_highlight_supported() syntax = row.row(align=True) syntax.active = is_syntax_highlight_supported syntax.prop(st, "show_syntax_highlight", text="") - if text: - text_name = text.name - is_osl = text_name.endswith((".osl", ".oso")) - - row = layout.row() - if is_osl: - row = layout.row() - row.operator("node.shader_script_update") - else: - row = layout.row() - row.active = text_name.endswith(".py") - row.prop(text, "use_module") - - row = layout.row() - row.active = is_syntax_highlight_supported - row.operator("text.run_script") - class TEXT_HT_footer(Header): bl_space_type = 'TEXT_EDITOR' diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py index 7b0a769ae62..4dc724299f0 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_common.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py @@ -354,6 +354,16 @@ class ToolSelectPanelHelper: i += 1 return None, -1 + @classmethod + def _tool_group_active_set_by_id(cls, context, idname_group, idname): + item_group = cls._tool_get_group_by_id(context, idname_group, coerce=True) + if item_group: + for i, item in enumerate(item_group): + if item and item.idname == idname: + cls._tool_group_active[item_group[0].idname] = i + return True + return False + @staticmethod def _tool_active_from_context(context, space_type, mode=None, create=False): if space_type in {'VIEW_3D', 'PROPERTIES'}: @@ -380,6 +390,14 @@ class ToolSelectPanelHelper: if tool is not None: tool.refresh_from_context() return tool + elif space_type == 'SEQUENCE_EDITOR': + space_data = context.space_data + if mode is None: + mode = space_data.view_type + tool = context.workspace.tools.from_space_sequencer(mode, create=create) + if tool is not None: + tool.refresh_from_context() + return tool return None @staticmethod @@ -646,6 +664,8 @@ class ToolSelectPanelHelper: return space_type, space_data.mode elif space_type == 'NODE_EDITOR': return space_type, None + elif space_type == 'SEQUENCE_EDITOR': + return space_type, context.space_data.view_type else: return None, None @@ -660,10 +680,10 @@ class ToolSelectPanelHelper: *, is_horizontal_layout=False, ): - tool_fallback = tool.tool_fallback + idname_fallback = tool.idname_fallback space_type = tool.space_type cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type) - item_fallback, _index = cls._tool_get_by_id(context, tool_fallback) + item_fallback, _index = cls._tool_get_by_id(context, idname_fallback) if item_fallback is not None: draw_settings = item_fallback.draw_settings if draw_settings is not None: @@ -699,12 +719,8 @@ class ToolSelectPanelHelper: if draw_settings is not None: draw_settings(context, layout, tool) - if context.preferences.experimental.use_tool_fallback: - tool_fallback = tool.tool_fallback - else: - tool_fallback = None - - if tool_fallback and tool_fallback != item.idname: + idname_fallback = tool.idname_fallback + if idname_fallback and idname_fallback != item.idname: tool_settings = context.tool_settings # Show popover which looks like an enum but isn't one. @@ -862,6 +878,7 @@ class WM_MT_toolsystem_submenu(Menu): def _activate_by_item(context, space_type, item, index, *, as_fallback=False): cls = ToolSelectPanelHelper._tool_class_from_space_type(space_type) + tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type, create=True) tool_fallback_id = cls.tool_fallback_id if as_fallback: @@ -889,6 +906,12 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False): # Done, now get the current tool to replace the item & index. tool_active = ToolSelectPanelHelper._tool_active_from_context(context, space_type) item, index = cls._tool_get_by_id(context, getattr(tool_active, "idname", None)) + else: + # Ensure the active fallback tool is read from saved state (even if the fallback tool is not in use). + stored_idname_fallback = tool.idname_fallback + if stored_idname_fallback: + cls._tool_group_active_set_by_id(context, tool_fallback_id, stored_idname_fallback) + del stored_idname_fallback # Find fallback keymap. item_fallback = None @@ -897,7 +920,6 @@ def _activate_by_item(context, space_type, item, index, *, as_fallback=False): item_fallback, _index = cls._tool_get_active_by_index(context, select_index) # End calculating fallback. - tool = ToolSelectPanelHelper._tool_active_from_context(context, space_type, create=True) tool.setup( idname=item.idname, keymap=item.keymap[0] if item.keymap is not None else "", diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py index 5f017e61db7..c1ad196b555 100644 --- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py +++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py @@ -134,6 +134,7 @@ class _defs_view3d_generic: idname="builtin.measure", label="Measure", description=description, + cursor='CROSSHAIR', icon="ops.view3d.ruler", widget="VIEW3D_GGT_ruler", keymap="3D View Tool: Measure", @@ -292,16 +293,29 @@ class _defs_transform: ) @ToolDef.from_fn + def shear(): + def draw_settings(context, layout, _tool): + # props = tool.operator_properties("transform.shear") + _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 2) + return dict( + idname="builtin.shear", + label="Shear", + icon="ops.transform.shear", + widget="VIEW3D_GGT_xform_shear", + keymap="3D View Tool: Shear", + draw_settings=draw_settings, + ) + + @ToolDef.from_fn def transform(): def draw_settings(context, layout, tool): if layout.use_property_split: layout.label(text="Gizmos:") show_drag = True - if context.preferences.experimental.use_tool_fallback: - tool_settings = context.tool_settings - if tool_settings.workspace_tool_type == 'FALLBACK': - show_drag = False + tool_settings = context.tool_settings + if tool_settings.workspace_tool_type == 'FALLBACK': + show_drag = False if show_drag: props = tool.gizmo_group_properties("VIEW3D_GGT_xform_gizmo") @@ -362,6 +376,7 @@ class _defs_view3d_select: label="Select Lasso", icon="ops.generic.select_lasso", widget=None, + cursor='DEFAULT', keymap="3D View Tool: Select Lasso", draw_settings=draw_settings, ) @@ -386,6 +401,7 @@ class _defs_view3d_select: label="Select Circle", icon="ops.generic.select_circle", widget=None, + cursor='DEFAULT', keymap="3D View Tool: Select Circle", draw_settings=draw_settings, draw_cursor=draw_cursor, @@ -764,20 +780,6 @@ class _defs_edit_mesh: ) @ToolDef.from_fn - def shear(): - def draw_settings(context, layout, _tool): - # props = tool.operator_properties("transform.shear") - _template_widget.VIEW3D_GGT_xform_gizmo.draw_settings_with_index(context, layout, 2) - return dict( - idname="builtin.shear", - label="Shear", - icon="ops.transform.shear", - widget="VIEW3D_GGT_xform_shear", - keymap=(), - draw_settings=draw_settings, - ) - - @ToolDef.from_fn def tosphere(): return dict( idname="builtin.to_sphere", @@ -1708,6 +1710,51 @@ class _defs_node_edit: keymap="Node Tool: Links Cut", ) +class _defs_sequencer_generic: + + @ToolDef.from_fn + def cut(): + def draw_settings(_context, layout, tool): + props = tool.operator_properties("sequencer.cut") + row = layout.row() + row.use_property_split = False + row.prop(props, "type", expand=True) + return dict( + idname="builtin.cut", + label="Cut", + icon="ops.mesh.knife_tool", + widget=None, + keymap="Sequencer Tool: Cut", + draw_settings=draw_settings, + ) + +class _defs_sequencer_select: + @ToolDef.from_fn + def select(): + return dict( + idname="builtin.select", + label="Select", + icon="ops.generic.select", + widget=None, + keymap="Sequencer Tool: Select", + ) + @ToolDef.from_fn + def box(): + def draw_settings(_context, layout, tool): + props = tool.operator_properties("sequencer.select_box") + row = layout.row() + row.use_property_split = False + row.prop(props, "mode", text="", expand=True, icon_only=True) + pass + return dict( + idname="builtin.select_box", + label="Select Box", + icon="ops.generic.select_box", + widget=None, + keymap="Sequencer Tool: Select Box", + draw_settings=draw_settings, + ) + class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel): bl_space_type = 'IMAGE_EDITOR' @@ -1961,6 +2008,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_edit_armature.extrude, _defs_edit_armature.extrude_cursor, ), + _defs_transform.shear, ], 'EDIT_MESH': [ *_tools_default, @@ -1999,7 +2047,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_edit_mesh.push_pull, ), ( - _defs_edit_mesh.shear, + _defs_transform.shear, _defs_edit_mesh.tosphere, ), ( @@ -2019,16 +2067,23 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_edit_curve.curve_radius, _defs_edit_curve.tilt, None, + _defs_transform.shear, _defs_edit_curve.curve_vertex_randomize, ], 'EDIT_SURFACE': [ *_tools_default, + None, + _defs_transform.shear, ], 'EDIT_METABALL': [ *_tools_default, + None, + _defs_transform.shear, ], 'EDIT_LATTICE': [ *_tools_default, + None, + _defs_transform.shear, ], 'EDIT_TEXT': [ _defs_view3d_generic.cursor, @@ -2116,6 +2171,8 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_gpencil_paint.curve, _defs_gpencil_paint.box, _defs_gpencil_paint.circle, + None, + *_tools_annotate, ], 'EDIT_GPENCIL': [ *_tools_gpencil_select, @@ -2130,11 +2187,13 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): _defs_gpencil_edit.shear, _defs_gpencil_edit.tosphere, ), - + None, + *_tools_annotate, ], 'SCULPT_GPENCIL': [ _defs_gpencil_sculpt.generate_from_brushes, None, + *_tools_annotate, lambda context: ( VIEW3D_PT_tools_active._tools_gpencil_select if _defs_gpencil_sculpt.poll_select_mask(context) @@ -2143,14 +2202,75 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel): ], 'WEIGHT_GPENCIL': [ _defs_gpencil_weight.generate_from_brushes, + None, + *_tools_annotate, ], } +class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel): + bl_space_type = 'SEQUENCE_EDITOR' + bl_region_type = 'TOOLS' + bl_label = "Tools" # not visible + bl_options = {'HIDE_HEADER'} + + # Satisfy the 'ToolSelectPanelHelper' API. + keymap_prefix = "Sequence Editor Tool:" + + # Default group to use as a fallback. + tool_fallback_id = "builtin.select" + @classmethod + def tools_from_context(cls, context, mode=None): + if mode is None: + if context.space_data: + mode = context.space_data.view_type + for tools in (cls._tools[None], cls._tools.get(mode, ())): + for item in tools: + if not (type(item) is ToolDef) and callable(item): + yield from item(context) + else: + yield item + + @classmethod + def tools_all(cls): + yield from cls._tools.items() + + _tools_select = ( + ( + _defs_sequencer_select.select, + _defs_sequencer_select.box, + ), + ) + _tools_annotate = ( + ( + _defs_annotate.scribble, + _defs_annotate.line, + _defs_annotate.poly, + _defs_annotate.eraser, + ), + ) + + _tools = { + None: [ + ], + 'PREVIEW': [ + *_tools_annotate, + ], + 'SEQUENCER': [ + *_tools_select, + _defs_sequencer_generic.cut, + ], + 'SEQUENCER_PREVIEW': [ + *_tools_select, + *_tools_annotate, + _defs_sequencer_generic.cut, + ], + } classes = ( IMAGE_PT_tools_active, NODE_PT_tools_active, VIEW3D_PT_tools_active, + SEQUENCER_PT_tools_active, ) if __name__ == "__main__": # only for live edit. diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py index 7dbf49d01e3..fd46bd53cd2 100644 --- a/release/scripts/startup/bl_ui/space_topbar.py +++ b/release/scripts/startup/bl_ui/space_topbar.py @@ -471,7 +471,7 @@ class TOPBAR_MT_file_export(Menu): text="Collada (Default) (.dae)") if bpy.app.build_options.alembic: self.layout.operator("wm.alembic_export", text="Alembic (.abc)") - if bpy.app.build_options.usd and context.preferences.experimental.use_usd_exporter: + if bpy.app.build_options.usd: self.layout.operator( "wm.usd_export", text="Universal Scene Description (.usd, .usdc, .usda)") diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 9527c7f4de8..ad5e7b5442c 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -997,6 +997,7 @@ class PreferenceThemeSpacePanel: "freestyle_face_mark", "split_normal", "bone_solid", + "bone_locked_weight", "paint_curve_pivot", }, 'GRAPH_EDITOR': { @@ -2003,7 +2004,7 @@ class USERPREF_PT_studiolight_matcaps(StudioLightPanel, StudioLightPanelMixin, P class USERPREF_PT_studiolight_world(StudioLightPanel, StudioLightPanelMixin, Panel): - bl_label = "LookDev HDRIs" + bl_label = "HDRIs" sl_type = 'WORLD' def draw_header_preset(self, _context): @@ -2087,26 +2088,6 @@ class ExperimentalPanel: url_prefix = "https://developer.blender.org/" - -class USERPREF_PT_experimental_ui(ExperimentalPanel, Panel): - bl_label = "User Interface" - - def draw(self, context): - prefs = context.preferences - experimental = prefs.experimental - - layout = self.layout - layout.use_property_split = True - layout.use_property_decorate = False - - task = "T66304" - split = layout.split(factor=0.66) - col = split.column() - col.prop(experimental, "use_tool_fallback", text="Use Tool Fallback") - col = split.column() - col.operator("wm.url_open", text=task, icon='URL').url = self.url_prefix + task - - """ # Example panel, leave it here so we always have a template to follow even # after the features are gone from the experimental panel. @@ -2114,10 +2095,14 @@ class USERPREF_PT_experimental_ui(ExperimentalPanel, Panel): class USERPREF_PT_experimental_virtual_reality(ExperimentalPanel, Panel): bl_label = "Virtual Reality" - def draw_centered(self, context, layout): + def draw(self, context): prefs = context.preferences experimental = prefs.experimental + layout = self.layout + layout.use_property_split = True + layout.use_property_decorate = False + task = "T71347" split = layout.split(factor=0.66) col = split.split() @@ -2134,30 +2119,6 @@ class USERPREF_PT_experimental_virtual_reality(ExperimentalPanel, Panel): """ -class USERPREF_PT_experimental_usd(ExperimentalPanel, Panel): - bl_label = "Universal Scene Description" - - @classmethod - def poll(cls, context): - # Only show the panel if Blender was actually built with USD support. - return getattr(bpy.app.build_options, "usd", False) - - def draw(self, context): - prefs = context.preferences - experimental = prefs.experimental - - layout = self.layout - layout.use_property_split = True - layout.use_property_decorate = False - - split = layout.split(factor=0.66) - col = split.split() - col.prop(experimental, "use_usd_exporter", text="USD Exporter") - col = split.split() - url = "https://devtalk.blender.org/t/universal-scene-description-usd-exporter-feedback/10920" - col.operator("wm.url_open", text='Give Feedback', icon='URL').url = url - - # ----------------------------------------------------------------------------- # Class Registration @@ -2242,9 +2203,6 @@ classes = ( USERPREF_PT_studiolight_matcaps, USERPREF_PT_studiolight_world, - USERPREF_PT_experimental_ui, - USERPREF_PT_experimental_usd, - # Popovers. USERPREF_PT_ndof_settings, diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 48e40554cfb..aa8f343e1a0 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -621,15 +621,19 @@ class VIEW3D_HT_header(Header): tool_settings = context.tool_settings view = context.space_data shading = view.shading - # mode_string = context.mode - obj = context.active_object show_region_tool_header = view.show_region_tool_header if not show_region_tool_header: layout.row(align=True).template_header() row = layout.row(align=True) + obj = context.active_object + # mode_string = context.mode object_mode = 'OBJECT' if obj is None else obj.mode + has_pose_mode = ( + (object_mode == 'POSE') or + (object_mode == 'WEIGHT_PAINT' and context.pose_object is not None) + ) # Note: This is actually deadly in case enum_items have to be dynamically generated # (because internal RNA array iterator will free everything immediately...). @@ -780,10 +784,13 @@ class VIEW3D_HT_header(Header): "view3d.toggle_xray", text="", icon='XRAY', - depress=getattr( - shading, - "show_xray_wireframe" if shading.type == 'WIREFRAME' else - "show_xray" + depress=( + overlay.show_xray_bone if has_pose_mode else + getattr( + shading, + "show_xray_wireframe" if shading.type == 'WIREFRAME' else + "show_xray" + ) ), ) @@ -918,7 +925,7 @@ class VIEW3D_MT_transform_base(Menu): if context.mode != 'OBJECT': layout.operator("transform.vertex_warp", text="Warp") layout.operator_context = 'EXEC_DEFAULT' - layout.operator("transform.vertex_random", text="Randomize") + layout.operator("transform.vertex_random", text="Randomize").offset = 0.1 layout.operator_context = 'INVOKE_REGION_WIN' @@ -3530,8 +3537,8 @@ class VIEW3D_MT_edit_mesh_context_menu(Menu): col.operator("transform.shear", text="Shear") col.operator("transform.vert_slide", text="Slide Vertices") col.operator_context = 'EXEC_DEFAULT' - col.operator("transform.vertex_random", text="Randomize Vertices") - col.operator("mesh.vertices_smooth", text="Smooth Vertices") + col.operator("transform.vertex_random", text="Randomize Vertices").offset = 0.1 + col.operator("mesh.vertices_smooth", text="Smooth Vertices").factor = 0.5 col.operator_context = 'INVOKE_REGION_WIN' col.operator("mesh.vertices_smooth_laplacian", text="Smooth Laplacian") @@ -3747,7 +3754,7 @@ class VIEW3D_MT_edit_mesh_vertices(Menu): layout.operator("transform.vert_slide", text="Slide Vertices") layout.operator_context = 'EXEC_DEFAULT' - layout.operator("mesh.vertices_smooth", text="Smooth Vertices") + layout.operator("mesh.vertices_smooth", text="Smooth Vertices").factor = 0.5 layout.operator_context = 'INVOKE_REGION_WIN' layout.separator() diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index f0c4aaa9344..19d5e3da309 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -313,7 +313,7 @@ class VIEW3D_PT_tools_posemode_options(View3DPanel, Panel): layout.prop(pose, "use_auto_ik") layout.prop(pose, "use_mirror_x") col = layout.column() - col.active = pose.use_mirror_x + col.active = pose.use_mirror_x and not pose.use_auto_ik col.prop(pose, "use_mirror_relative") layout.label(text="Affect Only") @@ -560,12 +560,23 @@ class VIEW3D_PT_slots_projectpaint(View3DPanel, Panel): layout.operator("image.save_all_modified", text="Save All Images", icon='FILE_TICK') +class VIEW3D_PT_mask(View3DPanel, Panel): + bl_category = "Tool" + bl_context = ".imagepaint" # dot on purpose (access from topbar) + bl_label = "Masking" + bl_options = {'DEFAULT_CLOSED'} + + def draw(self, context): + pass + + # TODO, move to space_view3d.py class VIEW3D_PT_stencil_projectpaint(View3DPanel, Panel): bl_category = "Tool" bl_context = ".imagepaint" # dot on purpose (access from topbar) - bl_label = "Mask" + bl_label = "Stencil Mask" bl_options = {'DEFAULT_CLOSED'} + bl_parent_id = "VIEW3D_PT_mask" bl_ui_units_x = 14 @classmethod @@ -1192,6 +1203,7 @@ class VIEW3D_PT_tools_imagepaint_options_cavity(View3DPaintPanel, Panel): bl_context = ".imagepaint" # dot on purpose (access from topbar) bl_label = "Cavity Mask" bl_parent_id = "VIEW3D_PT_tools_imagepaint_options" + bl_parent_id = "VIEW3D_PT_mask" bl_options = {'DEFAULT_CLOSED'} def draw_header(self, context): @@ -1876,7 +1888,7 @@ classes = ( VIEW3D_PT_tools_curveedit_options_stroke, VIEW3D_PT_tools_armatureedit_options, VIEW3D_PT_tools_posemode_options, - + VIEW3D_PT_slots_projectpaint, VIEW3D_PT_tools_brush_select, VIEW3D_PT_tools_brush_settings, @@ -1886,7 +1898,6 @@ classes = ( VIEW3D_PT_tools_brush_clone, TEXTURE_UL_texpaintslots, VIEW3D_MT_tools_projectpaint_uvlayer, - VIEW3D_PT_stencil_projectpaint, VIEW3D_PT_tools_brush_texture, VIEW3D_PT_tools_mask_texture, VIEW3D_PT_tools_brush_stroke, @@ -1912,9 +1923,13 @@ classes = ( VIEW3D_PT_tools_vertexpaint_symmetry_for_topbar, VIEW3D_PT_tools_vertexpaint_options, + VIEW3D_PT_mask, + VIEW3D_PT_stencil_projectpaint, + VIEW3D_PT_tools_imagepaint_options_cavity, + VIEW3D_PT_tools_imagepaint_symmetry, VIEW3D_PT_tools_imagepaint_options, - VIEW3D_PT_tools_imagepaint_options_cavity, + VIEW3D_PT_tools_imagepaint_options_external, VIEW3D_MT_tools_projectpaint_stencil, |