Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'release/scripts/startup/bl_ui')
-rw-r--r--release/scripts/startup/bl_ui/__init__.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_animviz.py17
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py106
-rw-r--r--release/scripts/startup/bl_ui/properties_data_armature.py1
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py4
-rw-r--r--release/scripts/startup/bl_ui/properties_data_camera.py7
-rw-r--r--release/scripts/startup/bl_ui/properties_data_gpencil.py3
-rw-r--r--release/scripts/startup/bl_ui/properties_data_mesh.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_freestyle.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_object.py30
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py13
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py14
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_rigidbody.py20
-rw-r--r--release/scripts/startup/bl_ui/properties_view_layer.py4
-rw-r--r--release/scripts/startup/bl_ui/space_clip.py38
-rw-r--r--release/scripts/startup/bl_ui/space_dopesheet.py47
-rw-r--r--release/scripts/startup/bl_ui/space_filebrowser.py194
-rw-r--r--release/scripts/startup/bl_ui/space_graph.py26
-rw-r--r--release/scripts/startup/bl_ui/space_image.py26
-rw-r--r--release/scripts/startup/bl_ui/space_nla.py30
-rw-r--r--release/scripts/startup/bl_ui/space_node.py63
-rw-r--r--release/scripts/startup/bl_ui/space_outliner.py16
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py592
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_common.py50
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py79
-rw-r--r--release/scripts/startup/bl_ui/space_topbar.py12
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py77
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py60
-rw-r--r--release/scripts/startup/bl_ui/space_view3d_toolbar.py12
29 files changed, 1210 insertions, 361 deletions
diff --git a/release/scripts/startup/bl_ui/__init__.py b/release/scripts/startup/bl_ui/__init__.py
index 25484e905c3..1fb40ad8bc8 100644
--- a/release/scripts/startup/bl_ui/__init__.py
+++ b/release/scripts/startup/bl_ui/__init__.py
@@ -117,6 +117,8 @@ def register():
for cls in mod.classes:
register_class(cls)
+ space_filebrowser.register_props()
+
from bpy.props import (
EnumProperty,
StringProperty,
diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py
index 6c3c1fd1721..28e456d023d 100644
--- a/release/scripts/startup/bl_ui/properties_animviz.py
+++ b/release/scripts/startup/bl_ui/properties_animviz.py
@@ -68,21 +68,28 @@ class MotionPathButtonsPanel:
col.prop(mpath, "frame_start", text="Cache From")
col.prop(mpath, "frame_end", text="To")
- row = layout.row(align=True)
+ col = layout.column(align=True)
+
if bones:
- row.operator("pose.paths_update", text="Update Paths", icon='BONE_DATA')
- row.operator("pose.paths_clear", text="", icon='X')
+ col.operator("pose.paths_update", text="Update Paths", icon='BONE_DATA')
else:
- row.operator("object.paths_update", text="Update Paths", icon='OBJECT_DATA')
- row.operator("object.paths_clear", text="", icon='X')
+ col.operator("object.paths_update", text="Update Paths", icon='OBJECT_DATA')
else:
col = layout.column(align=True)
col.label(text="Nothing to show yet...", icon='ERROR')
+
if bones:
col.operator("pose.paths_calculate", text="Calculate...", icon='BONE_DATA')
else:
col.operator("object.paths_calculate", text="Calculate...", icon='OBJECT_DATA')
+ row = col.row(align=True)
+ row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
+ if bones:
+ row.operator("pose.paths_clear", text="", icon='X')
+ else:
+ row.operator("object.paths_clear", text="", icon='X')
+
class MotionPathButtonsPanel_display:
bl_space_type = 'PROPERTIES'
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index 2a0cf56534c..fcac0af7e86 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -70,7 +70,7 @@ class ConstraintButtonsPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_label = ""
- bl_options = {'INSTANCED', 'HEADER_LAYOUT_EXPAND', 'DRAW_BOX'}
+ bl_options = {'INSTANCED', 'HEADER_LAYOUT_EXPAND'}
@staticmethod
def draw_influence(layout, con):
@@ -976,7 +976,6 @@ class ConstraintButtonsSubPanel:
bl_space_type = 'PROPERTIES'
bl_region_type = 'WINDOW'
bl_label = ""
- bl_options = {'DRAW_BOX'}
def get_constraint(self, _context):
con = self.custom_data
@@ -1147,6 +1146,35 @@ class ConstraintButtonsSubPanel:
col.prop(con, "frame_start", text="Frame Start")
col.prop(con, "frame_end", text="End")
+ def draw_transform_cache_velocity(self, context):
+ self.draw_transform_cache_subpanel(
+ context, self.layout.template_cache_file_velocity
+ )
+
+ def draw_transform_cache_procedural(self, context):
+ self.draw_transform_cache_subpanel(
+ context, self.layout.template_cache_file_procedural
+ )
+
+ def draw_transform_cache_time(self, context):
+ self.draw_transform_cache_subpanel(
+ context, self.layout.template_cache_file_time_settings
+ )
+
+ def draw_transform_cache_layers(self, context):
+ self.draw_transform_cache_subpanel(
+ context, self.layout.template_cache_file_layers
+ )
+
+ def draw_transform_cache_subpanel(self, context, template_func):
+ con = self.get_constraint(context)
+ if con.cache_file is None:
+ return
+
+ layout = self.layout
+ layout.use_property_split = True
+ layout.use_property_decorate = True
+ template_func(con, "cache_file")
# Child Of Constraint
@@ -1336,7 +1364,7 @@ class BONE_PT_bLockTrackConstraint(BoneConstraintPanel, ConstraintButtonsPanel,
self.draw_lock_track(context)
-# Disance Limit Constraint
+# Distance Limit Constraint
class OBJECT_PT_bDistLimitConstraint(ObjectConstraintPanel, ConstraintButtonsPanel, Panel):
def draw(self, context):
@@ -1535,6 +1563,70 @@ class BONE_PT_bTransformCacheConstraint(BoneConstraintPanel, ConstraintButtonsPa
self.draw_transform_cache(context)
+class OBJECT_PT_bTransformCacheConstraint_velocity(ObjectConstraintPanel, ConstraintButtonsSubPanel, Panel):
+ bl_parent_id = "OBJECT_PT_bTransformCacheConstraint"
+ bl_label = "Velocity"
+
+ def draw(self, context):
+ self.draw_transform_cache_velocity(context)
+
+
+class BONE_PT_bTransformCacheConstraint_velocity(BoneConstraintPanel, ConstraintButtonsSubPanel, Panel):
+ bl_parent_id = "BONE_PT_bTransformCacheConstraint"
+ bl_label = "Velocity"
+
+ def draw(self, context):
+ self.draw_transform_cache_velocity(context)
+
+
+class OBJECT_PT_bTransformCacheConstraint_layers(ObjectConstraintPanel, ConstraintButtonsSubPanel, Panel):
+ bl_parent_id = "OBJECT_PT_bTransformCacheConstraint"
+ bl_label = "Override Layers"
+
+ def draw(self, context):
+ self.draw_transform_cache_layers(context)
+
+
+class BONE_PT_bTransformCacheConstraint_layers(BoneConstraintPanel, ConstraintButtonsSubPanel, Panel):
+ bl_parent_id = "BONE_PT_bTransformCacheConstraint"
+ bl_label = "Override Layers"
+
+ def draw(self, context):
+ self.draw_transform_cache_layers(context)
+
+
+class OBJECT_PT_bTransformCacheConstraint_procedural(ObjectConstraintPanel, ConstraintButtonsSubPanel, Panel):
+ bl_parent_id = "OBJECT_PT_bTransformCacheConstraint"
+ bl_label = "Render Procedural"
+
+ def draw(self, context):
+ self.draw_transform_cache_procedural(context)
+
+
+class BONE_PT_bTransformCacheConstraint_procedural(BoneConstraintPanel, ConstraintButtonsSubPanel, Panel):
+ bl_parent_id = "BONE_PT_bTransformCacheConstraint"
+ bl_label = "Render Procedural"
+
+ def draw(self, context):
+ self.draw_transform_cache_procedural(context)
+
+
+class OBJECT_PT_bTransformCacheConstraint_time(ObjectConstraintPanel, ConstraintButtonsSubPanel, Panel):
+ bl_parent_id = "OBJECT_PT_bTransformCacheConstraint"
+ bl_label = "Time"
+
+ def draw(self, context):
+ self.draw_transform_cache_time(context)
+
+
+class BONE_PT_bTransformCacheConstraint_time(BoneConstraintPanel, ConstraintButtonsSubPanel, Panel):
+ bl_parent_id = "BONE_PT_bTransformCacheConstraint"
+ bl_label = "Time"
+
+ def draw(self, context):
+ self.draw_transform_cache_time(context)
+
+
# Python Constraint
class OBJECT_PT_bPythonConstraint(ObjectConstraintPanel, ConstraintButtonsPanel, Panel):
@@ -1621,6 +1713,10 @@ classes = (
OBJECT_PT_bCameraSolverConstraint,
OBJECT_PT_bObjectSolverConstraint,
OBJECT_PT_bTransformCacheConstraint,
+ OBJECT_PT_bTransformCacheConstraint_time,
+ OBJECT_PT_bTransformCacheConstraint_procedural,
+ OBJECT_PT_bTransformCacheConstraint_velocity,
+ OBJECT_PT_bTransformCacheConstraint_layers,
OBJECT_PT_bPythonConstraint,
OBJECT_PT_bArmatureConstraint,
OBJECT_PT_bArmatureConstraint_bones,
@@ -1658,6 +1754,10 @@ classes = (
BONE_PT_bCameraSolverConstraint,
BONE_PT_bObjectSolverConstraint,
BONE_PT_bTransformCacheConstraint,
+ BONE_PT_bTransformCacheConstraint_time,
+ BONE_PT_bTransformCacheConstraint_procedural,
+ BONE_PT_bTransformCacheConstraint_velocity,
+ BONE_PT_bTransformCacheConstraint_layers,
BONE_PT_bPythonConstraint,
BONE_PT_bArmatureConstraint,
BONE_PT_bArmatureConstraint_bones,
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py
index 87572fcd438..22f3d1a9c50 100644
--- a/release/scripts/startup/bl_ui/properties_data_armature.py
+++ b/release/scripts/startup/bl_ui/properties_data_armature.py
@@ -220,6 +220,7 @@ class DATA_PT_pose_library(ArmatureButtonsPanel, Panel):
).pose_index = poselib.pose_markers.active_index
col.operator("poselib.action_sanitize", icon='HELP', text="") # XXX: put in menu?
+ col.operator("poselib.convert_old_poselib", icon='ASSET_MANAGER', text="")
if pose_marker_active is not None:
col.operator("poselib.pose_move", icon='TRIA_UP', text="").direction = 'UP'
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py
index daf64642f68..1a00150d6d2 100644
--- a/release/scripts/startup/bl_ui/properties_data_bone.py
+++ b/release/scripts/startup/bl_ui/properties_data_bone.py
@@ -196,7 +196,7 @@ class BONE_PT_curved(BoneButtonsPanel, Panel):
row2.prop(bone, "bbone_handle_use_scale_start", index=1, text="Y", toggle=True)
row2.prop(bone, "bbone_handle_use_scale_start", index=2, text="Z", toggle=True)
split2.prop(bone, "bbone_handle_use_ease_start", text="Ease", toggle=True)
- row.label(icon="BLANK1")
+ row.label(icon='BLANK1')
col = topcol.column(align=True)
col.prop(bone, "bbone_handle_type_end", text="End Handle")
@@ -216,7 +216,7 @@ class BONE_PT_curved(BoneButtonsPanel, Panel):
row2.prop(bone, "bbone_handle_use_scale_end", index=1, text="Y", toggle=True)
row2.prop(bone, "bbone_handle_use_scale_end", index=2, text="Z", toggle=True)
split2.prop(bone, "bbone_handle_use_ease_end", text="Ease", toggle=True)
- row.label(icon="BLANK1")
+ row.label(icon='BLANK1')
class BONE_PT_relations(BoneButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_data_camera.py b/release/scripts/startup/bl_ui/properties_data_camera.py
index a8ef5c14a91..20bee833847 100644
--- a/release/scripts/startup/bl_ui/properties_data_camera.py
+++ b/release/scripts/startup/bl_ui/properties_data_camera.py
@@ -110,6 +110,13 @@ class DATA_PT_lens(CameraButtonsPanel, Panel):
sub = col.column(align=True)
sub.prop(ccam, "longitude_min", text="Longitude Min")
sub.prop(ccam, "longitude_max", text="Max")
+ elif ccam.panorama_type == 'FISHEYE_LENS_POLYNOMIAL':
+ col.prop(ccam, "fisheye_fov")
+ col.prop(ccam, "fisheye_polynomial_k0", text="K0")
+ col.prop(ccam, "fisheye_polynomial_k1", text="K1")
+ col.prop(ccam, "fisheye_polynomial_k2", text="K2")
+ col.prop(ccam, "fisheye_polynomial_k3", text="K3")
+ col.prop(ccam, "fisheye_polynomial_k4", text="K4")
elif engine == 'BLENDER_EEVEE':
col.prop(cam, "panorama_type")
if cam.panorama_type == 'FISHEYE_EQUIDISTANT':
diff --git a/release/scripts/startup/bl_ui/properties_data_gpencil.py b/release/scripts/startup/bl_ui/properties_data_gpencil.py
index 793c4a52350..34e83573bc9 100644
--- a/release/scripts/startup/bl_ui/properties_data_gpencil.py
+++ b/release/scripts/startup/bl_ui/properties_data_gpencil.py
@@ -110,7 +110,8 @@ class GPENCIL_MT_layer_context_menu(Menu):
layout.separator()
- layout.operator("gpencil.layer_merge", icon='SORT_ASC', text="Merge Down")
+ layout.operator("gpencil.layer_merge", icon='SORT_ASC', text="Merge Down").mode = 'ACTIVE'
+ layout.operator("gpencil.layer_merge", text="Merge All").mode = 'ALL'
layout.separator()
layout.operator("gpencil.layer_duplicate_object", text="Copy Layer to Selected").only_active = True
diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py
index ba5ecd1efde..11e2cd84903 100644
--- a/release/scripts/startup/bl_ui/properties_data_mesh.py
+++ b/release/scripts/startup/bl_ui/properties_data_mesh.py
@@ -82,6 +82,14 @@ class MESH_MT_shape_key_context_menu(Menu):
layout.operator("object.shape_key_move", icon='TRIA_UP_BAR', text="Move to Top").type = 'TOP'
layout.operator("object.shape_key_move", icon='TRIA_DOWN_BAR', text="Move to Bottom").type = 'BOTTOM'
+class MESH_MT_attribute_context_menu(Menu):
+ bl_label = "Attribute Specials"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator("geometry.attribute_convert")
+
class MESH_UL_vgroups(UIList):
def draw_item(self, _context, layout, _data, item, icon, _active_data_, _active_propname, _index):
@@ -557,6 +565,7 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel):
col.enabled = obj is not None and obj.mode != 'EDIT'
col.prop(me, "use_customdata_vertex_bevel", text="Vertex Bevel Weight")
col.prop(me, "use_customdata_edge_bevel", text="Edge Bevel Weight")
+ col.prop(me, "use_customdata_vertex_crease", text="Vertex Crease")
col.prop(me, "use_customdata_edge_crease", text="Edge Crease")
@@ -614,6 +623,10 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
col.operator("geometry.attribute_add", icon='ADD', text="")
col.operator("geometry.attribute_remove", icon='REMOVE', text="")
+ col.separator()
+
+ col.menu("MESH_MT_attribute_context_menu", icon='DOWNARROW_HLT', text="")
+
self.draw_attribute_warnings(context, layout)
def draw_attribute_warnings(self, context, layout):
@@ -651,6 +664,7 @@ class DATA_PT_mesh_attributes(MeshButtonsPanel, Panel):
classes = (
MESH_MT_vertex_group_context_menu,
MESH_MT_shape_key_context_menu,
+ MESH_MT_attribute_context_menu,
MESH_UL_vgroups,
MESH_UL_fmaps,
MESH_UL_shape_keys,
diff --git a/release/scripts/startup/bl_ui/properties_freestyle.py b/release/scripts/startup/bl_ui/properties_freestyle.py
index 3c765c10154..802812020b7 100644
--- a/release/scripts/startup/bl_ui/properties_freestyle.py
+++ b/release/scripts/startup/bl_ui/properties_freestyle.py
@@ -280,7 +280,7 @@ class VIEWLAYER_PT_freestyle_lineset(ViewLayerFreestyleEditorButtonsPanel, Panel
col.separator()
- col.menu("RENDER_MT_lineset_context_menu", icon="DOWNARROW_HLT", text="")
+ col.menu("RENDER_MT_lineset_context_menu", icon='DOWNARROW_HLT', text="")
if is_sortable:
col.separator()
@@ -526,7 +526,7 @@ class VIEWLAYER_PT_freestyle_linestyle_strokes(ViewLayerFreestyleLineStyle, Pane
row = layout.row(align=True)
row.alignment = 'LEFT'
row.label(text=lineset.name, icon='LINE_DATA')
- row.label(text="", icon='SMALL_TRI_RIGHT_VEC')
+ row.label(text="", icon='RIGHTARROW')
row.label(text=linestyle.name)
col = layout.column(align=True)
@@ -830,7 +830,7 @@ class VIEWLAYER_PT_freestyle_linestyle_color(ViewLayerFreestyleLineStyle, Panel)
row = layout.row(align=True)
row.alignment = 'LEFT'
row.label(text=lineset.name, icon='LINE_DATA')
- row.label(text="", icon='SMALL_TRI_RIGHT_VEC')
+ row.label(text="", icon='RIGHTARROW')
row.label(text=linestyle.name)
col = layout.column()
@@ -922,7 +922,7 @@ class VIEWLAYER_PT_freestyle_linestyle_alpha(ViewLayerFreestyleLineStyle, Panel)
row = layout.row(align=True)
row.alignment = 'LEFT'
row.label(text=lineset.name, icon='LINE_DATA')
- row.label(text="", icon='SMALL_TRI_RIGHT_VEC')
+ row.label(text="", icon='RIGHTARROW')
row.label(text=linestyle.name)
col = layout.column()
@@ -1036,7 +1036,7 @@ class VIEWLAYER_PT_freestyle_linestyle_thickness(ViewLayerFreestyleLineStyle, Pa
row = layout.row(align=True)
row.alignment = 'LEFT'
row.label(text=lineset.name, icon='LINE_DATA')
- row.label(text="", icon='SMALL_TRI_RIGHT_VEC')
+ row.label(text="", icon='RIGHTARROW')
row.label(text=linestyle.name)
col = layout.column()
@@ -1182,7 +1182,7 @@ class VIEWLAYER_PT_freestyle_linestyle_geometry(ViewLayerFreestyleLineStyle, Pan
row = layout.row(align=True)
row.alignment = 'LEFT'
row.label(text=lineset.name, icon='LINE_DATA')
- row.label(text="", icon='SMALL_TRI_RIGHT_VEC')
+ row.label(text="", icon='RIGHTARROW')
row.label(text=linestyle.name)
col = layout.column()
@@ -1215,7 +1215,7 @@ class VIEWLAYER_PT_freestyle_linestyle_texture(ViewLayerFreestyleLineStyle, Pane
row = layout.row(align=True)
row.alignment = 'LEFT'
row.label(text=lineset.name, icon='LINE_DATA')
- row.label(text="", icon='SMALL_TRI_RIGHT_VEC')
+ row.label(text="", icon='RIGHTARROW')
row.label(text=linestyle.name)
layout.prop(linestyle, "use_nodes")
diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py
index 81a641a20cf..fbd4ed3225a 100644
--- a/release/scripts/startup/bl_ui/properties_object.py
+++ b/release/scripts/startup/bl_ui/properties_object.py
@@ -184,24 +184,18 @@ class OBJECT_PT_collections(ObjectButtonsPanel, Panel):
row.operator("object.collection_add", text="Add to Collection")
row.operator("object.collection_add", text="", icon='ADD')
- obj_name = obj.name
- for collection in bpy.data.collections:
- # XXX this is slow and stupid!, we need 2 checks, one that's fast
- # and another that we can be sure its not a name collision
- # from linked library data
- collection_objects = collection.objects
- if obj_name in collection.objects and obj in collection_objects[:]:
- col = layout.column(align=True)
-
- col.context_pointer_set("collection", collection)
-
- row = col.box().row()
- row.prop(collection, "name", text="")
- row.operator("object.collection_remove", text="", icon='X', emboss=False)
- row.menu("COLLECTION_MT_context_menu", icon='DOWNARROW_HLT', text="")
-
- row = col.box().row()
- row.prop(collection, "instance_offset", text="")
+ for collection in obj.users_collection:
+ col = layout.column(align=True)
+
+ col.context_pointer_set("collection", collection)
+
+ row = col.box().row()
+ row.prop(collection, "name", text="")
+ row.operator("object.collection_remove", text="", icon='X', emboss=False)
+ row.menu("COLLECTION_MT_context_menu", icon='DOWNARROW_HLT', text="")
+
+ row = col.box().row()
+ row.prop(collection, "instance_offset", text="")
class OBJECT_PT_display(ObjectButtonsPanel, Panel):
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index c038f5f906a..347f771d1f6 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -496,7 +496,7 @@ class DisplayPanel(BrushPanel):
icon='HIDE_OFF' if brush.use_cursor_overlay else 'HIDE_ON',
)
- if mode in ['PAINT_2D', 'PAINT_TEXTURE', 'PAINT_VERTEX', 'SCULPT']:
+ if mode in {'PAINT_2D', 'PAINT_TEXTURE', 'PAINT_VERTEX', 'SCULPT'}:
row = col.row(align=True)
row.prop(brush, "texture_overlay_alpha", text="Texture Opacity")
row.prop(brush, "use_primary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
@@ -506,7 +506,7 @@ class DisplayPanel(BrushPanel):
icon='HIDE_OFF' if brush.use_primary_overlay else 'HIDE_ON',
)
- if mode in ['PAINT_TEXTURE', 'PAINT_2D']:
+ if mode in {'PAINT_TEXTURE', 'PAINT_2D'}:
row = col.row(align=True)
row.prop(brush, "mask_overlay_alpha", text="Mask Texture Opacity")
row.prop(brush, "use_secondary_overlay_override", toggle=True, text="", icon='BRUSH_DATA')
@@ -1107,7 +1107,11 @@ def brush_basic_texpaint_settings(layout, context, brush, *, compact=False):
capabilities = brush.image_paint_capabilities
if capabilities.has_color:
- UnifiedPaintPanel.prop_unified_color(layout, context, brush, "color", text="")
+ row = layout.row(align=True)
+ row.ui_units_x = 4
+ UnifiedPaintPanel.prop_unified_color(row, context, brush, "color", text="")
+ UnifiedPaintPanel.prop_unified_color(row, context, brush, "secondary_color", text="")
+ row.separator()
layout.prop(brush, "blend", text="" if compact else "Blend")
UnifiedPaintPanel.prop_unified(
@@ -1151,7 +1155,8 @@ def brush_basic__draw_color_selector(context, layout, brush, gp_settings, props)
if len(txt_ma) > maxw:
txt_ma = txt_ma[:maxw - 5] + '..' + txt_ma[-3:]
- sub = row.row()
+ sub = row.row(align=True)
+ sub.enabled = not gp_settings.use_material_pin
sub.ui_units_x = 8
sub.popover(
panel="TOPBAR_PT_gpencil_materials",
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 6408d4096fe..47f0b399b66 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -227,7 +227,12 @@ class PHYSICS_PT_settings(PhysicButtonsPanel, Panel):
split.enabled = note_flag and ob.mode == 'OBJECT'
bake_incomplete = (domain.cache_frame_pause_data < domain.cache_frame_end)
- if domain.cache_resumable and domain.has_cache_baked_data and not domain.is_cache_baking_data and bake_incomplete:
+ if (
+ domain.cache_resumable and
+ domain.has_cache_baked_data and
+ not domain.is_cache_baking_data and
+ bake_incomplete
+ ):
col = split.column()
col.operator("fluid.bake_data", text="Resume")
col = split.column()
@@ -1249,7 +1254,12 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel):
split.enabled = ob.mode == 'OBJECT'
bake_incomplete = (domain.cache_frame_pause_data < domain.cache_frame_end)
- if domain.cache_resumable and domain.has_cache_baked_data and not domain.is_cache_baking_data and bake_incomplete:
+ if (
+ domain.cache_resumable and
+ 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()
diff --git a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
index a55bd89ca18..9afe8415cf4 100644
--- a/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
+++ b/release/scripts/startup/bl_ui/properties_physics_rigidbody.py
@@ -109,7 +109,11 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
@classmethod
def poll(cls, context):
obj = context.object
- if obj.parent is not None and obj.parent.rigid_body is not None and not obj.parent.rigid_body.collision_shape == 'COMPOUND':
+ if (
+ (obj.parent is not None) and
+ (obj.parent.rigid_body is not None) and
+ (not obj.parent.rigid_body.collision_shape == 'COMPOUND')
+ ):
return False
return (obj and obj.rigid_body and (context.engine in cls.COMPAT_ENGINES))
@@ -124,7 +128,11 @@ class PHYSICS_PT_rigid_body_collisions(PHYSICS_PT_rigidbody_panel, Panel):
layout.prop(rbo, "collision_shape", text="Shape")
if rbo.collision_shape == 'COMPOUND':
- if parent is not None and parent.rigid_body is not None and parent.rigid_body.collision_shape == 'COMPOUND':
+ if (
+ (parent is not None) and
+ (parent.rigid_body is not None) and
+ (parent.rigid_body.collision_shape == 'COMPOUND')
+ ):
rigid_body_warning(layout, "Sub compound shapes are not allowed")
else:
found = False
@@ -179,7 +187,11 @@ class PHYSICS_PT_rigid_body_collisions_sensitivity(PHYSICS_PT_rigidbody_panel, P
@classmethod
def poll(cls, context):
obj = context.object
- if obj.parent is not None and obj.parent.rigid_body is not None and not obj.parent.rigid_body.collision_shape == 'COMPOUND':
+ if (
+ (obj.parent is not None) and
+ (obj.parent.rigid_body is not None) and
+ (not obj.parent.rigid_body.collision_shape == 'COMPOUND')
+ ):
return False
return (obj and obj.rigid_body and (context.engine in cls.COMPAT_ENGINES))
@@ -249,7 +261,7 @@ class PHYSICS_PT_rigid_body_dynamics(PHYSICS_PT_rigidbody_panel, Panel):
# col = layout.column(align=True)
# col.label(text="Activation:")
- # XXX: settings such as activate on collison/etc.
+ # XXX: settings such as activate on collision/etc.
col = flow.column()
col.prop(rbo, "linear_damping", text="Damping Translation")
diff --git a/release/scripts/startup/bl_ui/properties_view_layer.py b/release/scripts/startup/bl_ui/properties_view_layer.py
index 4b341e969c4..1387b1e7450 100644
--- a/release/scripts/startup/bl_ui/properties_view_layer.py
+++ b/release/scripts/startup/bl_ui/properties_view_layer.py
@@ -198,6 +198,10 @@ class ViewLayerCryptomattePanel(ViewLayerButtonsPanel, Panel):
view_layer.use_pass_cryptomatte_asset))
col.prop(view_layer, "pass_cryptomatte_depth", text="Levels")
+ if context.engine == 'BLENDER_EEVEE':
+ col.prop(view_layer, "use_pass_cryptomatte_accurate",
+ text="Accurate Mode")
+
class VIEWLAYER_PT_layer_passes_cryptomatte(ViewLayerCryptomattePanel, Panel):
bl_parent_id = "VIEWLAYER_PT_layer_passes"
diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py
index c18d77987ad..86e9ef3d664 100644
--- a/release/scripts/startup/bl_ui/space_clip.py
+++ b/release/scripts/startup/bl_ui/space_clip.py
@@ -1858,6 +1858,43 @@ class CLIP_MT_reconstruction_pie(Menu):
pie.operator("clip.apply_solution_scale", icon='ARROW_LEFTRIGHT')
+class CLIP_MT_view_pie(Menu):
+ bl_label = "View"
+
+ @classmethod
+ def poll(cls, context):
+ space = context.space_data
+
+ # View operators are not yet implemented in Dopesheet mode.
+ return space.view != 'DOPESHEET'
+
+ def draw(self, context):
+ layout = self.layout
+ sc = context.space_data
+
+ pie = layout.menu_pie()
+
+ if sc.view == 'CLIP':
+ pie.operator("clip.view_all")
+ pie.operator("clip.view_selected", icon='ZOOM_SELECTED')
+
+ if sc.mode == 'MASK':
+ pie.operator("clip.view_center_cursor")
+ pie.separator()
+ else:
+ # Add spaces so items stay in the same position through all modes.
+ pie.separator()
+ pie.separator()
+
+ pie.operator("clip.view_all", text="Frame All Fit").fit_view = True
+
+ if sc.view == 'GRAPH':
+ pie.operator_context = 'INVOKE_REGION_PREVIEW'
+ pie.operator("clip.graph_view_all")
+ pie.separator()
+ pie.operator("clip.graph_center_current_frame")
+
+
classes = (
CLIP_UL_tracking_objects,
CLIP_HT_header,
@@ -1925,6 +1962,7 @@ classes = (
CLIP_MT_tracking_pie,
CLIP_MT_reconstruction_pie,
CLIP_MT_solving_pie,
+ CLIP_MT_view_pie,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 781c430a752..18dfa4da6c6 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -379,6 +379,18 @@ class DOPESHEET_MT_view(Menu):
layout.menu("INFO_MT_area")
+class DOPESHEET_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("action.view_all")
+ pie.operator("action.view_selected", icon='ZOOM_SELECTED')
+ pie.operator("action.view_frame")
+
+
class DOPESHEET_MT_select(Menu):
bl_label = "Select"
@@ -527,6 +539,39 @@ class DOPESHEET_MT_key_transform(Menu):
layout.operator("transform.transform", text="Scale").mode = 'TIME_SCALE'
+class DopesheetActionPanelBase:
+ bl_region_type = 'UI'
+ bl_label = "Action"
+
+ @classmethod
+ def draw_generic_panel(cls, _context, layout, action):
+ layout.label(text=action.name, icon='ACTION')
+
+ layout.prop(action, "use_frame_range")
+
+ col = layout.column()
+ col.active = action.use_frame_range
+
+ row = col.row(align=True)
+ row.prop(action, "frame_start", text="Start")
+ row.prop(action, "frame_end", text="End")
+
+ col.prop(action, "use_cyclic")
+
+
+class DOPESHEET_PT_action(DopesheetActionPanelBase, Panel):
+ bl_space_type = 'DOPESHEET_EDITOR'
+ bl_category = "Item"
+
+ @classmethod
+ def poll(cls, context):
+ return bool(context.selected_visible_actions)
+
+ def draw(self, context):
+ action = context.selected_visible_actions[0]
+ self.draw_generic_panel(context, self.layout, action)
+
+
#######################################
# Grease Pencil Editing
@@ -778,7 +823,9 @@ classes = (
DOPESHEET_MT_context_menu,
DOPESHEET_MT_channel_context_menu,
DOPESHEET_MT_snap_pie,
+ DOPESHEET_MT_view_pie,
DOPESHEET_PT_filters,
+ DOPESHEET_PT_action,
DOPESHEET_PT_gpencil_mode,
DOPESHEET_PT_gpencil_layer_masks,
DOPESHEET_PT_gpencil_layer_transform,
diff --git a/release/scripts/startup/bl_ui/space_filebrowser.py b/release/scripts/startup/bl_ui/space_filebrowser.py
index b47404fd727..50005a8f7f0 100644
--- a/release/scripts/startup/bl_ui/space_filebrowser.py
+++ b/release/scripts/startup/bl_ui/space_filebrowser.py
@@ -36,15 +36,10 @@ class FILEBROWSER_HT_header(Header):
space_data = context.space_data
params = space_data.params
- row = layout.row(align=True)
- row.prop(params, "asset_library_ref", text="")
- # External libraries don't auto-refresh, add refresh button.
- if params.asset_library_ref != 'LOCAL':
- row.operator("file.refresh", text="", icon='FILE_REFRESH')
-
layout.separator_spacer()
- layout.prop(params, "import_type", text="")
+ if params.asset_library_ref != 'LOCAL':
+ layout.prop(params, "import_type", text="")
layout.separator_spacer()
@@ -57,7 +52,15 @@ class FILEBROWSER_HT_header(Header):
icon_only=True,
)
- layout.prop(params, "filter_search", text="", icon='VIEWZOOM')
+ sub = layout.row()
+ sub.ui_units_x = 8
+ sub.prop(params, "filter_search", text="", icon='VIEWZOOM')
+
+ layout.popover(
+ panel="ASSETBROWSER_PT_filter",
+ text="",
+ icon='FILTER'
+ )
layout.operator(
"screen.region_toggle",
@@ -132,7 +135,7 @@ class FILEBROWSER_PT_display(FileBrowserPanel, Panel):
class FILEBROWSER_PT_filter(FileBrowserPanel, Panel):
bl_region_type = 'HEADER'
bl_label = "Filter Settings" # Shows as tooltip in popover
- bl_ui_units_x = 8
+ bl_ui_units_x = 10
def draw(self, context):
layout = self.layout
@@ -195,13 +198,14 @@ class FILEBROWSER_PT_filter(FileBrowserPanel, Panel):
sub = row.column(align=True)
- if context.preferences.experimental.use_extended_asset_browser:
- sub.prop(params, "use_filter_asset_only")
+ sub.prop(params, "use_filter_asset_only")
filter_id = params.filter_id
for identifier in dir(filter_id):
if identifier.startswith("category_"):
- sub.prop(filter_id, identifier, toggle=True)
+ subrow = sub.row()
+ subrow.label(icon=filter_id.bl_rna.properties[identifier].icon)
+ subrow.prop(filter_id, identifier, toggle=False)
col.separator()
@@ -394,11 +398,19 @@ class FILEBROWSER_PT_advanced_filter(Panel):
filter_id = params.filter_id
for identifier in dir(filter_id):
if identifier.startswith("filter_"):
- col.prop(filter_id, identifier, toggle=True)
+ row = col.row()
+ row.label(icon=filter_id.bl_rna.properties[identifier].icon)
+ row.prop(filter_id, identifier, toggle=False)
def is_option_region_visible(context, space):
- if not space.active_operator:
+ from bpy_extras.asset_utils import SpaceAssetInfo
+
+ if SpaceAssetInfo.is_asset_browser(space):
+ pass
+ # For the File Browser, there must be an operator for there to be options
+ # (irrelevant for the Asset Browser).
+ elif not space.active_operator:
return False
for region in context.area.regions:
@@ -594,6 +606,31 @@ class ASSETBROWSER_PT_display(asset_utils.AssetBrowserPanel, Panel):
col.prop(params, "show_details_datetime", text="Date")
+class ASSETBROWSER_PT_filter(asset_utils.AssetBrowserPanel, Panel):
+ bl_region_type = 'HEADER'
+ bl_category = "Filter"
+ bl_label = "Filter"
+
+ def draw(self, context):
+ layout = self.layout
+ space = context.space_data
+ params = space.params
+ use_extended_browser = context.preferences.experimental.use_extended_asset_browser
+
+ if params.use_filter_blendid:
+ col = layout.column(align=True)
+
+ filter_id = params.filter_asset_id
+ for identifier in dir(filter_id):
+ if (
+ identifier.startswith("filter_") or
+ (identifier.startswith("experimental_filter_") and use_extended_browser)
+ ):
+ row = col.row()
+ row.label(icon=filter_id.bl_rna.properties[identifier].icon)
+ row.prop(filter_id, identifier, toggle=False)
+
+
class AssetBrowserMenu:
@classmethod
def poll(cls, context):
@@ -610,6 +647,7 @@ class ASSETBROWSER_MT_editor_menus(AssetBrowserMenu, Menu):
layout.menu("ASSETBROWSER_MT_view")
layout.menu("ASSETBROWSER_MT_select")
+ layout.menu("ASSETBROWSER_MT_edit")
class ASSETBROWSER_MT_view(AssetBrowserMenu, Menu):
@@ -648,28 +686,14 @@ class ASSETBROWSER_MT_select(AssetBrowserMenu, Menu):
layout.operator("file.select_box")
-class ASSETBROWSER_PT_navigation_bar(asset_utils.AssetBrowserPanel, Panel):
- bl_label = "Asset Navigation"
- bl_region_type = 'TOOLS'
- bl_options = {'HIDE_HEADER'}
-
- @classmethod
- def poll(cls, context):
- return (
- asset_utils.AssetBrowserPanel.poll(context) and
- context.preferences.experimental.use_extended_asset_browser
- )
+class ASSETBROWSER_MT_edit(AssetBrowserMenu, Menu):
+ bl_label = "Edit"
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
- space_file = context.space_data
-
- col = layout.column()
-
- col.scale_x = 1.3
- col.scale_y = 1.3
- col.prop(space_file.params, "asset_category", expand=True)
+ layout.operator("asset.catalog_undo", text="Undo")
+ layout.operator("asset.catalog_redo", text="Redo")
class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
@@ -679,42 +703,48 @@ class ASSETBROWSER_PT_metadata(asset_utils.AssetBrowserPanel, Panel):
def draw(self, context):
layout = self.layout
+ wm = context.window_manager
asset_file_handle = context.asset_file_handle
if asset_file_handle is None:
- layout.label(text="No asset selected", icon='INFO')
+ layout.label(text="No active asset", icon='INFO')
return
asset_library_ref = context.asset_library_ref
asset_lib_path = bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library_ref)
+ prefs = context.preferences
+ show_asset_debug_info = prefs.view.show_developer_ui and prefs.experimental.show_asset_debug_info
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False # No animation.
+
if asset_file_handle.local_id:
# If the active file is an ID, use its name directly so renaming is possible from right here.
- layout.prop(asset_file_handle.local_id, "name", text="")
+ layout.prop(asset_file_handle.local_id, "name")
- col = layout.column(align=True)
- col.label(text="Asset Catalog:")
- col.prop(asset_file_handle.local_id.asset_data, "catalog_id", text="UUID")
- col.prop(asset_file_handle.local_id.asset_data, "catalog_simple_name", text="Simple Name")
-
- row = layout.row()
- row.label(text="Source: Current File")
+ if show_asset_debug_info:
+ col = layout.column(align=True)
+ col.label(text="Asset Catalog:")
+ col.prop(asset_file_handle.local_id.asset_data, "catalog_id", text="UUID")
+ col.prop(asset_file_handle.local_id.asset_data, "catalog_simple_name", text="Simple Name")
else:
- layout.prop(asset_file_handle, "name", text="")
-
- col = layout.column(align=True)
- col.enabled = False
- col.label(text="Asset Catalog:")
- col.prop(asset_file_handle.asset_data, "catalog_id", text="UUID")
- col.prop(asset_file_handle.asset_data, "catalog_simple_name", text="Simple Name")
+ layout.prop(asset_file_handle, "name")
- col = layout.column(align=True) # Just to reduce margin.
- col.label(text="Source:")
- row = col.row()
- row.label(text=asset_lib_path)
+ if show_asset_debug_info:
+ col = layout.column(align=True)
+ col.enabled = False
+ col.label(text="Asset Catalog:")
+ col.prop(asset_file_handle.asset_data, "catalog_id", text="UUID")
+ col.prop(asset_file_handle.asset_data, "catalog_simple_name", text="Simple Name")
+ row = layout.row(align=True)
+ row.prop(wm, "asset_path_dummy", text="Source")
row.operator("asset.open_containing_blend_file", text="", icon='TOOL_SETTINGS')
+ layout.prop(asset_file_handle.asset_data, "description")
+ layout.prop(asset_file_handle.asset_data, "author")
+
class ASSETBROWSER_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel):
bl_label = "Preview"
@@ -726,24 +756,20 @@ class ASSETBROWSER_PT_metadata_preview(asset_utils.AssetMetaDataPanel, Panel):
row = layout.row()
box = row.box()
box.template_icon(icon_value=active_file.preview_icon_id, scale=5.0)
- if bpy.ops.ed.lib_id_load_custom_preview.poll():
- col = row.column(align=True)
- col.operator("ed.lib_id_load_custom_preview", icon='FILEBROWSER', text="")
- col.separator()
- col.operator("ed.lib_id_generate_preview", icon='FILE_REFRESH', text="")
+
+ col = row.column(align=True)
+ col.operator("ed.lib_id_load_custom_preview", icon='FILEBROWSER', text="")
+ col.separator()
+ col.operator("ed.lib_id_generate_preview", icon='FILE_REFRESH', text="")
+ col.menu("ASSETBROWSER_MT_metadata_preview_menu", icon='DOWNARROW_HLT', text="")
-class ASSETBROWSER_PT_metadata_details(asset_utils.AssetMetaDataPanel, Panel):
- bl_label = "Details"
+class ASSETBROWSER_MT_metadata_preview_menu(bpy.types.Menu):
+ bl_label = "Preview"
def draw(self, context):
layout = self.layout
- active_asset = asset_utils.SpaceAssetInfo.get_active_asset(context)
-
- layout.use_property_split = True
-
- if active_asset:
- layout.prop(active_asset, "description")
+ layout.operator("ed.lib_id_generate_preview_from_object", text="Render Active Object")
class ASSETBROWSER_PT_metadata_tags(asset_utils.AssetMetaDataPanel, Panel):
@@ -782,7 +808,7 @@ class ASSETBROWSER_MT_context_menu(AssetBrowserMenu, Menu):
st = context.space_data
params = st.params
- layout.operator("file.refresh", text="Refresh")
+ layout.operator("asset.library_refresh")
layout.separator()
@@ -818,18 +844,48 @@ classes = (
FILEBROWSER_MT_select,
FILEBROWSER_MT_context_menu,
ASSETBROWSER_PT_display,
+ ASSETBROWSER_PT_filter,
ASSETBROWSER_MT_editor_menus,
ASSETBROWSER_MT_view,
ASSETBROWSER_MT_select,
- ASSETBROWSER_PT_navigation_bar,
+ ASSETBROWSER_MT_edit,
+ ASSETBROWSER_MT_metadata_preview_menu,
ASSETBROWSER_PT_metadata,
ASSETBROWSER_PT_metadata_preview,
- ASSETBROWSER_PT_metadata_details,
ASSETBROWSER_PT_metadata_tags,
ASSETBROWSER_UL_metadata_tags,
ASSETBROWSER_MT_context_menu,
)
+def asset_path_str_get(_self):
+ asset_file_handle = bpy.context.asset_file_handle
+ if asset_file_handle is None:
+ return ""
+
+ if asset_file_handle.local_id:
+ return "Current File"
+
+ asset_library_ref = bpy.context.asset_library_ref
+ return bpy.types.AssetHandle.get_full_library_path(asset_file_handle, asset_library_ref)
+
+
+def register_props():
+ from bpy.props import (
+ StringProperty,
+ )
+ from bpy.types import (
+ WindowManager,
+ )
+
+ # Just a dummy property to be able to show a string in a label button via
+ # UILayout.prop().
+ WindowManager.asset_path_dummy = StringProperty(
+ name="Asset Blend Path",
+ description="Full path to the Blender file containing the active asset",
+ get=asset_path_str_get,
+ )
+
+
if __name__ == "__main__": # only for live edit.
from bpy.utils import register_class
diff --git a/release/scripts/startup/bl_ui/space_graph.py b/release/scripts/startup/bl_ui/space_graph.py
index 612b7ba2b09..db0020b7846 100644
--- a/release/scripts/startup/bl_ui/space_graph.py
+++ b/release/scripts/startup/bl_ui/space_graph.py
@@ -298,6 +298,8 @@ class GRAPH_MT_key(Menu):
layout.operator("graph.decimate", text="Decimate (Allowed Change)").mode = 'ERROR'
layout.operator_context = operator_context
+ layout.menu("GRAPH_MT_slider", text="Slider Operators")
+
layout.operator("graph.clean").channels = False
layout.operator("graph.clean", text="Clean Channels").channels = True
layout.operator("graph.smooth")
@@ -333,10 +335,32 @@ class GRAPH_MT_key_snap(Menu):
layout.operator("graph.snap", text="Selection to Nearest Second").type = 'NEAREST_SECOND'
layout.operator("graph.snap", text="Selection to Nearest Marker").type = 'NEAREST_MARKER'
layout.operator("graph.snap", text="Flatten Handles").type = 'HORIZONTAL'
+ layout.operator("graph.equalize_handles", text="Equalize Handles").side = 'BOTH'
layout.separator()
layout.operator("graph.frame_jump", text="Cursor to Selection")
layout.operator("graph.snap_cursor_value", text="Cursor Value to Selection")
+class GRAPH_MT_slider(Menu):
+ bl_label = "Slider Operators"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("graph.breakdown", text="Breakdown")
+ layout.operator("graph.blend_to_neighbor", text="Blend To Neighbor")
+
+
+class GRAPH_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("graph.view_all")
+ pie.operator("graph.view_selected", icon='ZOOM_SELECTED')
+ pie.operator("graph.view_frame")
+
class GRAPH_MT_delete(Menu):
bl_label = "Delete"
@@ -463,11 +487,13 @@ classes = (
GRAPH_MT_key,
GRAPH_MT_key_transform,
GRAPH_MT_key_snap,
+ GRAPH_MT_slider,
GRAPH_MT_delete,
GRAPH_MT_context_menu,
GRAPH_MT_channel_context_menu,
GRAPH_MT_pivot_pie,
GRAPH_MT_snap_pie,
+ GRAPH_MT_view_pie,
GRAPH_PT_filters,
)
diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py
index 6a769b1aecc..8e82b07716c 100644
--- a/release/scripts/startup/bl_ui/space_image.py
+++ b/release/scripts/startup/bl_ui/space_image.py
@@ -591,6 +591,31 @@ class IMAGE_MT_uvs_snap_pie(Menu):
).target = 'ADJACENT_UNSELECTED'
+class IMAGE_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ sima = context.space_data
+ show_uvedit = sima.show_uvedit
+ show_maskedit = sima.show_maskedit
+
+ pie = layout.menu_pie()
+ pie.operator("image.view_all")
+
+ if show_uvedit or show_maskedit:
+ pie.operator("image.view_selected", text="Frame Selected", icon='ZOOM_SELECTED')
+ pie.operator("image.view_center_cursor", text="Center View to Cursor")
+ else:
+ # Add spaces so items stay in the same position through all modes.
+ pie.separator()
+ pie.separator()
+
+ pie.operator("image.view_zoom_ratio", text="Zoom 1:1").ratio = 1
+ pie.operator("image.view_all", text="Frame All Fit").fit_view = True
+
+
class IMAGE_HT_tool_header(Header):
bl_space_type = 'IMAGE_EDITOR'
bl_region_type = 'TOOL_HEADER'
@@ -1633,6 +1658,7 @@ classes = (
IMAGE_MT_mask_context_menu,
IMAGE_MT_pivot_pie,
IMAGE_MT_uvs_snap_pie,
+ IMAGE_MT_view_pie,
IMAGE_HT_tool_header,
IMAGE_HT_header,
IMAGE_MT_editor_menus,
diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index d472352084c..2db2b11a5f9 100644
--- a/release/scripts/startup/bl_ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -22,6 +22,7 @@ from bpy.types import Header, Menu, Panel
from bpy.app.translations import contexts as i18n_contexts
from bl_ui.space_dopesheet import (
DopesheetFilterPopoverBase,
+ DopesheetActionPanelBase,
dopesheet_filter,
)
@@ -66,6 +67,21 @@ class NLA_PT_filters(DopesheetFilterPopoverBase, Panel):
DopesheetFilterPopoverBase.draw_standard_filters(context, layout)
+class NLA_PT_action(DopesheetActionPanelBase, Panel):
+ bl_space_type = 'NLA_EDITOR'
+ bl_category = "Strip"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ strip = context.active_nla_strip
+ return strip and strip.type == 'CLIP' and strip.action
+
+ def draw(self, context):
+ action = context.active_nla_strip.action
+ self.draw_generic_panel(context, self.layout, action)
+
+
class NLA_MT_editor_menus(Menu):
bl_idname = "NLA_MT_editor_menus"
bl_label = ""
@@ -247,6 +263,18 @@ class NLA_MT_snap_pie(Menu):
pie.operator("nla.snap", text="Selection to Nearest Marker").type = 'NEAREST_MARKER'
+class NLA_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("nla.view_all")
+ pie.operator("nla.view_selected", icon='ZOOM_SELECTED')
+ pie.operator("nla.view_frame")
+
+
class NLA_MT_context_menu(Menu):
bl_label = "NLA Context Menu"
@@ -300,9 +328,11 @@ classes = (
NLA_MT_add,
NLA_MT_edit_transform,
NLA_MT_snap_pie,
+ NLA_MT_view_pie,
NLA_MT_context_menu,
NLA_MT_channel_context_menu,
NLA_PT_filters,
+ NLA_PT_action,
)
if __name__ == "__main__": # only for live edit.
diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py
index f806fc345d1..5cf3a6109d0 100644
--- a/release/scripts/startup/bl_ui/space_node.py
+++ b/release/scripts/startup/bl_ui/space_node.py
@@ -49,6 +49,7 @@ class NODE_HT_header(Header):
scene = context.scene
snode = context.space_data
+ overlay = snode.overlay
snode_id = snode.id
id_from = snode.id_from
tool_settings = context.tool_settings
@@ -205,6 +206,13 @@ class NODE_HT_header(Header):
if tool_settings.snap_node_element != 'GRID':
row.prop(tool_settings, "snap_target", text="")
+ # Overlay toggle & popover
+ row = layout.row(align=True)
+ row.prop(overlay, "show_overlays", icon='OVERLAY', text="")
+ sub = row.row(align=True)
+ sub.active = overlay.show_overlays
+ sub.popover(panel="NODE_PT_overlay", text="")
+
class NODE_MT_editor_menus(Menu):
bl_idname = "NODE_MT_editor_menus"
@@ -359,6 +367,17 @@ class NODE_MT_node(Menu):
layout.operator("node.read_viewlayers")
+class NODE_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("node.view_all")
+ pie.operator("node.view_selected", icon='ZOOM_SELECTED')
+
+
class NODE_PT_active_tool(ToolActivePanelHelper, Panel):
bl_space_type = 'NODE_EDITOR'
bl_region_type = 'UI'
@@ -680,6 +699,34 @@ class NODE_PT_quality(bpy.types.Panel):
col.prop(snode, "use_auto_render")
+class NODE_PT_overlay(Panel):
+ bl_space_type = 'NODE_EDITOR'
+ bl_region_type = 'HEADER'
+ bl_label = "Overlays"
+ bl_ui_units_x = 7
+
+ def draw(self, context):
+ layout = self.layout
+ layout.label(text="Node Editor Overlays")
+
+ snode = context.space_data
+ overlay = snode.overlay
+
+ layout.active = overlay.show_overlays
+
+ col = layout.column()
+ col.prop(overlay, "show_wire_color", text="Wire Colors")
+
+ col.separator()
+
+ col.prop(overlay, "show_context_path", text="Context Path")
+ col.prop(snode, "show_annotation", text="Annotations")
+
+ if snode.tree_type == 'GeometryNodeTree':
+ col.separator()
+ col.prop(overlay, "show_timing", text="Timings")
+
+
class NODE_UL_interface_sockets(bpy.types.UIList):
def draw_item(self, context, layout, _data, item, icon, _active_data, _active_propname, _index):
socket = item
@@ -755,9 +802,17 @@ class NodeTreeInterfacePanel:
if tree.type == 'GEOMETRY':
layout.prop(active_socket, "description")
field_socket_prefixes = {
- "NodeSocketInt", "NodeSocketColor", "NodeSocketVector", "NodeSocketBool", "NodeSocketFloat"}
- is_field_type = any(active_socket.bl_socket_idname.startswith(prefix) for prefix in field_socket_prefixes)
- if in_out == "OUT" and is_field_type:
+ "NodeSocketInt",
+ "NodeSocketColor",
+ "NodeSocketVector",
+ "NodeSocketBool",
+ "NodeSocketFloat",
+ }
+ is_field_type = any(
+ active_socket.bl_socket_idname.startswith(prefix)
+ for prefix in field_socket_prefixes
+ )
+ if in_out == 'OUT' and is_field_type:
layout.prop(active_socket, "attribute_domain")
active_socket.draw(context, layout)
@@ -838,6 +893,7 @@ classes = (
NODE_MT_node,
NODE_MT_node_color_context_menu,
NODE_MT_context_menu,
+ NODE_MT_view_pie,
NODE_PT_material_slots,
NODE_PT_node_color_presets,
NODE_PT_active_node_generic,
@@ -848,6 +904,7 @@ classes = (
NODE_PT_backdrop,
NODE_PT_quality,
NODE_PT_annotation,
+ NODE_PT_overlay,
NODE_UL_interface_sockets,
NODE_PT_node_tree_interface_inputs,
NODE_PT_node_tree_interface_outputs,
diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py
index 3d18160d90f..d85538a37e0 100644
--- a/release/scripts/startup/bl_ui/space_outliner.py
+++ b/release/scripts/startup/bl_ui/space_outliner.py
@@ -142,6 +142,17 @@ class OUTLINER_MT_context_menu_view(Menu):
layout.operator("outliner.show_one_level", text="Hide One Level").open = False
+class OUTLINER_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("outliner.show_hierarchy")
+ pie.operator("outliner.show_active", icon='ZOOM_SELECTED')
+
+
class OUTLINER_MT_edit_datablocks(Menu):
bl_label = "Edit"
@@ -313,10 +324,6 @@ class OUTLINER_MT_object(Menu):
class OUTLINER_MT_asset(Menu):
bl_label = "Assets"
- @classmethod
- def poll(cls, context):
- return context.preferences.experimental.use_extended_asset_browser
-
def draw(self, context):
layout = self.layout
@@ -475,6 +482,7 @@ classes = (
OUTLINER_MT_asset,
OUTLINER_MT_context_menu,
OUTLINER_MT_context_menu_view,
+ OUTLINER_MT_view_pie,
OUTLINER_PT_filter,
)
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 7b102604587..6035170f9df 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -37,6 +37,14 @@ from bl_ui.space_toolsystem_common import (
from rna_prop_ui import PropertyPanel
+def _space_view_types(st):
+ view_type = st.view_type
+ return (
+ view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'},
+ view_type == 'PREVIEW',
+ )
+
+
def selected_sequences_len(context):
selected_sequences = getattr(context, "selected_sequences", None)
if selected_sequences is None:
@@ -46,44 +54,85 @@ def selected_sequences_len(context):
def draw_color_balance(layout, color_balance):
+ layout.prop(color_balance, "correction_method")
+
layout.use_property_split = False
flow = layout.grid_flow(row_major=True, columns=0, even_columns=True, even_rows=False, align=False)
- col = flow.column()
-
- box = col.box()
- split = box.split(factor=0.35)
- col = split.column(align=True)
- col.label(text="Lift:")
- col.separator()
- col.separator()
- col.prop(color_balance, "lift", text="")
- col.prop(color_balance, "invert_lift", text="Invert", icon='ARROW_LEFTRIGHT')
- split.template_color_picker(color_balance, "lift", value_slider=True, cubic=True)
-
- col = flow.column()
-
- box = col.box()
- split = box.split(factor=0.35)
- col = split.column(align=True)
- col.label(text="Gamma:")
- col.separator()
- col.separator()
- col.prop(color_balance, "gamma", text="")
- col.prop(color_balance, "invert_gamma", text="Invert", icon='ARROW_LEFTRIGHT')
- split.template_color_picker(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True)
-
- col = flow.column()
-
- box = col.box()
- split = box.split(factor=0.35)
- col = split.column(align=True)
- col.label(text="Gain:")
- col.separator()
- col.separator()
- col.prop(color_balance, "gain", text="")
- col.prop(color_balance, "invert_gain", text="Invert", icon='ARROW_LEFTRIGHT')
- split.template_color_picker(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True)
+
+ if color_balance.correction_method == 'LIFT_GAMMA_GAIN':
+ col = flow.column()
+
+ box = col.box()
+ split = box.split(factor=0.35)
+ col = split.column(align=True)
+ col.label(text="Lift:")
+ col.separator()
+ col.separator()
+ col.prop(color_balance, "lift", text="")
+ col.prop(color_balance, "invert_lift", text="Invert", icon='ARROW_LEFTRIGHT')
+ split.template_color_picker(color_balance, "lift", value_slider=True, cubic=True)
+
+ col = flow.column()
+
+ box = col.box()
+ split = box.split(factor=0.35)
+ col = split.column(align=True)
+ col.label(text="Gamma:")
+ col.separator()
+ col.separator()
+ col.prop(color_balance, "gamma", text="")
+ col.prop(color_balance, "invert_gamma", text="Invert", icon='ARROW_LEFTRIGHT')
+ split.template_color_picker(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True)
+
+ col = flow.column()
+
+ box = col.box()
+ split = box.split(factor=0.35)
+ col = split.column(align=True)
+ col.label(text="Gain:")
+ col.separator()
+ col.separator()
+ col.prop(color_balance, "gain", text="")
+ col.prop(color_balance, "invert_gain", text="Invert", icon='ARROW_LEFTRIGHT')
+ split.template_color_picker(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True)
+
+ elif color_balance.correction_method == 'OFFSET_POWER_SLOPE':
+ col = flow.column()
+
+ box = col.box()
+ split = box.split(factor=0.35)
+ col = split.column(align=True)
+ col.label(text="Offset:")
+ col.separator()
+ col.separator()
+ col.prop(color_balance, "offset", text="")
+ col.prop(color_balance, "invert_offset", text="Invert", icon='ARROW_LEFTRIGHT')
+ split.template_color_picker(color_balance, "offset", value_slider=True, cubic=True)
+
+ col = flow.column()
+
+ box = col.box()
+ split = box.split(factor=0.35)
+ col = split.column(align=True)
+ col.label(text="Power:")
+ col.separator()
+ col.separator()
+ col.prop(color_balance, "power", text="")
+ col.prop(color_balance, "invert_power", text="Invert", icon='ARROW_LEFTRIGHT')
+ split.template_color_picker(color_balance, "power", value_slider=True, cubic=True)
+
+ col = flow.column()
+
+ box = col.box()
+ split = box.split(factor=0.35)
+ col = split.column(align=True)
+ col.label(text="Slope:")
+ col.separator()
+ col.separator()
+ col.prop(color_balance, "slope", text="")
+ col.prop(color_balance, "invert_slope", text="Invert", icon='ARROW_LEFTRIGHT')
+ split.template_color_picker(color_balance, "slope", value_slider=True, cubic=True)
class SEQUENCER_PT_active_tool(ToolActivePanelHelper, Panel):
@@ -128,8 +177,6 @@ class SEQUENCER_HT_header(Header):
st = context.space_data
- show_region_tool_header = st.show_region_tool_header
-
layout.template_header()
layout.prop(st, "view_type", text="")
@@ -148,8 +195,8 @@ class SEQUENCER_HT_header(Header):
if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
row = layout.row(align=True)
row.prop(sequencer_tool_settings, "overlap_mode", text="")
- row = layout.row(align=True)
- row.prop(sequencer_tool_settings, "pivot_point", text="", icon_only=True)
+
+ if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
row = layout.row(align=True)
row.prop(tool_settings, "use_snap_sequencer", text="")
sub = row.row(align=True)
@@ -160,11 +207,22 @@ class SEQUENCER_HT_header(Header):
layout.prop(st, "display_mode", text="", icon_only=True)
layout.prop(st, "preview_channels", text="", icon_only=True)
+ # Gizmo toggle & popover.
+ row = layout.row(align=True)
+ # FIXME: place-holder icon.
+ row.prop(st, "show_gizmo", text="", toggle=True, icon='GIZMO')
+ sub = row.row(align=True)
+ sub.active = st.show_gizmo
+ sub.popover(
+ panel="SEQUENCER_PT_gizmo_display",
+ text="",
+ )
+
row = layout.row(align=True)
- row.prop(st, "show_strip_overlay", text="", icon='OVERLAY')
+ row.prop(st, "show_overlays", text="", icon='OVERLAY')
sub = row.row(align=True)
sub.popover(panel="SEQUENCER_PT_overlay", text="")
- sub.active = st.show_strip_overlay
+ sub.active = st.show_overlays
class SEQUENCER_MT_editor_menus(Menu):
@@ -174,15 +232,43 @@ class SEQUENCER_MT_editor_menus(Menu):
def draw(self, context):
layout = self.layout
st = context.space_data
+ has_sequencer, _has_preview = _space_view_types(st)
layout.menu("SEQUENCER_MT_view")
+ layout.menu("SEQUENCER_MT_select")
- if st.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'}:
- layout.menu("SEQUENCER_MT_select")
+ if has_sequencer:
if st.show_markers:
layout.menu("SEQUENCER_MT_marker")
layout.menu("SEQUENCER_MT_add")
- layout.menu("SEQUENCER_MT_strip")
+
+ layout.menu("SEQUENCER_MT_strip")
+
+ if st.view_type in {'SEQUENCER', 'PREVIEW'}:
+ layout.menu("SEQUENCER_MT_image")
+
+
+class SEQUENCER_PT_gizmo_display(Panel):
+ bl_space_type = 'SEQUENCE_EDITOR'
+ bl_region_type = 'HEADER'
+ bl_label = "Gizmos"
+ bl_ui_units_x = 8
+
+ def draw(self, context):
+ layout = self.layout
+
+ scene = context.scene
+ st = context.space_data
+
+ col = layout.column()
+ col.label(text="Viewport Gizmos")
+ col.separator()
+
+ col.active = st.show_gizmo
+ colsub = col.column()
+ colsub.prop(st, "show_gizmo_navigate", text="Navigate")
+ colsub.prop(st, "show_gizmo_tool", text="Active Tools")
+ # colsub.prop(st, "show_gizmo_context", text="Active Object") # Currently unused.
class SEQUENCER_PT_overlay(Panel):
@@ -212,9 +298,10 @@ class SEQUENCER_PT_preview_overlay(Panel):
overlay_settings = st.preview_overlay
layout = self.layout
- layout.active = st.show_strip_overlay
+ layout.active = st.show_overlays
layout.prop(overlay_settings, "show_image_outline")
- layout.prop(ed, "show_overlay", text="Frame Overlay")
+ layout.prop(overlay_settings, "show_cursor")
+ layout.prop(ed, "show_overlay_frame", text="Frame Overlay")
layout.prop(overlay_settings, "show_safe_areas", text="Safe Areas")
layout.prop(overlay_settings, "show_metadata", text="Metadata")
layout.prop(overlay_settings, "show_annotation", text="Annotations")
@@ -236,7 +323,7 @@ class SEQUENCER_PT_sequencer_overlay(Panel):
overlay_settings = st.timeline_overlay
layout = self.layout
- layout.active = st.show_strip_overlay
+ layout.active = st.show_overlays
layout.prop(overlay_settings, "show_strip_name", text="Name")
layout.prop(overlay_settings, "show_strip_source", text="Source")
@@ -342,6 +429,7 @@ class SEQUENCER_MT_view(Menu):
# wm_keymap_item_find_props() (see T32595).
layout.operator_context = 'INVOKE_REGION_PREVIEW'
layout.prop(st, "show_region_ui")
+ layout.prop(st, "show_region_tool_header")
layout.prop(st, "show_region_toolbar")
layout.operator_context = 'INVOKE_DEFAULT'
@@ -480,8 +568,10 @@ class SEQUENCER_MT_select_linked(Menu):
class SEQUENCER_MT_select(Menu):
bl_label = "Select"
- def draw(self, _context):
+ def draw(self, context):
layout = self.layout
+ st = context.space_data
+ has_sequencer, has_preview = _space_view_types(st)
layout.operator("sequencer.select_all", text="All").action = 'SELECT'
layout.operator("sequencer.select_all", text="None").action = 'DESELECT'
@@ -490,17 +580,20 @@ class SEQUENCER_MT_select(Menu):
layout.separator()
layout.operator("sequencer.select_box", text="Box Select")
- props = layout.operator("sequencer.select_box", text="Box Select (Include Handles)")
- props.include_handles = True
+ if has_sequencer:
+ props = layout.operator("sequencer.select_box", text="Box Select (Include Handles)")
+ props.include_handles = True
layout.separator()
- layout.operator_menu_enum("sequencer.select_side_of_frame", "side", text="Side of Frame...")
- layout.menu("SEQUENCER_MT_select_handle", text="Handle")
- layout.menu("SEQUENCER_MT_select_channel", text="Channel")
- layout.menu("SEQUENCER_MT_select_linked", text="Linked")
+ if has_sequencer:
+ layout.operator_menu_enum("sequencer.select_side_of_frame", "side", text="Side of Frame...")
+ layout.menu("SEQUENCER_MT_select_handle", text="Handle")
+ layout.menu("SEQUENCER_MT_select_channel", text="Channel")
+ layout.menu("SEQUENCER_MT_select_linked", text="Linked")
+
+ layout.separator()
- layout.separator()
layout.operator_menu_enum("sequencer.select_grouped", "type", text="Grouped")
@@ -708,43 +801,42 @@ class SEQUENCER_MT_add_effect(Menu):
col.enabled = selected_sequences_len(context) != 0
-class SEQUENCER_MT_strip_image_transform(Menu):
- bl_label = "Image Transform"
-
- def draw(self, _context):
- layout = self.layout
-
- layout.operator("sequencer.strip_transform_fit", text="Scale To Fit").fit_method = 'FIT'
- layout.operator("sequencer.strip_transform_fit", text="Scale to Fill").fit_method = 'FILL'
- layout.operator("sequencer.strip_transform_fit", text="Stretch To Fill").fit_method = 'STRETCH'
- layout.separator()
-
- layout.operator("sequencer.strip_transform_clear", text="Clear Position").property = 'POSITION'
- layout.operator("sequencer.strip_transform_clear", text="Clear Scale").property = 'SCALE'
- layout.operator("sequencer.strip_transform_clear", text="Clear Rotation").property = 'ROTATION'
- layout.operator("sequencer.strip_transform_clear", text="Clear All").property = 'ALL'
-
-
class SEQUENCER_MT_strip_transform(Menu):
bl_label = "Transform"
- def draw(self, _context):
+ def draw(self, context):
layout = self.layout
+ st = context.space_data
+ has_sequencer, has_preview = _space_view_types(st)
- layout.operator("transform.seq_slide", text="Move")
- layout.operator("transform.transform", text="Move/Extend from Current Frame").mode = 'TIME_EXTEND'
- layout.operator("sequencer.slip", text="Slip Strip Contents")
+ if has_preview:
+ layout.operator_context = 'INVOKE_REGION_PREVIEW'
+ else:
+ layout.operator_context = 'INVOKE_REGION_WIN'
- layout.separator()
- layout.operator("sequencer.snap")
- layout.operator("sequencer.offset_clear")
+ if has_preview:
+ layout.operator("transform.translate", text="Move")
+ layout.operator("transform.rotate", text="Rotate")
+ layout.operator("transform.resize", text="Scale")
+ else:
+ layout.operator("transform.seq_slide", text="Move")
+ layout.operator("transform.transform", text="Move/Extend from Current Frame").mode = 'TIME_EXTEND'
+ layout.operator("sequencer.slip", text="Slip Strip Contents")
- layout.separator()
- layout.operator_menu_enum("sequencer.swap", "side")
+ # TODO (for preview)
+ if has_sequencer:
+ layout.separator()
+ layout.operator("sequencer.snap")
+ layout.operator("sequencer.offset_clear")
- layout.separator()
- layout.operator("sequencer.gap_remove").all = False
- layout.operator("sequencer.gap_insert")
+ layout.separator()
+
+ if has_sequencer:
+ layout.operator_menu_enum("sequencer.swap", "side")
+
+ layout.separator()
+ layout.operator("sequencer.gap_remove").all = False
+ layout.operator("sequencer.gap_insert")
class SEQUENCER_MT_strip_input(Menu):
@@ -814,69 +906,123 @@ class SEQUENCER_MT_strip(Menu):
def draw(self, context):
layout = self.layout
+ st = context.space_data
+ has_sequencer, has_preview = _space_view_types(st)
- layout.operator_context = 'INVOKE_REGION_WIN'
-
- layout.separator()
layout.menu("SEQUENCER_MT_strip_transform")
- layout.menu("SEQUENCER_MT_strip_image_transform")
-
layout.separator()
- layout.operator("sequencer.split", text="Split").type = 'SOFT'
- layout.operator("sequencer.split", text="Hold Split").type = 'HARD'
- layout.separator()
- layout.operator("sequencer.copy", text="Copy")
- layout.operator("sequencer.paste", text="Paste")
- layout.operator("sequencer.duplicate_move")
+ if has_sequencer:
+
+ layout.operator("sequencer.split", text="Split").type = 'SOFT'
+ layout.operator("sequencer.split", text="Hold Split").type = 'HARD'
+ layout.separator()
+
+ if has_sequencer:
+ layout.operator("sequencer.copy", text="Copy")
+ layout.operator("sequencer.paste", text="Paste")
+ layout.operator("sequencer.duplicate_move")
+
layout.operator("sequencer.delete", text="Delete")
strip = context.active_sequence_strip
- if strip:
- strip_type = strip.type
+ if has_sequencer:
+ if strip:
+ strip_type = strip.type
- if strip_type != 'SOUND':
- layout.separator()
- layout.operator_menu_enum("sequencer.strip_modifier_add", "type", text="Add Modifier")
- layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
+ if strip_type != 'SOUND':
+ layout.separator()
+ layout.operator_menu_enum("sequencer.strip_modifier_add", "type", text="Add Modifier")
+ layout.operator("sequencer.strip_modifier_copy", text="Copy Modifiers to Selection")
+
+ if strip_type in {
+ 'CROSS', 'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
+ 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP', 'WIPE', 'GLOW',
+ 'TRANSFORM', 'COLOR', 'SPEED', 'MULTICAM', 'ADJUSTMENT',
+ 'GAUSSIAN_BLUR',
+ }:
+ layout.separator()
+ layout.menu("SEQUENCER_MT_strip_effect")
+ elif strip_type == 'MOVIE':
+ layout.separator()
+ layout.menu("SEQUENCER_MT_strip_movie")
+ elif strip_type == 'IMAGE':
+ layout.separator()
+ layout.operator("sequencer.rendersize")
+ layout.operator("sequencer.images_separate")
+ elif strip_type == 'TEXT':
+ layout.separator()
+ layout.menu("SEQUENCER_MT_strip_effect")
+ elif strip_type == 'META':
+ layout.separator()
+ layout.operator("sequencer.meta_make")
+ layout.operator("sequencer.meta_separate")
+ layout.operator("sequencer.meta_toggle", text="Toggle Meta")
+ if strip_type != 'META':
+ layout.separator()
+ layout.operator("sequencer.meta_make")
+ layout.operator("sequencer.meta_toggle", text="Toggle Meta")
- if strip_type in {
- 'CROSS', 'ADD', 'SUBTRACT', 'ALPHA_OVER', 'ALPHA_UNDER',
- 'GAMMA_CROSS', 'MULTIPLY', 'OVER_DROP', 'WIPE', 'GLOW',
- 'TRANSFORM', 'COLOR', 'SPEED', 'MULTICAM', 'ADJUSTMENT',
- 'GAUSSIAN_BLUR',
- }:
- layout.separator()
- layout.menu("SEQUENCER_MT_strip_effect")
- elif strip_type == 'MOVIE':
- layout.separator()
- layout.menu("SEQUENCER_MT_strip_movie")
- elif strip_type == 'IMAGE':
- layout.separator()
- layout.operator("sequencer.rendersize")
- layout.operator("sequencer.images_separate")
- elif strip_type == 'TEXT':
- layout.separator()
- layout.menu("SEQUENCER_MT_strip_effect")
- elif strip_type == 'META':
- layout.separator()
- layout.operator("sequencer.meta_make")
- layout.operator("sequencer.meta_separate")
- layout.operator("sequencer.meta_toggle", text="Toggle Meta")
- if strip_type != 'META':
- layout.separator()
- layout.operator("sequencer.meta_make")
- layout.operator("sequencer.meta_toggle", text="Toggle Meta")
+ if has_sequencer:
+ layout.separator()
+ layout.menu("SEQUENCER_MT_color_tag_picker")
- layout.separator()
- layout.menu("SEQUENCER_MT_color_tag_picker")
+ layout.separator()
+ layout.menu("SEQUENCER_MT_strip_lock_mute")
- layout.separator()
- layout.menu("SEQUENCER_MT_strip_lock_mute")
+ layout.separator()
+ layout.menu("SEQUENCER_MT_strip_input")
- layout.separator()
- layout.menu("SEQUENCER_MT_strip_input")
+
+class SEQUENCER_MT_image(Menu):
+ bl_label = "Image"
+
+ def draw(self, context):
+ layout = self.layout
+ st = context.space_data
+
+ if st.view_type == {'PREVIEW', 'SEQUENCER_PREVIEW'}:
+ layout.menu("SEQUENCER_MT_image_transform")
+
+ layout.menu("SEQUENCER_MT_image_clear")
+ layout.menu("SEQUENCER_MT_image_apply")
+
+
+class SEQUENCER_MT_image_transform(Menu):
+ bl_label = "Transform"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator_context = 'INVOKE_REGION_PREVIEW'
+
+ layout.operator("transform.translate")
+ layout.operator("transform.rotate")
+ layout.operator("transform.resize", text="Scale")
+
+
+class SEQUENCER_MT_image_clear(Menu):
+ bl_label = "Clear"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("sequencer.strip_transform_clear", text="Position").property = 'POSITION'
+ layout.operator("sequencer.strip_transform_clear", text="Scale").property = 'SCALE'
+ layout.operator("sequencer.strip_transform_clear", text="Rotation").property = 'ROTATION'
+ layout.operator("sequencer.strip_transform_clear", text="All Transforms").property = 'ALL'
+
+
+class SEQUENCER_MT_image_apply(Menu):
+ bl_label = "Apply"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("sequencer.strip_transform_fit", text="Scale To Fit").fit_method = 'FIT'
+ layout.operator("sequencer.strip_transform_fit", text="Scale to Fill").fit_method = 'FILL'
+ layout.operator("sequencer.strip_transform_fit", text="Stretch To Fill").fit_method = 'STRETCH'
class SEQUENCER_MT_context_menu(Menu):
@@ -976,6 +1122,68 @@ class SEQUENCER_MT_context_menu(Menu):
layout.menu("SEQUENCER_MT_strip_lock_mute")
+class SEQUENCER_MT_preview_context_menu(Menu):
+ bl_label = "Sequencer Preview Context Menu"
+
+ def draw(self, context):
+ layout = self.layout
+
+ layout.operator_context = 'INVOKE_REGION_WIN'
+
+ props = layout.operator("wm.call_panel", text="Rename...")
+ props.name = "TOPBAR_PT_name"
+ props.keep_open = False
+
+ # TODO: support in preview.
+ # layout.operator("sequencer.delete", text="Delete")
+
+ strip = context.active_sequence_strip
+
+ if strip:
+ pass
+
+
+class SEQUENCER_MT_pivot_pie(Menu):
+ bl_label = "Pivot Point"
+
+ def draw(self, context):
+ layout = self.layout
+ pie = layout.menu_pie()
+
+ tool_settings = context.tool_settings
+ sequencer_tool_settings = context.tool_settings.sequencer_tool_settings
+
+ pie.prop_enum(sequencer_tool_settings, "pivot_point", value='CENTER')
+ pie.prop_enum(sequencer_tool_settings, "pivot_point", value='CURSOR')
+ pie.prop_enum(sequencer_tool_settings, "pivot_point", value='INDIVIDUAL_ORIGINS')
+ pie.prop_enum(sequencer_tool_settings, "pivot_point", value='MEDIAN')
+
+
+class SEQUENCER_MT_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator("sequencer.view_all")
+ pie.operator("sequencer.view_selected", text="Frame Selected", icon='ZOOM_SELECTED')
+
+
+class SEQUENCER_MT_preview_view_pie(Menu):
+ bl_label = "View"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ pie = layout.menu_pie()
+ pie.operator_context = 'INVOKE_REGION_PREVIEW'
+ pie.operator("sequencer.view_all_preview")
+ pie.operator("sequencer.view_selected", text="Frame Selected", icon='ZOOM_SELECTED')
+ pie.separator()
+ pie.operator("sequencer.view_zoom_ratio", text="Zoom 1:1").ratio = 1
+
+
class SequencerButtonsPanel:
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'UI'
@@ -1003,35 +1211,38 @@ class SequencerButtonsPanel_Output:
return cls.has_preview(context)
-class SEQUENCER_PT_color_tag_picker(Panel):
- bl_label = "Color Tag"
+class SequencerColorTagPicker:
bl_space_type = 'SEQUENCE_EDITOR'
bl_region_type = 'UI'
- bl_category = "Strip"
- bl_options = {'HIDE_HEADER', 'INSTANCED'}
+
+ @staticmethod
+ def has_sequencer(context):
+ return (context.space_data.view_type in {'SEQUENCER', 'SEQUENCER_PREVIEW'})
@classmethod
def poll(cls, context):
- return context.active_sequence_strip is not None
+ return cls.has_sequencer(context) and context.active_sequence_strip is not None
- def draw(self, context):
+
+class SEQUENCER_PT_color_tag_picker(SequencerColorTagPicker, Panel):
+ bl_label = "Color Tag"
+ bl_category = "Strip"
+ bl_options = {'HIDE_HEADER', 'INSTANCED'}
+
+ def draw(self, _context):
layout = self.layout
row = layout.row(align=True)
- row.operator("sequencer.strip_color_tag_set", icon="X").color = 'NONE'
+ row.operator("sequencer.strip_color_tag_set", icon='X').color = 'NONE'
for i in range(1, 10):
icon = 'SEQUENCE_COLOR_%02d' % i
row.operator("sequencer.strip_color_tag_set", icon=icon).color = 'COLOR_%02d' % i
-class SEQUENCER_MT_color_tag_picker(Menu):
+class SEQUENCER_MT_color_tag_picker(SequencerColorTagPicker, Menu):
bl_label = "Set Color Tag"
- @classmethod
- def poll(cls, context):
- return context.active_sequence_strip is not None
-
- def draw(self, context):
+ def draw(self, _context):
layout = self.layout
row = layout.row(align=True)
@@ -1195,15 +1406,15 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
elif strip_type == 'SPEED':
col = layout.column(align=True)
col.prop(strip, "speed_control", text="Speed Control")
- if strip.speed_control == "MULTIPLY":
+ if strip.speed_control == 'MULTIPLY':
col.prop(strip, "speed_factor", text=" ")
- elif strip.speed_control == "LENGTH":
+ elif strip.speed_control == 'LENGTH':
col.prop(strip, "speed_length", text=" ")
- elif strip.speed_control == "FRAME_NUMBER":
+ elif strip.speed_control == 'FRAME_NUMBER':
col.prop(strip, "speed_frame_number", text=" ")
row = layout.row(align=True)
- row.enabled = strip.speed_control != "STRETCH"
+ row.enabled = strip.speed_control != 'STRETCH'
row = layout.row(align=True, heading="Interpolation")
row.prop(strip, "use_frame_interpolate", text="")
@@ -1710,7 +1921,6 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel):
def draw(self, context):
layout = self.layout
- layout.use_property_split = False
st = context.space_data
overlay_settings = st.timeline_overlay
@@ -1720,16 +1930,7 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel):
layout.active = not strip.mute
if sound is not None:
- col = layout.column()
-
- split = col.split(factor=0.4)
- split.label(text="")
- split.prop(sound, "use_mono")
- if overlay_settings.waveform_display_type == 'DEFAULT_WAVEFORMS':
- split = col.split(factor=0.4)
- split.label(text="")
- split.prop(strip, "show_waveform")
-
+ layout.use_property_split = True
col = layout.column()
split = col.split(factor=0.4)
@@ -1742,15 +1943,37 @@ class SEQUENCER_PT_adjust_sound(SequencerButtonsPanel, Panel):
split.label(text="Pitch")
split.prop(strip, "pitch", text="")
+ audio_channels = context.scene.render.ffmpeg.audio_channels
+ pan_enabled = sound.use_mono and audio_channels != 'MONO'
+ pan_text = "%.2f°" % (strip.pan * 90)
+
split = col.split(factor=0.4)
split.alignment = 'RIGHT'
split.label(text="Pan")
- audio_channels = context.scene.render.ffmpeg.audio_channels
- pan_text = ""
+ split.prop(strip, "pan", text="")
+ split.enabled = pan_enabled
+
if audio_channels != 'MONO' and audio_channels != 'STEREO':
- pan_text = "%.2f°" % (strip.pan * 90)
- split.prop(strip, "pan", text=pan_text)
- split.enabled = sound.use_mono and audio_channels != 'MONO'
+ split = col.split(factor=0.4)
+ split.alignment = 'RIGHT'
+ split.label(text="Pan Angle")
+ split.enabled = pan_enabled
+ subsplit = split.row()
+ subsplit.alignment = 'CENTER'
+ subsplit.label(text=pan_text)
+ subsplit.label(text=" ") # Compensate for no decorate.
+ subsplit.enabled = pan_enabled
+
+ layout.use_property_split = False
+ col = layout.column()
+
+ split = col.split(factor=0.4)
+ split.label(text="")
+ split.prop(sound, "use_mono")
+ if overlay_settings.waveform_display_type == 'DEFAULT_WAVEFORMS':
+ split = col.split(factor=0.4)
+ split.label(text="")
+ split.prop(strip, "show_waveform")
@@ -2104,6 +2327,22 @@ class SEQUENCER_PT_view(SequencerButtonsPanel_Output, Panel):
col.prop(st, "show_separate_color")
+class SEQUENCER_PT_view_cursor(SequencerButtonsPanel_Output, Panel):
+ bl_category = "View"
+ bl_label = "2D Cursor"
+
+ def draw(self, context):
+ layout = self.layout
+
+ st = context.space_data
+
+ layout.use_property_split = True
+ layout.use_property_decorate = False
+
+ col = layout.column()
+ col.prop(st, "cursor_location", text="Location")
+
+
class SEQUENCER_PT_frame_overlay(SequencerButtonsPanel_Output, Panel):
bl_label = "Frame Overlay"
bl_category = "View"
@@ -2119,7 +2358,7 @@ class SEQUENCER_PT_frame_overlay(SequencerButtonsPanel_Output, Panel):
scene = context.scene
ed = scene.sequence_editor
- self.layout.prop(ed, "show_overlay", text="")
+ self.layout.prop(ed, "show_overlay_frame", text="")
def draw(self, context):
layout = self.layout
@@ -2135,12 +2374,12 @@ class SEQUENCER_PT_frame_overlay(SequencerButtonsPanel_Output, Panel):
scene = context.scene
ed = scene.sequence_editor
- layout.active = ed.show_overlay
+ layout.active = ed.show_overlay_frame
col = layout.column()
col.prop(ed, "overlay_frame", text="Frame Offset")
- col.prop(st, "overlay_type")
- col.prop(ed, "use_overlay_lock")
+ col.prop(st, "overlay_frame_type")
+ col.prop(ed, "use_overlay_frame_lock")
class SEQUENCER_PT_view_safe_areas(SequencerButtonsPanel_Output, Panel):
@@ -2376,18 +2615,26 @@ classes = (
SEQUENCER_MT_strip_effect,
SEQUENCER_MT_strip_movie,
SEQUENCER_MT_strip,
- SEQUENCER_MT_strip_image_transform,
SEQUENCER_MT_strip_transform,
SEQUENCER_MT_strip_input,
SEQUENCER_MT_strip_lock_mute,
+ SEQUENCER_MT_image,
+ SEQUENCER_MT_image_transform,
+ SEQUENCER_MT_image_clear,
+ SEQUENCER_MT_image_apply,
SEQUENCER_MT_color_tag_picker,
SEQUENCER_MT_context_menu,
+ SEQUENCER_MT_preview_context_menu,
+ SEQUENCER_MT_pivot_pie,
+ SEQUENCER_MT_view_pie,
+ SEQUENCER_MT_preview_view_pie,
SEQUENCER_PT_color_tag_picker,
SEQUENCER_PT_active_tool,
SEQUENCER_PT_strip,
+ SEQUENCER_PT_gizmo_display,
SEQUENCER_PT_overlay,
SEQUENCER_PT_preview_overlay,
SEQUENCER_PT_sequencer_overlay,
@@ -2418,6 +2665,7 @@ classes = (
SEQUENCER_PT_custom_props,
SEQUENCER_PT_view,
+ SEQUENCER_PT_view_cursor,
SEQUENCER_PT_frame_overlay,
SEQUENCER_PT_view_safe_areas,
SEQUENCER_PT_view_safe_areas_center_cut,
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_common.py b/release/scripts/startup/bl_ui/space_toolsystem_common.py
index 4a598d0aa63..c4dabb5b5bc 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_common.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_common.py
@@ -64,7 +64,7 @@ from collections import namedtuple
ToolDef = namedtuple(
"ToolDef",
(
- # Unique tool name (withing space & mode context).
+ # Unique tool name (within space & mode context).
"idname",
# The name to display in the interface.
"label",
@@ -106,7 +106,7 @@ ToolDef = namedtuple(
# Keep this functionality since it's likely useful for add-on key-maps.
#
# Warning: currently 'from_dict' this is a list of one item,
- # so internally we can swap the key-map function for the key-map it's self.
+ # so internally we can swap the key-map function for the key-map itself.
# This isn't very nice and may change, tool definitions shouldn't care about this.
"keymap",
# Optional data-block associated with this tool.
@@ -190,7 +190,7 @@ class ToolActivePanelHelper:
ToolSelectPanelHelper.draw_active_tool_header(
context,
layout.column(),
- show_tool_icon=True,
+ show_tool_icon_always=True,
tool_key=ToolSelectPanelHelper._tool_key_from_context(context, space_type=self.bl_space_type),
)
@@ -202,13 +202,41 @@ class ToolSelectPanelHelper:
- keymap_prefix:
The text prefix for each key-map for this spaces tools.
- tools_all():
- Returns (context_mode, tools) tuple pair for all tools defined.
+ Generator (context_mode, tools) tuple pairs for all tools defined.
- tools_from_context(context, mode=None):
- Returns tools available in this context.
+ A generator for all tools available in the current context.
- Each tool is a 'ToolDef' or None for a separator in the toolbar, use ``None``.
+ Tool Sequence Structure
+ =======================
+
+ Sequences of tools as returned by tools_all() and tools_from_context() are comprised of:
+
+ - A `ToolDef` instance (representing a tool that can be activated).
+ - None (a visual separator in the tool list).
+ - A tuple of `ToolDef` or None values
+ (representing a group of tools that can be selected between using a click-drag action).
+ Note that only a single level of nesting is supported (groups cannot contain sub-groups).
+ - A callable which takes a single context argument and returns a tuple of values described above.
+ When the context is None, all potential tools must be returned.
"""
+ @classmethod
+ def tools_all(cls):
+ """
+ Return all tools for this toolbar, this must include all available tools ignoring the current context.
+ The value is must be a sequence of (mode, tool_list) pairs, where mode may be object-mode edit-mode etc.
+ The mode may be None for tool-bars that don't make use of sub-modes.
+ """
+ raise Exception("Sub-class %r must implement this method!" % cls)
+
+ @classmethod
+ def tools_from_context(cls, context, mode=None):
+ """
+ Return all tools for the current context,
+ this result is used at run-time and may filter out tools to display.
+ """
+ raise Exception("Sub-class %r must implement this method!" % cls)
+
@staticmethod
def _tool_class_from_space_type(space_type):
return next(
@@ -766,7 +794,7 @@ class ToolSelectPanelHelper:
def draw_active_tool_header(
context, layout,
*,
- show_tool_icon=False,
+ show_tool_icon_always=False,
tool_key=None,
):
if tool_key is None:
@@ -783,11 +811,15 @@ class ToolSelectPanelHelper:
return None
# Note: we could show 'item.text' here but it makes the layout jitter when switching tools.
# Add some spacing since the icon is currently assuming regular small icon size.
- if show_tool_icon:
+ if show_tool_icon_always:
layout.label(text=" " + item.label, icon_value=icon_value)
layout.separator()
else:
- layout.label(text=item.label)
+ if context.space_data.show_region_toolbar:
+ layout.template_icon(icon_value=0, scale=0.5)
+ else:
+ layout.template_icon(icon_value=icon_value, scale=0.5)
+ layout.separator()
draw_settings = item.draw_settings
if draw_settings is not None:
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 5970d6fdf2b..889155f1858 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -185,23 +185,18 @@ class _defs_annotate:
tool_settings = context.tool_settings
if space_type == 'VIEW_3D':
- layout.separator()
-
row = layout.row(align=True)
row.prop(tool_settings, "annotation_stroke_placement_view3d", text="Placement")
if tool_settings.gpencil_stroke_placement_view3d == 'CURSOR':
row.prop(tool_settings.gpencil_sculpt, "lockaxis")
elif tool_settings.gpencil_stroke_placement_view3d in {'SURFACE', 'STROKE'}:
row.prop(tool_settings, "use_gpencil_stroke_endpoints")
- elif space_type in {'IMAGE_EDITOR', 'NODE_EDITOR', 'SEQUENCE_EDITOR', 'CLIP_EDITOR'}:
- layout.separator()
+ elif space_type in {'IMAGE_EDITOR', 'NODE_EDITOR', 'SEQUENCE_EDITOR', 'CLIP_EDITOR'}:
row = layout.row(align=True)
row.prop(tool_settings, "annotation_stroke_placement_view2d", text="Placement")
if tool.idname == "builtin.annotate_line":
- layout.separator()
-
props = tool.operator_properties("gpencil.annotate")
if region_type == 'TOOL_HEADER':
row = layout.row()
@@ -223,7 +218,6 @@ class _defs_annotate:
subrow.prop(props, "stabilizer_radius", text="Radius", slider=True)
subrow.prop(props, "stabilizer_factor", text="Factor", slider=True)
else:
- layout.separator()
layout.prop(props, "use_stabilizer", text="Stabilize Stroke")
col = layout.column(align=False)
col.active = props.use_stabilizer
@@ -2435,12 +2429,26 @@ class _defs_node_edit:
icon="ops.node.links_cut",
widget=None,
keymap="Node Tool: Links Cut",
+ options={'KEYMAP_FALLBACK'},
)
class _defs_sequencer_generic:
@ToolDef.from_fn
+ def cursor():
+ return dict(
+ idname="builtin.cursor",
+ label="Cursor",
+ description=(
+ "Set the cursor location, drag to transform"
+ ),
+ icon="ops.generic.cursor",
+ keymap="Sequencer Tool: Cursor",
+ options={'KEYMAP_FALLBACK'},
+ )
+
+ @ToolDef.from_fn
def blade():
def draw_settings(_context, layout, tool):
props = tool.operator_properties("sequencer.split")
@@ -2455,6 +2463,7 @@ class _defs_sequencer_generic:
widget=None,
keymap="Sequencer Tool: Blade",
draw_settings=draw_settings,
+ options={'KEYMAP_FALLBACK'},
)
@ToolDef.from_fn
@@ -2502,16 +2511,28 @@ class _defs_sequencer_generic:
keymap="Sequencer Tool: Scale",
)
+ @ToolDef.from_fn
+ def transform():
+ return dict(
+ idname="builtin.transform",
+ label="Transform",
+ description=(
+ "Supports any combination of grab, rotate, and scale at once"
+ ),
+ icon="ops.transform.transform",
+ widget="SEQUENCER_GGT_gizmo2d",
+ # No keymap default action, only for gizmo!
+ )
class _defs_sequencer_select:
@ToolDef.from_fn
def select():
return dict(
idname="builtin.select",
- label="Select",
+ label="Tweak",
icon="ops.generic.select",
widget=None,
- keymap="Sequencer Tool: Select",
+ keymap="Sequencer Tool: Tweak",
)
@ToolDef.from_fn
@@ -2562,7 +2583,8 @@ class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
def tools_all(cls):
yield from cls._tools.items()
- # for reuse
+ # Private tool lists for convenient reuse in `_tools`.
+
_tools_transform = (
_defs_image_uv_transform.translate,
_defs_image_uv_transform.rotate,
@@ -2588,6 +2610,9 @@ class IMAGE_PT_tools_active(ToolSelectPanelHelper, Panel):
),
)
+ # Private tools dictionary, store data to implement `tools_all` & `tools_from_context`.
+ # The keys match image spaces modes: 'context.space_data.mode'.
+ # The values represent the tools, see `ToolSelectPanelHelper` for details.
_tools = {
None: [
# for all modes
@@ -2653,6 +2678,8 @@ class NODE_PT_tools_active(ToolSelectPanelHelper, Panel):
def tools_all(cls):
yield from cls._tools.items()
+ # Private tool lists for convenient reuse in `_tools`.
+
_tools_select = (
(
_defs_node_select.select,
@@ -2671,6 +2698,9 @@ class NODE_PT_tools_active(ToolSelectPanelHelper, Panel):
),
)
+ # Private tools dictionary, store data to implement `tools_all` & `tools_from_context`.
+ # The keys is always `None` since nodes don't use use modes to access different tools.
+ # The values represent the tools, see `ToolSelectPanelHelper` for details.
_tools = {
None: [
*_tools_select,
@@ -2709,7 +2739,8 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
def tools_all(cls):
yield from cls._tools.items()
- # for reuse
+ # Private tool lists for convenient reuse in `_tools`.
+
_tools_transform = (
_defs_transform.translate,
_defs_transform.rotate,
@@ -2765,6 +2796,9 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_view3d_generic.ruler,
)
+ # Private tools dictionary, store data to implement `tools_all` & `tools_from_context`.
+ # The keys match object-modes from: 'context.mode'.
+ # The values represent the tools, see `ToolSelectPanelHelper` for details.
_tools = {
None: [
# Don't use this! because of paint modes.
@@ -2967,7 +3001,11 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
),
None,
lambda context: (
- (_defs_view3d_generic.cursor,)
+ (
+ _defs_view3d_generic.cursor,
+ None,
+ *VIEW3D_PT_tools_active._tools_transform,
+ )
if context is None or context.pose_object
else ()
),
@@ -3074,6 +3112,8 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
def tools_all(cls):
yield from cls._tools.items()
+ # Private tool lists for convenient reuse in `_tools`.
+
_tools_select = (
(
_defs_sequencer_select.select,
@@ -3089,14 +3129,21 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
),
)
+ # Private tools dictionary, store data to implement `tools_all` & `tools_from_context`.
+ # The keys match sequence editors view type: 'context.space_data.view_type'.
+ # The values represent the tools, see `ToolSelectPanelHelper` for details.
_tools = {
None: [
],
'PREVIEW': [
*_tools_select,
+ _defs_sequencer_generic.cursor,
+ None,
_defs_sequencer_generic.translate,
_defs_sequencer_generic.rotate,
_defs_sequencer_generic.scale,
+ _defs_sequencer_generic.transform,
+ None,
_defs_sequencer_generic.sample,
*_tools_annotate,
],
@@ -3106,12 +3153,10 @@ class SEQUENCER_PT_tools_active(ToolSelectPanelHelper, Panel):
],
'SEQUENCER_PREVIEW': [
*_tools_select,
- _defs_sequencer_generic.translate,
- _defs_sequencer_generic.rotate,
- _defs_sequencer_generic.scale,
- _defs_sequencer_generic.blade,
- _defs_sequencer_generic.sample,
+ None,
*_tools_annotate,
+ None,
+ _defs_sequencer_generic.blade,
],
}
diff --git a/release/scripts/startup/bl_ui/space_topbar.py b/release/scripts/startup/bl_ui/space_topbar.py
index 1d75ad8ff0a..99abc60db6f 100644
--- a/release/scripts/startup/bl_ui/space_topbar.py
+++ b/release/scripts/startup/bl_ui/space_topbar.py
@@ -481,6 +481,7 @@ class TOPBAR_MT_file_export(Menu):
bl_owner_use_filter = False
def draw(self, _context):
+ self.layout.operator("wm.obj_export", text="Wavefront OBJ (.obj) - New")
if bpy.app.build_options.collada:
self.layout.operator("wm.collada_export",
text="Collada (Default) (.dae)")
@@ -588,7 +589,7 @@ class TOPBAR_MT_edit(Menu):
layout.separator()
- layout.operator("ed.undo_history", text="Undo History...")
+ layout.menu("TOPBAR_MT_undo_history")
layout.separator()
@@ -634,6 +635,8 @@ class TOPBAR_MT_window(Menu):
layout = self.layout
+ operator_context_default = layout.operator_context
+
layout.operator("wm.window_new")
layout.operator("wm.window_new_main")
@@ -655,7 +658,14 @@ class TOPBAR_MT_window(Menu):
layout.separator()
layout.operator("screen.screenshot")
+
+ # Showing the status in the area doesn't work well in this case.
+ # - From the top-bar, the text replaces the file-menu (not so bad but strange).
+ # - From menu-search it replaces the area that the user may want to screen-shot.
+ # Setting the context to screen causes the status to show in the global status-bar.
+ layout.operator_context = 'INVOKE_SCREEN'
layout.operator("screen.screenshot_area")
+ layout.operator_context = operator_context_default
if sys.platform[:3] == "win":
layout.separator()
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 7a8b6d42cad..0548486c786 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -398,21 +398,26 @@ class USERPREF_PT_edit_objects_duplicate_data(EditingPanel, CenterAlignMixIn, Pa
col = flow.column()
col.prop(edit, "use_duplicate_action", text="Action")
col.prop(edit, "use_duplicate_armature", text="Armature")
+ col.prop(edit, "use_duplicate_camera", text="Camera")
col.prop(edit, "use_duplicate_curve", text="Curve")
# col.prop(edit, "use_duplicate_fcurve", text="F-Curve") # Not implemented.
col.prop(edit, "use_duplicate_grease_pencil", text="Grease Pencil")
if hasattr(edit, "use_duplicate_hair"):
col.prop(edit, "use_duplicate_hair", text="Hair")
- col.prop(edit, "use_duplicate_light", text="Light")
+
col = flow.column()
+ col.prop(edit, "use_duplicate_lattice", text="Lattice")
+ col.prop(edit, "use_duplicate_light", text="Light")
col.prop(edit, "use_duplicate_lightprobe", text="Light Probe")
col.prop(edit, "use_duplicate_material", text="Material")
col.prop(edit, "use_duplicate_mesh", text="Mesh")
col.prop(edit, "use_duplicate_metaball", text="Metaball")
- col.prop(edit, "use_duplicate_particle", text="Particle")
+
col = flow.column()
+ col.prop(edit, "use_duplicate_particle", text="Particle")
if hasattr(edit, "use_duplicate_pointcloud"):
col.prop(edit, "use_duplicate_pointcloud", text="Point Cloud")
+ col.prop(edit, "use_duplicate_speaker", text="Speaker")
col.prop(edit, "use_duplicate_surface", text="Surface")
col.prop(edit, "use_duplicate_text", text="Text")
# col.prop(edit, "use_duplicate_texture", text="Texture") # Not implemented.
@@ -472,6 +477,16 @@ class USERPREF_PT_edit_weight_paint(EditingPanel, CenterAlignMixIn, Panel):
col.active = view.use_weight_color_range
col.template_color_ramp(view, "weight_color_range", expand=True)
+class USERPREF_PT_edit_text_editor(EditingPanel, CenterAlignMixIn, Panel):
+ bl_label = "Text Editor"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_centered(self, context, layout):
+ prefs = context.preferences
+ edit = prefs.edit
+
+ layout.prop(edit, "use_text_edit_auto_close")
+
class USERPREF_PT_edit_misc(EditingPanel, CenterAlignMixIn, Panel):
bl_label = "Miscellaneous"
@@ -581,9 +596,11 @@ class USERPREF_PT_system_cycles_devices(SystemPanel, CenterAlignMixIn, Panel):
@classmethod
def poll(cls, _context):
- # No GPU rendering on macOS currently.
+ # No GPU rendering on macOS x86_64 currently.
+ import platform
import sys
- return bpy.app.build_options.cycles and sys.platform != "darwin"
+ return bpy.app.build_options.cycles and \
+ (sys.platform != "darwin" or platform.machine() == "arm64")
def draw_centered(self, context, layout):
prefs = context.preferences
@@ -755,6 +772,17 @@ class USERPREF_PT_viewport_selection(ViewportPanel, CenterAlignMixIn, Panel):
layout.prop(system, "use_select_pick_depth")
+class USERPREF_PT_viewport_subdivision(ViewportPanel, CenterAlignMixIn, Panel):
+ bl_label = "Subdivision"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ def draw_centered(self, context, layout):
+ prefs = context.preferences
+ system = prefs.system
+
+ layout.prop(system, "use_gpu_subdivision")
+
+
# -----------------------------------------------------------------------------
# Theme Panels
@@ -920,6 +948,7 @@ class USERPREF_PT_theme_interface_styles(ThemePanel, CenterAlignMixIn, Panel):
flow.prop(ui, "editor_outline")
flow.prop(ui, "widget_text_cursor")
flow.prop(ui, "widget_emboss")
+ flow.prop(ui, "panel_roundness")
class USERPREF_PT_theme_interface_transparent_checker(ThemePanel, CenterAlignMixIn, Panel):
@@ -1404,12 +1433,18 @@ class USERPREF_PT_file_paths_asset_libraries(FilePathsPanel, Panel):
row.label(text="Path")
for i, library in enumerate(paths.asset_libraries):
- name_col.prop(library, "name", text="")
+ row = name_col.row()
+ row.alert = not library.name
+ row.prop(library, "name", text="")
+
row = path_col.row()
- row.prop(library, "path", text="")
+ subrow = row.row()
+ subrow.alert = not library.path
+ subrow.prop(library, "path", text="")
row.operator("preferences.asset_library_remove", text="", icon='X', emboss=False).index = i
+
row = box.row()
- row.alignment = 'LEFT'
+ row.alignment = 'RIGHT'
row.operator("preferences.asset_library_add", text="", icon='ADD', emboss=False)
@@ -1796,7 +1831,7 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
bl_options = {'HIDE_HEADER'}
_support_icon_mapping = {
- 'OFFICIAL': 'FILE_BLEND',
+ 'OFFICIAL': 'BLENDER',
'COMMUNITY': 'COMMUNITY',
'TESTING': 'EXPERIMENTAL',
}
@@ -1846,11 +1881,6 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
if p
)
- # Development option for 2.8x, don't show users bundled addons
- # unless they have been updated for 2.8x.
- # Developers can turn them on with '--debug'
- show_official_27x_addons = bpy.app.debug
-
# collect the categories that can be filtered on
addons = [
(mod, addon_utils.module_bl_info(mod))
@@ -1927,15 +1957,6 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
):
continue
- # Skip 2.7x add-ons included with Blender, unless in debug mode.
- is_addon_27x = info.get("blender", (0,)) < (2, 80)
- if (
- is_addon_27x and
- (not show_official_27x_addons) and
- (not mod.__file__.startswith(addon_user_dirs))
- ):
- continue
-
# Addon UI Code
col_box = col.column()
box = col_box.box()
@@ -1958,13 +1979,7 @@ class USERPREF_PT_addons(AddOnPanel, Panel):
sub.active = is_enabled
sub.label(text="%s: %s" % (info["category"], info["name"]))
- # WARNING: 2.8x exception, may be removed
- # use disabled state for old add-ons, chances are they are broken.
- if is_addon_27x:
- sub.label(text="Upgrade to 2.8x required")
- sub.label(icon='ERROR')
- # Remove code above after 2.8x migration is complete.
- elif info["warning"]:
+ if info["warning"]:
sub.label(icon='ERROR')
# icon showing support level.
@@ -2304,6 +2319,8 @@ class USERPREF_PT_experimental_debugging(ExperimentalPanel, Panel):
({"property": "proxy_to_override_auto_conversion"}, "T91671"),
({"property": "use_cycles_debug"}, None),
({"property": "use_geometry_nodes_legacy"}, "T91274"),
+ ({"property": "show_asset_debug_info"}, None),
+ ({"property": "use_asset_indexing"}, None),
),
)
@@ -2337,6 +2354,7 @@ classes = (
USERPREF_PT_viewport_quality,
USERPREF_PT_viewport_textures,
USERPREF_PT_viewport_selection,
+ USERPREF_PT_viewport_subdivision,
USERPREF_PT_edit_objects,
USERPREF_PT_edit_objects_new,
@@ -2345,6 +2363,7 @@ classes = (
USERPREF_PT_edit_annotations,
USERPREF_PT_edit_weight_paint,
USERPREF_PT_edit_gpencil,
+ USERPREF_PT_edit_text_editor,
USERPREF_PT_edit_misc,
USERPREF_PT_animation_timeline,
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 281c57b282f..5eca606216e 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -2265,6 +2265,7 @@ class VIEW3D_MT_object(Menu):
layout.separator()
+ layout.menu("VIEW3D_MT_object_asset")
layout.menu("VIEW3D_MT_object_parent")
layout.menu("VIEW3D_MT_object_collection")
layout.menu("VIEW3D_MT_object_relations")
@@ -2758,6 +2759,16 @@ class VIEW3D_MT_object_cleanup(Menu):
layout.operator("object.material_slot_remove_unused", text="Remove Unused Material Slots")
+class VIEW3D_MT_object_asset(Menu):
+ bl_label = "Asset"
+
+ def draw(self, _context):
+ layout = self.layout
+
+ layout.operator("asset.mark")
+ layout.operator("asset.clear", text="Clear Asset").set_fake_user = False
+ layout.operator("asset.clear", text="Clear Asset (Set Fake User)").set_fake_user = True
+
class VIEW3D_MT_make_single_user(Menu):
bl_label = "Make Single User"
@@ -3049,8 +3060,7 @@ class VIEW3D_MT_sculpt(Menu):
layout.separator()
- props = layout.operator("object.transfer_mode", text="Transfer Sculpt Mode")
- props.use_eyedropper = True
+ layout.operator("object.transfer_mode", text="Transfer Sculpt Mode")
class VIEW3D_MT_mask(Menu):
@@ -3443,7 +3453,7 @@ class VIEW3D_MT_pose_slide(Menu):
layout.operator("pose.push")
layout.operator("pose.relax")
layout.operator("pose.breakdown")
- layout.operator("pose.blend_to_neighbour")
+ layout.operator("pose.blend_to_neighbor")
class VIEW3D_MT_pose_propagate(Menu):
@@ -3596,12 +3606,14 @@ class VIEW3D_MT_pose_context_menu(Menu):
layout.operator("pose.push")
layout.operator("pose.relax")
layout.operator("pose.breakdown")
- layout.operator("pose.blend_to_neighbour")
+ layout.operator("pose.blend_to_neighbor")
layout.separator()
layout.operator("pose.paths_calculate", text="Calculate Motion Paths")
layout.operator("pose.paths_clear", text="Clear Motion Paths")
+ layout.operator("pose.paths_update", text="Update Armature Motion Paths")
+ layout.operator("object.paths_update_visible", text="Update All Motion Paths")
layout.separator()
@@ -4014,6 +4026,10 @@ class VIEW3D_MT_edit_mesh_vertices(Menu):
layout.separator()
+ layout.operator("transform.vert_crease")
+
+ layout.separator()
+
layout.operator("mesh.blend_from_shape")
layout.operator("mesh.shape_propagate_to_all", text="Propagate to Shapes")
@@ -5978,7 +5994,7 @@ class VIEW3D_PT_shading_render_pass(Panel):
class VIEW3D_PT_gizmo_display(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
- bl_label = "Gizmo"
+ bl_label = "Gizmos"
bl_ui_units_x = 8
def draw(self, context):
@@ -6492,18 +6508,38 @@ class VIEW3D_PT_overlay_sculpt(Panel):
row.prop(overlay, "sculpt_mode_face_sets_opacity", text="Face Sets")
-class VIEW3D_PT_overlay_pose(Panel):
+class VIEW3D_PT_overlay_bones(Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'HEADER'
bl_parent_id = 'VIEW3D_PT_overlay'
- bl_label = "Pose Mode"
+ bl_label = "Bones"
+
+ @staticmethod
+ def is_using_wireframe(context):
+ shading = VIEW3D_PT_shading.get_shading(context)
+
+ if shading.type == 'WIREFRAME' or shading.show_xray:
+ return True
+
+ mode = context.mode
+
+ if mode in {'POSE', 'PAINT_WEIGHT'}:
+ armature = context.pose_object
+ elif mode == 'EDIT_ARMATURE':
+ armature = context.edit_object
+ else:
+ return False
+
+ return armature and armature.display_type == 'WIRE'
@classmethod
def poll(cls, context):
mode = context.mode
return (
(mode == 'POSE') or
- (mode == 'PAINT_WEIGHT' and context.pose_object)
+ (mode == 'PAINT_WEIGHT' and context.pose_object) or
+ (mode in {'EDIT_ARMATURE', 'OBJECT'} and
+ VIEW3D_PT_overlay_bones.is_using_wireframe(context))
)
def draw(self, context):
@@ -6522,10 +6558,13 @@ class VIEW3D_PT_overlay_pose(Panel):
sub = row.row()
sub.active = display_all and overlay.show_xray_bone
sub.prop(overlay, "xray_alpha_bone", text="Fade Geometry")
- else:
+ elif mode == 'PAINT_WEIGHT':
row = col.row()
row.prop(overlay, "show_xray_bone")
+ if VIEW3D_PT_overlay_bones.is_using_wireframe(context):
+ col.prop(overlay, "bone_wire_alpha")
+
class VIEW3D_PT_overlay_texture_paint(Panel):
bl_space_type = 'VIEW_3D'
@@ -7540,6 +7579,7 @@ classes = (
VIEW3D_MT_image_add,
VIEW3D_MT_object,
VIEW3D_MT_object_animation,
+ VIEW3D_MT_object_asset,
VIEW3D_MT_object_rigid_body,
VIEW3D_MT_object_clear,
VIEW3D_MT_object_context_menu,
@@ -7692,7 +7732,7 @@ classes = (
VIEW3D_PT_overlay_texture_paint,
VIEW3D_PT_overlay_vertex_paint,
VIEW3D_PT_overlay_weight_paint,
- VIEW3D_PT_overlay_pose,
+ VIEW3D_PT_overlay_bones,
VIEW3D_PT_overlay_sculpt,
VIEW3D_PT_snapping,
VIEW3D_PT_proportional_edit,
diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
index acc3d933b85..4bd3d5cc3f2 100644
--- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py
@@ -689,13 +689,23 @@ class VIEW3D_PT_tools_brush_stroke_smooth_stroke(Panel, View3DPaintPanel, Smooth
class VIEW3D_PT_tools_weight_gradient(Panel, View3DPaintPanel):
- bl_context = ".weightpaint" # dot on purpose (access from topbar)
+ # dont give context on purpose to not show this in the generic header toolsettings
+ # this is added only in the gradient tool's ToolDef
+ #bl_context = ".weightpaint" # dot on purpose (access from topbar)
bl_label = "Falloff"
bl_options = {'DEFAULT_CLOSED'}
+ # also dont draw as an extra panel in the sidebar (already included in the Brush settings)
+ bl_space_type = 'TOPBAR'
+ bl_region_type = 'HEADER'
@classmethod
def poll(cls, context):
+ # since we dont give context above, check mode here (to not show in other modes like sculpt)
+ if context.mode != 'PAINT_WEIGHT':
+ return False
settings = context.tool_settings.weight_paint
+ if settings is None:
+ return False
brush = settings.brush
return brush is not None